From cd699daf090306d7c642f47db5d4b3a04e72cfa1 Mon Sep 17 00:00:00 2001 From: ling990 Date: Thu, 25 Aug 2022 16:18:41 +0800 Subject: [PATCH] modify testcases Signed-off-by: ling990 Signed-off-by: ling990 --- .../videoDecEncNdk/include/VDecEncNdkSample.h | 139 ++++ .../src/ActsVideoDecEncNdkTest.cpp | 537 ++++++++++++ .../videoDecEncNdk/src/VDecEncNdkSample.cpp | 764 ++++++++++++++++++ 3 files changed, 1440 insertions(+) create mode 100644 multimedia/media/media_cpp_standard/videoDecEncNdk/include/VDecEncNdkSample.h create mode 100644 multimedia/media/media_cpp_standard/videoDecEncNdk/src/ActsVideoDecEncNdkTest.cpp create mode 100644 multimedia/media/media_cpp_standard/videoDecEncNdk/src/VDecEncNdkSample.cpp diff --git a/multimedia/media/media_cpp_standard/videoDecEncNdk/include/VDecEncNdkSample.h b/multimedia/media/media_cpp_standard/videoDecEncNdk/include/VDecEncNdkSample.h new file mode 100644 index 000000000..83accef2f --- /dev/null +++ b/multimedia/media/media_cpp_standard/videoDecEncNdk/include/VDecEncNdkSample.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VIDEODECENC_NDK_SAMPLE_H +#define VIDEODECENC_NDK_SAMPLE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "nocopyable.h" +#include "ndktest_log.h" +#include "native_avmagic.h" +#include "surface.h" +#include "native_avcodec_videodecoder.h" +#include "native_avcodec_videoencoder.h" + +namespace OHOS { +namespace Media { +class VDecEncSignal { +public: + std::mutex inMutexDec_; + std::mutex outMutexDec_; + std::condition_variable inCondDec_; + std::condition_variable outCondDec_; + std::queue inQueueDec_; + std::queue outQueueDec_; + std::queue flagQueueDec_; + std::queue inBufferQueueDec_; + std::queue outBufferQueueDec_; + + std::mutex outMutexEnc_; + std::condition_variable outCondEnc_; + std::queue inQueueEnc_; + std::queue outQueueEnc_; + std::queue sizeQueueEnc_; + std::queue flagQueueEnc_; + std::queue inBufferQueueEnc_; + std::queue outBufferQueueEnc_; + int32_t errorNum_ = 0; + std::atomic isVdecFlushing_ = false; + std::atomic isVencFlushing_ = false; +}; + +class VDecEncNdkSample : public NoCopyable { +public: + VDecEncNdkSample() = default; + ~VDecEncNdkSample(); + + void SetEosState(bool needSetEos); + struct OH_AVCodec* CreateVideoDecoderByMime(std::string mimetype); + struct OH_AVCodec* CreateVideoDecoderByName(std::string name); + int32_t ConfigureDec(struct OH_AVFormat *format); + int32_t SetOutputSurface(); + int32_t PrepareDec(); + int32_t StartDec(); + int32_t StopDec(); + int32_t FlushDec(); + int32_t ResetDec(); + int32_t ReleaseDec(); + + struct OH_AVCodec* CreateVideoEncoderByMime(std::string mimetype); + struct OH_AVCodec* CreateVideoEncoderByName(std::string name); + int32_t ConfigureEnc(struct OH_AVFormat *format); + int32_t GetSurface(); + int32_t PrepareEnc(); + int32_t StartEnc(); + int32_t StopEnc(); + int32_t FlushEnc(); + int32_t ResetEnc(); + int32_t ReleaseEnc(); + + int32_t CalcuError(); + void SetReadPath(std::string filepath); + void SetSavePath(std::string filepath); + void ReRead(); + void ResetDecParam(); + void ResetEncParam(); + int32_t GetFrameCount(); + bool GetEncEosState(); + bool GetDecEosState(); + void PopInqueueDec(); + void PopOutqueueDec(); + void PopOutqueueEnc(); + void SendEncEos(); + int32_t PushInbufferDec(uint32_t index, uint32_t bufferSize); + VDecEncSignal* vcodecSignal_ = nullptr; + bool isDecInputEOS = false; + bool isEncInputEOS = false; + bool isDecOutputEOS = false; + bool isEncOutputEOS = false; + bool setEos = true; + +private: + OHNativeWindow *nativeWindow_; + struct OH_AVCodec* vdec_; + void InputFuncDec(); + void OutputFuncDec(); + int32_t WriteToFile(); + std::atomic isDecRunning_ = false; + std::unique_ptr testFile_; + std::unique_ptr inputLoopDec_; + std::unique_ptr outputLoopDec_; + struct OH_AVCodecAsyncCallback cbDec_; + int64_t timeStampDec_ = 0; + uint32_t decInCnt_ = 0; + uint32_t decOutCnt_ = 0; + + struct OH_AVCodec* venc_; + void OutputFuncEnc(); + std::atomic isEncRunning_ = false; + std::unique_ptr outputLoopEnc_; + struct OH_AVCodecAsyncCallback cbEnc_; + bool isFirstDecFrame_ = true; + uint32_t encOutCnt_ = 0; + std::string inFile_ = "/data/media/out_320_240_10s.h264"; + std::string outFile_ = "/data/media/video_out.es"; +}; +} +} +#endif // VIDEODECENC_NDK_SAMPLE_H diff --git a/multimedia/media/media_cpp_standard/videoDecEncNdk/src/ActsVideoDecEncNdkTest.cpp b/multimedia/media/media_cpp_standard/videoDecEncNdk/src/ActsVideoDecEncNdkTest.cpp new file mode 100644 index 000000000..821f6528f --- /dev/null +++ b/multimedia/media/media_cpp_standard/videoDecEncNdk/src/ActsVideoDecEncNdkTest.cpp @@ -0,0 +1,537 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "gtest/gtest.h" +#include "native_avcodec_videodecoder.h" +#include "native_avcodec_videoencoder.h" +#include "native_avcodec_base.h" +#include "native_avformat.h" +#include "ActsVideoDecEncNdkTest.h" + +using namespace std; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::Media; + +namespace { + const string MIME_TYPE_AVC = "video/avc"; + const string MIME_TYPE_MPEG4 = "video/mp4v-es"; + constexpr uint32_t DEFAULT_WIDTH = 320; + constexpr uint32_t DEFAULT_HEIGHT = 240; + constexpr uint32_t DEFAULT_PIXELFORMAT = 2; + constexpr uint32_t DEFAULT_FRAMERATE = 60; + const char* READPATH = "/data/media/out_320_240_10s.h264"; + + + bool CheckDecDesc(map InDesc, OH_AVFormat* OutDesc) + { + int32_t out ; + for (const auto& t: InDesc) { + bool res = OH_AVFormat_GetIntValue(OutDesc, t.first.c_str(), &out); + cout << "key: " << t.first << "; out: " << out < mediaDescription) + { + const char *key; + for (const auto& t: mediaDescription) { + key = t.first.c_str(); + if (not OH_AVFormat_SetIntValue(format, key, t.second)) { + cout << "OH_AV_FormatPutIntValue Fail. format key: " << t.first + << ", value: "<< t.second << endl; + return false; + } + } + return true; + } + + struct OH_AVFormat* createFormat() + { + OH_AVFormat *DefaultFormat = OH_AVFormat_Create(); + OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_WIDTH, DEFAULT_WIDTH); + OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT); + OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT); + OH_AVFormat_SetIntValue(DefaultFormat, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAMERATE); + return DefaultFormat; + } +} + +/** + * @tc.number : ActsVideoDecEncNdkTest001 + * @tc.name : stop at end of stream + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest001, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetSavePath("/data/media/video_001.es"); + + OH_AVFormat *VideoFormat = OH_AVFormat_Create(); + ASSERT_NE(nullptr, VideoFormat); + map VideoParam = { + {OH_MD_KEY_WIDTH, DEFAULT_WIDTH}, + {OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT}, + {OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT}, + {OH_MD_KEY_FRAME_RATE, DEFAULT_FRAMERATE}, + }; + ASSERT_EQ(true, SetFormat(VideoFormat, VideoParam)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + OH_AVFormat *OutDescDec = OH_VideoDecoder_GetOutputDescription(videoDec); + ASSERT_NE(nullptr, OutDescDec); + ASSERT_EQ(true, CheckDecDesc(VideoParam, OutDescDec)); + + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + OH_AVFormat *OutDescEnc = OH_VideoEncoder_GetOutputDescription(videoEnc); + ASSERT_NE(nullptr, OutDescEnc); + ASSERT_EQ(true, CheckDecDesc(VideoParam, OutDescEnc)); + + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + +/** + * @tc.number : ActsVideoDecEncNdkTest002 + * @tc.name : reset at end of stream + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest002, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetSavePath("/data/media/video_002.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + + + /** + * @tc.number : ActsVideoDecEncNdkTest003 + * @tc.name : release at end of stream + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest003, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetSavePath("/data/media/video_003.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + +/** +* @tc.number : ActsVideoDecEncNdkTest004 +* @tc.name : flush at running +* @tc.desc : Basic function test +*/ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest004, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetEosState(false); + vDecEncSample->SetSavePath("/data/media/video_004.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (vDecEncSample->GetFrameCount() < 100) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushEnc()); + vDecEncSample->ReRead(); + vDecEncSample->ResetDecParam(); + vDecEncSample->ResetEncParam(); + vDecEncSample->SetEosState(true); + vDecEncSample->SetSavePath("/data/media/video_004_2.es"); + + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + + + /** + * @tc.number : ActsVideoDecEncNdkTest005 + * @tc.name : flush dec at eos and restart + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest005, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetEosState(false); + vDecEncSample->SetSavePath("/data/media/video_005.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetDecEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushEnc()); + vDecEncSample->ReRead(); + vDecEncSample->ResetDecParam(); + vDecEncSample->ResetEncParam(); + vDecEncSample->SetSavePath("/data/media/video_005_2.es"); + vDecEncSample->SetEosState(true); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + + + /** + * @tc.number : ActsVideoDecEncNdkTest006 + * @tc.name : stop at running and restart to eos + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest006, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetEosState(false); + vDecEncSample->SetSavePath("/data/media/video_006.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (vDecEncSample->GetFrameCount() < 100) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc()); + vDecEncSample->ReRead(); + vDecEncSample->ResetDecParam(); + vDecEncSample->ResetEncParam(); + vDecEncSample->SetEosState(true); + vDecEncSample->SetSavePath("/data/media/video_006_2.es"); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + + + /** + * @tc.number : ActsVideoDecEncNdkTest007 + * @tc.name : stop dec at eos and restart to eos + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest007, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetEosState(false); + vDecEncSample->SetSavePath("/data/media/video_007.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetDecEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->FlushEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); + vDecEncSample->ReRead(); + vDecEncSample->ResetDecParam(); + vDecEncSample->ResetEncParam(); + vDecEncSample->SetSavePath("/data/media/video_007_2.es"); + vDecEncSample->SetEosState(true); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + + + /** + * @tc.number : ActsVideoDecEncNdkTest008 + * @tc.name : reset at eos and restart to eos + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest008, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetSavePath("/data/media/video_008.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ResetEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); + vDecEncSample->ReRead(); + vDecEncSample->ResetDecParam(); + vDecEncSample->ResetEncParam(); + vDecEncSample->SetSavePath("/data/media/video_008_2.es"); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StopEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} + + + /** + * @tc.number : ActsVideoDecEncNdkTest009 + * @tc.name : release at eos and restart to eos + * @tc.desc : Basic function test + */ +HWTEST_F(ActsVideoDecEncNdkTest, ActsVideoDecEncNdkTest009, Function | MediumTest | Level1) +{ + VDecEncNdkSample *vDecEncSample = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec = vDecEncSample->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec); + struct OH_AVCodec* videoEnc = vDecEncSample->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc); + vDecEncSample->SetReadPath(READPATH); + vDecEncSample->SetSavePath("/data/media/video_009.es"); + + OH_AVFormat *VideoFormat = createFormat(); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ConfigureEnc(VideoFormat)); + + ASSERT_EQ(AV_ERR_OK, vDecEncSample->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample->StartDec()); + + while (!vDecEncSample->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseDec()); + videoDec = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->ReleaseEnc()); + videoEnc = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); + vDecEncSample->ReRead(); + vDecEncSample->ResetDecParam(); + vDecEncSample->ResetEncParam(); + + VDecEncNdkSample *vDecEncSample2 = new VDecEncNdkSample(); + + struct OH_AVCodec* videoDec2 = vDecEncSample2->CreateVideoDecoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoDec2); + struct OH_AVCodec* videoEnc2 = vDecEncSample2->CreateVideoEncoderByMime(MIME_TYPE_AVC); + ASSERT_NE(nullptr, videoEnc2); + vDecEncSample2->SetReadPath(READPATH); + vDecEncSample2->SetSavePath("/data/media/video_009_2.es"); + + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ConfigureDec(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ConfigureEnc(VideoFormat)); + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->GetSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->SetOutputSurface()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->PrepareEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->PrepareDec()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->StartEnc()); + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->StartDec()); + + while (!vDecEncSample2->GetEncEosState()) {}; + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ReleaseDec()); + videoDec2 = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample2->ReleaseEnc()); + videoEnc2 = nullptr; + OH_AVFormat_Destroy(VideoFormat); + VideoFormat = nullptr; + ASSERT_EQ(AV_ERR_OK, vDecEncSample->CalcuError()); +} \ No newline at end of file diff --git a/multimedia/media/media_cpp_standard/videoDecEncNdk/src/VDecEncNdkSample.cpp b/multimedia/media/media_cpp_standard/videoDecEncNdk/src/VDecEncNdkSample.cpp new file mode 100644 index 000000000..b69e80942 --- /dev/null +++ b/multimedia/media/media_cpp_standard/videoDecEncNdk/src/VDecEncNdkSample.cpp @@ -0,0 +1,764 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gtest/gtest.h" +#include "audio_info.h" +#include "av_common.h" +#include "avcodec_video_encoder.h" +#include "avcodec_video_decoder.h" +#include "native_avmemory.h" +#include "VDecEncNdkSample.h" + +using namespace OHOS; +using namespace OHOS::Media; +using namespace std; + +namespace { + constexpr uint32_t SAMPLE_DURATION_US = 23000; + constexpr uint32_t ES[] = { + 2106, 11465, 321, 72, 472, 68, 76, 79, 509, 90, 677, 88, 956, 99, 347, 77, 452, 681, 81, 1263, 94, 106, 97, + 998, 97, 797, 93, 1343, 150, 116, 117, 926, 1198, 128, 110, 78, 1582, 158, 135, 112, 1588, 165, 132, + 128, 1697, 168, 149, 117, 1938, 170, 141, 142, 1830, 106, 161, 122, 1623, 160, 154, 156, 1998, 230, + 177, 139, 1650, 186, 128, 134, 1214, 122, 1411, 120, 1184, 128, 1591, 195, 145, 105, 1587, 169, 140, + 118, 1952, 177, 150, 161, 1437, 159, 123, 1758, 180, 165, 144, 1936, 214, 191, 175, 2122, 180, 179, + 160, 1927, 161, 184, 119, 1973, 218, 210, 129, 1962, 196, 127, 154, 2308, 173, 127, 1572, 142, 122, + 2065, 262, 159, 206, 2251, 269, 179, 170, 2056, 308, 168, 191, 2090, 303, 191, 110, 1932, 272, 162, + 122, 1877, 245, 167, 141, 1908, 294, 162, 118, 1493, 132, 1782, 273, 184, 133, 1958, 274, 180, 149, + 2070, 216, 169, 143, 1882, 224, 149, 139, 1749, 277, 184, 139, 2141, 197, 170, 140, 2002, 269, 162, + 140, 1862, 202, 179, 131, 1868, 214, 164, 140, 1546, 226, 150, 130, 1707, 162, 146, 1824, 181, 147, + 130, 1898, 209, 143, 131, 1805, 180, 148, 106, 1776, 147, 141, 1572, 177, 130, 105, 1776, 178, 144, + 122, 1557, 142, 124, 114, 1436, 143, 126, 1326, 127, 1755, 169, 127, 105, 1807, 177, 131, 134, 1613, + 187, 137, 136, 1314, 134, 118, 2005, 194, 129, 147, 1566, 185, 132, 131, 1236, 174, 137, 106, 11049, + 574, 126, 1242, 188, 130, 119, 1450, 187, 137, 141, 1116, 124, 1848, 138, 122, 1605, 186, 127, 140, + 1798, 170, 124, 121, 1666, 157, 128, 130, 1678, 135, 118, 1804, 169, 135, 125, 1837, 168, 124, 124}; + constexpr uint32_t ES_LENGTH = sizeof(ES) / sizeof(uint32_t); + constexpr int32_t STOPNUM = 10000; + + void VdecAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData) + { + cout << "DEC Error errorCode=" << errorCode << endl; + VDecEncSignal* vcodecSignal_ = static_cast(userData); + vcodecSignal_->errorNum_ += 1; + } + + void VdecAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) + { + cout << "DEC Format Changed" << endl; + } + void VdecAsyncNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData) + { + VDecEncSignal* vcodecSignal_ = static_cast(userData); + unique_lock lock(vcodecSignal_->inMutexDec_); + if (vcodecSignal_->isVdecFlushing_.load()) { + cout << "VdecAsyncNeedInputData isVdecFlushing_ is true, return" << endl; + return; + } + vcodecSignal_->inQueueDec_.push(index); + vcodecSignal_->inBufferQueueDec_.push(data); + vcodecSignal_->inCondDec_.notify_all(); + } + + void VdecAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, + OH_AVCodecBufferAttr *attr, void *userData) + { + VDecEncSignal* vcodecSignal_ = static_cast(userData); + unique_lock lock(vcodecSignal_->outMutexDec_); + if (vcodecSignal_->isVdecFlushing_.load()) { + cout << "VdecAsyncNeedInputData isVdecFlushing_ is true, return" << endl; + return; + } + vcodecSignal_->outQueueDec_.push(index); + vcodecSignal_->flagQueueDec_.push(attr->flags); + vcodecSignal_->outCondDec_.notify_all(); + } + + + void VencAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData) + { + cout << "ENC Error errorCode=" << errorCode << endl; + VDecEncSignal* vcodecSignal_ = static_cast(userData); + vcodecSignal_->errorNum_ += 1; + } + + void VencAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) + { + cout << "ENC Format Changed" << endl; + } + + void VencAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, + OH_AVCodecBufferAttr *attr, void *userData) + { + VDecEncSignal* vcodecSignal_ = static_cast(userData); + unique_lock lock(vcodecSignal_->outMutexEnc_); + if (vcodecSignal_->isVencFlushing_.load()) { + cout << "VdecAsyncNeedInputData isVencFlushing_ is true, return" << endl; + return; + } + vcodecSignal_->outQueueEnc_.push(index); + vcodecSignal_->sizeQueueEnc_.push(attr->size); + vcodecSignal_->flagQueueEnc_.push(attr->flags); + vcodecSignal_->outBufferQueueEnc_.push(data); + vcodecSignal_->outCondEnc_.notify_all(); + } + + void clearIntqueue (std::queue& q) + { + std::queue empty; + swap(empty, q); + } + + void clearBufferqueue (std::queue& q) + { + std::queue empty; + swap(empty, q); + } +} + +VDecEncNdkSample::~VDecEncNdkSample() +{ + OH_VideoDecoder_Destroy(vdec_); + OH_VideoEncoder_Destroy(venc_); + + delete vcodecSignal_; + vcodecSignal_ = nullptr; +} + +void VDecEncNdkSample::SetReadPath(std::string filepath) +{ + inFile_ = filepath; + if (testFile_ == nullptr) { + testFile_ = std::make_unique(); + } + testFile_->open(inFile_, std::ios::in | std::ios::binary); +} + +void VDecEncNdkSample::SetSavePath(std::string filepath) +{ + outFile_ = filepath; +} + +void VDecEncNdkSample::SetEosState(bool needSetEos) +{ + setEos = needSetEos; +} + +void VDecEncNdkSample::ReRead() +{ + if (testFile_ != nullptr) { + testFile_->close(); + cout << "ReRead close before file success " << endl; + } + cout << "ReRead inFile is " << inFile_ << endl; + testFile_->open(inFile_, std::ios::in | std::ios::binary); + if (testFile_ != nullptr) { + cout << "testFile open success" << endl; + } + decInCnt_ = 0; + isFirstDecFrame_ = true; + timeStampDec_ = 0; +} + +void VDecEncNdkSample::ResetDecParam() +{ + decInCnt_ = 0; + decOutCnt_ = 0; + isDecInputEOS = false; + isDecOutputEOS = false; + unique_lock lockIn(vcodecSignal_->inMutexDec_); + clearIntqueue(vcodecSignal_->inQueueDec_); + clearBufferqueue(vcodecSignal_->inBufferQueueDec_); + vcodecSignal_->inCondDec_.notify_all(); + unique_lock lockOut(vcodecSignal_->outMutexDec_); + clearIntqueue(vcodecSignal_->outQueueDec_); + clearIntqueue(vcodecSignal_->flagQueueDec_); + clearBufferqueue(vcodecSignal_->outBufferQueueDec_); + vcodecSignal_->outCondDec_.notify_all(); + isDecRunning_.store(true); + cout << "isDecRunning_.load() is " << isDecRunning_.load() << endl; +} +void VDecEncNdkSample::ResetEncParam() +{ + encOutCnt_ = 0; + isEncInputEOS = false; + isEncOutputEOS = false; + unique_lock lockOut(vcodecSignal_->outMutexEnc_); + clearIntqueue(vcodecSignal_->outQueueEnc_); + clearIntqueue(vcodecSignal_->sizeQueueEnc_); + clearIntqueue(vcodecSignal_->flagQueueEnc_); + clearBufferqueue(vcodecSignal_->outBufferQueueEnc_); + vcodecSignal_->outCondEnc_.notify_all(); + isEncRunning_.store(true); + cout << "isEncRunning_.load() is " << isEncRunning_.load() << endl; +} + +struct OH_AVCodec* VDecEncNdkSample::CreateVideoDecoderByMime(std::string mimetype) +{ + vdec_ = OH_VideoDecoder_CreateByMime(mimetype.c_str()); + NDK_CHECK_AND_RETURN_RET_LOG(vdec_ != nullptr, nullptr, "Fatal: OH_VideoDecoder_CreateByMime"); + if (vcodecSignal_ == nullptr) { + vcodecSignal_ = new VDecEncSignal(); + NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory"); + } + cbDec_.onError = VdecAsyncError; + cbDec_.onStreamChanged = VdecAsyncStreamChanged; + cbDec_.onNeedInputData = VdecAsyncNeedInputData; + cbDec_.onNeedOutputData = VdecAsyncNewOutputData; + int32_t ret = OH_VideoDecoder_SetCallback(vdec_, cbDec_, static_cast(vcodecSignal_)); + NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoDecoder_SetCallback"); + return vdec_; +} + +struct OH_AVCodec* VDecEncNdkSample::CreateVideoDecoderByName(std::string name) +{ + vdec_ = OH_VideoDecoder_CreateByName(name.c_str()); + NDK_CHECK_AND_RETURN_RET_LOG(vdec_ != nullptr, nullptr, "Fatal: OH_VideoDecoder_CreateByName"); + if (vcodecSignal_ == nullptr) { + vcodecSignal_ = new VDecEncSignal(); + NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory"); + } + cbDec_.onError = VdecAsyncError; + cbDec_.onStreamChanged = VdecAsyncStreamChanged; + cbDec_.onNeedInputData = VdecAsyncNeedInputData; + cbDec_.onNeedOutputData = VdecAsyncNewOutputData; + int32_t ret = OH_VideoDecoder_SetCallback(vdec_, cbDec_, static_cast(vcodecSignal_)); + NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoDecoder_SetCallback"); + return vdec_; +} + +int32_t VDecEncNdkSample::ConfigureDec(struct OH_AVFormat *format) +{ + return OH_VideoDecoder_Configure(vdec_, format); +} + +int32_t VDecEncNdkSample::PrepareDec() +{ + return OH_VideoDecoder_Prepare(vdec_); +} + +int32_t VDecEncNdkSample::StartDec() +{ + cout << "Enter dec start" << endl; + isDecRunning_.store(true); + + if (inputLoopDec_ == nullptr) { + inputLoopDec_ = make_unique(&VDecEncNdkSample::InputFuncDec, this); + NDK_CHECK_AND_RETURN_RET_LOG(inputLoopDec_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory"); + } + if (outputLoopDec_ == nullptr) { + outputLoopDec_ = make_unique(&VDecEncNdkSample::OutputFuncDec, this); + NDK_CHECK_AND_RETURN_RET_LOG(outputLoopDec_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory"); + } + cout << "Exit dec start" << endl; + return OH_VideoDecoder_Start(vdec_); +} + +int32_t VDecEncNdkSample::StopDec() +{ + cout << "ENTER DEC stop" << endl; + unique_lock lock(vcodecSignal_->inMutexDec_); + unique_lock lock2(vcodecSignal_->outMutexDec_); + vcodecSignal_->isVdecFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_VideoDecoder_Stop(vdec_); + unique_lock lockIn(vcodecSignal_->inMutexDec_); + clearIntqueue(vcodecSignal_->inQueueDec_); + clearBufferqueue(vcodecSignal_->inBufferQueueDec_); + vcodecSignal_->inCondDec_.notify_all(); + lockIn.unlock(); + unique_lock lockOut(vcodecSignal_->outMutexDec_); + clearIntqueue(vcodecSignal_->outQueueDec_); + clearIntqueue(vcodecSignal_->flagQueueDec_); + clearBufferqueue(vcodecSignal_->outBufferQueueDec_); + vcodecSignal_->outCondDec_.notify_all(); + lockOut.unlock(); + vcodecSignal_->isVdecFlushing_.store(false); + cout << "EXIT DEC stop" << endl; + return ret; +} + +int32_t VDecEncNdkSample::FlushDec() +{ + cout << "ENTER DEC FLUSH" << endl; + unique_lock lock(vcodecSignal_->inMutexDec_); + unique_lock lock2(vcodecSignal_->outMutexDec_); + vcodecSignal_->isVdecFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_VideoDecoder_Flush(vdec_); + unique_lock lockIn(vcodecSignal_->inMutexDec_); + clearIntqueue(vcodecSignal_->inQueueDec_); + clearBufferqueue(vcodecSignal_->inBufferQueueDec_); + vcodecSignal_->inCondDec_.notify_all(); + lockIn.unlock(); + unique_lock lockOut(vcodecSignal_->outMutexDec_); + clearIntqueue(vcodecSignal_->outQueueDec_); + clearIntqueue(vcodecSignal_->flagQueueDec_); + clearBufferqueue(vcodecSignal_->outBufferQueueDec_); + vcodecSignal_->outCondDec_.notify_all(); + lockOut.unlock(); + vcodecSignal_->isVdecFlushing_.store(false); + cout << "EXIT DEC FLUSH" << endl; + return ret; +} + +int32_t VDecEncNdkSample::ResetDec() +{ + cout << "Enter DEC reset" << endl; + unique_lock lock(vcodecSignal_->inMutexDec_); + unique_lock lock2(vcodecSignal_->outMutexDec_); + vcodecSignal_->isVdecFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_VideoDecoder_Reset(vdec_); + unique_lock lockIn(vcodecSignal_->inMutexDec_); + clearIntqueue(vcodecSignal_->inQueueDec_); + clearBufferqueue(vcodecSignal_->inBufferQueueDec_); + vcodecSignal_->inCondDec_.notify_all(); + lockIn.unlock(); + unique_lock lockOut(vcodecSignal_->outMutexDec_); + clearIntqueue(vcodecSignal_->outQueueDec_); + clearIntqueue(vcodecSignal_->flagQueueDec_); + clearBufferqueue(vcodecSignal_->outBufferQueueDec_); + vcodecSignal_->outCondDec_.notify_all(); + lockOut.unlock(); + vcodecSignal_->isVdecFlushing_.store(false); + cout << "Exit DEC reset" << endl; + return ret; +} + +int32_t VDecEncNdkSample::ReleaseDec() +{ + cout << "Enter DEC release" << endl; + isDecRunning_.store(false); + if (inputLoopDec_ != nullptr && inputLoopDec_->joinable()) { + unique_lock lock(vcodecSignal_->inMutexDec_); + vcodecSignal_->inQueueDec_.push(STOPNUM); + vcodecSignal_->inCondDec_.notify_all(); + lock.unlock(); + inputLoopDec_->join(); + inputLoopDec_.reset(); + } + if (outputLoopDec_ != nullptr && outputLoopDec_->joinable()) { + unique_lock lock(vcodecSignal_->outMutexDec_); + vcodecSignal_->outQueueDec_.push(STOPNUM); + vcodecSignal_->outCondDec_.notify_all(); + lock.unlock(); + outputLoopDec_->join(); + outputLoopDec_.reset(); + } + OH_VideoDecoder_Destroy(vdec_); + cout << "Exit DEC release" << endl; + return AV_ERR_OK; +} + +void VDecEncNdkSample::PopInqueueDec() +{ + if (vcodecSignal_ == nullptr) { + return; + } + vcodecSignal_->inQueueDec_.pop(); + vcodecSignal_->inBufferQueueDec_.pop(); +} + +int32_t VDecEncNdkSample::PushInbufferDec(uint32_t index, uint32_t bufferSize) +{ + if (vdec_ == nullptr) { + return AV_ERR_INVALID_VAL; + } + struct OH_AVCodecBufferAttr attr; + attr.offset = 0; + if (decInCnt_ == ES_LENGTH) { + attr.flags = AVCODEC_BUFFER_FLAGS_EOS; + attr.pts = 0; + attr.size = 0; + cout << "EOS Frame, frameCount = " << decInCnt_ << endl; + isDecInputEOS = true; + } else { + attr.pts = timeStampDec_; + attr.size = bufferSize; + if (isFirstDecFrame_) { + attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA; + isFirstDecFrame_ = false; + } else { + attr.flags = AVCODEC_BUFFER_FLAGS_NONE; + } + } + return OH_VideoDecoder_PushInputData(vdec_, index, attr); +} + +void VDecEncNdkSample::InputFuncDec() +{ + while (true) { + cout << "ENTER DEC IN" << endl; + if (!isDecRunning_.load()) { + break; + } + unique_lock lock(vcodecSignal_->inMutexDec_); + vcodecSignal_->inCondDec_.wait(lock, [this]() { return vcodecSignal_->inQueueDec_.size() > 0; }); + if (!isDecRunning_.load()) { + break; + } + + uint32_t index = vcodecSignal_->inQueueDec_.front(); + OH_AVMemory *buffer = reinterpret_cast(vcodecSignal_->inBufferQueueDec_.front()); + if (vcodecSignal_->isVdecFlushing_.load() || isDecInputEOS || buffer == nullptr) { + PopInqueueDec(); + continue; + } + NDK_CHECK_AND_RETURN_LOG(testFile_ != nullptr && testFile_->is_open(), "Fatal: open file fail"); + uint32_t bufferSize = 0; + if (decInCnt_ < ES_LENGTH) { + bufferSize = ES[decInCnt_]; + char *fileBuffer = (char *)malloc(sizeof(char) * bufferSize + 1); + NDK_CHECK_AND_RETURN_LOG(fileBuffer != nullptr, "Fatal: malloc fail"); + (void)testFile_->read(fileBuffer, bufferSize); + if (testFile_->eof()) { + free(fileBuffer); + cout << "Finish" << endl; + break; + } + if (memcpy_s(OH_AVMemory_GetAddr(buffer), OH_AVMemory_GetSize(buffer), fileBuffer, bufferSize) != EOK + || buffer == nullptr) { + free(fileBuffer); + PopInqueueDec(); + continue; + } + free(fileBuffer); + } + if (PushInbufferDec(index, bufferSize) != AV_ERR_OK) { + cout << "Fatal: OH_VideoDecoder_PushInputData fail, exit" << endl; + vcodecSignal_->errorNum_ += 1; + } else { + decInCnt_++; + } + timeStampDec_ += SAMPLE_DURATION_US; + PopInqueueDec(); + } +} + +void VDecEncNdkSample::PopOutqueueDec() +{ + if (vcodecSignal_ == nullptr) { + return; + } + vcodecSignal_->outQueueDec_.pop(); + vcodecSignal_->flagQueueDec_.pop(); +} + +void VDecEncNdkSample::SendEncEos() +{ + if (vcodecSignal_ == nullptr || venc_== nullptr) { + return; + } + if (setEos) { + int32_t ret = OH_VideoEncoder_NotifyEndOfStream(venc_); + if (ret == 0) { + cout << "ENC IN: input EOS " << endl; + isEncInputEOS = true; + } else { + cout << "ENC IN: input EOS fail" << endl; + vcodecSignal_->errorNum_ += 1; + } + } +} + +void VDecEncNdkSample::OutputFuncDec() +{ + while (true) { + if (!isDecRunning_.load()) { + break; + } + unique_lock lock(vcodecSignal_->outMutexDec_); + vcodecSignal_->outCondDec_.wait(lock, [this]() { return vcodecSignal_->outQueueDec_.size() > 0; }); + if (!isDecRunning_.load()) { + break; + } + if (vcodecSignal_->isVdecFlushing_.load() || vcodecSignal_->isVencFlushing_.load() || isEncInputEOS) { + PopOutqueueDec(); + continue; + } + + uint32_t index = vcodecSignal_->outQueueDec_.front(); + uint32_t outflag = vcodecSignal_->flagQueueDec_.front(); + if (outflag == 0) { + uint32_t ret = OH_VideoDecoder_RenderOutputData(vdec_, index); + if (ret == 0) { + decOutCnt_ += 1; + cout << "DEC OUT.: render output success, decOutCnt_ is " << decOutCnt_ << endl; + } else { + cout << "DEC OUT. Fatal: ReleaseOutputBuffer fail" << endl; + vcodecSignal_->errorNum_ += 1; + break; + } + } else { + cout << "DEC OUT.: output EOS" << endl; + isDecOutputEOS = true; + SendEncEos(); + } + PopOutqueueDec(); + } +} + +struct OH_AVCodec* VDecEncNdkSample::CreateVideoEncoderByMime(std::string mimetype) +{ + venc_ = OH_VideoEncoder_CreateByMime(mimetype.c_str()); + NDK_CHECK_AND_RETURN_RET_LOG(venc_ != nullptr, nullptr, "Fatal: OH_VideoEncoder_CreateByMime"); + + if (vcodecSignal_ == nullptr) { + vcodecSignal_ = new VDecEncSignal(); + NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory"); + } + cbEnc_.onError = VencAsyncError; + cbEnc_.onStreamChanged = VencAsyncStreamChanged; + cbEnc_.onNeedOutputData = VencAsyncNewOutputData; + int32_t ret = OH_VideoEncoder_SetCallback(venc_, cbEnc_, static_cast(vcodecSignal_)); + NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoEncoder_SetCallback"); + return venc_; +} + +struct OH_AVCodec* VDecEncNdkSample::CreateVideoEncoderByName(std::string name) +{ + venc_ = OH_VideoEncoder_CreateByName(name.c_str()); + NDK_CHECK_AND_RETURN_RET_LOG(venc_ != nullptr, nullptr, "Fatal: OH_VideoEncoder_CreateByName"); + + if (vcodecSignal_ == nullptr) { + vcodecSignal_ = new VDecEncSignal(); + NDK_CHECK_AND_RETURN_RET_LOG(vcodecSignal_ != nullptr, nullptr, "Fatal: No Memory"); + } + cbEnc_.onError = VencAsyncError; + cbEnc_.onStreamChanged = VencAsyncStreamChanged; + cbEnc_.onNeedOutputData = VencAsyncNewOutputData; + int32_t ret = OH_VideoEncoder_SetCallback(venc_, cbEnc_, static_cast(vcodecSignal_)); + NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_VideoEncoder_SetCallback"); + return venc_; +} + +int32_t VDecEncNdkSample::ConfigureEnc(struct OH_AVFormat *format) +{ + return OH_VideoEncoder_Configure(venc_, format); +} + +struct VEncObject : public OH_AVCodec { + explicit VEncObject(const std::shared_ptr &encoder) + : OH_AVCodec(AVMagic::MEDIA_MAGIC_VIDEO_ENCODER), videoEncoder_(encoder) {} + ~VEncObject() = default; + + const std::shared_ptr videoEncoder_; +}; + +int32_t VDecEncNdkSample::GetSurface() +{ + return OH_VideoEncoder_GetSurface(venc_, &nativeWindow_); +} + +struct VDecObject : public OH_AVCodec { + explicit VDecObject(const std::shared_ptr &decoder) + : OH_AVCodec(AVMagic::MEDIA_MAGIC_VIDEO_DECODER), videoDecoder_(decoder) {} + ~VDecObject() = default; + + const std::shared_ptr videoDecoder_; +}; + +int32_t VDecEncNdkSample::SetOutputSurface() +{ + return OH_VideoDecoder_SetSurface(vdec_, nativeWindow_); +} + +int32_t VDecEncNdkSample::PrepareEnc() +{ + return OH_VideoEncoder_Prepare(venc_); +} + +int32_t VDecEncNdkSample::StartEnc() +{ + cout << "Enter enc start" << endl; + isEncRunning_.store(true); + if (outputLoopEnc_ == nullptr) { + outputLoopEnc_ = make_unique(&VDecEncNdkSample::OutputFuncEnc, this); + NDK_CHECK_AND_RETURN_RET_LOG(outputLoopEnc_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory"); + } + cout << "Exit enc start" << endl; + return OH_VideoEncoder_Start(venc_); +} + +int32_t VDecEncNdkSample::StopEnc() +{ + cout << "Enter enc stop" << endl; + unique_lock lock(vcodecSignal_->outMutexEnc_); + vcodecSignal_->isVencFlushing_.store(true); + lock.unlock(); + int32_t ret = OH_VideoEncoder_Stop(venc_); + unique_lock lockOut(vcodecSignal_->outMutexEnc_); + clearIntqueue(vcodecSignal_->outQueueEnc_); + clearIntqueue(vcodecSignal_->sizeQueueEnc_); + clearIntqueue(vcodecSignal_->flagQueueEnc_); + clearBufferqueue(vcodecSignal_->outBufferQueueEnc_); + vcodecSignal_->outCondEnc_.notify_all(); + lockOut.unlock(); + vcodecSignal_->isVencFlushing_.store(false); + cout << "Exit enc stop" << endl; + return ret; +} + +int32_t VDecEncNdkSample::FlushEnc() +{ + cout << "Enter enc flush" << endl; + unique_lock lock(vcodecSignal_->outMutexEnc_); + vcodecSignal_->isVencFlushing_.store(true); + lock.unlock(); + int32_t ret = OH_VideoEncoder_Flush(venc_); + unique_lock lockOut(vcodecSignal_->outMutexEnc_); + clearIntqueue(vcodecSignal_->outQueueEnc_); + clearIntqueue(vcodecSignal_->sizeQueueEnc_); + clearIntqueue(vcodecSignal_->flagQueueEnc_); + clearBufferqueue(vcodecSignal_->outBufferQueueEnc_); + vcodecSignal_->outCondEnc_.notify_all(); + lockOut.unlock(); + vcodecSignal_->isVencFlushing_.store(false); + cout << "Exit enc flush" << endl; + return ret; +} + +int32_t VDecEncNdkSample::ResetEnc() +{ + cout << "Enter enc reset" << endl; + unique_lock lock(vcodecSignal_->outMutexEnc_); + vcodecSignal_->isVencFlushing_.store(true); + lock.unlock(); + int32_t ret = OH_VideoEncoder_Reset(venc_); + unique_lock lockOut(vcodecSignal_->outMutexEnc_); + clearIntqueue(vcodecSignal_->outQueueEnc_); + clearIntqueue(vcodecSignal_->sizeQueueEnc_); + clearIntqueue(vcodecSignal_->flagQueueEnc_); + clearBufferqueue(vcodecSignal_->outBufferQueueEnc_); + vcodecSignal_->outCondEnc_.notify_all(); + lockOut.unlock(); + vcodecSignal_->isVencFlushing_.store(false); + cout << "exit enc reset" << endl; + return ret; +} + +int32_t VDecEncNdkSample::ReleaseEnc() +{ + cout << "Enter enc release" << endl; + isEncRunning_.store(false); + if (outputLoopEnc_ != nullptr && outputLoopEnc_->joinable()) { + unique_lock lock(vcodecSignal_->outMutexEnc_); + vcodecSignal_->outQueueEnc_.push(STOPNUM); + vcodecSignal_->outCondEnc_.notify_all(); + lock.unlock(); + outputLoopEnc_->join(); + outputLoopEnc_.reset(); + } + cout << "exit enc release" << endl; + OH_VideoEncoder_Destroy(venc_); + cout << "exit enc destroy" << endl; + return AV_ERR_OK; +} + +void VDecEncNdkSample::PopOutqueueEnc() +{ + if (vcodecSignal_ == nullptr) { + return; + } + vcodecSignal_->outQueueEnc_.pop(); + vcodecSignal_->sizeQueueEnc_.pop(); + vcodecSignal_->flagQueueEnc_.pop(); + vcodecSignal_->outBufferQueueEnc_.pop(); +} + +int32_t VDecEncNdkSample::WriteToFile() +{ + auto buffer = vcodecSignal_->outBufferQueueEnc_.front(); + uint32_t size = vcodecSignal_->sizeQueueEnc_.front(); + if (buffer == nullptr) { + cout << "getOutPut Buffer fail" << endl; + return AV_ERR_INVALID_VAL; + } + FILE *outFile = fopen(outFile_.c_str(), "a"); + if (outFile == nullptr) { + cout << "dump data fail" << endl; + return AV_ERR_INVALID_VAL; + } else { + fwrite(OH_AVMemory_GetAddr(buffer), 1, size, outFile); + } + return fclose(outFile); +} + +void VDecEncNdkSample::OutputFuncEnc() +{ + while (true) { + if (!isEncRunning_.load()) { + break; + } + unique_lock lock(vcodecSignal_->outMutexEnc_); + vcodecSignal_->outCondEnc_.wait(lock, [this]() { return vcodecSignal_->outQueueEnc_.size() > 0; }); + if (!isEncRunning_.load()) { + break; + } + if (vcodecSignal_->isVencFlushing_.load() || isEncOutputEOS) { + PopOutqueueEnc(); + continue; + } + + uint32_t index = vcodecSignal_->outQueueEnc_.front(); + uint32_t encOutflag = vcodecSignal_->flagQueueEnc_.front(); + if (encOutflag == 1) { + cout << "ENC get output EOS" << endl; + isEncOutputEOS = true; + } else { + if (WriteToFile() != 0) { + PopOutqueueEnc(); + continue; + } + uint32_t ret = OH_VideoEncoder_FreeOutputData(venc_, index); + if (ret != 0) { + cout << "Fatal: ReleaseOutputBuffer fail" << endl; + vcodecSignal_->errorNum_ += 1; + } else { + encOutCnt_ += 1; + cout << "ENC OUT.: output success, encOutCnt_ is " << encOutCnt_ << endl; + } + } + PopOutqueueEnc(); + } +} + +int32_t VDecEncNdkSample::CalcuError() +{ + cout << "errorNum_ is :" << vcodecSignal_->errorNum_ << endl; + cout << "decInCnt_ is :" << decInCnt_ << endl; + cout << "decOutCnt_ is :" << decOutCnt_ << endl; + cout << "encOutCnt_ is :" << encOutCnt_ << endl; + cout << "DEC inQueueDec_.size() is " << vcodecSignal_->inQueueDec_.size() << endl; + cout << "DEC outQueueDec_.size() is " << vcodecSignal_->outQueueDec_.size() << endl; + cout << "DEC outBufferQueueDec_.size() is " << vcodecSignal_->outBufferQueueDec_.size() << endl; + cout << "DEC outQueueEnc_.size() is " << vcodecSignal_->outQueueEnc_.size() << endl; + return vcodecSignal_->errorNum_ ; +} + +int32_t VDecEncNdkSample::GetFrameCount() +{ + return encOutCnt_; +} +bool VDecEncNdkSample::GetEncEosState() +{ + return isEncOutputEOS; +} +bool VDecEncNdkSample::GetDecEosState() +{ + return isDecOutputEOS; +} \ No newline at end of file -- GitLab