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