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 "videoenc_sample.h"
21 #include "native_avcapability.h"
22 using namespace OHOS;
23 using namespace OHOS::Media;
24 using namespace std;
25 namespace {
26 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
27 constexpr int64_t NANOS_IN_MICRO = 1000L;
28 constexpr uint32_t FRAME_INTERVAL = 16666;
29 constexpr uint32_t MAX_PIXEL_FMT = 5;
30 constexpr uint8_t RGBA_SIZE = 4;
31 constexpr uint32_t IDR_FRAME_INTERVAL = 10;
32 constexpr uint32_t DOUBLE = 2;
33 constexpr uint32_t THREE = 3;
34 sptr<Surface> cs = nullptr;
35 sptr<Surface> ps = nullptr;
36 VEncNdkFuzzSample *g_encSample = nullptr;
37
clearIntqueue(std::queue<uint32_t> & q)38 void clearIntqueue(std::queue<uint32_t> &q)
39 {
40 std::queue<uint32_t> empty;
41 swap(empty, q);
42 }
43
clearBufferqueue(std::queue<OH_AVCodecBufferAttr> & q)44 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
45 {
46 std::queue<OH_AVCodecBufferAttr> empty;
47 swap(empty, q);
48 }
49 } // namespace
50
~VEncNdkFuzzSample()51 VEncNdkFuzzSample::~VEncNdkFuzzSample()
52 {
53 if (surfInput && nativeWindow) {
54 OH_NativeWindow_DestroyNativeWindow(nativeWindow);
55 nativeWindow = nullptr;
56 }
57 Release();
58 }
59
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)60 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
61 {
62 cout << "Error errorCode=" << errorCode << endl;
63 g_encSample->isRunning_.store(false);
64 g_encSample->signal_->inCond_.notify_all();
65 }
66
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)67 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
68 {
69 cout << "Format Changed" << endl;
70 }
71
VencInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)72 static void VencInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
73 {
74 if (g_encSample->isFlushing_) {
75 return;
76 }
77 if (g_encSample->inputCallbackFlush) {
78 g_encSample->Flush();
79 cout << "OH_VideoEncoder_Flush end" << endl;
80 g_encSample->isRunning_.store(false);
81 g_encSample->signal_->inCond_.notify_all();
82 g_encSample->signal_->outCond_.notify_all();
83 return;
84 }
85 if (g_encSample->inputCallbackStop) {
86 OH_VideoEncoder_Stop(codec);
87 cout << "OH_VideoEncoder_Stop end" << endl;
88 g_encSample->isRunning_.store(false);
89 g_encSample->signal_->inCond_.notify_all();
90 g_encSample->signal_->outCond_.notify_all();
91 return;
92 }
93 VEncSignal *signal = static_cast<VEncSignal *>(userData);
94 unique_lock<mutex> lock(signal->inMutex_);
95 signal->inIdxQueue_.push(index);
96 signal->inBufferQueue_.push(data);
97 signal->inCond_.notify_all();
98 }
99
VencOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)100 static void VencOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
101 void *userData)
102 {
103 if (g_encSample->isFlushing_) {
104 return;
105 }
106 if (g_encSample->outputCallbackFlush) {
107 g_encSample->Flush();
108 cout << "OH_VideoEncoder_Flush end" << endl;
109 g_encSample->isRunning_.store(false);
110 g_encSample->signal_->inCond_.notify_all();
111 g_encSample->signal_->outCond_.notify_all();
112 return;
113 }
114 if (g_encSample->outputCallbackStop) {
115 OH_VideoEncoder_Stop(codec);
116 cout << "OH_VideoEncoder_Stop end" << endl;
117 g_encSample->isRunning_.store(false);
118 g_encSample->signal_->inCond_.notify_all();
119 g_encSample->signal_->outCond_.notify_all();
120 return;
121 }
122 OH_VideoEncoder_FreeOutputData(codec, index);
123 }
GetSystemTimeUs()124 int64_t VEncNdkFuzzSample::GetSystemTimeUs()
125 {
126 struct timespec now;
127 (void)clock_gettime(CLOCK_BOOTTIME, &now);
128 int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
129
130 return nanoTime / NANOS_IN_MICRO;
131 }
132
ConfigureVideoEncoder()133 int32_t VEncNdkFuzzSample::ConfigureVideoEncoder()
134 {
135 OH_AVFormat *format = OH_AVFormat_Create();
136 if (format == nullptr) {
137 cout << "Fatal: Failed to create format" << endl;
138 return AV_ERR_UNKNOWN;
139 }
140 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
141 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
142 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
143 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
144 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, defaultBitrate);
145 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
146 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, 1);
147 if (defaultBitrateMode == CQ) {
148 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, defaultQuality);
149 }
150 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitrateMode);
151 int ret = OH_VideoEncoder_Configure(venc_, format);
152 OH_AVFormat_Destroy(format);
153 return ret;
154 }
155
ConfigureVideoEncoderTemporal(int32_t temporalGopSize)156 int32_t VEncNdkFuzzSample::ConfigureVideoEncoderTemporal(int32_t temporalGopSize)
157 {
158 OH_AVFormat *format = OH_AVFormat_Create();
159 if (format == nullptr) {
160 cout << "Fatal: Failed to create format" << endl;
161 return AV_ERR_UNKNOWN;
162 }
163 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
164 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
165 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
166 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
167 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, defaultBitrate);
168
169 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
170
171 if (temporalConfig) {
172 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize);
173 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE,
174 ADJACENT_REFERENCE);
175 }
176 if (temporalEnable) {
177 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, 1);
178 }
179 if (temporalJumpMode) {
180 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, JUMP_REFERENCE);
181 }
182 int ret = OH_VideoEncoder_Configure(venc_, format);
183 OH_AVFormat_Destroy(format);
184 return ret;
185 }
186
ConfigureVideoEncoderFuzz(int32_t data)187 int32_t VEncNdkFuzzSample::ConfigureVideoEncoderFuzz(int32_t data)
188 {
189 OH_AVFormat *format = OH_AVFormat_Create();
190 if (format == nullptr) {
191 cout << "Fatal: Failed to create format" << endl;
192 return AV_ERR_UNKNOWN;
193 }
194 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
195 defaultWidth = data;
196 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
197 defaultHeight = data;
198 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
199 double frameRate = data;
200 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
201
202 OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, data);
203 OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, data);
204 OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, data);
205 OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, data);
206 OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, data);
207 OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
208 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
209 OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, data);
210 int ret = OH_VideoEncoder_Configure(venc_, format);
211 OH_AVFormat_Destroy(format);
212 return ret;
213 }
214
SetVideoEncoderCallback()215 int32_t VEncNdkFuzzSample::SetVideoEncoderCallback()
216 {
217 signal_ = new VEncSignal();
218 if (signal_ == nullptr) {
219 cout << "Failed to new VEncSignal" << endl;
220 return AV_ERR_UNKNOWN;
221 }
222
223 cb_.onError = VencError;
224 cb_.onStreamChanged = VencFormatChanged;
225 cb_.onNeedInputData = VencInputDataReady;
226 cb_.onNeedOutputData = VencOutputDataReady;
227 return OH_VideoEncoder_SetCallback(venc_, cb_, static_cast<void *>(signal_));
228 }
229
StateEos()230 int32_t VEncNdkFuzzSample::StateEos()
231 {
232 unique_lock<mutex> lock(signal_->inMutex_);
233 signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
234 uint32_t index = signal_->inIdxQueue_.front();
235 signal_->inIdxQueue_.pop();
236 signal_->inBufferQueue_.pop();
237 lock.unlock();
238 OH_AVCodecBufferAttr attr;
239 attr.pts = 0;
240 attr.size = 0;
241 attr.offset = 0;
242 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
243 return OH_VideoEncoder_PushInputData(venc_, index, attr);
244 }
ReleaseInFile()245 void VEncNdkFuzzSample::ReleaseInFile()
246 {
247 if (inFile_ != nullptr) {
248 if (inFile_->is_open()) {
249 inFile_->close();
250 }
251 inFile_.reset();
252 inFile_ = nullptr;
253 }
254 }
255
StopInloop()256 void VEncNdkFuzzSample::StopInloop()
257 {
258 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
259 unique_lock<mutex> lock(signal_->inMutex_);
260 clearIntqueue(signal_->inIdxQueue_);
261 isRunning_.store(false);
262 signal_->inCond_.notify_all();
263 lock.unlock();
264
265 inputLoop_->join();
266 inputLoop_ = nullptr;
267 }
268 }
269
TestApi()270 void VEncNdkFuzzSample::TestApi()
271 {
272 OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
273 OH_VideoEncoder_Prepare(venc_);
274 OH_VideoEncoder_GetInputDescription(venc_);
275 OH_VideoEncoder_Start(venc_);
276 OH_AVFormat *format = OH_AVFormat_Create();
277 OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
278 OH_VideoEncoder_SetParameter(venc_, format);
279 OH_VideoEncoder_NotifyEndOfStream(venc_);
280 OH_VideoEncoder_GetOutputDescription(venc_);
281 OH_AVFormat_Destroy(format);
282 OH_VideoEncoder_Flush(venc_);
283 bool isValid = false;
284 OH_VideoEncoder_IsValid(venc_, &isValid);
285 OH_VideoEncoder_Stop(venc_);
286 OH_VideoEncoder_Reset(venc_);
287 }
288
CreateSurface()289 int32_t VEncNdkFuzzSample::CreateSurface()
290 {
291 int32_t ret = 0;
292 ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
293 if (ret != AV_ERR_OK) {
294 cout << "OH_VideoEncoder_GetSurface fail" << endl;
295 return ret;
296 }
297 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
298 if (ret != AV_ERR_OK) {
299 cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
300 return ret;
301 }
302 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, defaultWidth, defaultHeight);
303 if (ret != AV_ERR_OK) {
304 cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
305 return ret;
306 }
307 return AV_ERR_OK;
308 }
309
GetStride()310 void VEncNdkFuzzSample::GetStride()
311 {
312 OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
313 int32_t inputStride = 0;
314 OH_AVFormat_GetIntValue(format, "stride", &inputStride);
315 stride_ = inputStride;
316 OH_AVFormat_Destroy(format);
317 }
318
OpenFile()319 int32_t VEncNdkFuzzSample::OpenFile()
320 {
321 if (fuzzMode) {
322 return AV_ERR_OK;
323 }
324 int32_t ret = AV_ERR_OK;
325 inFile_ = make_unique<ifstream>();
326 if (inFile_ == nullptr) {
327 isRunning_.store(false);
328 (void)OH_VideoEncoder_Stop(venc_);
329 return AV_ERR_UNKNOWN;
330 }
331 inFile_->open(inpDir, ios::in | ios::binary);
332 if (!inFile_->is_open()) {
333 cout << "file open fail" << endl;
334 isRunning_.store(false);
335 (void)OH_VideoEncoder_Stop(venc_);
336 inFile_->close();
337 inFile_.reset();
338 inFile_ = nullptr;
339 return AV_ERR_UNKNOWN;
340 }
341 return ret;
342 }
343
StartVideoEncoder()344 int32_t VEncNdkFuzzSample::StartVideoEncoder()
345 {
346 isRunning_.store(true);
347 int32_t ret = 0;
348 if (surfInput) {
349 ret = CreateSurface();
350 if (ret != AV_ERR_OK) {
351 return ret;
352 }
353 }
354 if (venc_ == nullptr) {
355 cout << "codec is nullptr" << endl;
356 }
357 ret = OH_VideoEncoder_Start(venc_);
358 GetStride();
359 if (ret != AV_ERR_OK) {
360 cout << "Failed to start codec" << endl;
361 isRunning_.store(false);
362 signal_->inCond_.notify_all();
363 signal_->outCond_.notify_all();
364 return ret;
365 }
366 if (OpenFile() != AV_ERR_OK) {
367 return AV_ERR_UNKNOWN;
368 }
369 if (surfInput) {
370 inputLoop_ = make_unique<thread>(&VEncNdkFuzzSample::InputFuncSurface, this);
371 } else {
372 inputLoop_ = make_unique<thread>(&VEncNdkFuzzSample::InputFunc, this);
373 }
374 if (inputLoop_ == nullptr) {
375 isRunning_.store(false);
376 (void)OH_VideoEncoder_Stop(venc_);
377 ReleaseInFile();
378 return AV_ERR_UNKNOWN;
379 }
380 return AV_ERR_OK;
381 }
382
CreateVideoEncoder()383 int32_t VEncNdkFuzzSample::CreateVideoEncoder()
384 {
385 OH_AVCapability *cap = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true, HARDWARE);
386 const char *tmpCodecName = OH_AVCapability_GetName(cap);
387 char gCodecName[128] = {};
388 if (memcpy_s(gCodecName, sizeof(gCodecName), tmpCodecName, strlen(tmpCodecName)) != 0) {
389 cout << "memcpy failed" << endl;
390 }
391
392 venc_ = OH_VideoEncoder_CreateByName(gCodecName);
393 if (!venc_) {
394 cout << "create codec failed" << endl;
395 }
396 g_encSample = this;
397 return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
398 }
399
WaitForEOS()400 void VEncNdkFuzzSample::WaitForEOS()
401 {
402 if (inputLoop_)
403 inputLoop_->join();
404 if (outputLoop_)
405 outputLoop_->join();
406 inputLoop_ = nullptr;
407 outputLoop_ = nullptr;
408 }
409
ReturnZeroIfEOS(uint32_t expectedSize)410 uint32_t VEncNdkFuzzSample::ReturnZeroIfEOS(uint32_t expectedSize)
411 {
412 if (inFile_->gcount() != (expectedSize)) {
413 cout << "no more data" << endl;
414 return 0;
415 }
416 return 1;
417 }
418
ReadOneFrameYUV420SP(uint8_t * dst)419 uint32_t VEncNdkFuzzSample::ReadOneFrameYUV420SP(uint8_t *dst)
420 {
421 uint8_t *start = dst;
422 // copy Y
423 for (uint32_t i = 0; i < defaultHeight; i++) {
424 inFile_->read(reinterpret_cast<char *>(dst), defaultWidth);
425 if (!ReturnZeroIfEOS(defaultWidth)) {
426 return 0;
427 }
428 dst += stride_;
429 }
430 // copy UV
431 for (uint32_t i = 0; i < defaultHeight / sampleRatio; i++) {
432 inFile_->read(reinterpret_cast<char *>(dst), defaultWidth);
433 if (!ReturnZeroIfEOS(defaultWidth)) {
434 return 0;
435 }
436 dst += stride_;
437 }
438 return dst - start;
439 }
440
ReadOneFrameRGBA8888(uint8_t * dst)441 void VEncNdkFuzzSample::ReadOneFrameRGBA8888(uint8_t *dst)
442 {
443 for (uint32_t i = 0; i < defaultHeight; i++) {
444 inFile_->read(reinterpret_cast<char *>(dst), defaultWidth * RGBA_SIZE);
445 dst += stride_;
446 }
447 }
448
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)449 uint32_t VEncNdkFuzzSample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
450 {
451 struct Region region;
452 struct Region::Rect *rect = new Region::Rect();
453 rect->x = 0;
454 rect->y = 0;
455 rect->w = defaultWidth;
456 rect->h = defaultHeight;
457 region.rects = rect;
458 NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
459 int32_t err = OH_NativeBuffer_Unmap(nativeBuffer);
460 if (err != 0) {
461 cout << "OH_NativeBuffer_Unmap failed" << endl;
462 return 1;
463 }
464 err = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
465 delete rect;
466 if (err != 0) {
467 cout << "FlushBuffer failed" << endl;
468 return 1;
469 }
470 return 0;
471 }
472
ProcessNativeWindowBuffer(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)473 bool VEncNdkFuzzSample::ProcessNativeWindowBuffer(OHNativeWindowBuffer *ohNativeWindowBuffer,
474 OH_NativeBuffer *nativeBuffer)
475 {
476 if (nativeWindow == nullptr) {
477 cout << "nativeWindow == nullptr" << endl;
478 return false;
479 }
480
481 int fenceFd = -1;
482 int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
483 if (err != 0) {
484 cout << "RequestBuffer failed, GSError=" << err << endl;
485 return false;
486 }
487 if (fenceFd > 0) {
488 close(fenceFd);
489 }
490
491 nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
492 void *virAddr = nullptr;
493 OH_NativeBuffer_Config config;
494 OH_NativeBuffer_GetConfig(nativeBuffer, &config);
495 err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
496 if (err != 0) {
497 cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
498 isRunning_.store(false);
499 return false;
500 }
501
502 uint8_t *dst = (uint8_t *)virAddr;
503 if (fuzzMode) {
504 if (dst == nullptr) {
505 return false;
506 }
507 if (memcpy_s(dst, (config.stride * config.height * THREE) / DOUBLE, fuzzData, fuzzSize) != EOK) {
508 cout << "Fatal: memcpy fail" << endl;
509 return false;
510 }
511 } else {
512 const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
513 int stride = sbuffer->GetStride();
514 if (dst == nullptr || stride < defaultWidth) {
515 cout << "invalid va or stride=" << stride << endl;
516 err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
517 isRunning_.store(false);
518 return false;
519 }
520 stride_ = stride;
521 if (!ReadOneFrameYUV420SP(dst)) {
522 return false;
523 }
524 }
525
526 return true;
527 }
528
InputFuncSurface()529 void VEncNdkFuzzSample::InputFuncSurface()
530 {
531 bool enableInput = true;
532 while (enableInput) {
533 OH_NativeBuffer *nativeBuffer = nullptr;
534 if (outputCallbackFlush || outputCallbackStop) {
535 OH_VideoEncoder_NotifyEndOfStream(venc_);
536 enableInput = false;
537 break;
538 }
539
540 OHNativeWindowBuffer *ohNativeWindowBuffer = nullptr;
541 if (!ProcessNativeWindowBuffer(ohNativeWindowBuffer, nativeBuffer)) {
542 break;
543 }
544
545 if (fuzzMode && frameCount == defaultFuzzTime) {
546 int32_t err = OH_VideoEncoder_NotifyEndOfStream(venc_);
547 if (err != 0) {
548 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
549 }
550 break;
551 }
552 if (FlushSurf(ohNativeWindowBuffer, nativeBuffer)) {
553 break;
554 }
555
556 usleep(FRAME_INTERVAL);
557 frameCount++;
558 }
559 }
560
FlushBuffer()561 void VEncNdkFuzzSample::FlushBuffer()
562 {
563 unique_lock<mutex> inLock(signal_->inMutex_);
564 clearIntqueue(signal_->inIdxQueue_);
565 std::queue<OH_AVMemory *> empty;
566 swap(empty, signal_->inBufferQueue_);
567 signal_->inCond_.notify_all();
568 inLock.unlock();
569 unique_lock<mutex> outLock(signal_->outMutex_);
570 clearIntqueue(signal_->outIdxQueue_);
571 clearBufferqueue(signal_->attrQueue_);
572 signal_->outCond_.notify_all();
573 outLock.unlock();
574 }
575
RepeatStartBeforeEOS()576 void VEncNdkFuzzSample::RepeatStartBeforeEOS()
577 {
578 if (repeatStartFlushBeforeEos > 0) {
579 repeatStartFlushBeforeEos--;
580 OH_VideoEncoder_Flush(venc_);
581 FlushBuffer();
582 OH_VideoEncoder_Start(venc_);
583 }
584
585 if (repeatStartStopBeforeEos > 0) {
586 repeatStartStopBeforeEos--;
587 OH_VideoEncoder_Stop(venc_);
588 FlushBuffer();
589 OH_VideoEncoder_Start(venc_);
590 }
591 }
592
RandomEOS(uint32_t index)593 bool VEncNdkFuzzSample::RandomEOS(uint32_t index)
594 {
595 if (enableRandomEos && randomEos == frameCount) {
596 OH_AVCodecBufferAttr attr;
597 attr.pts = 0;
598 attr.size = 0;
599 attr.offset = 0;
600 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
601 OH_VideoEncoder_PushInputData(venc_, index, attr);
602 cout << "random eos" << endl;
603 frameCount++;
604 unique_lock<mutex> lock(signal_->inMutex_);
605 signal_->inIdxQueue_.pop();
606 signal_->inBufferQueue_.pop();
607 return true;
608 }
609 return false;
610 }
611
AutoSwitchParam()612 void VEncNdkFuzzSample::AutoSwitchParam()
613 {
614 int64_t currentBitrate = defaultBitrate;
615 double currentFrameRate = defaultFrameRate;
616 if (frameCount == switchParamsTimeSec * static_cast<int32_t>(defaultFrameRate)) {
617 OH_AVFormat *format = OH_AVFormat_Create();
618 if (needResetBitrate) {
619 currentBitrate = defaultBitrate >> 1;
620 cout<<"switch bitrate "<< currentBitrate;
621 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, currentBitrate);
622 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
623 }
624 if (needResetFrameRate) {
625 currentFrameRate = defaultFrameRate * DOUBLE;
626 cout<< "switch framerate" << currentFrameRate << endl;
627 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, currentFrameRate);
628 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
629 }
630 OH_AVFormat_Destroy(format);
631 }
632 if (frameCount == switchParamsTimeSec * static_cast<int32_t>(defaultFrameRate) * DOUBLE) {
633 OH_AVFormat *format = OH_AVFormat_Create();
634 if (needResetBitrate) {
635 currentBitrate = defaultBitrate << 1;
636 cout<<"switch bitrate "<< currentBitrate;
637 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, currentBitrate);
638 }
639 if (needResetFrameRate) {
640 currentFrameRate = defaultFrameRate / DOUBLE;
641 cout<< "switch framerate" << currentFrameRate << endl;
642 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, currentFrameRate);
643 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
644 }
645 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
646 OH_AVFormat_Destroy(format);
647 }
648 }
649
SetEOS(uint32_t index)650 void VEncNdkFuzzSample::SetEOS(uint32_t index)
651 {
652 OH_AVCodecBufferAttr attr;
653 attr.pts = 0;
654 attr.size = 0;
655 attr.offset = 0;
656 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
657 int32_t res = OH_VideoEncoder_PushInputData(venc_, index, attr);
658 cout << "OH_VideoEncoder_PushInputData EOS res: " << res << endl;
659 unique_lock<mutex> lock(signal_->inMutex_);
660 signal_->inIdxQueue_.pop();
661 signal_->inBufferQueue_.pop();
662 }
663
SetForceIDR()664 void VEncNdkFuzzSample::SetForceIDR()
665 {
666 OH_AVFormat *format = OH_AVFormat_Create();
667 OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
668 OH_VideoEncoder_SetParameter(venc_, format);
669 OH_AVFormat_Destroy(format);
670 }
671
PushData(OH_AVMemory * buffer,uint32_t index,int32_t & result)672 int32_t VEncNdkFuzzSample::PushData(OH_AVMemory *buffer, uint32_t index, int32_t &result)
673 {
674 int32_t res = -2;
675 OH_AVCodecBufferAttr attr;
676 uint8_t *fileBuffer = OH_AVMemory_GetAddr(buffer);
677 if (fileBuffer == nullptr) {
678 cout << "Fatal: no memory" << endl;
679 return -1;
680 }
681 int32_t size = OH_AVMemory_GetSize(buffer);
682 if (DEFAULT_PIX_FMT == AV_PIXEL_FORMAT_RGBA) {
683 if (size < defaultHeight * stride_) {
684 return -1;
685 }
686 ReadOneFrameRGBA8888(fileBuffer);
687 attr.size = stride_ * defaultHeight;
688 } else {
689 if (size < (defaultHeight * stride_ + (defaultHeight * stride_ / DOUBLE))) {
690 return -1;
691 }
692 attr.size = ReadOneFrameYUV420SP(fileBuffer);
693 }
694 if (repeatRun && inFile_->eof()) {
695 inFile_->clear();
696 inFile_->seekg(0, ios::beg);
697 encodeCount++;
698 cout << "repeat"<< " encodeCount:" << encodeCount << endl;
699 return -1;
700 }
701 if (inFile_->eof()) {
702 SetEOS(index);
703 return 0;
704 }
705 attr.pts = GetSystemTimeUs();
706 attr.offset = 0;
707 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
708 if (enableForceIDR && (frameCount % IDR_FRAME_INTERVAL == 0)) {
709 SetForceIDR();
710 }
711 result = OH_VideoEncoder_PushInputData(venc_, index, attr);
712 unique_lock<mutex> lock(signal_->inMutex_);
713 signal_->inIdxQueue_.pop();
714 signal_->inBufferQueue_.pop();
715 return res;
716 }
717
CheckResult(bool isRandomEosSuccess,int32_t pushResult)718 int32_t VEncNdkFuzzSample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
719 {
720 if (isRandomEosSuccess) {
721 if (pushResult == 0) {
722 errCount = errCount + 1;
723 cout << "push input after eos should be failed! pushResult:" << pushResult << endl;
724 }
725 return -1;
726 } else if (pushResult != 0) {
727 errCount = errCount + 1;
728 cout << "push input data failed, error:" << pushResult << endl;
729 return -1;
730 }
731 return 0;
732 }
733
InputDataNormal(bool & runningFlag,uint32_t index,OH_AVMemory * buffer)734 void VEncNdkFuzzSample::InputDataNormal(bool &runningFlag, uint32_t index, OH_AVMemory *buffer)
735 {
736 if (!inFile_->eof()) {
737 bool isRandomEosSuccess = RandomEOS(index);
738 if (isRandomEosSuccess) {
739 runningFlag = false;
740 return;
741 }
742 int32_t pushResult = 0;
743 int32_t ret = PushData(buffer, index, pushResult);
744 if (ret == 0) {
745 runningFlag = false;
746 return;
747 } else if (ret == -1) {
748 return;
749 }
750 if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
751 runningFlag = false;
752 isRunning_.store(false);
753 signal_->inCond_.notify_all();
754 signal_->outCond_.notify_all();
755 return;
756 }
757 frameCount++;
758 if (enableAutoSwitchParam) {
759 AutoSwitchParam();
760 }
761 }
762 }
763
InputDataFuzz(bool & runningFlag,uint32_t index)764 void VEncNdkFuzzSample::InputDataFuzz(bool &runningFlag, uint32_t index)
765 {
766 frameCount++;
767 if (frameCount == defaultFuzzTime) {
768 SetEOS(index);
769 runningFlag = false;
770 return;
771 }
772 OH_AVCodecBufferAttr attr;
773 attr.size = fuzzSize;
774 attr.pts = GetSystemTimeUs();
775 attr.offset = 0;
776 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
777 OH_VideoEncoder_PushInputData(venc_, index, attr);
778 unique_lock<mutex> lock(signal_->inMutex_);
779 signal_->inIdxQueue_.pop();
780 signal_->inBufferQueue_.pop();
781 }
782
InputFunc()783 void VEncNdkFuzzSample::InputFunc()
784 {
785 errCount = 0;
786 bool runningFlag = true;
787 while (runningFlag) {
788 if (!isRunning_.load()) {
789 break;
790 }
791 RepeatStartBeforeEOS();
792 unique_lock<mutex> lock(signal_->inMutex_);
793 signal_->inCond_.wait(lock, [this]() {
794 if (!isRunning_.load()) {
795 return true;
796 }
797 return signal_->inIdxQueue_.size() > 0 && !isFlushing_.load();
798 });
799 if (!isRunning_.load()) {
800 break;
801 }
802 uint32_t index = signal_->inIdxQueue_.front();
803 auto buffer = signal_->inBufferQueue_.front();
804 lock.unlock();
805 unique_lock<mutex> flushlock(signal_->flushMutex_);
806 if (isFlushing_) {
807 continue;
808 }
809 if (fuzzMode == false) {
810 InputDataNormal(runningFlag, index, buffer);
811 } else {
812 InputDataFuzz(runningFlag, index);
813 }
814 flushlock.unlock();
815 if (sleepOnFPS) {
816 usleep(FRAME_INTERVAL);
817 }
818 }
819 }
820
CheckAttrFlag(OH_AVCodecBufferAttr attr)821 int32_t VEncNdkFuzzSample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
822 {
823 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
824 cout << "attr.flags == AVCODEC_BUFFER_FLAGS_EOS" << endl;
825 unique_lock<mutex> inLock(signal_->inMutex_);
826 isRunning_.store(false);
827 signal_->inCond_.notify_all();
828 signal_->outCond_.notify_all();
829 inLock.unlock();
830 return -1;
831 }
832 if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
833 cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
834 }
835 outCount = outCount + 1;
836 return 0;
837 }
838
OutputFuncFail()839 void VEncNdkFuzzSample::OutputFuncFail()
840 {
841 cout << "errCount > 0" << endl;
842 unique_lock<mutex> inLock(signal_->inMutex_);
843 isRunning_.store(false);
844 signal_->inCond_.notify_all();
845 signal_->outCond_.notify_all();
846 inLock.unlock();
847 (void)Stop();
848 Release();
849 }
850
OutputFunc()851 void VEncNdkFuzzSample::OutputFunc()
852 {
853 bool enableOutput = true;
854 while (enableOutput) {
855 if (!isRunning_.load()) {
856 enableOutput = false;
857 break;
858 }
859 OH_AVCodecBufferAttr attr;
860 uint32_t index;
861 unique_lock<mutex> lock(signal_->outMutex_);
862 signal_->outCond_.wait(lock, [this]() {
863 if (!isRunning_.load()) {
864 return true;
865 }
866 return signal_->outIdxQueue_.size() > 0 && !isFlushing_.load();
867 });
868 if (!isRunning_.load()) {
869 break;
870 }
871 index = signal_->outIdxQueue_.front();
872 attr = signal_->attrQueue_.front();
873 signal_->outBufferQueue_.pop();
874 signal_->outIdxQueue_.pop();
875 signal_->attrQueue_.pop();
876 lock.unlock();
877 if (CheckAttrFlag(attr) == -1) {
878 break;
879 }
880
881 if (OH_VideoEncoder_FreeOutputData(venc_, index) != AV_ERR_OK) {
882 cout << "Fatal: ReleaseOutputBuffer fail" << endl;
883 errCount = errCount + 1;
884 }
885 if (errCount > 0) {
886 OutputFuncFail();
887 break;
888 }
889 }
890 }
891
Flush()892 int32_t VEncNdkFuzzSample::Flush()
893 {
894 isFlushing_.store(true);
895 unique_lock<mutex> flushLock(signal_->flushMutex_);
896 unique_lock<mutex> inLock(signal_->inMutex_);
897 clearIntqueue(signal_->inIdxQueue_);
898 signal_->inCond_.notify_all();
899 inLock.unlock();
900 unique_lock<mutex> outLock(signal_->outMutex_);
901 clearIntqueue(signal_->outIdxQueue_);
902 clearBufferqueue(signal_->attrQueue_);
903 signal_->outCond_.notify_all();
904 outLock.unlock();
905 int32_t ret = OH_VideoEncoder_Flush(venc_);
906 isFlushing_.store(false);
907 flushLock.unlock();
908 return ret;
909 }
910
Reset()911 int32_t VEncNdkFuzzSample::Reset()
912 {
913 isRunning_.store(false);
914 StopInloop();
915 StopOutloop();
916 ReleaseInFile();
917 return OH_VideoEncoder_Reset(venc_);
918 }
919
Release()920 int32_t VEncNdkFuzzSample::Release()
921 {
922 int ret = OH_VideoEncoder_Destroy(venc_);
923 venc_ = nullptr;
924 if (signal_ != nullptr) {
925 delete signal_;
926 signal_ = nullptr;
927 }
928 return ret;
929 }
930
Stop()931 int32_t VEncNdkFuzzSample::Stop()
932 {
933 StopInloop();
934 clearIntqueue(signal_->outIdxQueue_);
935 clearBufferqueue(signal_->attrQueue_);
936 ReleaseInFile();
937 return OH_VideoEncoder_Stop(venc_);
938 }
939
Start()940 int32_t VEncNdkFuzzSample::Start()
941 {
942 return OH_VideoEncoder_Start(venc_);
943 }
944
StopOutloop()945 void VEncNdkFuzzSample::StopOutloop()
946 {
947 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
948 unique_lock<mutex> lock(signal_->outMutex_);
949 clearIntqueue(signal_->outIdxQueue_);
950 clearBufferqueue(signal_->attrQueue_);
951 signal_->outCond_.notify_all();
952 lock.unlock();
953 }
954 }
955
SetParameter(OH_AVFormat * format)956 int32_t VEncNdkFuzzSample::SetParameter(OH_AVFormat *format)
957 {
958 if (venc_) {
959 return OH_VideoEncoder_SetParameter(venc_, format);
960 }
961 return AV_ERR_UNKNOWN;
962 }
963
SetParameterFuzz(int32_t data)964 int32_t VEncNdkFuzzSample::SetParameterFuzz(int32_t data)
965 {
966 if (venc_) {
967 OH_AVFormat *format = OH_AVFormat_Create();
968 if (format == nullptr) {
969 return AV_ERR_UNKNOWN;
970 }
971 double frameRate = data;
972 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
973 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
974 int ret = OH_VideoEncoder_SetParameter(venc_, format);
975 OH_AVFormat_Destroy(format);
976 return ret;
977 }
978 return AV_ERR_UNKNOWN;
979 }
980