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