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