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 }