• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gst_consumer_surface_allocator.h"
17 #include "gst_consumer_surface_memory.h"
18 #include "media_log.h"
19 #include "scope_guard.h"
20 
21 using namespace OHOS;
22 
23 #define GST_CONSUMER_SURFACE_MEMORY_TYPE "ConsumerSurfaceMemory"
24 
25 #define gst_consumer_surface_allocator_parent_class parent_class
26 
27 GST_DEBUG_CATEGORY_STATIC(gst_consumer_surface_allocator_debug_category);
28 #define GST_CAT_DEFAULT gst_consumer_surface_allocator_debug_category
29 
30 struct _GstConsumerSurfaceAllocatorPrivate {
31     sptr<Surface> csurface;
32 };
33 
34 G_DEFINE_TYPE_WITH_PRIVATE(GstConsumerSurfaceAllocator, gst_consumer_surface_allocator, GST_TYPE_ALLOCATOR);
35 
36 static void gst_consumer_surface_allocator_class_init(GstConsumerSurfaceAllocatorClass *klass);
37 static void gst_consumer_surface_allocator_free(GstAllocator *allocator, GstMemory *mem);
38 static gpointer gst_consumer_surface_allocator_mem_map(GstMemory *mem, gsize maxsize, GstMapFlags flags);
39 static void gst_consumer_surface_allocator_init(GstConsumerSurfaceAllocator *sallocator);
40 static void gst_consumer_surface_allocator_finalize(GObject *obj);
41 
gst_is_consumer_surface_memory(GstMemory * mem)42 gboolean gst_is_consumer_surface_memory(GstMemory *mem)
43 {
44     return gst_memory_is_type(mem, GST_CONSUMER_SURFACE_MEMORY_TYPE);
45 }
46 
gst_consumer_surface_allocator_alloc(GstAllocator * allocator,gsize size,GstAllocationParams * params)47 static GstMemory *gst_consumer_surface_allocator_alloc(GstAllocator *allocator, gsize size, GstAllocationParams *params)
48 {
49     g_return_val_if_fail(params != nullptr, nullptr);
50     g_return_val_if_fail(allocator != nullptr, nullptr);
51     GstConsumerSurfaceAllocator *sallocator = GST_CONSUMER_SURFACE_ALLOCATOR(allocator);
52     g_return_val_if_fail(sallocator != nullptr && sallocator->priv != nullptr, nullptr);
53     g_return_val_if_fail(sallocator->priv->csurface != nullptr, nullptr);
54     GstConsumerSurfaceMemory *mem =
55         reinterpret_cast<GstConsumerSurfaceMemory *>(g_slice_alloc0(sizeof(GstConsumerSurfaceMemory)));
56     g_return_val_if_fail(mem != nullptr, nullptr);
57 
58     ON_SCOPE_EXIT(0) { g_slice_free(GstConsumerSurfaceMemory, mem); };
59     // shorten code
60     sptr<Surface> surface = sallocator->priv->csurface;
61     sptr<SurfaceBuffer> surface_buffer = nullptr;
62     gint32 fencefd = -1;
63     gint64 timestamp = 0;
64     gboolean endOfStream = false;
65     gboolean is_key_frame = FALSE;
66     Rect damage = {0, 0, 0, 0};
67     if (surface->AcquireBuffer(surface_buffer, fencefd, timestamp, damage) != SURFACE_ERROR_OK) {
68         GST_WARNING_OBJECT(allocator, "Acquire surface buffer failed");
69         return nullptr;
70     }
71     g_return_val_if_fail(surface_buffer != nullptr, nullptr);
72     ON_SCOPE_EXIT(1) { surface->ReleaseBuffer(surface_buffer, -1); };
73     (void)surface_buffer->ExtraGet("timeStamp", timestamp);
74     (void)surface_buffer->ExtraGet("endOfStream", endOfStream);
75 
76     gst_memory_init(GST_MEMORY_CAST(mem), GST_MEMORY_FLAG_NO_SHARE,
77         allocator, nullptr, surface_buffer->GetSize(), 0, 0, size);
78     mem->surface_buffer = surface_buffer;
79     mem->fencefd = fencefd;
80     mem->timestamp = timestamp;
81     mem->is_key_frame = is_key_frame;
82     mem->damage = damage;
83     mem->is_eos_frame = endOfStream;
84     mem->buffer_handle = reinterpret_cast<intptr_t>(surface_buffer->GetBufferHandle());
85     GST_INFO_OBJECT(allocator, "acquire surface buffer");
86 
87     CANCEL_SCOPE_EXIT_GUARD(0);
88     CANCEL_SCOPE_EXIT_GUARD(1);
89     return GST_MEMORY_CAST(mem);
90 }
91 
gst_consumer_surface_allocator_free(GstAllocator * allocator,GstMemory * mem)92 static void gst_consumer_surface_allocator_free(GstAllocator *allocator, GstMemory *mem)
93 {
94     g_return_if_fail(mem != nullptr && allocator != nullptr);
95     g_return_if_fail(gst_is_consumer_surface_memory(mem));
96     GstConsumerSurfaceAllocator *sallocator = GST_CONSUMER_SURFACE_ALLOCATOR(allocator);
97     g_return_if_fail(sallocator->priv != nullptr && sallocator->priv->csurface != nullptr);
98 
99     GstConsumerSurfaceMemory *surfacemem = reinterpret_cast<GstConsumerSurfaceMemory*>(mem);
100     (void)sallocator->priv->csurface->ReleaseBuffer(surfacemem->surface_buffer, surfacemem->fencefd);
101     GST_INFO_OBJECT(allocator, "release surface buffer");
102     surfacemem->surface_buffer = nullptr;
103     g_slice_free(GstConsumerSurfaceMemory, surfacemem);
104 }
105 
gst_consumer_surface_allocator_mem_map(GstMemory * mem,gsize maxsize,GstMapFlags flags)106 static gpointer gst_consumer_surface_allocator_mem_map(GstMemory *mem, gsize maxsize, GstMapFlags flags)
107 {
108     (void)flags;
109     g_return_val_if_fail(mem != nullptr, nullptr);
110     g_return_val_if_fail(gst_is_consumer_surface_memory(mem), nullptr);
111 
112     GstConsumerSurfaceMemory *surfacemem = reinterpret_cast<GstConsumerSurfaceMemory*>(mem);
113     g_return_val_if_fail(surfacemem->surface_buffer != nullptr, nullptr);
114 
115     return surfacemem->surface_buffer->GetVirAddr();
116 }
117 
gst_consumer_surface_allocator_mem_unmap(GstMemory * mem)118 static void gst_consumer_surface_allocator_mem_unmap(GstMemory *mem)
119 {
120     (void)mem;
121 }
122 
gst_consumer_surface_allocator_init(GstConsumerSurfaceAllocator * sallocator)123 static void gst_consumer_surface_allocator_init(GstConsumerSurfaceAllocator *sallocator)
124 {
125     GstAllocator *allocator = GST_ALLOCATOR_CAST(sallocator);
126     g_return_if_fail(allocator != nullptr);
127     auto priv = reinterpret_cast<GstConsumerSurfaceAllocatorPrivate *>(
128                 gst_consumer_surface_allocator_get_instance_private(sallocator));
129     g_return_if_fail(priv != nullptr);
130     sallocator->priv = priv;
131 
132     GST_DEBUG_OBJECT(allocator, "init allocator 0x%06" PRIXPTR "", FAKE_POINTER(allocator));
133 
134     allocator->mem_type = GST_CONSUMER_SURFACE_MEMORY_TYPE;
135     allocator->mem_map = (GstMemoryMapFunction)gst_consumer_surface_allocator_mem_map;
136     allocator->mem_unmap = (GstMemoryUnmapFunction)gst_consumer_surface_allocator_mem_unmap;
137 }
138 
gst_consumer_surface_allocator_finalize(GObject * obj)139 static void gst_consumer_surface_allocator_finalize(GObject *obj)
140 {
141     GstConsumerSurfaceAllocator *allocator = GST_CONSUMER_SURFACE_ALLOCATOR(obj);
142     g_return_if_fail(allocator != nullptr && allocator->priv != nullptr);
143     allocator->priv->csurface = nullptr;
144 
145     GST_DEBUG_OBJECT(allocator, "finalize allocator 0x%06" PRIXPTR "", FAKE_POINTER(allocator));
146     G_OBJECT_CLASS(parent_class)->finalize(obj);
147 }
148 
gst_consumer_surface_allocator_class_init(GstConsumerSurfaceAllocatorClass * klass)149 static void gst_consumer_surface_allocator_class_init(GstConsumerSurfaceAllocatorClass *klass)
150 {
151     GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
152     g_return_if_fail(gobjectClass != nullptr);
153     GST_DEBUG_CATEGORY_INIT(gst_consumer_surface_allocator_debug_category, "surfaceallocator", 0, "surface allocator");
154     gobjectClass->finalize = gst_consumer_surface_allocator_finalize;
155 
156     GstAllocatorClass *allocatorClass = GST_ALLOCATOR_CLASS(klass);
157     g_return_if_fail(allocatorClass != nullptr);
158 
159     allocatorClass->alloc = gst_consumer_surface_allocator_alloc;
160     allocatorClass->free = gst_consumer_surface_allocator_free;
161 }
162 
gst_consumer_surface_allocator_set_surface(GstAllocator * allocator,sptr<Surface> & consumerSurface)163 void gst_consumer_surface_allocator_set_surface(GstAllocator *allocator, sptr<Surface> &consumerSurface)
164 {
165     GstConsumerSurfaceAllocator *sallocator = GST_CONSUMER_SURFACE_ALLOCATOR(allocator);
166     g_return_if_fail(sallocator != nullptr && sallocator->priv != nullptr);
167     sallocator->priv->csurface = consumerSurface;
168 }
169 
gst_consumer_surface_allocator_new()170 GstAllocator *gst_consumer_surface_allocator_new()
171 {
172     GstAllocator *alloc = GST_ALLOCATOR_CAST(g_object_new(
173         GST_TYPE_CONSUMER_SURFACE_ALLOCATOR, "name", "ConsumerSurface::Allocator", nullptr));
174     (void)gst_object_ref_sink(alloc);
175 
176     return alloc;
177 }
178