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