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