• 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_ndk_sample.h"
24 using namespace OHOS;
25 using namespace OHOS::Media;
26 using namespace std;
27 namespace {
28 const string MIME_TYPE = "video/avc";
29 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
30 constexpr int64_t NANOS_IN_MICRO = 1000L;
31 constexpr uint32_t FRAME_INTERVAL = 16666;
32 constexpr uint32_t MAX_PIXEL_FMT = 5;
33 constexpr uint32_t IDR_FRAME_INTERVAL = 10;
34 sptr<Surface> cs = nullptr;
35 sptr<Surface> ps = nullptr;
clearIntqueue(std::queue<uint32_t> & q)36 void clearIntqueue(std::queue<uint32_t> &q)
37 {
38     std::queue<uint32_t> empty;
39     swap(empty, q);
40 }
41 
clearBufferqueue(std::queue<OH_AVCodecBufferAttr> & q)42 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
43 {
44     std::queue<OH_AVCodecBufferAttr> empty;
45     swap(empty, q);
46 }
47 } // namespace
48 
~VEncNdkSample()49 VEncNdkSample::~VEncNdkSample()
50 {
51     Release();
52 }
53 
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)54 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
55 {
56     cout << "Error errorCode=" << errorCode << endl;
57 }
58 
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)59 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
60 {
61     cout << "Format Changed" << endl;
62 }
63 
VencInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)64 static void VencInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
65 {
66     VEncSignal *signal = static_cast<VEncSignal *>(userData);
67     unique_lock<mutex> lock(signal->inMutex_);
68     signal->inIdxQueue_.push(index);
69     signal->inBufferQueue_.push(data);
70     signal->inCond_.notify_all();
71 }
72 
VencOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)73 static void VencOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
74                                 void *userData)
75 {
76     VEncSignal *signal = static_cast<VEncSignal *>(userData);
77     unique_lock<mutex> lock(signal->outMutex_);
78     signal->outIdxQueue_.push(index);
79     signal->attrQueue_.push(*attr);
80     signal->outBufferQueue_.push(data);
81     signal->outCond_.notify_all();
82 }
GetSystemTimeUs()83 int64_t VEncNdkSample::GetSystemTimeUs()
84 {
85     struct timespec now;
86     (void)clock_gettime(CLOCK_BOOTTIME, &now);
87     int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
88 
89     return nanoTime / NANOS_IN_MICRO;
90 }
91 
ConfigureVideoEncoder()92 int32_t VEncNdkSample::ConfigureVideoEncoder()
93 {
94     OH_AVFormat *format = OH_AVFormat_Create();
95     if (format == nullptr) {
96         cout << "Fatal: Failed to create format" << endl;
97         return AV_ERR_UNKNOWN;
98     }
99     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
100     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
101     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
102     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
103     (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
104     int ret = OH_VideoEncoder_Configure(venc_, format);
105     OH_AVFormat_Destroy(format);
106     return ret;
107 }
108 
ConfigureVideoEncoder_fuzz(int32_t data)109 int32_t VEncNdkSample::ConfigureVideoEncoder_fuzz(int32_t data)
110 {
111     OH_AVFormat *format = OH_AVFormat_Create();
112     if (format == nullptr) {
113         cout << "Fatal: Failed to create format" << endl;
114         return AV_ERR_UNKNOWN;
115     }
116     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
117     DEFAULT_WIDTH = data;
118     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
119     DEFAULT_HEIGHT = data;
120     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
121     double frameRate = data;
122     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
123 
124     OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, data);
125     OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, data);
126     OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, data);
127     OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, data);
128     OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, data);
129     OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
130     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
131     OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, data);
132 
133     int ret = OH_VideoEncoder_Configure(venc_, format);
134     OH_AVFormat_Destroy(format);
135     return ret;
136 }
137 
SetVideoEncoderCallback()138 int32_t VEncNdkSample::SetVideoEncoderCallback()
139 {
140     signal_ = new VEncSignal();
141     if (signal_ == nullptr) {
142         cout << "Failed to new VEncSignal" << endl;
143         return AV_ERR_UNKNOWN;
144     }
145 
146     cb_.onError = VencError;
147     cb_.onStreamChanged = VencFormatChanged;
148     cb_.onNeedInputData = VencInputDataReady;
149     cb_.onNeedOutputData = VencOutputDataReady;
150     return OH_VideoEncoder_SetCallback(venc_, cb_, static_cast<void *>(signal_));
151 }
152 
state_EOS()153 int32_t VEncNdkSample::state_EOS()
154 {
155     unique_lock<mutex> lock(signal_->inMutex_);
156     signal_->inCond_.wait(lock, [this]() {
157         return signal_->inIdxQueue_.size() > 0;
158     });
159     uint32_t index = signal_->inIdxQueue_.front();
160     signal_->inIdxQueue_.pop();
161     signal_->inBufferQueue_.pop();
162     lock.unlock();
163     OH_AVCodecBufferAttr attr;
164     attr.pts = 0;
165     attr.size = 0;
166     attr.offset = 0;
167     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
168     return OH_VideoEncoder_PushInputData(venc_, index, attr);
169 }
ReleaseInFile()170 void VEncNdkSample::ReleaseInFile()
171 {
172     if (inFile_ != nullptr) {
173         if (inFile_->is_open()) {
174             inFile_->close();
175         }
176         inFile_.reset();
177         inFile_ = nullptr;
178     }
179 }
180 
StopInloop()181 void VEncNdkSample::StopInloop()
182 {
183     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
184         unique_lock<mutex> lock(signal_->inMutex_);
185         clearIntqueue(signal_->inIdxQueue_);
186         signal_->inCond_.notify_all();
187         lock.unlock();
188 
189         inputLoop_->join();
190         inputLoop_ = nullptr;
191     }
192 }
193 
testApi()194 void VEncNdkSample::testApi()
195 {
196     OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
197     OH_VideoEncoder_Prepare(venc_);
198     OH_VideoEncoder_GetInputDescription(venc_);
199     OH_VideoEncoder_Start(venc_);
200     OH_AVFormat *format = OH_AVFormat_Create();
201     OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
202     OH_VideoEncoder_SetParameter(venc_, format);
203     OH_VideoEncoder_NotifyEndOfStream(venc_);
204     OH_VideoEncoder_GetOutputDescription(venc_);
205     OH_AVFormat_Destroy(format);
206     OH_VideoEncoder_Flush(venc_);
207     bool isValid = false;
208     OH_VideoEncoder_IsValid(venc_, &isValid);
209     OH_VideoEncoder_Stop(venc_);
210     OH_VideoEncoder_Reset(venc_);
211 }
212 
CreateSurface()213 int32_t VEncNdkSample::CreateSurface()
214 {
215     int32_t ret = 0;
216     ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
217     if (ret != AV_ERR_OK) {
218         cout << "OH_VideoEncoder_GetSurface fail" << endl;
219         return ret;
220     }
221     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
222     if (ret != AV_ERR_OK) {
223         cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
224         return ret;
225     }
226     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
227     if (ret != AV_ERR_OK) {
228         cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
229         return ret;
230     }
231     return AV_ERR_OK;
232 }
233 
OpenFileFail()234 int32_t VEncNdkSample::OpenFileFail()
235 {
236     cout << "file open fail" << endl;
237     isRunning_.store(false);
238     (void)OH_VideoEncoder_Stop(venc_);
239     inFile_->close();
240     inFile_.reset();
241     inFile_ = nullptr;
242     return AV_ERR_UNKNOWN;
243 }
244 
StartVideoEncoder()245 int32_t VEncNdkSample::StartVideoEncoder()
246 {
247     isRunning_.store(true);
248     int32_t ret = 0;
249     if (SURFACE_INPUT) {
250         ret = CreateSurface();
251         return ret;
252     }
253     ret = OH_VideoEncoder_Start(venc_);
254     if (ret != AV_ERR_OK) {
255         cout << "Failed to start codec" << endl;
256         isRunning_.store(false);
257         signal_->inCond_.notify_all();
258         signal_->outCond_.notify_all();
259         return ret;
260     }
261     inFile_ = make_unique<ifstream>();
262     if (inFile_ == nullptr) {
263         isRunning_.store(false);
264         (void)OH_VideoEncoder_Stop(venc_);
265         return AV_ERR_UNKNOWN;
266     }
267     inFile_->open(INP_DIR, ios::in | ios::binary);
268     if (!inFile_->is_open()) {
269         OpenFileFail();
270     }
271     if (SURFACE_INPUT) {
272         inputLoop_ = make_unique<thread>(&VEncNdkSample::InputFuncSurface, this);
273     } else {
274         inputLoop_ = make_unique<thread>(&VEncNdkSample::InputFunc, this);
275     }
276     if (inputLoop_ == nullptr) {
277         cout << "Failed to create input loop" << endl;
278         isRunning_.store(false);
279         (void)OH_VideoEncoder_Stop(venc_);
280         ReleaseInFile();
281         return AV_ERR_UNKNOWN;
282     }
283     outputLoop_ = make_unique<thread>(&VEncNdkSample::OutputFunc, this);
284     if (outputLoop_ == nullptr) {
285         cout << "Failed to create output loop" << endl;
286         isRunning_.store(false);
287         (void)OH_VideoEncoder_Stop(venc_);
288         ReleaseInFile();
289         StopInloop();
290         Release();
291         return AV_ERR_UNKNOWN;
292     }
293     return AV_ERR_OK;
294 }
295 
CreateVideoEncoder(const char * codecName)296 int32_t VEncNdkSample::CreateVideoEncoder(const char *codecName)
297 {
298     venc_ = OH_VideoEncoder_CreateByName(codecName);
299     return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
300 }
301 
WaitForEOS()302 void VEncNdkSample::WaitForEOS()
303 {
304     if (inputLoop_)
305         inputLoop_->join();
306     if (outputLoop_)
307         outputLoop_->join();
308     inputLoop_ = nullptr;
309     outputLoop_ = nullptr;
310 }
311 
ReturnZeroIfEOS(uint32_t expectedSize)312 uint32_t VEncNdkSample::ReturnZeroIfEOS(uint32_t expectedSize)
313 {
314     if (inFile_->gcount() != (expectedSize)) {
315         cout << "no more data" << endl;
316         return 0;
317     }
318     return 1;
319 }
320 
ReadOneFrameYUV420SP(uint8_t * dst)321 uint32_t VEncNdkSample::ReadOneFrameYUV420SP(uint8_t *dst)
322 {
323     uint8_t *start = dst;
324     // copy Y
325     for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
326         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
327         if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
328             return 0;
329         dst += stride_;
330     }
331     // copy UV
332     for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
333         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
334         if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
335             return 0;
336         dst += stride_;
337     }
338     return dst - start;
339 }
340 
InputFuncSurface()341 void VEncNdkSample::InputFuncSurface()
342 {
343     while (true) {
344         OHNativeWindowBuffer *ohNativeWindowBuffer;
345         int fenceFd = -1;
346         if (nativeWindow == nullptr) {
347             cout << "nativeWindow == nullptr" << endl;
348             break;
349         }
350 
351         int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
352         if (err != 0) {
353             cout << "RequestBuffer failed, GSError=" << err << endl;
354             continue;
355         }
356         if (fenceFd > 0) {
357             close(fenceFd);
358         }
359         OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
360         void *virAddr = nullptr;
361         err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
362         if (err != 0) {
363             cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
364             isRunning_.store(false);
365             break;
366         }
367         uint8_t *dst = (uint8_t *)virAddr;
368         const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
369         int stride = sbuffer->GetStride();
370         if (dst == nullptr || stride < DEFAULT_WIDTH) {
371             cout << "invalid va or stride=" << stride << endl;
372             err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
373             isRunning_.store(false);
374             break;
375         }
376         stride_ = stride;
377         if (!ReadOneFrameYUV420SP(dst)) {
378             err = OH_VideoEncoder_NotifyEndOfStream(venc_);
379             if (err != 0) {
380                 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
381             }
382             break;
383         }
384         struct Region region;
385         struct Region::Rect *rect = new Region::Rect();
386         rect->x = 0;
387         rect->y = 0;
388         rect->w = DEFAULT_WIDTH;
389         rect->h = DEFAULT_HEIGHT;
390         region.rects = rect;
391         NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
392         err = OH_NativeBuffer_Unmap(nativeBuffer);
393         if (err != 0) {
394             cout << "OH_NativeBuffer_Unmap failed" << endl;
395             break;
396         }
397         err = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
398         delete rect;
399         if (err != 0) {
400             cout << "FlushBuffer failed" << endl;
401             break;
402         }
403         usleep(FRAME_INTERVAL);
404     }
405 }
406 
Flush_buffer()407 void VEncNdkSample::Flush_buffer()
408 {
409     unique_lock<mutex> inLock(signal_->inMutex_);
410     clearIntqueue(signal_->inIdxQueue_);
411     std::queue<OH_AVMemory *> empty;
412     swap(empty, signal_->inBufferQueue_);
413     signal_->inCond_.notify_all();
414     inLock.unlock();
415     unique_lock<mutex> outLock(signal_->outMutex_);
416     clearIntqueue(signal_->outIdxQueue_);
417     clearBufferqueue(signal_->attrQueue_);
418     signal_->outCond_.notify_all();
419     outLock.unlock();
420 }
421 
RepeatStartBeforeEOS()422 void VEncNdkSample::RepeatStartBeforeEOS()
423 {
424     if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
425         REPEAT_START_FLUSH_BEFORE_EOS--;
426         OH_VideoEncoder_Flush(venc_);
427         Flush_buffer();
428         OH_VideoEncoder_Start(venc_);
429     }
430     if (REPEAT_START_STOP_BEFORE_EOS > 0) {
431         REPEAT_START_STOP_BEFORE_EOS--;
432         OH_VideoEncoder_Stop(venc_);
433         Flush_buffer();
434         OH_VideoEncoder_Start(venc_);
435     }
436 }
437 
RandomEOS(uint32_t index)438 bool VEncNdkSample::RandomEOS(uint32_t index)
439 {
440     uint32_t random_eos = rand() % 25;
441     if (enable_random_eos && random_eos == frameCount) {
442         OH_AVCodecBufferAttr attr;
443         attr.pts = 0;
444         attr.size = 0;
445         attr.offset = 0;
446         attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
447         OH_VideoEncoder_PushInputData(venc_, index, attr);
448         cout << "random eos" << endl;
449         frameCount++;
450         unique_lock<mutex> lock(signal_->inMutex_);
451         signal_->inIdxQueue_.pop();
452         signal_->inBufferQueue_.pop();
453         return true;
454     }
455     return false;
456 }
457 
SetEOS(uint32_t index)458 void VEncNdkSample::SetEOS(uint32_t index)
459 {
460     OH_AVCodecBufferAttr attr;
461     attr.pts = 0;
462     attr.size = 0;
463     attr.offset = 0;
464     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
465     int32_t res = OH_VideoEncoder_PushInputData(venc_, index, attr);
466     cout << "OH_VideoEncoder_PushInputData    EOS   res: " << res << endl;
467     unique_lock<mutex> lock(signal_->inMutex_);
468     signal_->inIdxQueue_.pop();
469     signal_->inBufferQueue_.pop();
470 }
471 
PushData(OH_AVMemory * buffer,uint32_t index,int32_t & result)472 int32_t VEncNdkSample::PushData(OH_AVMemory *buffer, uint32_t index, int32_t &result)
473 {
474     int32_t res = -2;
475     OH_AVCodecBufferAttr attr;
476     uint32_t yuvSize = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3 / 2;
477     uint8_t *fileBuffer = OH_AVMemory_GetAddr(buffer);
478     if (fileBuffer == nullptr) {
479         cout << "Fatal: no memory" << endl;
480         return -1;
481     }
482     (void)inFile_->read((char *)fileBuffer, yuvSize);
483 
484     if (repeatRun && inFile_->eof()) {
485         inFile_->clear();
486         inFile_->seekg(0, ios::beg);
487         encode_count++;
488         cout << "repeat"<< "   encode_count:" << encode_count << endl;
489         return -1;
490     }
491     if (inFile_->eof()) {
492         SetEOS(index);
493         return 0;
494     }
495     attr.pts = GetSystemTimeUs();
496     attr.size = yuvSize;
497     attr.offset = 0;
498     attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
499     int32_t size = OH_AVMemory_GetSize(buffer);
500     if (size < yuvSize) {
501         cout << "bufferSize smaller than yuv size" << endl;
502         return -1;
503     }
504     if (enableForceIDR && (frameCount % IDR_FRAME_INTERVAL == 0)) {
505         OH_AVFormat *format = OH_AVFormat_Create();
506         OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
507         OH_VideoEncoder_SetParameter(venc_, format);
508         OH_AVFormat_Destroy(format);
509         format = nullptr;
510     }
511     result = OH_VideoEncoder_PushInputData(venc_, index, attr);
512     unique_lock<mutex> lock(signal_->inMutex_);
513     signal_->inIdxQueue_.pop();
514     signal_->inBufferQueue_.pop();
515     return res;
516 }
517 
CheckResult(bool isRandomEosSuccess,int32_t pushResult)518 int32_t VEncNdkSample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
519 {
520     if (isRandomEosSuccess) {
521         if (pushResult == 0) {
522             errCount = errCount + 1;
523             cout << "push input after eos should be failed!  pushResult:" << pushResult << endl;
524         }
525         return -1;
526     } else if (pushResult != 0) {
527         errCount = errCount + 1;
528         cout << "push input data failed, error:" << pushResult << endl;
529         return -1;
530     }
531     return 0;
532 }
533 
InputFunc()534 void VEncNdkSample::InputFunc()
535 {
536     errCount = 0;
537     while (true) {
538         if (!isRunning_.load()) {
539             break;
540         }
541         RepeatStartBeforeEOS();
542         unique_lock<mutex> lock(signal_->inMutex_);
543         signal_->inCond_.wait(lock, [this]() {
544             if (!isRunning_.load()) {
545                 return true;
546             }
547             return signal_->inIdxQueue_.size() > 0;
548         });
549         if (!isRunning_.load()) {
550             break;
551         }
552         uint32_t index = signal_->inIdxQueue_.front();
553         auto buffer = signal_->inBufferQueue_.front();
554 
555         lock.unlock();
556         if (!inFile_->eof()) {
557             bool isRandomEosSuccess = RandomEOS(index);
558             if (isRandomEosSuccess) {
559                 continue;
560             }
561             int32_t pushResult = 0;
562             int32_t ret = PushData(buffer, index, pushResult);
563             if (ret == 0) {
564                 break;
565             } else if (ret == -1) {
566                 continue;
567             }
568 
569             if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
570                 break;
571             }
572             frameCount++;
573         }
574         if (sleepOnFPS) {
575             usleep(FRAME_INTERVAL);
576         }
577     }
578 }
579 
CheckAttrFlag(OH_AVCodecBufferAttr attr)580 int32_t VEncNdkSample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
581 {
582     if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
583         cout << "attr.flags == AVCODEC_BUFFER_FLAGS_EOS" << endl;
584         unique_lock<mutex> inLock(signal_->inMutex_);
585         isRunning_.store(false);
586         signal_->inCond_.notify_all();
587         signal_->outCond_.notify_all();
588         inLock.unlock();
589         return -1;
590     }
591     if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
592         cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
593     }
594     outCount = outCount + 1;
595     return 0;
596 }
597 
OutputFuncFail()598 void VEncNdkSample::OutputFuncFail()
599 {
600     cout << "errCount > 0" << endl;
601     unique_lock<mutex> inLock(signal_->inMutex_);
602     isRunning_.store(false);
603     signal_->inCond_.notify_all();
604     signal_->outCond_.notify_all();
605     inLock.unlock();
606     (void)Stop();
607     Release();
608 }
609 
OutputFunc()610 void VEncNdkSample::OutputFunc()
611 {
612     FILE *outFile = fopen(OUT_DIR, "wb");
613 
614     while (true) {
615         if (!isRunning_.load()) {
616             break;
617         }
618         OH_AVCodecBufferAttr attr;
619         uint32_t index;
620         unique_lock<mutex> lock(signal_->outMutex_);
621         signal_->outCond_.wait(lock, [this]() {
622             if (!isRunning_.load()) {
623                 return true;
624             }
625             return signal_->outIdxQueue_.size() > 0;
626         });
627         if (!isRunning_.load()) {
628             break;
629         }
630         index = signal_->outIdxQueue_.front();
631         attr = signal_->attrQueue_.front();
632         OH_AVMemory *buffer = signal_->outBufferQueue_.front();
633         signal_->outBufferQueue_.pop();
634         signal_->outIdxQueue_.pop();
635         signal_->attrQueue_.pop();
636         lock.unlock();
637         if (CheckAttrFlag(attr) == -1) {
638             break;
639         }
640         int size = attr.size;
641 
642         if (outFile == nullptr) {
643             cout << "dump data fail" << endl;
644         } else {
645             fwrite(OH_AVMemory_GetAddr(buffer), 1, size, outFile);
646         }
647 
648         if (OH_VideoEncoder_FreeOutputData(venc_, index) != AV_ERR_OK) {
649             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
650             errCount = errCount + 1;
651         }
652         if (errCount > 0) {
653             OutputFuncFail();
654             break;
655         }
656     }
657     (void)fclose(outFile);
658 }
659 
Flush()660 int32_t VEncNdkSample::Flush()
661 {
662     unique_lock<mutex> inLock(signal_->inMutex_);
663     clearIntqueue(signal_->inIdxQueue_);
664     signal_->inCond_.notify_all();
665     inLock.unlock();
666     unique_lock<mutex> outLock(signal_->outMutex_);
667     clearIntqueue(signal_->outIdxQueue_);
668     clearBufferqueue(signal_->attrQueue_);
669     signal_->outCond_.notify_all();
670     outLock.unlock();
671     return OH_VideoEncoder_Flush(venc_);
672 }
673 
Reset()674 int32_t VEncNdkSample::Reset()
675 {
676     isRunning_.store(false);
677     StopInloop();
678     StopOutloop();
679     ReleaseInFile();
680     return OH_VideoEncoder_Reset(venc_);
681 }
682 
Release()683 int32_t VEncNdkSample::Release()
684 {
685     int ret = OH_VideoEncoder_Destroy(venc_);
686     venc_ = nullptr;
687     if (signal_ != nullptr) {
688         delete signal_;
689         signal_ = nullptr;
690     }
691     return ret;
692 }
693 
Stop()694 int32_t VEncNdkSample::Stop()
695 {
696     StopInloop();
697     clearIntqueue(signal_->outIdxQueue_);
698     clearBufferqueue(signal_->attrQueue_);
699     ReleaseInFile();
700     return OH_VideoEncoder_Stop(venc_);
701 }
702 
Start()703 int32_t VEncNdkSample::Start()
704 {
705     return OH_VideoEncoder_Start(venc_);
706 }
707 
StopOutloop()708 void VEncNdkSample::StopOutloop()
709 {
710     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
711         unique_lock<mutex> lock(signal_->outMutex_);
712         clearIntqueue(signal_->outIdxQueue_);
713         clearBufferqueue(signal_->attrQueue_);
714         signal_->outCond_.notify_all();
715         lock.unlock();
716     }
717 }
718 
SetParameter(OH_AVFormat * format)719 void VEncNdkSample::SetParameter(OH_AVFormat *format)
720 {
721     if (venc_) {
722         OH_VideoEncoder_SetParameter(venc_, format);
723     }
724 }