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