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 }