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