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