• 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 "openssl/crypto.h"
19 #include "openssl/sha.h"
20 #include "native_buffer_inner.h"
21 #include "display_type.h"
22 #include "iconsumer_surface.h"
23 #include "videoenc_ndk_inner_sample.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::MediaAVCodec;
27 using namespace std;
28 
29 namespace {
30 const string MIME_TYPE = "video/avc";
31 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
32 constexpr int64_t NANOS_IN_MICRO = 1000L;
33 constexpr uint32_t FRAME_INTERVAL = 16666;
34 constexpr uint32_t MAX_PIXEL_FMT = 5;
35 constexpr uint32_t IDR_FRAME_INTERVAL = 10;
36 
clearIntqueue(std::queue<uint32_t> & q)37 void clearIntqueue(std::queue<uint32_t> &q)
38 {
39     std::queue<uint32_t> empty;
40     swap(empty, q);
41 }
42 
clearBufferqueue(std::queue<AVCodecBufferInfo> & q)43 void clearBufferqueue(std::queue<AVCodecBufferInfo> &q)
44 {
45     std::queue<AVCodecBufferInfo> empty;
46     swap(empty, q);
47 }
48 
clearFlagqueue(std::queue<AVCodecBufferFlag> & q)49 void clearFlagqueue(std::queue<AVCodecBufferFlag> &q)
50 {
51     std::queue<AVCodecBufferFlag> empty;
52     swap(empty, q);
53 }
54 } // namespace
55 
VEncInnerCallback(std::shared_ptr<VEncInnerSignal> signal)56 VEncInnerCallback::VEncInnerCallback(std::shared_ptr<VEncInnerSignal> signal) : innersignal_(signal) {}
57 
OnError(AVCodecErrorType errorType,int32_t errorCode)58 void VEncInnerCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
59 {
60     cout << "Error errorType:" << errorType << " errorCode:" << errorCode << endl;
61 }
62 
OnOutputFormatChanged(const Format & format)63 void VEncInnerCallback::OnOutputFormatChanged(const Format& format)
64 {
65     cout << "Format Changed" << endl;
66 }
67 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)68 void VEncInnerCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
69 {
70     cout << "OnInputBufferAvailable index:" << index << endl;
71     if (innersignal_ == nullptr) {
72         std::cout << "buffer is null 1" << endl;
73         return;
74     }
75 
76     unique_lock<mutex> lock(innersignal_->inMutex_);
77     innersignal_->inIdxQueue_.push(index);
78     innersignal_->inBufferQueue_.push(buffer);
79     innersignal_->inCond_.notify_all();
80 }
81 
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)82 void VEncInnerCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info,
83     AVCodecBufferFlag flag, std::shared_ptr<AVSharedMemory> buffer)
84 {
85     cout << "OnOutputBufferAvailable index:" << index << endl;
86     unique_lock<mutex> lock(innersignal_->outMutex_);
87     innersignal_->outIdxQueue_.push(index);
88     innersignal_->infoQueue_.push(info);
89     innersignal_->flagQueue_.push(flag);
90     innersignal_->outBufferQueue_.push(buffer);
91     cout << "**********out info size = " << info.size << endl;
92     innersignal_->outCond_.notify_all();
93 }
94 
~VEncNdkInnerSample()95 VEncNdkInnerSample::~VEncNdkInnerSample()
96 {
97     Release();
98 }
99 
GetSystemTimeUs()100 int64_t VEncNdkInnerSample::GetSystemTimeUs()
101 {
102     struct timespec now;
103     (void)clock_gettime(CLOCK_BOOTTIME, &now);
104     int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
105 
106     return nanoTime / NANOS_IN_MICRO;
107 }
108 
CreateByMime(const std::string & mime)109 int32_t VEncNdkInnerSample::CreateByMime(const std::string &mime)
110 {
111     venc_ = VideoEncoderFactory::CreateByMime(mime);
112     return venc_ == nullptr ? AVCS_ERR_INVALID_OPERATION : AVCS_ERR_OK;
113 }
114 
CreateByName(const std::string & name)115 int32_t VEncNdkInnerSample::CreateByName(const std::string &name)
116 {
117     venc_ = VideoEncoderFactory::CreateByName(name);
118     return venc_ == nullptr ? AVCS_ERR_INVALID_OPERATION : AVCS_ERR_OK;
119 }
120 
Configure()121 int32_t VEncNdkInnerSample::Configure()
122 {
123     Format format;
124     format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, DEFAULT_WIDTH);
125     format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, DEFAULT_HEIGHT);
126     format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::NV12));
127     format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
128     format.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, DEFAULT_BITRATE);
129 
130     return venc_->Configure(format);
131 }
132 
ConfigureFuzz(int32_t data)133 int32_t VEncNdkInnerSample::ConfigureFuzz(int32_t data)
134 {
135     Format format;
136     double frameRate = data;
137     format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, data);
138     format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, data);
139     format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
140     format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate);
141     format.PutIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, data);
142     format.PutIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, data);
143     format.PutIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, data);
144     format.PutIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, data);
145     format.PutIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, data);
146     format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
147     format.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, data);
148     format.PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, data);
149 
150     return venc_->Configure(format);
151 }
152 
Prepare()153 int32_t VEncNdkInnerSample::Prepare()
154 {
155     return venc_->Prepare();
156 }
157 
Start()158 int32_t VEncNdkInnerSample::Start()
159 {
160     return venc_->Start();
161 }
162 
Stop()163 int32_t VEncNdkInnerSample::Stop()
164 {
165     StopInloop();
166     clearIntqueue(signal_->outIdxQueue_);
167     clearBufferqueue(signal_->infoQueue_);
168     clearFlagqueue(signal_->flagQueue_);
169     ReleaseInFile();
170 
171     return venc_->Stop();
172 }
173 
Flush()174 int32_t VEncNdkInnerSample::Flush()
175 {
176     unique_lock<mutex> inLock(signal_->inMutex_);
177     clearIntqueue(signal_->inIdxQueue_);
178     signal_->inCond_.notify_all();
179     inLock.unlock();
180     unique_lock<mutex> outLock(signal_->outMutex_);
181     clearIntqueue(signal_->outIdxQueue_);
182     clearBufferqueue(signal_->infoQueue_);
183     clearFlagqueue(signal_->flagQueue_);
184     signal_->outCond_.notify_all();
185     outLock.unlock();
186 
187     return venc_->Flush();
188 }
189 
NotifyEos()190 int32_t VEncNdkInnerSample::NotifyEos()
191 {
192     return venc_->NotifyEos();
193 }
194 
Reset()195 int32_t VEncNdkInnerSample::Reset()
196 {
197     isRunning_.store(false);
198     StopInloop();
199     StopOutloop();
200     ReleaseInFile();
201 
202     if (venc_ == nullptr) {
203         std::cout << "InnerEncoder create failed!" << std::endl;
204         return AVCS_ERR_INVALID_OPERATION;
205     }
206     return venc_->Reset();
207 }
208 
Release()209 int32_t VEncNdkInnerSample::Release()
210 {
211     int32_t ret = venc_->Release();
212     venc_ = nullptr;
213     if (signal_ != nullptr) {
214         signal_ = nullptr;
215     }
216     return ret;
217 }
218 
CreateInputSurface()219 int32_t VEncNdkInnerSample::CreateInputSurface()
220 {
221     sptr<Surface> surface = venc_->CreateInputSurface();
222     if (surface == nullptr) {
223         cout << "CreateInputSurface fail" << endl;
224         return AVCS_ERR_INVALID_OPERATION;
225     }
226 
227     nativeWindow = CreateNativeWindowFromSurface(&surface);
228     if (nativeWindow == nullptr) {
229         cout << "CreateNativeWindowFromSurface failed!" << endl;
230         return AVCS_ERR_INVALID_VAL;
231     }
232 
233     int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
234     if (ret != AVCS_ERR_OK) {
235         cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
236         return ret;
237     }
238 
239     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
240     if (ret != AVCS_ERR_OK) {
241         cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
242         return ret;
243     }
244 
245     return AVCS_ERR_OK;
246 }
247 
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)248 int32_t VEncNdkInnerSample::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
249 {
250     return venc_->QueueInputBuffer(index, info, flag);
251 }
252 
GetOutputFormat(Format & format)253 int32_t VEncNdkInnerSample::GetOutputFormat(Format &format)
254 {
255     return venc_->GetOutputFormat(format);
256 }
257 
ReleaseOutputBuffer(uint32_t index)258 int32_t VEncNdkInnerSample::ReleaseOutputBuffer(uint32_t index)
259 {
260     return venc_->ReleaseOutputBuffer(index);
261 }
262 
SetParameter(const Format & format)263 int32_t VEncNdkInnerSample::SetParameter(const Format &format)
264 {
265     return venc_->SetParameter(format);
266 }
267 
SetCallback()268 int32_t VEncNdkInnerSample::SetCallback()
269 {
270     signal_ = make_shared<VEncInnerSignal>();
271     if (signal_ == nullptr) {
272         cout << "Failed to new VEncInnerSignal" << endl;
273         return AVCS_ERR_UNKNOWN;
274     }
275 
276     cb_ = make_shared<VEncInnerCallback>(signal_);
277     return venc_->SetCallback(cb_);
278 }
279 
GetInputFormat(Format & format)280 int32_t VEncNdkInnerSample::GetInputFormat(Format &format)
281 {
282     return venc_->GetInputFormat(format);
283 }
284 
StartVideoEncoder()285 int32_t VEncNdkInnerSample::StartVideoEncoder()
286 {
287     isRunning_.store(true);
288     int32_t ret = 0;
289 
290     if (surfaceInput) {
291         ret = CreateInputSurface();
292         return ret;
293     }
294 
295     ret = venc_->Start();
296     if (ret != AVCS_ERR_OK) {
297         cout << "Failed to start codec" << endl;
298         isRunning_.store(false);
299         signal_->inCond_.notify_all();
300         signal_->outCond_.notify_all();
301         return ret;
302     }
303 
304     inFile_ = make_unique<ifstream>();
305     if (inFile_ == nullptr) {
306         isRunning_.store(false);
307         venc_->Stop();
308         return AVCS_ERR_UNKNOWN;
309     }
310 
311     inFile_->open(INP_DIR, ios::in | ios::binary);
312     if (!inFile_->is_open()) {
313         OpenFileFail();
314     }
315 
316     if (surfaceInput) {
317         inputLoop_ = make_unique<thread>(&VEncNdkInnerSample::InputFuncSurface, this);
318     } else {
319         inputLoop_ = make_unique<thread>(&VEncNdkInnerSample::InputFunc, this);
320     }
321 
322     if (inputLoop_ == nullptr) {
323         cout << "Failed to create input loop" << endl;
324         isRunning_.store(false);
325         venc_->Stop();
326         ReleaseInFile();
327         return AVCS_ERR_UNKNOWN;
328     }
329 
330     outputLoop_ = make_unique<thread>(&VEncNdkInnerSample::OutputFunc, this);
331     if (outputLoop_ == nullptr) {
332         cout << "Failed to create output loop" << endl;
333         isRunning_.store(false);
334         venc_->Stop();
335         ReleaseInFile();
336         StopInloop();
337         Release();
338         return AVCS_ERR_UNKNOWN;
339     }
340     return AVCS_ERR_OK;
341 }
342 
testApi()343 int32_t VEncNdkInnerSample::testApi()
344 {
345     if (venc_ == nullptr) {
346         std::cout << "InnerEncoder create failed!" << std::endl;
347         return AVCS_ERR_INVALID_OPERATION;
348     }
349 
350     Format format;
351     format.PutIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, 1);
352     venc_->CreateInputSurface();
353     venc_->Prepare();
354     venc_->GetInputFormat(format);
355     venc_->Start();
356     venc_->SetParameter(format);
357     venc_->NotifyEos();
358     venc_->GetOutputFormat(format);
359     venc_->Flush();
360     venc_->Stop();
361     venc_->Reset();
362 
363     return AVCS_ERR_OK;
364 }
365 
PushData(std::shared_ptr<AVSharedMemory> buffer,uint32_t index,int32_t & result)366 int32_t VEncNdkInnerSample::PushData(std::shared_ptr<AVSharedMemory> buffer, uint32_t index, int32_t &result)
367 {
368     int32_t res = -2;
369     uint32_t yuvSize = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3 / 2;
370     uint8_t *fileBuffer = buffer->GetBase();
371     if (fileBuffer == nullptr) {
372         cout << "Fatal: no memory" << endl;
373         return -1;
374     }
375     (void)inFile_->read((char *)fileBuffer, yuvSize);
376 
377     if (repeatRun && inFile_->eof()) {
378         inFile_->clear();
379         inFile_->seekg(0, ios::beg);
380         encodeCount++;
381         cout << "repeat" << "  encodeCount:" << encodeCount << endl;
382         return -1;
383     }
384 
385     if (inFile_->eof()) {
386         SetEOS(index);
387         return 0;
388     }
389 
390     AVCodecBufferInfo info;
391     info.presentationTimeUs = GetSystemTimeUs();
392     info.size = yuvSize;
393     info.offset = 0;
394     AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_NONE;
395 
396     int32_t size = buffer->GetSize();
397     if (size < (int32_t)yuvSize) {
398         cout << "bufferSize smaller than yuv size" << endl;
399         return -1;
400     }
401 
402     if (enableForceIDR && (frameCount % IDR_FRAME_INTERVAL == 0)) {
403         Format format;
404         format.PutIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, 1);
405         venc_->SetParameter(format);
406     }
407     result = venc_->QueueInputBuffer(index, info, flag);
408     unique_lock<mutex> lock(signal_->inMutex_);
409     signal_->inIdxQueue_.pop();
410     signal_->inBufferQueue_.pop();
411 
412     return res;
413 }
414 
OpenFileFail()415 int32_t VEncNdkInnerSample::OpenFileFail()
416 {
417     cout << "file open fail" << endl;
418     isRunning_.store(false);
419     venc_->Stop();
420     inFile_->close();
421     inFile_.reset();
422     inFile_ = nullptr;
423     return AVCS_ERR_UNKNOWN;
424 }
425 
CheckResult(bool isRandomEosSuccess,int32_t pushResult)426 int32_t VEncNdkInnerSample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
427 {
428     if (isRandomEosSuccess) {
429         if (pushResult == 0) {
430             errCount = errCount + 1;
431             cout << "push input after eos should be failed!  pushResult:" << pushResult << endl;
432         }
433         return -1;
434     } else if (pushResult != 0) {
435         errCount = errCount + 1;
436         cout << "push input data failed, error:" << pushResult << endl;
437         return -1;
438     }
439     return 0;
440 }
441 
CheckFlag(AVCodecBufferFlag flag)442 int32_t VEncNdkInnerSample::CheckFlag(AVCodecBufferFlag flag)
443 {
444     if (flag == AVCODEC_BUFFER_FLAG_EOS) {
445         cout << "flag == AVCODEC_BUFFER_FLAG_EOS" << endl;
446         unique_lock<mutex> inLock(signal_->inMutex_);
447         isRunning_.store(false);
448         signal_->inCond_.notify_all();
449         signal_->outCond_.notify_all();
450         inLock.unlock();
451         return -1;
452     }
453 
454     if (flag == AVCODEC_BUFFER_FLAG_CODEC_DATA) {
455         cout << "enc AVCODEC_BUFFER_FLAG_CODEC_DATA" << endl;
456     }
457     outCount = outCount + 1;
458     return 0;
459 }
460 
InputProcess(OH_NativeBuffer * nativeBuffer,OHNativeWindowBuffer * ohNativeWindowBuffer)461 int32_t VEncNdkInnerSample::InputProcess(OH_NativeBuffer *nativeBuffer, OHNativeWindowBuffer *ohNativeWindowBuffer)
462 {
463     int32_t ret = 0;
464     struct Region region;
465     struct Region::Rect *rect = new Region::Rect();
466     rect->x = 0;
467     rect->y = 0;
468     rect->w = DEFAULT_WIDTH;
469     rect->h = DEFAULT_HEIGHT;
470     region.rects = rect;
471     NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
472     ret = OH_NativeBuffer_Unmap(nativeBuffer);
473     if (ret != 0) {
474         cout << "OH_NativeBuffer_Unmap failed" << endl;
475         delete rect;
476         return ret;
477     }
478 
479     ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
480     delete rect;
481     if (ret != 0) {
482         cout << "FlushBuffer failed" << endl;
483         return ret;
484     }
485     return ret;
486 }
487 
StateEOS()488 int32_t VEncNdkInnerSample::StateEOS()
489 {
490     unique_lock<mutex> lock(signal_->inMutex_);
491     signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
492     uint32_t index = signal_->inIdxQueue_.front();
493     signal_->inIdxQueue_.pop();
494     signal_->inBufferQueue_.pop();
495     lock.unlock();
496 
497     AVCodecBufferInfo info;
498     info.presentationTimeUs = 0;
499     info.size = 0;
500     info.offset = 0;
501     AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
502 
503     return venc_->QueueInputBuffer(index, info, flag);
504 }
505 
ReturnZeroIfEOS(uint32_t expectedSize)506 uint32_t VEncNdkInnerSample::ReturnZeroIfEOS(uint32_t expectedSize)
507 {
508     if (inFile_->gcount() != (int32_t)expectedSize) {
509         cout << "no more data" << endl;
510         return 0;
511     }
512     return 1;
513 }
514 
ReadOneFrameYUV420SP(uint8_t * dst)515 uint32_t VEncNdkInnerSample::ReadOneFrameYUV420SP(uint8_t *dst)
516 {
517     uint8_t *start = dst;
518     // copy Y
519     for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
520         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
521         if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
522             return 0;
523         dst += stride_;
524     }
525     // copy UV
526     for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
527         inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
528         if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
529             return 0;
530         dst += stride_;
531     }
532     return dst - start;
533 }
534 
RandomEOS(uint32_t index)535 bool VEncNdkInnerSample::RandomEOS(uint32_t index)
536 {
537     uint32_t random_eos = rand() % 25;
538     if (enableRandomEos && random_eos == frameCount) {
539         AVCodecBufferInfo info;
540         info.presentationTimeUs = 0;
541         info.size = 0;
542         info.offset = 0;
543         AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
544 
545         venc_->QueueInputBuffer(index, info, flag);
546         cout << "random eos" << endl;
547         frameCount++;
548         unique_lock<mutex> lock(signal_->inMutex_);
549         signal_->inIdxQueue_.pop();
550         signal_->inBufferQueue_.pop();
551         return true;
552     }
553     return false;
554 }
555 
RepeatStartBeforeEOS()556 void VEncNdkInnerSample::RepeatStartBeforeEOS()
557 {
558     if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
559         REPEAT_START_FLUSH_BEFORE_EOS--;
560         venc_->Flush();
561         FlushBuffer();
562         venc_->Start();
563     }
564 
565     if (REPEAT_START_STOP_BEFORE_EOS > 0) {
566         REPEAT_START_STOP_BEFORE_EOS--;
567         venc_->Stop();
568         FlushBuffer();
569         venc_->Start();
570     }
571 }
572 
SetEOS(uint32_t index)573 void VEncNdkInnerSample::SetEOS(uint32_t index)
574 {
575     AVCodecBufferInfo info;
576     info.presentationTimeUs = 0;
577     info.size = 0;
578     info.offset = 0;
579     AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
580 
581     int32_t res = venc_->QueueInputBuffer(index, info, flag);
582     cout << "QueueInputBuffer EOS res: " << res << endl;
583     unique_lock<mutex> lock(signal_->inMutex_);
584     signal_->inIdxQueue_.pop();
585     signal_->inBufferQueue_.pop();
586 }
587 
WaitForEOS()588 void VEncNdkInnerSample::WaitForEOS()
589 {
590     if (inputLoop_)
591         inputLoop_->join();
592     if (outputLoop_)
593         outputLoop_->join();
594     inputLoop_ = nullptr;
595     outputLoop_ = nullptr;
596 }
597 
InputFuncSurface()598 void VEncNdkInnerSample::InputFuncSurface()
599 {
600     while (true) {
601         OHNativeWindowBuffer *ohNativeWindowBuffer;
602         int fenceFd = -1;
603         if (nativeWindow == nullptr) {
604             cout << "nativeWindow == nullptr" << endl;
605             break;
606         }
607 
608         int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
609         if (err != 0) {
610             cout << "RequestBuffer failed, GSError=" << err << endl;
611             continue;
612         }
613         if (fenceFd > 0) {
614             close(fenceFd);
615         }
616         OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
617         void *virAddr = nullptr;
618         err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
619         if (err != 0) {
620             cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
621             isRunning_.store(false);
622             break;
623         }
624         uint8_t *dst = (uint8_t *)virAddr;
625         const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
626         int32_t stride = sbuffer->GetStride();
627         if (dst == nullptr || stride < (int32_t)DEFAULT_WIDTH) {
628             cout << "invalid va or stride=" << stride << endl;
629             err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
630             isRunning_.store(false);
631             break;
632         }
633         stride_ = stride;
634         if (!ReadOneFrameYUV420SP(dst)) {
635             err = venc_->NotifyEos();
636             if (err != 0) {
637                 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
638             }
639             break;
640         }
641 
642         err = InputProcess(nativeBuffer, ohNativeWindowBuffer);
643         if (err != 0) {
644             break;
645         }
646         usleep(FRAME_INTERVAL);
647     }
648 }
649 
InputFunc()650 void VEncNdkInnerSample::InputFunc()
651 {
652     errCount = 0;
653     while (true) {
654         if (!isRunning_.load()) {
655             break;
656         }
657         RepeatStartBeforeEOS();
658         unique_lock<mutex> lock(signal_->inMutex_);
659         signal_->inCond_.wait(lock, [this]() {
660             if (!isRunning_.load()) {
661                 return true;
662             }
663             return signal_->inIdxQueue_.size() > 0;
664         });
665         if (!isRunning_.load()) {
666             break;
667         }
668         uint32_t index = signal_->inIdxQueue_.front();
669         auto buffer = signal_->inBufferQueue_.front();
670 
671         lock.unlock();
672         if (!inFile_->eof()) {
673             bool isRandomEosSuccess = RandomEOS(index);
674             if (isRandomEosSuccess) {
675                 continue;
676             }
677             int32_t pushResult = 0;
678             int32_t ret = PushData(buffer, index, pushResult);
679             if (ret == 0) {
680                 break;
681             } else if (ret == -1) {
682                 continue;
683             }
684 
685             if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
686                 break;
687             }
688             frameCount++;
689         }
690         if (sleepOnFPS) {
691             usleep(FRAME_INTERVAL);
692         }
693     }
694 }
695 
OutputFunc()696 void VEncNdkInnerSample::OutputFunc()
697 {
698     FILE *outFile = fopen(OUT_DIR, "wb");
699 
700     while (true) {
701         if (!isRunning_.load()) {
702             break;
703         }
704 
705         unique_lock<mutex> lock(signal_->outMutex_);
706         signal_->outCond_.wait(lock, [this]() {
707             if (!isRunning_.load()) {
708                 return true;
709             }
710             return signal_->outIdxQueue_.size() > 0;
711         });
712 
713         if (!isRunning_.load()) {
714             break;
715         }
716 
717         std::shared_ptr<AVSharedMemory> buffer = signal_->outBufferQueue_.front();
718         AVCodecBufferInfo info = signal_->infoQueue_.front();
719         AVCodecBufferFlag flag = signal_->flagQueue_.front();
720         uint32_t index = signal_->outIdxQueue_.front();
721 
722         signal_->outBufferQueue_.pop();
723         signal_->outIdxQueue_.pop();
724         signal_->infoQueue_.pop();
725         signal_->flagQueue_.pop();
726         lock.unlock();
727 
728         if (CheckFlag(flag) == -1) {
729             break;
730         }
731 
732         int size = info.size;
733         if (outFile == nullptr) {
734             cout << "dump data fail" << endl;
735         } else {
736             fwrite(buffer->GetBase(), 1, size, outFile);
737         }
738 
739         if (venc_->ReleaseOutputBuffer(index) != AVCS_ERR_OK) {
740             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
741             errCount = errCount + 1;
742         }
743         if (errCount > 0) {
744             OutputFuncFail();
745             break;
746         }
747     }
748     (void)fclose(outFile);
749 }
750 
OutputFuncFail()751 void VEncNdkInnerSample::OutputFuncFail()
752 {
753     cout << "errCount > 0" << endl;
754     unique_lock<mutex> inLock(signal_->inMutex_);
755     isRunning_.store(false);
756     signal_->inCond_.notify_all();
757     signal_->outCond_.notify_all();
758     inLock.unlock();
759     (void)Stop();
760     Release();
761 }
762 
FlushBuffer()763 void VEncNdkInnerSample::FlushBuffer()
764 {
765     std::queue<std::shared_ptr<AVSharedMemory>> empty;
766     unique_lock<mutex> inLock(signal_->inMutex_);
767     clearIntqueue(signal_->inIdxQueue_);
768     swap(empty, signal_->inBufferQueue_);
769     signal_->inCond_.notify_all();
770     inLock.unlock();
771 
772     unique_lock<mutex> outLock(signal_->outMutex_);
773     clearIntqueue(signal_->outIdxQueue_);
774     clearBufferqueue(signal_->infoQueue_);
775     clearFlagqueue(signal_->flagQueue_);
776     signal_->outCond_.notify_all();
777     outLock.unlock();
778 }
779 
StopInloop()780 void VEncNdkInnerSample::StopInloop()
781 {
782     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
783         unique_lock<mutex> lock(signal_->inMutex_);
784         clearIntqueue(signal_->inIdxQueue_);
785         isRunning_.store(false);
786         signal_->inCond_.notify_all();
787         lock.unlock();
788 
789         inputLoop_->join();
790         inputLoop_ = nullptr;
791     }
792 }
793 
StopOutloop()794 void VEncNdkInnerSample::StopOutloop()
795 {
796     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
797         unique_lock<mutex> lock(signal_->outMutex_);
798         clearIntqueue(signal_->outIdxQueue_);
799         clearBufferqueue(signal_->infoQueue_);
800         clearFlagqueue(signal_->flagQueue_);
801         signal_->outCond_.notify_all();
802         lock.unlock();
803     }
804 }
805 
ReleaseInFile()806 void VEncNdkInnerSample::ReleaseInFile()
807 {
808     if (inFile_ != nullptr) {
809         if (inFile_->is_open()) {
810             inFile_->close();
811         }
812         inFile_.reset();
813         inFile_ = nullptr;
814     }
815 }
816