• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 <sys/timeb.h>
18 #include <utility>
19 #include <vector>
20 #include <string>
21 #include <sstream>
22 #include <random>
23 #include "openssl/crypto.h"
24 #include "openssl/sha.h"
25 #include "videodec_api11_sample.h"
26 #include "nlohmann/json.hpp"
27 using namespace OHOS;
28 using namespace OHOS::Media;
29 using namespace std;
30 using namespace nlohmann;
31 namespace {
32 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
33 constexpr int64_t MICRO_IN_SECOND = 1000000L;
34 constexpr int64_t NANOS_IN_MICRO = 1000L;
35 constexpr int32_t THREE = 3;
36 constexpr int32_t EIGHT = 8;
37 constexpr int32_t TEN = 10;
38 constexpr int32_t SIXTEEN = 16;
39 constexpr int32_t TWENTY_FOUR = 24;
40 constexpr uint8_t H264_NALU_TYPE = 0x1f;
41 constexpr uint32_t START_CODE_SIZE = 4;
42 constexpr uint32_t MILLION = 1000000;
43 constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
44 constexpr uint8_t SPS = 7;
45 constexpr uint8_t PPS = 8;
46 constexpr int32_t RES_CHANGE_TIME = 4;
47 constexpr int32_t CROP_INFO_SIZE = 2;
48 constexpr int32_t CROP_INFO[RES_CHANGE_TIME][CROP_INFO_SIZE] = {{621, 1103},
49     {1079, 1919}, {719, 1279}, {855, 1919}};
50 constexpr int32_t CROP_BOTTOM = 0;
51 constexpr int32_t CROP_RIGHT = 1;
52 constexpr int32_t DEFAULT_ANGLE = 90;
53 constexpr int32_t SYS_MAX_INPUT_SIZE = 1024 * 1024 * 24;
54 constexpr int32_t MIN_RANGE = 64;
55 constexpr int32_t MAX_RANGE = 1920;
56 constexpr int32_t MIN_FRANGE = 1;
57 constexpr int32_t MAX_FRANGE = 30;
58 constexpr int32_t EVEN_NUMBER = 2;
59 SHA512_CTX g_c;
60 uint8_t g_md[SHA512_DIGEST_LENGTH];
61 VDecAPI11Sample *dec_sample = nullptr;
62 
clearIntqueue(std::queue<uint32_t> & q)63 void clearIntqueue(std::queue<uint32_t> &q)
64 {
65     std::queue<uint32_t> empty;
66     swap(empty, q);
67 }
68 
clearBufferqueue(std::queue<OH_AVCodecBufferAttr> & q)69 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
70 {
71     std::queue<OH_AVCodecBufferAttr> empty;
72     swap(empty, q);
73 }
74 } // namespace
75 
76 class ConsumerListenerBuffer : public IBufferConsumerListener {
77 public:
ConsumerListenerBuffer(sptr<Surface> cs,std::string_view name)78     ConsumerListenerBuffer(sptr<Surface> cs, std::string_view name) : cs(cs) {};
~ConsumerListenerBuffer()79     ~ConsumerListenerBuffer() {}
OnBufferAvailable()80     void OnBufferAvailable() override
81     {
82         sptr<SurfaceBuffer> buffer;
83         int32_t flushFence;
84         cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
85         cs->ReleaseBuffer(buffer, -1);
86     }
87 
88 private:
89     int64_t timestamp = 0;
90     Rect damage = {};
91     sptr<Surface> cs {nullptr};
92 };
93 
~VDecAPI11Sample()94 VDecAPI11Sample::~VDecAPI11Sample()
95 {
96     for (int i = 0; i < MAX_SURF_NUM; i++) {
97         if (nativeWindow[i]) {
98             OH_NativeWindow_DestroyNativeWindow(nativeWindow[i]);
99             nativeWindow[i] = nullptr;
100         }
101     }
102     Stop();
103     Release();
104 }
105 
VdecAPI11Error(OH_AVCodec * codec,int32_t errorCode,void * userData)106 void VdecAPI11Error(OH_AVCodec *codec, int32_t errorCode, void *userData)
107 {
108     cout << "Error errorCode=" << errorCode << endl;
109 }
110 
VdecAPI11FormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)111 void VdecAPI11FormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
112 {
113     int32_t currentWidth = 0;
114     int32_t currentHeight = 0;
115     int32_t stride = 0;
116     int32_t sliceHeight = 0;
117     int32_t picWidth = 0;
118     int32_t picHeight = 0;
119     OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &currentWidth);
120     OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &currentHeight);
121     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &stride);
122     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &sliceHeight);
123     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_WIDTH, &picWidth);
124     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_HEIGHT, &picHeight);
125     dec_sample->DEFAULT_WIDTH = currentWidth;
126     dec_sample->DEFAULT_HEIGHT = currentHeight;
127     dec_sample->stride_ = stride;
128     dec_sample->sliceHeight_ = sliceHeight;
129     dec_sample->picWidth_ = picWidth;
130     dec_sample->picHeight_ = picHeight;
131     if (dec_sample->isResChangeStream) {
132         static int32_t resCount = 0;
133         int32_t cropBottom = 0;
134         int32_t cropRight = 0;
135         OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_CROP_BOTTOM, &cropBottom);
136         OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_CROP_RIGHT, &cropRight);
137         if (cropBottom != CROP_INFO[resCount][CROP_BOTTOM] || cropRight != CROP_INFO[resCount][CROP_RIGHT]) {
138             dec_sample->errCount++;
139         }
140         if (stride <= 0 || sliceHeight <= 0) {
141             dec_sample->errCount++;
142         }
143         resCount++;
144     }
145 }
146 
VdecAPI11InputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * data,void * userData)147 void VdecAPI11InputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
148 {
149     if (dec_sample->isFlushing_) {
150         return;
151     }
152     if (dec_sample->inputCallbackFlush && dec_sample->outCount > 1) {
153         dec_sample->Flush();
154         cout << "OH_VideoDecoder_Flush end" << endl;
155         dec_sample->isRunning_.store(false);
156         dec_sample->signal_->inCond_.notify_all();
157         dec_sample->signal_->outCond_.notify_all();
158         return;
159     }
160     if (dec_sample->inputCallbackStop && dec_sample->outCount > 1) {
161         OH_VideoDecoder_Stop(codec);
162         cout << "OH_VideoDecoder_Stop end" << endl;
163         dec_sample->isRunning_.store(false);
164         dec_sample->signal_->inCond_.notify_all();
165         dec_sample->signal_->outCond_.notify_all();
166         return;
167     }
168     VDecAPI11Signal *signal = static_cast<VDecAPI11Signal *>(userData);
169     unique_lock<mutex> lock(signal->inMutex_);
170     signal->inIdxQueue_.push(index);
171     signal->inBufferQueue_.push(data);
172     signal->inCond_.notify_all();
173 }
174 
VdecAPI11OutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * data,void * userData)175 void VdecAPI11OutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
176 {
177     if (dec_sample->isFlushing_) {
178         return;
179     }
180     if (dec_sample->outputCallbackFlush && dec_sample->outCount > 1) {
181         dec_sample->Flush();
182         cout << "OH_VideoDecoder_Flush end" << endl;
183         dec_sample->isRunning_.store(false);
184         dec_sample->signal_->inCond_.notify_all();
185         dec_sample->signal_->outCond_.notify_all();
186         return;
187     }
188     if (dec_sample->outputCallbackStop && dec_sample->outCount > 1) {
189         OH_VideoDecoder_Stop(codec);
190         cout << "OH_VideoDecoder_Stop end" << endl;
191         dec_sample->isRunning_.store(false);
192         dec_sample->signal_->inCond_.notify_all();
193         dec_sample->signal_->outCond_.notify_all();
194         return;
195     }
196     VDecAPI11Signal *signal = static_cast<VDecAPI11Signal *>(userData);
197     unique_lock<mutex> lock(signal->outMutex_);
198     signal->outIdxQueue_.push(index);
199     signal->outBufferQueue_.push(data);
200     signal->outCond_.notify_all();
201 }
202 
Flush_buffer()203 void VDecAPI11Sample::Flush_buffer()
204 {
205     unique_lock<mutex> inLock(signal_->inMutex_);
206     clearIntqueue(signal_->inIdxQueue_);
207     std::queue<OH_AVBuffer *> empty;
208     swap(empty, signal_->inBufferQueue_);
209     signal_->inCond_.notify_all();
210     inLock.unlock();
211     unique_lock<mutex> outLock(signal_->outMutex_);
212     clearIntqueue(signal_->outIdxQueue_);
213     clearBufferqueue(signal_->attrQueue_);
214     signal_->outCond_.notify_all();
215     outLock.unlock();
216 }
217 
LoadHashFile()218 std::vector<uint8_t> VDecAPI11Sample::LoadHashFile()
219 {
220     std::ifstream f("/data/test/media/hash_val.json", ios::in);
221     std::vector<uint8_t> ret;
222     if (f) {
223         json data = json::parse(f);
224         filesystem::path filePath = INP_DIR;
225         std::string pixFmt = defualtPixelFormat == AV_PIXEL_FORMAT_NV12 ? "nv12" : "nv21";
226         std::string fileName = filePath.filename();
227         std::string hashValue = data[fileName.c_str()][pixFmt];
228         std::stringstream ss(hashValue);
229         std::string item;
230         while (getline(ss, item, ',')) {
231             if (!item.empty()) {
232                 ret.push_back(stol(item, nullptr, SIXTEEN));
233             }
234         }
235     }
236     return ret;
237 }
238 
DumpHashValue(std::vector<uint8_t> & srcHashVal,uint8_t outputHashVal[])239 static void DumpHashValue(std::vector<uint8_t> &srcHashVal, uint8_t outputHashVal[])
240 {
241     printf("--------------output hash value----------------\n");
242     for (int i = 1; i < SHA512_DIGEST_LENGTH + 1; i++) {
243         printf("%02x,", outputHashVal[i - 1]);
244         if (i % SIXTEEN == 0) {
245             printf("\n");
246         }
247     }
248     printf("--------------standard hash value----------------\n");
249     for (int i = 1; i < SHA512_DIGEST_LENGTH + 1; i++) {
250         printf("%02x,", srcHashVal[i - 1]);
251         if (i % SIXTEEN == 0) {
252             printf("\n");
253         }
254     }
255 }
256 
MdCompare(uint8_t source[])257 bool VDecAPI11Sample::MdCompare(uint8_t source[])
258 {
259     std::vector<uint8_t> srcHashVal = LoadHashFile();
260     DumpHashValue(srcHashVal, source);
261     if (srcHashVal.size() != SHA512_DIGEST_LENGTH) {
262         cout << "get hash value failed, size" << srcHashVal.size() << endl;
263         return false;
264     }
265     for (int32_t i = 0; i < SHA512_DIGEST_LENGTH; i++) {
266         if (source[i] != srcHashVal[i]) {
267             cout << "decoded hash value mismatch" << endl;
268             return false;
269         }
270     }
271     return true;
272 }
273 
HighRand()274 int32_t HighRand()
275 {
276     std::mt19937 rng(std::random_device{}());
277     std::uniform_int_distribution<> dis(MIN_RANGE, MAX_RANGE);
278     int HRand = dis(rng);
279     if (HRand % EVEN_NUMBER != 0) {
280         HRand = HRand + 1;
281     }
282     cout << "HRand is =  " << HRand << endl;
283     return HRand;
284 }
285 
FrameRand()286 int32_t FrameRand()
287 {
288     std::mt19937 rng(std::random_device{}());
289     std::uniform_int_distribution<> dis(MIN_FRANGE, MAX_FRANGE);
290     int FRand = dis(rng);
291     if (FRand % EVEN_NUMBER != 0) {
292         FRand = FRand + 1;
293     }
294     cout << "FRand is =  " << FRand << endl;
295     return FRand;
296 }
297 
WidthRand()298 int32_t WidthRand()
299 {
300     std::mt19937 rng(std::random_device{}());
301     std::uniform_int_distribution<> dis(MIN_RANGE, MAX_RANGE);
302     int WRand = dis(rng);
303     if (WRand % EVEN_NUMBER != 0) {
304         WRand = WRand + 1;
305     }
306     cout << "WRand is =  " << WRand << endl;
307     return WRand;
308 }
309 
GetSystemTimeUs()310 int64_t VDecAPI11Sample::GetSystemTimeUs()
311 {
312     struct timespec now;
313     (void)clock_gettime(CLOCK_BOOTTIME, &now);
314     int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
315     return nanoTime / NANOS_IN_MICRO;
316 }
317 
ConfigureVideoDecoder()318 int32_t VDecAPI11Sample::ConfigureVideoDecoder()
319 {
320     if (autoSwitchSurface) {
321         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
322         if (OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) != AV_ERR_INVALID_STATE) {
323             errCount++;
324         }
325     }
326     OH_AVFormat *format = OH_AVFormat_Create();
327     if (format == nullptr) {
328         cout << "Fatal: Failed to create format" << endl;
329         return AV_ERR_UNKNOWN;
330     }
331     if (maxInputSize != 0) {
332         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, maxInputSize);
333     }
334     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
335     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
336     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defualtPixelFormat);
337     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
338     if (useHDRSource) {
339         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, DEFAULT_PROFILE);
340     }
341     if (NV21_FLAG) {
342         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV21);
343     }
344     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ENABLE_SYNC_MODE, enbleSyncMode);
345     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_DECODER_BLANK_FRAME_ON_SHUTDOWN, enbleBlankFrame);
346     int ret = OH_VideoDecoder_Configure(vdec_, format);
347     OH_AVFormat_Destroy(format);
348     return ret;
349 }
350 
CreateSurface()351 void VDecAPI11Sample::CreateSurface()
352 {
353     cs[0] = Surface::CreateSurfaceAsConsumer();
354     sptr<IBufferConsumerListener> listener = new ConsumerListenerBuffer(cs[0], OUT_DIR);
355     cs[0]->RegisterConsumerListener(listener);
356     auto p = cs[0]->GetProducer();
357     ps[0] = Surface::CreateSurfaceAsProducer(p);
358     nativeWindow[0] = CreateNativeWindowFromSurface(&ps[0]);
359     if (autoSwitchSurface) {
360         cs[1] = Surface::CreateSurfaceAsConsumer();
361         sptr<IBufferConsumerListener> listener2 = new ConsumerListenerBuffer(cs[1], OUT_DIR2);
362         cs[1]->RegisterConsumerListener(listener2);
363         auto p2 = cs[1]->GetProducer();
364         ps[1] = Surface::CreateSurfaceAsProducer(p2);
365         nativeWindow[1] = CreateNativeWindowFromSurface(&ps[1]);
366     }
367 }
368 
RunVideoDec_Surface(string codeName)369 int32_t VDecAPI11Sample::RunVideoDec_Surface(string codeName)
370 {
371     SF_OUTPUT = true;
372     int err = AV_ERR_OK;
373     CreateSurface();
374     if (!nativeWindow[0]) {
375         cout << "Failed to create surface" << endl;
376         return AV_ERR_UNKNOWN;
377     }
378     err = CreateVideoDecoder(codeName);
379     if (err != AV_ERR_OK) {
380         cout << "Failed to create video decoder" << endl;
381         return err;
382     }
383     err = SetVideoDecoderCallback();
384     if (err != AV_ERR_OK) {
385         cout << "Failed to setCallback" << endl;
386         Release();
387         return err;
388     }
389     err = ConfigureVideoDecoder();
390     if (err != AV_ERR_OK) {
391         cout << "Failed to configure video decoder" << endl;
392         Release();
393         return err;
394     }
395     err = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
396     if (err != AV_ERR_OK) {
397         cout << "Failed to set surface" << endl;
398         return err;
399     }
400     err = StartVideoDecoder();
401     if (err != AV_ERR_OK) {
402         cout << "Failed to start video decoder" << endl;
403         Release();
404         return err;
405     }
406     return err;
407 }
408 
RunVideoDec(string codeName)409 int32_t VDecAPI11Sample::RunVideoDec(string codeName)
410 {
411     SF_OUTPUT = false;
412     int err = CreateVideoDecoder(codeName);
413     if (err != AV_ERR_OK) {
414         cout << "Failed to create video decoder" << endl;
415         return err;
416     }
417 
418     err = ConfigureVideoDecoder();
419     if (err != AV_ERR_OK) {
420         cout << "Failed to configure video decoder" << endl;
421         Release();
422         return err;
423     }
424 
425     err = SetVideoDecoderCallback();
426     if (err != AV_ERR_OK) {
427         cout << "Failed to setCallback" << endl;
428         Release();
429         return err;
430     }
431 
432     err = StartVideoDecoder();
433     if (err != AV_ERR_OK) {
434         cout << "Failed to start video decoder" << endl;
435         Release();
436         return err;
437     }
438     return err;
439 }
440 
SetVideoDecoderCallback()441 int32_t VDecAPI11Sample::SetVideoDecoderCallback()
442 {
443     signal_ = new VDecAPI11Signal();
444     if (signal_ == nullptr) {
445         cout << "Failed to new VDecAPI11Signal" << endl;
446         return AV_ERR_UNKNOWN;
447     }
448 
449     cb_.onError = VdecAPI11Error;
450     cb_.onStreamChanged = VdecAPI11FormatChanged;
451     cb_.onNeedInputBuffer = VdecAPI11InputDataReady;
452     cb_.onNewOutputBuffer = VdecAPI11OutputDataReady;
453     return OH_VideoDecoder_RegisterCallback(vdec_, cb_, static_cast<void *>(signal_));
454 }
455 
ReleaseInFile()456 void VDecAPI11Sample::ReleaseInFile()
457 {
458     if (inFile_ != nullptr) {
459         if (inFile_->is_open()) {
460             inFile_->close();
461         }
462         inFile_.reset();
463         inFile_ = nullptr;
464     }
465 }
466 
StopInloop()467 void VDecAPI11Sample::StopInloop()
468 {
469     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
470         unique_lock<mutex> lock(signal_->inMutex_);
471         clearIntqueue(signal_->inIdxQueue_);
472         isRunning_.store(false);
473         signal_->inCond_.notify_all();
474         lock.unlock();
475 
476         inputLoop_->join();
477         inputLoop_.reset();
478     }
479 }
480 
CreateVideoDecoder(string codeName)481 int32_t VDecAPI11Sample::CreateVideoDecoder(string codeName)
482 {
483     vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
484     dec_sample = this;
485     return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
486 }
487 
StartDecoder()488 int32_t VDecAPI11Sample::StartDecoder()
489 {
490     isRunning_.store(true);
491     inFile_ = make_unique<ifstream>();
492     if (inFile_ == nullptr) {
493         isRunning_.store(false);
494         (void)OH_VideoDecoder_Stop(vdec_);
495         return AV_ERR_UNKNOWN;
496     }
497     inFile_->open(INP_DIR, ios::in | ios::binary);
498     if (!inFile_->is_open()) {
499         cout << "failed open file " << INP_DIR << endl;
500         isRunning_.store(false);
501         (void)OH_VideoDecoder_Stop(vdec_);
502         inFile_->close();
503         inFile_.reset();
504         inFile_ = nullptr;
505         return AV_ERR_UNKNOWN;
506     }
507     inputLoop_ = make_unique<thread>(&VDecAPI11Sample::InputFuncTest, this);
508     if (inputLoop_ == nullptr) {
509         cout << "Failed to create input loop" << endl;
510         isRunning_.store(false);
511         (void)OH_VideoDecoder_Stop(vdec_);
512         ReleaseInFile();
513         return AV_ERR_UNKNOWN;
514     }
515     outputLoop_ = make_unique<thread>(&VDecAPI11Sample::OutputFuncTest, this);
516     if (outputLoop_ == nullptr) {
517         cout << "Failed to create output loop" << endl;
518         isRunning_.store(false);
519         (void)OH_VideoDecoder_Stop(vdec_);
520         ReleaseInFile();
521         StopInloop();
522         Release();
523         return AV_ERR_UNKNOWN;
524     }
525     return AV_ERR_OK;
526 }
527 
StartSyncDecoder()528 int32_t VDecAPI11Sample::StartSyncDecoder()
529 {
530     isRunning_.store(true);
531     inFile_ = make_unique<ifstream>();
532     if (inFile_ == nullptr) {
533         isRunning_.store(false);
534         (void)OH_VideoDecoder_Stop(vdec_);
535         return AV_ERR_UNKNOWN;
536     }
537     inFile_->open(INP_DIR, ios::in | ios::binary);
538     if (!inFile_->is_open()) {
539         cout << "failed open file " << INP_DIR << endl;
540         isRunning_.store(false);
541         (void)OH_VideoDecoder_Stop(vdec_);
542         inFile_->close();
543         inFile_.reset();
544         inFile_ = nullptr;
545         return AV_ERR_UNKNOWN;
546     }
547     signal_ = new VDecAPI11Signal();
548     inputLoop_ = make_unique<thread>(&VDecAPI11Sample::SyncInputFunc, this);
549     if (inputLoop_ == nullptr) {
550         cout << "Failed to create input loop" << endl;
551         isRunning_.store(false);
552         (void)OH_VideoDecoder_Stop(vdec_);
553         ReleaseInFile();
554         return AV_ERR_UNKNOWN;
555     }
556     outputLoop_ = make_unique<thread>(&VDecAPI11Sample::SyncOutputFunc, this);
557     if (outputLoop_ == nullptr) {
558         cout << "Failed to create output loop" << endl;
559         isRunning_.store(false);
560         (void)OH_VideoDecoder_Stop(vdec_);
561         ReleaseInFile();
562         StopInloop();
563         Release();
564         return AV_ERR_UNKNOWN;
565     }
566     return AV_ERR_OK;
567 }
568 
StartVideoDecoder()569 int32_t VDecAPI11Sample::StartVideoDecoder()
570 {
571     isRunning_.store(true);
572     if (PREPARE_FLAG) {
573         int res = OH_VideoDecoder_Prepare(vdec_);
574         if (res != AV_ERR_OK) {
575             cout << "Failed to start codec, prepare failed! " << res << endl;
576             isRunning_.store(false);
577             ReleaseInFile();
578             Release();
579             return res;
580         }
581     }
582     int ret = OH_VideoDecoder_Start(vdec_);
583     if (ret != AV_ERR_OK) {
584         cout << "Failed to start codec" << endl;
585         isRunning_.store(false);
586         ReleaseInFile();
587         Release();
588         return ret;
589     }
590     if (enbleSyncMode == 0) {
591         ret = StartDecoder();
592     } else {
593         ret = StartSyncDecoder();
594     }
595     return ret;
596 }
597 
testAPI()598 void VDecAPI11Sample::testAPI()
599 {
600     cs[0] = Surface::CreateSurfaceAsConsumer();
601     sptr<IBufferConsumerListener> listener = new ConsumerListenerBuffer(cs[0], OUT_DIR);
602     cs[0]->RegisterConsumerListener(listener);
603     auto p = cs[0]->GetProducer();
604     ps[0] = Surface::CreateSurfaceAsProducer(p);
605     nativeWindow[0] = CreateNativeWindowFromSurface(&ps[0]);
606     OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
607 
608     OH_VideoDecoder_Prepare(vdec_);
609     OH_VideoDecoder_Start(vdec_);
610 
611     OH_AVFormat *format = OH_AVFormat_Create();
612     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
613     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
614     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
615     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
616     OH_VideoDecoder_SetParameter(vdec_, format);
617     OH_AVFormat_Destroy(format);
618     OH_VideoDecoder_GetOutputDescription(vdec_);
619     OH_VideoDecoder_Flush(vdec_);
620     OH_VideoDecoder_Stop(vdec_);
621     OH_VideoDecoder_Reset(vdec_);
622     bool isvalid = false;
623     OH_VideoDecoder_IsValid(vdec_, &isvalid);
624 }
625 
WaitForEOS()626 void VDecAPI11Sample::WaitForEOS()
627 {
628     if (!AFTER_EOS_DESTORY_CODEC && inputLoop_ && inputLoop_->joinable()) {
629         inputLoop_->join();
630     }
631 
632     if (outputLoop_ && outputLoop_->joinable()) {
633         outputLoop_->join();
634     }
635 }
636 
InFuncTest()637 void VDecAPI11Sample::InFuncTest()
638 {
639     if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
640         REPEAT_START_FLUSH_BEFORE_EOS--;
641         OH_VideoDecoder_Flush(vdec_);
642         Flush_buffer();
643         OH_VideoDecoder_Start(vdec_);
644     }
645     if (REPEAT_START_STOP_BEFORE_EOS > 0) {
646         REPEAT_START_STOP_BEFORE_EOS--;
647         OH_VideoDecoder_Stop(vdec_);
648         Flush_buffer();
649         inFile_->clear();
650         inFile_->seekg(0, ios::beg);
651         OH_VideoDecoder_Start(vdec_);
652     }
653 }
654 
InputFuncTest()655 void VDecAPI11Sample::InputFuncTest()
656 {
657     bool flag = true;
658     while (flag) {
659         if (!isRunning_.load()) {
660             flag = false;
661             break;
662         }
663         InFuncTest();
664         uint32_t index;
665         unique_lock<mutex> lock(signal_->inMutex_);
666         signal_->inCond_.wait(lock, [this]() {
667             if (!isRunning_.load()) {
668                 return true;
669             }
670             return signal_->inIdxQueue_.size() > 0 && !isFlushing_.load();
671         });
672         if (!isRunning_.load()) {
673             flag = false;
674             break;
675         }
676         index = signal_->inIdxQueue_.front();
677         auto buffer = signal_->inBufferQueue_.front();
678         signal_->inIdxQueue_.pop();
679         signal_->inBufferQueue_.pop();
680         if (!inFile_->eof()) {
681             int ret = PushData(index, buffer);
682             if (ret == 1) {
683                 flag = false;
684                 break;
685             }
686         }
687         lock.unlock();
688         if (sleepOnFPS) {
689             usleep(MICRO_IN_SECOND / (int32_t)DEFAULT_FRAME_RATE);
690         }
691     }
692 }
693 
SyncInputFunc()694 void VDecAPI11Sample::SyncInputFunc()
695 {
696     bool flag = true;
697     while (flag) {
698         if (!isRunning_.load()) {
699             flag = false;
700             break;
701         }
702         uint32_t index;
703         if (OH_VideoDecoder_QueryInputBuffer(vdec_, &index, syncInputWaitTime) != AV_ERR_OK) {
704             cout << "OH_VideoDecoder_QueryInputBuffer fail" << endl;
705             continue;
706         }
707         OH_AVBuffer *buffer = OH_VideoDecoder_GetInputBuffer(vdec_, index);
708         if (buffer == nullptr) {
709             cout << "OH_VideoDecoder_GetInputBuffer fail" << endl;
710             errCount = errCount + 1;
711             continue;
712         }
713         if (!inFile_->eof()) {
714             int ret = PushData(index, buffer);
715             if (ret == 1) {
716                 flag = false;
717                 break;
718             }
719         }
720         if (sleepOnFPS) {
721             usleep(MICRO_IN_SECOND / (int32_t)DEFAULT_FRAME_RATE);
722         }
723     }
724 }
725 
PushData(uint32_t index,OH_AVBuffer * buffer)726 int32_t VDecAPI11Sample::PushData(uint32_t index, OH_AVBuffer *buffer)
727 {
728     OH_AVCodecBufferAttr attr;
729     if (BEFORE_EOS_INPUT && frameCount_ > TEN) {
730         SetEOS(index, buffer);
731         return 1;
732     }
733     if (BEFORE_EOS_INPUT_INPUT && frameCount_ > TEN) {
734         memset_s(&attr, sizeof(OH_AVCodecBufferAttr), 0, sizeof(OH_AVCodecBufferAttr));
735         attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
736         BEFORE_EOS_INPUT_INPUT = false;
737     }
738     char ch[4] = {};
739     (void)inFile_->read(ch, START_CODE_SIZE);
740     if (repeatRun && inFile_->eof()) {
741         static uint32_t repeat_count = 0;
742         inFile_->clear();
743         inFile_->seekg(0, ios::beg);
744         cout << "repeat run " << repeat_count << endl;
745         repeat_count++;
746         return 0;
747     }
748     if (inFile_->eof()) {
749         SetEOS(index, buffer);
750         return 1;
751     }
752     uint32_t bufferSize = (uint32_t)(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) | ((ch[1] & 0xFF) << SIXTEEN) |
753                                      ((ch[0] & 0xFF) << TWENTY_FOUR));
754     if (useHDRSource) {
755         uint32_t zero = 0;
756         uint32_t one = 1;
757         uint32_t two = 2;
758         uint32_t three = 3;
759         bufferSize = (uint32_t)(((ch[zero] & 0xFF)) | ((ch[one] & 0xFF) << EIGHT) | ((ch[two] & 0xFF) << SIXTEEN) |
760                                      ((ch[three] & 0xFF) << TWENTY_FOUR));
761     }
762     if (bufferSize >= DEFAULT_WIDTH * DEFAULT_HEIGHT * THREE >> 1) {
763         cout << "read bufferSize abnormal. buffersize = " << bufferSize << endl;
764         return 1;
765     }
766     return SendData(bufferSize, index, buffer);
767 }
768 
CheckAndReturnBufferSize(OH_AVBuffer * buffer)769 int32_t VDecAPI11Sample::CheckAndReturnBufferSize(OH_AVBuffer *buffer)
770 {
771     int32_t size = OH_AVBuffer_GetCapacity(buffer);
772     if ((maxInputSize < 0) && (size < 0)) {
773         errCount++;
774     } else if ((maxInputSize > 0) && (size > SYS_MAX_INPUT_SIZE)) {
775         errCount++;
776     }
777     return size;
778 }
779 
SendData(uint32_t bufferSize,uint32_t index,OH_AVBuffer * buffer)780 uint32_t VDecAPI11Sample::SendData(uint32_t bufferSize, uint32_t index, OH_AVBuffer *buffer)
781 {
782     OH_AVCodecBufferAttr attr;
783     uint8_t *fileBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
784     if (fileBuffer == nullptr) {
785         delete[] fileBuffer;
786         return 0;
787     }
788     if (memcpy_s(fileBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
789         cout << "Fatal: memory copy failed" << endl;
790     }
791     (void)inFile_->read(reinterpret_cast<char*>(fileBuffer) + START_CODE_SIZE, bufferSize);
792     if ((fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == SPS ||
793         (fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == PPS) {
794         attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
795     } else {
796         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
797     }
798     int32_t size = CheckAndReturnBufferSize(buffer);
799     if (size < bufferSize + START_CODE_SIZE) {
800         delete[] fileBuffer;
801         return 0;
802     }
803     uint8_t *avBuffer = OH_AVBuffer_GetAddr(buffer);
804     if (avBuffer == nullptr) {
805         inFile_->clear();
806         inFile_->seekg(0, ios::beg);
807         delete[] fileBuffer;
808         return 0;
809     }
810     if (memcpy_s(avBuffer, size, fileBuffer, bufferSize + START_CODE_SIZE) != EOK) {
811         delete[] fileBuffer;
812         return 0;
813     }
814     int64_t startPts = GetSystemTimeUs();
815     attr.pts = startPts;
816     attr.size = bufferSize + START_CODE_SIZE;
817     attr.offset = 0;
818     if (isRunning_.load()) {
819         OH_AVBuffer_SetBufferAttr(buffer, &attr);
820         OH_VideoDecoder_PushInputBuffer(vdec_, index) == AV_ERR_OK ? (0) : (errCount++);
821         frameCount_ = frameCount_ + 1;
822         outCount = outCount + 1;
823         if (autoSwitchSurface && (frameCount_ % (int32_t)DEFAULT_FRAME_RATE == 0)) {
824             switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
825             OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) == AV_ERR_OK ? (0) : (errCount++);
826         }
827     }
828     delete[] fileBuffer;
829     return 0;
830 }
831 
CheckOutputDescription()832 void VDecAPI11Sample::CheckOutputDescription()
833 {
834     OH_AVFormat *newFormat = OH_VideoDecoder_GetOutputDescription(vdec_);
835     if (newFormat != nullptr) {
836         int32_t cropTop = 0;
837         int32_t cropBottom = 0;
838         int32_t cropLeft = 0;
839         int32_t cropRight = 0;
840         int32_t stride = 0;
841         int32_t sliceHeight = 0;
842         int32_t picWidth = 0;
843         int32_t picHeight = 0;
844         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_TOP, &cropTop);
845         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_BOTTOM, &cropBottom);
846         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_LEFT, &cropLeft);
847         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_RIGHT, &cropRight);
848         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_STRIDE, &stride);
849         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &sliceHeight);
850         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_PIC_WIDTH, &picWidth);
851         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_PIC_HEIGHT, &picHeight);
852         if (cropTop != expectCropTop || cropLeft != expectCropLeft) {
853             std::cout << "cropTop:" << cropTop << " cropBottom:" << cropBottom << " cropLeft:" << cropLeft <<std::endl;
854             errCount++;
855         }
856         if (stride <= 0 || sliceHeight <= 0) {
857             std::cout << "cropRight:" << cropRight << std::endl;
858             std::cout << "stride:" << stride << " sliceHeight:" << sliceHeight << std::endl;
859             errCount++;
860         }
861         if (picWidth != DEFAULT_WIDTH || picHeight != DEFAULT_HEIGHT) {
862             std::cout << "picWidth:" << picWidth << " picHeight:" << picHeight << std::endl;
863             errCount++;
864         }
865     } else {
866         errCount++;
867     }
868     OH_AVFormat_Destroy(newFormat);
869 }
870 
AutoSwitchSurface()871 void VDecAPI11Sample::AutoSwitchSurface()
872 {
873     if (autoSwitchSurface) {
874         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
875         if (OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) != AV_ERR_OK) {
876             errCount++;
877         }
878         OH_AVFormat *format = OH_AVFormat_Create();
879         int32_t angle = DEFAULT_ANGLE * reinterpret_cast<int32_t>(switchSurfaceFlag);
880         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, angle);
881         OH_VideoDecoder_SetParameter(vdec_, format);
882         OH_AVFormat_Destroy(format);
883     }
884 }
885 
CheckAttrFlag(OH_AVCodecBufferAttr attr)886 int32_t VDecAPI11Sample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
887 {
888     if (IS_FIRST_FRAME) {
889         GetStride();
890         IS_FIRST_FRAME = false;
891     }
892     if (needCheckOutputDesc) {
893         CheckOutputDescription();
894         needCheckOutputDesc = false;
895     }
896 
897     if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
898         cout << "AVCODEC_BUFFER_FLAGS_EOS" << endl;
899         AutoSwitchSurface();
900         SHA512_Final(g_md, &g_c);
901         OPENSSL_cleanse(&g_c, sizeof(g_c));
902         if (!SF_OUTPUT) {
903             if (!MdCompare(g_md)) {
904                 errCount++;
905             }
906         }
907         return -1;
908     }
909     if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
910         cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
911         return 0;
912     }
913     outFrameCount = outFrameCount + 1;
914     return 0;
915 }
916 
GetStride()917 void VDecAPI11Sample::GetStride()
918 {
919     OH_AVFormat *format = OH_VideoDecoder_GetOutputDescription(vdec_);
920     int32_t currentWidth = 0;
921     int32_t currentHeight = 0;
922     int32_t stride = 0;
923     int32_t sliceHeight = 0;
924     int32_t picWidth = 0;
925     int32_t picHeight = 0;
926     OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &currentWidth);
927     OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &currentHeight);
928     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &stride);
929     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &sliceHeight);
930     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_WIDTH, &picWidth);
931     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_HEIGHT, &picHeight);
932     dec_sample->DEFAULT_WIDTH = currentWidth;
933     dec_sample->DEFAULT_HEIGHT = currentHeight;
934     dec_sample->stride_ = stride;
935     dec_sample->sliceHeight_ = sliceHeight;
936     dec_sample->picWidth_ = picWidth;
937     dec_sample->picHeight_ = picHeight;
938     OH_AVFormat_Destroy(format);
939 }
940 
OutputFuncTest()941 void VDecAPI11Sample::OutputFuncTest()
942 {
943     FILE *outFile = nullptr;
944     if (outputYuvFlag) {
945         outFile = fopen(OUT_DIR, "wb");
946     }
947     SHA512_Init(&g_c);
948     bool flag = true;
949     while (flag) {
950         if (!isRunning_.load()) {
951             flag = false;
952             break;
953         }
954         OH_AVCodecBufferAttr attr;
955         unique_lock<mutex> lock(signal_->outMutex_);
956         signal_->outCond_.wait(lock, [this]() {
957             if (!isRunning_.load()) {
958                 return true;
959             }
960             return signal_->outIdxQueue_.size() > 0 && !isFlushing_.load();
961         });
962         if (!isRunning_.load()) {
963             flag = false;
964             break;
965         }
966         uint32_t index = signal_->outIdxQueue_.front();
967         OH_AVBuffer *buffer = signal_->outBufferQueue_.front();
968         signal_->outBufferQueue_.pop();
969         signal_->outIdxQueue_.pop();
970         if (OH_AVBuffer_GetBufferAttr(buffer, &attr) != AV_ERR_OK) {
971             errCount = errCount + 1;
972         }
973         if (CheckAttrFlag(attr) == -1) {
974             flag = false;
975             break;
976         }
977         ProcessOutputData(buffer, index);
978         if (outFile != nullptr) {
979             fwrite(OH_AVBuffer_GetAddr(buffer), 1, attr.size, outFile);
980         }
981         lock.unlock();
982         if (errCount > 0) {
983             flag = false;
984             break;
985         }
986     }
987     if (outFile) {
988         (void)fclose(outFile);
989     }
990 }
991 
SyncOutputFunc()992 void VDecAPI11Sample::SyncOutputFunc()
993 {
994     FILE *outFile = nullptr;
995     if (outputYuvFlag) {
996         outFile = fopen(OUT_DIR, "wb");
997     }
998     SHA512_Init(&g_c);
999     bool flag = true;
1000     while (flag) {
1001         if (!isRunning_.load()) {
1002             flag = false;
1003             break;
1004         }
1005         OH_AVCodecBufferAttr attr;
1006         uint32_t index = 0;
1007         if (OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, syncOutputWaitTime) != AV_ERR_OK) {
1008             cout << "OH_VideoDecoder_QueryOutputBuffer fail" << endl;
1009             continue;
1010         }
1011         OH_AVBuffer *buffer = OH_VideoDecoder_GetOutputBuffer(vdec_, index);
1012         if (buffer == nullptr) {
1013             cout << "OH_VideoDecoder_GetOutputBuffer fail" << endl;
1014             errCount = errCount + 1;
1015             continue;
1016         }
1017         if (OH_AVBuffer_GetBufferAttr(buffer, &attr) != AV_ERR_OK) {
1018             errCount = errCount + 1;
1019         }
1020         if (SyncOutputFuncEos(attr, index) != AV_ERR_OK) {
1021             flag = false;
1022             break;
1023         }
1024         ProcessOutputData(buffer, index);
1025         if (outFile != nullptr) {
1026             fwrite(OH_AVBuffer_GetAddr(buffer), 1, attr.size, outFile);
1027         }
1028         if (errCount > 0) {
1029             flag = false;
1030             break;
1031         }
1032     }
1033     if (outFile) {
1034         (void)fclose(outFile);
1035     }
1036 }
1037 
SyncOutputFuncEos(OH_AVCodecBufferAttr attr,uint32_t index)1038 int32_t VDecAPI11Sample::SyncOutputFuncEos(OH_AVCodecBufferAttr attr, uint32_t index)
1039 {
1040     if (CheckAttrFlag(attr) == -1) {
1041         if (queryInputBufferEOS) {
1042             OH_VideoDecoder_QueryInputBuffer(vdec_, &index, 0);
1043             OH_VideoDecoder_QueryInputBuffer(vdec_, &index, MILLION);
1044             OH_VideoDecoder_QueryInputBuffer(vdec_, &index, -1);
1045         }
1046         if (queryOutputBufferEOS) {
1047             OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, 0);
1048             OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, MILLION);
1049             OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, -1);
1050         }
1051         return AV_ERR_UNKNOWN;
1052     }
1053     return AV_ERR_OK;
1054 }
1055 
ProcessOutputData(OH_AVBuffer * buffer,uint32_t index)1056 void VDecAPI11Sample::ProcessOutputData(OH_AVBuffer *buffer, uint32_t index)
1057 {
1058     if (!SF_OUTPUT) {
1059         uint8_t *bufferAddr = OH_AVBuffer_GetAddr(buffer);
1060         uint32_t cropSize = (picWidth_ * picHeight_ * THREE) >> 1;
1061         uint8_t *cropBuffer = new uint8_t[cropSize];
1062         uint8_t *copyPos = cropBuffer;
1063         //copy y
1064         for (int32_t i = 0; i < picHeight_; i++) {
1065             memcpy_s(copyPos, picWidth_, bufferAddr, picWidth_);
1066             bufferAddr += stride_;
1067             copyPos += picWidth_;
1068         }
1069         bufferAddr += (sliceHeight_ - picHeight_) * stride_;
1070         //copy uv
1071         for (int32_t i = 0; i < picHeight_ >> 1; i++) {
1072             memcpy_s(copyPos, picWidth_, bufferAddr, picWidth_);
1073             bufferAddr += stride_;
1074             copyPos += picWidth_;
1075         }
1076         SHA512_Update(&g_c, cropBuffer, cropSize);
1077         delete[] cropBuffer;
1078         if (OH_VideoDecoder_FreeOutputBuffer(vdec_, index) != AV_ERR_OK) {
1079             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
1080             errCount = errCount + 1;
1081         }
1082     } else {
1083         if (rsAtTime) {
1084             RenderOutAtTime(index);
1085         } else {
1086             if (OH_VideoDecoder_RenderOutputBuffer(vdec_, index) != AV_ERR_OK) {
1087                 cout << "Fatal: RenderOutputBuffer fail" << endl;
1088                 errCount = errCount + 1;
1089             }
1090         }
1091     }
1092 }
1093 
RenderOutAtTime(uint32_t index)1094 void VDecAPI11Sample::RenderOutAtTime(uint32_t index)
1095 {
1096     if (isAPI) {
1097         OH_AVErrCode code = OH_VideoDecoder_RenderOutputBufferAtTime(vdec_, index, -100000000);
1098         if (code != AV_ERR_OK) {
1099             cout << "Fatal: RenderOutputBufferAtTime fail" << endl;
1100             errCount = code;
1101         }
1102     } else {
1103         int32_t usTimeNum = 1000;
1104         int32_t msTimeNum = 1000000;
1105         if (renderTimestampNs == 0) {
1106             renderTimestampNs = GetSystemTimeUs() / usTimeNum;
1107         }
1108         renderTimestampNs = renderTimestampNs + (usTimeNum / DEFAULT_FRAME_RATE * msTimeNum);
1109         OH_AVErrCode code = OH_VideoDecoder_RenderOutputBufferAtTime(vdec_, index, renderTimestampNs);
1110         if (code != AV_ERR_OK) {
1111             cout << "Fatal: RenderOutputBufferAtTime fail" << endl;
1112             errCount = code;
1113         }
1114     }
1115 }
1116 
state_EOS()1117 int32_t VDecAPI11Sample::state_EOS()
1118 {
1119     uint32_t index;
1120     unique_lock<mutex> lock(signal_->inMutex_);
1121     signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
1122     index = signal_->inIdxQueue_.front();
1123     signal_->inIdxQueue_.pop();
1124     signal_->inBufferQueue_.pop();
1125     lock.unlock();
1126     return OH_VideoDecoder_PushInputBuffer(vdec_, index);
1127 }
1128 
SetEOS(uint32_t index,OH_AVBuffer * buffer)1129 void VDecAPI11Sample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
1130 {
1131     OH_AVCodecBufferAttr attr;
1132     attr.pts = 0;
1133     attr.size = 0;
1134     attr.offset = 0;
1135     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
1136     OH_AVBuffer_SetBufferAttr(buffer, &attr);
1137     int32_t res = OH_VideoDecoder_PushInputBuffer(vdec_, index);
1138     cout << "OH_VideoDecoder_PushInputBuffer    EOS   res: " << res << endl;
1139 }
1140 
Flush()1141 int32_t VDecAPI11Sample::Flush()
1142 {
1143     isFlushing_.store(true);
1144     unique_lock<mutex> inLock(signal_->inMutex_);
1145     clearIntqueue(signal_->inIdxQueue_);
1146     signal_->inCond_.notify_all();
1147     inLock.unlock();
1148     unique_lock<mutex> outLock(signal_->outMutex_);
1149     clearIntqueue(signal_->outIdxQueue_);
1150     clearBufferqueue(signal_->attrQueue_);
1151     signal_->outCond_.notify_all();
1152     outLock.unlock();
1153     isRunning_.store(false);
1154     int32_t ret = OH_VideoDecoder_Flush(vdec_);
1155     isFlushing_.store(false);
1156     return ret;
1157 }
1158 
Reset()1159 int32_t VDecAPI11Sample::Reset()
1160 {
1161     isRunning_.store(false);
1162     StopInloop();
1163     StopOutloop();
1164     ReleaseInFile();
1165     return OH_VideoDecoder_Reset(vdec_);
1166 }
1167 
Release()1168 int32_t VDecAPI11Sample::Release()
1169 {
1170     int ret = 0;
1171     if (vdec_ != nullptr) {
1172         ret = OH_VideoDecoder_Destroy(vdec_);
1173         vdec_ = nullptr;
1174     }
1175 
1176     if (signal_ != nullptr) {
1177         delete signal_;
1178         signal_ = nullptr;
1179     }
1180     return ret;
1181 }
1182 
Stop()1183 int32_t VDecAPI11Sample::Stop()
1184 {
1185     StopInloop();
1186     StopOutloop();
1187     ReleaseInFile();
1188     return OH_VideoDecoder_Stop(vdec_);
1189 }
1190 
Prepare()1191 int32_t VDecAPI11Sample::Prepare()
1192 {
1193     return OH_VideoDecoder_Prepare(vdec_);
1194 }
1195 
Start()1196 int32_t VDecAPI11Sample::Start()
1197 {
1198     isRunning_.store(true);
1199     return OH_VideoDecoder_Start(vdec_);
1200 }
1201 
StopOutloop()1202 void VDecAPI11Sample::StopOutloop()
1203 {
1204     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
1205         unique_lock<mutex> lock(signal_->outMutex_);
1206         clearIntqueue(signal_->outIdxQueue_);
1207         clearBufferqueue(signal_->attrQueue_);
1208         isRunning_.store(false);
1209         signal_->outCond_.notify_all();
1210         lock.unlock();
1211         outputLoop_->join();
1212         outputLoop_.reset();
1213     }
1214 }
1215 
SetParameter(OH_AVFormat * format)1216 int32_t VDecAPI11Sample::SetParameter(OH_AVFormat *format)
1217 {
1218     return OH_VideoDecoder_SetParameter(vdec_, format);
1219 }
1220 
SwitchSurface()1221 int32_t VDecAPI11Sample::SwitchSurface()
1222 {
1223     int32_t ret = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]);
1224     switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
1225     cout << "manual switch surf "<< switchSurfaceFlag << endl;
1226     return ret;
1227 }
1228 
RepeatCallSetSurface()1229 int32_t VDecAPI11Sample::RepeatCallSetSurface()
1230 {
1231     for (int i = 0; i < REPEAT_CALL_TIME; i++) {
1232         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
1233         int32_t ret = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]);
1234         if (ret != AV_ERR_OK && ret != AV_ERR_OPERATE_NOT_PERMIT && ret != AV_ERR_INVALID_STATE) {
1235             return AV_ERR_OPERATE_NOT_PERMIT;
1236         }
1237     }
1238     return AV_ERR_OK;
1239 }
1240 
DecodeSetSurface()1241 int32_t VDecAPI11Sample::DecodeSetSurface()
1242 {
1243     CreateSurface();
1244     return OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
1245 }