• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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