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