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