• 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_surface_allocator.h"
17 #include <sync_fence.h>
18 #include "media_log.h"
19 #include "media_dfx.h"
20 
21 GST_DEBUG_CATEGORY_STATIC(gst_surface_allocator_debug_category);
22 #define GST_CAT_DEFAULT gst_surface_allocator_debug_category
23 
24 #define gst_surface_allocator_parent_class parent_class
25 G_DEFINE_TYPE(GstSurfaceAllocator, gst_surface_allocator, GST_TYPE_ALLOCATOR);
26 
27 using namespace OHOS;
28 using namespace OHOS::Media;
29 
30 enum class VideoScaleType {
31     VIDEO_SCALE_TYPE_FIT,
32     VIDEO_SCALE_TYPE_FIT_CROP,
33 };
34 
35 namespace {
36     const std::unordered_map<VideoScaleType, OHOS::ScalingMode> SCALEMODE_MAP = {
37         { VideoScaleType::VIDEO_SCALE_TYPE_FIT, OHOS::SCALING_MODE_SCALE_TO_WINDOW },
38         { VideoScaleType::VIDEO_SCALE_TYPE_FIT_CROP, OHOS::SCALING_MODE_SCALE_CROP},
39     };
40 }
41 
gst_surface_allocator_set_surface(GstSurfaceAllocator * allocator,OHOS::sptr<OHOS::Surface> surface)42 gboolean gst_surface_allocator_set_surface(GstSurfaceAllocator *allocator, OHOS::sptr<OHOS::Surface> surface)
43 {
44     if (allocator == nullptr) {
45         GST_ERROR("allocator is nullptr");
46         return FALSE;
47     }
48     if (surface == nullptr) {
49         GST_ERROR("surface is nullptr");
50         return FALSE;
51     }
52     allocator->surface = surface;
53     return TRUE;
54 }
55 
gst_surface_allocator_get_scale_type(GstSurfaceAllocParam param)56 static OHOS::ScalingMode gst_surface_allocator_get_scale_type(GstSurfaceAllocParam param)
57 {
58     if (SCALEMODE_MAP.find(static_cast<VideoScaleType>(param.scale_type)) == SCALEMODE_MAP.end()) {
59         return OHOS::SCALING_MODE_SCALE_TO_WINDOW;
60     }
61     return SCALEMODE_MAP.at(static_cast<VideoScaleType>(param.scale_type));
62 }
63 
gst_surface_request_buffer(const GstSurfaceAllocator * allocator,GstSurfaceAllocParam param,OHOS::sptr<OHOS::SurfaceBuffer> & buffer)64 static bool gst_surface_request_buffer(const GstSurfaceAllocator *allocator, GstSurfaceAllocParam param,
65     OHOS::sptr<OHOS::SurfaceBuffer> &buffer)
66 {
67     MediaTrace trace("Surface::RequestBuffer");
68     static constexpr int32_t stride_alignment = 8;
69     int32_t wait_time = param.dont_wait ? 0 : INT_MAX; // wait forever or no wait.
70     OHOS::BufferRequestConfig request_config = {
71         param.width, param.height, stride_alignment, param.format,
72         param.usage | BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
73         wait_time
74     };
75     int32_t release_fence = -1;
76     OHOS::SurfaceError ret = allocator->surface->RequestBuffer(buffer, release_fence, request_config);
77     if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK || buffer == nullptr) {
78         GST_ERROR("there is no more surface buffer");
79         return false;
80     }
81     {
82         MediaTrace mapTrace("Surface::Map");
83         if (buffer->Map() != OHOS::SurfaceError::SURFACE_ERROR_OK) {
84             GST_ERROR("surface buffer Map failed");
85             allocator->surface->CancelBuffer(buffer);
86             return false;
87         }
88     }
89 
90     {
91         MediaTrace FenceTrace("Surface::WaitFence");
92         OHOS::sptr<OHOS::SyncFence> autoFence = new(std::nothrow) OHOS::SyncFence(release_fence);
93         if (autoFence != nullptr) {
94             autoFence->Wait(100); // 100ms
95         }
96     }
97 
98     {
99         MediaTrace scaleTrace("Surface::SetScalingMode");
100         auto scaleType = gst_surface_allocator_get_scale_type(param);
101         ret = allocator->surface->SetScalingMode(buffer->GetSeqNum(), scaleType);
102         if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
103             GST_ERROR("surface buffer set scaling mode failed");
104             allocator->surface->CancelBuffer(buffer);
105             return false;
106         }
107     }
108     return true;
109 }
110 
gst_surface_allocator_alloc(GstSurfaceAllocator * allocator,GstSurfaceAllocParam param)111 GstSurfaceMemory *gst_surface_allocator_alloc(GstSurfaceAllocator *allocator, GstSurfaceAllocParam param)
112 {
113     g_return_val_if_fail(allocator != nullptr && allocator->surface != nullptr, nullptr);
114 
115     OHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr;
116     if (!gst_surface_request_buffer(allocator, param, buffer) || buffer == nullptr) {
117         GST_ERROR("failed to request surface buffer");
118         return nullptr;
119     }
120 
121     GstSurfaceMemory *memory = reinterpret_cast<GstSurfaceMemory *>(g_slice_alloc0(sizeof(GstSurfaceMemory)));
122     if (memory == nullptr) {
123         GST_ERROR("alloc GstSurfaceMemory slice failed");
124         allocator->surface->CancelBuffer(buffer);
125         return nullptr;
126     }
127 
128     gst_memory_init(GST_MEMORY_CAST(memory), (GstMemoryFlags)0, GST_ALLOCATOR_CAST(allocator), nullptr,
129         buffer->GetSize(), 0, 0, buffer->GetSize());
130 
131     memory->buf = buffer;
132     memory->fence = -1;
133     memory->need_render = FALSE;
134     GST_DEBUG("alloc surface buffer for width: %d, height: %d, format: %d, size: %u",
135         param.width, param.height, param.format, buffer->GetSize());
136 
137     return memory;
138 }
139 
gst_surface_allocator_free(GstAllocator * baseAllocator,GstMemory * baseMemory)140 static void gst_surface_allocator_free(GstAllocator *baseAllocator, GstMemory *baseMemory)
141 {
142     GstSurfaceAllocator *allocator = reinterpret_cast<GstSurfaceAllocator*>(baseAllocator);
143     GstSurfaceMemory *memory = reinterpret_cast<GstSurfaceMemory*>(baseMemory);
144     g_return_if_fail(memory != nullptr && allocator != nullptr && allocator->surface != nullptr);
145 
146     GST_DEBUG("free surface buffer for width: %d, height: %d, format: %d, size: %u, need_render: %d, fence: %d",
147         memory->buf->GetWidth(), memory->buf->GetHeight(), memory->buf->GetFormat(), memory->buf->GetSize(),
148         memory->need_render, memory->fence);
149 
150     if (!memory->need_render) {
151         OHOS::SurfaceError ret = allocator->surface->CancelBuffer(memory->buf);
152         if (ret != OHOS::SurfaceError::SURFACE_ERROR_OK) {
153             GST_INFO("cancel buffer to surface failed, %d", ret);
154         }
155     }
156 
157     memory->buf = nullptr;
158     g_slice_free(GstSurfaceMemory, memory);
159 }
160 
gst_surface_allocator_alloc_dummy(GstAllocator * allocator,gsize size,GstAllocationParams * params)161 static GstMemory *gst_surface_allocator_alloc_dummy(GstAllocator *allocator, gsize size, GstAllocationParams *params)
162 {
163     (void)allocator;
164     (void)size;
165     (void)params;
166     return nullptr;
167 }
168 
gst_surface_allocator_mem_map(GstMemory * mem,gsize maxsize,GstMapFlags flags)169 static gpointer gst_surface_allocator_mem_map(GstMemory *mem, gsize maxsize, GstMapFlags flags)
170 {
171     (void)maxsize;
172     (void)flags;
173     g_return_val_if_fail(mem != nullptr, nullptr);
174     g_return_val_if_fail(gst_is_surface_memory(mem), nullptr);
175 
176     GstSurfaceMemory *sf_mem = reinterpret_cast<GstSurfaceMemory *>(mem);
177     g_return_val_if_fail(sf_mem->buf != nullptr, nullptr);
178 
179     return sf_mem->buf->GetVirAddr();
180 }
181 
gst_surface_allocator_mem_unmap(GstMemory * mem)182 static void gst_surface_allocator_mem_unmap(GstMemory *mem)
183 {
184     (void)mem;
185 }
186 
gst_surface_allocator_init(GstSurfaceAllocator * allocator)187 static void gst_surface_allocator_init(GstSurfaceAllocator *allocator)
188 {
189     GstAllocator *base_allocator = GST_ALLOCATOR_CAST(allocator);
190     g_return_if_fail(base_allocator != nullptr);
191 
192     GST_DEBUG_OBJECT(allocator, "init allocator 0x%06" PRIXPTR "", FAKE_POINTER(allocator));
193 
194     base_allocator->mem_type = GST_SURFACE_MEMORY_TYPE;
195     base_allocator->mem_map = (GstMemoryMapFunction)gst_surface_allocator_mem_map;
196     base_allocator->mem_unmap = (GstMemoryUnmapFunction)gst_surface_allocator_mem_unmap;
197 }
198 
gst_surface_allocator_finalize(GObject * obj)199 static void gst_surface_allocator_finalize(GObject *obj)
200 {
201     GstSurfaceAllocator *allocator = GST_SURFACE_ALLOCATOR_CAST(obj);
202     g_return_if_fail(allocator != nullptr);
203 
204     allocator->surface = nullptr;
205     GST_DEBUG_OBJECT(allocator, "finalize allocator 0x%06" PRIXPTR "", FAKE_POINTER(allocator));
206     G_OBJECT_CLASS(parent_class)->finalize(obj);
207 }
208 
gst_surface_allocator_class_init(GstSurfaceAllocatorClass * klass)209 static void gst_surface_allocator_class_init(GstSurfaceAllocatorClass *klass)
210 {
211     GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
212     g_return_if_fail(gobject_class != nullptr);
213 
214     gobject_class->finalize = gst_surface_allocator_finalize;
215 
216     GstAllocatorClass *allocatorClass = GST_ALLOCATOR_CLASS(klass);
217     g_return_if_fail(allocatorClass != nullptr);
218 
219     allocatorClass->alloc = gst_surface_allocator_alloc_dummy;
220     allocatorClass->free = gst_surface_allocator_free;
221     GST_DEBUG_CATEGORY_INIT(gst_surface_allocator_debug_category, "prosurallocator", 0, "surface allocator");
222 }
223 
gst_surface_allocator_new()224 GstSurfaceAllocator *gst_surface_allocator_new()
225 {
226     GstSurfaceAllocator *alloc = GST_SURFACE_ALLOCATOR_CAST(g_object_new(
227         GST_TYPE_SURFACE_ALLOCATOR, "name", "SurfaceAllocator", nullptr));
228     (void)gst_object_ref_sink(alloc);
229 
230     return alloc;
231 }
232