mirror of
https://gitee.com/openharmony/multimedia_av_codec
synced 2024-11-27 00:50:36 +00:00
Merge branch 'develop_test' of gitee.com:zjskpajs/av_codec into dev_av_muxer
Signed-off-by: cailei24 <cailei24@huawei.com>
This commit is contained in:
commit
cec62116c6
2
BUILD.gn
2
BUILD.gn
@ -11,7 +11,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/config/ohos/rules.gni")
|
||||
import("//build/config/ohos/config.gni")
|
||||
import("//build/ohos.gni")
|
||||
|
||||
group("av_codec_packages") {
|
||||
|
@ -10,7 +10,7 @@
|
||||
"dirs": {},
|
||||
"scripts": {},
|
||||
"component": {
|
||||
"name": "multimedia_av_codec",
|
||||
"name": "av_codec",
|
||||
"subsystem": "multimedia",
|
||||
"syscap": [
|
||||
"SystemCapability.Multimedia.Avcodec.Core",
|
||||
@ -56,8 +56,8 @@
|
||||
"//foundation/multimedia/av_codec/interfaces/inner_api/native:av_codec_client"
|
||||
],
|
||||
"service_group": [
|
||||
"//foundation/multimedia/av_codec/services:av_codec_services_package",
|
||||
"//foundation/multimedia/av_codec/sa_profile:av_codec_service_sa_profile"
|
||||
"//foundation/multimedia/av_codec/services:av_codec_services_package",
|
||||
"//foundation/multimedia/av_codec/sa_profile:av_codec_service_profile"
|
||||
]
|
||||
},
|
||||
"inner_kits": [
|
||||
|
@ -240,5 +240,5 @@ ohos_shared_library("av_codec_client") {
|
||||
]
|
||||
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ ohos_shared_library("native_av_codec_core") {
|
||||
]
|
||||
output_extension = "so"
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
||||
ohos_shared_library("native_av_codec_codec") {
|
||||
@ -200,7 +200,7 @@ ohos_shared_library("native_av_codec_codec") {
|
||||
]
|
||||
output_extension = "so"
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
||||
ohos_shared_library("native_av_codec_avmuxer") {
|
||||
@ -225,5 +225,5 @@ ohos_shared_library("native_av_codec_avmuxer") {
|
||||
]
|
||||
output_extension = "so"
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
@ -13,8 +13,7 @@
|
||||
|
||||
import("//build/ohos/sa_profile/sa_profile.gni")
|
||||
|
||||
ohos_sa_profile("av_codec_service_sa_profile") {
|
||||
ohos_sa_profile("av_codec_service_profile") {
|
||||
sources = [ "3011.xml" ]
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
||||
|
@ -77,5 +77,5 @@ ohos_shared_library("av_codec_service_dfx") {
|
||||
]
|
||||
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
@ -68,5 +68,5 @@ ohos_static_library("av_codec_engine_avcodeclist") {
|
||||
]
|
||||
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
@ -55,5 +55,20 @@ int32_t CodecBase::SignalRequestIDRFrame()
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::shared_ptr<CodecBase> CodecBase::Create(const std::string& name)
|
||||
{
|
||||
AVCODEC_LOGW("Create is not supported");
|
||||
(void)name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<CodecBase> CodecBase::Create(bool isEncoder, const std::string& mime)
|
||||
{
|
||||
AVCODEC_LOGW("Create is not supported");
|
||||
(void)isEncoder;
|
||||
(void)mime;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# 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
|
||||
@ -16,6 +16,6 @@ import("//build/ohos.gni")
|
||||
ohos_prebuilt_etc("av_codec_service.cfg") {
|
||||
source = "av_codec_service.cfg"
|
||||
relative_install_dir = "init"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
subsystem_name = "multimedia"
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"services" : [{
|
||||
"name" : "av_codec_service",
|
||||
"path" : ["/system/bin/sa_main", "/system/profile/av_codec_service.xml"],
|
||||
"ondemand" : true,
|
||||
"uid" : "system",
|
||||
"gid" : ["system", "shell"]
|
||||
"name" : "av_codec_service",
|
||||
"path" : ["/system/bin/sa_main", "/system/profile/av_codec_service.xml"],
|
||||
"uid" : "media",
|
||||
"gid" : ["av_codec_rw", "system"],
|
||||
"secon" : "u:r:media_service:s0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -215,5 +215,5 @@ ohos_shared_library("av_codec_service") {
|
||||
]
|
||||
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
@ -285,7 +285,6 @@ int32_t CodecServer::SetParameter(const Format &format)
|
||||
int32_t CodecServer::SetCallback(const std::shared_ptr<AVCodecCallback> &callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(status_ == INITIALIZED, AVCS_ERR_INVALID_OPERATION, "invalid state");
|
||||
{
|
||||
std::lock_guard<std::mutex> cbLock(cbMutex_);
|
||||
codecCb_ = callback;
|
||||
@ -294,8 +293,6 @@ int32_t CodecServer::SetCallback(const std::shared_ptr<AVCodecCallback> &callbac
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t CodecServer::DumpInfo(int32_t fd)
|
||||
{
|
||||
std::string dumpString;
|
||||
|
@ -35,7 +35,7 @@ ohos_static_library("av_codec_format") {
|
||||
]
|
||||
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
||||
ohos_shared_library("av_codec_service_utils") {
|
||||
@ -93,5 +93,5 @@ include_dirs = [
|
||||
]
|
||||
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
}
|
||||
|
@ -31,4 +31,4 @@ group("av_codec_unit_test") {
|
||||
"unittest:format_unit_test",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2021 Huawei Device Co., Ltd.
|
||||
# Copyright (C) 2023 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
|
||||
@ -24,6 +24,9 @@ ohos_executable("av_codec_demo") {
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/interface",
|
||||
"//foundation/multimedia/av_codec/services/dfx/include",
|
||||
"//foundation/multimedia/av_codec/services/utils/include",
|
||||
"./av_codec_audio",
|
||||
"./audio_demo",
|
||||
"./include",
|
||||
]
|
||||
|
||||
cflags = [
|
||||
@ -59,6 +62,9 @@ ohos_executable("av_codec_demo") {
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/avmuxer/avmuxer_ffmpeg_demo.cpp",
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/avmuxer/avmuxer_demo_common.c",
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/avmuxer/native_avmuxer_demo.c",
|
||||
"./audio_demo/avcodec_audio_encoder_inner_demo.cpp",
|
||||
"./audio_demo/avcodec_audio_decoder_demo.cpp",
|
||||
"./audio_demo/avcodec_audio_encoder_demo.cpp"
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -66,14 +72,16 @@ ohos_executable("av_codec_demo") {
|
||||
"//foundation/multimedia/av_codec/interfaces/inner_api/native:av_codec_client",
|
||||
"//foundation/multimedia/av_codec/services/services:av_codec_service",
|
||||
"//foundation/multimedia/av_codec/services/utils:av_codec_format",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c:capi_packages"
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"c_utils:utils",
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
"ipc:ipc_core",
|
||||
]
|
||||
install_enable = false
|
||||
|
||||
part_name = "multimedia_av_codec"
|
||||
part_name = "av_codec"
|
||||
subsystem_name = "multimedia"
|
||||
}
|
||||
}
|
||||
|
234
test/nativedemo/audio_demo/avcodec_audio_decoder_demo.cpp
Normal file
234
test/nativedemo/audio_demo/avcodec_audio_decoder_demo.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 "avcodec_audio_decoder_demo.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_common.h"
|
||||
#include "demo_log.h"
|
||||
#include "securec.h"
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace OHOS;
|
||||
using namespace OHOS::Media;
|
||||
using namespace OHOS::Media::AudioDemo;
|
||||
using namespace std;
|
||||
namespace {
|
||||
constexpr uint32_t CHANNEL_COUNT = 2;
|
||||
constexpr uint32_t SAMPLE_RATE = 44100;
|
||||
constexpr uint32_t BITS_RATE = 169000;
|
||||
constexpr uint32_t BITS_PER_CODED_RATE = 4;
|
||||
constexpr uint32_t FRAME_DURATION_US = 33000;
|
||||
constexpr uint32_t DEFAULT_FRAME_COUNT = 1;
|
||||
} // namespace
|
||||
|
||||
static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) {
|
||||
cout << "Error received, errorCode:" << errorCode << endl;
|
||||
}
|
||||
|
||||
static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) {
|
||||
cout << "OnOutputFormatChanged received" << endl;
|
||||
}
|
||||
|
||||
static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData) {
|
||||
ADecSignal *signal_ = static_cast<ADecSignal *>(userData);
|
||||
cout << "OnInputBufferAvailable received, index:" << index << endl;
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inQueue_.push(index);
|
||||
signal_->inBufferQueue_.push(data);
|
||||
signal_->inCond_.notify_all();
|
||||
}
|
||||
|
||||
static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
|
||||
void *userData) {
|
||||
ADecSignal *signal_ = static_cast<ADecSignal *>(userData);
|
||||
cout << "OnOutputBufferAvailable received, index:" << index << endl;
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outQueue_.push(index);
|
||||
signal_->outBufferQueue_.push(data);
|
||||
signal_->attrQueue_.push(attr);
|
||||
signal_->outCond_.notify_all();
|
||||
}
|
||||
|
||||
void ADecDemo::RunCase() {
|
||||
DEMO_CHECK_AND_RETURN_LOG(CreateDec() == AVCS_ERR_OK, "Fatal: CreateDec fail");
|
||||
|
||||
OH_AVFormat *format = OH_AVFormat_Create();
|
||||
OH_AVFormat_SetIntValue(format, "channel-count", CHANNEL_COUNT);
|
||||
OH_AVFormat_SetIntValue(format, "sample-rate", SAMPLE_RATE);
|
||||
OH_AVFormat_SetIntValue(format, "bits_per_coded-rate", BITS_PER_CODED_RATE);
|
||||
OH_AVFormat_SetLongValue(format, "bits-rate", BITS_RATE);
|
||||
DEMO_CHECK_AND_RETURN_LOG(Configure(format) == AVCS_ERR_OK, "Fatal: Configure fail");
|
||||
|
||||
DEMO_CHECK_AND_RETURN_LOG(Start() == AVCS_ERR_OK, "Fatal: Start fail");
|
||||
sleep(3); // start run 3s
|
||||
DEMO_CHECK_AND_RETURN_LOG(Stop() == AVCS_ERR_OK, "Fatal: Stop fail");
|
||||
DEMO_CHECK_AND_RETURN_LOG(Release() == AVCS_ERR_OK, "Fatal: Release fail");
|
||||
}
|
||||
|
||||
ADecDemo::~ADecDemo() {
|
||||
OH_AudioDecoder_Destroy(audioDec_);
|
||||
if (signal_) {
|
||||
delete signal_;
|
||||
signal_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ADecDemo::CreateDec() {
|
||||
|
||||
audioDec_ = OH_AudioDecoder_CreateByName("OH.Media.Codec.MP3.FFMPEGMp3");
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(audioDec_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: CreateByName fail");
|
||||
|
||||
signal_ = new ADecSignal();
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
|
||||
int32_t ret = OH_AudioDecoder_SetCallback(audioDec_, cb_, signal_);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "Fatal: SetCallback fail");
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t ADecDemo::Configure(OH_AVFormat *format) {
|
||||
return OH_AudioDecoder_Configure(audioDec_, format);
|
||||
}
|
||||
|
||||
int32_t ADecDemo::Start() {
|
||||
isRunning_.store(true);
|
||||
|
||||
testFile_ = std::make_unique<std::ifstream>();
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(testFile_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
testFile_->open("/data/media/audio.mp3", std::ios::in | std::ios::binary);
|
||||
|
||||
inputLoop_ = make_unique<thread>(&ADecDemo::InputFunc, this);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(inputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
outputLoop_ = make_unique<thread>(&ADecDemo::OutputFunc, this);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(outputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
return OH_AudioDecoder_Start(audioDec_);
|
||||
}
|
||||
|
||||
int32_t ADecDemo::Stop() {
|
||||
isRunning_.store(false);
|
||||
|
||||
if (inputLoop_ != nullptr && inputLoop_->joinable()) {
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inCond_.notify_all();
|
||||
lock.unlock();
|
||||
inputLoop_->join();
|
||||
inputLoop_.reset();
|
||||
}
|
||||
|
||||
if (outputLoop_ != nullptr && outputLoop_->joinable()) {
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outCond_.notify_all();
|
||||
lock.unlock();
|
||||
outputLoop_->join();
|
||||
outputLoop_.reset();
|
||||
}
|
||||
|
||||
return OH_AudioDecoder_Stop(audioDec_);
|
||||
}
|
||||
|
||||
int32_t ADecDemo::Flush() {
|
||||
return OH_AudioDecoder_Flush(audioDec_);
|
||||
}
|
||||
|
||||
int32_t ADecDemo::Reset() {
|
||||
return OH_AudioDecoder_Reset(audioDec_);
|
||||
}
|
||||
|
||||
int32_t ADecDemo::Release() {
|
||||
return OH_AudioDecoder_Destroy(audioDec_);
|
||||
}
|
||||
|
||||
void ADecDemo::InputFunc() {
|
||||
while (true) {
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inCond_.wait(lock, [this]() { return signal_->inQueue_.size() > 0; });
|
||||
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t index = signal_->inQueue_.front();
|
||||
auto buffer = signal_->inBufferQueue_.front();
|
||||
DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
|
||||
DEMO_CHECK_AND_BREAK_LOG(testFile_ != nullptr && testFile_->is_open(), "Fatal: open file fail");
|
||||
constexpr uint32_t bufferSize = 0;
|
||||
(void)testFile_->read((char *)OH_AVMemory_GetAddr(buffer), bufferSize);
|
||||
|
||||
OH_AVCodecBufferAttr info;
|
||||
info.size = bufferSize;
|
||||
info.offset = 0;
|
||||
// info.presentationTimeUs = timeStamp_;
|
||||
|
||||
int32_t ret = AVCS_ERR_OK;
|
||||
if (isFirstFrame_) {
|
||||
info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
|
||||
ret = OH_AudioDecoder_PushInputData(audioDec_, index, info);
|
||||
isFirstFrame_ = false;
|
||||
} else {
|
||||
info.flags = AVCODEC_BUFFER_FLAGS_NONE;
|
||||
ret = OH_AudioDecoder_PushInputData(audioDec_, index, info);
|
||||
}
|
||||
|
||||
// free(fileBuffer);
|
||||
timeStamp_ += FRAME_DURATION_US;
|
||||
signal_->inQueue_.pop();
|
||||
signal_->inBufferQueue_.pop();
|
||||
|
||||
frameCount_++;
|
||||
if (frameCount_ == DEFAULT_FRAME_COUNT) {
|
||||
cout << "Finish decode, exit" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != AVCS_ERR_OK) {
|
||||
cout << "Fatal error, exit" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ADecDemo::OutputFunc() {
|
||||
while (true) {
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outCond_.wait(lock, [this]() { return signal_->outQueue_.size() > 0; });
|
||||
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t index = signal_->outQueue_.front();
|
||||
if (OH_AudioDecoder_FreeOutputData(audioDec_, index) != AV_ERR_OK) {
|
||||
cout << "Fatal: ReleaseOutputBuffer fail" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
signal_->outBufferQueue_.pop();
|
||||
signal_->attrQueue_.pop();
|
||||
signal_->outQueue_.pop();
|
||||
}
|
||||
}
|
74
test/nativedemo/audio_demo/avcodec_audio_decoder_demo.h
Normal file
74
test/nativedemo/audio_demo/avcodec_audio_decoder_demo.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 AVCODEC_AUDIO_DECODER_DEMO_H
|
||||
#define AVCODEC_AUDIO_DECODER_DEMO_H
|
||||
|
||||
#include "native_avcodec_audiodecoder.h"
|
||||
#include <atomic>
|
||||
#include <fstream>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "nocopyable.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace AudioDemo {
|
||||
class ADecSignal {
|
||||
public:
|
||||
std::mutex inMutex_;
|
||||
std::mutex outMutex_;
|
||||
std::condition_variable inCond_;
|
||||
std::condition_variable outCond_;
|
||||
std::queue<uint32_t> inQueue_;
|
||||
std::queue<uint32_t> outQueue_;
|
||||
std::queue<OH_AVMemory *> inBufferQueue_;
|
||||
std::queue<OH_AVMemory *> outBufferQueue_;
|
||||
std::queue<OH_AVCodecBufferAttr *> attrQueue_;
|
||||
};
|
||||
|
||||
class ADecDemo : public NoCopyable {
|
||||
public:
|
||||
ADecDemo() = default;
|
||||
virtual ~ADecDemo();
|
||||
void RunCase();
|
||||
|
||||
private:
|
||||
int32_t CreateDec();
|
||||
int32_t Configure(OH_AVFormat *format);
|
||||
int32_t Start();
|
||||
int32_t Stop();
|
||||
int32_t Flush();
|
||||
int32_t Reset();
|
||||
int32_t Release();
|
||||
void InputFunc();
|
||||
void OutputFunc();
|
||||
|
||||
std::atomic<bool> isRunning_ = false;
|
||||
std::unique_ptr<std::ifstream> testFile_;
|
||||
std::unique_ptr<std::thread> inputLoop_;
|
||||
std::unique_ptr<std::thread> outputLoop_;
|
||||
OH_AVCodec *audioDec_;
|
||||
ADecSignal *signal_;
|
||||
struct OH_AVCodecAsyncCallback cb_;
|
||||
bool isFirstFrame_ = true;
|
||||
int64_t timeStamp_ = 0;
|
||||
uint32_t frameCount_ = 0;
|
||||
};
|
||||
} // AudioDemo
|
||||
} // namespace AV_Codec
|
||||
} // namespace OHOS
|
||||
#endif // AVCODEC_AUDIO_DECODER_DEMO_H
|
234
test/nativedemo/audio_demo/avcodec_audio_encoder_demo.cpp
Normal file
234
test/nativedemo/audio_demo/avcodec_audio_encoder_demo.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 "avcodec_audio_encoder_demo.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_common.h"
|
||||
#include "demo_log.h"
|
||||
#include "securec.h"
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace OHOS;
|
||||
using namespace OHOS::Media;
|
||||
using namespace OHOS::Media::AudioDemo;
|
||||
using namespace std;
|
||||
namespace {
|
||||
constexpr uint32_t CHANNEL_COUNT = 2;
|
||||
constexpr uint32_t SAMPLE_RATE = 44100;
|
||||
constexpr uint32_t BITS_RATE = 169000;
|
||||
constexpr uint32_t BITS_PER_CODED_RATE = 4;
|
||||
constexpr uint32_t FRAME_DURATION_US = 33000;
|
||||
constexpr uint32_t DEFAULT_FRAME_COUNT = 1;
|
||||
} // namespace
|
||||
|
||||
static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) {
|
||||
cout << "Error received, errorCode:" << errorCode << endl;
|
||||
}
|
||||
|
||||
static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) {
|
||||
cout << "OnOutputFormatChanged received" << endl;
|
||||
}
|
||||
|
||||
static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData) {
|
||||
AEncSignal *signal_ = static_cast<AEncSignal *>(userData);
|
||||
cout << "OnInputBufferAvailable received, index:" << index << endl;
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inQueue_.push(index);
|
||||
signal_->inBufferQueue_.push(data);
|
||||
signal_->inCond_.notify_all();
|
||||
}
|
||||
|
||||
static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
|
||||
void *userData) {
|
||||
AEncSignal *signal_ = static_cast<AEncSignal *>(userData);
|
||||
cout << "OnOutputBufferAvailable received, index:" << index << endl;
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outQueue_.push(index);
|
||||
signal_->outBufferQueue_.push(data);
|
||||
signal_->attrQueue_.push(attr);
|
||||
signal_->outCond_.notify_all();
|
||||
}
|
||||
|
||||
AEncDemo::~AEncDemo() {
|
||||
OH_AudioEncoder_Destroy(audioEnc_);
|
||||
if (signal_) {
|
||||
delete signal_;
|
||||
signal_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AEncDemo::RunCase() {
|
||||
DEMO_CHECK_AND_RETURN_LOG(CreateDec() == AVCS_ERR_OK, "Fatal: CreateDec fail");
|
||||
|
||||
OH_AVFormat *format = OH_AVFormat_Create();
|
||||
OH_AVFormat_SetIntValue(format, "channel-count", CHANNEL_COUNT);
|
||||
OH_AVFormat_SetIntValue(format, "sample-rate", SAMPLE_RATE);
|
||||
OH_AVFormat_SetIntValue(format, "bits_per_coded-rate", BITS_PER_CODED_RATE);
|
||||
OH_AVFormat_SetLongValue(format, "bits-rate", BITS_RATE);
|
||||
|
||||
DEMO_CHECK_AND_RETURN_LOG(Configure(format) == AVCS_ERR_OK, "Fatal: Configure fail");
|
||||
|
||||
DEMO_CHECK_AND_RETURN_LOG(Start() == AVCS_ERR_OK, "Fatal: Start fail");
|
||||
sleep(3); // start run 3s
|
||||
DEMO_CHECK_AND_RETURN_LOG(Stop() == AVCS_ERR_OK, "Fatal: Stop fail");
|
||||
DEMO_CHECK_AND_RETURN_LOG(Release() == AVCS_ERR_OK, "Fatal: Release fail");
|
||||
}
|
||||
|
||||
int32_t AEncDemo::CreateDec() {
|
||||
audioEnc_ = OH_AudioEncoder_CreateByName("OH.Media.Codec.MP3.FFMPEGMp3");
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(audioEnc_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: CreateByName fail");
|
||||
|
||||
signal_ = new AEncSignal();
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
|
||||
int32_t ret = OH_AudioEncoder_SetCallback(audioEnc_, cb_, signal_);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "Fatal: SetCallback fail");
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AEncDemo::Configure(OH_AVFormat *format) {
|
||||
return OH_AudioEncoder_Configure(audioEnc_, format);
|
||||
}
|
||||
|
||||
int32_t AEncDemo::Start() {
|
||||
isRunning_.store(true);
|
||||
|
||||
testFile_ = std::make_unique<std::ifstream>();
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(testFile_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
testFile_->open("/data/media/video.pcm", std::ios::in | std::ios::binary);
|
||||
|
||||
inputLoop_ = make_unique<thread>(&AEncDemo::InputFunc, this);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(inputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
outputLoop_ = make_unique<thread>(&AEncDemo::OutputFunc, this);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(outputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
return OH_AudioEncoder_Start(audioEnc_);
|
||||
}
|
||||
|
||||
int32_t AEncDemo::Stop() {
|
||||
isRunning_.store(false);
|
||||
|
||||
if (inputLoop_ != nullptr && inputLoop_->joinable()) {
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inCond_.notify_all();
|
||||
lock.unlock();
|
||||
inputLoop_->join();
|
||||
inputLoop_.reset();
|
||||
}
|
||||
|
||||
if (outputLoop_ != nullptr && outputLoop_->joinable()) {
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outCond_.notify_all();
|
||||
lock.unlock();
|
||||
outputLoop_->join();
|
||||
outputLoop_.reset();
|
||||
}
|
||||
|
||||
return OH_AudioEncoder_Stop(audioEnc_);
|
||||
}
|
||||
|
||||
int32_t AEncDemo::Flush() {
|
||||
return OH_AudioEncoder_Flush(audioEnc_);
|
||||
}
|
||||
|
||||
int32_t AEncDemo::Reset() {
|
||||
return OH_AudioEncoder_Reset(audioEnc_);
|
||||
}
|
||||
|
||||
int32_t AEncDemo::Release() {
|
||||
return OH_AudioEncoder_Destroy(audioEnc_);
|
||||
}
|
||||
|
||||
void AEncDemo::InputFunc() {
|
||||
while (true) {
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inCond_.wait(lock, [this]() { return signal_->inQueue_.size() > 0; });
|
||||
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t index = signal_->inQueue_.front();
|
||||
auto buffer = signal_->inBufferQueue_.front();
|
||||
DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
|
||||
DEMO_CHECK_AND_BREAK_LOG(testFile_ != nullptr && testFile_->is_open(), "Fatal: open file fail");
|
||||
constexpr uint32_t bufferSize = 0;
|
||||
(void)testFile_->read((char *)OH_AVMemory_GetAddr(buffer), bufferSize);
|
||||
|
||||
OH_AVCodecBufferAttr info;
|
||||
info.size = bufferSize;
|
||||
info.offset = 0;
|
||||
// info.presentationTimeUs = timeStamp_;
|
||||
|
||||
int32_t ret = AVCS_ERR_OK;
|
||||
if (isFirstFrame_) {
|
||||
info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
|
||||
ret = OH_AudioEncoder_PushInputData(audioEnc_, index, info);
|
||||
isFirstFrame_ = false;
|
||||
} else {
|
||||
info.flags = AVCODEC_BUFFER_FLAGS_NONE;
|
||||
ret = OH_AudioEncoder_PushInputData(audioEnc_, index, info);
|
||||
}
|
||||
|
||||
// free(fileBuffer);
|
||||
timeStamp_ += FRAME_DURATION_US;
|
||||
signal_->inQueue_.pop();
|
||||
signal_->inBufferQueue_.pop();
|
||||
frameCount_++;
|
||||
if (frameCount_ == DEFAULT_FRAME_COUNT) {
|
||||
cout << "Finish decode, exit" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != AVCS_ERR_OK) {
|
||||
cout << "Fatal error, exit" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AEncDemo::OutputFunc() {
|
||||
while (true) {
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outCond_.wait(lock, [this]() { return signal_->outQueue_.size() > 0; });
|
||||
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t index = signal_->outQueue_.front();
|
||||
|
||||
if (OH_AudioEncoder_FreeOutputData(audioEnc_, index) != AV_ERR_OK) {
|
||||
cout << "Fatal: ReleaseOutputBuffer fail" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
signal_->outQueue_.pop();
|
||||
signal_->outBufferQueue_.pop();
|
||||
signal_->attrQueue_.pop();
|
||||
}
|
||||
}
|
75
test/nativedemo/audio_demo/avcodec_audio_encoder_demo.h
Normal file
75
test/nativedemo/audio_demo/avcodec_audio_encoder_demo.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 AVCODEC_AUDIO_ENCODER_DEMO_H
|
||||
#define AVCODEC_AUDIO_ENCODER_DEMO_H
|
||||
|
||||
#include "native_avcodec_audioencoder.h"
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <fstream>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "nocopyable.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace AudioDemo {
|
||||
class AEncSignal {
|
||||
public:
|
||||
std::mutex inMutex_;
|
||||
std::mutex outMutex_;
|
||||
std::condition_variable inCond_;
|
||||
std::condition_variable outCond_;
|
||||
std::queue<uint32_t> inQueue_;
|
||||
std::queue<uint32_t> outQueue_;
|
||||
std::queue<OH_AVMemory *> inBufferQueue_;
|
||||
std::queue<OH_AVMemory *> outBufferQueue_;
|
||||
std::queue<OH_AVCodecBufferAttr *> attrQueue_;
|
||||
};
|
||||
|
||||
class AEncDemo : public NoCopyable {
|
||||
public:
|
||||
AEncDemo() = default;
|
||||
virtual ~AEncDemo();
|
||||
void RunCase();
|
||||
|
||||
private:
|
||||
int32_t CreateDec();
|
||||
int32_t Configure(OH_AVFormat *format);
|
||||
int32_t Start();
|
||||
int32_t Stop();
|
||||
int32_t Flush();
|
||||
int32_t Reset();
|
||||
int32_t Release();
|
||||
void InputFunc();
|
||||
void OutputFunc();
|
||||
|
||||
std::atomic<bool> isRunning_ = false;
|
||||
std::unique_ptr<std::ifstream> testFile_;
|
||||
std::unique_ptr<std::thread> inputLoop_;
|
||||
std::unique_ptr<std::thread> outputLoop_;
|
||||
OH_AVCodec *audioEnc_;
|
||||
AEncSignal *signal_;
|
||||
struct OH_AVCodecAsyncCallback cb_;
|
||||
bool isFirstFrame_ = true;
|
||||
int64_t timeStamp_ = 0;
|
||||
uint32_t frameCount_ = 0;
|
||||
};
|
||||
} // AudioDemo
|
||||
} // namespace AV_Codec
|
||||
} // namespace OHOS
|
||||
#endif // AVCODEC_AUDIO_DECODER_DEMO_H
|
246
test/nativedemo/audio_demo/avcodec_audio_encoder_inner_demo.cpp
Normal file
246
test/nativedemo/audio_demo/avcodec_audio_encoder_inner_demo.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 "avcodec_audio_encoder_inner_demo.h"
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "securec.h"
|
||||
#include "demo_log.h"
|
||||
#include "avcodec_errors.h"
|
||||
|
||||
using namespace OHOS;
|
||||
using namespace OHOS::Media;
|
||||
using namespace OHOS::Media::InnerAudioDemo;
|
||||
using namespace std;
|
||||
namespace {
|
||||
constexpr uint32_t CHANNEL_COUNT = 2;
|
||||
constexpr uint32_t SAMPLE_RATE = 44100;
|
||||
constexpr uint32_t BITS_RATE = 169000;
|
||||
constexpr uint32_t BITS_PER_CODED_RATE = 4;
|
||||
constexpr uint32_t FRAME_DURATION_US = 33000;
|
||||
constexpr uint32_t DEFAULT_FRAME_COUNT = 1;
|
||||
}
|
||||
|
||||
void ADecInnerDemo::RunCase()
|
||||
{
|
||||
DEMO_CHECK_AND_RETURN_LOG(CreateDec() == AVCS_ERR_OK, "Fatal: CreateDec fail");
|
||||
|
||||
Format format;
|
||||
format.PutIntValue("channel-count", CHANNEL_COUNT);
|
||||
format.PutIntValue("sample-rate", SAMPLE_RATE);
|
||||
format.PutLongValue("bits-rate", BITS_RATE);
|
||||
format.PutIntValue("bits_per_coded-rate", BITS_PER_CODED_RATE);
|
||||
DEMO_CHECK_AND_RETURN_LOG(Configure(format) == AVCS_ERR_OK, "Fatal: Configure fail");
|
||||
|
||||
DEMO_CHECK_AND_RETURN_LOG(Start() == AVCS_ERR_OK, "Fatal: Start fail");
|
||||
sleep(3); // start run 3s
|
||||
DEMO_CHECK_AND_RETURN_LOG(Stop() == AVCS_ERR_OK, "Fatal: Stop fail");
|
||||
DEMO_CHECK_AND_RETURN_LOG(Release() == AVCS_ERR_OK, "Fatal: Release fail");
|
||||
}
|
||||
|
||||
int32_t ADecInnerDemo::CreateDec()
|
||||
{
|
||||
audioDec_ = AudioDecoderFactory::CreateByName("OH.Media.Codec.MP3.FFMPEGMp3");
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(audioDec_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: CreateByName fail");
|
||||
|
||||
signal_ = make_shared<ADecSignal>();
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
cb_ = make_unique<ADecDemoCallback>(signal_);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(cb_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(audioDec_->SetCallback(cb_) == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "Fatal: SetCallback fail");
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t ADecInnerDemo::Configure(const Format &format)
|
||||
{
|
||||
return audioDec_->Configure(format);
|
||||
}
|
||||
|
||||
|
||||
int32_t ADecInnerDemo::Start()
|
||||
{
|
||||
isRunning_.store(true);
|
||||
|
||||
testFile_ = std::make_unique<std::ifstream>();
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(testFile_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
testFile_->open("/data/media/video.es", std::ios::in | std::ios::binary);
|
||||
|
||||
inputLoop_ = make_unique<thread>(&ADecInnerDemo::InputFunc, this);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(inputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
outputLoop_ = make_unique<thread>(&ADecInnerDemo::OutputFunc, this);
|
||||
DEMO_CHECK_AND_RETURN_RET_LOG(outputLoop_ != nullptr, AVCS_ERR_UNKNOWN, "Fatal: No memory");
|
||||
|
||||
return audioDec_->Start();
|
||||
}
|
||||
|
||||
int32_t ADecInnerDemo::Stop()
|
||||
{
|
||||
isRunning_.store(false);
|
||||
|
||||
if (inputLoop_ != nullptr && inputLoop_->joinable()) {
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inQueue_.push(0);
|
||||
signal_->inCond_.notify_all();
|
||||
lock.unlock();
|
||||
inputLoop_->join();
|
||||
inputLoop_.reset();
|
||||
}
|
||||
|
||||
if (outputLoop_ != nullptr && outputLoop_->joinable()) {
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outQueue_.push(0);
|
||||
signal_->outCond_.notify_all();
|
||||
lock.unlock();
|
||||
outputLoop_->join();
|
||||
outputLoop_.reset();
|
||||
}
|
||||
|
||||
return audioDec_->Stop();
|
||||
}
|
||||
|
||||
int32_t ADecInnerDemo::Flush()
|
||||
{
|
||||
return audioDec_->Flush();
|
||||
}
|
||||
|
||||
int32_t ADecInnerDemo::Reset()
|
||||
{
|
||||
return audioDec_->Reset();
|
||||
}
|
||||
|
||||
int32_t ADecInnerDemo::Release()
|
||||
{
|
||||
return audioDec_->Release();
|
||||
}
|
||||
|
||||
void ADecInnerDemo::InputFunc()
|
||||
{
|
||||
while (true) {
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inCond_.wait(lock, [this](){ return signal_->inQueue_.size() > 0; });
|
||||
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t index = signal_->inQueue_.front();
|
||||
auto buffer = audioDec_->GetInputBuffer(index);
|
||||
DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
|
||||
DEMO_CHECK_AND_BREAK_LOG(testFile_ != nullptr && testFile_->is_open(), "Fatal: open file fail");
|
||||
|
||||
constexpr uint32_t bufferSize = 0; // replace with the actual size
|
||||
char *fileBuffer = static_cast<char *>(malloc(sizeof(char) * bufferSize + 1));
|
||||
DEMO_CHECK_AND_BREAK_LOG(fileBuffer != nullptr, "Fatal: malloc fail");
|
||||
|
||||
(void)testFile_->read(fileBuffer, bufferSize);
|
||||
|
||||
DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
|
||||
if (memcpy_s(buffer->GetBase(), buffer->GetSize(), fileBuffer, bufferSize) != EOK) {
|
||||
free(fileBuffer);
|
||||
cout << "Fatal: memcpy fail" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
AVCodecBufferInfo info;
|
||||
info.size = bufferSize;
|
||||
info.offset = 0;
|
||||
info.presentationTimeUs = timeStamp_;
|
||||
|
||||
int32_t ret = AVCS_ERR_OK;
|
||||
if (isFirstFrame_) {
|
||||
ret = audioDec_->QueueInputBuffer(index, info, AVCODEC_BUFFER_FLAG_CODEC_DATA);
|
||||
isFirstFrame_ = false;
|
||||
} else {
|
||||
ret = audioDec_->QueueInputBuffer(index, info, AVCODEC_BUFFER_FLAG_NONE);
|
||||
}
|
||||
|
||||
free(fileBuffer);
|
||||
timeStamp_ += FRAME_DURATION_US;
|
||||
signal_->inQueue_.pop();
|
||||
|
||||
frameCount_++;
|
||||
if (frameCount_ == DEFAULT_FRAME_COUNT) {
|
||||
cout << "Finish decode, exit" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != AVCS_ERR_OK) {
|
||||
cout << "Fatal error, exit" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ADecInnerDemo::OutputFunc()
|
||||
{
|
||||
while (true) {
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outCond_.wait(lock, [this](){ return signal_->outQueue_.size() > 0; });
|
||||
|
||||
if (!isRunning_.load()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t index = signal_->outQueue_.front();
|
||||
if (audioDec_->ReleaseOutputBuffer(index) != AVCS_ERR_OK) {
|
||||
cout << "Fatal: ReleaseOutputBuffer fail" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
signal_->outQueue_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
ADecDemoCallback::ADecDemoCallback(shared_ptr<ADecSignal> signal)
|
||||
: signal_(signal)
|
||||
{
|
||||
}
|
||||
|
||||
void ADecDemoCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
|
||||
{
|
||||
cout << "Error received, errorType:" << errorType << " errorCode:" << errorCode << endl;
|
||||
}
|
||||
|
||||
void ADecDemoCallback::OnOutputFormatChanged(const Format &format)
|
||||
{
|
||||
cout << "OnOutputFormatChanged received" << endl;
|
||||
}
|
||||
|
||||
void ADecDemoCallback::OnInputBufferAvailable(uint32_t index)
|
||||
{
|
||||
cout << "OnInputBufferAvailable received, index:" << index << endl;
|
||||
unique_lock<mutex> lock(signal_->inMutex_);
|
||||
signal_->inQueue_.push(index);
|
||||
signal_->inCond_.notify_all();
|
||||
}
|
||||
|
||||
void ADecDemoCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
|
||||
{
|
||||
cout << "OnOutputBufferAvailable received, index:" << index << endl;
|
||||
unique_lock<mutex> lock(signal_->outMutex_);
|
||||
signal_->outQueue_.push(index);
|
||||
signal_->outCond_.notify_all();
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 AVCODEC_AUDIO_ENCODER_INNER_DEMO_H
|
||||
#define AVCODEC_AUDIO_ENCODER_INNER_DEMO_H
|
||||
|
||||
#include <atomic>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include "avcodec_common.h"
|
||||
#include "avcodec_audio_decoder.h"
|
||||
#include "nocopyable.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace InnerAudioDemo {
|
||||
class ADecSignal {
|
||||
public:
|
||||
std::mutex inMutex_;
|
||||
std::mutex outMutex_;
|
||||
std::condition_variable inCond_;
|
||||
std::condition_variable outCond_;
|
||||
std::queue<uint32_t> inQueue_;
|
||||
std::queue<uint32_t> outQueue_;
|
||||
};
|
||||
|
||||
class ADecDemoCallback : public AVCodecCallback, public NoCopyable {
|
||||
public:
|
||||
explicit ADecDemoCallback(std::shared_ptr<ADecSignal> signal);
|
||||
virtual ~ADecDemoCallback() = default;
|
||||
|
||||
void OnError(AVCodecErrorType errorType, int32_t errorCode) override;
|
||||
void OnOutputFormatChanged(const Format &format) override;
|
||||
void OnInputBufferAvailable(uint32_t index) override;
|
||||
void OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ADecSignal> signal_;
|
||||
};
|
||||
|
||||
class ADecInnerDemo : public NoCopyable {
|
||||
public:
|
||||
ADecInnerDemo() = default;
|
||||
virtual ~ADecInnerDemo() = default;
|
||||
void RunCase();
|
||||
|
||||
private:
|
||||
int32_t CreateDec();
|
||||
int32_t Configure(const Format &format);
|
||||
int32_t Start();
|
||||
int32_t Stop();
|
||||
int32_t Flush();
|
||||
int32_t Reset();
|
||||
int32_t Release();
|
||||
void InputFunc();
|
||||
void OutputFunc();
|
||||
|
||||
std::atomic<bool> isRunning_ = false;
|
||||
std::unique_ptr<std::ifstream> testFile_;
|
||||
std::unique_ptr<std::thread> inputLoop_;
|
||||
std::unique_ptr<std::thread> outputLoop_;
|
||||
std::shared_ptr<AVCodecAudioDecoder> audioDec_;
|
||||
std::shared_ptr<ADecSignal> signal_;
|
||||
std::shared_ptr<ADecDemoCallback> cb_;
|
||||
bool isFirstFrame_ = true;
|
||||
int64_t timeStamp_ = 0;
|
||||
uint32_t frameCount_ = 0;
|
||||
};
|
||||
} // InnerAudioDemo
|
||||
} // namespace AV_Codec
|
||||
} // namespace OHOS
|
||||
#endif // AVCODEC_AUDIO_ENCODER_INNER_DEMO_H
|
@ -15,79 +15,61 @@
|
||||
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "avmuxer_demo.h"
|
||||
#include "avmuxer_ffmpeg_demo.h"
|
||||
#include "avmuxer_engine_demo.h"
|
||||
#include "avcodec_audio_encoder_inner_demo.h"
|
||||
#include "avcodec_audio_decoder_demo.h"
|
||||
#include "avcodec_audio_encoder_demo.h"
|
||||
|
||||
using namespace OHOS;
|
||||
using namespace OHOS::Media;
|
||||
using namespace OHOS::Media::Plugin;
|
||||
using namespace OHOS::Media::AudioDemo;
|
||||
using namespace OHOS::Media::InnerAudioDemo;
|
||||
using namespace std;
|
||||
|
||||
constexpr int RUN_TIME = 600;
|
||||
|
||||
extern "C" {
|
||||
extern int NativeSelectMode();
|
||||
extern int RunNativeMuxer(const char *out);
|
||||
}
|
||||
|
||||
static int RunLoopNativeMuxer(string out)
|
||||
static int RunAudioDecoder()
|
||||
{
|
||||
time_t startTime = time(NULL);
|
||||
time_t curTime = time(NULL);
|
||||
while (difftime(curTime, startTime) < RUN_TIME) {
|
||||
RunNativeMuxer(out.c_str());
|
||||
time(&curTime);
|
||||
auto audioEnc = std::make_unique<ADecDemo>();
|
||||
if (audioEnc == nullptr) {
|
||||
cout << "audio decoder is null" << endl;
|
||||
return 0;
|
||||
}
|
||||
audioEnc->RunCase();
|
||||
cout << "demo audio decoder end" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RunAVMuxer()
|
||||
static int RunAudioEncoder()
|
||||
{
|
||||
auto avmuxer = std::make_unique<AVMuxerDemo>();
|
||||
if (avmuxer == nullptr) {
|
||||
cout << "avmuxer is null" << endl;
|
||||
auto audioEnc = std::make_unique<AEncDemo>();
|
||||
if (audioEnc == nullptr) {
|
||||
cout << "audio encoder is null" << endl;
|
||||
return 0;
|
||||
}
|
||||
avmuxer->RunCase();
|
||||
cout << "demo avmuxer end" << endl;
|
||||
audioEnc->RunCase();
|
||||
cout << "demo audio encoder end" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RunAVMuxerWithMultithread()
|
||||
static int RunAudioInnerDecoder()
|
||||
{
|
||||
auto avmuxer = std::make_unique<AVMuxerDemo>();
|
||||
if (avmuxer == nullptr) {
|
||||
cout << "avmuxer is null" << endl;
|
||||
auto audioEnc = std::make_unique<ADecInnerDemo>();
|
||||
if (audioEnc == nullptr) {
|
||||
cout << "audio decoder is null" << endl;
|
||||
return 0;
|
||||
}
|
||||
avmuxer->RunMultiThreadCase();
|
||||
cout << "demo multi thread avmuxer end" << endl;
|
||||
audioEnc->RunCase();
|
||||
cout << "demo audio decoder end" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RunFfmpegMuxer()
|
||||
static int RunAudioInnerEncoder()
|
||||
{
|
||||
std::unique_ptr<AVMuxerDemoBase> ffmpegMuxer = std::make_unique<AVMuxerFFmpegDemo>();
|
||||
if (ffmpegMuxer == nullptr) {
|
||||
cout << "ffmpegMuxer is null" << endl;
|
||||
auto audioEnc = std::make_unique<ADecInnerDemo>();
|
||||
if (audioEnc == nullptr) {
|
||||
cout << "audio encoder is null" << endl;
|
||||
return 0;
|
||||
}
|
||||
ffmpegMuxer->RunCase();
|
||||
cout << "demo ffmpegMuxer end" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RunEngineMuxer()
|
||||
{
|
||||
std::unique_ptr<AVMuxerDemoBase> muxer = std::make_unique<AVMuxerEngineDemo>();
|
||||
if (muxer == nullptr) {
|
||||
cout << "AVMuxerEngineDemo is null" << endl;
|
||||
return 0;
|
||||
}
|
||||
muxer->RunCase();
|
||||
cout << "demo engine demo end" << endl;
|
||||
audioEnc->RunCase();
|
||||
cout << "demo audio encoder end" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -98,44 +80,24 @@ int main(int argc, char *argv[])
|
||||
if (argc >= minRequiredArgCount && argv[1] != nullptr) {
|
||||
path = argv[1];
|
||||
}
|
||||
cout << "Please select muxer number(default native muxer): " << endl;
|
||||
cout << "0:native_muxer" << endl;
|
||||
cout << "1:native_muxer loop" << endl;
|
||||
cout << "2:native_muxer multithread" << endl;
|
||||
cout << "3:inner_muxer" << endl;
|
||||
cout << "4:inner_muxer with multithread write" << endl;
|
||||
cout << "5:ffmpeg_muxer" << endl;
|
||||
cout << "6:engine_muxer" << endl;
|
||||
cout << "Please select a demo scenario number(default Audio Decoder): " << endl;
|
||||
cout << "0:Audio Decoder" << endl;
|
||||
cout << "1:Audio Encoder" << endl;
|
||||
cout << "2:Audio Inner Decoder" << endl;
|
||||
cout << "3:Audio Inner Encoder" << endl;
|
||||
|
||||
string mode;
|
||||
(void)getline(cin, mode);
|
||||
if (mode == "" || mode == "0") {
|
||||
NativeSelectMode();
|
||||
RunNativeMuxer("native_mux");
|
||||
(void)RunAudioDecoder();
|
||||
} else if (mode == "1") {
|
||||
NativeSelectMode();
|
||||
RunLoopNativeMuxer("loop_native_mux");
|
||||
(void)RunAudioEncoder();
|
||||
} else if (mode == "2") {
|
||||
NativeSelectMode();
|
||||
vector<thread> vecThread;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
string out = to_string(i + 1);
|
||||
out += "_native_mux";
|
||||
vecThread.push_back(thread(RunLoopNativeMuxer, out));
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
vecThread[i].join();
|
||||
}
|
||||
(void)RunAudioInnerDecoder();
|
||||
} else if (mode == "3") {
|
||||
RunAVMuxer();
|
||||
} else if (mode == "4") {
|
||||
RunAVMuxerWithMultithread();
|
||||
} else if (mode == "5") {
|
||||
RunFfmpegMuxer();
|
||||
} else if (mode == "6") {
|
||||
RunEngineMuxer();
|
||||
} else {
|
||||
(void)RunAudioInnerEncoder();
|
||||
} else {
|
||||
cout << "no that selection" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
50
test/nativedemo/include/demo_log.h
Normal file
50
test/nativedemo/include/demo_log.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 DEMO_LOG_H
|
||||
#define DEMO_LOG_H
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace OHOS {
|
||||
#define DEMO_CHECK_AND_RETURN_RET_LOG(cond, ret, fmt, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
(void)printf("%s\n", fmt, ##__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEMO_CHECK_AND_RETURN_LOG(cond, fmt, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
(void)printf("%s\n", fmt, ##__VA_ARGS__); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEMO_CHECK_AND_BREAK_LOG(cond, fmt, ...) \
|
||||
if (!(cond)) { \
|
||||
(void)printf("%s\n", fmt, ##__VA_ARGS__); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define DEMO_CHECK_AND_CONTINUE_LOG(cond, fmt, ...) \
|
||||
if (!(cond)) { \
|
||||
(void)printf("%s\n", fmt, ##__VA_ARGS__); \
|
||||
continue; \
|
||||
}
|
||||
}
|
||||
#endif // DEMO_LOG_H
|
Loading…
Reference in New Issue
Block a user