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