1 /*
2  * Copyright (C) 2023 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 "openssl/crypto.h"
20 #include "openssl/sha.h"
21 #include "native_buffer_inner.h"
22 #include "display_type.h"
23 #include "videoenc_api11_sample.h"
24 #include "native_avcapability.h"
25 using namespace OHOS;
26 using namespace OHOS::Media;
27 using namespace std;
28 namespace {
29 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
30 constexpr int64_t NANOS_IN_MICRO = 1000L;
31 constexpr uint32_t FRAME_INTERVAL = 16666;
32 constexpr uint32_t MAX_PIXEL_FMT = 5;
33 constexpr uint8_t RGBA_SIZE = 4;
34 constexpr uint32_t IDR_FRAME_INTERVAL = 10;
35 constexpr uint32_t DOUBLE = 2;
36 constexpr uint32_t BADPOC = 1000;
37 constexpr uint32_t LTR_INTERVAL = 5;
38 sptr<Surface> cs = nullptr;
39 sptr<Surface> ps = nullptr;
40 OH_AVCapability *cap = nullptr;
41 VEncAPI11Sample *enc_sample = nullptr;
42 constexpr uint8_t FILE_END = -1;
43 constexpr uint8_t LOOP_END = 0;
44 int32_t g_picWidth;
45 int32_t g_picHeight;
46 int32_t g_keyWidth;
47 int32_t g_keyHeight;
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     signal->inIdxQueue_.push(index);
87     signal->inBufferQueue_.push(buffer);
88     signal->inCond_.notify_all();
89 }
90 
onEncOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)91 static void onEncOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
92 {
93     VEncAPI11Signal *signal = static_cast<VEncAPI11Signal *>(userData);
94     unique_lock<mutex> lock(signal->outMutex_);
95     signal->outIdxQueue_.push(index);
96     signal->outBufferQueue_.push(buffer);
97     signal->outCond_.notify_all();
98 }
99 
onEncInputParam(OH_AVCodec * codec,uint32_t index,OH_AVFormat * parameter,void * userData)100 static void onEncInputParam(OH_AVCodec *codec, uint32_t index, OH_AVFormat *parameter, void *userData)
101 {
102     static bool useLtrOnce = false;
103     if (!parameter || !userData) {
104         return;
105     }
106     if (enc_sample->frameCount % enc_sample->ltrParam.ltrInterval == 0) {
107         OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_MARK_LTR, 1);
108     }
109     if (!enc_sample->ltrParam.enableUseLtr) {
110         enc_sample->frameCount++;
111         OH_VideoEncoder_PushInputParameter(codec, index);
112         return;
113     }
114     static int32_t useLtrIndex = 0;
115     if (enc_sample->ltrParam.useLtrIndex == 0) {
116         useLtrIndex = LTR_INTERVAL;
117     } else if (enc_sample->ltrParam.useBadLtr) {
118         useLtrIndex = BADPOC;
119     } else {
120         uint32_t interval = enc_sample->ltrParam.ltrInterval;
121         if (interval > 0 && enc_sample->frameCount > 0 && (enc_sample->frameCount % interval == 0)) {
122             useLtrIndex = enc_sample->frameCount / interval * interval;
123         }
124     }
125     if (enc_sample->frameCount > useLtrIndex) {
126         if (!enc_sample->ltrParam.useLtrOnce) {
127             OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrIndex);
128         } else {
129             if (!useLtrOnce) {
130                 OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrIndex);
131                 useLtrOnce = true;
132             }
133         }
134     } else if (enc_sample->frameCount == useLtrIndex && enc_sample->frameCount > 0) {
135         int32_t sampleInterval = enc_sample->ltrParam.ltrInterval;
136         OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrIndex - sampleInterval);
137     }
138     enc_sample->frameCount++;
139     OH_VideoEncoder_PushInputParameter(codec, index);
140 }
141 
DumpLtrInfo(OH_AVBuffer * buffer)142 void VEncAPI11Sample::DumpLtrInfo(OH_AVBuffer *buffer)
143 {
144     OH_AVFormat *format = OH_AVBuffer_GetParameter(buffer);
145     int32_t isLtr = 0;
146     int32_t framePoc = 0;
147     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PER_FRAME_IS_LTR, &isLtr);
148     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PER_FRAME_POC, &framePoc);
149 }
150 
DumpQPInfo(OH_AVBuffer * buffer)151 void VEncAPI11Sample::DumpQPInfo(OH_AVBuffer *buffer)
152 {
153     OH_AVFormat *format = OH_AVBuffer_GetParameter(buffer);
154     int32_t qp_average = 0;
155     double mse = 0;
156     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_AVERAGE, &qp_average);
157     OH_AVFormat_GetDoubleValue(format, OH_MD_KEY_VIDEO_ENCODER_MSE, &mse);
158 }
159 
DumpInfo(OH_AVCodecBufferAttr attr,OH_AVBuffer * buffer)160 void VEncAPI11Sample::DumpInfo(OH_AVCodecBufferAttr attr, OH_AVBuffer *buffer)
161 {
162     if (enableLTR && attr.flags == AVCODEC_BUFFER_FLAGS_NONE) {
163         DumpLtrInfo(buffer);
164     }
165     if (getQpMse && attr.flags == AVCODEC_BUFFER_FLAGS_NONE) {
166         DumpQPInfo(buffer);
167     }
168 }
169 
GetSystemTimeUs()170 int64_t VEncAPI11Sample::GetSystemTimeUs()
171 {
172     struct timespec now;
173     (void)clock_gettime(CLOCK_BOOTTIME, &now);
174     int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
175 
176     return nanoTime / NANOS_IN_MICRO;
177 }
178 
ConfigureVideoEncoder()179 int32_t VEncAPI11Sample::ConfigureVideoEncoder()
180 {
181     OH_AVFormat *format = OH_AVFormat_Create();
182     if (format == nullptr) {
183         cout << "Fatal: Failed to create format" << endl;
184         return AV_ERR_UNKNOWN;
185     }
186     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
187     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
188     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
189     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
190     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, DEFAULT_KEY_FRAME_INTERVAL);
191     if (isAVCEncoder) {
192         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, avcProfile);
193     } else {
194         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, hevcProfile);
195     }
196     if (configMain10) {
197         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, HEVC_PROFILE_MAIN_10);
198     } else if (configMain) {
199         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, HEVC_PROFILE_MAIN);
200     }
201     if (DEFAULT_BITRATE_MODE == CQ) {
202         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, DEFAULT_QUALITY);
203     } else {
204         (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
205     }
206     if (enableQP) {
207         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MAX, DEFAULT_QP);
208         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MIN, DEFAULT_QP);
209     }
210     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, DEFAULT_BITRATE_MODE);
211     if (enableLTR && (ltrParam.ltrCount >= 0)) {
212         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_LTR_FRAME_COUNT, ltrParam.ltrCount);
213     }
214     if (enableColorSpaceParams) {
215         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, DEFAULT_RANGE_FLAG);
216         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, DEFAULT_COLOR_PRIMARIES);
217         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, DEFAULT_TRANSFER_CHARACTERISTICS);
218         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, DEFAULT_MATRIX_COEFFICIENTS);
219     }
220     int ret = OH_VideoEncoder_Configure(venc_, format);
221     OH_AVFormat_Destroy(format);
222     return ret;
223 }
224 
ConfigureVideoEncoder_Temporal(int32_t temporal_gop_size)225 int32_t VEncAPI11Sample::ConfigureVideoEncoder_Temporal(int32_t temporal_gop_size)
226 {
227     OH_AVFormat *format = OH_AVFormat_Create();
228     if (format == nullptr) {
229         cout << "Fatal: Failed to create format" << endl;
230         return AV_ERR_UNKNOWN;
231     }
232     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
233     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
234     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
235     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
236     (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
237 
238     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, DEFAULT_KEY_FRAME_INTERVAL);
239 
240     if (TEMPORAL_CONFIG) {
241         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporal_gop_size);
242         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE,
243             ADJACENT_REFERENCE);
244     }
245     if (TEMPORAL_ENABLE) {
246         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, 1);
247     } else {
248         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, 0);
249     }
250     if (TEMPORAL_JUMP_MODE) {
251         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, JUMP_REFERENCE);
252     }
253     if (enableLTR && (ltrParam.ltrCount > 0)) {
254         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_LTR_FRAME_COUNT, ltrParam.ltrCount);
255     }
256     if (TEMPORAL_UNIFORMLY) {
257         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporal_gop_size);
258         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE,
259             UNIFORMLY_SCALED_REFERENCE);
260     }
261     int ret = OH_VideoEncoder_Configure(venc_, format);
262     OH_AVFormat_Destroy(format);
263     return ret;
264 }
265 
ConfigureVideoEncoder_fuzz(int32_t data)266 int32_t VEncAPI11Sample::ConfigureVideoEncoder_fuzz(int32_t data)
267 {
268     OH_AVFormat *format = OH_AVFormat_Create();
269     if (format == nullptr) {
270         cout << "Fatal: Failed to create format" << endl;
271         return AV_ERR_UNKNOWN;
272     }
273     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
274     DEFAULT_WIDTH = data;
275     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
276     DEFAULT_HEIGHT = data;
277     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
278     double frameRate = data;
279     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
280 
281     OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, data);
282     OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, data);
283     OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, data);
284     OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, data);
285     OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, data);
286     OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
287     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
288     OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, data);
289 
290     int ret = OH_VideoEncoder_Configure(venc_, format);
291     OH_AVFormat_Destroy(format);
292     return ret;
293 }
294 
SetVideoEncoderCallback()295 int32_t VEncAPI11Sample::SetVideoEncoderCallback()
296 {
297     signal_ = new VEncAPI11Signal();
298     if (signal_ == nullptr) {
299         cout << "Failed to new VEncAPI11Signal" << endl;
300         return AV_ERR_UNKNOWN;
301     }
302     if (SURF_INPUT) {
303         int32_t ret = OH_VideoEncoder_RegisterParameterCallback(venc_, onEncInputParam, static_cast<void *>(this));
304         if (ret != AV_ERR_OK) {
305             return ret;
306         }
307     }
308     cb_.onError = VencError;
309     cb_.onStreamChanged = VencFormatChanged;
310     cb_.onNeedInputBuffer = onEncInputBufferAvailable;
311     cb_.onNewOutputBuffer = onEncOutputBufferAvailable;
312 
313     return OH_VideoEncoder_RegisterCallback(venc_, cb_, static_cast<void *>(signal_));
314 }
315 
state_EOS()316 int32_t VEncAPI11Sample::state_EOS()
317 {
318     unique_lock<mutex> lock(signal_->inMutex_);
319     signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
320     uint32_t index = signal_->inIdxQueue_.front();
321     OH_AVBuffer *buffer = signal_->inBufferQueue_.front();
322     signal_->inIdxQueue_.pop();
323     signal_->inBufferQueue_.pop();
324     lock.unlock();
325     OH_AVCodecBufferAttr attr;
326     attr.pts = 0;
327     attr.size = 0;
328     attr.offset = 0;
329     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
330     OH_AVBuffer_SetBufferAttr(buffer, &attr);
331     return OH_VideoEncoder_PushInputBuffer(venc_, index);
332 }
ReleaseInFile()333 void VEncAPI11Sample::ReleaseInFile()
334 {
335     if (inFile_ != nullptr) {
336         if (inFile_->is_open()) {
337             inFile_->close();
338         }
339         inFile_.reset();
340         inFile_ = nullptr;
341     }
342 }
343 
StopInloop()344 void VEncAPI11Sample::StopInloop()
345 {
346     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
347         unique_lock<mutex> lock(signal_->inMutex_);
348         clearIntqueue(signal_->inIdxQueue_);
349         isRunning_.store(false);
350         signal_->inCond_.notify_all();
351         lock.unlock();
352 
353         inputLoop_->join();
354         inputLoop_ = nullptr;
355     }
356 }
357 
testApi()358 void VEncAPI11Sample::testApi()
359 {
360     OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
361     OH_VideoEncoder_Prepare(venc_);
362     OH_VideoEncoder_GetInputDescription(venc_);
363     OH_VideoEncoder_Start(venc_);
364     OH_AVFormat *format = OH_AVFormat_Create();
365     OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
366     OH_VideoEncoder_SetParameter(venc_, format);
367     OH_VideoEncoder_NotifyEndOfStream(venc_);
368     OH_VideoEncoder_GetOutputDescription(venc_);
369     OH_AVFormat_Destroy(format);
370     OH_VideoEncoder_Flush(venc_);
371     bool isValid = false;
372     OH_VideoEncoder_IsValid(venc_, &isValid);
373     OH_VideoEncoder_Stop(venc_);
374     OH_VideoEncoder_Reset(venc_);
375 }
376 
CreateSurface()377 int32_t VEncAPI11Sample::CreateSurface()
378 {
379     int32_t ret = 0;
380     ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
381     if (ret != AV_ERR_OK) {
382         cout << "OH_VideoEncoder_GetSurface fail" << endl;
383         return ret;
384     }
385     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
386     if (ret != AV_ERR_OK) {
387         cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
388         return ret;
389     }
390     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
391     if (ret != AV_ERR_OK) {
392         cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
393         return ret;
394     }
395     return AV_ERR_OK;
396 }
397 
GetStride()398 void VEncAPI11Sample::GetStride()
399 {
400     OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
401     int32_t inputStride = 0;
402     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &inputStride);
403     stride_ = inputStride;
404     OH_AVFormat_Destroy(format);
405 }
406 
OpenFile()407 int32_t VEncAPI11Sample::OpenFile()
408 {
409     int32_t ret = AV_ERR_OK;
410     inFile_ = make_unique<ifstream>();
411     if (inFile_ == nullptr) {
412         isRunning_.store(false);
413         (void)OH_VideoEncoder_Stop(venc_);
414         return AV_ERR_UNKNOWN;
415     }
416     inFile_->open(INP_DIR, ios::in | ios::binary);
417     if (!inFile_->is_open()) {
418         ret = OpenFileFail();
419     }
420     return ret;
421 }
422 
StartVideoEncoder()423 int32_t VEncAPI11Sample::StartVideoEncoder()
424 {
425     isRunning_.store(true);
426     int32_t ret = 0;
427     if (SURF_INPUT) {
428         ret = CreateSurface();
429         if (ret != AV_ERR_OK) {
430             return ret;
431         }
432     }
433     ret = OH_VideoEncoder_Start(venc_);
434     GetStride();
435     if (ret != AV_ERR_OK) {
436         cout << "Failed to start codec" << endl;
437         isRunning_.store(false);
438         signal_->inCond_.notify_all();
439         signal_->outCond_.notify_all();
440         return ret;
441     }
442     inFile_ = make_unique<ifstream>();
443     if (inFile_ == nullptr) {
444         isRunning_.store(false);
445         (void)OH_VideoEncoder_Stop(venc_);
446         return AV_ERR_UNKNOWN;
447     }
448     readMultiFilesFunc();
449     if (SURF_INPUT) {
450         inputLoop_ = make_unique<thread>(&VEncAPI11Sample::InputFuncSurface, this);
451     } else {
452         inputLoop_ = make_unique<thread>(&VEncAPI11Sample::InputFunc, this);
453     }
454     if (inputLoop_ == nullptr) {
455         isRunning_.store(false);
456         (void)OH_VideoEncoder_Stop(venc_);
457         ReleaseInFile();
458         return AV_ERR_UNKNOWN;
459     }
460     outputLoop_ = make_unique<thread>(&VEncAPI11Sample::OutputFunc, this);
461     if (outputLoop_ == nullptr) {
462         isRunning_.store(false);
463         (void)OH_VideoEncoder_Stop(venc_);
464         ReleaseInFile();
465         StopInloop();
466         Release();
467         return AV_ERR_UNKNOWN;
468     }
469     return AV_ERR_OK;
470 }
471 
readMultiFilesFunc()472 void VEncAPI11Sample::readMultiFilesFunc()
473 {
474     if (!readMultiFiles) {
475         inFile_->open(INP_DIR, ios::in | ios::binary);
476         if (!inFile_->is_open()) {
477             OpenFileFail();
478         }
479     }
480 }
481 
CreateVideoEncoder(const char * codecName)482 int32_t VEncAPI11Sample::CreateVideoEncoder(const char *codecName)
483 {
484     cap = OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true, HARDWARE);
485     const char *tmpCodecName = OH_AVCapability_GetName(cap);
486     if (!strcmp(codecName, tmpCodecName)) {
487         isAVCEncoder = true;
488     } else {
489         isAVCEncoder = false;
490     }
491     venc_ = OH_VideoEncoder_CreateByName(codecName);
492     enc_sample = this;
493     return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
494 }
495 
WaitForEOS()496 void VEncAPI11Sample::WaitForEOS()
497 {
498     if (inputLoop_)
499         inputLoop_->join();
500     if (outputLoop_)
501         outputLoop_->join();
502     inputLoop_ = nullptr;
503     outputLoop_ = nullptr;
504 }
505 
ReturnZeroIfEOS(uint32_t expectedSize)506 uint32_t VEncAPI11Sample::ReturnZeroIfEOS(uint32_t expectedSize)
507 {
508     if (inFile_->gcount() != (expectedSize)) {
509         cout << "no more data" << endl;
510         return 0;
511     }
512     return 1;
513 }
514 
ReadOneFrameYUV420SP(uint8_t * dst)515 uint32_t VEncAPI11Sample::ReadOneFrameYUV420SP(uint8_t *dst)
516 {
517     uint8_t *start = dst;
518     // copy Y
519     for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
520         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
521         if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
522             return 0;
523         dst += stride_;
524     }
525     // copy UV
526     for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
527         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
528         if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
529             return 0;
530         dst += stride_;
531     }
532     return dst - start;
533 }
534 
ReadOneFrameYUVP010(uint8_t * dst)535 uint32_t VEncAPI11Sample::ReadOneFrameYUVP010(uint8_t *dst)
536 {
537     uint8_t *start = dst;
538     int32_t num = 2;
539     // copy Y
540     for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
541         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH*num);
542         if (!ReturnZeroIfEOS(DEFAULT_WIDTH*num))
543             return 0;
544         dst += stride_;
545     }
546     // copy UV
547     for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
548         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH*num);
549         if (!ReturnZeroIfEOS(DEFAULT_WIDTH*num))
550             return 0;
551         dst += stride_;
552     }
553     return dst - start;
554 }
555 
ReadOneFrameRGBA8888(uint8_t * dst)556 uint32_t VEncAPI11Sample::ReadOneFrameRGBA8888(uint8_t *dst)
557 {
558     uint8_t *start = dst;
559     for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
560         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH * RGBA_SIZE);
561         if (inFile_->eof())
562             return 0;
563         dst += stride_;
564     }
565     return dst - start;
566 }
567 
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)568 uint32_t VEncAPI11Sample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
569 {
570     int32_t ret = 0;
571     struct Region region;
572     struct Region::Rect *rect = new Region::Rect();
573     rect->x = 0;
574     rect->y = 0;
575     rect->w = DEFAULT_WIDTH;
576     rect->h = DEFAULT_HEIGHT;
577     region.rects = rect;
578     NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
579     ret = OH_NativeBuffer_Unmap(nativeBuffer);
580     if (ret != 0) {
581         cout << "OH_NativeBuffer_Unmap failed" << endl;
582         delete rect;
583         return ret;
584     }
585     ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
586     delete rect;
587     if (ret != 0) {
588         cout << "FlushBuffer failed" << endl;
589         return ret;
590     }
591     return ret;
592 }
593 
InputFuncSurface()594 void VEncAPI11Sample::InputFuncSurface()
595 {
596     int32_t readFileIndex = 0;
597     while (true) {
598         OHNativeWindowBuffer *ohNativeWindowBuffer;
599         OH_NativeBuffer *nativeBuffer = nullptr;
600         uint8_t *dst = nullptr;
601         int err = InitBuffer(ohNativeWindowBuffer, nativeBuffer, dst);
602         if (err == 0) {
603             break;
604         } else if (err == -1) {
605             continue;
606         }
607         if (readMultiFiles) {
608             err = ReadOneFrameFromList(dst, readFileIndex);
609             if (err == LOOP_END) {
610                 break;
611             } else if (err == FILE_END) {
612                 OH_NativeWindow_NativeWindowAbortBuffer(nativeWindow, ohNativeWindowBuffer);
613                 cout << "OH_NativeWindow_NativeWindowAbortBuffer" << endl;
614                 continue;
615             }
616         } else if (!ReadOneFrameYUV420SP(dst)) {
617             err = OH_VideoEncoder_NotifyEndOfStream(venc_);
618             if (err != 0) {
619                 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
620             }
621             break;
622         }
623         err = FlushSurf(ohNativeWindowBuffer, nativeBuffer);
624         if (err != 0) {
625             break;
626         }
627         usleep(FRAME_INTERVAL);
628     }
629 }
630 
InitBuffer(OHNativeWindowBuffer * & ohNativeWindowBuffer,OH_NativeBuffer * & nativeBuffer,uint8_t * & dst)631 int32_t VEncAPI11Sample::InitBuffer(OHNativeWindowBuffer *&ohNativeWindowBuffer,
632     OH_NativeBuffer *&nativeBuffer, uint8_t *&dst)
633 {
634     int fenceFd = -1;
635     if (nativeWindow == nullptr) {
636         return 0;
637     }
638     int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
639     if (err != 0) {
640         cout << "RequestBuffer failed, GSError=" << err << endl;
641         return -1;
642     }
643     if (fenceFd > 0) {
644         close(fenceFd);
645     }
646     nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
647     void *virAddr = nullptr;
648     err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
649     if (err != 0) {
650         cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
651         isRunning_.store(false);
652         return 0;
653     }
654     dst = (uint8_t *)virAddr;
655     const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
656     int32_t stride = sbuffer->GetStride();
657     if (dst == nullptr || stride < (int32_t)DEFAULT_WIDTH) {
658         cout << "invalid va or stride=" << stride << endl;
659         err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
660         isRunning_.store(false);
661         return 0;
662     }
663     stride_ = stride;
664     return 1;
665 }
666 
ReadOneFrameFromList(uint8_t * dst,int32_t & index)667 uint32_t VEncAPI11Sample::ReadOneFrameFromList(uint8_t *dst, int32_t &index)
668 {
669     int32_t ret = 0;
670     if (index >= fileInfos.size()) {
671         ret = OH_VideoEncoder_NotifyEndOfStream(venc_);
672         if (ret != 0) {
673             cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
674         }
675         return LOOP_END;
676     }
677     if (!inFile_->is_open()) {
678         inFile_->open(fileInfos[index].fileDir);
679         if (!inFile_->is_open()) {
680             return OpenFileFail();
681         }
682         DEFAULT_WIDTH = fileInfos[index].width;
683         DEFAULT_HEIGHT = fileInfos[index].height;
684         if (setFormatRbgx) {
685             ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_RGBX_8888);
686         } else if (setFormat8Bit) {
687             ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
688         } else if (setFormat10Bit) {
689             ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_P010);
690         } else {
691             ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, fileInfos[index].format);
692         }
693         if (ret != AV_ERR_OK) {
694             return ret;
695         }
696         ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
697         if (ret != AV_ERR_OK) {
698             return ret;
699         }
700         cout << fileInfos[index].fileDir << endl;
701         cout << "set width:" << fileInfos[index].width << "height: " << fileInfos[index].height << endl;
702         return FILE_END;
703     }
704     ret = ReadOneFrameByType(dst, fileInfos[index].format);
705     if (!ret) {
706         if (inFile_->is_open()) {
707             inFile_->close();
708         }
709         index++;
710         if (index >= fileInfos.size()) {
711             OH_VideoEncoder_NotifyEndOfStream(venc_);
712             return LOOP_END;
713         }
714         return FILE_END;
715     }
716     return ret;
717 }
718 
ReadOneFrameByType(uint8_t * dst,OH_NativeBuffer_Format format)719 uint32_t VEncAPI11Sample::ReadOneFrameByType(uint8_t *dst, OH_NativeBuffer_Format format)
720 {
721     if (format == NATIVEBUFFER_PIXEL_FMT_RGBA_8888) {
722         return ReadOneFrameRGBA8888(dst);
723     } else if (format == NATIVEBUFFER_PIXEL_FMT_YCBCR_420_SP || format == NATIVEBUFFER_PIXEL_FMT_YCRCB_420_SP) {
724         return ReadOneFrameYUV420SP(dst);
725     } else if (format == NATIVEBUFFER_PIXEL_FMT_YCBCR_P010) {
726         return ReadOneFrameYUVP010(dst);
727     } else {
728         cout << "error fileType" << endl;
729         return 0;
730     }
731 }
732 
OpenFileFail()733 int32_t VEncAPI11Sample::OpenFileFail()
734 {
735     cout << "file open fail" << endl;
736     isRunning_.store(false);
737     (void)OH_VideoEncoder_Stop(venc_);
738     inFile_->close();
739     inFile_.reset();
740     inFile_ = nullptr;
741     return AV_ERR_UNKNOWN;
742 }
743 
Flush_buffer()744 void VEncAPI11Sample::Flush_buffer()
745 {
746     unique_lock<mutex> inLock(signal_->inMutex_);
747     clearIntqueue(signal_->inIdxQueue_);
748     std::queue<OH_AVBuffer *> empty;
749     swap(empty, signal_->inBufferQueue_);
750     signal_->inCond_.notify_all();
751     inLock.unlock();
752     unique_lock<mutex> outLock(signal_->outMutex_);
753     clearIntqueue(signal_->outIdxQueue_);
754     signal_->outCond_.notify_all();
755     outLock.unlock();
756 }
757 
RepeatStartBeforeEOS()758 void VEncAPI11Sample::RepeatStartBeforeEOS()
759 {
760     if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
761         REPEAT_START_FLUSH_BEFORE_EOS--;
762         OH_VideoEncoder_Flush(venc_);
763         Flush_buffer();
764         OH_VideoEncoder_Start(venc_);
765     }
766 
767     if (REPEAT_START_STOP_BEFORE_EOS > 0) {
768         REPEAT_START_STOP_BEFORE_EOS--;
769         OH_VideoEncoder_Stop(venc_);
770         Flush_buffer();
771         OH_VideoEncoder_Start(venc_);
772     }
773 }
774 
RandomEOS(uint32_t index)775 bool VEncAPI11Sample::RandomEOS(uint32_t index)
776 {
777     uint32_t random_eos = rand() % 25;
778     if (enable_random_eos && random_eos == frameCount) {
779         OH_VideoEncoder_NotifyEndOfStream(venc_);
780         cout << "random eos" << endl;
781         frameCount++;
782         unique_lock<mutex> lock(signal_->inMutex_);
783         signal_->inIdxQueue_.pop();
784         signal_->inBufferQueue_.pop();
785         return true;
786     }
787     return false;
788 }
789 
AutoSwitchParam()790 void VEncAPI11Sample::AutoSwitchParam()
791 {
792     int64_t currentBitrate = DEFAULT_BITRATE;
793     double currentFrameRate = DEFAULT_FRAME_RATE;
794     int32_t currentQP = DEFAULT_QP;
795     if (frameCount == switchParamsTimeSec * (int32_t)DEFAULT_FRAME_RATE) {
796         OH_AVFormat *format = OH_AVFormat_Create();
797         if (needResetBitrate) {
798             currentBitrate = DEFAULT_BITRATE >> 1;
799             (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, currentBitrate);
800         }
801         if (needResetFrameRate) {
802             currentFrameRate = DEFAULT_FRAME_RATE * DOUBLE;
803             (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, currentFrameRate);
804         }
805         if (needResetQP) {
806             currentQP = DEFAULT_QP;
807             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MAX, currentQP);
808             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MIN, currentQP);
809         }
810         SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
811         OH_AVFormat_Destroy(format);
812     }
813     if (frameCount == switchParamsTimeSec * (int32_t)DEFAULT_FRAME_RATE * DOUBLE) {
814         OH_AVFormat *format = OH_AVFormat_Create();
815         if (needResetBitrate) {
816             currentBitrate = DEFAULT_BITRATE << 1;
817             cout<<"switch bitrate "<< currentBitrate;
818             (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, currentBitrate);
819         }
820         if (needResetFrameRate) {
821             currentFrameRate = DEFAULT_FRAME_RATE / DOUBLE;
822             cout<< "switch framerate" << currentFrameRate << endl;
823             (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, currentFrameRate);
824         }
825         if (needResetQP) {
826             currentQP = DEFAULT_QP * DOUBLE;
827             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MAX, currentQP);
828             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MIN, currentQP);
829         }
830         SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
831         OH_AVFormat_Destroy(format);
832     }
833 }
834 
SetEOS(uint32_t index,OH_AVBuffer * buffer)835 void VEncAPI11Sample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
836 {
837     OH_AVCodecBufferAttr attr;
838     attr.pts = 0;
839     attr.size = 0;
840     attr.offset = 0;
841     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
842     OH_AVBuffer_SetBufferAttr(buffer, &attr);
843     int32_t res = OH_VideoEncoder_PushInputBuffer(venc_, index);
844     cout << "OH_VideoEncoder_PushInputBuffer    EOS   res: " << res << endl;
845     unique_lock<mutex> lock(signal_->inMutex_);
846     signal_->inIdxQueue_.pop();
847     signal_->inBufferQueue_.pop();
848 }
849 
SetForceIDR()850 void VEncAPI11Sample::SetForceIDR()
851 {
852     OH_AVFormat *format = OH_AVFormat_Create();
853     OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
854     OH_VideoEncoder_SetParameter(venc_, format);
855     OH_AVFormat_Destroy(format);
856 }
857 
SetLTRParameter(OH_AVBuffer * buffer)858 void VEncAPI11Sample::SetLTRParameter(OH_AVBuffer *buffer)
859 {
860     if (!ltrParam.enableUseLtr) {
861         return;
862     }
863     OH_AVFormat *format = OH_AVFormat_Create();
864     if (frameCount % ltrParam.ltrInterval == 0) {
865         OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_MARK_LTR, 1);
866     }
867     if (!ltrParam.enableUseLtr) {
868         OH_AVBuffer_SetParameter(buffer, format) == AV_ERR_OK ? (0) : (errCount++);
869         OH_AVFormat_Destroy(format);
870         return;
871     }
872     static int32_t useLtrIndex = 0;
873     if (ltrParam.useLtrIndex == 0) {
874         useLtrIndex = LTR_INTERVAL;
875     } else if (ltrParam.useBadLtr) {
876         useLtrIndex = BADPOC;
877     } else {
878         uint32_t interval = ltrParam.ltrInterval;
879         if (interval > 0 && frameCount > 0 && (frameCount % interval == 0)) {
880             useLtrIndex = frameCount / interval * interval;
881         }
882     }
883     if (frameCount > useLtrIndex) {
884         if (!ltrParam.useLtrOnce) {
885             OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrIndex);
886         } else {
887             OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrIndex);
888             ltrParam.useLtrOnce = true;
889         }
890     } else if (frameCount == useLtrIndex && frameCount > 0) {
891         OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrIndex - ltrParam.ltrInterval);
892     }
893     OH_AVBuffer_SetParameter(buffer, format) == AV_ERR_OK ? (0) : (errCount++);
894     OH_AVFormat_Destroy(format);
895 }
896 
SetBufferParameter(OH_AVBuffer * buffer)897 void VEncAPI11Sample::SetBufferParameter(OH_AVBuffer *buffer)
898 {
899     int32_t currentQP = DEFAULT_QP;
900     if (!enableAutoSwitchBufferParam) {
901         return;
902     }
903     if (frameCount == switchParamsTimeSec * (int32_t)DEFAULT_FRAME_RATE) {
904         OH_AVFormat *format = OH_AVFormat_Create();
905         if (needResetQP) {
906             currentQP = DEFAULT_QP;
907             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MAX, currentQP);
908             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MIN, currentQP);
909         }
910         OH_AVBuffer_SetParameter(buffer, format) == AV_ERR_OK ? (0) : (errCount++);
911         OH_AVFormat_Destroy(format);
912     }
913     if (frameCount == switchParamsTimeSec * (int32_t)DEFAULT_FRAME_RATE * DOUBLE) {
914         OH_AVFormat *format = OH_AVFormat_Create();
915         if (needResetQP) {
916             currentQP = DEFAULT_QP * DOUBLE;
917             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MAX, currentQP);
918             (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_QP_MIN, currentQP);
919         }
920         OH_AVBuffer_SetParameter(buffer, format) == AV_ERR_OK ? (0) : (errCount++);
921         OH_AVFormat_Destroy(format);
922     }
923 }
924 
PushData(OH_AVBuffer * buffer,uint32_t index,int32_t & result)925 int32_t VEncAPI11Sample::PushData(OH_AVBuffer *buffer, uint32_t index, int32_t &result)
926 {
927     int32_t res = -2;
928     OH_AVCodecBufferAttr attr;
929     uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
930     if (fileBuffer == nullptr) {
931         cout << "Fatal: no memory" << endl;
932         return -1;
933     }
934     int32_t size = OH_AVBuffer_GetCapacity(buffer);
935     if (DEFAULT_PIX_FMT == AV_PIXEL_FORMAT_RGBA) {
936         if (size < DEFAULT_HEIGHT * stride_) {
937             return -1;
938         }
939         attr.size = ReadOneFrameRGBA8888(fileBuffer);
940     } else {
941         if (size < (DEFAULT_HEIGHT * stride_ + (DEFAULT_HEIGHT * stride_ / DOUBLE))) {
942             return -1;
943         }
944         attr.size = ReadOneFrameYUV420SP(fileBuffer);
945     }
946     if (repeatRun && inFile_->eof()) {
947         inFile_->clear();
948         inFile_->seekg(0, ios::beg);
949         encode_count++;
950         cout << "repeat"<< "   encode_count:" << encode_count << endl;
951         return -1;
952     }
953     if (inFile_->eof()) {
954         SetEOS(index, buffer);
955         return 0;
956     }
957     attr.pts = GetSystemTimeUs();
958     attr.offset = 0;
959     attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
960     if (enableForceIDR && (frameCount % IDR_FRAME_INTERVAL == 0)) {
961         SetForceIDR();
962     }
963     OH_AVBuffer_SetBufferAttr(buffer, &attr);
964     SetBufferParameter(buffer);
965     SetLTRParameter(buffer);
966     result = OH_VideoEncoder_PushInputBuffer(venc_, index);
967     frameCount++;
968     unique_lock<mutex> lock(signal_->inMutex_);
969     signal_->inIdxQueue_.pop();
970     signal_->inBufferQueue_.pop();
971     return res;
972 }
973 
CheckResult(bool isRandomEosSuccess,int32_t pushResult)974 int32_t VEncAPI11Sample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
975 {
976     if (isRandomEosSuccess) {
977         if (pushResult == 0) {
978             errCount = errCount + 1;
979             cout << "push input after eos should be failed!  pushResult:" << pushResult << endl;
980         }
981         return -1;
982     } else if (pushResult != 0) {
983         errCount = errCount + 1;
984         cout << "push input data failed, error:" << pushResult << endl;
985         return -1;
986     }
987     return 0;
988 }
989 
InputFunc()990 void VEncAPI11Sample::InputFunc()
991 {
992     errCount = 0;
993     while (true) {
994         if (!isRunning_.load()) {
995             break;
996         }
997         RepeatStartBeforeEOS();
998         unique_lock<mutex> lock(signal_->inMutex_);
999         signal_->inCond_.wait(lock, [this]() {
1000             if (!isRunning_.load()) {
1001                 return true;
1002             }
1003             return signal_->inIdxQueue_.size() > 0;
1004         });
1005         if (!isRunning_.load()) {
1006             break;
1007         }
1008         uint32_t index = signal_->inIdxQueue_.front();
1009         auto buffer = signal_->inBufferQueue_.front();
1010         lock.unlock();
1011         if (!inFile_->eof()) {
1012             bool isRandomEosSuccess = RandomEOS(index);
1013             if (isRandomEosSuccess) {
1014                 continue;
1015             }
1016             int32_t pushResult = 0;
1017             int32_t ret = PushData(buffer, index, pushResult);
1018             if (ret == 0) {
1019                 break;
1020             } else if (ret == -1) {
1021                 continue;
1022             }
1023             if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
1024                 break;
1025             }
1026             if (enableAutoSwitchParam) {
1027                 AutoSwitchParam();
1028             }
1029         }
1030         if (sleepOnFPS) {
1031             usleep(FRAME_INTERVAL);
1032         }
1033     }
1034 }
1035 
CheckAttrFlag(OH_AVCodecBufferAttr attr)1036 int32_t VEncAPI11Sample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
1037 {
1038     if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
1039         cout << "attr.flags == AVCODEC_BUFFER_FLAGS_EOS" << endl;
1040         unique_lock<mutex> inLock(signal_->inMutex_);
1041         isRunning_.store(false);
1042         signal_->inCond_.notify_all();
1043         signal_->outCond_.notify_all();
1044         inLock.unlock();
1045         return -1;
1046     }
1047     if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
1048         cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
1049         return 0;
1050     }
1051     outCount = outCount + 1;
1052     return 0;
1053 }
1054 
OutputFuncFail()1055 void VEncAPI11Sample::OutputFuncFail()
1056 {
1057     cout << "errCount > 0" << endl;
1058     unique_lock<mutex> inLock(signal_->inMutex_);
1059     isRunning_.store(false);
1060     signal_->inCond_.notify_all();
1061     signal_->outCond_.notify_all();
1062     inLock.unlock();
1063     (void)Stop();
1064     Release();
1065 }
1066 
OutputFunc()1067 void VEncAPI11Sample::OutputFunc()
1068 {
1069     FILE *outFile = fopen(OUT_DIR, "wb");
1070     while (true) {
1071         if (!isRunning_.load()) {
1072             break;
1073         }
1074         OH_AVCodecBufferAttr attr;
1075         unique_lock<mutex> lock(signal_->outMutex_);
1076         signal_->outCond_.wait(lock, [this]() {
1077             if (!isRunning_.load()) {
1078                 return true;
1079             }
1080             return signal_->outIdxQueue_.size() > 0;
1081         });
1082         if (!isRunning_.load()) {
1083             break;
1084         }
1085         uint32_t index = signal_->outIdxQueue_.front();
1086         OH_AVBuffer *buffer = signal_->outBufferQueue_.front();
1087         signal_->outBufferQueue_.pop();
1088         signal_->outIdxQueue_.pop();
1089         lock.unlock();
1090         DumpInfo(attr, buffer);
1091         if (OH_AVBuffer_GetBufferAttr(buffer, &attr) != AV_ERR_OK) {
1092             errCount = errCount + 1;
1093         }
1094         if (CheckAttrFlag(attr) == -1) {
1095             break;
1096         }
1097         int size = attr.size;
1098         if (outFile == nullptr) {
1099             cout << "dump data fail" << endl;
1100         } else {
1101             fwrite(OH_AVBuffer_GetAddr(buffer), 1, size, outFile);
1102         }
1103         if (OH_VideoEncoder_FreeOutputBuffer(venc_, index) != AV_ERR_OK) {
1104             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
1105             errCount = errCount + 1;
1106         }
1107         if (errCount > 0) {
1108             OutputFuncFail();
1109             break;
1110         }
1111     }
1112     if (outFile) {
1113         (void)fclose(outFile);
1114     }
1115 }
1116 
Flush()1117 int32_t VEncAPI11Sample::Flush()
1118 {
1119     unique_lock<mutex> inLock(signal_->inMutex_);
1120     clearIntqueue(signal_->inIdxQueue_);
1121     signal_->inCond_.notify_all();
1122     inLock.unlock();
1123     unique_lock<mutex> outLock(signal_->outMutex_);
1124     clearIntqueue(signal_->outIdxQueue_);
1125     signal_->outCond_.notify_all();
1126     outLock.unlock();
1127     return OH_VideoEncoder_Flush(venc_);
1128 }
1129 
Reset()1130 int32_t VEncAPI11Sample::Reset()
1131 {
1132     isRunning_.store(false);
1133     StopInloop();
1134     StopOutloop();
1135     ReleaseInFile();
1136     return OH_VideoEncoder_Reset(venc_);
1137 }
1138 
Release()1139 int32_t VEncAPI11Sample::Release()
1140 {
1141     int ret = OH_VideoEncoder_Destroy(venc_);
1142     venc_ = nullptr;
1143     if (signal_ != nullptr) {
1144         delete signal_;
1145         signal_ = nullptr;
1146     }
1147     return ret;
1148 }
1149 
Stop()1150 int32_t VEncAPI11Sample::Stop()
1151 {
1152     StopInloop();
1153     clearIntqueue(signal_->outIdxQueue_);
1154     ReleaseInFile();
1155     return OH_VideoEncoder_Stop(venc_);
1156 }
1157 
Start()1158 int32_t VEncAPI11Sample::Start()
1159 {
1160     return OH_VideoEncoder_Start(venc_);
1161 }
1162 
StopOutloop()1163 void VEncAPI11Sample::StopOutloop()
1164 {
1165     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
1166         unique_lock<mutex> lock(signal_->outMutex_);
1167         clearIntqueue(signal_->outIdxQueue_);
1168         signal_->outCond_.notify_all();
1169         lock.unlock();
1170     }
1171 }
1172 
SetParameter(OH_AVFormat * format)1173 int32_t VEncAPI11Sample::SetParameter(OH_AVFormat *format)
1174 {
1175     if (venc_) {
1176         return OH_VideoEncoder_SetParameter(venc_, format);
1177     }
1178     return AV_ERR_UNKNOWN;
1179 }
1180