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 <filesystem>
18 #include <utility>
19 #include <vector>
20 #include <string>
21 #include <sstream>
22 #include "openssl/crypto.h"
23 #include "openssl/sha.h"
24 #include "videodec_sample.h"
25 #include "nlohmann/json.hpp"
26 using namespace OHOS;
27 using namespace OHOS::Media;
28 using namespace std;
29 using namespace nlohmann;
30 namespace {
31 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
32 constexpr int64_t MICRO_IN_SECOND = 1000000L;
33 constexpr int64_t NANOS_IN_MICRO = 1000L;
34 constexpr int32_t THREE = 3;
35 constexpr int32_t EIGHT = 8;
36 constexpr int32_t TEN = 10;
37 constexpr int32_t SIXTEEN = 16;
38 constexpr int32_t TWENTY_FOUR = 24;
39 constexpr uint8_t H264_NALU_TYPE = 0x1f;
40 constexpr uint32_t START_CODE_SIZE = 4;
41 constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
42 constexpr uint8_t SPS = 7;
43 constexpr uint8_t PPS = 8;
44 constexpr int32_t RES_CHANGE_TIME = 4;
45 constexpr int32_t CROP_INFO_SIZE = 2;
46 constexpr int32_t CROP_INFO[RES_CHANGE_TIME][CROP_INFO_SIZE] = {{621, 1103},
47     {1079, 1919}, {719, 1279}, {855, 1919}};
48 constexpr int32_t CROP_BOTTOM = 0;
49 constexpr int32_t CROP_RIGHT = 1;
50 constexpr int32_t DEFAULT_ANGLE = 90;
51 constexpr int32_t SYS_MAX_INPUT_SIZE = 1024 * 1024 * 24;
52 SHA512_CTX c;
53 uint8_t g_md[SHA512_DIGEST_LENGTH];
54 VDecNdkSample *dec_sample = nullptr;
55 
clearIntqueue(std::queue<uint32_t> & q)56 void clearIntqueue(std::queue<uint32_t> &q)
57 {
58     std::queue<uint32_t> empty;
59     swap(empty, q);
60 }
61 
clearBufferqueue(std::queue<OH_AVCodecBufferAttr> & q)62 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
63 {
64     std::queue<OH_AVCodecBufferAttr> empty;
65     swap(empty, q);
66 }
67 } // namespace
68 
69 class TestConsumerListener : public IBufferConsumerListener {
70 public:
TestConsumerListener(sptr<Surface> cs,std::string_view name)71     TestConsumerListener(sptr<Surface> cs, std::string_view name) : cs(cs) {};
~TestConsumerListener()72     ~TestConsumerListener() {}
OnBufferAvailable()73     void OnBufferAvailable() override
74     {
75         sptr<SurfaceBuffer> buffer;
76         int32_t flushFence;
77         cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
78 
79         cs->ReleaseBuffer(buffer, -1);
80     }
81 
82 private:
83     int64_t timestamp = 0;
84     Rect damage = {};
85     sptr<Surface> cs {nullptr};
86 };
87 
~VDecNdkSample()88 VDecNdkSample::~VDecNdkSample()
89 {
90     for (int i = 0; i < MAX_SURF_NUM; i++) {
91         if (nativeWindow[i]) {
92             OH_NativeWindow_DestroyNativeWindow(nativeWindow[i]);
93             nativeWindow[i] = nullptr;
94         }
95     }
96     Stop();
97     Release();
98 }
99 
VdecError(OH_AVCodec * codec,int32_t errorCode,void * userData)100 void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
101 {
102     cout << "Error errorCode=" << errorCode << endl;
103 }
104 
VdecFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)105 void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
106 {
107     int32_t current_width = 0;
108     int32_t current_height = 0;
109     int32_t stride = 0;
110     int32_t sliceHeight = 0;
111     int32_t picWidth = 0;
112     int32_t picHeight = 0;
113     OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, &current_width);
114     OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, &current_height);
115     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &stride);
116     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &sliceHeight);
117     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_WIDTH, &picWidth);
118     OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_PIC_HEIGHT, &picHeight);
119     dec_sample->DEFAULT_WIDTH = current_width;
120     dec_sample->DEFAULT_HEIGHT = current_height;
121     dec_sample->stride_ = stride;
122     dec_sample->sliceHeight_ = sliceHeight;
123     dec_sample->picWidth_ = picWidth;
124     dec_sample->picHeight_ = picHeight;
125     if (dec_sample->isResChangeStream) {
126         static int32_t resCount = 0;
127         int32_t cropBottom = 0;
128         int32_t cropRight = 0;
129         OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_CROP_BOTTOM, &cropBottom);
130         OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_CROP_RIGHT, &cropRight);
131 
132         if (cropBottom != CROP_INFO[resCount][CROP_BOTTOM] || cropRight != CROP_INFO[resCount][CROP_RIGHT]) {
133             dec_sample->errCount++;
134         }
135         if (stride <= 0 || sliceHeight <= 0) {
136             dec_sample->errCount++;
137         }
138         resCount++;
139     }
140 }
141 
VdecInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)142 void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
143 {
144     if (dec_sample->isFlushing_) {
145         return;
146     }
147     if (dec_sample->inputCallbackFlush && dec_sample->outCount > 1) {
148         dec_sample->Flush();
149         cout << "OH_VideoDecoder_Flush end" << endl;
150         dec_sample->isRunning_.store(false);
151         dec_sample->signal_->inCond_.notify_all();
152         dec_sample->signal_->outCond_.notify_all();
153         return;
154     }
155     if (dec_sample->inputCallbackStop && dec_sample->outCount > 1) {
156         OH_VideoDecoder_Stop(codec);
157         cout << "OH_VideoDecoder_Stop end" << endl;
158         dec_sample->isRunning_.store(false);
159         dec_sample->signal_->inCond_.notify_all();
160         dec_sample->signal_->outCond_.notify_all();
161         return;
162     }
163     VDecSignal *signal = static_cast<VDecSignal *>(userData);
164     unique_lock<mutex> lock(signal->inMutex_);
165     signal->inIdxQueue_.push(index);
166     signal->inBufferQueue_.push(data);
167     signal->inCond_.notify_all();
168 }
169 
VdecOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)170 void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
171                          void *userData)
172 {
173     if (dec_sample->isFlushing_) {
174         return;
175     }
176     if (dec_sample->outputCallbackFlush && dec_sample->outCount > 1) {
177         dec_sample->Flush();
178         cout << "OH_VideoDecoder_Flush end" << endl;
179         dec_sample->isRunning_.store(false);
180         dec_sample->signal_->inCond_.notify_all();
181         dec_sample->signal_->outCond_.notify_all();
182         return;
183     }
184     if (dec_sample->outputCallbackStop && dec_sample->outCount > 1) {
185         OH_VideoDecoder_Stop(codec);
186         cout << "OH_VideoDecoder_Stop end" << endl;
187         dec_sample->isRunning_.store(false);
188         dec_sample->signal_->inCond_.notify_all();
189         dec_sample->signal_->outCond_.notify_all();
190         return;
191     }
192     VDecSignal *signal = static_cast<VDecSignal *>(userData);
193     unique_lock<mutex> lock(signal->outMutex_);
194     signal->outIdxQueue_.push(index);
195     signal->attrQueue_.push(*attr);
196     signal->outBufferQueue_.push(data);
197     signal->outCond_.notify_all();
198 }
199 
Flush_buffer()200 void VDecNdkSample::Flush_buffer()
201 {
202     unique_lock<mutex> inLock(signal_->inMutex_);
203     clearIntqueue(signal_->inIdxQueue_);
204     std::queue<OH_AVMemory *> empty;
205     swap(empty, signal_->inBufferQueue_);
206     signal_->inCond_.notify_all();
207     inLock.unlock();
208     unique_lock<mutex> outLock(signal_->outMutex_);
209     clearIntqueue(signal_->outIdxQueue_);
210     clearBufferqueue(signal_->attrQueue_);
211     signal_->outCond_.notify_all();
212     outLock.unlock();
213 }
214 
find_files(const std::string & dir_path,const std::string & extension)215 std::vector<std::string> find_files(const std::string& dir_path, const std::string& extension)
216 {
217     std::vector<std::string> found_files;
218     for (const auto& entry : std::filesystem::directory_iterator(dir_path)) {
219         if (entry.is_regular_file() && entry.path().extension() == extension) {
220             found_files.push_back(entry.path().c_str());
221         }
222     }
223     return found_files;
224 }
225 
LoadHashFile()226 std::vector<uint8_t> VDecNdkSample::LoadHashFile()
227 {
228     std::ifstream f("/data/test/media/hash_val.json", ios::in);
229     std::vector<uint8_t> ret;
230     if (f) {
231         json data = json::parse(f);
232         filesystem::path filePath = INP_DIR;
233         std::string pixFmt = defualtPixelFormat == AV_PIXEL_FORMAT_NV12 ? "nv12" : "nv21";
234         std::string fileName = filePath.filename();
235         std::string hashValue = data[fileName.c_str()][pixFmt];
236         std::stringstream ss(hashValue);
237         std::string item;
238         while (getline(ss, item, ',')) {
239             if (!item.empty()) {
240                 ret.push_back(stol(item, nullptr, SIXTEEN));
241             }
242         }
243     }
244     return ret;
245 }
246 
DumpHashValue(std::vector<uint8_t> & srcHashVal,uint8_t outputHashVal[])247 static void DumpHashValue(std::vector<uint8_t> &srcHashVal, uint8_t outputHashVal[])
248 {
249     printf("--------------output hash value----------------\n");
250     for (int i = 1; i < SHA512_DIGEST_LENGTH + 1; i++) {
251         printf("%02x, ", outputHashVal[i - 1]);
252         if (i % SIXTEEN == 0) {
253             printf("\n");
254         }
255     }
256     printf("--------------standard hash value----------------\n");
257     for (int i = 1; i < SHA512_DIGEST_LENGTH + 1; i++) {
258         printf("%02x, ", srcHashVal[i - 1]);
259         if (i % SIXTEEN == 0) {
260             printf("\n");
261         }
262     }
263 }
264 
MdCompare(uint8_t source[])265 bool VDecNdkSample::MdCompare(uint8_t source[])
266 {
267     std::vector<uint8_t> srcHashVal = LoadHashFile();
268     DumpHashValue(srcHashVal, source);
269     if (srcHashVal.size() != SHA512_DIGEST_LENGTH) {
270         cout << "get hash value failed, size" << srcHashVal.size() << endl;
271         return false;
272     }
273     for (int32_t i = 0; i < SHA512_DIGEST_LENGTH; i++) {
274         if (source[i] != srcHashVal[i]) {
275             cout << "decoded hash value mismatch" << endl;
276             return false;
277         }
278     }
279     return true;
280 }
281 
282 
GetSystemTimeUs()283 int64_t VDecNdkSample::GetSystemTimeUs()
284 {
285     struct timespec now;
286     (void)clock_gettime(CLOCK_BOOTTIME, &now);
287     int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
288     return nanoTime / NANOS_IN_MICRO;
289 }
290 
ConfigureVideoDecoder()291 int32_t VDecNdkSample::ConfigureVideoDecoder()
292 {
293     if (autoSwitchSurface) {
294         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
295         if (OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) != AV_ERR_INVALID_STATE) {
296             errCount++;
297         }
298     }
299     OH_AVFormat *format = OH_AVFormat_Create();
300     if (format == nullptr) {
301         cout << "Fatal: Failed to create format" << endl;
302         return AV_ERR_UNKNOWN;
303     }
304     if (maxInputSize != 0) {
305         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, maxInputSize);
306     }
307     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
308     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
309     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defualtPixelFormat);
310     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
311     int ret = OH_VideoDecoder_Configure(vdec_, format);
312     OH_AVFormat_Destroy(format);
313     return ret;
314 }
315 
CreateSurface()316 void VDecNdkSample::CreateSurface()
317 {
318     cs[0] = Surface::CreateSurfaceAsConsumer();
319     sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs[0], OUT_DIR);
320     cs[0]->RegisterConsumerListener(listener);
321     auto p = cs[0]->GetProducer();
322     ps[0] = Surface::CreateSurfaceAsProducer(p);
323     nativeWindow[0] = CreateNativeWindowFromSurface(&ps[0]);
324     if (autoSwitchSurface)  {
325         cs[1] = Surface::CreateSurfaceAsConsumer();
326         sptr<IBufferConsumerListener> listener2 = new TestConsumerListener(cs[1], OUT_DIR2);
327         cs[1]->RegisterConsumerListener(listener2);
328         auto p2 = cs[1]->GetProducer();
329         ps[1] = Surface::CreateSurfaceAsProducer(p2);
330         nativeWindow[1] = CreateNativeWindowFromSurface(&ps[1]);
331     }
332 }
333 
RunVideoDec_Surface(string codeName)334 int32_t VDecNdkSample::RunVideoDec_Surface(string codeName)
335 {
336     SF_OUTPUT = true;
337     int err = AV_ERR_OK;
338     CreateSurface();
339     if (!nativeWindow[0]) {
340         cout << "Failed to create surface" << endl;
341         return AV_ERR_UNKNOWN;
342     }
343     err = CreateVideoDecoder(codeName);
344     if (err != AV_ERR_OK) {
345         cout << "Failed to create video decoder" << endl;
346         return err;
347     }
348     err = SetVideoDecoderCallback();
349     if (err != AV_ERR_OK) {
350         cout << "Failed to setCallback" << endl;
351         Release();
352         return err;
353     }
354     err = ConfigureVideoDecoder();
355     if (err != AV_ERR_OK) {
356         cout << "Failed to configure video decoder" << endl;
357         Release();
358         return err;
359     }
360     err = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
361     if (err != AV_ERR_OK) {
362         cout << "Failed to set surface" << endl;
363         return err;
364     }
365     err = StartVideoDecoder();
366     if (err != AV_ERR_OK) {
367         cout << "Failed to start video decoder" << endl;
368         Release();
369         return err;
370     }
371     return err;
372 }
373 
RunVideoDec(string codeName)374 int32_t VDecNdkSample::RunVideoDec(string codeName)
375 {
376     SF_OUTPUT = false;
377     int err = CreateVideoDecoder(codeName);
378     if (err != AV_ERR_OK) {
379         cout << "Failed to create video decoder" << endl;
380         return err;
381     }
382 
383     err = ConfigureVideoDecoder();
384     if (err != AV_ERR_OK) {
385         cout << "Failed to configure video decoder" << endl;
386         Release();
387         return err;
388     }
389 
390     err = SetVideoDecoderCallback();
391     if (err != AV_ERR_OK) {
392         cout << "Failed to setCallback" << endl;
393         Release();
394         return err;
395     }
396 
397     err = StartVideoDecoder();
398     if (err != AV_ERR_OK) {
399         cout << "Failed to start video decoder" << endl;
400         Release();
401         return err;
402     }
403     return err;
404 }
405 
SetVideoDecoderCallback()406 int32_t VDecNdkSample::SetVideoDecoderCallback()
407 {
408     signal_ = new VDecSignal();
409     if (signal_ == nullptr) {
410         cout << "Failed to new VDecSignal" << endl;
411         return AV_ERR_UNKNOWN;
412     }
413 
414     cb_.onError = VdecError;
415     cb_.onStreamChanged = VdecFormatChanged;
416     cb_.onNeedInputData = VdecInputDataReady;
417     cb_.onNeedOutputData = VdecOutputDataReady;
418     return OH_VideoDecoder_SetCallback(vdec_, cb_, static_cast<void *>(signal_));
419 }
420 
ReleaseInFile()421 void VDecNdkSample::ReleaseInFile()
422 {
423     if (inFile_ != nullptr) {
424         if (inFile_->is_open()) {
425             inFile_->close();
426         }
427         inFile_.reset();
428         inFile_ = nullptr;
429     }
430 }
431 
StopInloop()432 void VDecNdkSample::StopInloop()
433 {
434     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
435         unique_lock<mutex> lock(signal_->inMutex_);
436         clearIntqueue(signal_->inIdxQueue_);
437         isRunning_.store(false);
438         signal_->inCond_.notify_all();
439         lock.unlock();
440 
441         inputLoop_->join();
442         inputLoop_.reset();
443     }
444 }
445 
CreateVideoDecoder(string codeName)446 int32_t VDecNdkSample::CreateVideoDecoder(string codeName)
447 {
448     vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
449     dec_sample = this;
450     return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
451 }
452 
StartVideoDecoder()453 int32_t VDecNdkSample::StartVideoDecoder()
454 {
455     isRunning_.store(true);
456     int ret = OH_VideoDecoder_Start(vdec_);
457     if (ret != AV_ERR_OK) {
458         cout << "Failed to start codec" << endl;
459         isRunning_.store(false);
460         ReleaseInFile();
461         Release();
462         return ret;
463     }
464     inFile_ = make_unique<ifstream>();
465     if (inFile_ == nullptr) {
466         isRunning_.store(false);
467         (void)OH_VideoDecoder_Stop(vdec_);
468         return AV_ERR_UNKNOWN;
469     }
470     inFile_->open(INP_DIR, ios::in | ios::binary);
471     if (!inFile_->is_open()) {
472         cout << "failed open file " << INP_DIR << endl;
473         isRunning_.store(false);
474         (void)OH_VideoDecoder_Stop(vdec_);
475         inFile_->close();
476         inFile_.reset();
477         inFile_ = nullptr;
478         return AV_ERR_UNKNOWN;
479     }
480 
481     inputLoop_ = make_unique<thread>(&VDecNdkSample::InputFuncTest, this);
482     if (inputLoop_ == nullptr) {
483         cout << "Failed to create input loop" << endl;
484         isRunning_.store(false);
485         (void)OH_VideoDecoder_Stop(vdec_);
486         ReleaseInFile();
487         return AV_ERR_UNKNOWN;
488     }
489     outputLoop_ = make_unique<thread>(&VDecNdkSample::OutputFuncTest, this);
490     if (outputLoop_ == nullptr) {
491         cout << "Failed to create output loop" << endl;
492         isRunning_.store(false);
493         (void)OH_VideoDecoder_Stop(vdec_);
494         ReleaseInFile();
495         StopInloop();
496         Release();
497         return AV_ERR_UNKNOWN;
498     }
499 
500     return AV_ERR_OK;
501 }
502 
testAPI()503 void VDecNdkSample::testAPI()
504 {
505     cs[0] = Surface::CreateSurfaceAsConsumer();
506     sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs[0], OUT_DIR);
507     cs[0]->RegisterConsumerListener(listener);
508     auto p = cs[0]->GetProducer();
509     ps[0] = Surface::CreateSurfaceAsProducer(p);
510     nativeWindow[0] = CreateNativeWindowFromSurface(&ps[0]);
511     OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
512 
513     OH_VideoDecoder_Prepare(vdec_);
514     OH_VideoDecoder_Start(vdec_);
515 
516     OH_AVFormat *format = OH_AVFormat_Create();
517     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
518     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
519     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
520     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
521     OH_VideoDecoder_SetParameter(vdec_, format);
522     OH_AVFormat_Destroy(format);
523     OH_VideoDecoder_GetOutputDescription(vdec_);
524     OH_VideoDecoder_Flush(vdec_);
525     OH_VideoDecoder_Stop(vdec_);
526     OH_VideoDecoder_Reset(vdec_);
527     bool isvalid = false;
528     OH_VideoDecoder_IsValid(vdec_, &isvalid);
529 }
530 
WaitForEOS()531 void VDecNdkSample::WaitForEOS()
532 {
533     if (!AFTER_EOS_DESTORY_CODEC && inputLoop_ && inputLoop_->joinable()) {
534         inputLoop_->join();
535     }
536 
537     if (outputLoop_ && outputLoop_->joinable()) {
538         outputLoop_->join();
539     }
540 }
541 
InputFuncTest()542 void VDecNdkSample::InputFuncTest()
543 {
544     while (true) {
545         if (!isRunning_.load()) {
546             break;
547         }
548         if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
549             REPEAT_START_FLUSH_BEFORE_EOS--;
550             OH_VideoDecoder_Flush(vdec_);
551             Flush_buffer();
552             OH_VideoDecoder_Start(vdec_);
553         }
554         if (REPEAT_START_STOP_BEFORE_EOS > 0) {
555             REPEAT_START_STOP_BEFORE_EOS--;
556             OH_VideoDecoder_Stop(vdec_);
557             Flush_buffer();
558             inFile_->clear();
559             inFile_->seekg(0, ios::beg);
560             OH_VideoDecoder_Start(vdec_);
561         }
562         uint32_t index;
563         unique_lock<mutex> lock(signal_->inMutex_);
564         signal_->inCond_.wait(lock, [this]() {
565             if (!isRunning_.load()) {
566                 return true;
567             }
568             return signal_->inIdxQueue_.size() > 0 && !isFlushing_.load();
569         });
570         if (!isRunning_.load()) {
571             break;
572         }
573         index = signal_->inIdxQueue_.front();
574         auto buffer = signal_->inBufferQueue_.front();
575 
576         signal_->inIdxQueue_.pop();
577         signal_->inBufferQueue_.pop();
578         if (!inFile_->eof()) {
579             int ret = PushData(index, buffer);
580             if (ret == 1) {
581                 break;
582             }
583         }
584         lock.unlock();
585         if (sleepOnFPS) {
586             usleep(MICRO_IN_SECOND / (int32_t)DEFAULT_FRAME_RATE);
587         }
588     }
589 }
590 
PushData(uint32_t index,OH_AVMemory * buffer)591 int32_t VDecNdkSample::PushData(uint32_t index, OH_AVMemory *buffer)
592 {
593     static uint32_t repeat_count = 0;
594     OH_AVCodecBufferAttr attr;
595     if (BEFORE_EOS_INPUT && frameCount_ > TEN) {
596         SetEOS(index);
597         return 1;
598     }
599     if (BEFORE_EOS_INPUT_INPUT && frameCount_ > TEN) {
600         memset_s(&attr, sizeof(OH_AVCodecBufferAttr), 0, sizeof(OH_AVCodecBufferAttr));
601         attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
602         BEFORE_EOS_INPUT_INPUT = false;
603     }
604     char ch[4] = {};
605     (void)inFile_->read(ch, START_CODE_SIZE);
606     if (repeatRun && inFile_->eof()) {
607         inFile_->clear();
608         inFile_->seekg(0, ios::beg);
609         cout << "repeat run " << repeat_count << endl;
610         repeat_count++;
611         return 0;
612     }
613     if (inFile_->eof()) {
614         SetEOS(index);
615         return 1;
616     }
617     uint32_t bufferSize = (uint32_t)(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) | ((ch[1] & 0xFF) << SIXTEEN) |
618                                      ((ch[0] & 0xFF) << TWENTY_FOUR));
619     if (bufferSize >= DEFAULT_WIDTH * DEFAULT_HEIGHT * THREE >> 1) {
620         cout << "read bufferSize abnormal. buffersize = " << bufferSize << endl;
621         return 1;
622     }
623 
624     return SendData(bufferSize, index, buffer);
625 }
626 
CheckAndReturnBufferSize(OH_AVMemory * buffer)627 int32_t VDecNdkSample::CheckAndReturnBufferSize(OH_AVMemory *buffer)
628 {
629     int32_t size = OH_AVMemory_GetSize(buffer);
630     if ((maxInputSize < 0) && (size < 0)) {
631         errCount++;
632     } else if ((maxInputSize > 0) && (size > SYS_MAX_INPUT_SIZE)) {
633         errCount++;
634     }
635     return size;
636 }
637 
SendData(uint32_t bufferSize,uint32_t index,OH_AVMemory * buffer)638 uint32_t VDecNdkSample::SendData(uint32_t bufferSize, uint32_t index, OH_AVMemory *buffer)
639 {
640     OH_AVCodecBufferAttr attr;
641     uint8_t *fileBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
642     if (fileBuffer == nullptr) {
643         delete[] fileBuffer;
644         return 0;
645     }
646     if (memcpy_s(fileBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
647         cout << "Fatal: memory copy failed" << endl;
648     }
649     (void)inFile_->read(reinterpret_cast<char*>(fileBuffer) + START_CODE_SIZE, bufferSize);
650     if ((fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == SPS ||
651         (fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == PPS) {
652         attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
653     } else {
654         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
655     }
656     int32_t size = CheckAndReturnBufferSize(buffer);
657     if (size < bufferSize + START_CODE_SIZE) {
658         delete[] fileBuffer;
659         return 0;
660     }
661     uint8_t *avBuffer = OH_AVMemory_GetAddr(buffer);
662     if (avBuffer == nullptr) {
663         cout << "avBuffer == nullptr" << endl;
664         inFile_->clear();
665         inFile_->seekg(0, ios::beg);
666         delete[] fileBuffer;
667         return 0;
668     }
669     if (memcpy_s(avBuffer, size, fileBuffer, bufferSize + START_CODE_SIZE) != EOK) {
670         delete[] fileBuffer;
671         return 0;
672     }
673     int64_t startPts = GetSystemTimeUs();
674     attr.pts = startPts;
675     attr.size = bufferSize + START_CODE_SIZE;
676     attr.offset = 0;
677     if (isRunning_.load()) {
678         OH_VideoDecoder_PushInputData(vdec_, index, attr) == AV_ERR_OK ? (0) : (errCount++);
679         frameCount_ = frameCount_ + 1;
680         outCount = outCount + 1;
681         if (autoSwitchSurface && (frameCount_ % (int32_t)DEFAULT_FRAME_RATE == 0)) {
682             switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
683             OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) == AV_ERR_OK ? (0) : (errCount++);
684         }
685     }
686     delete[] fileBuffer;
687     return 0;
688 }
689 
CheckOutputDescription()690 void VDecNdkSample::CheckOutputDescription()
691 {
692     OH_AVFormat *newFormat = OH_VideoDecoder_GetOutputDescription(vdec_);
693     if (newFormat != nullptr) {
694         int32_t picWidth = 0;
695         int32_t picHeight = 0;
696         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_PIC_WIDTH, &picWidth);
697         OH_AVFormat_GetIntValue(newFormat, OH_MD_KEY_VIDEO_PIC_HEIGHT, &picHeight);
698         if (picWidth != DEFAULT_WIDTH || picHeight != DEFAULT_HEIGHT) {
699             std::cout << "DEFAULT_WIDTH:" << picWidth << " DEFAULT_HEIGHT:" << picHeight << std::endl;
700             errCount++;
701         }
702     } else {
703         std::cout << "errCount newFormat == nullptr: " << errCount << std::endl;
704         errCount++;
705     }
706     OH_AVFormat_Destroy(newFormat);
707 }
708 
AutoSwitchSurface()709 void VDecNdkSample::AutoSwitchSurface()
710 {
711     if (autoSwitchSurface) {
712         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
713         if (OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]) != AV_ERR_OK) {
714             errCount++;
715         }
716         OH_AVFormat *format = OH_AVFormat_Create();
717         int32_t angle = DEFAULT_ANGLE * reinterpret_cast<int32_t>(switchSurfaceFlag);
718         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, angle);
719         OH_VideoDecoder_SetParameter(vdec_, format);
720         OH_AVFormat_Destroy(format);
721     }
722 }
723 
OutputFuncTest()724 void VDecNdkSample::OutputFuncTest()
725 {
726     SHA512_Init(&c);
727     while (true) {
728         if (!isRunning_.load()) {
729             break;
730         }
731         OH_AVCodecBufferAttr attr;
732         uint32_t index;
733         unique_lock<mutex> lock(signal_->outMutex_);
734         signal_->outCond_.wait(lock, [this]() {
735             if (!isRunning_.load()) {
736                 return true;
737             }
738             return signal_->outIdxQueue_.size() > 0 && !isFlushing_.load();
739         });
740         if (!isRunning_.load()) {
741             break;
742         }
743         index = signal_->outIdxQueue_.front();
744         attr = signal_->attrQueue_.front();
745         OH_AVMemory *buffer = signal_->outBufferQueue_.front();
746         signal_->outBufferQueue_.pop();
747         signal_->outIdxQueue_.pop();
748         signal_->attrQueue_.pop();
749         if (dec_sample->checkOutPut) {
750             CheckOutputDescription();
751         }
752         if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
753             AutoSwitchSurface();
754             SHA512_Final(g_md, &c);
755             OPENSSL_cleanse(&c, sizeof(c));
756             if (!MdCompare(g_md)) {
757                 errCount++;
758             }
759             break;
760         }
761         ProcessOutputData(buffer, index);
762         lock.unlock();
763         if (errCount > 0) {
764             break;
765         }
766     }
767 }
768 
ProcessOutputData(OH_AVMemory * buffer,uint32_t index)769 void VDecNdkSample::ProcessOutputData(OH_AVMemory *buffer, uint32_t index)
770 {
771     if (!SF_OUTPUT) {
772         uint8_t *bufferAddr = OH_AVMemory_GetAddr(buffer);
773         uint32_t cropSize = (picWidth_ * picHeight_ * THREE) >> 1;
774         uint8_t *cropBuffer = new uint8_t[cropSize];
775         uint8_t *copyPos = cropBuffer;
776         //copy y
777         for (int32_t i = 0; i < picHeight_; i++) {
778             memcpy_s(copyPos, picWidth_, bufferAddr, picWidth_);
779             bufferAddr += stride_;
780             copyPos += picWidth_;
781         }
782         bufferAddr += (sliceHeight_ - picHeight_) * stride_;
783         //copy uv
784         for (int32_t i = 0; i < picHeight_ >> 1; i++) {
785             memcpy_s(copyPos, picWidth_, bufferAddr, picWidth_);
786             bufferAddr += stride_;
787             copyPos += picWidth_;
788         }
789         SHA512_Update(&c, cropBuffer, cropSize);
790         delete[] cropBuffer;
791         if (OH_VideoDecoder_FreeOutputData(vdec_, index) != AV_ERR_OK) {
792             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
793             errCount = errCount + 1;
794         }
795     } else {
796         if (OH_VideoDecoder_RenderOutputData(vdec_, index) != AV_ERR_OK) {
797             cout << "Fatal: RenderOutputBuffer fail" << endl;
798             errCount = errCount + 1;
799         }
800     }
801 }
802 
state_EOS()803 int32_t VDecNdkSample::state_EOS()
804 {
805     uint32_t index;
806     unique_lock<mutex> lock(signal_->inMutex_);
807     signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
808     index = signal_->inIdxQueue_.front();
809     signal_->inIdxQueue_.pop();
810     signal_->inBufferQueue_.pop();
811     lock.unlock();
812     OH_AVCodecBufferAttr attr;
813     attr.pts = 0;
814     attr.size = 0;
815     attr.offset = 0;
816     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
817     return OH_VideoDecoder_PushInputData(vdec_, index, attr);
818 }
819 
SetEOS(uint32_t index)820 void VDecNdkSample::SetEOS(uint32_t index)
821 {
822     OH_AVCodecBufferAttr attr;
823     attr.pts = 0;
824     attr.size = 0;
825     attr.offset = 0;
826     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
827     int32_t res = OH_VideoDecoder_PushInputData(vdec_, index, attr);
828     cout << "OH_VideoDecoder_PushInputData    EOS   res: " << res << endl;
829 }
830 
Flush()831 int32_t VDecNdkSample::Flush()
832 {
833     unique_lock<mutex> inLock(signal_->inMutex_);
834     clearIntqueue(signal_->inIdxQueue_);
835     signal_->inCond_.notify_all();
836     inLock.unlock();
837     unique_lock<mutex> outLock(signal_->outMutex_);
838     clearIntqueue(signal_->outIdxQueue_);
839     clearBufferqueue(signal_->attrQueue_);
840     signal_->outCond_.notify_all();
841     outLock.unlock();
842     isRunning_.store(false);
843     return OH_VideoDecoder_Flush(vdec_);
844 }
845 
Reset()846 int32_t VDecNdkSample::Reset()
847 {
848     isRunning_.store(false);
849     StopInloop();
850     StopOutloop();
851     ReleaseInFile();
852     return OH_VideoDecoder_Reset(vdec_);
853 }
854 
Release()855 int32_t VDecNdkSample::Release()
856 {
857     int ret = 0;
858     if (vdec_ != nullptr) {
859         ret = OH_VideoDecoder_Destroy(vdec_);
860         vdec_ = nullptr;
861     }
862 
863     if (signal_ != nullptr) {
864         delete signal_;
865         signal_ = nullptr;
866     }
867     return ret;
868 }
869 
Stop()870 int32_t VDecNdkSample::Stop()
871 {
872     StopInloop();
873     StopOutloop();
874     ReleaseInFile();
875     return OH_VideoDecoder_Stop(vdec_);
876 }
877 
Start()878 int32_t VDecNdkSample::Start()
879 {
880     isRunning_.store(true);
881     return OH_VideoDecoder_Start(vdec_);
882 }
883 
StopOutloop()884 void VDecNdkSample::StopOutloop()
885 {
886     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
887         unique_lock<mutex> lock(signal_->outMutex_);
888         clearIntqueue(signal_->outIdxQueue_);
889         clearBufferqueue(signal_->attrQueue_);
890         isRunning_.store(false);
891         signal_->outCond_.notify_all();
892         lock.unlock();
893         outputLoop_->join();
894         outputLoop_.reset();
895     }
896 }
897 
SetParameter(OH_AVFormat * format)898 int32_t VDecNdkSample::SetParameter(OH_AVFormat *format)
899 {
900     return OH_VideoDecoder_SetParameter(vdec_, format);
901 }
902 
SwitchSurface()903 int32_t VDecNdkSample::SwitchSurface()
904 {
905     int32_t ret = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]);
906     switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
907     cout << "manual switch surf "<< switchSurfaceFlag << endl;
908     return ret;
909 }
910 
RepeatCallSetSurface()911 int32_t VDecNdkSample::RepeatCallSetSurface()
912 {
913     int32_t ret = AV_ERR_OK;
914     for (int i = 0; i < REPEAT_CALL_TIME; i++) {
915         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
916         ret = OH_VideoDecoder_SetSurface(vdec_, nativeWindow[switchSurfaceFlag]);
917         if (ret != AV_ERR_OK && ret != AV_ERR_OPERATE_NOT_PERMIT) {
918             return AV_ERR_OPERATE_NOT_PERMIT;
919         }
920     }
921     return ret;
922 }
923 
DecodeSetSurface()924 int32_t VDecNdkSample::DecodeSetSurface()
925 {
926     CreateSurface();
927     return OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
928 }