• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 #include <arpa/inet.h>
16 #include <sys/time.h>
17 #include <utility>
18 #include "iconsumer_surface.h"
19 #include "native_buffer_inner.h"
20 #include "syncvideoenc_sample.h"
21 #include "native_avcapability.h"
22 #include <random>
23 using namespace OHOS;
24 using namespace OHOS::Media;
25 using namespace std;
26 
27 namespace {
28 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
29 constexpr int64_t NANOS_IN_MICRO = 1000L;
30 constexpr uint32_t FRAME_INTERVAL = 16666;
31 constexpr uint32_t MAX_PIXEL_FMT = 5;
32 constexpr uint32_t DOUBLE = 2;
33 constexpr uint32_t THREE = 3;
34 OH_AVCapability *cap = nullptr;
35 VEncSyncSample *g_encSample = nullptr;
36 constexpr int32_t TIMESTAMP_BASE = 1000000;
37 constexpr int32_t DURATION_BASE = 46000;
38 } // namespace
39 
~VEncSyncSample()40 VEncSyncSample::~VEncSyncSample()
41 {
42     if (surfInput && nativeWindow) {
43         OH_NativeWindow_DestroyNativeWindow(nativeWindow);
44         nativeWindow = nullptr;
45     }
46     Stop();
47     Release();
48 }
49 
GetSystemTimeUs()50 int64_t VEncSyncSample::GetSystemTimeUs()
51 {
52     struct timespec now;
53     (void)clock_gettime(CLOCK_BOOTTIME, &now);
54     int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
55 
56     return nanoTime / NANOS_IN_MICRO;
57 }
58 
ConfigureVideoEncoder()59 int32_t VEncSyncSample::ConfigureVideoEncoder()
60 {
61     OH_AVFormat *format = OH_AVFormat_Create();
62     if (format == nullptr) {
63         return AV_ERR_UNKNOWN;
64     }
65     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
66     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
67     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
68     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
69     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
70     if (isAVCEncoder) {
71         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, avcProfile);
72     } else {
73         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, hevcProfile);
74     }
75     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, HEVC_PROFILE_MAIN);
76     if (DEFAULT_BITRATE_MODE == CQ) {
77         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, defaultQuality);
78     } else {
79         (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, defaultBitrate);
80     }
81     if (enableQP) {
82         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MAX, defaultQp);
83         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MIN, defaultQp);
84     }
85     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, DEFAULT_BITRATE_MODE);
86     if (enableColorSpaceParams) {
87         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, defaultRangeFlag);
88         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, DEFAULT_COLOR_PRIMARIES);
89         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, DEFAULT_TRANSFER_CHARACTERISTICS);
90         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, DEFAULT_MATRIX_COEFFICIENTS);
91     }
92     if (enableRepeat) {
93         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, defaultFrameAfter);
94         if (setMaxCount) {
95             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, defaultMaxCount);
96         }
97     }
98     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ENABLE_SYNC_MODE, enbleSyncMode);
99     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_B_FRAME, enbleBFrameMode);
100     int ret = OH_VideoEncoder_Configure(venc_, format);
101     OH_AVFormat_Destroy(format);
102     return ret;
103 }
104 
ConfigureVideoEncoderFuzz(int32_t data)105 int32_t VEncSyncSample::ConfigureVideoEncoderFuzz(int32_t data)
106 {
107     OH_AVFormat *format = OH_AVFormat_Create();
108     if (format == nullptr) {
109         cout << "Fatal: Failed to create format" << endl;
110         return AV_ERR_UNKNOWN;
111     }
112     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
113     defaultWidth = data;
114     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
115     defaultHeight = data;
116     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
117     double frameRate = data;
118     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
119 
120     OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, data);
121     OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, data);
122     OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, data);
123     OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, data);
124     OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, data);
125     OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
126     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
127     OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, data);
128     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ENABLE_SYNC_MODE, enbleSyncMode);
129     int ret = OH_VideoEncoder_Configure(venc_, format);
130     OH_AVFormat_Destroy(format);
131     return ret;
132 }
133 
CreateSurface()134 int32_t VEncSyncSample::CreateSurface()
135 {
136     int32_t ret = 0;
137     ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
138     if (ret != AV_ERR_OK) {
139         cout << "OH_VideoEncoder_GetSurface fail" << endl;
140         return ret;
141     }
142     if (DEFAULT_PIX_FMT == AV_PIXEL_FORMAT_RGBA1010102) {
143         ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, NATIVEBUFFER_PIXEL_FMT_RGBA_1010102);
144     } else {
145         ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
146     }
147     if (ret != AV_ERR_OK) {
148         cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
149         return ret;
150     }
151     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, defaultWidth, defaultHeight);
152     if (ret != AV_ERR_OK) {
153         cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
154         return ret;
155     }
156     return AV_ERR_OK;
157 }
158 
CreateVideoEncoder(const char * codecName)159 int32_t VEncSyncSample::CreateVideoEncoder(const char *codecName)
160 {
161     cap = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true, HARDWARE);
162     const char *tmpCodecName = OH_AVCapability_GetName(cap);
163     if (!strcmp(codecName, tmpCodecName)) {
164         isAVCEncoder = true;
165     } else {
166         isAVCEncoder = false;
167     }
168     venc_ = OH_VideoEncoder_CreateByName(codecName);
169     g_encSample = this;
170     return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
171 }
172 
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)173 uint32_t VEncSyncSample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
174 {
175     int32_t ret = 0;
176     struct Region region;
177     struct Region::Rect *rect = new Region::Rect();
178     rect->x = 0;
179     rect->y = 0;
180     rect->w = defaultWidth;
181     rect->h = defaultHeight;
182     region.rects = rect;
183     NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
184     ret = OH_NativeBuffer_Unmap(nativeBuffer);
185     if (ret != 0) {
186         cout << "OH_NativeBuffer_Unmap failed" << endl;
187         delete rect;
188         return ret;
189     }
190     ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
191     delete rect;
192     if (ret != 0) {
193         cout << "FlushBuffer failed" << endl;
194         return ret;
195     }
196     return ret;
197 }
198 
InputFuncSurfaceFuzz()199 void VEncSyncSample::InputFuncSurfaceFuzz()
200 {
201     OHNativeWindowBuffer *ohNativeWindowBuffer;
202     int fenceFd = -1;
203     if (nativeWindow == nullptr) {
204         cout << "nativeWindow == nullptr" << endl;
205         return;
206     }
207     int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
208     if (err != 0) {
209         cout << "RequestBuffer failed, GSError=" << err << endl;
210         return;
211     }
212     if (fenceFd > 0) {
213         close(fenceFd);
214     }
215     OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
216     void *virAddr = nullptr;
217     OH_NativeBuffer_Config config;
218     OH_NativeBuffer_GetConfig (nativeBuffer, &config);
219     err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
220     if (err != 0) {
221         cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
222         return;
223     }
224     uint8_t *dst = (uint8_t *)virAddr;
225     if (dst == nullptr) {
226         return;
227     }
228     if (memcpy_s(dst, (config.stride * config.height * THREE) / DOUBLE, fuzzData, fuzzSize) != EOK) {
229         return;
230     }
231     if (frameCount == maxFrameInput) {
232         err = OH_VideoEncoder_NotifyEndOfStream(venc_);
233         if (err != 0) {
234             cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
235             isRunning_.store(false);
236         }
237         return;
238     }
239     if (FlushSurf(ohNativeWindowBuffer, nativeBuffer)) {
240         return;
241     }
242     usleep(FRAME_INTERVAL);
243     frameCount++;
244 }
245 
SyncInputFuncFuzz()246 void VEncSyncSample::SyncInputFuncFuzz()
247 {
248     uint32_t index;
249     if (OH_VideoEncoder_QueryInputBuffer(venc_, &index, syncInputWaitTime) != AV_ERR_OK) {
250         return;
251     }
252     OH_AVBuffer *buffer = OH_VideoEncoder_GetInputBuffer(venc_, index);
253     if (buffer == nullptr) {
254         cout << "OH_VideoEncoder_GetInputBuffer fail" << endl;
255         errCount = errCount + 1;
256         return;
257     }
258     OH_AVCodecBufferAttr attr;
259     int32_t bufferSize = OH_AVBuffer_GetCapacity(buffer);
260     uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
261     if (fileBuffer == nullptr) {
262         return;
263     }
264     if (memcpy_s(fileBuffer, bufferSize, fuzzData, fuzzSize) != EOK) {
265         cout << "Fatal: memcpy fail" << endl;
266         return;
267     }
268     attr.size = fuzzSize;
269     attr.pts = TIMESTAMP_BASE + DURATION_BASE * frameIndex_;
270     frameIndex_++;
271     attr.offset = 0;
272     attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
273     OH_AVBuffer_SetBufferAttr(buffer, &attr);
274     OH_VideoEncoder_PushInputBuffer(venc_, index);
275     frameCount++;
276     if (sleepOnFPS) {
277         usleep(FRAME_INTERVAL);
278     }
279 }
280 
SyncOutputFuncFuzz()281 void VEncSyncSample::SyncOutputFuncFuzz()
282 {
283     uint32_t index = 0;
284     int32_t ret = OH_VideoEncoder_QueryOutputBuffer(venc_, &index, syncOutputWaitTime);
285     if (ret != AV_ERR_OK) {
286         return;
287     }
288     OH_AVBuffer *buffer = OH_VideoEncoder_GetOutputBuffer(venc_, index);
289     if (buffer == nullptr) {
290         cout << "OH_VideoEncoder_GetOutputBuffer fail" << endl;
291         errCount = errCount + 1;
292         return;
293     }
294 
295     if (OH_VideoEncoder_FreeOutputBuffer(venc_, index) != AV_ERR_OK) {
296         cout << "Fatal: ReleaseOutputBuffer fail" << endl;
297         errCount = errCount + 1;
298     }
299 }
300 
Release()301 int32_t VEncSyncSample::Release()
302 {
303     int ret = OH_VideoEncoder_Destroy(venc_);
304     venc_ = nullptr;
305     return ret;
306 }
307 
Stop()308 int32_t VEncSyncSample::Stop()
309 {
310     return OH_VideoEncoder_Stop(venc_);
311 }
312 
Start()313 int32_t VEncSyncSample::Start()
314 {
315     return OH_VideoEncoder_Start(venc_);
316 }
317 
SetParameter(int32_t data)318 int32_t VEncSyncSample::SetParameter(int32_t data)
319 {
320     if (venc_) {
321         OH_AVFormat *format = OH_AVFormat_Create();
322         if (format == nullptr) {
323             return AV_ERR_UNKNOWN;
324         }
325         double frameRate = data;
326         (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
327         OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
328         int ret = OH_VideoEncoder_SetParameter(venc_, format);
329         OH_AVFormat_Destroy(format);
330         return ret;
331     }
332     return AV_ERR_UNKNOWN;
333 }