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 <sys/timeb.h>
18 #include <utility>
19 #include <openssl/rand.h>
20 #include "iconsumer_surface.h"
21 #include "native_buffer_inner.h"
22 #include "VideoencApi11Sample.h"
23 #include "native_avcapability.h"
24 using namespace OHOS;
25 using namespace OHOS::Media;
26 using namespace std;
27 namespace {
28 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
29 constexpr int64_t NANOS_IN_MICRO = 1000L;
30 constexpr uint32_t FRAME_INTERVAL = 16666;
31 constexpr uint8_t RGBA_SIZE = 4;
32 constexpr uint32_t DOUBLE = 2;
33 constexpr uint32_t ZERO = 0;
34 constexpr uint32_t ONE = 1;
35 constexpr uint32_t TWO = 2;
36 constexpr uint32_t THREE = 3;
37 constexpr uint32_t FOUR = 4;
38 constexpr uint32_t FIVE = 5;
39 constexpr uint32_t SIX = 6;
40 sptr<Surface> cs = nullptr;
41 sptr<Surface> ps = nullptr;
42 VEncAPI11Sample* enc_sample = nullptr;
43 int32_t g_picWidth;
44 int32_t g_picHeight;
45 int32_t g_keyWidth;
46 int32_t g_keyHeight;
47 bool g_flagValue = true;
48
clearIntqueue(std::queue<uint32_t> & q)49 void clearIntqueue(std::queue<uint32_t> &q)
50 {
51 std::queue<uint32_t> empty;
52 swap(empty, q);
53 }
54 } // namespace
55
~VEncAPI11Sample()56 VEncAPI11Sample::~VEncAPI11Sample()
57 {
58 if (SURF_INPUT && nativeWindow) {
59 OH_NativeWindow_DestroyNativeWindow(nativeWindow);
60 nativeWindow = nullptr;
61 }
62 Release();
63 }
64
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)65 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
66 {
67 cout << "Error errorCode=" << errorCode << endl;
68 }
69
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)70 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
71 {
72 cout << "Format Changed" << endl;
73 OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_WIDTH, &g_picWidth);
74 OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_HEIGHT, &g_picHeight);
75 OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &g_keyWidth);
76 OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &g_keyHeight);
77 cout << "format info: " << OH_AVFormat_DumpInfo(format) << ", OH_MD_KEY_VIDEO_PIC_WIDTH: " << g_picWidth
78 << ", OH_MD_KEY_VIDEO_PIC_HEIGHT: "<< g_picHeight << ", OH_MD_KEY_WIDTH: " << g_keyWidth
79 << ", OH_MD_KEY_HEIGHT: " << g_keyHeight << endl;
80 }
81
onEncInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)82 static void onEncInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
83 {
84 VEncAPI11Signal *signal = static_cast<VEncAPI11Signal *>(userData);
85 unique_lock<mutex> lock(signal->inMutex_);
86 if (enc_sample == nullptr || enc_sample->roiInfo == nullptr) {
87 cout << "enc_sample or roiInfo is null" << endl;
88 return;
89 }
90 OH_AVFormat *parameter = OH_AVFormat_Create();
91 if (parameter == nullptr) {
92 cout << "Failed to create OH_AVFormat!" << endl;
93 return;
94 }
95 bool ret = OH_AVFormat_SetStringValue(parameter, OH_MD_KEY_VIDEO_ENCODER_ROI_PARAMS, enc_sample->roiInfo);
96 cout << "ret = " << ret << endl;
97 cout << "roiInfo = " << enc_sample->roiInfo << endl;
98 OH_AVBuffer_SetParameter(buffer, parameter);
99 OH_AVFormat_Destroy(parameter);
100 signal->inIdxQueue_.push(index);
101 signal->inBufferQueue_.push(buffer);
102 signal->inCond_.notify_all();
103 }
104
onEncOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)105 static void onEncOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
106 {
107 VEncAPI11Signal *signal = static_cast<VEncAPI11Signal *>(userData);
108 unique_lock<mutex> lock(signal->outMutex_);
109 signal->outIdxQueue_.push(index);
110 signal->outBufferQueue_.push(buffer);
111 signal->outCond_.notify_all();
112 }
113
onEncInputParam(OH_AVCodec * codec,uint32_t index,OH_AVFormat * parameter,void * userData)114 static void onEncInputParam(OH_AVCodec *codec, uint32_t index, OH_AVFormat *parameter, void *userData)
115 {
116 if (enc_sample == nullptr || enc_sample->roiInfo == nullptr) {
117 cout << "enc_sample or roiInfo is null" << endl;
118 return;
119 }
120 OH_AVFormat_SetStringValue(parameter, OH_MD_KEY_VIDEO_ENCODER_ROI_PARAMS, enc_sample->roiInfo);
121 if (!parameter || !userData) {
122 return;
123 }
124 OH_VideoEncoder_PushInputParameter(codec, index);
125 }
126
GetSystemTimeUs()127 int64_t VEncAPI11Sample::GetSystemTimeUs()
128 {
129 struct timespec now;
130 (void)clock_gettime(CLOCK_BOOTTIME, &now);
131 int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
132
133 return nanoTime / NANOS_IN_MICRO;
134 }
135
ConfigureVideoEncoderSqr()136 int32_t VEncAPI11Sample::ConfigureVideoEncoderSqr()
137 {
138 OH_AVFormat *format = OH_AVFormat_Create();
139 if (format == nullptr) {
140 cout << "Fatal: Failed to create format" << endl;
141 return AV_ERR_UNKNOWN;
142 }
143 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
144 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
145 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
146 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
147 if (MODE_ENABLE) {
148 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, DEFAULT_BITRATE_MODE);
149 }
150 if (SETBIRATE) {
151 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
152 }
153 if (QUALITY_ENABLE) {
154 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, DEFAULT_QUALITY);
155 }
156 if (FACTOR_ENABLE) {
157 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_SQR_FACTOR, DEFAULT_SQR_FACTOR);
158 }
159 if (MAXBITE_ENABLE) {
160 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_MAX_BITRATE, DEFAULT_MAX_BITRATE);
161 }
162 if (B_ENABLE) {
163 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_B_FRAME, DEFAULT_BFRAME);
164 }
165 if (MAXBFRAMES_ENABLE) {
166 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_MAX_B_FRAMES, DEFAULT_MAX_B_FRAMES);
167 }
168 if (configMain10) {
169 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, HEVC_PROFILE_MAIN_10);
170 }
171 int ret = OH_VideoEncoder_Configure(venc_, format);
172 OH_AVFormat_Destroy(format);
173 return ret;
174 }
175
GetBframes(OH_AVFormat * format)176 int32_t VEncAPI11Sample::GetBframes(OH_AVFormat *format)
177 {
178 int32_t value = 0;
179 OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_MAX_B_FRAMES, &value);
180 cout << "value: " << value << endl;
181 return value;
182 }
183
ConfigureVideoEncoder()184 int32_t VEncAPI11Sample::ConfigureVideoEncoder()
185 {
186 OH_AVFormat *format = OH_AVFormat_Create();
187 if (format == nullptr) {
188 cout << "Fatal: Failed to create format" << endl;
189 return AV_ERR_UNKNOWN;
190 }
191 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
192 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
193 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
194 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
195 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, DEFAULT_KEY_FRAME_INTERVAL);
196 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, DEFAULT_BITRATE_MODE);
197 if (enablePTSBasedRateControl) {
198 std::cout << "enablePTSBasedRateControl var frame!!!!" << std::endl;
199 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_PTS_BASED_RATECONTROL, 1);
200 }
201 if (FACTOR_ENABLE) {
202 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_SQR_FACTOR, DEFAULT_SQR_FACTOR);
203 }
204 if (MAXBITE_ENABLE) {
205 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_MAX_BITRATE, DEFAULT_MAX_BITRATE);
206 }
207 int ret = OH_VideoEncoder_Configure(venc_, format);
208 OH_AVFormat_Destroy(format);
209 return ret;
210 }
211
SetVideoEncoderCallback()212 int32_t VEncAPI11Sample::SetVideoEncoderCallback()
213 {
214 signal_ = new VEncAPI11Signal();
215 if (signal_ == nullptr) {
216 cout << "Failed to new VEncAPI11Signal" << endl;
217 return AV_ERR_UNKNOWN;
218 }
219 if (SURF_INPUT) {
220 int32_t ret = OH_VideoEncoder_RegisterParameterCallback(venc_, onEncInputParam, static_cast<void *>(this));
221 if (ret != AV_ERR_OK) {
222 return ret;
223 }
224 }
225 cb_.onError = VencError;
226 cb_.onStreamChanged = VencFormatChanged;
227 cb_.onNeedInputBuffer = onEncInputBufferAvailable;
228 cb_.onNewOutputBuffer = onEncOutputBufferAvailable;
229
230 return OH_VideoEncoder_RegisterCallback(venc_, cb_, static_cast<void *>(signal_));
231 }
232
ReleaseInFile()233 void VEncAPI11Sample::ReleaseInFile()
234 {
235 if (inFile_ != nullptr) {
236 if (inFile_->is_open()) {
237 inFile_->close();
238 }
239 inFile_.reset();
240 inFile_ = nullptr;
241 }
242 }
243
StopInloop()244 void VEncAPI11Sample::StopInloop()
245 {
246 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
247 unique_lock<mutex> lock(signal_->inMutex_);
248 clearIntqueue(signal_->inIdxQueue_);
249 isRunning_.store(false);
250 signal_->inCond_.notify_all();
251 lock.unlock();
252
253 inputLoop_->join();
254 inputLoop_ = nullptr;
255 }
256 }
257
CreateSurface()258 int32_t VEncAPI11Sample::CreateSurface()
259 {
260 int32_t ret = 0;
261 ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
262 if (ret != AV_ERR_OK) {
263 cout << "OH_VideoEncoder_GetSurface fail" << endl;
264 return ret;
265 }
266 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
267 if (ret != AV_ERR_OK) {
268 cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
269 return ret;
270 }
271 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
272 if (ret != AV_ERR_OK) {
273 cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
274 return ret;
275 }
276 return AV_ERR_OK;
277 }
278
GetStride()279 void VEncAPI11Sample::GetStride()
280 {
281 OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
282 int32_t inputStride = 0;
283 OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &inputStride);
284 stride_ = inputStride;
285 OH_AVFormat_Destroy(format);
286 }
287
OpenFile()288 int32_t VEncAPI11Sample::OpenFile()
289 {
290 int32_t ret = AV_ERR_OK;
291 inFile_ = make_unique<ifstream>();
292 if (inFile_ == nullptr) {
293 isRunning_.store(false);
294 (void)OH_VideoEncoder_Stop(venc_);
295 return AV_ERR_UNKNOWN;
296 }
297 inFile_->open(INP_DIR, ios::in | ios::binary);
298 cout << "input file: " << INP_DIR << endl;
299 if (!inFile_->is_open()) {
300 ret = OpenFileFail();
301 }
302 return ret;
303 }
304
StartVideoEncoder()305 int32_t VEncAPI11Sample::StartVideoEncoder()
306 {
307 isRunning_.store(true);
308 int32_t ret = 0;
309 if (SURF_INPUT) {
310 ret = CreateSurface();
311 if (ret != AV_ERR_OK) {
312 return ret;
313 }
314 }
315 ret = OH_VideoEncoder_Start(venc_);
316 GetStride();
317 if (ret != AV_ERR_OK) {
318 cout << "Failed to start codec" << endl;
319 isRunning_.store(false);
320 signal_->inCond_.notify_all();
321 signal_->outCond_.notify_all();
322 return ret;
323 }
324 inFile_ = make_unique<ifstream>();
325 if (inFile_ == nullptr) {
326 isRunning_.store(false);
327 (void)OH_VideoEncoder_Stop(venc_);
328 return AV_ERR_UNKNOWN;
329 }
330 readMultiFilesFunc();
331 if (SURF_INPUT) {
332 inputLoop_ = make_unique<thread>(&VEncAPI11Sample::InputFuncSurface, this);
333 } else {
334 inputLoop_ = make_unique<thread>(&VEncAPI11Sample::InputFunc, this);
335 }
336 if (inputLoop_ == nullptr) {
337 isRunning_.store(false);
338 (void)OH_VideoEncoder_Stop(venc_);
339 ReleaseInFile();
340 return AV_ERR_UNKNOWN;
341 }
342 outputLoop_ = make_unique<thread>(&VEncAPI11Sample::OutputFunc, this);
343 if (outputLoop_ == nullptr) {
344 isRunning_.store(false);
345 (void)OH_VideoEncoder_Stop(venc_);
346 ReleaseInFile();
347 StopInloop();
348 Release();
349 return AV_ERR_UNKNOWN;
350 }
351 return AV_ERR_OK;
352 }
353
readMultiFilesFunc()354 void VEncAPI11Sample::readMultiFilesFunc()
355 {
356 if (!readMultiFiles) {
357 inFile_->open(INP_DIR, ios::in | ios::binary);
358 if (!inFile_->is_open()) {
359 OpenFileFail();
360 }
361 }
362 }
363
CreateVideoEncoder(const char * codecName)364 int32_t VEncAPI11Sample::CreateVideoEncoder(const char *codecName)
365 {
366 venc_ = OH_VideoEncoder_CreateByName(codecName);
367 enc_sample = this;
368 return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
369 }
370
WaitForEOS()371 void VEncAPI11Sample::WaitForEOS()
372 {
373 if (inputLoop_)
374 inputLoop_->join();
375 if (outputLoop_)
376 outputLoop_->join();
377 inputLoop_ = nullptr;
378 outputLoop_ = nullptr;
379 }
380
ReturnZeroIfEOS(uint32_t expectedSize)381 uint32_t VEncAPI11Sample::ReturnZeroIfEOS(uint32_t expectedSize)
382 {
383 if (inFile_->gcount() != (expectedSize)) {
384 cout << "no more data" << endl;
385 return 0;
386 }
387 return 1;
388 }
389
ReadOneFrameYUV420SP(uint8_t * dst)390 uint32_t VEncAPI11Sample::ReadOneFrameYUV420SP(uint8_t *dst)
391 {
392 uint8_t *start = dst;
393 // copy Y
394 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
395 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
396 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
397 return 0;
398 dst += stride_;
399 }
400 // copy UV
401 for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
402 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
403 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
404 return 0;
405 dst += stride_;
406 }
407 return dst - start;
408 }
409
ReadOneFrameRGBA8888(uint8_t * dst)410 uint32_t VEncAPI11Sample::ReadOneFrameRGBA8888(uint8_t *dst)
411 {
412 uint8_t *start = dst;
413 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
414 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH * RGBA_SIZE);
415 if (inFile_->eof())
416 return 0;
417 dst += stride_;
418 }
419 return dst - start;
420 }
421
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)422 uint32_t VEncAPI11Sample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
423 {
424 int32_t ret = 0;
425 struct Region region;
426 struct Region::Rect *rect = new Region::Rect();
427 rect->x = 0;
428 rect->y = 0;
429 rect->w = DEFAULT_WIDTH;
430 rect->h = DEFAULT_HEIGHT;
431 region.rects = rect;
432 int64_t tmp = GetSystemTimeUs();
433 if (!enablePTSBasedRateControl) {
434 tmp = GetSystemTimeUs();
435 } else {
436 tmp = timeList[frameIndex];
437 }
438 frameIndex++;
439 NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, tmp);
440 ret = OH_NativeBuffer_Unmap(nativeBuffer);
441 if (ret != 0) {
442 cout << "OH_NativeBuffer_Unmap failed" << endl;
443 delete rect;
444 return ret;
445 }
446 ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
447 delete rect;
448 if (ret != 0) {
449 cout << "FlushBuffer failed" << endl;
450 return ret;
451 }
452 return ret;
453 }
454
InputFuncSurface()455 void VEncAPI11Sample::InputFuncSurface()
456 {
457 int32_t inputframeCount = 0;
458 bool isParamSetSurface = false;
459 while (g_flagValue) {
460 OHNativeWindowBuffer *ohNativeWindowBuffer;
461 OH_NativeBuffer *nativeBuffer = nullptr;
462 uint8_t *dst = nullptr;
463 int err = InitBuffer(ohNativeWindowBuffer, nativeBuffer, dst);
464 if (err == 0) {
465 g_flagValue = false;
466 break;
467 } else if (err == -1) {
468 continue;
469 }
470 if (!ReadOneFrameYUV420SP(dst)) {
471 err = OH_VideoEncoder_NotifyEndOfStream(venc_);
472 if (err != 0) {
473 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
474 }
475 g_flagValue = false;
476 break;
477 }
478 err = FlushSurf(ohNativeWindowBuffer, nativeBuffer);
479 if (err != 0) {
480 g_flagValue = false;
481 break;
482 }
483 if (inputframeCount == FIVE && !isParamSetSurface && enableParameter) {
484 int32_t paramResult = SetParameter();
485 if (paramResult != 0) {
486 cout << "set param failed, error:" << paramResult << endl;
487 errCount = errCount + 1;
488 break;
489 }
490 isParamSetSurface = true;
491 }
492 inputframeCount++;
493 if (sleepOnFPS) {
494 usleep(FRAME_INTERVAL);
495 }
496 }
497 }
498
InitBuffer(OHNativeWindowBuffer * & ohNativeWindowBuffer,OH_NativeBuffer * & nativeBuffer,uint8_t * & dst)499 int32_t VEncAPI11Sample::InitBuffer(OHNativeWindowBuffer *&ohNativeWindowBuffer,
500 OH_NativeBuffer *&nativeBuffer, uint8_t *&dst)
501 {
502 int fenceFd = -1;
503 if (nativeWindow == nullptr) {
504 return 0;
505 }
506 int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
507 if (err != 0) {
508 cout << "RequestBuffer failed, GSError=" << err << endl;
509 return -1;
510 }
511 if (fenceFd > 0) {
512 close(fenceFd);
513 }
514 nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
515 void *virAddr = nullptr;
516 err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
517 if (err != 0) {
518 cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
519 isRunning_.store(false);
520 return 0;
521 }
522 dst = (uint8_t *)virAddr;
523 const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
524 int32_t stride = sbuffer->GetStride();
525 if (dst == nullptr || stride < (int32_t)DEFAULT_WIDTH) {
526 cout << "invalid va or stride=" << stride << endl;
527 err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
528 isRunning_.store(false);
529 return 0;
530 }
531 stride_ = stride;
532 return 1;
533 }
534
OpenFileFail()535 int32_t VEncAPI11Sample::OpenFileFail()
536 {
537 cout << "file open fail" << endl;
538 isRunning_.store(false);
539 (void)OH_VideoEncoder_Stop(venc_);
540 inFile_->close();
541 inFile_.reset();
542 inFile_ = nullptr;
543 return AV_ERR_UNKNOWN;
544 }
545
Flush_buffer()546 void VEncAPI11Sample::Flush_buffer()
547 {
548 unique_lock<mutex> inLock(signal_->inMutex_);
549 clearIntqueue(signal_->inIdxQueue_);
550 std::queue<OH_AVBuffer *> empty;
551 swap(empty, signal_->inBufferQueue_);
552 signal_->inCond_.notify_all();
553 inLock.unlock();
554 unique_lock<mutex> outLock(signal_->outMutex_);
555 clearIntqueue(signal_->outIdxQueue_);
556 signal_->outCond_.notify_all();
557 outLock.unlock();
558 }
559
RepeatStartBeforeEOS()560 void VEncAPI11Sample::RepeatStartBeforeEOS()
561 {
562 if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
563 REPEAT_START_FLUSH_BEFORE_EOS--;
564 OH_VideoEncoder_Flush(venc_);
565 Flush_buffer();
566 OH_VideoEncoder_Start(venc_);
567 }
568
569 if (REPEAT_START_STOP_BEFORE_EOS > 0) {
570 REPEAT_START_STOP_BEFORE_EOS--;
571 OH_VideoEncoder_Stop(venc_);
572 Flush_buffer();
573 OH_VideoEncoder_Start(venc_);
574 }
575 }
576
RandomEOS(uint32_t index)577 bool VEncAPI11Sample::RandomEOS(uint32_t index)
578 {
579 uint32_t random_eos;
580 if (RAND_bytes((unsigned char*)&random_eos, sizeof(random_eos)) != 1) {
581 return false;
582 }
583 const uint32_t MAX_EOS_VALUE = 25;
584 random_eos %= MAX_EOS_VALUE;
585 if (enable_random_eos && random_eos == frameCount) {
586 OH_VideoEncoder_NotifyEndOfStream(venc_);
587 cout << "random eos" << endl;
588 frameCount++;
589 unique_lock<mutex> lock(signal_->inMutex_);
590 signal_->inIdxQueue_.pop();
591 signal_->inBufferQueue_.pop();
592 return true;
593 }
594 return false;
595 }
596
SetEOS(uint32_t index,OH_AVBuffer * buffer)597 void VEncAPI11Sample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
598 {
599 OH_AVCodecBufferAttr attr;
600 attr.pts = 0;
601 attr.size = 0;
602 attr.offset = 0;
603 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
604 OH_AVBuffer_SetBufferAttr(buffer, &attr);
605 int32_t res = OH_VideoEncoder_PushInputBuffer(venc_, index);
606 cout << "OH_VideoEncoder_PushInputBuffer EOS res: " << res << endl;
607 unique_lock<mutex> lock(signal_->inMutex_);
608 signal_->inIdxQueue_.pop();
609 signal_->inBufferQueue_.pop();
610 }
611
PushData(OH_AVBuffer * buffer,uint32_t index,int32_t & result)612 int32_t VEncAPI11Sample::PushData(OH_AVBuffer *buffer, uint32_t index, int32_t &result)
613 {
614 int32_t res = -2;
615 OH_AVCodecBufferAttr attr;
616 uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
617 if (fileBuffer == nullptr) {
618 cout << "Fatal: no memory" << endl;
619 return -1;
620 }
621 int32_t size = OH_AVBuffer_GetCapacity(buffer);
622 if (DEFAULT_PIX_FMT == AV_PIXEL_FORMAT_RGBA) {
623 if (size < DEFAULT_HEIGHT * stride_) {
624 return -1;
625 }
626 attr.size = ReadOneFrameRGBA8888(fileBuffer);
627 } else {
628 if (size < (DEFAULT_HEIGHT * stride_ + (DEFAULT_HEIGHT * stride_ / DOUBLE))) {
629 return -1;
630 }
631 attr.size = ReadOneFrameYUV420SP(fileBuffer);
632 }
633 if (repeatRun && inFile_->eof()) {
634 inFile_->clear();
635 inFile_->seekg(0, ios::beg);
636 encode_count++;
637 cout << "repeat"<< "encode_count:" << encode_count << endl;
638 return -1;
639 }
640 if (inFile_->eof()) {
641 SetEOS(index, buffer);
642 return 0;
643 }
644 if (!enablePTSBasedRateControl) {
645 attr.pts = GetSystemTimeUs();
646 } else {
647 attr.pts = timeList[frameIndex];
648 }
649 frameIndex++;
650 attr.offset = 0;
651 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
652 OH_AVBuffer_SetBufferAttr(buffer, &attr);
653 result = OH_VideoEncoder_PushInputBuffer(venc_, index);
654 frameCount++;
655 unique_lock<mutex> lock(signal_->inMutex_);
656 signal_->inIdxQueue_.pop();
657 signal_->inBufferQueue_.pop();
658 return res;
659 }
660
CheckResult(bool isRandomEosSuccess,int32_t pushResult)661 int32_t VEncAPI11Sample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
662 {
663 if (isRandomEosSuccess) {
664 if (pushResult == 0) {
665 errCount = errCount + 1;
666 cout << "push input after eos should be failed! pushResult:" << pushResult << endl;
667 }
668 return -1;
669 } else if (pushResult != 0) {
670 errCount = errCount + 1;
671 cout << "push input data failed, error:" << pushResult << endl;
672 return -1;
673 }
674 return 0;
675 }
676
InputFunc()677 void VEncAPI11Sample::InputFunc()
678 {
679 errCount = 0;
680 while (g_flagValue) {
681 if (!isRunning_.load()) {
682 break;
683 }
684 RepeatStartBeforeEOS();
685 unique_lock<mutex> lock(signal_->inMutex_);
686 signal_->inCond_.wait(lock, [this]() {
687 if (!isRunning_.load()) {
688 return true;
689 }
690 return signal_->inIdxQueue_.size() > 0;
691 });
692 if (!isRunning_.load()) {
693 break;
694 }
695 uint32_t index = signal_->inIdxQueue_.front();
696 auto buffer = signal_->inBufferQueue_.front();
697 lock.unlock();
698 if (!inFile_->eof()) {
699 bool isRandomEosSuccess = RandomEOS(index);
700 if (isRandomEosSuccess) {
701 continue;
702 }
703 int32_t pushResult = 0;
704 int32_t ret = PushData(buffer, index, pushResult);
705 if (ret == 0) {
706 break;
707 } else if (ret == -1) {
708 continue;
709 }
710 if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
711 break;
712 }
713 if (frameCount_1 == FIVE && !isParamSet && enableParameter) {
714 SetParameter();
715 isParamSet = true;
716 }
717 }
718 if (sleepOnFPS) {
719 usleep(FRAME_INTERVAL);
720 }
721 frameCount_1++;
722 }
723 }
724
SetParameter()725 int32_t VEncAPI11Sample::SetParameter()
726 {
727 int ret = AV_ERR_OK;
728 OH_AVFormat *format = OH_AVFormat_Create();
729 if (format == nullptr) {
730 return AV_ERR_UNKNOWN;
731 }
732 if (venc_ == nullptr) {
733 OH_AVFormat_Destroy(format);
734 return AV_ERR_UNKNOWN;
735 }
736 if (MODE_ENABLE_RUN) {
737 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, DEFAULT_BITRATE_MODE_RUN);
738 }
739 if (IFRAME_ENABLE_RUN) {
740 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_I_FRAME_INTERVAL, DEFAULT_INTERVAL_RUN);
741 }
742 if (SETBIRATE_RUN) {
743 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE_RUN);
744 }
745 if (QUALITY_ENABLE_RUN) {
746 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, DEFAULT_QUALITY_RUN);
747 }
748 if (FACTOR_ENABLE_RUN) {
749 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_SQR_FACTOR, DEFAULT_SQR_FACTOR_RUN);
750 }
751 if (MAXBITE_ENABLE_RUN) {
752 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_MAX_BITRATE, DEFAULT_MAX_BITRATE_RUN);
753 }
754 if (FRAMERATE_ENABLE_RUN) {
755 OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE_RUN);
756 }
757 ret = OH_VideoEncoder_SetParameter(venc_, format);
758 OH_AVFormat_Destroy(format);
759 return ret;
760 }
761
CheckAttrFlag(OH_AVCodecBufferAttr attr)762 int32_t VEncAPI11Sample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
763 {
764 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
765 cout << "attr.flags == AVCODEC_BUFFER_FLAGS_EOS" << endl;
766 unique_lock<mutex> inLock(signal_->inMutex_);
767 isRunning_.store(false);
768 signal_->inCond_.notify_all();
769 signal_->outCond_.notify_all();
770 inLock.unlock();
771 return -1;
772 }
773 if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
774 cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
775 return 0;
776 }
777 outCount = outCount + 1;
778 return 0;
779 }
780
OutputFuncFail()781 void VEncAPI11Sample::OutputFuncFail()
782 {
783 cout << "errCount > 0" << endl;
784 unique_lock<mutex> inLock(signal_->inMutex_);
785 isRunning_.store(false);
786 signal_->inCond_.notify_all();
787 signal_->outCond_.notify_all();
788 inLock.unlock();
789 (void)Stop();
790 Release();
791 }
792
OutputFunc()793 void VEncAPI11Sample::OutputFunc()
794 {
795 FILE *outFile = fopen(OUT_DIR, "wb");
796 while (g_flagValue) {
797 if (!isRunning_.load()) {
798 break;
799 }
800 OH_AVCodecBufferAttr attr;
801 unique_lock<mutex> lock(signal_->outMutex_);
802 signal_->outCond_.wait(lock, [this]() {
803 if (!isRunning_.load()) {
804 return true;
805 }
806 return signal_->outIdxQueue_.size() > 0;
807 });
808 if (!isRunning_.load()) {
809 break;
810 }
811 uint32_t index = signal_->outIdxQueue_.front();
812 OH_AVBuffer *buffer = signal_->outBufferQueue_.front();
813 signal_->outBufferQueue_.pop();
814 signal_->outIdxQueue_.pop();
815 lock.unlock();
816 if (OH_AVBuffer_GetBufferAttr(buffer, &attr) != AV_ERR_OK) {
817 errCount = errCount + 1;
818 }
819 if (CheckAttrFlag(attr) == -1) {
820 break;
821 }
822 int size = attr.size;
823 if (outFile == nullptr) {
824 cout << "dump data fail" << endl;
825 } else {
826 fwrite(OH_AVBuffer_GetAddr(buffer), 1, size, outFile);
827 }
828 if (OH_VideoEncoder_FreeOutputBuffer(venc_, index) != AV_ERR_OK) {
829 errCount = errCount + 1;
830 }
831 if (errCount > 0) {
832 OutputFuncFail();
833 break;
834 }
835 }
836 if (outFile) {
837 (void)fclose(outFile);
838 }
839 }
840
Flush()841 int32_t VEncAPI11Sample::Flush()
842 {
843 unique_lock<mutex> inLock(signal_->inMutex_);
844 clearIntqueue(signal_->inIdxQueue_);
845 signal_->inCond_.notify_all();
846 inLock.unlock();
847 unique_lock<mutex> outLock(signal_->outMutex_);
848 clearIntqueue(signal_->outIdxQueue_);
849 signal_->outCond_.notify_all();
850 outLock.unlock();
851 return OH_VideoEncoder_Flush(venc_);
852 }
853
Reset()854 int32_t VEncAPI11Sample::Reset()
855 {
856 isRunning_.store(false);
857 StopInloop();
858 StopOutloop();
859 ReleaseInFile();
860 return OH_VideoEncoder_Reset(venc_);
861 }
862
Release()863 int32_t VEncAPI11Sample::Release()
864 {
865 int ret = OH_VideoEncoder_Destroy(venc_);
866 venc_ = nullptr;
867 if (signal_ != nullptr) {
868 delete signal_;
869 signal_ = nullptr;
870 }
871 return ret;
872 }
873
Stop()874 int32_t VEncAPI11Sample::Stop()
875 {
876 StopInloop();
877 clearIntqueue(signal_->outIdxQueue_);
878 ReleaseInFile();
879 return OH_VideoEncoder_Stop(venc_);
880 }
881
Start()882 int32_t VEncAPI11Sample::Start()
883 {
884 return OH_VideoEncoder_Start(venc_);
885 }
886
StopOutloop()887 void VEncAPI11Sample::StopOutloop()
888 {
889 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
890 unique_lock<mutex> lock(signal_->outMutex_);
891 clearIntqueue(signal_->outIdxQueue_);
892 signal_->outCond_.notify_all();
893 lock.unlock();
894 }
895 }
896
LoadTimeStampData(std::string filePath,std::string & inputDir,std::string & outputDir,uint32_t & w,uint32_t & h,uint32_t & bitrateMode,uint32_t & bitRate,bool & surfaceMode)897 int32_t VEncAPI11Sample::LoadTimeStampData(std::string filePath, std::string &inputDir,
898 std::string &outputDir, uint32_t &w, uint32_t &h,
899 uint32_t &bitrateMode, uint32_t &bitRate, bool &surfaceMode)
900 {
901 std::ifstream file(filePath);
902 if (!file.is_open()) {
903 return AV_ERR_IO;
904 }
905 std::string temp;
906 int32_t num = 0;
907 while (getline(file, temp)) {
908 if (num == ZERO) {
909 inputDir = temp;
910 num++;
911 continue;
912 }
913 if (num == ONE) {
914 outputDir = temp;
915 num++;
916 continue;
917 }
918 if (num == TWO) {
919 w = stoi(temp);
920 num++;
921 continue;
922 }
923 if (num == THREE) {
924 h = stoi(temp);
925 num++;
926 continue;
927 }
928 if (num == FOUR) {
929 bitrateMode = stoi(temp);
930 num++;
931 continue;
932 }
933 if (num == FIVE) {
934 bitRate = stoi(temp);
935 num++;
936 continue;
937 }
938 if (num == SIX) {
939 surfaceMode = stoi(temp) == 1 ? true : false;
940 num++;
941 continue;
942 }
943 timeList.push_back(stoll(temp));
944 num++;
945 }
946 file.close();
947 return AV_ERR_OK;
948 }