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