• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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             continue;
705         }
706         OH_AVBuffer *buffer = OH_VideoDecoder_GetInputBuffer(vdec_, index);
707         if (buffer == nullptr) {
708             cout << "OH_VideoDecoder_GetInputBuffer fail" << endl;
709             errCount = errCount + 1;
710             continue;
711         }
712         if (!inFile_->eof()) {
713             int ret = PushData(index, buffer);
714             if (ret == 1) {
715                 flag = false;
716                 break;
717             }
718         }
719         if (sleepOnFPS) {
720             usleep(MICRO_IN_SECOND / (int32_t)DEFAULT_FRAME_RATE);
721         }
722     }
723 }
724 
PushData(uint32_t index,OH_AVBuffer * buffer)725 int32_t VDecAPI11Sample::PushData(uint32_t index, OH_AVBuffer *buffer)
726 {
727     OH_AVCodecBufferAttr attr;
728     if (BEFORE_EOS_INPUT && frameCount_ > TEN) {
729         SetEOS(index, buffer);
730         return 1;
731     }
732     if (BEFORE_EOS_INPUT_INPUT && frameCount_ > TEN) {
733         memset_s(&attr, sizeof(OH_AVCodecBufferAttr), 0, sizeof(OH_AVCodecBufferAttr));
734         attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
735         BEFORE_EOS_INPUT_INPUT = false;
736     }
737     char ch[4] = {};
738     (void)inFile_->read(ch, START_CODE_SIZE);
739     if (repeatRun && inFile_->eof()) {
740         static uint32_t repeat_count = 0;
741         inFile_->clear();
742         inFile_->seekg(0, ios::beg);
743         cout << "repeat run " << repeat_count << endl;
744         repeat_count++;
745         return 0;
746     }
747     if (inFile_->eof()) {
748         SetEOS(index, buffer);
749         return 1;
750     }
751     uint32_t bufferSize = (uint32_t)(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) | ((ch[1] & 0xFF) << SIXTEEN) |
752                                      ((ch[0] & 0xFF) << TWENTY_FOUR));
753     if (useHDRSource) {
754         uint32_t zero = 0;
755         uint32_t one = 1;
756         uint32_t two = 2;
757         uint32_t three = 3;
758         bufferSize = (uint32_t)(((ch[zero] & 0xFF)) | ((ch[one] & 0xFF) << EIGHT) | ((ch[two] & 0xFF) << SIXTEEN) |
759                                      ((ch[three] & 0xFF) << TWENTY_FOUR));
760     }
761     if (bufferSize >= DEFAULT_WIDTH * DEFAULT_HEIGHT * THREE >> 1) {
762         cout << "read bufferSize abnormal. buffersize = " << bufferSize << endl;
763         return 1;
764     }
765     return SendData(bufferSize, index, buffer);
766 }
767 
CheckAndReturnBufferSize(OH_AVBuffer * buffer)768 int32_t VDecAPI11Sample::CheckAndReturnBufferSize(OH_AVBuffer *buffer)
769 {
770     int32_t size = OH_AVBuffer_GetCapacity(buffer);
771     if ((maxInputSize < 0) && (size < 0)) {
772         errCount++;
773     } else if ((maxInputSize > 0) && (size > SYS_MAX_INPUT_SIZE)) {
774         errCount++;
775     }
776     return size;
777 }
778 
SendData(uint32_t bufferSize,uint32_t index,OH_AVBuffer * buffer)779 uint32_t VDecAPI11Sample::SendData(uint32_t bufferSize, uint32_t index, OH_AVBuffer *buffer)
780 {
781     OH_AVCodecBufferAttr attr;
782     uint8_t *fileBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
783     if (fileBuffer == nullptr) {
784         delete[] fileBuffer;
785         return 0;
786     }
787     if (memcpy_s(fileBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
788         cout << "Fatal: memory copy failed" << endl;
789     }
790     (void)inFile_->read(reinterpret_cast<char*>(fileBuffer) + START_CODE_SIZE, bufferSize);
791     if ((fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == SPS ||
792         (fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == PPS) {
793         attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
794     } else {
795         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
796     }
797     int32_t size = CheckAndReturnBufferSize(buffer);
798     if (size < bufferSize + START_CODE_SIZE) {
799         delete[] fileBuffer;
800         return 0;
801     }
802     uint8_t *avBuffer = OH_AVBuffer_GetAddr(buffer);
803     if (avBuffer == nullptr) {
804         inFile_->clear();
805         inFile_->seekg(0, ios::beg);
806         delete[] fileBuffer;
807         return 0;
808     }
809     if (memcpy_s(avBuffer, size, fileBuffer, bufferSize + START_CODE_SIZE) != EOK) {
810         delete[] fileBuffer;
811         return 0;
812     }
813     int64_t startPts = GetSystemTimeUs();
814     attr.pts = startPts;
815     attr.size = bufferSize + START_CODE_SIZE;
816     attr.offset = 0;
817     if (isRunning_.load()) {
818         OH_AVBuffer_SetBufferAttr(buffer, &attr);
819         OH_VideoDecoder_PushInputBuffer(vdec_, index) == AV_ERR_OK ? (0) : (errCount++);
820         frameCount_ = frameCount_ + 1;
821         outCount = outCount + 1;
822         if (autoSwitchSurface && (frameCount_ % (int32_t)DEFAULT_FRAME_RATE == 0)) {
823             switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
824             OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) == AV_ERR_OK ? (0) : (errCount++);
825         }
826     }
827     delete[] fileBuffer;
828     return 0;
829 }
830 
CheckOutputDescription()831 void VDecAPI11Sample::CheckOutputDescription()
832 {
833     OH_AVFormat *newFormat = OH_VideoDecoder_GetOutputDescription(vdec_);
834     if (newFormat != nullptr) {
835         int32_t cropTop = 0;
836         int32_t cropBottom = 0;
837         int32_t cropLeft = 0;
838         int32_t cropRight = 0;
839         int32_t stride = 0;
840         int32_t sliceHeight = 0;
841         int32_t picWidth = 0;
842         int32_t picHeight = 0;
843         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_TOP, &cropTop);
844         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_BOTTOM, &cropBottom);
845         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_LEFT, &cropLeft);
846         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_CROP_RIGHT, &cropRight);
847         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_STRIDE, &stride);
848         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &sliceHeight);
849         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_PIC_WIDTH, &picWidth);
850         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_PIC_HEIGHT, &picHeight);
851         if (cropTop != expectCropTop || cropLeft != expectCropLeft) {
852             std::cout << "cropTop:" << cropTop << " cropBottom:" << cropBottom << " cropLeft:" << cropLeft <<std::endl;
853             errCount++;
854         }
855         if (stride <= 0 || sliceHeight <= 0) {
856             std::cout << "cropRight:" << cropRight << std::endl;
857             std::cout << "stride:" << stride << " sliceHeight:" << sliceHeight << std::endl;
858             errCount++;
859         }
860         if (picWidth != DEFAULT_WIDTH || picHeight != DEFAULT_HEIGHT) {
861             std::cout << "picWidth:" << picWidth << " picHeight:" << picHeight << std::endl;
862             errCount++;
863         }
864     } else {
865         errCount++;
866     }
867     OH_AVFormat_Destroy(newFormat);
868 }
869 
AutoSwitchSurface()870 void VDecAPI11Sample::AutoSwitchSurface()
871 {
872     if (autoSwitchSurface) {
873         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
874         if (OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) != AV_ERR_OK) {
875             errCount++;
876         }
877         OH_AVFormat *format = OH_AVFormat_Create();
878         int32_t angle = DEFAULT_ANGLE * reinterpret_cast<int32_t>(switchSurfaceFlag);
879         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, angle);
880         OH_VideoDecoder_SetParameter(vdec_, format);
881         OH_AVFormat_Destroy(format);
882     }
883 }
884 
CheckAttrFlag(OH_AVCodecBufferAttr attr)885 int32_t VDecAPI11Sample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
886 {
887     if (IS_FIRST_FRAME) {
888         GetStride();
889         IS_FIRST_FRAME = false;
890     }
891     if (needCheckOutputDesc) {
892         CheckOutputDescription();
893         needCheckOutputDesc = false;
894     }
895 
896     if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
897         cout << "AVCODEC_BUFFER_FLAGS_EOS" << endl;
898         AutoSwitchSurface();
899         SHA512_Final(g_md, &g_c);
900         OPENSSL_cleanse(&g_c, sizeof(g_c));
901         if (!SF_OUTPUT) {
902             if (!MdCompare(g_md)) {
903                 errCount++;
904             }
905         }
906         return -1;
907     }
908     if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
909         cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
910         return 0;
911     }
912     outFrameCount = outFrameCount + 1;
913     return 0;
914 }
915 
GetStride()916 void VDecAPI11Sample::GetStride()
917 {
918     OH_AVFormat *format = OH_VideoDecoder_GetOutputDescription(vdec_);
919     int32_t currentWidth = 0;
920     int32_t currentHeight = 0;
921     int32_t stride = 0;
922     int32_t sliceHeight = 0;
923     int32_t picWidth = 0;
924     int32_t picHeight = 0;
925     OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &currentWidth);
926     OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &currentHeight);
927     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &stride);
928     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &sliceHeight);
929     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_WIDTH, &picWidth);
930     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_HEIGHT, &picHeight);
931     dec_sample->DEFAULT_WIDTH = currentWidth;
932     dec_sample->DEFAULT_HEIGHT = currentHeight;
933     dec_sample->stride_ = stride;
934     dec_sample->sliceHeight_ = sliceHeight;
935     dec_sample->picWidth_ = picWidth;
936     dec_sample->picHeight_ = picHeight;
937     OH_AVFormat_Destroy(format);
938 }
939 
OutputFuncTest()940 void VDecAPI11Sample::OutputFuncTest()
941 {
942     FILE *outFile = nullptr;
943     if (outputYuvFlag) {
944         outFile = fopen(OUT_DIR, "wb");
945     }
946     SHA512_Init(&g_c);
947     bool flag = true;
948     while (flag) {
949         if (!isRunning_.load()) {
950             flag = false;
951             break;
952         }
953         OH_AVCodecBufferAttr attr;
954         unique_lock<mutex> lock(signal_->outMutex_);
955         signal_->outCond_.wait(lock, [this]() {
956             if (!isRunning_.load()) {
957                 return true;
958             }
959             return signal_->outIdxQueue_.size() > 0 && !isFlushing_.load();
960         });
961         if (!isRunning_.load()) {
962             flag = false;
963             break;
964         }
965         uint32_t index = signal_->outIdxQueue_.front();
966         OH_AVBuffer *buffer = signal_->outBufferQueue_.front();
967         signal_->outBufferQueue_.pop();
968         signal_->outIdxQueue_.pop();
969         if (OH_AVBuffer_GetBufferAttr(buffer, &attr) != AV_ERR_OK) {
970             errCount = errCount + 1;
971         }
972         if (CheckAttrFlag(attr) == -1) {
973             flag = false;
974             break;
975         }
976         ProcessOutputData(buffer, index);
977         if (outFile != nullptr) {
978             fwrite(OH_AVBuffer_GetAddr(buffer), 1, attr.size, outFile);
979         }
980         lock.unlock();
981         if (errCount > 0) {
982             flag = false;
983             break;
984         }
985     }
986     if (outFile) {
987         (void)fclose(outFile);
988     }
989 }
990 
SyncOutputFunc()991 void VDecAPI11Sample::SyncOutputFunc()
992 {
993     FILE *outFile = nullptr;
994     if (outputYuvFlag) {
995         outFile = fopen(OUT_DIR, "wb");
996     }
997     SHA512_Init(&g_c);
998     bool flag = true;
999     while (flag) {
1000         if (!isRunning_.load()) {
1001             flag = false;
1002             break;
1003         }
1004         OH_AVCodecBufferAttr attr;
1005         uint32_t index = 0;
1006         if (OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, syncOutputWaitTime) != AV_ERR_OK) {
1007             continue;
1008         }
1009         OH_AVBuffer *buffer = OH_VideoDecoder_GetOutputBuffer(vdec_, index);
1010         if (buffer == nullptr) {
1011             cout << "OH_VideoDecoder_GetOutputBuffer fail" << endl;
1012             errCount = errCount + 1;
1013             continue;
1014         }
1015         if (OH_AVBuffer_GetBufferAttr(buffer, &attr) != AV_ERR_OK) {
1016             errCount = errCount + 1;
1017         }
1018         if (SyncOutputFuncEos(attr, index) != AV_ERR_OK) {
1019             flag = false;
1020             break;
1021         }
1022         ProcessOutputData(buffer, index);
1023         if (outFile != nullptr) {
1024             fwrite(OH_AVBuffer_GetAddr(buffer), 1, attr.size, outFile);
1025         }
1026         if (errCount > 0) {
1027             flag = false;
1028             break;
1029         }
1030     }
1031     if (outFile) {
1032         (void)fclose(outFile);
1033     }
1034 }
1035 
SyncOutputFuncEos(OH_AVCodecBufferAttr attr,uint32_t index)1036 int32_t VDecAPI11Sample::SyncOutputFuncEos(OH_AVCodecBufferAttr attr, uint32_t index)
1037 {
1038     if (CheckAttrFlag(attr) == -1) {
1039         if (queryInputBufferEOS) {
1040             OH_VideoDecoder_QueryInputBuffer(vdec_, &index, 0);
1041             OH_VideoDecoder_QueryInputBuffer(vdec_, &index, MILLION);
1042             OH_VideoDecoder_QueryInputBuffer(vdec_, &index, -1);
1043         }
1044         if (queryOutputBufferEOS) {
1045             OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, 0);
1046             OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, MILLION);
1047             OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, -1);
1048         }
1049         return AV_ERR_UNKNOWN;
1050     }
1051     return AV_ERR_OK;
1052 }
1053 
ProcessOutputData(OH_AVBuffer * buffer,uint32_t index)1054 void VDecAPI11Sample::ProcessOutputData(OH_AVBuffer *buffer, uint32_t index)
1055 {
1056     if (!SF_OUTPUT) {
1057         uint8_t *bufferAddr = OH_AVBuffer_GetAddr(buffer);
1058         uint32_t cropSize = (picWidth_ * picHeight_ * THREE) >> 1;
1059         uint8_t *cropBuffer = new uint8_t[cropSize];
1060         uint8_t *copyPos = cropBuffer;
1061         //copy y
1062         for (int32_t i = 0; i < picHeight_; i++) {
1063             memcpy_s(copyPos, picWidth_, bufferAddr, picWidth_);
1064             bufferAddr += stride_;
1065             copyPos += picWidth_;
1066         }
1067         bufferAddr += (sliceHeight_ - picHeight_) * stride_;
1068         //copy uv
1069         for (int32_t i = 0; i < picHeight_ >> 1; i++) {
1070             memcpy_s(copyPos, picWidth_, bufferAddr, picWidth_);
1071             bufferAddr += stride_;
1072             copyPos += picWidth_;
1073         }
1074         SHA512_Update(&g_c, cropBuffer, cropSize);
1075         delete[] cropBuffer;
1076         if (OH_VideoDecoder_FreeOutputBuffer(vdec_, index) != AV_ERR_OK) {
1077             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
1078             errCount = errCount + 1;
1079         }
1080     } else {
1081         if (rsAtTime) {
1082             RenderOutAtTime(index);
1083         } else {
1084             if (OH_VideoDecoder_RenderOutputBuffer(vdec_, index) != AV_ERR_OK) {
1085                 cout << "Fatal: RenderOutputBuffer fail" << endl;
1086                 errCount = errCount + 1;
1087             }
1088         }
1089     }
1090 }
1091 
RenderOutAtTime(uint32_t index)1092 void VDecAPI11Sample::RenderOutAtTime(uint32_t index)
1093 {
1094     if (isAPI) {
1095         OH_AVErrCode code = OH_VideoDecoder_RenderOutputBufferAtTime(vdec_, index, -100000000);
1096         if (code != AV_ERR_OK) {
1097             cout << "Fatal: RenderOutputBufferAtTime fail" << endl;
1098             errCount = code;
1099         }
1100     } else {
1101         int32_t usTimeNum = 1000;
1102         int32_t msTimeNum = 1000000;
1103         if (renderTimestampNs == 0) {
1104             renderTimestampNs = GetSystemTimeUs() / usTimeNum;
1105         }
1106         renderTimestampNs = renderTimestampNs + (usTimeNum / DEFAULT_FRAME_RATE * msTimeNum);
1107         OH_AVErrCode code = OH_VideoDecoder_RenderOutputBufferAtTime(vdec_, index, renderTimestampNs);
1108         if (code != AV_ERR_OK) {
1109             cout << "Fatal: RenderOutputBufferAtTime fail" << endl;
1110             errCount = code;
1111         }
1112     }
1113 }
1114 
state_EOS()1115 int32_t VDecAPI11Sample::state_EOS()
1116 {
1117     uint32_t index;
1118     unique_lock<mutex> lock(signal_->inMutex_);
1119     signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
1120     index = signal_->inIdxQueue_.front();
1121     signal_->inIdxQueue_.pop();
1122     signal_->inBufferQueue_.pop();
1123     lock.unlock();
1124     return OH_VideoDecoder_PushInputBuffer(vdec_, index);
1125 }
1126 
SetEOS(uint32_t index,OH_AVBuffer * buffer)1127 void VDecAPI11Sample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
1128 {
1129     OH_AVCodecBufferAttr attr;
1130     attr.pts = 0;
1131     attr.size = 0;
1132     attr.offset = 0;
1133     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
1134     OH_AVBuffer_SetBufferAttr(buffer, &attr);
1135     int32_t res = OH_VideoDecoder_PushInputBuffer(vdec_, index);
1136     cout << "OH_VideoDecoder_PushInputBuffer    EOS   res: " << res << endl;
1137 }
1138 
Flush()1139 int32_t VDecAPI11Sample::Flush()
1140 {
1141     isFlushing_.store(true);
1142     unique_lock<mutex> inLock(signal_->inMutex_);
1143     clearIntqueue(signal_->inIdxQueue_);
1144     signal_->inCond_.notify_all();
1145     inLock.unlock();
1146     unique_lock<mutex> outLock(signal_->outMutex_);
1147     clearIntqueue(signal_->outIdxQueue_);
1148     clearBufferqueue(signal_->attrQueue_);
1149     signal_->outCond_.notify_all();
1150     outLock.unlock();
1151     isRunning_.store(false);
1152     int32_t ret = OH_VideoDecoder_Flush(vdec_);
1153     isFlushing_.store(false);
1154     return ret;
1155 }
1156 
Reset()1157 int32_t VDecAPI11Sample::Reset()
1158 {
1159     isRunning_.store(false);
1160     StopInloop();
1161     StopOutloop();
1162     ReleaseInFile();
1163     return OH_VideoDecoder_Reset(vdec_);
1164 }
1165 
Release()1166 int32_t VDecAPI11Sample::Release()
1167 {
1168     int ret = 0;
1169     if (vdec_ != nullptr) {
1170         ret = OH_VideoDecoder_Destroy(vdec_);
1171         vdec_ = nullptr;
1172     }
1173 
1174     if (signal_ != nullptr) {
1175         delete signal_;
1176         signal_ = nullptr;
1177     }
1178     return ret;
1179 }
1180 
Stop()1181 int32_t VDecAPI11Sample::Stop()
1182 {
1183     StopInloop();
1184     StopOutloop();
1185     ReleaseInFile();
1186     return OH_VideoDecoder_Stop(vdec_);
1187 }
1188 
Prepare()1189 int32_t VDecAPI11Sample::Prepare()
1190 {
1191     return OH_VideoDecoder_Prepare(vdec_);
1192 }
1193 
Start()1194 int32_t VDecAPI11Sample::Start()
1195 {
1196     isRunning_.store(true);
1197     return OH_VideoDecoder_Start(vdec_);
1198 }
1199 
StopOutloop()1200 void VDecAPI11Sample::StopOutloop()
1201 {
1202     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
1203         unique_lock<mutex> lock(signal_->outMutex_);
1204         clearIntqueue(signal_->outIdxQueue_);
1205         clearBufferqueue(signal_->attrQueue_);
1206         isRunning_.store(false);
1207         signal_->outCond_.notify_all();
1208         lock.unlock();
1209         outputLoop_->join();
1210         outputLoop_.reset();
1211     }
1212 }
1213 
SetParameter(OH_AVFormat * format)1214 int32_t VDecAPI11Sample::SetParameter(OH_AVFormat *format)
1215 {
1216     return OH_VideoDecoder_SetParameter(vdec_, format);
1217 }
1218 
SwitchSurface()1219 int32_t VDecAPI11Sample::SwitchSurface()
1220 {
1221     int32_t ret = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]);
1222     switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
1223     cout << "manual switch surf "<< switchSurfaceFlag << endl;
1224     return ret;
1225 }
1226 
RepeatCallSetSurface()1227 int32_t VDecAPI11Sample::RepeatCallSetSurface()
1228 {
1229     for (int i = 0; i < REPEAT_CALL_TIME; i++) {
1230         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
1231         int32_t ret = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]);
1232         if (ret != AV_ERR_OK && ret != AV_ERR_OPERATE_NOT_PERMIT && ret != AV_ERR_INVALID_STATE) {
1233             return AV_ERR_OPERATE_NOT_PERMIT;
1234         }
1235     }
1236     return AV_ERR_OK;
1237 }
1238 
DecodeSetSurface()1239 int32_t VDecAPI11Sample::DecodeSetSurface()
1240 {
1241     CreateSurface();
1242     return OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
1243 }