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