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