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