• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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_api11_sample.h"
21 using namespace OHOS;
22 using namespace OHOS::Media;
23 using namespace std;
24 namespace {
25 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
26 constexpr int64_t NANOS_IN_MICRO = 1000L;
27 constexpr uint32_t FRAME_INTERVAL = 16666;
28 constexpr uint32_t MAX_PIXEL_FMT = 5;
29 constexpr uint32_t DEFAULT_BITRATE = 10000000;
30 constexpr uint32_t DOUBLE = 2;
31 constexpr uint32_t THREE = 3;
32 sptr<Surface> cs = nullptr;
33 sptr<Surface> ps = nullptr;
34 VEncAPI11FuzzSample *g_vEncSample = nullptr;
35 
clearIntqueue(std::queue<uint32_t> & q)36 void clearIntqueue(std::queue<uint32_t> &q)
37 {
38     std::queue<uint32_t> empty;
39     swap(empty, q);
40 }
41 } // namespace
42 
~VEncAPI11FuzzSample()43 VEncAPI11FuzzSample::~VEncAPI11FuzzSample()
44 {
45     if (surfInput && nativeWindow) {
46         OH_NativeWindow_DestroyNativeWindow(nativeWindow);
47         nativeWindow = nullptr;
48     }
49     Release();
50 }
51 
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)52 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
53 {
54     cout << "Error errorCode=" << errorCode << endl;
55     g_vEncSample->isRunning_.store(false);
56     g_vEncSample->signal_->inCond_.notify_all();
57 }
58 
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)59 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
60 {
61     cout << "Format Changed" << endl;
62 }
63 
onEncInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)64 static void onEncInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
65 {
66     VEncSignal *signal = static_cast<VEncSignal *>(userData);
67     unique_lock<mutex> lock(signal->inMutex_);
68     signal->inIdxQueue_.push(index);
69     signal->inBufferQueue_.push(buffer);
70     signal->inCond_.notify_all();
71 }
72 
onEncOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)73 static void onEncOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
74 {
75     OH_VideoEncoder_FreeOutputBuffer(codec, index);
76 }
77 
onEncInputParam(OH_AVCodec * codec,uint32_t index,OH_AVFormat * parameter,void * userData)78 static void onEncInputParam(OH_AVCodec *codec, uint32_t index, OH_AVFormat *parameter, void *userData)
79 {
80     OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
81     OH_VideoEncoder_PushInputParameter(codec, index);
82     return;
83 }
84 
GetSystemTimeUs()85 int64_t VEncAPI11FuzzSample::GetSystemTimeUs()
86 {
87     struct timespec now;
88     (void)clock_gettime(CLOCK_BOOTTIME, &now);
89     int64_t nanoTime = reinterpret_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
90 
91     return nanoTime / NANOS_IN_MICRO;
92 }
93 
ConfigureVideoEncoderFuzz(int32_t data)94 int32_t VEncAPI11FuzzSample::ConfigureVideoEncoderFuzz(int32_t data)
95 {
96     OH_AVFormat *format = OH_AVFormat_Create();
97     if (format == nullptr) {
98         cout << "Fatal: Failed to create format" << endl;
99         return AV_ERR_UNKNOWN;
100     }
101     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
102     defaultWidth = data;
103     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
104     defaultHeight = data;
105     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
106     double frameRate = data;
107     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
108 
109     OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, defaultRangeFlag);
110     OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, defaultColorPrimaries);
111     OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, defaultTransferCharacteristics);
112     OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, defaultMatarixCoefficients);
113     OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
114     OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitrateMode);
115     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, defaultBitRate);
116     OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, defaultQuality);
117     if (enableRepeat) {
118         OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, defaultFrameAfter);
119         if (setMaxCount) {
120             OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, defaultMaxCount);
121         }
122     }
123 
124     int ret = OH_VideoEncoder_Configure(venc_, format);
125     OH_AVFormat_Destroy(format);
126     return ret;
127 }
128 
ConfigureVideoEncoder()129 int32_t VEncAPI11FuzzSample::ConfigureVideoEncoder()
130 {
131     OH_AVFormat *format = OH_AVFormat_Create();
132     if (format == nullptr) {
133         return AV_ERR_UNKNOWN;
134     }
135     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
136     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
137     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defaultPixFmt);
138     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
139     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
140     if (defaultBitRate == CQ) {
141         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, defaultQuality);
142     } else {
143         (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitRate);
144     }
145     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitrateMode);
146     int ret = OH_VideoEncoder_Configure(venc_, format);
147     OH_AVFormat_Destroy(format);
148     return ret;
149 }
SetVideoEncoderCallback()150 int32_t VEncAPI11FuzzSample::SetVideoEncoderCallback()
151 {
152     signal_ = new VEncSignal();
153     if (signal_ == nullptr) {
154         cout << "Failed to new VEncSignal" << endl;
155         return AV_ERR_UNKNOWN;
156     }
157     if (surfInput) {
158         int32_t ret = OH_VideoEncoder_RegisterParameterCallback(venc_, onEncInputParam, static_cast<void *>(this));
159         if (ret != AV_ERR_OK) {
160             return ret;
161         }
162     }
163     cb_.onError = VencError;
164     cb_.onStreamChanged = VencFormatChanged;
165     cb_.onNeedInputBuffer = onEncInputBufferAvailable;
166     cb_.onNewOutputBuffer = onEncOutputBufferAvailable;
167     return OH_VideoEncoder_RegisterCallback(venc_, cb_, static_cast<void *>(signal_));
168 }
169 
StopInloop()170 void VEncAPI11FuzzSample::StopInloop()
171 {
172     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
173         unique_lock<mutex> lock(signal_->inMutex_);
174         clearIntqueue(signal_->inIdxQueue_);
175         isRunning_.store(false);
176         signal_->inCond_.notify_all();
177         lock.unlock();
178 
179         inputLoop_->join();
180         inputLoop_ = nullptr;
181     }
182 }
183 
ReleaseInFile()184 void VEncAPI11FuzzSample::ReleaseInFile()
185 {
186     if (inFile_ != nullptr) {
187         if (inFile_->is_open()) {
188             inFile_->close();
189         }
190         inFile_.reset();
191         inFile_ = nullptr;
192     }
193 }
194 
CreateSurface()195 int32_t VEncAPI11FuzzSample::CreateSurface()
196 {
197     int32_t ret = 0;
198     ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
199     if (ret != AV_ERR_OK) {
200         cout << "OH_VideoEncoder_GetSurface fail" << endl;
201         return ret;
202     }
203     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
204     if (ret != AV_ERR_OK) {
205         cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
206         return ret;
207     }
208     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, defaultWidth, defaultHeight);
209     if (ret != AV_ERR_OK) {
210         cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
211         return ret;
212     }
213     return AV_ERR_OK;
214 }
215 
OpenFile()216 int32_t VEncAPI11FuzzSample::OpenFile()
217 {
218     if (fuzzMode) {
219         return AV_ERR_OK;
220     }
221     int32_t ret = AV_ERR_OK;
222     inFile_ = make_unique<ifstream>();
223     if (inFile_ == nullptr) {
224         isRunning_.store(false);
225         (void)OH_VideoEncoder_Stop(venc_);
226         return AV_ERR_UNKNOWN;
227     }
228     inFile_->open(inpDir, ios::in | ios::binary);
229     if (!inFile_->is_open()) {
230         cout << "file open fail" << endl;
231         isRunning_.store(false);
232         (void)OH_VideoEncoder_Stop(venc_);
233         inFile_->close();
234         inFile_.reset();
235         inFile_ = nullptr;
236         return AV_ERR_UNKNOWN;
237     }
238     return ret;
239 }
240 
GetStride()241 void VEncAPI11FuzzSample::GetStride()
242 {
243     OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
244     int32_t inputStride = 0;
245     OH_AVFormat_GetIntValue(format, "stride", &inputStride);
246     stride_ = inputStride;
247     OH_AVFormat_Destroy(format);
248 }
249 
StartVideoEncoder()250 int32_t VEncAPI11FuzzSample::StartVideoEncoder()
251 {
252     isRunning_.store(true);
253     int32_t ret = 0;
254     if (surfInput) {
255         ret = CreateSurface();
256         if (ret != AV_ERR_OK) {
257             return ret;
258         }
259     }
260     if (OpenFile() != AV_ERR_OK) {
261         return AV_ERR_UNKNOWN;
262     }
263     ret = OH_VideoEncoder_Start(venc_);
264     GetStride();
265     if (ret != AV_ERR_OK) {
266         isRunning_.store(false);
267         signal_->inCond_.notify_all();
268         return ret;
269     }
270     if (surfInput) {
271         inputLoop_ = make_unique<thread>(&VEncAPI11FuzzSample::InputFuncSurface, this);
272     } else {
273         inputLoop_ = make_unique<thread>(&VEncAPI11FuzzSample::InputFunc, this);
274     }
275     if (inputLoop_ == nullptr) {
276         isRunning_.store(false);
277         (void)OH_VideoEncoder_Stop(venc_);
278         return AV_ERR_UNKNOWN;
279     }
280     return AV_ERR_OK;
281 }
282 
CreateVideoEncoder()283 int32_t VEncAPI11FuzzSample::CreateVideoEncoder()
284 {
285     venc_ = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
286     g_vEncSample = this;
287     return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
288 }
289 
WaitForEOS()290 void VEncAPI11FuzzSample::WaitForEOS()
291 {
292     if (inputLoop_)
293         inputLoop_->join();
294     inputLoop_ = nullptr;
295 }
296 
PushData(OH_AVBuffer * buffer,uint32_t index,int32_t & result)297 int32_t VEncAPI11FuzzSample::PushData(OH_AVBuffer *buffer, uint32_t index, int32_t &result)
298 {
299     int32_t res = -2;
300     OH_AVCodecBufferAttr attr;
301     uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
302     if (fileBuffer == nullptr) {
303         cout << "Fatal: no memory" << endl;
304         return -1;
305     }
306     int32_t size = OH_AVBuffer_GetCapacity(buffer);
307     if (size < (defaultWidth * stride_ + (defaultWidth * stride_ / DOUBLE))) {
308         return -1;
309     }
310     attr.size = ReadOneFrameYUV420SP(fileBuffer);
311     if (inFile_->eof()) {
312         SetEOS(index, buffer);
313         return 0;
314     }
315     attr.pts = GetSystemTimeUs();
316     attr.offset = 0;
317     attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
318     OH_AVBuffer_SetBufferAttr(buffer, &attr);
319     result = OH_VideoEncoder_PushInputBuffer(venc_, index);
320     frameCount++;
321     unique_lock<mutex> lock(signal_->inMutex_);
322     signal_->inIdxQueue_.pop();
323     signal_->inBufferQueue_.pop();
324     return res;
325 }
326 
ReadOneFrameYUV420SP(uint8_t * dst)327 uint32_t VEncAPI11FuzzSample::ReadOneFrameYUV420SP(uint8_t *dst)
328 {
329     uint8_t *start = dst;
330     // copy Y
331     for (uint32_t i = 0; i < defaultWidth; i++) {
332         inFile_->read(reinterpret_cast<char *>(dst), defaultWidth);
333         if (!ReturnZeroIfEOS(defaultWidth)) {
334             return 0;
335         }
336         dst += stride_;
337     }
338     // copy UV
339     for (uint32_t i = 0; i < defaultWidth / DOUBLE; i++) {
340         inFile_->read(reinterpret_cast<char *>(dst), defaultWidth);
341         if (!ReturnZeroIfEOS(defaultWidth)) {
342             return 0;
343         }
344         dst += stride_;
345     }
346     return dst - start;
347 }
348 
ReturnZeroIfEOS(uint32_t expectedSize)349 uint32_t VEncAPI11FuzzSample::ReturnZeroIfEOS(uint32_t expectedSize)
350 {
351     if (inFile_->gcount() != (expectedSize)) {
352         cout << "no more data" << endl;
353         return 0;
354     }
355     return 1;
356 }
357 
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)358 uint32_t VEncAPI11FuzzSample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
359 {
360     struct Region region;
361     struct Region::Rect *rect = new Region::Rect();
362     rect->x = 0;
363     rect->y = 0;
364     rect->w = defaultWidth;
365     rect->h = defaultHeight;
366     region.rects = rect;
367     NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
368     int32_t err = OH_NativeBuffer_Unmap(nativeBuffer);
369     if (err != 0) {
370         return 1;
371     }
372     err = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
373     delete rect;
374     if (err != 0) {
375         return 1;
376     }
377     return 0;
378 }
379 
InputFuncSurface()380 void VEncAPI11FuzzSample::InputFuncSurface()
381 {
382     while (isRunning_.load()) {
383         OHNativeWindowBuffer *ohNativeWindowBuffer;
384         int fenceFd = -1;
385         if (nativeWindow == nullptr) {
386             cout << "nativeWindow == nullptr" << endl;
387             isRunning_.store(false);
388             break;
389         }
390         int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
391         if (err != 0) {
392             cout << "RequestBuffer failed, GSError=" << err << endl;
393             isRunning_.store(false);
394             break;
395         }
396         if (fenceFd > 0) {
397             close(fenceFd);
398         }
399         OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
400         void *virAddr = nullptr;
401         OH_NativeBuffer_Config config;
402         OH_NativeBuffer_GetConfig (nativeBuffer, &config);
403         err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
404         if (err != 0) {
405             cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
406             isRunning_.store(false);
407             break;
408         }
409         uint8_t *dst = (uint8_t *)virAddr;
410         if (dst == nullptr) {
411             break;
412         }
413         if (memcpy_s(dst, (config.stride * config.height * THREE) / DOUBLE, fuzzData, fuzzSize) != EOK) {
414             break;
415         }
416         if (frameCount == maxFrameInput) {
417             err = OH_VideoEncoder_NotifyEndOfStream(venc_);
418             if (err != 0) {
419                 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
420                 isRunning_.store(false);
421             }
422             break;
423         }
424         if (FlushSurf(ohNativeWindowBuffer, nativeBuffer)) {
425             break;
426         }
427         usleep(FRAME_INTERVAL);
428         frameCount++;
429     }
430 }
431 
SetEOS(uint32_t index,OH_AVBuffer * buffer)432 void VEncAPI11FuzzSample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
433 {
434     OH_AVCodecBufferAttr attr;
435     attr.pts = 0;
436     attr.size = 0;
437     attr.offset = 0;
438     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
439     OH_AVBuffer_SetBufferAttr(buffer, &attr);
440     int32_t res = OH_VideoEncoder_PushInputBuffer(venc_, index);
441     cout << "OH_VideoEncoder_PushInputBuffer    EOS   res: " << res << endl;
442     unique_lock<mutex> lock(signal_->inMutex_);
443 }
444 
InputFunc()445 void VEncAPI11FuzzSample::InputFunc()
446 {
447     errCount = 0;
448     while (isRunning_.load()) {
449         unique_lock<mutex> lock(signal_->inMutex_);
450         signal_->inCond_.wait(lock, [this]() {
451             if (!isRunning_.load()) {
452                 return true;
453             }
454             return signal_->inIdxQueue_.size() > 0;
455         });
456         if (!isRunning_.load()) {
457             break;
458         }
459         uint32_t index = signal_->inIdxQueue_.front();
460         auto buffer = signal_->inBufferQueue_.front();
461         signal_->inIdxQueue_.pop();
462         signal_->inBufferQueue_.pop();
463         lock.unlock();
464         OH_AVCodecBufferAttr attr;
465         int32_t bufferSize = OH_AVBuffer_GetCapacity(buffer);
466         uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
467         if (fileBuffer == nullptr) {
468             break;
469         }
470         if (memcpy_s(fileBuffer, bufferSize, fuzzData, fuzzSize) != EOK) {
471             cout << "Fatal: memcpy fail" << endl;
472             break;
473         }
474         attr.size = fuzzSize;
475         if (frameCount == maxFrameInput) {
476             SetEOS(index, buffer);
477             break;
478         }
479         attr.pts = GetSystemTimeUs();
480         attr.offset = 0;
481         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
482         OH_AVBuffer_SetBufferAttr(buffer, &attr);
483         OH_VideoEncoder_PushInputBuffer(venc_, index);
484         frameCount++;
485         if (sleepOnFPS) {
486             usleep(FRAME_INTERVAL);
487         }
488     }
489 }
490 
CheckAttrFlag(OH_AVCodecBufferAttr attr)491 int32_t VEncAPI11FuzzSample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
492 {
493     if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
494         cout << "attr.flags == AVCODEC_BUFFER_FLAGS_EOS" << endl;
495         unique_lock<mutex> inLock(signal_->inMutex_);
496         isRunning_.store(false);
497         signal_->inCond_.notify_all();
498         inLock.unlock();
499         return -1;
500     }
501     if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
502         cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
503     }
504     return 0;
505 }
506 
Flush()507 int32_t VEncAPI11FuzzSample::Flush()
508 {
509     unique_lock<mutex> inLock(signal_->inMutex_);
510     clearIntqueue(signal_->inIdxQueue_);
511     signal_->inCond_.notify_all();
512     inLock.unlock();
513     return OH_VideoEncoder_Flush(venc_);
514 }
515 
Reset()516 int32_t VEncAPI11FuzzSample::Reset()
517 {
518     isRunning_.store(false);
519     StopInloop();
520     return OH_VideoEncoder_Reset(venc_);
521 }
522 
Release()523 int32_t VEncAPI11FuzzSample::Release()
524 {
525     int ret = OH_VideoEncoder_Destroy(venc_);
526     venc_ = nullptr;
527     if (signal_ != nullptr) {
528         delete signal_;
529         signal_ = nullptr;
530     }
531     return ret;
532 }
533 
Stop()534 int32_t VEncAPI11FuzzSample::Stop()
535 {
536     StopInloop();
537     return OH_VideoEncoder_Stop(venc_);
538 }
539 
Start()540 int32_t VEncAPI11FuzzSample::Start()
541 {
542     return OH_VideoEncoder_Start(venc_);
543 }
544 
SetParameter(int32_t data)545 int32_t VEncAPI11FuzzSample::SetParameter(int32_t data)
546 {
547     if (venc_) {
548         OH_AVFormat *format = OH_AVFormat_Create();
549         if (format == nullptr) {
550             return AV_ERR_UNKNOWN;
551         }
552         double frameRate = data;
553         (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
554         OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
555         int ret = OH_VideoEncoder_SetParameter(venc_, format);
556         OH_AVFormat_Destroy(format);
557         return ret;
558     }
559     return AV_ERR_UNKNOWN;
560 }