diff --git a/multimedia/media/media_cpp_standard/audioDecEncNdk/include/ADecEncNdkSample.h b/multimedia/media/media_cpp_standard/audioDecEncNdk/include/ADecEncNdkSample.h new file mode 100644 index 0000000000000000000000000000000000000000..ea8bc106c1b3657d19d0530f6e9471ac18d3218f --- /dev/null +++ b/multimedia/media/media_cpp_standard/audioDecEncNdk/include/ADecEncNdkSample.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 AUDIODECENC_NDK_SAMPLE_H +#define AUDIODECENC_NDK_SAMPLE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "native_avcodec_base.h" +#include "native_avcodec_audiodecoder.h" +#include "native_avcodec_audioencoder.h" +#include "nocopyable.h" +#include "ndktest_log.h" + +namespace OHOS { +namespace Media { +class ADecEncSignal { +public: + std::mutex inMutexDec_; + std::condition_variable inCondDec_; + std::queue inQueueDec_; + std::queue outQueueDec_; + std::queue sizeQueueDec_; + std::queue flagQueueDec_; + std::queue inBufferQueueDec_; + std::queue outBufferQueueDec_; + + std::mutex inMutexEnc_; + std::mutex outMutexEnc_; + std::condition_variable inCondEnc_; + 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 isFlushing_ = false; +}; + +class ADecEncNdkSample : public NoCopyable { +public: + ADecEncNdkSample() = default; + ~ADecEncNdkSample(); + + struct OH_AVCodec* CreateAudioDecoder(std::string mimetype); + int32_t ConfigureDec(struct OH_AVFormat *format); + int32_t PrepareDec(); + int32_t StartDec(); + int32_t StopDec(); + int32_t FlushDec(); + int32_t ResetDec(); + int32_t ReleaseDec(); + + struct OH_AVCodec* CreateAudioEncoder(std::string mimetype); + int32_t ConfigureEnc(struct OH_AVFormat *format); + int32_t PrepareEnc(); + int32_t StartEnc(); + int32_t StopEnc(); + int32_t FlushEnc(); + int32_t ResetEnc(); + int32_t ReleaseEnc(); + int32_t CalcuError(); + + void SetReadPath(const char* inp_path, uint32_t es[], uint32_t length); + void SetEosState(bool needSetEos); + void SetSavePath(const char* outp_path); + void ReRead(); + void ResetDecParam(); + void ResetEncParam(); + int32_t GetFrameCount(); + bool GetEncEosState(); + bool GetDecEosState(); + void PopInqueueDec(); + void PopOutqueueDec(); + void PopInqueueEnc(); + void PopOutqueueEnc(); + int32_t PushInbufferDec(uint32_t index, uint32_t bufferSize); + int32_t PushInbufferEnc(); + + ADecEncSignal* acodecSignal_ = nullptr; + uint32_t decInCnt_ = 0; + uint32_t decOutCnt_ = 0; + uint32_t encInCnt_ = 0; + uint32_t encOutCnt_ = 0; + bool isDecInputEOS = false; + bool isEncInputEOS = false; + bool isDecOutputEOS = false; + bool isEncOutputEOS = false; + bool setEos = true; + +private: + struct OH_AVCodec* adec_; + void InputFuncDec(); + std::atomic isDecRunning_ = false; + std::unique_ptr testFile_; + std::unique_ptr inputLoopDec_; + std::unique_ptr outputLoopDec_; + struct OH_AVCodecAsyncCallback cbDec_; + int64_t timeStampDec_ = 0; + struct OH_AVCodec* aenc_; + void InputFuncEnc(); + void OutputFuncEnc(); + int32_t WriteToFile(); + std::atomic isEncRunning_ = false; + std::unique_ptr inputLoopEnc_; + std::unique_ptr outputLoopEnc_; + struct OH_AVCodecAsyncCallback cbEnc_; + int64_t timeStampEnc_ = 0; + std::string outDir_ = "/data/media/out.aac"; + const char* INP_FILE; + const char* OUT_FILE; + uint32_t* ES; + uint32_t ES_LENGTH = 0; +}; +} +} +#endif // AUDIODECENC_NDK_SAMPLE_H diff --git a/multimedia/media/media_cpp_standard/audioDecEncNdk/include/ActsAudioDecEncNdkTest.h b/multimedia/media/media_cpp_standard/audioDecEncNdk/include/ActsAudioDecEncNdkTest.h new file mode 100644 index 0000000000000000000000000000000000000000..149dd75b950a717bcc8dac247177ca0d779be968 --- /dev/null +++ b/multimedia/media/media_cpp_standard/audioDecEncNdk/include/ActsAudioDecEncNdkTest.h @@ -0,0 +1,49 @@ +/* + * 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 ACTSAUDIODECODER_NDK_FUNC_TEST_H +#define ACTSAUDIODECODER_NDK_FUNC_TEST_H + +#include "gtest/gtest.h" +#include "ADecEncNdkSample.h" + +namespace OHOS { +namespace Media { +class ActsAudioDecEncNdkTest : public testing::Test { +public: + // Preset action of the test suite, which is executed before the first test case + static void SetUpTestCase(void) + { + printf("ActsAudioDecEncNdkTest::SetUpTestCase"); + } + // Test suite cleanup action, which is executed after the last test case + static void TearDownTestCase(void) + { + printf("ActsAudioDecEncNdkTest::TearDownTestCase"); + } + // Preset action of the test case + void SetUp(void) + { + printf("ActsAudioDecEncNdkTest::SetUp"); + } + // Cleanup action of the test case + virtual void TearDown(void) + { + printf("ActsAudioDecEncNdkTest::TearDown"); + } +}; +} +} +#endif // ACTSAUDIODECODER_NDK_FUNC_TEST_H \ No newline at end of file diff --git a/multimedia/media/media_cpp_standard/audioDecEncNdk/src/ADecEncNdkSample.cpp b/multimedia/media/media_cpp_standard/audioDecEncNdk/src/ADecEncNdkSample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b542b4ac87b604ba8befc7d7c309c37d054b472 --- /dev/null +++ b/multimedia/media/media_cpp_standard/audioDecEncNdk/src/ADecEncNdkSample.cpp @@ -0,0 +1,753 @@ +/* + * 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 "ADecEncNdkSample.h" +#include "native_avmemory.h" +#include "native_averrors.h" +using namespace OHOS; +using namespace OHOS::Media; +using namespace std; + +namespace { + constexpr uint32_t SAMPLE_DURATION_US = 23000; + constexpr uint32_t STOPNUM = 10000; + + void AdecAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData) + { + ADecEncSignal* acodecSignal_ = static_cast(userData); + cout << "DEC Error errorCode=" << errorCode << endl; + acodecSignal_->errorNum_ += 1; + } + + void AdecAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) + { + cout << "DEC Format Changed" << endl; + } + + void AdecAsyncNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData) + { + ADecEncSignal* acodecSignal_ = static_cast(userData); + unique_lock lock(acodecSignal_->inMutexDec_); + if (acodecSignal_->isFlushing_.load()) { + return; + } + acodecSignal_->inQueueDec_.push(index); + acodecSignal_->inBufferQueueDec_.push(data); + acodecSignal_->inCondDec_.notify_all(); + } + + void AdecAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, + OH_AVCodecBufferAttr *attr, void *userData) + { + ADecEncSignal* acodecSignal_ = static_cast(userData); + unique_lock lock(acodecSignal_->inMutexEnc_); + if (acodecSignal_->isFlushing_.load()) { + cout << "DEC OutputAvailable: isFlushing_.load() is true, return" << endl; + return; + } + acodecSignal_->outQueueDec_.push(index); + acodecSignal_->sizeQueueDec_.push(attr->size); + acodecSignal_->flagQueueDec_.push(attr->flags); + acodecSignal_->outBufferQueueDec_.push(data); + acodecSignal_->inCondEnc_.notify_all(); + } + + void AencAsyncError(OH_AVCodec *codec, int32_t errorCode, void *userData) + { + ADecEncSignal* acodecSignal_ = static_cast(userData); + cout << "ENC Error errorCode=" << errorCode << endl; + acodecSignal_->errorNum_ += 1; + } + + void AencAsyncStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) + { + cout << "ENC Format Changed" << endl; + } + + void AencAsyncNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData) + { + ADecEncSignal* acodecSignal_ = static_cast(userData); + unique_lock lock(acodecSignal_->inMutexEnc_); + if (acodecSignal_->isFlushing_.load()) { + return; + } + acodecSignal_->inQueueEnc_.push(index); + acodecSignal_->inBufferQueueEnc_.push(data); + acodecSignal_->inCondEnc_.notify_all(); + } + + void AencAsyncNewOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, + OH_AVCodecBufferAttr *attr, void *userData) + { + ADecEncSignal* acodecSignal_ = static_cast(userData); + unique_lock lock(acodecSignal_->outMutexEnc_); + if (acodecSignal_->isFlushing_.load()) { + return; + } + acodecSignal_->outQueueEnc_.push(index); + acodecSignal_->sizeQueueEnc_.push(attr->size); + acodecSignal_->flagQueueEnc_.push(attr->flags); + acodecSignal_->outBufferQueueEnc_.push(data); + acodecSignal_->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); + } +} + +ADecEncNdkSample::~ADecEncNdkSample() +{ + OH_AudioDecoder_Destroy(adec_); + OH_AudioEncoder_Destroy(aenc_); + delete acodecSignal_; + acodecSignal_ = nullptr; +} + +struct OH_AVCodec* ADecEncNdkSample::CreateAudioDecoder(std::string mimetype) +{ + adec_ = OH_AudioDecoder_CreateByMime(mimetype.c_str()); + NDK_CHECK_AND_RETURN_RET_LOG(adec_ != nullptr, nullptr, "Fatal: OH_AudioDecoder_CreateByMime"); + + acodecSignal_ = new ADecEncSignal(); + NDK_CHECK_AND_RETURN_RET_LOG(acodecSignal_ != nullptr, nullptr, "Fatal: No Memory"); + + cbDec_.onError = AdecAsyncError; + cbDec_.onStreamChanged = AdecAsyncStreamChanged; + cbDec_.onNeedInputData = AdecAsyncNeedInputData; + cbDec_.onNeedOutputData = AdecAsyncNewOutputData; + int32_t ret = OH_AudioDecoder_SetCallback(adec_, cbDec_, static_cast(acodecSignal_)); + NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_AudioDecoder_SetCallback"); + return adec_; +} + +int32_t ADecEncNdkSample::ConfigureDec(struct OH_AVFormat *format) +{ + return OH_AudioDecoder_Configure(adec_, format); +} + +int32_t ADecEncNdkSample::PrepareDec() +{ + return OH_AudioDecoder_Prepare(adec_); +} + +int32_t ADecEncNdkSample::StartDec() +{ + cout << "Enter start dec" << endl; + isDecRunning_.store(true); + if (testFile_ == nullptr) { + testFile_ = std::make_unique(); + NDK_CHECK_AND_RETURN_RET_LOG(testFile_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory"); + testFile_->open(INP_FILE, std::ios::in | std::ios::binary); + } + if (inputLoopDec_ == nullptr) { + inputLoopDec_ = make_unique(&ADecEncNdkSample::InputFuncDec, this); + NDK_CHECK_AND_RETURN_RET_LOG(inputLoopDec_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory"); + } + cout << "Exit start dec" << endl; + return OH_AudioDecoder_Start(adec_); +} + +void ADecEncNdkSample::ResetDecParam() +{ + isDecInputEOS = false; + isDecOutputEOS = false; + decInCnt_ = 0; + decOutCnt_ = 0; + acodecSignal_->isFlushing_.store(true); + unique_lock lock(acodecSignal_->inMutexDec_); + clearIntqueue(acodecSignal_->inQueueDec_); + clearBufferqueue(acodecSignal_->inBufferQueueDec_); + acodecSignal_->inCondDec_.notify_all(); + lock.unlock(); + unique_lock lock2(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->outQueueDec_); + clearIntqueue(acodecSignal_->sizeQueueDec_); + clearIntqueue(acodecSignal_->flagQueueDec_); + clearBufferqueue(acodecSignal_->outBufferQueueDec_); + acodecSignal_->inCondEnc_.notify_all(); + lock2.unlock(); + acodecSignal_->isFlushing_.store(false); + isDecRunning_.store(true); +} + +void ADecEncNdkSample::ResetEncParam() +{ + isEncInputEOS = false; + isEncOutputEOS = false; + encInCnt_ = 0; + encOutCnt_ = 0; + acodecSignal_->isFlushing_.store(true); + unique_lock lock(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->inQueueEnc_); + clearBufferqueue(acodecSignal_->inBufferQueueEnc_); + acodecSignal_->inCondEnc_.notify_all(); + lock.unlock(); + unique_lock lock2(acodecSignal_->outMutexEnc_); + clearIntqueue(acodecSignal_->outQueueEnc_); + clearIntqueue(acodecSignal_->sizeQueueEnc_); + clearIntqueue(acodecSignal_->flagQueueEnc_); + clearBufferqueue(acodecSignal_->outBufferQueueEnc_); + acodecSignal_->outCondEnc_.notify_all(); + lock2.unlock(); + acodecSignal_->isFlushing_.store(false); + isEncRunning_.store(true); +} + +int32_t ADecEncNdkSample::StopDec() +{ + cout << "ENTER DEC STOP" << endl; + unique_lock lock(acodecSignal_->inMutexDec_); + unique_lock lock2(acodecSignal_->inMutexEnc_); + acodecSignal_->isFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_AudioDecoder_Stop(adec_); + unique_lock lockIn(acodecSignal_->inMutexDec_); + clearIntqueue(acodecSignal_->inQueueDec_); + clearBufferqueue(acodecSignal_->inBufferQueueDec_); + acodecSignal_->inCondDec_.notify_all(); + unique_lock lockOut(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->outQueueDec_); + clearIntqueue(acodecSignal_->sizeQueueDec_); + clearIntqueue(acodecSignal_->flagQueueDec_); + clearBufferqueue(acodecSignal_->outBufferQueueDec_); + acodecSignal_->inCondEnc_.notify_all(); + acodecSignal_->isFlushing_.store(false); + lockIn.unlock(); + lockOut.unlock(); + cout << "EXIT DEC STOP" << endl; + return ret; +} + +int32_t ADecEncNdkSample::FlushDec() +{ + cout << "ENTER DEC FLUSH" << endl; + unique_lock lock(acodecSignal_->inMutexDec_); + unique_lock lock2(acodecSignal_->inMutexEnc_); + acodecSignal_->isFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_AudioDecoder_Flush(adec_); + unique_lock lockIn(acodecSignal_->inMutexDec_); + clearIntqueue(acodecSignal_->inQueueDec_); + clearBufferqueue(acodecSignal_->inBufferQueueDec_); + acodecSignal_->inCondDec_.notify_all(); + unique_lock lockOut(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->outQueueDec_); + clearIntqueue(acodecSignal_->sizeQueueDec_); + clearIntqueue(acodecSignal_->flagQueueDec_); + clearBufferqueue(acodecSignal_->outBufferQueueDec_); + acodecSignal_->inCondEnc_.notify_all(); + acodecSignal_->isFlushing_.store(false); + lockIn.unlock(); + lockOut.unlock(); + cout << "EXIT DEC FLUSH" << endl; + return ret; +} + +int32_t ADecEncNdkSample::ResetDec() +{ + cout << "enter Reset DEC" << endl; + unique_lock lock(acodecSignal_->inMutexDec_); + unique_lock lock2(acodecSignal_->inMutexEnc_); + acodecSignal_->isFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_AudioDecoder_Reset(adec_); + unique_lock lockIn(acodecSignal_->inMutexDec_); + clearIntqueue(acodecSignal_->inQueueDec_); + clearBufferqueue(acodecSignal_->inBufferQueueDec_); + acodecSignal_->inCondDec_.notify_all(); + unique_lock lockOut(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->outQueueDec_); + clearIntqueue(acodecSignal_->sizeQueueDec_); + clearIntqueue(acodecSignal_->flagQueueDec_); + clearBufferqueue(acodecSignal_->outBufferQueueDec_); + acodecSignal_->inCondEnc_.notify_all(); + acodecSignal_->isFlushing_.store(false); + lockIn.unlock(); + lockOut.unlock(); + cout << "exit Reset DEC" << endl; + return ret; +} + +int32_t ADecEncNdkSample::ReleaseDec() +{ + cout << "enter Release DEC" << endl; + isDecRunning_.store(false); + isEncRunning_.store(false); + cout << "isDecRunning_ set false" << endl; + if (inputLoopDec_ != nullptr && inputLoopDec_->joinable()) { + unique_lock lock(acodecSignal_->inMutexDec_); + acodecSignal_->inQueueDec_.push(STOPNUM); + acodecSignal_->inCondDec_.notify_all(); + lock.unlock(); + inputLoopDec_->join(); + inputLoopDec_.reset(); + } + OH_AudioDecoder_Destroy(adec_); + cout << "exit Release DEC" << endl; + return AV_ERR_OK; +} + +void ADecEncNdkSample::PopInqueueDec() +{ + if (acodecSignal_ == nullptr) { + return; + } + acodecSignal_->inQueueDec_.pop(); + acodecSignal_->inBufferQueueDec_.pop(); +} + +int32_t ADecEncNdkSample::PushInbufferDec(uint32_t index, uint32_t bufferSize) +{ + struct OH_AVCodecBufferAttr attr; + attr.offset = 0; + attr.flags = AVCODEC_BUFFER_FLAGS_NONE; + if (decInCnt_ == ES_LENGTH) { + cout << "DEC input: set EOS" << endl; + attr.flags = AVCODEC_BUFFER_FLAGS_EOS; + attr.pts = 0; + attr.size = 0; + isDecInputEOS = true; + } else { + attr.pts = timeStampDec_; + attr.size = bufferSize; + } + return OH_AudioDecoder_PushInputData(adec_, index, attr); +} + +void ADecEncNdkSample::InputFuncDec() +{ + while (true) { + if (!isDecRunning_.load()) { + break; + } + unique_lock lock(acodecSignal_->inMutexDec_); + acodecSignal_->inCondDec_.wait(lock, [this]() {return acodecSignal_->inQueueDec_.size() > 0; }); + if (!isDecRunning_.load()) { + break; + } + uint32_t index = acodecSignal_->inQueueDec_.front(); + OH_AVMemory *buffer = reinterpret_cast(acodecSignal_->inBufferQueueDec_.front()); + if (acodecSignal_->isFlushing_.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); + break; + } + if (memcpy_s(OH_AVMemory_GetAddr(buffer), OH_AVMemory_GetSize(buffer), + fileBuffer, bufferSize) != EOK) { + free(fileBuffer); + PopInqueueDec(); + break; + } + free(fileBuffer); + } + if (PushInbufferDec(index, bufferSize) != AV_ERR_OK) { + cout << "Fatal: OH_AudioDecoder_PushInputData fail" << endl; + acodecSignal_->errorNum_ += 1; + } else { + decInCnt_++; + } + timeStampDec_ += SAMPLE_DURATION_US; + PopInqueueDec(); + } +} + +struct OH_AVCodec* ADecEncNdkSample::CreateAudioEncoder(std::string mimetype) +{ + aenc_ = OH_AudioEncoder_CreateByMime(mimetype.c_str()); + NDK_CHECK_AND_RETURN_RET_LOG(aenc_ != nullptr, nullptr, "Fatal: OH_AudioEncoder_CreateByMime"); + cbEnc_.onError = AencAsyncError; + cbEnc_.onStreamChanged = AencAsyncStreamChanged; + cbEnc_.onNeedInputData = AencAsyncNeedInputData; + cbEnc_.onNeedOutputData = AencAsyncNewOutputData; + int32_t ret = OH_AudioEncoder_SetCallback(aenc_, cbEnc_, static_cast(acodecSignal_)); + NDK_CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, NULL, "Fatal: OH_AudioEncoder_SetCallback"); + return aenc_; +} + +int32_t ADecEncNdkSample::ConfigureEnc(struct OH_AVFormat *format) +{ + return OH_AudioEncoder_Configure(aenc_, format); +} + + +int32_t ADecEncNdkSample::PrepareEnc() +{ + return OH_AudioEncoder_Prepare(aenc_); +} + +int32_t ADecEncNdkSample::StartEnc() +{ + isEncRunning_.store(true); + if (inputLoopEnc_ == nullptr) { + inputLoopEnc_ = make_unique(&ADecEncNdkSample::InputFuncEnc, this); + NDK_CHECK_AND_RETURN_RET_LOG(inputLoopEnc_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory"); + } + if (outputLoopEnc_ == nullptr) { + outputLoopEnc_ = make_unique(&ADecEncNdkSample::OutputFuncEnc, this); + NDK_CHECK_AND_RETURN_RET_LOG(outputLoopEnc_ != nullptr, AV_ERR_UNKNOWN, "Fatal: No memory"); + } + return OH_AudioEncoder_Start(aenc_); +} + +int32_t ADecEncNdkSample::StopEnc() +{ + cout << "ENTER ENC STOP" << endl; + unique_lock lock(acodecSignal_->outMutexEnc_); + unique_lock lock2(acodecSignal_->inMutexEnc_); + acodecSignal_->isFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_AudioEncoder_Stop(aenc_); + unique_lock lockIn(acodecSignal_->outMutexEnc_); + clearIntqueue(acodecSignal_->outQueueEnc_); + clearIntqueue(acodecSignal_->sizeQueueEnc_); + clearIntqueue(acodecSignal_->flagQueueEnc_); + clearBufferqueue(acodecSignal_->outBufferQueueEnc_); + acodecSignal_->outCondEnc_.notify_all(); + unique_lock lockOut(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->inQueueEnc_); + clearBufferqueue(acodecSignal_->inBufferQueueEnc_); + acodecSignal_->inCondEnc_.notify_all(); + acodecSignal_->isFlushing_.store(false); + lockIn.unlock(); + lockOut.unlock(); + cout << "EXIT ENC STOP" << endl; + return ret; +} + +int32_t ADecEncNdkSample::FlushEnc() +{ + cout << "ENTER ENC FLUSH" << endl; + unique_lock lock(acodecSignal_->outMutexEnc_); + unique_lock lock2(acodecSignal_->inMutexEnc_); + acodecSignal_->isFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_AudioEncoder_Flush(aenc_); + unique_lock lockIn(acodecSignal_->outMutexEnc_); + clearIntqueue(acodecSignal_->outQueueEnc_); + clearIntqueue(acodecSignal_->sizeQueueEnc_); + clearIntqueue(acodecSignal_->flagQueueEnc_); + clearBufferqueue(acodecSignal_->outBufferQueueEnc_); + acodecSignal_->outCondEnc_.notify_all(); + unique_lock lockOut(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->inQueueEnc_); + clearBufferqueue(acodecSignal_->inBufferQueueEnc_); + acodecSignal_->inCondEnc_.notify_all(); + acodecSignal_->isFlushing_.store(false); + lockIn.unlock(); + lockOut.unlock(); + cout << "EXIT ENC FLUSH" << endl; + return ret; +} + +int32_t ADecEncNdkSample::ResetEnc() +{ + cout << "enter Reset ENC" << endl; + unique_lock lock(acodecSignal_->outMutexEnc_); + unique_lock lock2(acodecSignal_->inMutexEnc_); + acodecSignal_->isFlushing_.store(true); + lock.unlock(); + lock2.unlock(); + int32_t ret = OH_AudioEncoder_Reset(aenc_); + unique_lock lockIn(acodecSignal_->outMutexEnc_); + clearIntqueue(acodecSignal_->outQueueEnc_); + clearIntqueue(acodecSignal_->sizeQueueEnc_); + clearIntqueue(acodecSignal_->flagQueueEnc_); + clearBufferqueue(acodecSignal_->outBufferQueueEnc_); + acodecSignal_->outCondEnc_.notify_all(); + unique_lock lockOut(acodecSignal_->inMutexEnc_); + clearIntqueue(acodecSignal_->inQueueEnc_); + clearBufferqueue(acodecSignal_->inBufferQueueEnc_); + acodecSignal_->inCondEnc_.notify_all(); + acodecSignal_->isFlushing_.store(false); + lockIn.unlock(); + lockOut.unlock(); + cout << "exit Reset ENC" << endl; + return ret; +} + +int32_t ADecEncNdkSample::ReleaseEnc() +{ + cout << "enter Release ENC" << endl; + isEncRunning_.store(false); + cout << "set isEncRunning_ false success" << endl; + if (inputLoopEnc_ != nullptr && inputLoopEnc_->joinable()) { + cout << "enter inputLoopEnc_ set function " << endl; + unique_lock lock(acodecSignal_->inMutexEnc_); + acodecSignal_->outQueueDec_.push(STOPNUM); + acodecSignal_->inQueueEnc_.push(STOPNUM); + acodecSignal_->inCondEnc_.notify_all(); + lock.unlock(); + inputLoopEnc_->join(); + inputLoopEnc_.reset(); + } + cout << "set inputLoopEnc_ release success" << endl; + if (outputLoopEnc_ != nullptr && outputLoopEnc_->joinable()) { + unique_lock lock(acodecSignal_->outMutexEnc_); + acodecSignal_->outQueueEnc_.push(STOPNUM); + acodecSignal_->outCondEnc_.notify_all(); + lock.unlock(); + outputLoopEnc_->join(); + outputLoopEnc_.reset(); + } + OH_AudioEncoder_Destroy(aenc_); + cout << "exit RELEASE ENC" << endl; + return AV_ERR_OK; +} + +void ADecEncNdkSample::PopOutqueueDec() +{ + if (acodecSignal_ == nullptr) { + return; + } + acodecSignal_->outQueueDec_.pop(); + acodecSignal_->sizeQueueDec_.pop(); + acodecSignal_->flagQueueDec_.pop(); + acodecSignal_->outBufferQueueDec_.pop(); +} + +void ADecEncNdkSample::PopInqueueEnc() +{ + if (acodecSignal_ == nullptr) { + return; + } + acodecSignal_->inQueueEnc_.pop(); + acodecSignal_->inBufferQueueEnc_.pop(); +} + +int32_t ADecEncNdkSample::PushInbufferEnc() +{ + uint32_t indexEnc = acodecSignal_->inQueueEnc_.front(); + OH_AVMemory *bufferEnc = reinterpret_cast(acodecSignal_->inBufferQueueEnc_.front()); + if (bufferEnc == nullptr) { + cout << "Fatal: GetEncInputBuffer fail" << endl; + return AV_ERR_NO_MEMORY; + } + uint32_t indexDec = acodecSignal_->outQueueDec_.front(); + OH_AVMemory *bufferDec = acodecSignal_->outBufferQueueDec_.front(); + uint32_t sizeDecOut = acodecSignal_->sizeQueueDec_.front(); + uint32_t flagDecOut = acodecSignal_->flagQueueDec_.front(); + + struct OH_AVCodecBufferAttr attr; + attr.offset = 0; + attr.size = sizeDecOut; + attr.pts = timeStampEnc_; + attr.flags = 0; + if (flagDecOut == 1) { + cout << "DEC output EOS " << endl; + isDecOutputEOS = true; + cout << "set isDecOutputEOS = true " << endl; + if (setEos) { + isEncInputEOS = true; + attr.flags = 1; + } + } else { + if (memcpy_s(OH_AVMemory_GetAddr(bufferEnc), OH_AVMemory_GetSize(bufferEnc), + OH_AVMemory_GetAddr(bufferDec), sizeDecOut) != EOK) { + cout << "ENC input Fatal: memcpy fail" << endl; + PopOutqueueDec(); + PopInqueueEnc(); + return AV_ERR_OPERATE_NOT_PERMIT; + } + if (OH_AudioDecoder_FreeOutputData(adec_, indexDec) != AV_ERR_OK) { + cout << "Fatal: DEC ReleaseDecOutputBuffer fail" << endl; + acodecSignal_->errorNum_ += 1; + } else { + decOutCnt_ += 1; + } + } + return OH_AudioEncoder_PushInputData(aenc_, indexEnc, attr); +} + +void ADecEncNdkSample::InputFuncEnc() +{ + while (true) { + cout << "DEC enter InputFuncEnc()" << endl; + if (!isEncRunning_.load()) { + break; + } + unique_lock lock(acodecSignal_->inMutexEnc_); + acodecSignal_->inCondEnc_.wait(lock, [this]() { + return (acodecSignal_->inQueueEnc_.size() > 0 && acodecSignal_->outQueueDec_.size() > 0); + }); + + if (!isEncRunning_.load()) { + break; + } + if (acodecSignal_->isFlushing_.load() || isDecOutputEOS) { + PopOutqueueDec(); + PopInqueueEnc(); + continue; + } + if (PushInbufferEnc() != AV_ERR_OK) { + cout << "Fatal error, exit" << endl; + acodecSignal_->errorNum_ += 1; + } else { + encInCnt_++; + } + timeStampEnc_ += SAMPLE_DURATION_US; + PopOutqueueDec(); + PopInqueueEnc(); + } +} + +void ADecEncNdkSample::PopOutqueueEnc() +{ + if (acodecSignal_ == nullptr) { + return; + } + acodecSignal_->outQueueEnc_.pop(); + acodecSignal_->sizeQueueEnc_.pop(); + acodecSignal_->flagQueueEnc_.pop(); + acodecSignal_->outBufferQueueEnc_.pop(); +} + +int32_t ADecEncNdkSample::WriteToFile() +{ + auto buffer = acodecSignal_->outBufferQueueEnc_.front(); + if (buffer == nullptr) { + cout << "getOutPut Buffer fail" << endl; + return AV_ERR_INVALID_VAL; + } + uint32_t size = acodecSignal_->sizeQueueEnc_.front(); + FILE *outFile = fopen(OUT_FILE, "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 ADecEncNdkSample::OutputFuncEnc() +{ + while (true) { + if (!isEncRunning_.load()) { + break; + } + unique_lock lock(acodecSignal_->outMutexEnc_); + acodecSignal_->outCondEnc_.wait(lock, [this]() { return acodecSignal_->outQueueEnc_.size() > 0; }); + if (!isEncRunning_.load()) { + break; + } + if (acodecSignal_->isFlushing_.load() || isEncOutputEOS) { + PopOutqueueEnc(); + continue; + } + uint32_t index = acodecSignal_->outQueueEnc_.front(); + uint32_t encOutflag = acodecSignal_->flagQueueEnc_.front(); + if (encOutflag == 1) { + cout << "ENC get output EOS" << endl; + isEncOutputEOS = true; + } else { + if (WriteToFile() != 0) { + PopOutqueueEnc(); + continue; + } + if (OH_AudioEncoder_FreeOutputData(aenc_, index) != AV_ERR_OK) { + cout << "Fatal: ReleaseOutputBuffer fail" << endl; + acodecSignal_->errorNum_ += 1; + } else { + encOutCnt_ += 1; + cout << "ENC output cnt: " << encOutCnt_ << endl; + } + } + PopOutqueueEnc(); + } +} + +void ADecEncNdkSample::SetReadPath(const char * inp_path, uint32_t es[], uint32_t length) +{ + INP_FILE = inp_path; + ES = es; + ES_LENGTH = length; +} + +void ADecEncNdkSample::ReRead() +{ + if (testFile_ != nullptr) { + testFile_->close(); + cout << "ReRead close before file success " << endl; + } + cout << "ReRead INP_FILE is " << INP_FILE << endl; + testFile_->open(INP_FILE, std::ios::in | std::ios::binary); + if (testFile_ != nullptr) { + cout << "testFile open success" << endl; + } + decInCnt_ = 0; +} + +void ADecEncNdkSample::SetEosState(bool needSetEos) +{ + setEos = needSetEos; +} + +void ADecEncNdkSample::SetSavePath(const char * outp_path) +{ + OUT_FILE = outp_path; +} + +int32_t ADecEncNdkSample::CalcuError() +{ + cout << "errorNum_ is :" << acodecSignal_->errorNum_ << endl; + cout << "decInCnt_ is :" << decInCnt_ << endl; + cout << "decOutCnt_ is :" << decOutCnt_ << endl; + cout << "encInCnt_ is :" << encInCnt_ << endl; + cout << "encOutCnt_ is :" << encOutCnt_ << endl; + cout << "acodecSignal_->inQueueDec_.size() is :" << acodecSignal_->inQueueDec_.size() << endl; + cout << "acodecSignal_->outQueueDec_.size() is :" << acodecSignal_->outQueueDec_.size() << endl; + cout << "acodecSignal_->inQueueEnc_.size() is :" << acodecSignal_->inQueueEnc_.size() << endl; + cout << "acodecSignal_->outQueueEnc_.size() is :" << acodecSignal_->outQueueEnc_.size() << endl; + return acodecSignal_->errorNum_ ; +} + +int32_t ADecEncNdkSample::GetFrameCount() +{ + return encOutCnt_; +} + +bool ADecEncNdkSample::GetEncEosState() +{ + return isEncOutputEOS; +} + +bool ADecEncNdkSample::GetDecEosState() +{ + return isDecOutputEOS; +} \ No newline at end of file diff --git a/multimedia/media/media_cpp_standard/include/ndktest_log.h b/multimedia/media/media_cpp_standard/include/ndktest_log.h new file mode 100644 index 0000000000000000000000000000000000000000..a2ae49b37cbdf918036ba386a01d5c548425d9fa --- /dev/null +++ b/multimedia/media/media_cpp_standard/include/ndktest_log.h @@ -0,0 +1,56 @@ +/* + * 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 NDKTEST_LOG_H +#define NDKTEST_LOG_H + +#include + +#define RET_FAIL (-1) +#define RET_OK 0 + +#define NDK_CHECK_AND_RETURN_RET_LOG(cond, ret, fmt, ...) \ + do { \ + if (!(cond)) { \ + (void)printf("%s\n", fmt, ##__VA_ARGS__); \ + return ret; \ + } \ + } while (0) + +#define NDK_CHECK_AND_RETURN_LOG(cond, fmt, ...) \ + do { \ + if (!(cond)) { \ + (void)printf("%s\n", fmt, ##__VA_ARGS__); \ + return; \ + } \ + } while (0) + +#define NDK_CHECK_AND_BREAK_LOG(cond, fmt, ...) \ + if (!(cond)) { \ + (void)printf("%s\n", fmt, ##__VA_ARGS__); \ + break; \ + } + +#define NDK_CHECK_AND_CONTINUE_LOG(cond, fmt, ...) \ + if (!(cond)) { \ + (void)printf("%s\n", fmt, ##__VA_ARGS__); \ + continue; \ + } + +#define NDK_CHECK_AND_LOG(cond, fmt, ...) \ + if (!(cond)) { \ + (void)printf("%s\n", fmt, ##__VA_ARGS__); \ + } +#endif // NDKTEST_LOG_H \ No newline at end of file