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 "iconsumer_surface.h"
19 #include "openssl/crypto.h"
20 #include "openssl/sha.h"
21 #include "videodec_ndk_sample.h"
22 using namespace OHOS;
23 using namespace OHOS::Media;
24 using namespace std;
25 namespace {
26 const string MIME_TYPE = "video/avc";
27 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
28 constexpr int64_t NANOS_IN_MICRO = 1000L;
29 constexpr int32_t THREE = 3;
30 constexpr int32_t EIGHT = 8;
31 constexpr int32_t TEN = 10;
32 constexpr int32_t SIXTEEN = 16;
33 constexpr int32_t TWENTY_FOUR = 24;
34 constexpr uint32_t FRAME_INTERVAL = 1; // 16666
35 constexpr uint8_t H264_NALU_TYPE = 0x1f;
36 constexpr uint32_t START_CODE_SIZE = 4;
37 constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
38 constexpr uint8_t SPS = 7;
39 constexpr uint8_t PPS = 8;
40
41 SHA512_CTX c;
42 sptr<Surface> cs = nullptr;
43 sptr<Surface> ps = nullptr;
44 unsigned char md[SHA512_DIGEST_LENGTH];
45 VDecNdkSample *dec_sample = nullptr;
46
clearIntqueue(std::queue<uint32_t> & q)47 void clearIntqueue(std::queue<uint32_t> &q)
48 {
49 std::queue<uint32_t> empty;
50 swap(empty, q);
51 }
52
clearBufferqueue(std::queue<OH_AVCodecBufferAttr> & q)53 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
54 {
55 std::queue<OH_AVCodecBufferAttr> empty;
56 swap(empty, q);
57 }
58 } // namespace
59
60 class TestConsumerListener : public IBufferConsumerListener {
61 public:
TestConsumerListener(sptr<Surface> cs,std::string_view name)62 TestConsumerListener(sptr<Surface> cs, std::string_view name) : cs(cs) {};
~TestConsumerListener()63 ~TestConsumerListener() {}
OnBufferAvailable()64 void OnBufferAvailable() override
65 {
66 sptr<SurfaceBuffer> buffer;
67 int32_t flushFence;
68 cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
69
70 cs->ReleaseBuffer(buffer, -1);
71 }
72
73 private:
74 int64_t timestamp = 0;
75 Rect damage = {};
76 sptr<Surface> cs {nullptr};
77 };
~VDecNdkSample()78 VDecNdkSample::~VDecNdkSample()
79 {
80 Release();
81 }
82
VdecError(OH_AVCodec * codec,int32_t errorCode,void * userData)83 void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
84 {
85 cout << "Error errorCode=" << errorCode << endl;
86 dec_sample->StopInloop();
87 dec_sample->StopOutloop();
88 dec_sample->ReleaseInFile();
89 dec_sample->Release();
90 }
91
VdecFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)92 void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
93 {
94 cout << "Format Changed" << endl;
95 int32_t current_width = 0;
96 int32_t current_height = 0;
97 OH_AVFormat_GetIntValue(format, OH_MD_KEY_WIDTH, ¤t_width);
98 OH_AVFormat_GetIntValue(format, OH_MD_KEY_HEIGHT, ¤t_height);
99 dec_sample->DEFAULT_WIDTH = current_width;
100 dec_sample->DEFAULT_HEIGHT = current_height;
101 }
102
VdecInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)103 void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
104 {
105 VDecSignal *signal = static_cast<VDecSignal *>(userData);
106 unique_lock<mutex> lock(signal->inMutex_);
107 signal->inIdxQueue_.push(index);
108 signal->inBufferQueue_.push(data);
109 signal->inCond_.notify_all();
110 }
111
VdecOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)112 void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
113 void *userData)
114 {
115 VDecSignal *signal = static_cast<VDecSignal *>(userData);
116 unique_lock<mutex> lock(signal->outMutex_);
117 signal->outIdxQueue_.push(index);
118 signal->attrQueue_.push(*attr);
119 signal->outBufferQueue_.push(data);
120 signal->outCond_.notify_all();
121 }
122
Flush_buffer()123 void VDecNdkSample::Flush_buffer()
124 {
125 unique_lock<mutex> inLock(signal_->inMutex_);
126 clearIntqueue(signal_->inIdxQueue_);
127 std::queue<OH_AVMemory *> empty;
128 swap(empty, signal_->inBufferQueue_);
129 signal_->inCond_.notify_all();
130 inLock.unlock();
131 unique_lock<mutex> outLock(signal_->outMutex_);
132 clearIntqueue(signal_->outIdxQueue_);
133 clearBufferqueue(signal_->attrQueue_);
134 signal_->outCond_.notify_all();
135 outLock.unlock();
136 }
137
MdCompare(unsigned char buffer[],int len,const char * source[])138 bool VDecNdkSample::MdCompare(unsigned char buffer[], int len, const char *source[])
139 {
140 bool result = true;
141 for (int i = 0; i < len; i++) {
142 }
143 return result;
144 }
145
GetSystemTimeUs()146 int64_t VDecNdkSample::GetSystemTimeUs()
147 {
148 struct timespec now;
149 (void)clock_gettime(CLOCK_BOOTTIME, &now);
150 int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
151 return nanoTime / NANOS_IN_MICRO;
152 }
153
ConfigureVideoDecoder()154 int32_t VDecNdkSample::ConfigureVideoDecoder()
155 {
156 OH_AVFormat *format = OH_AVFormat_Create();
157 if (format == nullptr) {
158 cout << "Fatal: Failed to create format" << endl;
159 return AV_ERR_UNKNOWN;
160 }
161 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
162 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
163 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
164 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
165 int ret = OH_VideoDecoder_Configure(vdec_, format);
166 OH_AVFormat_Destroy(format);
167 return ret;
168 }
169
RunVideoDec_Surface(string codeName)170 int32_t VDecNdkSample::RunVideoDec_Surface(string codeName)
171 {
172 SF_OUTPUT = true;
173 int err = AV_ERR_OK;
174 cs = Surface::CreateSurfaceAsConsumer();
175 sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs, OUT_DIR);
176 cs->RegisterConsumerListener(listener);
177 auto p = cs->GetProducer();
178 ps = Surface::CreateSurfaceAsProducer(p);
179 OHNativeWindow *nativeWindow = CreateNativeWindowFromSurface(&ps);
180 if (!nativeWindow) {
181 cout << "Failed to create surface" << endl;
182 return AV_ERR_UNKNOWN;
183 }
184 err = CreateVideoDecoder(codeName);
185 if (err != AV_ERR_OK) {
186 cout << "Failed to create video decoder" << endl;
187 return err;
188 }
189 err = SetVideoDecoderCallback();
190 if (err != AV_ERR_OK) {
191 cout << "Failed to setCallback" << endl;
192 Release();
193 return err;
194 }
195 err = ConfigureVideoDecoder();
196 if (err != AV_ERR_OK) {
197 cout << "Failed to configure video decoder" << endl;
198 Release();
199 return err;
200 }
201 err = OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
202 if (err != AV_ERR_OK) {
203 cout << "Failed to set surface" << endl;
204 return err;
205 }
206 err = StartVideoDecoder();
207 if (err != AV_ERR_OK) {
208 cout << "Failed to start video decoder" << endl;
209 Release();
210 return err;
211 }
212 return err;
213 }
214
RunVideoDec(string codeName)215 int32_t VDecNdkSample::RunVideoDec(string codeName)
216 {
217 SF_OUTPUT = false;
218 int err = CreateVideoDecoder(codeName);
219 if (err != AV_ERR_OK) {
220 cout << "Failed to create video decoder" << endl;
221 return err;
222 }
223
224 err = ConfigureVideoDecoder();
225 if (err != AV_ERR_OK) {
226 cout << "Failed to configure video decoder" << endl;
227 Release();
228 return err;
229 }
230
231 err = SetVideoDecoderCallback();
232 if (err != AV_ERR_OK) {
233 cout << "Failed to setCallback" << endl;
234 Release();
235 return err;
236 }
237
238 err = StartVideoDecoder();
239 if (err != AV_ERR_OK) {
240 cout << "Failed to start video decoder" << endl;
241 Release();
242 return err;
243 }
244 return err;
245 }
246
SetVideoDecoderCallback()247 int32_t VDecNdkSample::SetVideoDecoderCallback()
248 {
249 signal_ = new VDecSignal();
250 if (signal_ == nullptr) {
251 cout << "Failed to new VDecSignal" << endl;
252 return AV_ERR_UNKNOWN;
253 }
254
255 cb_.onError = VdecError;
256 cb_.onStreamChanged = VdecFormatChanged;
257 cb_.onNeedInputData = VdecInputDataReady;
258 cb_.onNeedOutputData = VdecOutputDataReady;
259 return OH_VideoDecoder_SetCallback(vdec_, cb_, static_cast<void *>(signal_));
260 }
261
ReleaseInFile()262 void VDecNdkSample::ReleaseInFile()
263 {
264 if (inFile_ != nullptr) {
265 if (inFile_->is_open()) {
266 inFile_->close();
267 }
268 inFile_.reset();
269 inFile_ = nullptr;
270 }
271 }
272
StopInloop()273 void VDecNdkSample::StopInloop()
274 {
275 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
276 unique_lock<mutex> lock(signal_->inMutex_);
277 clearIntqueue(signal_->inIdxQueue_);
278 signal_->inCond_.notify_all();
279 lock.unlock();
280
281 inputLoop_->join();
282 inputLoop_.reset();
283 }
284 }
285
CreateVideoDecoder(string codeName)286 int32_t VDecNdkSample::CreateVideoDecoder(string codeName)
287 {
288 vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
289 dec_sample = this;
290 return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
291 }
292
StartVideoDecoder()293 int32_t VDecNdkSample::StartVideoDecoder()
294 {
295 isRunning_.store(true);
296 int ret = OH_VideoDecoder_Start(vdec_);
297 if (ret != AV_ERR_OK) {
298 cout << "Failed to start codec" << endl;
299 isRunning_.store(false);
300 ReleaseInFile();
301 Release();
302 return ret;
303 }
304 inFile_ = make_unique<ifstream>();
305 if (inFile_ == nullptr) {
306 isRunning_.store(false);
307 (void)OH_VideoDecoder_Stop(vdec_);
308 return AV_ERR_UNKNOWN;
309 }
310 inFile_->open(INP_DIR, ios::in | ios::binary);
311 if (!inFile_->is_open()) {
312 cout << "failed open file " << INP_DIR << endl;
313 isRunning_.store(false);
314 (void)OH_VideoDecoder_Stop(vdec_);
315 inFile_->close();
316 inFile_.reset();
317 inFile_ = nullptr;
318 return AV_ERR_UNKNOWN;
319 }
320
321 inputLoop_ = make_unique<thread>(&VDecNdkSample::InputFuncTest, this);
322 if (inputLoop_ == nullptr) {
323 cout << "Failed to create input loop" << endl;
324 isRunning_.store(false);
325 (void)OH_VideoDecoder_Stop(vdec_);
326 ReleaseInFile();
327 return AV_ERR_UNKNOWN;
328 }
329 outputLoop_ = make_unique<thread>(&VDecNdkSample::OutputFuncTest, this);
330 if (outputLoop_ == nullptr) {
331 cout << "Failed to create output loop" << endl;
332 isRunning_.store(false);
333 (void)OH_VideoDecoder_Stop(vdec_);
334 ReleaseInFile();
335 StopInloop();
336 Release();
337 return AV_ERR_UNKNOWN;
338 }
339
340 return AV_ERR_OK;
341 }
342
testAPI()343 void VDecNdkSample::testAPI()
344 {
345 cs = Surface::CreateSurfaceAsConsumer();
346 sptr<IBufferConsumerListener> listener = new TestConsumerListener(cs, OUT_DIR);
347 cs->RegisterConsumerListener(listener);
348 auto p = cs->GetProducer();
349 ps = Surface::CreateSurfaceAsProducer(p);
350 OHNativeWindow *nativeWindow = CreateNativeWindowFromSurface(&ps);
351 OH_VideoDecoder_SetSurface(vdec_, nativeWindow);
352
353 OH_VideoDecoder_Prepare(vdec_);
354 OH_VideoDecoder_Start(vdec_);
355
356 OH_AVFormat *format = OH_AVFormat_Create();
357 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
358 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
359 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV12);
360 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
361 OH_VideoDecoder_SetParameter(vdec_, format);
362 OH_AVFormat_Destroy(format);
363 OH_VideoDecoder_GetOutputDescription(vdec_);
364 OH_VideoDecoder_Flush(vdec_);
365 OH_VideoDecoder_Stop(vdec_);
366 OH_VideoDecoder_Reset(vdec_);
367 bool isvalid = false;
368 OH_VideoDecoder_IsValid(vdec_, &isvalid);
369 }
370
WaitForEOS()371 void VDecNdkSample::WaitForEOS()
372 {
373 if (inputLoop_ && inputLoop_->joinable()) {
374 inputLoop_->join();
375 }
376 if (outputLoop_ && outputLoop_->joinable()) {
377 outputLoop_->join();
378 }
379 }
380
InputFuncTest()381 void VDecNdkSample::InputFuncTest()
382 {
383 while (true) {
384 if (!isRunning_.load()) {
385 break;
386 }
387 if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
388 REPEAT_START_FLUSH_BEFORE_EOS--;
389 OH_VideoDecoder_Flush(vdec_);
390 Flush_buffer();
391 OH_VideoDecoder_Start(vdec_);
392 }
393 if (REPEAT_START_STOP_BEFORE_EOS > 0) {
394 REPEAT_START_STOP_BEFORE_EOS--;
395 OH_VideoDecoder_Stop(vdec_);
396 Flush_buffer();
397 OH_VideoDecoder_Start(vdec_);
398 }
399 uint32_t index;
400 unique_lock<mutex> lock(signal_->inMutex_);
401 signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
402 if (!isRunning_.load()) {
403 break;
404 }
405 index = signal_->inIdxQueue_.front();
406 auto buffer = signal_->inBufferQueue_.front();
407
408 signal_->inIdxQueue_.pop();
409 signal_->inBufferQueue_.pop();
410 lock.unlock();
411 if (!inFile_->eof()) {
412 int ret = PushData(index, buffer);
413 if (ret == 1) {
414 break;
415 }
416 }
417 if (sleepOnFPS) {
418 usleep(FRAME_INTERVAL);
419 }
420 }
421 }
422
PushData(uint32_t index,OH_AVMemory * buffer)423 int32_t VDecNdkSample::PushData(uint32_t index, OH_AVMemory *buffer)
424 {
425 static uint32_t repeat_count = 0;
426 OH_AVCodecBufferAttr attr;
427 if (BEFORE_EOS_INPUT && frameCount_ > TEN) {
428 SetEOS(index);
429 return 1;
430 }
431 if (BEFORE_EOS_INPUT_INPUT && frameCount_ > TEN) {
432 memset_s(&attr, sizeof(OH_AVCodecBufferAttr), 0, sizeof(OH_AVCodecBufferAttr));
433 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
434 BEFORE_EOS_INPUT_INPUT = false;
435 }
436 char ch[4] = {};
437 (void)inFile_->read(ch, START_CODE_SIZE);
438 if (repeatRun && inFile_->eof()) {
439 inFile_->clear();
440 inFile_->seekg(0, ios::beg);
441 cout << "repeat run " << repeat_count << endl;
442 repeat_count++;
443 return 0;
444 }
445 if (inFile_->eof()) {
446 SetEOS(index);
447 return 1;
448 }
449 uint32_t bufferSize = (uint32_t)(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) | ((ch[1] & 0xFF) << SIXTEEN) |
450 ((ch[0] & 0xFF) << TWENTY_FOUR));
451 if (bufferSize >= DEFAULT_WIDTH * DEFAULT_HEIGHT * THREE >> 1) {
452 cout << "read bufferSize abnormal. buffersize = " << bufferSize << endl;
453 return 1;
454 }
455
456 return SendData(bufferSize, index, buffer);
457 }
458
SendData(uint32_t bufferSize,uint32_t index,OH_AVMemory * buffer)459 uint32_t VDecNdkSample::SendData(uint32_t bufferSize, uint32_t index, OH_AVMemory *buffer)
460 {
461 OH_AVCodecBufferAttr attr;
462 uint8_t *fileBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
463 if (fileBuffer == nullptr) {
464 cout << "Fatal: no memory" << endl;
465 delete[] fileBuffer;
466 return 0;
467 }
468 if (memcpy_s(fileBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
469 cout << "Fatal: memory copy failed" << endl;
470 }
471 (void)inFile_->read((char *)fileBuffer + START_CODE_SIZE, bufferSize);
472 if ((fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == SPS ||
473 (fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == PPS) {
474 attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
475 } else {
476 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
477 }
478
479 int32_t size = OH_AVMemory_GetSize(buffer);
480 if (size < bufferSize + START_CODE_SIZE) {
481 delete[] fileBuffer;
482 cout << "buffer size not enough." << endl;
483 return 0;
484 }
485 uint8_t *avBuffer = OH_AVMemory_GetAddr(buffer);
486 if (avBuffer == nullptr) {
487 cout << "avBuffer == nullptr" << endl;
488 inFile_->clear();
489 inFile_->seekg(0, ios::beg);
490 delete[] fileBuffer;
491 return 0;
492 }
493 if (memcpy_s(avBuffer, size, fileBuffer, bufferSize + START_CODE_SIZE) != EOK) {
494 delete[] fileBuffer;
495 cout << "Fatal: memcpy fail" << endl;
496 return 0;
497 }
498 int64_t startPts = GetSystemTimeUs();
499 attr.pts = startPts;
500 attr.size = bufferSize + START_CODE_SIZE;
501 attr.offset = 0;
502 int32_t result = OH_VideoDecoder_PushInputData(vdec_, index, attr);
503 if (result != AV_ERR_OK) {
504 errCount = errCount + 1;
505 cout << "push input data failed,error:" << result << endl;
506 }
507 delete[] fileBuffer;
508 frameCount_ = frameCount_ + 1;
509 return 0;
510 }
511
OutputFuncTest()512 void VDecNdkSample::OutputFuncTest()
513 {
514 SHA512_Init(&c);
515 while (true) {
516 if (!isRunning_.load()) {
517 break;
518 }
519 OH_AVCodecBufferAttr attr;
520 uint32_t index;
521 unique_lock<mutex> lock(signal_->outMutex_);
522 signal_->outCond_.wait(lock, [this]() { return signal_->outIdxQueue_.size() > 0; });
523 if (!isRunning_.load()) {
524 break;
525 }
526 index = signal_->outIdxQueue_.front();
527 attr = signal_->attrQueue_.front();
528 OH_AVMemory *buffer = signal_->outBufferQueue_.front();
529 signal_->outBufferQueue_.pop();
530 signal_->outIdxQueue_.pop();
531 signal_->attrQueue_.pop();
532 lock.unlock();
533 if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
534 SHA512_Final(md, &c);
535 OPENSSL_cleanse(&c, sizeof(c));
536 MdCompare(md, SHA512_DIGEST_LENGTH, fileSourcesha256);
537 if (AFTER_EOS_DESTORY_CODEC) {
538 (void)Stop();
539 Release();
540 }
541 break;
542 }
543 ProcessOutputData(buffer, index);
544 if (errCount > 0) {
545 break;
546 }
547 }
548 }
549
ProcessOutputData(OH_AVMemory * buffer,uint32_t index)550 void VDecNdkSample::ProcessOutputData(OH_AVMemory *buffer, uint32_t index)
551 {
552 if (!SF_OUTPUT) {
553 uint32_t size = OH_AVMemory_GetSize(buffer);
554 if (size >= DEFAULT_WIDTH * DEFAULT_HEIGHT * THREE >> 1) {
555 uint8_t *cropBuffer = new uint8_t[size];
556 if (memcpy_s(cropBuffer, DEFAULT_WIDTH * DEFAULT_HEIGHT, OH_AVMemory_GetAddr(buffer),
557 DEFAULT_WIDTH * DEFAULT_HEIGHT) != EOK) {
558 cout << "Fatal: memory copy failed Y" << endl;
559 }
560 // copy UV
561 uint32_t uvSize = size - DEFAULT_WIDTH * DEFAULT_HEIGHT;
562 if (memcpy_s(cropBuffer + DEFAULT_WIDTH * DEFAULT_HEIGHT, uvSize,
563 OH_AVMemory_GetAddr(buffer) + DEFAULT_WIDTH * DEFAULT_HEIGHT, uvSize) != EOK) {
564 cout << "Fatal: memory copy failed UV" << endl;
565 }
566 SHA512_Update(&c, cropBuffer, size);
567 delete[] cropBuffer;
568 }
569 if (OH_VideoDecoder_FreeOutputData(vdec_, index) != AV_ERR_OK) {
570 cout << "Fatal: ReleaseOutputBuffer fail" << endl;
571 errCount = errCount + 1;
572 }
573 } else {
574 if (OH_VideoDecoder_RenderOutputData(vdec_, index) != AV_ERR_OK) {
575 cout << "Fatal: RenderOutputBuffer fail" << endl;
576 errCount = errCount + 1;
577 }
578 }
579 }
580
state_EOS()581 int32_t VDecNdkSample::state_EOS()
582 {
583 uint32_t index;
584 unique_lock<mutex> lock(signal_->inMutex_);
585 signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
586 index = signal_->inIdxQueue_.front();
587 signal_->inIdxQueue_.pop();
588 signal_->inBufferQueue_.pop();
589 lock.unlock();
590 OH_AVCodecBufferAttr attr;
591 attr.pts = 0;
592 attr.size = 0;
593 attr.offset = 0;
594 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
595 return OH_VideoDecoder_PushInputData(vdec_, index, attr);
596 }
597
SetEOS(uint32_t index)598 void VDecNdkSample::SetEOS(uint32_t index)
599 {
600 OH_AVCodecBufferAttr attr;
601 attr.pts = 0;
602 attr.size = 0;
603 attr.offset = 0;
604 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
605 int32_t res = OH_VideoDecoder_PushInputData(vdec_, index, attr);
606 cout << "OH_VideoDecoder_PushInputData EOS res: " << res << endl;
607 }
608
Flush()609 int32_t VDecNdkSample::Flush()
610 {
611 unique_lock<mutex> inLock(signal_->inMutex_);
612 clearIntqueue(signal_->inIdxQueue_);
613 signal_->inCond_.notify_all();
614 inLock.unlock();
615 unique_lock<mutex> outLock(signal_->outMutex_);
616 clearIntqueue(signal_->outIdxQueue_);
617 clearBufferqueue(signal_->attrQueue_);
618 signal_->outCond_.notify_all();
619 outLock.unlock();
620
621 return OH_VideoDecoder_Flush(vdec_);
622 }
623
Reset()624 int32_t VDecNdkSample::Reset()
625 {
626 isRunning_.store(false);
627 StopInloop();
628 StopOutloop();
629 ReleaseInFile();
630 return OH_VideoDecoder_Reset(vdec_);
631 }
632
Release()633 int32_t VDecNdkSample::Release()
634 {
635 int ret = 0;
636 if (vdec_ != nullptr) {
637 ret = OH_VideoDecoder_Destroy(vdec_);
638 vdec_ = nullptr;
639 }
640
641 if (signal_ != nullptr) {
642 delete signal_;
643 signal_ = nullptr;
644 }
645 return ret;
646 }
647
Stop()648 int32_t VDecNdkSample::Stop()
649 {
650 StopInloop();
651 clearIntqueue(signal_->outIdxQueue_);
652 clearBufferqueue(signal_->attrQueue_);
653 ReleaseInFile();
654 return OH_VideoDecoder_Stop(vdec_);
655 }
656
Start()657 int32_t VDecNdkSample::Start()
658 {
659 return OH_VideoDecoder_Start(vdec_);
660 }
661
StopOutloop()662 void VDecNdkSample::StopOutloop()
663 {
664 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
665 unique_lock<mutex> lock(signal_->outMutex_);
666 clearIntqueue(signal_->outIdxQueue_);
667 clearBufferqueue(signal_->attrQueue_);
668 signal_->outCond_.notify_all();
669 lock.unlock();
670 }
671 }
672
SetParameter(OH_AVFormat * format)673 int32_t VDecNdkSample::SetParameter(OH_AVFormat *format)
674 {
675 return OH_VideoDecoder_SetParameter(vdec_, format);
676 }