mirror of
https://gitee.com/openharmony/multimedia_av_codec
synced 2025-02-11 10:46:11 +00:00
commit
aed543404e
2
BUILD.gn
2
BUILD.gn
@ -17,6 +17,6 @@ import("//build/ohos.gni")
|
||||
group("av_codec_packages") {
|
||||
public_deps = [
|
||||
"interfaces/inner_api/native:av_codec_client",
|
||||
"services:av_codec_service",
|
||||
"services/services:av_codec_service",
|
||||
]
|
||||
}
|
||||
|
@ -77,9 +77,10 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"test": [
|
||||
"//foundation/multimedia/av_codec/test:av_codec_demo_test"
|
||||
]
|
||||
"test": [
|
||||
"//foundation/multimedia/av_codec/test:av_codec_demo_test",
|
||||
"//foundation/multimedia/av_codec/test:av_codec_unit_test"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,12 @@
|
||||
|
||||
declare_args() {
|
||||
multimedia_av_codec_support_capi = true
|
||||
multimedia_av_codec_support_codec = true
|
||||
multimedia_av_codec_support_codec = false
|
||||
multimedia_av_codec_support_codeclist = false
|
||||
multimedia_av_codec_support_demuxer = false
|
||||
multimedia_av_codec_support_muxer = true
|
||||
multimedia_av_codec_support_ffmpeg_demuxer = false
|
||||
multimedia_av_codec_support_test = false
|
||||
multimedia_av_codec_support_test = true
|
||||
}
|
||||
|
||||
av_codec_defines = []
|
||||
|
@ -14,15 +14,14 @@
|
||||
*/
|
||||
|
||||
#include "avmuxer_impl.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <functional>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "securec.h"
|
||||
#include "i_avcodec_service.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "avsharedmemorybase.h"
|
||||
#include "avcodec_dfx.h"
|
||||
#include "i_avcodec_service.h"
|
||||
#include "avcodec_errors.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVMuxerImpl"};
|
||||
@ -30,9 +29,9 @@ namespace {
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
std::shared_ptr<AVMuxer> AVMuxerFactory::CreateAVMuxer(int32_t fd, AVOutputFormat format)
|
||||
std::shared_ptr<AVMuxer> AVMuxerFactory::CreateAVMuxer(int32_t fd, OutputFormat format)
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
AVCodecTrace trace("AVMuxerFactory::CreateAVMuxer");
|
||||
CHECK_AND_RETURN_RET_LOG((fcntl(fd, F_GETFL, 0) & O_RDWR) == O_RDWR, nullptr, "No permission to read and write fd");
|
||||
CHECK_AND_RETURN_RET_LOG(lseek(fd, 0, SEEK_CUR) != -1, nullptr, "The fd is not seekable");
|
||||
|
||||
@ -44,7 +43,7 @@ std::shared_ptr<AVMuxer> AVMuxerFactory::CreateAVMuxer(int32_t fd, AVOutputForma
|
||||
return impl;
|
||||
}
|
||||
|
||||
AVMuxerImpl::AVMuxerImpl(int32_t fd, AVOutputFormat format) : fd_(fd), format_(format)
|
||||
AVMuxerImpl::AVMuxerImpl(int32_t fd, OutputFormat format) : fd_(fd), format_(format)
|
||||
{
|
||||
(void)fd_;
|
||||
(void)format_;
|
||||
@ -53,77 +52,77 @@ AVMuxerImpl::AVMuxerImpl(int32_t fd, AVOutputFormat format) : fd_(fd), format_(f
|
||||
|
||||
AVMuxerImpl::~AVMuxerImpl()
|
||||
{
|
||||
if (muxerClient_ != nullptr) {
|
||||
(void)AVCodecServiceFactory::GetInstance().DestroyMuxerService(muxerClient_);
|
||||
muxerClient_ = nullptr;
|
||||
if (muxerService_ != nullptr) {
|
||||
(void)muxerService_->Release();
|
||||
(void)AVCodecServiceFactory::GetInstance().DestroyMuxerService(muxerService_);
|
||||
muxerService_ = nullptr;
|
||||
}
|
||||
AVCODEC_LOGD("AVMuxerImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::Init()
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
muxerClient_ = AVCodecServiceFactory::GetInstance().CreateMuxerService();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "Create avmuxer engine failed");
|
||||
return AVCS_ERR_OK;
|
||||
AVCodecTrace trace("AVMuxer::Init");
|
||||
AVCODEC_LOGI("Init");
|
||||
muxerService_ = AVCodecServiceFactory::GetInstance().CreateMuxerService();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerService_ != nullptr, AVCS_ERR_NO_MEMORY, "Create AVMuxer Service failed");
|
||||
return muxerService_->InitParameter(fd_, format_);
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
|
||||
return muxerClient_->SetLocation(latitude, longitude);
|
||||
AVCodecTrace trace("AVMuxer::SetLocation");
|
||||
AVCODEC_LOGI("SetLocation");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerService_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Service does not exist");
|
||||
return muxerService_->SetLocation(latitude, longitude);
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::SetRotation(int32_t rotation)
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
|
||||
return muxerClient_->SetRotation(rotation);
|
||||
AVCodecTrace trace("AVMuxer::SetRotation");
|
||||
AVCODEC_LOGI("SetRotation");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerService_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Service does not exist");
|
||||
return muxerService_->SetRotation(rotation);
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::SetParameter(const Format &generalFormat)
|
||||
int32_t AVMuxerImpl::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
|
||||
return muxerClient_->SetParameter(generalFormat);
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::AddTrack(uint32_t &trackIndex, const Format &trackFormat)
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
|
||||
return muxerClient_->AddTrack(trackIndex, trackFormat);
|
||||
AVCodecTrace trace("AVMuxer::AddTrack");
|
||||
AVCODEC_LOGI("AddTrack");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerService_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Service does not exist");
|
||||
return muxerService_->AddTrack(trackIndex, trackDesc);
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::Start()
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
|
||||
return muxerClient_->Start();
|
||||
AVCodecTrace trace("AVMuxer::Start");
|
||||
AVCODEC_LOGI("Start");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerService_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Service does not exist");
|
||||
return muxerService_->Start();
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::WriteSampleBuffer(uint32_t trackIndex, uint8_t *sampleBuffer, AVCodecBufferInfo info)
|
||||
int32_t AVMuxerImpl::WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr && info.offset >= 0 && info.size >= 0,
|
||||
AVCS_ERR_INVALID_VAL, "Invalid memory");
|
||||
AVCodecTrace trace("AVMuxer::WriteSampleBuffer");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerService_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Service does not exist");
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr && info.timeUs >= 0, AVCS_ERR_INVALID_VAL, "Invalid memory");
|
||||
|
||||
std::shared_ptr<AVSharedMemory> sharedSampleBuffer =
|
||||
AVSharedMemoryBase::CreateFromLocal(info.size, AVSharedMemory::FLAGS_READ_ONLY, "SampleBuffer");
|
||||
CHECK_AND_RETURN_RET_LOG(sharedSampleBuffer == nullptr, AVCS_ERR_NO_MEMORY, "Create AVSharedMemoryBase failed");
|
||||
errno_t rc = memcpy_s(sharedSampleBuffer->GetBase(), sharedSampleBuffer->GetSize(), sampleBuffer + info.offset, info.size);
|
||||
std::shared_ptr<AVSharedMemoryBase> sharedSampleBuffer =
|
||||
std::make_shared<AVSharedMemoryBase>(info.size, AVSharedMemory::FLAGS_READ_ONLY, "sampleBuffer");
|
||||
int32_t ret = sharedSampleBuffer->Init();
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_NO_MEMORY, "create AVSharedMemoryBase failed");
|
||||
errno_t rc = memcpy_s(sharedSampleBuffer->GetBase(), sharedSampleBuffer->GetSize(), sampleBuffer, info.size);
|
||||
CHECK_AND_RETURN_RET_LOG(rc == EOK, AVCS_ERR_UNKNOWN, "memcpy_s failed");
|
||||
|
||||
return muxerClient_->WriteSampleBuffer(trackIndex, sharedSampleBuffer, info);
|
||||
return muxerService_->WriteSampleBuffer(sharedSampleBuffer, info);
|
||||
}
|
||||
|
||||
int32_t AVMuxerImpl::Stop()
|
||||
{
|
||||
AVCodecTrace trace(std::string(__FUNCTION__));
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Engine does not exist");
|
||||
return muxerClient_->Stop();
|
||||
AVCodecTrace trace("AVMuxer::Stop");
|
||||
AVCODEC_LOGI("Stop");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerService_ != nullptr, AVCS_ERR_INVALID_OPERATION, "AVMuxer Service does not exist");
|
||||
return muxerService_->Stop();
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -16,28 +16,27 @@
|
||||
#define AVMUXER_IMPL_H
|
||||
|
||||
#include "avmuxer.h"
|
||||
#include "i_avmuxer.h"
|
||||
#include "i_muxer_service.h"
|
||||
#include "nocopyable.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerImpl : public AVMuxer, public NoCopyable {
|
||||
public:
|
||||
AVMuxerImpl(int32_t fd, AVOutputFormat format);
|
||||
AVMuxerImpl(int32_t fd, OutputFormat format);
|
||||
~AVMuxerImpl() override;
|
||||
int32_t Init();
|
||||
int32_t SetLocation(float latitude, float longitude) override;
|
||||
int32_t SetRotation(int32_t rotation) override;
|
||||
int32_t SetParameter(const Format &generalFormat) override;
|
||||
int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) override;
|
||||
int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) override;
|
||||
int32_t Start() override;
|
||||
int32_t WriteSampleBuffer(uint32_t trackIndex, uint8_t *sampleBuffer, AVCodecBufferInfo info) override;
|
||||
int32_t WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info) override;
|
||||
int32_t Stop() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<IAVMuxer> muxerClient_ = nullptr;
|
||||
std::shared_ptr<IMuxerService> muxerService_ = nullptr;
|
||||
int32_t fd_ = -1;
|
||||
AVOutputFormat format_ = AV_OUTPUT_FORMAT_UNKNOWN;
|
||||
OutputFormat format_ = OUTPUT_FORMAT_UNKNOWN;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
|
@ -20,7 +20,12 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
const char *OH_AVCODEC_MIMETYPE_VIDEO_AVC = "video/avc";
|
||||
const char *OH_AVCODEC_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
|
||||
const char *OH_AVCODEC_MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
|
||||
const char *OH_AVCODEC_MIMETYPE_AUDIO_MPEG = "audio/mpeg";
|
||||
const char *OH_AVCODEC_MIMETYPE_IMAGE_JPG = "image/jpeg";
|
||||
const char *OH_AVCODEC_MIMETYPE_IMAGE_PNG = "image/png";
|
||||
const char *OH_AVCODEC_MIMETYPE_IMAGE_BMP = "image/bmp";
|
||||
const char *OH_ED_KEY_TIME_STAMP = "timeStamp";
|
||||
const char *OH_ED_KEY_EOS = "endOfStream";
|
||||
const char *OH_MD_KEY_TRACK_TYPE = "track_type";
|
||||
@ -39,6 +44,7 @@ const char *OH_MD_KEY_AUD_CHANNEL_COUNT = "channel_count";
|
||||
const char *OH_MD_KEY_AUD_SAMPLE_RATE = "sample_rate";
|
||||
const char *OH_MD_KEY_I_FRAME_INTERVAL = "i_frame_interval";
|
||||
const char *OH_MD_KEY_ROTATION = "rotation_angle";
|
||||
const char *OH_MD_KEY_CODEC_CONFIG = "codec_config";
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "native_avmagic.h"
|
||||
#include "avmuxer.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "avcodec_errors.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "NativeAVMuxer"};
|
||||
@ -34,7 +35,7 @@ struct AVMuxerObject : public OH_AVMuxer {
|
||||
|
||||
struct OH_AVMuxer *OH_AVMuxer_Create(int32_t fd, OH_AVOutputFormat format) {
|
||||
CHECK_AND_RETURN_RET_LOG(fd >= 0, nullptr, "fd %{public}d is error!", fd);
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd, static_cast<AVOutputFormat>(format));
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd, static_cast<OutputFormat>(format));
|
||||
CHECK_AND_RETURN_RET_LOG(avmuxer != nullptr, nullptr, "create muxer failed!");
|
||||
struct AVMuxerObject *object = new(std::nothrow) AVMuxerObject(avmuxer);
|
||||
return object;
|
||||
@ -60,23 +61,18 @@ OH_AVErrCode OH_AVMuxer_SetRotation(OH_AVMuxer *muxer, int32_t rotation) {
|
||||
struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
|
||||
CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
|
||||
|
||||
if (rotation != VIDEO_ROTATION_0 && rotation != VIDEO_ROTATION_90 &&
|
||||
rotation != VIDEO_ROTATION_180 &&rotation != VIDEO_ROTATION_270) {
|
||||
CHECK_AND_RETURN_RET_LOG(false, AV_ERR_INVALID_VAL, "rotation is invalid value!");
|
||||
}
|
||||
|
||||
int32_t ret = object->muxer_->SetRotation(rotation);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AV_ERR_OPERATE_NOT_PERMIT, "muxer_ SetRotation failed!");
|
||||
|
||||
return AV_ERR_OK;
|
||||
}
|
||||
|
||||
OH_AVErrCode OH_AVMuxer_AddTrack(OH_AVMuxer *muxer, uint32_t *trackIndex, OH_AVFormat *trackFormat) {
|
||||
OH_AVErrCode OH_AVMuxer_AddTrack(OH_AVMuxer *muxer, int32_t *trackIndex, OH_AVFormat *trackFormat) {
|
||||
CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AV_ERR_INVALID_VAL, "input muxer is nullptr!");
|
||||
CHECK_AND_RETURN_RET_LOG(muxer->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
|
||||
CHECK_AND_RETURN_RET_LOG(trackIndex != nullptr, AV_ERR_INVALID_VAL, "input track index is nullptr!");
|
||||
CHECK_AND_RETURN_RET_LOG(trackFormat != nullptr, AV_ERR_INVALID_VAL, "input track format is nullptr!");
|
||||
CHECK_AND_RETURN_RET_LOG(trackFormat->magic_ == AVMagic::AVCODEC_MAGIC_AVMUXER, AV_ERR_INVALID_VAL, "magic error!");
|
||||
CHECK_AND_RETURN_RET_LOG(trackFormat->magic_ == AVMagic::AVCODEC_MAGIC_FORMAT, AV_ERR_INVALID_VAL, "magic error!");
|
||||
|
||||
struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
|
||||
CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
|
||||
@ -106,11 +102,14 @@ OH_AVErrCode OH_AVMuxer_WriteSampleBuffer(OH_AVMuxer *muxer, uint32_t trackIndex
|
||||
|
||||
struct AVMuxerObject *object = reinterpret_cast<AVMuxerObject *>(muxer);
|
||||
CHECK_AND_RETURN_RET_LOG(object->muxer_ != nullptr, AV_ERR_INVALID_VAL, "muxer_ is nullptr!");
|
||||
AVCodecBufferInfo innerInfo;
|
||||
innerInfo.presentationTimeUs = info.pts;
|
||||
innerInfo.offset = info.offset;
|
||||
innerInfo.size = info.size;
|
||||
int32_t ret = object->muxer_->WriteSampleBuffer(trackIndex, sampleBuffer, innerInfo);
|
||||
|
||||
TrackSampleInfo sampleInfo;
|
||||
sampleInfo.trackIndex = trackIndex;
|
||||
sampleInfo.timeUs = info.pts;
|
||||
sampleInfo.size = info.size;
|
||||
sampleInfo.flags = info.flags;
|
||||
|
||||
int32_t ret = object->muxer_->WriteSampleBuffer(sampleBuffer, sampleInfo);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AV_ERR_OPERATE_NOT_PERMIT, "muxer_ WriteSampleBuffer failed!");
|
||||
|
||||
return AV_ERR_OK;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "avsharedmemory.h"
|
||||
#include "avcodec_common.h"
|
||||
#include "format.h"
|
||||
#include "avcodec_info.h"
|
||||
|
||||
|
||||
#define AV_MAGIC(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + ((d) << 0))
|
||||
|
@ -100,6 +100,16 @@ config("av_codec_client_local_config") {
|
||||
]
|
||||
}
|
||||
|
||||
config("av_codec_client_ipc_config") {
|
||||
include_dirs = [
|
||||
"$AV_CODEC_ROOT_DIR/services/services/sa_avcodec/client",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/sa_avcodec/ipc",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/common",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/muxer/client",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/muxer/ipc",
|
||||
]
|
||||
}
|
||||
|
||||
config("av_codec_client_public_config") {
|
||||
include_dirs = [
|
||||
"$AV_CODEC_ROOT_DIR/frameworks/native/avcodec",
|
||||
@ -111,6 +121,7 @@ config("av_codec_client_public_config") {
|
||||
"$AV_CODEC_ROOT_DIR/services/utils",
|
||||
"$AV_CODEC_ROOT_DIR/services/include",
|
||||
"$AV_CODEC_ROOT_DIR/services/dfx/include",
|
||||
"$AV_CODEC_ROOT_DIR/services/utils/include",
|
||||
"//base/hiviewdfx/hilog/interfaces/native/innerkits/include",
|
||||
"//utils/system/safwk/native/include",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
@ -159,6 +170,7 @@ ohos_shared_library("av_codec_client") {
|
||||
install_enable = true
|
||||
public_configs = [
|
||||
":av_codec_client_local_config",
|
||||
":av_codec_client_ipc_config",
|
||||
":av_codec_client_public_config",
|
||||
":av_codec_packege_include",
|
||||
]
|
||||
@ -202,8 +214,8 @@ ohos_shared_library("av_codec_client") {
|
||||
if (multimedia_av_codec_support_muxer) {
|
||||
sources += [
|
||||
"$AV_CODEC_ROOT_DIR/frameworks/native/avmuxer/avmuxer_impl.cpp",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/muxer/client/avmuxer_client.cpp",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/muxer/ipc/avmuxer_proxy.cpp",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/muxer/client/muxer_client.cpp",
|
||||
"$AV_CODEC_ROOT_DIR/services/services/muxer/ipc/muxer_service_proxy.cpp",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -118,20 +118,20 @@ enum AVSeekMode : uint8_t {
|
||||
*/
|
||||
enum VideoRotation : uint32_t {
|
||||
/**
|
||||
* Video without rotation
|
||||
*/
|
||||
* Video without rotation
|
||||
*/
|
||||
VIDEO_ROTATION_0 = 0,
|
||||
/**
|
||||
* Video rotated 90 degrees
|
||||
*/
|
||||
* Video rotated 90 degrees
|
||||
*/
|
||||
VIDEO_ROTATION_90 = 90,
|
||||
/**
|
||||
* Video rotated 180 degrees
|
||||
*/
|
||||
* Video rotated 180 degrees
|
||||
*/
|
||||
VIDEO_ROTATION_180 = 180,
|
||||
/**
|
||||
* Video rotated 270 degrees
|
||||
*/
|
||||
* Video rotated 270 degrees
|
||||
*/
|
||||
VIDEO_ROTATION_270 = 270,
|
||||
};
|
||||
|
||||
@ -151,6 +151,53 @@ enum StateChangeReason {
|
||||
*/
|
||||
BACKGROUND = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enumerates the output format.
|
||||
*
|
||||
* @since 10
|
||||
* @version 4.0
|
||||
*/
|
||||
enum OutputFormat : uint32_t{
|
||||
/**
|
||||
* output format unknown
|
||||
*/
|
||||
OUTPUT_FORMAT_UNKNOWN = 0,
|
||||
/**
|
||||
* output format mp4
|
||||
*/
|
||||
OUTPUT_FORMAT_MPEG_4 = 1,
|
||||
/**
|
||||
* output format m4a
|
||||
*/
|
||||
OUTPUT_FORMAT_M4A = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Description information of a sample associated a media track.
|
||||
*
|
||||
* @since 10
|
||||
* @version 4.0
|
||||
*/
|
||||
struct TrackSampleInfo {
|
||||
/**
|
||||
* @brief the id of track that this sample belongs to.
|
||||
*/
|
||||
uint32_t trackIndex;
|
||||
/**
|
||||
* @brief the presentation timestamp in microseconds.
|
||||
*/
|
||||
int64_t timeUs;
|
||||
/**
|
||||
* @brief the size in bytes.
|
||||
*/
|
||||
uint32_t size;
|
||||
/**
|
||||
* @brief the flags associated with the sample, this
|
||||
* maybe be a combination of multiple {@link AVCodecBufferFlag}.
|
||||
*/
|
||||
uint32_t flags;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // AV_COMMOM_H
|
@ -57,16 +57,11 @@ struct AVCodecBufferInfo {
|
||||
int32_t offset = 0;
|
||||
};
|
||||
|
||||
typedef enum AVOutputFormat {
|
||||
AV_OUTPUT_FORMAT_UNKNOWN = 0,
|
||||
AV_OUTPUT_FORMAT_MPEG_4 = 1,
|
||||
AV_OUTPUT_FORMAT_M4A = 2,
|
||||
} AVOutputFormat;
|
||||
|
||||
struct AVBufferElement {
|
||||
std::shared_ptr<AVSharedMemory> buffer;
|
||||
std::shared_ptr<AVSharedMemory> metaData;
|
||||
};
|
||||
|
||||
class AVCodecCallback {
|
||||
public:
|
||||
virtual ~AVCodecCallback() = default;
|
||||
|
@ -16,7 +16,6 @@
|
||||
#ifndef AVCODEC_ERRORS_H
|
||||
#define AVCODEC_ERRORS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "errors.h"
|
||||
#include "native_averrors.h"
|
||||
|
@ -508,6 +508,9 @@ public:
|
||||
static constexpr std::string_view AUDIO_OPUS = "audio/opus";
|
||||
static constexpr std::string_view AUDIO_FLAC = "audio/flac";
|
||||
static constexpr std::string_view AUDIO_RAW = "audio/raw";
|
||||
static constexpr std::string_view IMAGE_JPG = "image/jpeg";
|
||||
static constexpr std::string_view IMAGE_PNG = "image/png";
|
||||
static constexpr std::string_view IMAGE_BMP = "image/bmp";
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -16,9 +16,8 @@
|
||||
#ifndef AVMUXER_H
|
||||
#define AVMUXER_H
|
||||
|
||||
#include "format.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_common.h"
|
||||
#include "media_description.h"
|
||||
#include "av_common.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
@ -27,21 +26,20 @@ public:
|
||||
virtual ~AVMuxer() = default;
|
||||
virtual int32_t SetLocation(float latitude, float longitude) = 0;
|
||||
virtual int32_t SetRotation(int32_t rotation) = 0;
|
||||
virtual int32_t SetParameter(const Format &generalFormat) = 0;
|
||||
virtual int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) = 0;
|
||||
virtual int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) = 0;
|
||||
virtual int32_t Start() = 0;
|
||||
virtual int32_t WriteSampleBuffer(uint32_t trackIndex, uint8_t *sampleBuffer, AVCodecBufferInfo info) = 0;
|
||||
virtual int32_t WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info) = 0;
|
||||
virtual int32_t Stop() = 0;
|
||||
};
|
||||
|
||||
class __attribute__((visibility("default"))) AVMuxerFactory {
|
||||
public:
|
||||
static std::shared_ptr<AVMuxer> CreateAVMuxer(int32_t fd, AVOutputFormat format);
|
||||
static std::shared_ptr<AVMuxer> CreateAVMuxer(int32_t fd, OutputFormat format);
|
||||
private:
|
||||
AVMuxerFactory() = default;
|
||||
~AVMuxerFactory() = default;
|
||||
};
|
||||
} // namespace MediaAVCodec
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // AVMUXER_H
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -68,7 +68,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value, which is a 32-bit integer.
|
||||
* @return Returns <b>true</b> if the setting is successful; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool PutIntValue(const std::string_view &key, int32_t value);
|
||||
@ -79,7 +79,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value, which is a 64-bit integer.
|
||||
* @return Returns <b>true</b> if the setting is successful; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool PutLongValue(const std::string_view &key, int64_t value);
|
||||
@ -90,7 +90,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value, which is a single-precision floating-point number.
|
||||
* @return Returns <b>true</b> if the metadata is successfully set; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool PutFloatValue(const std::string_view &key, float value);
|
||||
@ -101,7 +101,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value, which is a double-precision floating-point number.
|
||||
* @return Returns <b>true</b> if the setting is successful; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool PutDoubleValue(const std::string_view &key, double value);
|
||||
@ -112,7 +112,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value, which is a string.
|
||||
* @return Returns <b>true</b> if the metadata is successfully set; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool PutStringValue(const std::string_view &key, const std::string_view &value);
|
||||
@ -124,7 +124,7 @@ public:
|
||||
* @param addr Indicates the metadata addr, which is a uint8_t *.
|
||||
* @param size Indicates the metadata addr size, which is a size_t.
|
||||
* @return Returns <b>true</b> if the metadata is successfully set; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool PutBuffer(const std::string_view &key, const uint8_t *addr, size_t size);
|
||||
@ -135,7 +135,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value to obtain, which is a 32-bit integer.
|
||||
* @return Returns <b>true</b> if the integer is successfully obtained; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool GetIntValue(const std::string_view &key, int32_t &value) const;
|
||||
@ -146,7 +146,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value to obtain, which is a 64-bit long integer.
|
||||
* @return Returns <b>true</b> if the integer is successfully obtained; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool GetLongValue(const std::string_view &key, int64_t &value) const;
|
||||
@ -158,7 +158,7 @@ public:
|
||||
* @param value Indicates the metadata value to obtain, which is a single-precision floating-point number.
|
||||
* @return Returns <b>true</b> if the single-precision number is successfully obtained; returns
|
||||
* <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool GetFloatValue(const std::string_view &key, float &value) const;
|
||||
@ -170,7 +170,7 @@ public:
|
||||
* @param value Indicates the metadata value to obtain, which is a double-precision floating-point number.
|
||||
* @return Returns <b>true</b> if the double-precision number is successfully obtained; returns
|
||||
* <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool GetDoubleValue(const std::string_view &key, double &value) const;
|
||||
@ -181,7 +181,7 @@ public:
|
||||
* @param key Indicates the metadata key.
|
||||
* @param value Indicates the metadata value to obtain, which is a string.
|
||||
* @return Returns <b>true</b> if the string is successfully obtained; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool GetStringValue(const std::string_view &key, std::string &value) const;
|
||||
@ -193,7 +193,7 @@ public:
|
||||
* @param addr Indicates the metadata addr to obtain, which is a uint8_t **.
|
||||
* @param size Indicates the metadata addr size to obtain, which is a size_t.
|
||||
* @return Returns <b>true</b> if the string is successfully obtained; returns <b>false</b> otherwise.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool GetBuffer(const std::string_view &key, uint8_t **addr, size_t &size) const;
|
||||
@ -233,7 +233,7 @@ public:
|
||||
* @brief Obtains the metadata map.
|
||||
*
|
||||
* @return Returns the map object.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
const FormatDataMap &GetFormatMap() const;
|
||||
@ -242,7 +242,7 @@ public:
|
||||
* @brief Convert the metadata map to string.
|
||||
*
|
||||
* @return Returns a converted string.
|
||||
* @since 1.0
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
std::string Stringify() const;
|
||||
|
136
interfaces/inner_api/native/media_description.h
Normal file
136
interfaces/inner_api/native/media_description.h
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 MEDIA_DESCRIPTION_H
|
||||
#define MEDIA_DESCRIPTION_H
|
||||
|
||||
#include "format.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
/**
|
||||
* @brief Provides the uniform container for storing the media description.
|
||||
*/
|
||||
using MediaDescription = Format;
|
||||
|
||||
/**
|
||||
* @brief Provides the key's definition for MediaDescription.
|
||||
*/
|
||||
class MediaDescriptionKey {
|
||||
public:
|
||||
/**
|
||||
* Key for track index, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_TRACK_INDEX = "track_index";
|
||||
|
||||
/**
|
||||
* Key for track type, value type is uint8_t, see {link @MediaTrackType}
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_TRACK_TYPE = "track_type";
|
||||
|
||||
/**
|
||||
* Key for codec mime type, value type is string
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_CODEC_MIME = "codec_mime";
|
||||
|
||||
/**
|
||||
* Key for duration, value type is int64_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_DURATION = "duration";
|
||||
|
||||
/**
|
||||
* Key for bitrate, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_BITRATE = "bitrate";
|
||||
|
||||
/**
|
||||
* Key for max input size, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_MAX_INPUT_SIZE = "max_input_size";
|
||||
|
||||
/**
|
||||
* Key for video width, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_WIDTH = "width";
|
||||
|
||||
/**
|
||||
* Key for video height, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_HEIGHT = "height";
|
||||
|
||||
/**
|
||||
* Key for video pixelformat, value type is int32_t, see {link @MediaPixelFormat}
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_PIXEL_FORMAT = "pixel_format";
|
||||
|
||||
/**
|
||||
* Key for video frame rate, value type is double.
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_FRAME_RATE = "frame_rate";
|
||||
|
||||
/**
|
||||
* Key for video capture rate, value type is double
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_CAPTURE_RATE = "capture_rate";
|
||||
|
||||
/**
|
||||
* Key for the interval of key frame. value type is int32_t, the unit is milliseconds.
|
||||
* A negative value means no key frames are requested after the first frame. A zero
|
||||
* value means a stream containing all key frames is requested.
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_I_FRAME_INTERVAL = "i_frame_interval";
|
||||
|
||||
/**
|
||||
* Key for the request a I-Frame immediately. value type is boolean
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_REQUEST_I_FRAME = "req_i_frame";
|
||||
|
||||
/**
|
||||
* Key for audio channel count, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_CHANNEL_COUNT = "channel_count";
|
||||
|
||||
/**
|
||||
* Key for audio sample rate, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_SAMPLE_RATE = "sample_rate";
|
||||
|
||||
/**
|
||||
* Key for track count in the container, value type is uint32_t
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_TRACK_COUNT = "track_count";
|
||||
|
||||
/**
|
||||
* Key for container format type, value type is string
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_CONTAINER_FORMAT = "container_format";
|
||||
|
||||
/**
|
||||
* custom key prefix, media service will pass through to HAL.
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_CUSTOM_PREFIX = "vendor.custom";
|
||||
|
||||
/**
|
||||
* Key for codec specific data buffer, vlaue type is uint8_t*
|
||||
*/
|
||||
static constexpr std::string_view MD_KEY_CODEC_CONFIG = "codec_config";
|
||||
|
||||
private:
|
||||
MediaDescriptionKey() = delete;
|
||||
~MediaDescriptionKey() = delete;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // MEDIA_DESCRIPTION_H
|
@ -206,6 +206,9 @@ ohos_shared_library("native_av_codec_codec") {
|
||||
ohos_shared_library("native_av_codec_avmuxer") {
|
||||
install_enable = true
|
||||
sources = [
|
||||
"$AV_CODEC_ROOT_DIR/frameworks/native/capi/avcodec/native_avcodec_base.cpp",
|
||||
"$AV_CODEC_ROOT_DIR/frameworks/native/capi/common/native_avformat.cpp",
|
||||
"$AV_CODEC_ROOT_DIR/frameworks/native/capi/common/native_avmemory.cpp",
|
||||
"$AV_CODEC_ROOT_DIR/frameworks/native/capi/avmuxer/native_avmuxer.cpp",
|
||||
]
|
||||
|
||||
@ -214,14 +217,11 @@ ohos_shared_library("native_av_codec_avmuxer") {
|
||||
deps = [
|
||||
"//foundation/multimedia/av_codec/interfaces/inner_api/native:av_codec_client",
|
||||
"//foundation/multimedia/av_codec/services/utils:av_codec_format",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c:native_av_codec_core",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"c_utils:utils",
|
||||
"graphic_standard:surface",
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
"graphic_standard:surface",
|
||||
]
|
||||
output_extension = "so"
|
||||
subsystem_name = "multimedia"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2022 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
|
||||
@ -20,6 +20,7 @@ ohos_ndk_headers("native_av_codec_avmuxer_header") {
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c/native_avbase.h",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c/native_averrors.h",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c/native_avformat.h",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c/native_avmemory.h",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c/native_avmuxer.h",
|
||||
]
|
||||
}
|
||||
@ -35,6 +36,7 @@ ohos_ndk_library("libnative_av_codec_avmuxer") {
|
||||
"native_av_codec_avmuxer/native_avbase.h",
|
||||
"native_av_codec_avmuxer/native_averrors.h",
|
||||
"native_av_codec_avmuxer/native_avformat.h",
|
||||
"native_av_codec_avmuxer/native_avmemory.h",
|
||||
"native_av_codec_avmuxer/native_avmuxer.h",
|
||||
]
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
{ "name": "OH_AVFormat_GetStringValue" },
|
||||
{ "name": "OH_AVFormat_GetBuffer" },
|
||||
{ "name": "OH_AVFormat_DumpInfo" },
|
||||
{ "name": "OH_AVMemory_GetAddr" },
|
||||
{ "name": "OH_AVMemory_GetSize" },
|
||||
{ "name": "OH_AVMuxer_Create" },
|
||||
{ "name": "OH_AVMuxer_SetLocation" },
|
||||
{ "name": "OH_AVMuxer_SetRotation" },
|
||||
|
@ -47,6 +47,18 @@ typedef enum OH_AVCodecBufferFlags {
|
||||
AVCODEC_BUFFER_FLAGS_CODEC_DATA = 1 << 3,
|
||||
} OH_AVCodecBufferFlags;
|
||||
|
||||
/**
|
||||
* @brief Enumerates the muxer ouputfile format
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
typedef enum OH_AVOutputFormat {
|
||||
AV_OUTPUT_FORMAT_UNKNOWN = 0,
|
||||
AV_OUTPUT_FORMAT_MPEG_4 = 1,
|
||||
AV_OUTPUT_FORMAT_M4A = 2,
|
||||
} OH_AVOutputFormat;
|
||||
|
||||
/**
|
||||
* @brief Define the Buffer description information of OH_AVCodec
|
||||
* @syscap SystemCapability.Multimedia.Media.CodecBase
|
||||
@ -64,18 +76,6 @@ typedef struct OH_AVCodecBufferAttr {
|
||||
uint32_t flags;
|
||||
} OH_AVCodecBufferAttr;
|
||||
|
||||
/**
|
||||
* @brief Enumerates the muxer ouputfile format
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
typedef enum OH_AVOutputFormat {
|
||||
AV_OUTPUT_FORMAT_UNKNOWN = 0,
|
||||
AV_OUTPUT_FORMAT_MPEG_4 = 1,
|
||||
AV_OUTPUT_FORMAT_M4A = 2,
|
||||
} OH_AVOutputFormat;
|
||||
|
||||
/**
|
||||
* @brief When an error occurs in the running of the OH_AVCodec instance, the function pointer will be called
|
||||
* to report specific error information.
|
||||
@ -157,7 +157,12 @@ typedef struct OH_AVCodecAsyncCallback {
|
||||
* @version 1.0
|
||||
*/
|
||||
extern const char *OH_AVCODEC_MIMETYPE_VIDEO_AVC;
|
||||
extern const char *OH_AVCODEC_MIMETYPE_VIDEO_MPEG4;
|
||||
extern const char *OH_AVCODEC_MIMETYPE_AUDIO_AAC;
|
||||
extern const char *OH_AVCODEC_MIMETYPE_AUDIO_MPEG;
|
||||
extern const char *OH_AVCODEC_MIMETYPE_IMAGE_JPG;
|
||||
extern const char *OH_AVCODEC_MIMETYPE_IMAGE_PNG;
|
||||
extern const char *OH_AVCODEC_MIMETYPE_IMAGE_BMP;
|
||||
|
||||
/**
|
||||
* @brief The extra data's key of surface Buffer
|
||||
@ -208,6 +213,8 @@ extern const char *OH_MD_KEY_AUD_SAMPLE_RATE;
|
||||
extern const char *OH_MD_KEY_I_FRAME_INTERVAL;
|
||||
/* Key of the surface rotation angle. value type is int32_t: should be {0, 90, 180, 270}, default is 0. */
|
||||
extern const char *OH_MD_KEY_ROTATION;
|
||||
/* Key of the codec specific data. value type is uint8_t*. */
|
||||
extern const char *OH_MD_KEY_CODEC_CONFIG;
|
||||
|
||||
/**
|
||||
* @brief Media type.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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
|
||||
@ -21,8 +21,8 @@ extern "C" {
|
||||
|
||||
/**
|
||||
* @brief AV error code
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @since 9
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
typedef enum OH_AVErrCode {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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
|
||||
@ -26,219 +26,190 @@ extern "C" {
|
||||
|
||||
typedef struct OH_AVFormat OH_AVFormat;
|
||||
|
||||
/**
|
||||
* @brief Enumerates AVPixel Format.
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @since 9
|
||||
* @version 1.0
|
||||
*/
|
||||
typedef enum OH_AVPixelFormat {
|
||||
/**
|
||||
* yuv 420 planar.
|
||||
*/
|
||||
AV_PIXEL_FORMAT_YUVI420 = 1,
|
||||
/**
|
||||
* NV12. yuv 420 semiplanar.
|
||||
*/
|
||||
AV_PIXEL_FORMAT_NV12 = 2,
|
||||
/**
|
||||
* NV21. yvu 420 semiplanar.
|
||||
*/
|
||||
AV_PIXEL_FORMAT_NV21 = 3,
|
||||
/**
|
||||
* format from surface.
|
||||
*/
|
||||
AV_PIXEL_FORMAT_SURFACE_FORMAT = 4,
|
||||
/**
|
||||
* RGBA8888
|
||||
*/
|
||||
AV_PIXEL_FORMAT_RGBA = 5,
|
||||
} OH_AVPixelFormat;
|
||||
|
||||
/**
|
||||
* @briefCreate an OH_AVFormat handle pointer to read and write data
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @return Returns a pointer to an OH_AVFormat instance
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
struct OH_AVFormat *OH_AVFormat_Create(void);
|
||||
|
||||
/**
|
||||
* @brief Destroy the specified OH_AVFormat handle resource
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @return void
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
void OH_AVFormat_Destroy(struct OH_AVFormat *format);
|
||||
|
||||
/**
|
||||
* @brief Copy OH_AVFormat handle resource
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param to OH_AVFormat handle pointer to receive data
|
||||
* @param from pointer to the OH_AVFormat handle of the copied data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_Copy(struct OH_AVFormat *to, struct OH_AVFormat *from);
|
||||
|
||||
/**
|
||||
* @brief Write Int data to OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key key to write data
|
||||
* @param value written data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_SetIntValue(struct OH_AVFormat *format, const char *key, int32_t value);
|
||||
|
||||
/**
|
||||
* @brief Write Long data to OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key key to write data
|
||||
* @param value written data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_SetLongValue(struct OH_AVFormat *format, const char *key, int64_t value);
|
||||
|
||||
/**
|
||||
* @brief Write Float data to OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key key to write data
|
||||
* @param value written data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_SetFloatValue(struct OH_AVFormat *format, const char *key, float value);
|
||||
|
||||
/**
|
||||
* @brief Write Double data to OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key key to write data
|
||||
* @param value written data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_SetDoubleValue(struct OH_AVFormat *format, const char *key, double value);
|
||||
|
||||
/**
|
||||
* @brief Write String data to OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key key to write data
|
||||
* @param value written data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_SetStringValue(struct OH_AVFormat *format, const char *key, const char *value);
|
||||
|
||||
/**
|
||||
* @brief Writes a block of data of a specified length to OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key key to write data
|
||||
* @param addr written data addr
|
||||
* @param size written data length
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_SetBuffer(struct OH_AVFormat *format, const char *key, const uint8_t *addr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Read Int data from OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key read key value
|
||||
* @param out read data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_GetIntValue(struct OH_AVFormat *format, const char *key, int32_t *out);
|
||||
|
||||
/**
|
||||
* @brief Read Long data from OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key read key value
|
||||
* @param out read data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_GetLongValue(struct OH_AVFormat *format, const char *key, int64_t *out);
|
||||
|
||||
/**
|
||||
* @brief Read Float data from OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key read key value
|
||||
* @param out read data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_GetFloatValue(struct OH_AVFormat *format, const char *key, float *out);
|
||||
|
||||
/**
|
||||
* @brief Read Double data from OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key read key value
|
||||
* @param out read data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_GetDoubleValue(struct OH_AVFormat *format, const char *key, double *out);
|
||||
|
||||
/**
|
||||
* @brief Read Double data from OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key read key value
|
||||
* @param out The read string pointer, the data life cycle pointed to is updated with GetString,
|
||||
* and Format is destroyed. If the caller needs to hold it for a long time, it must copy the memory
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_GetStringValue(struct OH_AVFormat *format, const char *key, const char **out);
|
||||
|
||||
/**
|
||||
* @brief Read a block of data of specified length from OH_AVFormat
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @param key Key value for reading and writing data
|
||||
* @param addr The life cycle is held by the format, with the destruction of the format,
|
||||
* if the caller needs to hold it for a long time, it must copy the memory
|
||||
* @param size Length of read and write data
|
||||
* @return The return value is TRUE for success, FALSE for failure
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
bool OH_AVFormat_GetBuffer(struct OH_AVFormat *format, const char *key, uint8_t **addr, size_t *size);
|
||||
|
||||
/**
|
||||
* @brief Output the information contained in OH_AVFormat as a string.
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @syscap SystemCapability.Multimedia.Media.AVCodec
|
||||
* @param format pointer to an OH_AVFormat instance
|
||||
* @return Returns a string consisting of key and data
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
const char *OH_AVFormat_DumpInfo(struct OH_AVFormat *format);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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
|
||||
@ -29,7 +29,7 @@ typedef struct OH_AVMemory OH_AVMemory;
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @param mem Encapsulate OH_AVMemory structure instance pointer
|
||||
* @return the memory's virtual address if the memory is valid, otherwise nullptr.
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
uint8_t *OH_AVMemory_GetAddr(struct OH_AVMemory *mem);
|
||||
@ -39,7 +39,7 @@ uint8_t *OH_AVMemory_GetAddr(struct OH_AVMemory *mem);
|
||||
* @syscap SystemCapability.Multimedia.Media.Core
|
||||
* @param mem Encapsulate OH_AVMemory structure instance pointer
|
||||
* @return the memory's size if the memory is valid, otherwise -1.
|
||||
* @since 9
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
int32_t OH_AVMemory_GetSize(struct OH_AVMemory *mem);
|
||||
|
@ -74,15 +74,16 @@ OH_AVErrCode OH_AVMuxer_SetRotation(OH_AVMuxer *muxer, int32_t rotation);
|
||||
* Note: This interface can only be called before OH_AVMuxer_Start.
|
||||
* @syscap SystemCapability.Multimedia.Media.AVMuxer
|
||||
* @param muxer Pointer to an OH_AVMuxer instance
|
||||
* @param trackIndex The uint32_t handle pointer used to get the track index for this newly added track,
|
||||
* and it should be used in the OH_AVMuxer_WriteSampleBuffer. The track index is greater than or equal to 0.
|
||||
* @param trackIndex The int32_t handle pointer used to get the track index for this newly added track,
|
||||
* and it should be used in the OH_AVMuxer_WriteSampleBuffer. The track index is greater than or equal to 0,
|
||||
* others is error index.
|
||||
* @param trackFormat OH_AVFormat handle pointer contain track format
|
||||
* @return Returns AV_ERR_OK if the execution is successful,
|
||||
* otherwise returns a specific error code, refer to {@link OH_AVErrCode}
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
OH_AVErrCode OH_AVMuxer_AddTrack(OH_AVMuxer *muxer, uint32_t *trackIndex, OH_AVFormat *trackFormat);
|
||||
OH_AVErrCode OH_AVMuxer_AddTrack(OH_AVMuxer *muxer, int32_t *trackIndex, OH_AVFormat *trackFormat);
|
||||
|
||||
/**
|
||||
* @brief Start the muxer.
|
||||
|
@ -16,8 +16,6 @@ import("//build/ohos.gni")
|
||||
group("av_codec_services_package") {
|
||||
deps = [
|
||||
"etc:av_codec_service.cfg",
|
||||
"engine:av_codec_engine_package",
|
||||
"services:av_codec_service",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ import("//foundation/multimedia/av_codec/config.gni")
|
||||
|
||||
group("av_codec_engine_package") {
|
||||
deps = [
|
||||
"plugin:av_codec_engine_plugins",
|
||||
"plugin:av_codec_plugin",
|
||||
#"avcodeclist:av_codec_engine_avcodeclist",
|
||||
]
|
||||
}
|
||||
|
364
services/engine/muxer/muxer_engine_impl.cpp
Normal file
364
services/engine/muxer/muxer_engine_impl.cpp
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* 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 "muxer_engine_impl.h"
|
||||
#include <set>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "securec.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "muxer_factory.h"
|
||||
#include "avcodec_dfx.h"
|
||||
#include "avcodec_info.h"
|
||||
#include "avcodec_errors.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MuxerEngineImpl"};
|
||||
constexpr int32_t MAX_LATITUDE = 90;
|
||||
constexpr int32_t MIN_LATITUDE = -90;
|
||||
constexpr int32_t MAX_LONGITUDE = 180;
|
||||
constexpr int32_t MIN_LONGITUDE = -180;
|
||||
constexpr int32_t ERR_TRACK_INDEX = -1;
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
const std::map<uint32_t, std::set<std::string_view>> MUX_FORMAT_INFO = {
|
||||
{OUTPUT_FORMAT_MPEG_4, {CodecMimeType::AUDIO_MPEG, CodecMimeType::AUDIO_AAC,
|
||||
CodecMimeType::VIDEO_AVC, CodecMimeType::VIDEO_MPEG4,
|
||||
CodecMimeType::IMAGE_JPG, CodecMimeType::IMAGE_PNG, CodecMimeType::IMAGE_BMP}},
|
||||
{OUTPUT_FORMAT_M4A, {CodecMimeType::AUDIO_AAC,
|
||||
CodecMimeType::VIDEO_AVC, CodecMimeType::VIDEO_MPEG4,
|
||||
CodecMimeType::IMAGE_JPG, CodecMimeType::IMAGE_PNG, CodecMimeType::IMAGE_BMP}},
|
||||
};
|
||||
|
||||
const std::map<std::string_view, std::set<std::string_view>> MUX_MIME_INFO = {
|
||||
{CodecMimeType::AUDIO_MPEG, {MediaDescriptionKey::MD_KEY_SAMPLE_RATE, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT}},
|
||||
{CodecMimeType::AUDIO_AAC, {MediaDescriptionKey::MD_KEY_SAMPLE_RATE, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT}},
|
||||
{CodecMimeType::VIDEO_AVC, {MediaDescriptionKey::MD_KEY_WIDTH, MediaDescriptionKey::MD_KEY_HEIGHT}},
|
||||
{CodecMimeType::VIDEO_MPEG4, {MediaDescriptionKey::MD_KEY_WIDTH, MediaDescriptionKey::MD_KEY_HEIGHT}},
|
||||
{CodecMimeType::IMAGE_JPG, {MediaDescriptionKey::MD_KEY_WIDTH, MediaDescriptionKey::MD_KEY_HEIGHT}},
|
||||
{CodecMimeType::IMAGE_PNG, {MediaDescriptionKey::MD_KEY_WIDTH, MediaDescriptionKey::MD_KEY_HEIGHT}},
|
||||
{CodecMimeType::IMAGE_BMP, {MediaDescriptionKey::MD_KEY_WIDTH, MediaDescriptionKey::MD_KEY_HEIGHT}},
|
||||
};
|
||||
|
||||
std::shared_ptr<IMuxerEngine> IMuxerEngineFactory::CreateMuxerEngine(int32_t appUid, int32_t appPid, int32_t fd, OutputFormat format)
|
||||
{
|
||||
AVCodecTrace trace("IMuxerEngineFactory::CreateMuxerEngine");
|
||||
CHECK_AND_RETURN_RET_LOG((fcntl(fd, F_GETFL, 0) & O_RDWR) == O_RDWR, nullptr, "no permission to read and write fd");
|
||||
CHECK_AND_RETURN_RET_LOG(lseek(fd, 0, SEEK_CUR) != -1, nullptr, "the fd is not seekable");
|
||||
std::shared_ptr<IMuxerEngine> muxerEngineImpl = std::make_shared<MuxerEngineImpl>(appUid, appPid, fd, format);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngineImpl != nullptr, nullptr, "create MuxerEngine implementation failed");
|
||||
return muxerEngineImpl;
|
||||
}
|
||||
|
||||
MuxerEngineImpl::MuxerEngineImpl(int32_t appUid, int32_t appPid, int32_t fd, OutputFormat format)
|
||||
: appUid_(appUid), appPid_(appPid), fd_(fd), format_(format), que_("muxer_write_queue")
|
||||
{
|
||||
AVCodecTrace trace("MuxerEngine::Create");
|
||||
AVCODEC_LOGI("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
muxer_ = Plugin::MuxerFactory::Instance().CreatePlugin(fd_, format_);
|
||||
if (muxer_ != nullptr && fd_ >= 0) {
|
||||
state_ = INITIALIZED;
|
||||
AVCODEC_LOGI("state_ is INITIALIZED");
|
||||
} else {
|
||||
AVCODEC_LOGE("state_ is UNINITIALIZED");
|
||||
}
|
||||
}
|
||||
|
||||
MuxerEngineImpl::~MuxerEngineImpl()
|
||||
{
|
||||
AVCODEC_LOGD("Destroy");
|
||||
|
||||
if (state_ == STARTED) {
|
||||
que_.SetActive(false);
|
||||
StopThread();
|
||||
}
|
||||
|
||||
appUid_ = -1;
|
||||
appPid_ = -1;
|
||||
muxer_ = nullptr;
|
||||
tracks_.clear();
|
||||
AVCODEC_LOGI("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
AVCodecTrace trace("MuxerEngine::SetLocation");
|
||||
AVCODEC_LOGI("SetLocation");
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(state_ == INITIALIZED, AVCS_ERR_INVALID_OPERATION,
|
||||
"The state is not INITIALIZED, the interface must be called after constructor and before Start(). "
|
||||
"The current state is %{public}s", ConvertStateToString(state_).c_str());
|
||||
if (latitude < MIN_LATITUDE || latitude > MAX_LATITUDE ||
|
||||
longitude < MIN_LONGITUDE || longitude > MAX_LONGITUDE) {
|
||||
AVCODEC_LOGW("Invalid GeoLocation, latitude must be greater than %{public}d and less than %{public}d,"
|
||||
"longitude must be greater than %{public}d and less than %{public}d",
|
||||
MIN_LATITUDE, MAX_LATITUDE, MIN_LONGITUDE, MAX_LONGITUDE);
|
||||
return AVCS_ERR_INVALID_VAL;
|
||||
}
|
||||
|
||||
return TranslatePluginStatus(muxer_->SetLocation(latitude, longitude));
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::SetRotation(int32_t rotation)
|
||||
{
|
||||
AVCodecTrace trace("MuxerEngine::SetRotation");
|
||||
AVCODEC_LOGI("SetRotation");
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(state_ == INITIALIZED, AVCS_ERR_INVALID_OPERATION,
|
||||
"The state is not INITIALIZED, the interface must be called after constructor and before Start(). "
|
||||
"The current state is %{public}s", ConvertStateToString(state_).c_str());
|
||||
if (rotation != VIDEO_ROTATION_0 && rotation != VIDEO_ROTATION_90 &&
|
||||
rotation != VIDEO_ROTATION_180 && rotation != VIDEO_ROTATION_270) {
|
||||
AVCODEC_LOGW("Invalid rotation: %{public}d, keep default 0", rotation);
|
||||
return AVCS_ERR_INVALID_VAL;
|
||||
}
|
||||
|
||||
return TranslatePluginStatus(muxer_->SetRotation(rotation));
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
AVCodecTrace trace("MuxerEngine::AddTrack");
|
||||
AVCODEC_LOGI("AddTrack");
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
trackIndex = ERR_TRACK_INDEX;
|
||||
CHECK_AND_RETURN_RET_LOG(state_ == INITIALIZED, AVCS_ERR_INVALID_OPERATION,
|
||||
"The state is not INITIALIZED, the interface must be called after constructor and before Start(). "
|
||||
"The current state is %{public}s", ConvertStateToString(state_).c_str());
|
||||
std::string mimeType = {};
|
||||
CHECK_AND_RETURN_RET_LOG(trackDesc.GetStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, mimeType),
|
||||
AVCS_ERR_INVALID_VAL, "track format does not contain mime");
|
||||
CHECK_AND_RETURN_RET_LOG(CanAddTrack(mimeType), AVCS_ERR_UNSUPPORT_CONTAINER_TYPE,
|
||||
"track mime is unsupported: %{public}s", mimeType.c_str());
|
||||
CHECK_AND_RETURN_RET_LOG(CheckKeys(mimeType, trackDesc), AVCS_ERR_INVALID_VAL,
|
||||
"track format keys not contained");
|
||||
|
||||
int32_t trackId = -1;
|
||||
Plugin::Status ret = muxer_->AddTrack(trackId, trackDesc);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == Plugin::Status::NO_ERROR, TranslatePluginStatus(ret), "AddTrack failed");
|
||||
CHECK_AND_RETURN_RET_LOG(trackId >= 0, AVCS_ERR_INVALID_OPERATION,
|
||||
"The track index is greater than or equal to 0, less than 99");
|
||||
trackIndex = trackId;
|
||||
tracks_[trackIndex] = mimeType;
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::Start()
|
||||
{
|
||||
AVCodecTrace trace("MuxerEngine::Start");
|
||||
AVCODEC_LOGI("Start");
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(state_ == INITIALIZED, AVCS_ERR_INVALID_OPERATION,
|
||||
"The state is not INITIALIZED, the interface must be called after AddTrack() and before WriteSampleBuffer(). "
|
||||
"The current state is %{public}s", ConvertStateToString(state_).c_str());
|
||||
CHECK_AND_RETURN_RET_LOG(tracks_.size() > 0, AVCS_ERR_INVALID_OPERATION,
|
||||
"The track count is error, count is %{public}d", tracks_.size());
|
||||
Plugin::Status ret = muxer_->Start();
|
||||
CHECK_AND_RETURN_RET_LOG(ret == Plugin::Status::NO_ERROR, TranslatePluginStatus(ret), "Start failed");
|
||||
state_ = STARTED;
|
||||
StartThread("muxer_write_loop");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
AVCodecTrace trace("MuxerEngine::WriteSampleBuffer");
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(state_ == STARTED, AVCS_ERR_INVALID_OPERATION,
|
||||
"The state is not STARTED, the interface must be called after Start() and before Stop(). "
|
||||
"The current state is %{public}s", ConvertStateToString(state_).c_str());
|
||||
CHECK_AND_RETURN_RET_LOG(tracks_.find(info.trackIndex) != tracks_.end(), AVCS_ERR_INVALID_VAL,
|
||||
"The track index does not exist");
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr && info.timeUs >= 0, AVCS_ERR_INVALID_VAL, "Invalid memory");
|
||||
|
||||
std::shared_ptr<BlockBuffer> blockBuffer = std::make_shared<BlockBuffer>();
|
||||
blockBuffer->buffer_ = sampleBuffer;
|
||||
blockBuffer->info_ = info;
|
||||
que_.Push(blockBuffer);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::Stop()
|
||||
{
|
||||
AVCodecTrace trace("MuxerEngine::Stop");
|
||||
AVCODEC_LOGI("Stop");
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(state_ == STARTED, AVCS_ERR_INVALID_OPERATION,
|
||||
"The state is not STARTED. The current state is %{public}s", ConvertStateToString(state_).c_str());
|
||||
state_ = STOPPED;
|
||||
que_.SetActive(false, false);
|
||||
cond_.wait(lock, [this] { return que_.Empty(); });
|
||||
StopThread();
|
||||
return TranslatePluginStatus(muxer_->Stop());
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::DumpInfo(int32_t fd)
|
||||
{
|
||||
std::string dumpString;
|
||||
dumpString += "In MuxerEngine::DumpInfo\n";
|
||||
dumpString += "Current MuxerEngine state is: " + ConvertStateToString(state_) + "\n";
|
||||
dumpString += "Current MuxerEngine output format is: " + std::to_string(format_) + "\n";
|
||||
write(fd, dumpString.c_str(), dumpString.size());
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::StartThread(std::string name)
|
||||
{
|
||||
threadName_ = name;
|
||||
if (thread_ != nullptr) {
|
||||
AVCODEC_LOGW("Started already! [%{public}s]", threadName_.c_str());
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
isThreadExit_ = false;
|
||||
thread_ = std::make_unique<std::thread>(&MuxerEngineImpl::ThreadProcessor, this);
|
||||
AVCodecTrace::TraceBegin("muxer_write_thread", FAKE_POINTER(thread_.get()));
|
||||
AVCODEC_LOGD("thread started! [%{public}s]", threadName_.c_str());
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::StopThread() noexcept
|
||||
{
|
||||
if (isThreadExit_) {
|
||||
AVCODEC_LOGD("Stopped already! [%{public}s]", threadName_.c_str());
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
if (std::this_thread::get_id() == thread_->get_id()) {
|
||||
AVCODEC_LOGD("Stop at the task thread, reject");
|
||||
return AVCS_ERR_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::thread> t;
|
||||
isThreadExit_ = true;
|
||||
cond_.notify_all();
|
||||
std::swap(thread_, t);
|
||||
if (t != nullptr && t->joinable()) {
|
||||
t->join();
|
||||
}
|
||||
thread_ = nullptr;
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
void MuxerEngineImpl::ThreadProcessor()
|
||||
{
|
||||
AVCODEC_LOGD("Enter ThreadProcessor [%{public}s]", threadName_.c_str());
|
||||
constexpr uint32_t nameSizeMax = 15;
|
||||
pthread_setname_np(pthread_self(), threadName_.substr(0, nameSizeMax).c_str());
|
||||
int32_t taskId = FAKE_POINTER(thread_.get());
|
||||
for (;;) {
|
||||
AVCodecTrace trace(threadName_);
|
||||
if (isThreadExit_) {
|
||||
AVCodecTrace::TraceEnd("muxer_write_thread", taskId);
|
||||
AVCODEC_LOGD("Exit ThreadProcessor [%{public}s]", threadName_.c_str());
|
||||
return;
|
||||
}
|
||||
auto buffer = que_.Pop();
|
||||
if (buffer != nullptr) {
|
||||
(void)muxer_->WriteSampleBuffer(buffer->buffer_->GetBase(), buffer->info_);
|
||||
}
|
||||
if (que_.Empty()) {
|
||||
cond_.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MuxerEngineImpl::CanAddTrack(std::string &mimeType)
|
||||
{
|
||||
auto it = MUX_FORMAT_INFO.find(format_);
|
||||
if (it == MUX_FORMAT_INFO.end()) {
|
||||
return false;
|
||||
}
|
||||
return it->second.find(mimeType) != it->second.end();
|
||||
}
|
||||
|
||||
bool MuxerEngineImpl::CheckKeys(std::string &mimeType, const MediaDescription &trackDesc)
|
||||
{
|
||||
bool ret = true;
|
||||
auto it = MUX_MIME_INFO.find(mimeType);
|
||||
if (it == MUX_MIME_INFO.end()) {
|
||||
return ret; // 不做检查
|
||||
}
|
||||
|
||||
for (auto &key : it->second) {
|
||||
if(!trackDesc.ContainKey(key)) {
|
||||
ret = false;
|
||||
AVCODEC_LOGE("the MediaDescriptionKey %{public}s not contained", key.data());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string MuxerEngineImpl::ConvertStateToString(int32_t state)
|
||||
{
|
||||
std::string stateInfo {};
|
||||
switch (state)
|
||||
{
|
||||
case UNINITIALIZED:
|
||||
stateInfo = "UNINITIALIZED";
|
||||
break;
|
||||
case INITIALIZED:
|
||||
stateInfo = "INITIALIZED";
|
||||
break;
|
||||
case STARTED:
|
||||
stateInfo = "STARTED";
|
||||
break;
|
||||
case STOPPED:
|
||||
stateInfo = "STOPPED";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return stateInfo;
|
||||
}
|
||||
|
||||
int32_t MuxerEngineImpl::TranslatePluginStatus(Plugin::Status error)
|
||||
{
|
||||
const static std::map<Plugin::Status, int32_t> g_transTable = {
|
||||
{Plugin::Status::END_OF_STREAM, AVCodecServiceErrCode::AVCS_ERR_OK},
|
||||
{Plugin::Status::OK, AVCodecServiceErrCode::AVCS_ERR_OK},
|
||||
{Plugin::Status::NO_ERROR, AVCodecServiceErrCode::AVCS_ERR_OK},
|
||||
{Plugin::Status::ERROR_UNKNOWN, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_PLUGIN_ALREADY_EXISTS, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_INCOMPATIBLE_VERSION, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_NO_MEMORY, AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY},
|
||||
{Plugin::Status::ERROR_WRONG_STATE, AVCodecServiceErrCode::AVCS_ERR_INVALID_OPERATION},
|
||||
{Plugin::Status::ERROR_UNIMPLEMENTED, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT},
|
||||
{Plugin::Status::ERROR_INVALID_PARAMETER, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
|
||||
{Plugin::Status::ERROR_INVALID_DATA, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
|
||||
{Plugin::Status::ERROR_MISMATCHED_TYPE, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
|
||||
{Plugin::Status::ERROR_TIMED_OUT, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_UNSUPPORTED_FORMAT, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT_CONTAINER_TYPE},
|
||||
{Plugin::Status::ERROR_NOT_ENOUGH_DATA, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_NOT_EXISTED, AVCodecServiceErrCode::AVCS_ERR_OPEN_FILE_FAILED},
|
||||
{Plugin::Status::ERROR_AGAIN, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_PERMISSION_DENIED, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_NULL_POINTER, AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL},
|
||||
{Plugin::Status::ERROR_INVALID_OPERATION, AVCodecServiceErrCode::AVCS_ERR_INVALID_OPERATION},
|
||||
{Plugin::Status::ERROR_CLIENT, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_SERVER, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN},
|
||||
{Plugin::Status::ERROR_DELAY_READY, AVCodecServiceErrCode::AVCS_ERR_OK},
|
||||
};
|
||||
auto ite = g_transTable.find(error);
|
||||
if (ite == g_transTable.end()) {
|
||||
return AVCS_ERR_UNKNOWN;
|
||||
}
|
||||
return ite->second;
|
||||
}
|
||||
} // Media
|
||||
} // OHOS
|
79
services/engine/muxer/muxer_engine_impl.h
Normal file
79
services/engine/muxer/muxer_engine_impl.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 MUXER_ENGINE_IMPL_H
|
||||
#define MUXER_ENGINE_IMPL_H
|
||||
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include "i_muxer_engine.h"
|
||||
#include "muxer.h"
|
||||
#include "block_queue.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class MuxerEngineImpl : public IMuxerEngine {
|
||||
public:
|
||||
MuxerEngineImpl(int32_t appUid, int32_t appPid, int32_t fd, OutputFormat format);
|
||||
~MuxerEngineImpl() override;
|
||||
int32_t SetLocation(float latitude, float longitude) override;
|
||||
int32_t SetRotation(int32_t rotation) override;
|
||||
int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) override;
|
||||
int32_t Start() override;
|
||||
int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) override;
|
||||
int32_t Stop() override;
|
||||
int32_t DumpInfo(int32_t fd) override;
|
||||
|
||||
private:
|
||||
int32_t StartThread(std::string name);
|
||||
int32_t StopThread() noexcept;
|
||||
void ThreadProcessor();
|
||||
bool CanAddTrack(std::string &mimeType);
|
||||
bool CheckKeys(std::string &mimeType, const MediaDescription &trackDesc);
|
||||
std::string ConvertStateToString(int32_t state);
|
||||
int32_t TranslatePluginStatus(Plugin::Status error);
|
||||
|
||||
private:
|
||||
enum State {
|
||||
UNINITIALIZED,
|
||||
INITIALIZED,
|
||||
STARTED,
|
||||
STOPPED
|
||||
};
|
||||
struct BlockBuffer {
|
||||
std::shared_ptr<AVSharedMemory> buffer_;
|
||||
TrackSampleInfo info_;
|
||||
};
|
||||
|
||||
int32_t appUid_ = -1;
|
||||
int32_t appPid_ = -1;
|
||||
int64_t fd_ = -1;
|
||||
OutputFormat format_;
|
||||
std::atomic<State> state_ = UNINITIALIZED;
|
||||
std::shared_ptr<Plugin::Muxer> muxer_ = nullptr;
|
||||
std::map<int32_t, std::string> tracks_;
|
||||
BlockQueue<std::shared_ptr<BlockBuffer>> que_;
|
||||
std::string threadName_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_;
|
||||
std::unique_ptr<std::thread> thread_ = nullptr;
|
||||
bool isThreadExit_ = true;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // MUXER_ENGINE_IMPL_H
|
@ -10,15 +10,35 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("//foundation/multimedia/av_codec/config.gni")
|
||||
config("plugin_presets") {
|
||||
include_dirs = [
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c",
|
||||
"//foundation/multimedia/av_codec/interfaces/inner_api/native",
|
||||
"//foundation/multimedia/av_codec/services/dfx/include",
|
||||
"//foundation/multimedia/av_codec/services/utils/include",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/core",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/interface",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//base/hiviewdfx/hilog/interfaces/native/innerkits/include",
|
||||
]
|
||||
|
||||
group("av_codec_engine_plugins") {
|
||||
deps = []
|
||||
if (multimedia_av_codec_support_demuxer) {
|
||||
deps += [
|
||||
#"plugins/demuxer:av_codec_engine_demuxer",
|
||||
]
|
||||
}
|
||||
cflags = [
|
||||
"-O2",
|
||||
"-fPIC",
|
||||
"-Wall",
|
||||
"-frtti",
|
||||
"-fexceptions",
|
||||
]
|
||||
cflags_cc = cflags
|
||||
}
|
||||
|
||||
group("av_codec_plugin") {
|
||||
deps = [
|
||||
"plugins:av_codec_plugin_store",
|
||||
]
|
||||
}
|
||||
|
||||
|
55
services/engine/plugin/core/muxer.cpp
Normal file
55
services/engine/plugin/core/muxer.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 "muxer.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
Muxer::Muxer (uint32_t pkgVer, uint32_t apiVer, std::shared_ptr<MuxerPlugin> plugin)
|
||||
: pkgVersion_(pkgVer), apiVersion_(apiVer), muxer_(std::move(plugin)) {}
|
||||
|
||||
Status Muxer::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
return muxer_->SetLocation(latitude, longitude);
|
||||
}
|
||||
|
||||
Status Muxer::SetRotation(int32_t rotation)
|
||||
{
|
||||
return muxer_->SetRotation(rotation);
|
||||
}
|
||||
|
||||
Status Muxer::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
return muxer_->AddTrack(trackIndex, trackDesc);
|
||||
}
|
||||
|
||||
Status Muxer::Start()
|
||||
{
|
||||
return muxer_->Start();
|
||||
}
|
||||
|
||||
Status Muxer::WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
return muxer_->WriteSampleBuffer(sampleBuffer, info);
|
||||
}
|
||||
|
||||
Status Muxer::Stop()
|
||||
{
|
||||
return muxer_->Stop();
|
||||
}
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
50
services/engine/plugin/core/muxer.h
Normal file
50
services/engine/plugin/core/muxer.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 PLUGIN_CORE_MUXER_H
|
||||
#define PLUGIN_CORE_MUXER_H
|
||||
|
||||
#include "muxer_plugin.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
class Muxer {
|
||||
public:
|
||||
Muxer(const Muxer &) = delete;
|
||||
Muxer operator=(const Muxer &) = delete;
|
||||
~Muxer() = default;
|
||||
|
||||
Status SetLocation(float latitude, float longitude);
|
||||
Status SetRotation(int32_t rotation);
|
||||
Status AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc);
|
||||
Status Start();
|
||||
Status WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info);
|
||||
Status Stop();
|
||||
|
||||
private:
|
||||
friend class MuxerFactory;
|
||||
|
||||
Muxer(uint32_t pkgVer, uint32_t apiVer, std::shared_ptr<MuxerPlugin> plugin);
|
||||
|
||||
private:
|
||||
const uint32_t pkgVersion_;
|
||||
const uint32_t apiVersion_;
|
||||
std::shared_ptr<MuxerPlugin> muxer_;
|
||||
};
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // PLUGIN_CORE_MUXER_H
|
173
services/engine/plugin/core/muxer_factory.cpp
Normal file
173
services/engine/plugin/core/muxer_factory.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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 "muxer_factory.h"
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <dirent.h>
|
||||
#include "muxer_plugin.h"
|
||||
#include "avcodec_log.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MuxerFactory"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
static std::string g_libFileHead = "libav_codec_plugin_";
|
||||
static std::string g_fileSeparator = "/";
|
||||
static std::string g_fileMark = "Muxer";
|
||||
static std::string g_libFileTail = AV_CODEC_PLUGIN_FILE_TAIL;
|
||||
|
||||
MuxerFactory::MuxerFactory()
|
||||
{
|
||||
RegisterPlugins();
|
||||
}
|
||||
|
||||
MuxerFactory::~MuxerFactory()
|
||||
{
|
||||
UnregisterAllPlugins();
|
||||
}
|
||||
|
||||
std::shared_ptr<Muxer> MuxerFactory::CreatePlugin(int32_t fd, uint32_t outputFormat)
|
||||
{
|
||||
AVCODEC_LOGD("CreatePlugin: fd %{public}d, outputFormat %{public}d", fd, outputFormat);
|
||||
std::string pluginName;
|
||||
int32_t maxProb = 0;
|
||||
for (auto& name : registerData_->registerNames) {
|
||||
std::shared_ptr<PluginRegInfo> regInfo = registerData_->registerTable[name];
|
||||
if (regInfo->pluginDef->pluginType == PluginType::MUXER) {
|
||||
auto prob = regInfo->pluginDef->sniffer(name, outputFormat);
|
||||
if (prob > maxProb) {
|
||||
maxProb = prob;
|
||||
pluginName = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
AVCODEC_LOGD("maxProb %{public}d, pluginName %{public}s", maxProb, pluginName.c_str());
|
||||
if (!pluginName.empty()) {
|
||||
std::shared_ptr<PluginRegInfo> regInfo = registerData_->registerTable[pluginName];
|
||||
auto plugin = regInfo->pluginDef->creator(pluginName, fd);
|
||||
return std::shared_ptr<Muxer>(
|
||||
new Muxer(regInfo->packageDef->pkgVersion, regInfo->pluginDef->apiVersion, plugin));
|
||||
} else {
|
||||
AVCODEC_LOGE("No plugins matching output format - %{public}d", outputFormat);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MuxerFactory::RegisterPlugins()
|
||||
{
|
||||
RegisterDynamicPlugins(AV_CODEC_PLUGIN_PATH);
|
||||
}
|
||||
|
||||
void MuxerFactory::RegisterDynamicPlugins(const char* libDirPath)
|
||||
{
|
||||
DIR* libDir = opendir(libDirPath);
|
||||
if (libDir) {
|
||||
struct dirent* lib = nullptr;
|
||||
std::shared_ptr<PluginLoader> loader = nullptr;
|
||||
while ((lib = readdir(libDir))) {
|
||||
if (lib->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
std::string libName = lib->d_name;
|
||||
AVCODEC_LOGD("libName %{public}s", libName.c_str());
|
||||
if (libName.find(g_libFileHead) ||
|
||||
libName.find(g_fileMark) == std::string::npos ||
|
||||
libName.compare(libName.size() - g_libFileTail.size(), g_libFileTail.size(), g_libFileTail)) {
|
||||
continue;
|
||||
}
|
||||
std::string pluginName =
|
||||
libName.substr(g_libFileHead.size(), libName.size() - g_libFileHead.size() - g_libFileTail.size());
|
||||
std::string libPath = libDirPath + g_fileSeparator + lib->d_name;
|
||||
loader = PluginLoader::Create(pluginName, libPath);
|
||||
if (loader) {
|
||||
loader->FetchRegisterFunction()(std::make_shared<RegisterImpl>(registerData_, loader));
|
||||
registeredLoaders_.push_back(loader);
|
||||
}
|
||||
}
|
||||
closedir(libDir);
|
||||
}
|
||||
}
|
||||
|
||||
void MuxerFactory::UnregisterAllPlugins()
|
||||
{
|
||||
for (auto& loader : registeredLoaders_) {
|
||||
loader->FetchUnregisterFunction()();
|
||||
loader.reset();
|
||||
}
|
||||
registeredLoaders_.clear();
|
||||
registerData_->registerNames.clear();
|
||||
registerData_->registerTable.clear();
|
||||
}
|
||||
|
||||
bool MuxerFactory::RegisterData::IsExist(const std::string& name)
|
||||
{
|
||||
return registerTable.find(name) != registerTable.end();
|
||||
}
|
||||
|
||||
Status MuxerFactory::RegisterImpl::AddPlugin(const PluginDefBase& def)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(Verification(def), Status::ERROR_INVALID_DATA,
|
||||
"The plugin type is not muxer, or plugin rank < 0, or plugin rank > 100");
|
||||
CHECK_AND_RETURN_RET_LOG(VersionMatched(def), Status::ERROR_UNKNOWN,
|
||||
"The plugin version is not matched");
|
||||
CHECK_AND_RETURN_RET_LOG(!registerData->IsExist(def.name),
|
||||
Status::ERROR_PLUGIN_ALREADY_EXISTS, "The plugin already exists");
|
||||
|
||||
auto& pluginDef = (MuxerPluginDef&)(def);
|
||||
std::shared_ptr<PluginRegInfo> regInfo = std::make_shared<PluginRegInfo>();
|
||||
regInfo->packageDef = packageDef;
|
||||
regInfo->pluginDef = std::make_shared<MuxerPluginDef>(pluginDef);
|
||||
regInfo->loader = std::move(pluginLoader);
|
||||
|
||||
registerData->registerTable[pluginDef.name] = regInfo;
|
||||
registerData->registerNames.push_back(pluginDef.name);
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
Status MuxerFactory::RegisterImpl::AddPackage(const PackageDef& def)
|
||||
{
|
||||
return SetPackageDef(def);
|
||||
}
|
||||
|
||||
Status MuxerFactory::RegisterImpl::SetPackageDef(const PackageDef& def)
|
||||
{
|
||||
packageDef = std::make_shared<PackageDef>(def);
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
bool MuxerFactory::RegisterImpl::Verification(const PluginDefBase& def)
|
||||
{
|
||||
if (def.rank < 0 || def.rank > 100) { // 100
|
||||
return false;
|
||||
}
|
||||
return (def.pluginType == PluginType::MUXER);
|
||||
}
|
||||
|
||||
bool MuxerFactory::RegisterImpl::VersionMatched(const PluginDefBase& def)
|
||||
{
|
||||
int major = (def.apiVersion >> 16) & 0xFFFF; // 16
|
||||
int minor = def.apiVersion & 0xFFFF;
|
||||
uint32_t version = MUXER_API_VERSION;
|
||||
int coreMajor = (version >> 16) & 0xFFFF; // 16
|
||||
int coreMinor = version & 0xFFFF;
|
||||
return (major == coreMajor) && (minor <= coreMinor);
|
||||
}
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
81
services/engine/plugin/core/muxer_factory.h
Normal file
81
services/engine/plugin/core/muxer_factory.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 MUXER_FACTORY_H
|
||||
#define MUXER_FACTORY_H
|
||||
|
||||
#include "muxer.h"
|
||||
#include "plugin_loader.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
class MuxerFactory {
|
||||
public:
|
||||
MuxerFactory(const MuxerFactory&) = delete;
|
||||
MuxerFactory operator=(const MuxerFactory&) = delete;
|
||||
~MuxerFactory();
|
||||
static MuxerFactory& Instance()
|
||||
{
|
||||
static MuxerFactory impl;
|
||||
return impl;
|
||||
}
|
||||
|
||||
std::shared_ptr<Muxer> CreatePlugin(int32_t fd, uint32_t outputFormat);
|
||||
|
||||
private:
|
||||
MuxerFactory();
|
||||
|
||||
void RegisterPlugins();
|
||||
void RegisterDynamicPlugins(const char* libDirPath);
|
||||
void UnregisterAllPlugins();
|
||||
|
||||
private:
|
||||
struct PluginRegInfo {
|
||||
std::shared_ptr<PackageDef> packageDef;
|
||||
std::shared_ptr<MuxerPluginDef> pluginDef;
|
||||
std::shared_ptr<PluginLoader> loader;
|
||||
};
|
||||
struct RegisterData {
|
||||
std::vector<std::string> registerNames;
|
||||
std::map<std::string, std::shared_ptr<PluginRegInfo>> registerTable;
|
||||
bool IsExist(const std::string& name);
|
||||
};
|
||||
struct RegisterImpl : PackageRegister {
|
||||
explicit RegisterImpl(std::shared_ptr<RegisterData> data, std::shared_ptr<PluginLoader> loader = nullptr)
|
||||
: pluginLoader(std::move(loader)), registerData(std::move(data)) {}
|
||||
|
||||
~RegisterImpl() override = default;
|
||||
|
||||
Status AddPlugin(const PluginDefBase& def) override;
|
||||
Status AddPackage(const PackageDef& def) override;
|
||||
Status SetPackageDef(const PackageDef& def);
|
||||
bool Verification(const PluginDefBase& def);
|
||||
bool VersionMatched(const PluginDefBase& def);
|
||||
|
||||
std::shared_ptr<PluginLoader> pluginLoader;
|
||||
std::shared_ptr<RegisterData> registerData;
|
||||
std::shared_ptr<PackageDef> packageDef {nullptr};
|
||||
};
|
||||
|
||||
std::shared_ptr<RegisterData> registerData_ = std::make_shared<RegisterData>();
|
||||
std::vector<std::shared_ptr<PluginLoader>> registeredLoaders_;
|
||||
};
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // MUXER_FACTORY_H
|
93
services/engine/plugin/core/plugin_loader.cpp
Normal file
93
services/engine/plugin/core/plugin_loader.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 "plugin_loader.h"
|
||||
#include <dlfcn.h>
|
||||
#include "avcodec_log.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PluginLoader"};
|
||||
}
|
||||
|
||||
using namespace OHOS::Media::Plugin;
|
||||
|
||||
// NOLINTNEXTLINE: void*
|
||||
PluginLoader::PluginLoader(void* handler, std::string name) : handler_(handler), name_(std::move(name))
|
||||
{
|
||||
}
|
||||
|
||||
PluginLoader::~PluginLoader()
|
||||
{
|
||||
UnLoadPluginFile();
|
||||
}
|
||||
|
||||
std::shared_ptr<PluginLoader> PluginLoader::Create(const std::string& name, const std::string& path)
|
||||
{
|
||||
if (name.empty() || path.empty()) {
|
||||
return {};
|
||||
}
|
||||
return CheckSymbol(LoadPluginFile(path), name);
|
||||
}
|
||||
|
||||
RegisterFunc PluginLoader::FetchRegisterFunction()
|
||||
{
|
||||
return registerFunc_;
|
||||
}
|
||||
|
||||
UnregisterFunc PluginLoader::FetchUnregisterFunction()
|
||||
{
|
||||
return unregisterFunc_;
|
||||
}
|
||||
|
||||
void* PluginLoader::LoadPluginFile(const std::string& path)
|
||||
{
|
||||
auto pathStr = path.c_str();
|
||||
if (pathStr) {
|
||||
auto ptr = ::dlopen(pathStr, RTLD_NOW | RTLD_LOCAL);
|
||||
if (ptr == nullptr) {
|
||||
AVCODEC_LOGE("dlopen failed due to %{public}s", ::dlerror());
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<PluginLoader> PluginLoader::CheckSymbol(void* handler, const std::string& name)
|
||||
{
|
||||
if (handler) {
|
||||
std::string registerFuncName = "register_" + name;
|
||||
std::string unregisterFuncName = "unregister_" + name;
|
||||
RegisterFunc registerFunc = nullptr;
|
||||
UnregisterFunc unregisterFunc = nullptr;
|
||||
AVCODEC_LOGD("CheckSymbol: registerFuncName %{public}s", registerFuncName.c_str());
|
||||
AVCODEC_LOGD("CheckSymbol: unregisterFuncName %{public}s", unregisterFuncName.c_str());
|
||||
registerFunc = (RegisterFunc)(::dlsym(handler, registerFuncName.c_str()));
|
||||
unregisterFunc = (UnregisterFunc)(::dlsym(handler, unregisterFuncName.c_str()));
|
||||
if (registerFunc && unregisterFunc) {
|
||||
std::shared_ptr<PluginLoader> loader(new PluginLoader(handler, name));
|
||||
loader->registerFunc_ = registerFunc;
|
||||
loader->unregisterFunc_ = unregisterFunc;
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void PluginLoader::UnLoadPluginFile()
|
||||
{
|
||||
if (handler_) {
|
||||
::dlclose(const_cast<void*>(handler_)); // NOLINT: const_cast
|
||||
}
|
||||
}
|
57
services/engine/plugin/core/plugin_loader.h
Normal file
57
services/engine/plugin/core/plugin_loader.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 PLUGIN_CORE_PLUGIN_LOADER_H
|
||||
#define PLUGIN_CORE_PLUGIN_LOADER_H
|
||||
|
||||
#include "plugin_base.h"
|
||||
#include "plugin_definition.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
class PluginLoader {
|
||||
public:
|
||||
PluginLoader(const PluginLoader &) = delete;
|
||||
|
||||
PluginLoader operator=(const PluginLoader &) = delete;
|
||||
|
||||
~PluginLoader();
|
||||
|
||||
static std::shared_ptr<PluginLoader> Create(const std::string &name, const std::string &path);
|
||||
|
||||
RegisterFunc FetchRegisterFunction();
|
||||
|
||||
UnregisterFunc FetchUnregisterFunction();
|
||||
|
||||
private:
|
||||
PluginLoader(void* handler, std::string name); // NOLINT: void*
|
||||
|
||||
static void* LoadPluginFile(const std::string &path);
|
||||
|
||||
static std::shared_ptr<PluginLoader> CheckSymbol(void* handler, const std::string &name); // NOLINT: void*
|
||||
|
||||
void UnLoadPluginFile();
|
||||
|
||||
private:
|
||||
const void *handler_;
|
||||
const std::string name_;
|
||||
RegisterFunc registerFunc_ {nullptr};
|
||||
UnregisterFunc unregisterFunc_ {nullptr};
|
||||
};
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // PLUGIN_CORE_PLUGIN_LOADER_H
|
64
services/engine/plugin/interface/muxer_plugin.h
Normal file
64
services/engine/plugin/interface/muxer_plugin.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 PLUGIN_INTF_MUXER_PLUGIN_H
|
||||
#define PLUGIN_INTF_MUXER_PLUGIN_H
|
||||
|
||||
#include "media_description.h"
|
||||
#include "av_common.h"
|
||||
#include "plugin_base.h"
|
||||
#include "plugin_definition.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
|
||||
struct MuxerPlugin : public PluginBase {
|
||||
explicit MuxerPlugin(std::string &&name) : PluginBase(std::move(name)) {}
|
||||
virtual Status SetLocation(float latitude, float longitude) = 0;
|
||||
virtual Status SetRotation(int32_t rotation) = 0;
|
||||
virtual Status AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) = 0;
|
||||
virtual Status Start() = 0;
|
||||
virtual Status WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info) = 0;
|
||||
virtual Status Stop() = 0;
|
||||
};
|
||||
|
||||
/// Muxer plugin api major number.
|
||||
#define MUXER_API_VERSION_MAJOR (1)
|
||||
|
||||
/// Muxer plugin api minor number
|
||||
#define MUXER_API_VERSION_MINOR (0)
|
||||
|
||||
/// Muxer plugin version
|
||||
#define MUXER_API_VERSION MAKE_VERSION(MUXER_API_VERSION_MAJOR, MUXER_API_VERSION_MINOR)
|
||||
|
||||
/// Muxer create function
|
||||
using MuxerPluginCreatorFunc = std::shared_ptr<MuxerPlugin>(*)(const std::string& name, int32_t fd);
|
||||
/// Muxer sniff function
|
||||
using MuxerPluginSnifferFunc = int32_t (*)(const std::string& name, uint32_t outputFormat);
|
||||
|
||||
struct MuxerPluginDef : public PluginDefBase {
|
||||
MuxerPluginCreatorFunc creator {nullptr}; ///< Muxer plugin create function.
|
||||
MuxerPluginSnifferFunc sniffer {nullptr}; ///< Muxer plugin sniff function.
|
||||
MuxerPluginDef()
|
||||
{
|
||||
apiVersion = MUXER_API_VERSION; ///< Muxer plugin version.
|
||||
pluginType = PluginType::MUXER; ///< Plugin type, MUST be MUXER.
|
||||
}
|
||||
};
|
||||
} // Plugin
|
||||
} // Media
|
||||
} // OHOS
|
||||
#endif // PLUGIN_INTF_MUXER_PLUGIN_H
|
59
services/engine/plugin/interface/plugin_base.h
Normal file
59
services/engine/plugin/interface/plugin_base.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 PLUGIN_INTF_PLUGIN_BASE_H
|
||||
#define PLUGIN_INTF_PLUGIN_BASE_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
/**
|
||||
* @brief Base class of a plugin. All plugins of different types inherit this interface.
|
||||
*
|
||||
* @details The base class contains only common operation methods and defines basic operation processes.
|
||||
* Different operations are valid only in the corresponding states. The timing of calls is guaranteed by
|
||||
* the plugin framework. Some operations also change the plugin status.
|
||||
* For details, see the description of each function.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
struct PluginBase {
|
||||
/// Constructor
|
||||
explicit PluginBase(std::string name): pluginName_(std::move(name)) {}
|
||||
|
||||
/// Destructor
|
||||
virtual ~PluginBase() = default;
|
||||
|
||||
/**
|
||||
* @brief Get plugin name
|
||||
*
|
||||
* @return plugin name
|
||||
*/
|
||||
std::string GetName() const
|
||||
{
|
||||
return pluginName_;
|
||||
}
|
||||
|
||||
protected:
|
||||
const std::string pluginName_;
|
||||
};
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // PLUGIN_INTF_PLUGIN_BASE_H
|
246
services/engine/plugin/interface/plugin_definition.h
Normal file
246
services/engine/plugin/interface/plugin_definition.h
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.
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_INTF_PLUGIN_DEFINITION_H
|
||||
#define PLUGIN_INTF_PLUGIN_DEFINITION_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cstdint> // NOLINT: using int32_t in this file
|
||||
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
/**
|
||||
* @brief Macro definition, creating the version information.
|
||||
*
|
||||
* @details The versioning is the process of assigning a unique version number to a unique state
|
||||
* of plugin interface. Within a given version number category (major, minor), these numbers are
|
||||
* usually assigned in ascending order and correspond to new developments in the plugin.
|
||||
*
|
||||
* Given a version number MAJOR.MINOR:
|
||||
* - MAJOR: When you make incompatible API changes.
|
||||
* - MINOR: When you add features in a backwards-compatible manner or do backwards-compatible bug fixes.
|
||||
*/
|
||||
#define MAKE_VERSION(MAJOR, MINOR) ((((MAJOR)&0xFFFF) << 16) | ((MINOR)&0xFFFF))
|
||||
|
||||
/// Plugin interface major number
|
||||
#define PLUGIN_INTERFACE_VERSION_MAJOR (1)
|
||||
|
||||
/// Plugin interface minor number
|
||||
#define PLUGIN_INTERFACE_VERSION_MINOR (0)
|
||||
|
||||
/// Plugin interface version
|
||||
#define PLUGIN_INTERFACE_VERSION MAKE_VERSION(PLUGIN_INTERFACE_VERSION_MAJOR, PLUGIN_INTERFACE_VERSION_MINOR)
|
||||
|
||||
/**
|
||||
* @enum License Type.
|
||||
* an official permission or permit.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
enum struct LicenseType : uint8_t {
|
||||
APACHE_V2, ///< The Apache License 2.0
|
||||
LGPL, ///< The GNU Lesser General Public License
|
||||
GPL, ///< The GNU General Public License
|
||||
CC0, ///< The Creative Commons Zero v1.0 Universal
|
||||
UNKNOWN, ///< Unknown License
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Definition of plugin packaging information.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
struct PackageDef {
|
||||
uint32_t pkgVersion; ///< Package information version, which indicates the latest plug-in interface version
|
||||
///< used by the plugin in the package. The default value is PLUGIN_INTERFACE_VERSION.
|
||||
|
||||
std::string name; ///< Package name. The plugin framework registers the plugin using this name.
|
||||
///< If the plugins are packaged as a dynamic library, the name of library
|
||||
///< must be in the format of "libplugin_<name>.so".
|
||||
|
||||
LicenseType
|
||||
licenseType; ///< The License information of the plugin in the package.
|
||||
///< The different plugins must be the same.
|
||||
///< The plugin framework processing in the plugin running state based on different license.
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum Plugin Return Status.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
enum struct Status : int32_t {
|
||||
END_OF_STREAM = 1, ///< Read source when end of stream
|
||||
OK = 0, ///< The execution result is correct.
|
||||
NO_ERROR = OK, ///< Same as Status::OK
|
||||
ERROR_UNKNOWN = -1, ///< An unknown error occurred.
|
||||
ERROR_PLUGIN_ALREADY_EXISTS = -2, ///< The plugin already exists, usually occurs when in plugin registered.
|
||||
ERROR_INCOMPATIBLE_VERSION = -3, ///< Incompatible version, may occur during plugin registration or function calling.
|
||||
ERROR_NO_MEMORY = -4, ///< The system memory is insufficient.
|
||||
ERROR_WRONG_STATE = -5, ///< The function is called in an invalid state.
|
||||
ERROR_UNIMPLEMENTED = -6, ///< This method or interface is not implemented.
|
||||
ERROR_INVALID_PARAMETER = -7, ///< The plugin does not support this parameter.
|
||||
ERROR_INVALID_DATA = -8, ///< The value is not in the valid range.
|
||||
ERROR_MISMATCHED_TYPE = -9, ///< Mismatched data type
|
||||
ERROR_TIMED_OUT = -10, ///< Operation timeout.
|
||||
ERROR_UNSUPPORTED_FORMAT = -11, ///< The plugin not support this format/name.
|
||||
ERROR_NOT_ENOUGH_DATA = -12, ///< Not enough data when read from source.
|
||||
ERROR_NOT_EXISTED = -13, ///< Source is not existed.
|
||||
ERROR_AGAIN = -14, ///< Operation is not available right now, should try again later.
|
||||
ERROR_PERMISSION_DENIED = -15, ///< Permission denied.
|
||||
ERROR_NULL_POINTER = -16, ///< Null pointer.
|
||||
ERROR_INVALID_OPERATION = -17, ///< Invalid operation.
|
||||
ERROR_CLIENT = -18, ///< Http client error
|
||||
ERROR_SERVER = -19, ///< Http server error
|
||||
ERROR_DELAY_READY = -20, ///< Delay ready event
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum Plugin Type.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
enum struct PluginType : int32_t {
|
||||
INVALID_TYPE = -1, ///< Invalid plugin
|
||||
MUXER = 1, ///< reference MuxerPlugin
|
||||
DEMUXER, ///< reference DemuxerPlugin
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Describes the basic information about the plugin.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
struct PluginDefBase {
|
||||
uint32_t apiVersion; ///< Versions of different plugins. Different types of plugin have their own versions.
|
||||
|
||||
PluginType pluginType = PluginType::INVALID_TYPE; ///< Describe the plugin type, e.g. 'source', 'codec'.
|
||||
|
||||
std::string name; ///< Indicates the name of a plugin. The name of the same type plugins must be unique.
|
||||
///< Plugins with the same name may fail to be registered.
|
||||
|
||||
std::string description; ///< Detailed description of the plugin.
|
||||
|
||||
uint32_t rank; ///< Plugin score. The plugin with a high score may be preferred. You can evaluate the
|
||||
///< plugin score in terms of performance, version support, and license. Range: 0 to 100.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The plugin registration interface.
|
||||
* The plugin framework will provide the implementation.
|
||||
* Developers only need to invoke the API to register the plugin.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
struct Register {
|
||||
virtual ~Register() = default;
|
||||
/**
|
||||
* @brief Register the plugin.
|
||||
*
|
||||
* @param def Basic information about the plugin
|
||||
* @return Registration status return
|
||||
* @retval OK: The plugin is registered succeed.
|
||||
* @retval ERROR_PLUGIN_ALREADY_EXISTS: The plugin already exists in plugin registered.
|
||||
* @retval ERROR_INCOMPATIBLE_VERSION: Incompatible version during plugin registration.
|
||||
*/
|
||||
virtual Status AddPlugin(const PluginDefBase& def) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The package registration interface.
|
||||
* The plugin framework will provide the implementation and auto invoke the API to
|
||||
* finish the package registration when plugin framework first time be initialized.
|
||||
*
|
||||
* @since 10
|
||||
* @version 1.0
|
||||
*/
|
||||
struct PackageRegister : Register {
|
||||
~PackageRegister() override = default;
|
||||
|
||||
/**
|
||||
* @brief Register the package.
|
||||
* During package registration, all plugins in the package are automatically registered.
|
||||
*
|
||||
* @param def plugin packaging information.
|
||||
* @return Registration status return
|
||||
* @retval OK: The package is registered succeed without any errors.
|
||||
* @retval ERROR_PLUGIN_ALREADY_EXISTS: The package or plugins already exists.
|
||||
* @retval ERROR_INCOMPATIBLE_VERSION: Incompatible plugin interface version or api version.
|
||||
*/
|
||||
virtual Status AddPackage(const PackageDef& def) = 0;
|
||||
};
|
||||
|
||||
/// Plugin registration function, all plugins must be implemented.
|
||||
using RegisterFunc = Status (*)(std::shared_ptr<Register> reg);
|
||||
|
||||
/// Plugin deregister function, all plugins must be implemented.
|
||||
using UnregisterFunc = void (*)();
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
#define PLUGIN_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
|
||||
#define PLUGIN_EXPORT extern "C" __attribute__((visibility("default")))
|
||||
#else
|
||||
#define PLUGIN_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Macro definition, string concatenation
|
||||
#define PLUGIN_PASTE_ARGS(str1, str2) str1##str2
|
||||
|
||||
/// Macro definition, string concatenation
|
||||
#define PLUGIN_PASTE(str1, str2) PLUGIN_PASTE_ARGS(str1, str2)
|
||||
|
||||
/// Macro definition, stringify
|
||||
#define PLUGIN_STRINGIFY_ARG(str) #str
|
||||
|
||||
/// Macro definition, stringify
|
||||
#define PLUGIN_STRINGIFY(str) PLUGIN_STRINGIFY_ARG(str)
|
||||
|
||||
/**
|
||||
* @brief Macro definition, Defines basic plugin information.
|
||||
* Which is invoked during plugin package registration. All plugin packages must be implemented.
|
||||
*
|
||||
* @param name Package name. For details, @see PackageDef::name
|
||||
* @param license Package License, For details, @see PackageDef::licenseType
|
||||
* @param registerFunc Plugin registration function, MUST NOT be NULL.
|
||||
* @param unregisterFunc Plugin deregister function,MUST NOT be NULL.
|
||||
*/
|
||||
#define PLUGIN_DEFINITION(name, license, registerFunc, unregisterFunc) \
|
||||
PLUGIN_EXPORT OHOS::Media::Plugin::Status PLUGIN_PASTE(register_, name)( \
|
||||
const std::shared_ptr<OHOS::Media::Plugin::PackageRegister>& pkgReg) \
|
||||
{ \
|
||||
pkgReg->AddPackage({PLUGIN_INTERFACE_VERSION, PLUGIN_STRINGIFY(name), license}); \
|
||||
std::shared_ptr<OHOS::Media::Plugin::Register> pluginReg = pkgReg; \
|
||||
return registerFunc(pluginReg); \
|
||||
} \
|
||||
PLUGIN_EXPORT void PLUGIN_PASTE(unregister_, name)() \
|
||||
{ \
|
||||
unregisterFunc(); \
|
||||
}
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // PLUGIN_INTF_PLUGIN_DEFINITION_H
|
19
services/engine/plugin/plugins/BUILD.gn
Normal file
19
services/engine/plugin/plugins/BUILD.gn
Normal file
@ -0,0 +1,19 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
import("//foundation/multimedia/av_codec/config.gni")
|
||||
group("av_codec_plugin_store") {
|
||||
deps = []
|
||||
deps += [ "muxer/ffmpeg_muxer:plugin_muxer_ffmpeg" ]
|
||||
}
|
47
services/engine/plugin/plugins/muxer/ffmpeg_muxer/BUILD.gn
Normal file
47
services/engine/plugin/plugins/muxer/ffmpeg_muxer/BUILD.gn
Normal file
@ -0,0 +1,47 @@
|
||||
# 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.
|
||||
#
|
||||
import("//foundation/multimedia/av_codec/config.gni")
|
||||
|
||||
group("plugin_muxer_ffmpeg") {
|
||||
deps = []
|
||||
deps += [ ":av_codec_plugin_FFmpegMuxer" ]
|
||||
}
|
||||
|
||||
# standard
|
||||
import("//build/ohos.gni")
|
||||
ohos_shared_library("av_codec_plugin_FFmpegMuxer") {
|
||||
sources = [
|
||||
"ffmpeg_muxer_plugin.cpp",
|
||||
"ffmpeg_utils.cpp",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"//third_party/ffmpeg",
|
||||
]
|
||||
|
||||
public_configs = [
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin:plugin_presets",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
"//third_party/bounds_checking_function:libsec_static",
|
||||
"//foundation/multimedia/av_codec/services/utils:av_codec_format",
|
||||
"//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog",
|
||||
"//third_party/ffmpeg:libohosffmpeg",
|
||||
]
|
||||
|
||||
relative_install_dir = "media/av_codec_plugins"
|
||||
subsystem_name = "multimedia"
|
||||
part_name = "multimedia_av_codec"
|
||||
}
|
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* 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 "ffmpeg_muxer_plugin.h"
|
||||
#include <functional>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "securec.h"
|
||||
#include "ffmpeg_utils.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "avcodec_common.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "FfmpegMuxerPlugin"};
|
||||
}
|
||||
|
||||
namespace {
|
||||
using namespace OHOS::Media;
|
||||
using namespace Plugin;
|
||||
using namespace Ffmpeg;
|
||||
|
||||
std::map<std::string, std::shared_ptr<AVOutputFormat>> g_pluginOutputFmt;
|
||||
|
||||
std::map<std::string, uint32_t> g_supportedMuxer = {{"mp4", OUTPUT_FORMAT_MPEG_4}, {"ipod", OUTPUT_FORMAT_M4A}};
|
||||
|
||||
bool IsMuxerSupported(const char *name)
|
||||
{
|
||||
auto it = g_supportedMuxer.find(name);
|
||||
if (it != g_supportedMuxer.end()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t Sniff(const std::string& pluginName, uint32_t outputFormat)
|
||||
{
|
||||
if (pluginName.empty()) {
|
||||
return 0;
|
||||
}
|
||||
auto plugin = g_pluginOutputFmt[pluginName];
|
||||
int32_t confidence = 0;
|
||||
auto it = g_supportedMuxer.find(plugin->name);
|
||||
if (it != g_supportedMuxer.end() && it->second == outputFormat) {
|
||||
confidence = 60;
|
||||
}
|
||||
|
||||
return confidence;
|
||||
}
|
||||
|
||||
Status RegisterMuxerPlugins(const std::shared_ptr<Register>& reg)
|
||||
{
|
||||
const AVOutputFormat *outputFormat = nullptr;
|
||||
void *ite = nullptr;
|
||||
while ((outputFormat = av_muxer_iterate(&ite))) {
|
||||
if (!IsMuxerSupported(outputFormat->name)) {
|
||||
continue;
|
||||
}
|
||||
if (outputFormat->long_name != nullptr) {
|
||||
if (!strncmp(outputFormat->long_name, "raw ", 4)) { // 4
|
||||
continue;
|
||||
}
|
||||
}
|
||||
std::string pluginName = "ffmpegMux_" + std::string(outputFormat->name);
|
||||
ReplaceDelimiter(".,|-<> ", '_', pluginName);
|
||||
MuxerPluginDef def;
|
||||
def.name = pluginName;
|
||||
def.description = "ffmpeg muxer";
|
||||
def.rank = 100; // 100
|
||||
def.creator = [](const std::string& name, int32_t fd) -> std::shared_ptr<MuxerPlugin> {
|
||||
return std::make_shared<FFmpegMuxerPlugin>(name, fd);
|
||||
};
|
||||
def.sniffer = Sniff;
|
||||
if (reg->AddPlugin(def) != Status::NO_ERROR) {
|
||||
continue;
|
||||
}
|
||||
g_pluginOutputFmt[pluginName] = std::shared_ptr<AVOutputFormat>(
|
||||
const_cast<AVOutputFormat*>(outputFormat), [](AVOutputFormat *ptr) {}); // do not delete
|
||||
}
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
PLUGIN_DEFINITION(FFmpegMuxer, LicenseType::LGPL, RegisterMuxerPlugins, [] {g_pluginOutputFmt.clear();})
|
||||
|
||||
void ResetCodecParameter(AVCodecParameters *par)
|
||||
{
|
||||
av_freep(&par->extradata);
|
||||
(void)memset_s(par, sizeof(*par), 0, sizeof(*par));
|
||||
par->codec_type = AVMEDIA_TYPE_UNKNOWN;
|
||||
par->codec_id = AV_CODEC_ID_NONE;
|
||||
par->format = -1;
|
||||
par->profile = FF_PROFILE_UNKNOWN;
|
||||
par->level = FF_LEVEL_UNKNOWN;
|
||||
par->field_order = AV_FIELD_UNKNOWN;
|
||||
par->color_range = AVCOL_RANGE_UNSPECIFIED;
|
||||
par->color_primaries = AVCOL_PRI_UNSPECIFIED;
|
||||
par->color_trc = AVCOL_TRC_UNSPECIFIED;
|
||||
par->color_space = AVCOL_SPC_UNSPECIFIED;
|
||||
par->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
|
||||
par->sample_aspect_ratio = AVRational {0, 1};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
namespace Ffmpeg {
|
||||
FFmpegMuxerPlugin::FFmpegMuxerPlugin(std::string name, int32_t fd) : MuxerPlugin(std::move(name)), fd_(dup(fd))
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
if ((fcntl(fd_, F_GETFL, 0) & O_RDWR) != O_RDWR) {
|
||||
AVCODEC_LOGE("No permission to read and write fd");
|
||||
}
|
||||
if (lseek(fd_, 0, SEEK_SET) < 0) {
|
||||
AVCODEC_LOGE("The fd is not seekable");
|
||||
}
|
||||
auto pkt = av_packet_alloc();
|
||||
cachePacket_ = std::shared_ptr<AVPacket> (pkt, [] (AVPacket *packet) {av_packet_free(&packet);});
|
||||
outputFormat_ = g_pluginOutputFmt[pluginName_];
|
||||
auto fmt = avformat_alloc_context();
|
||||
fmt->pb = InitAvIoCtx(fd_, 1);
|
||||
fmt->oformat = outputFormat_.get();
|
||||
fmt->flags = static_cast<uint32_t>(fmt->flags) | static_cast<uint32_t>(AVFMT_FLAG_CUSTOM_IO);
|
||||
fmt->io_open = IoOpen;
|
||||
fmt->io_close = IoClose;
|
||||
formatContext_ = std::shared_ptr<AVFormatContext>(fmt, [](AVFormatContext *ptr) {
|
||||
if (ptr) {
|
||||
DeInitAvIoCtx(ptr->pb);
|
||||
avformat_free_context(ptr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
FFmpegMuxerPlugin::~FFmpegMuxerPlugin()
|
||||
{
|
||||
AVCODEC_LOGD("Destory");
|
||||
outputFormat_.reset();
|
||||
cachePacket_.reset();
|
||||
formatContext_.reset();
|
||||
CloseFd();
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
Status FFmpegMuxerPlugin::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
std::string location = std::to_string(longitude) + " ";
|
||||
location += std::to_string(latitude) + " ";
|
||||
location += std::to_string(0.0f);
|
||||
av_dict_set(&formatContext_.get()->metadata, "location", location.c_str(), 0);
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
Status FFmpegMuxerPlugin::SetRotation(int32_t rotation)
|
||||
{
|
||||
rotation_ = rotation;
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
Status FFmpegMuxerPlugin::SetCodecParameterOfTrack(AVStream *stream, const MediaDescription &trackDesc)
|
||||
{
|
||||
bool ret = false;
|
||||
uint8_t *extraData = nullptr;
|
||||
size_t extraDataSize = 0;
|
||||
std::string mimeType = {};
|
||||
AVCodecID codeID = AV_CODEC_ID_NONE;
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(trackDesc.GetStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, mimeType),
|
||||
Status::ERROR_MISMATCHED_TYPE, "get mimeType failed!"); // mime
|
||||
AVCODEC_LOGD("mimeType is %{public}s", mimeType.c_str());
|
||||
CHECK_AND_RETURN_RET_LOG(Mime2CodecId(mimeType, codeID), Status::ERROR_INVALID_DATA,
|
||||
"this mimeType do not support! mimeType:%{public}s", mimeType.c_str());
|
||||
|
||||
AVCodecParameters *par = stream->codecpar;
|
||||
par->codec_id = codeID;
|
||||
if (!mimeType.compare(0, 5, "audio")) {
|
||||
par->codec_type = AVMEDIA_TYPE_AUDIO; // type
|
||||
ret = trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, par->sample_rate); // sample rate
|
||||
CHECK_AND_RETURN_RET_LOG(ret, Status::ERROR_MISMATCHED_TYPE, "get audio sample_rate failed!");
|
||||
ret = trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, par->channels); // channels
|
||||
CHECK_AND_RETURN_RET_LOG(ret, Status::ERROR_MISMATCHED_TYPE, "get audio channels failed!");
|
||||
} else if(!mimeType.compare(0, 5, "video") || !mimeType.compare(0, 5, "image")) {
|
||||
if (!mimeType.compare(0, 5, "image")) { // pic
|
||||
stream->disposition = AV_DISPOSITION_ATTACHED_PIC;
|
||||
}
|
||||
par->codec_type = AVMEDIA_TYPE_VIDEO; // type
|
||||
ret = trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, par->width); // width
|
||||
CHECK_AND_RETURN_RET_LOG(ret, Status::ERROR_MISMATCHED_TYPE, "get video width failed!");
|
||||
ret = trackDesc.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, par->height); // height
|
||||
CHECK_AND_RETURN_RET_LOG(ret, Status::ERROR_MISMATCHED_TYPE, "get video height failed!");
|
||||
} else{
|
||||
AVCODEC_LOGD("mimeType %{public}s is unsupported", mimeType.c_str());
|
||||
}
|
||||
|
||||
trackDesc.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, par->bit_rate); // bit rate
|
||||
if (trackDesc.GetBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, &extraData, extraDataSize)) { // codec config
|
||||
par->extradata = static_cast<uint8_t *>(av_mallocz(extraDataSize + AV_INPUT_BUFFER_PADDING_SIZE));
|
||||
CHECK_AND_RETURN_RET_LOG(par->extradata != nullptr, Status::ERROR_NO_MEMORY, "codec config malloc failed!");
|
||||
par->extradata_size = static_cast<int32_t>(extraDataSize);
|
||||
errno_t rc = memcpy_s(par->extradata, par->extradata_size, extraData, extraDataSize);
|
||||
CHECK_AND_RETURN_RET_LOG(rc == EOK, Status::ERROR_UNKNOWN, "memcpy_s failed");
|
||||
}
|
||||
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
Status FFmpegMuxerPlugin::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(outputFormat_ != nullptr, Status::ERROR_NULL_POINTER, "AVOutputFormat is nullptr");
|
||||
auto st = avformat_new_stream(formatContext_.get(), nullptr);
|
||||
CHECK_AND_RETURN_RET_LOG(st != nullptr, Status::ERROR_NO_MEMORY, "avformat_new_stream failed!");
|
||||
st->codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN;
|
||||
st->codecpar->codec_id = AV_CODEC_ID_NONE;
|
||||
trackIndex = st->index;
|
||||
|
||||
// 设置track参数
|
||||
ResetCodecParameter(st->codecpar);
|
||||
Status ret = SetCodecParameterOfTrack(st, trackDesc);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == Status::NO_ERROR, ret, "SetCodecParameter failed!");
|
||||
formatContext_->flags |= AVFMT_TS_NONSTRICT;
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
Status FFmpegMuxerPlugin::Start()
|
||||
{
|
||||
if (rotation_ != 0) {
|
||||
std::string rotate = std::to_string(rotation_);
|
||||
for (uint32_t i = 0; i < formatContext_->nb_streams; i++) {
|
||||
if (formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
av_dict_set(&formatContext_->streams[i]->metadata, "rotate", rotate.c_str(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
AVDictionary *options = nullptr;
|
||||
av_dict_set(&options, "movflags", "faststart", 0);
|
||||
int ret = avformat_write_header(formatContext_.get(), &options);
|
||||
if (ret < 0) {
|
||||
AVCODEC_LOGE("write header failed, %{public}s", AVStrError(ret).c_str());
|
||||
return Status::ERROR_UNKNOWN;
|
||||
}
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
Status FFmpegMuxerPlugin::Stop()
|
||||
{
|
||||
int ret = av_write_frame(formatContext_.get(), nullptr); // flush out cache data
|
||||
if (ret < 0) {
|
||||
AVCODEC_LOGE("write trailer failed, %{public}s", AVStrError(ret).c_str());
|
||||
}
|
||||
ret = av_write_trailer(formatContext_.get());
|
||||
if (ret != 0) {
|
||||
AVCODEC_LOGE("write trailer failed, %{public}s", AVStrError(ret).c_str());
|
||||
}
|
||||
avio_flush(formatContext_->pb);
|
||||
|
||||
CloseFd();
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
Status FFmpegMuxerPlugin::WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr, Status::ERROR_NULL_POINTER, "av_write_frame sampleBuffer is null!");
|
||||
CHECK_AND_RETURN_RET_LOG(info.trackIndex < formatContext_->nb_streams, Status::ERROR_INVALID_PARAMETER, "track index is invalid!");
|
||||
(void)memset_s(cachePacket_.get(), sizeof(AVPacket), 0, sizeof(AVPacket));
|
||||
cachePacket_->data = sampleBuffer;
|
||||
cachePacket_->size = info.size;
|
||||
cachePacket_->stream_index = static_cast<int>(info.trackIndex);
|
||||
cachePacket_->pts = ConvertTimeToFFmpeg(info.timeUs, formatContext_->streams[info.trackIndex]->time_base);
|
||||
cachePacket_->dts = cachePacket_->pts;
|
||||
cachePacket_->flags = 0;
|
||||
if (info.flags & AVCODEC_BUFFER_FLAG_SYNC_FRAME) {
|
||||
AVCODEC_LOGD("It is key frame");
|
||||
cachePacket_->flags |= AV_PKT_FLAG_KEY;
|
||||
}
|
||||
auto ret = av_write_frame(formatContext_.get(), cachePacket_.get());
|
||||
av_packet_unref(cachePacket_.get());
|
||||
if (ret < 0) {
|
||||
AVCODEC_LOGE("write sample buffer failed, %{public}s", AVStrError(ret).c_str());
|
||||
return Status::ERROR_UNKNOWN;
|
||||
}
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
AVIOContext *FFmpegMuxerPlugin::InitAvIoCtx(int32_t fd, int writeFlags)
|
||||
{
|
||||
IOContext *ioContext = new IOContext();
|
||||
ioContext->fd_ = fd;
|
||||
ioContext->pos_ = 0;
|
||||
ioContext->end_ = 0;
|
||||
|
||||
constexpr int bufferSize = 4 * 1024; // 4096
|
||||
auto buffer = static_cast<unsigned char*>(av_malloc(bufferSize));
|
||||
AVIOContext *avioContext = avio_alloc_context(buffer, bufferSize, writeFlags, static_cast<void*>(ioContext),
|
||||
IoRead, IoWrite, IoSeek);
|
||||
if (avioContext == nullptr) {
|
||||
delete ioContext;
|
||||
av_free(buffer);
|
||||
return nullptr;
|
||||
}
|
||||
avioContext->seekable = AVIO_SEEKABLE_NORMAL;
|
||||
return avioContext;
|
||||
}
|
||||
|
||||
void FFmpegMuxerPlugin::DeInitAvIoCtx(AVIOContext *ptr)
|
||||
{
|
||||
if (ptr != nullptr) {
|
||||
delete static_cast<IOContext*>(ptr->opaque);
|
||||
ptr->opaque = nullptr;
|
||||
av_freep(&ptr->buffer);
|
||||
av_opt_free(ptr);
|
||||
avio_context_free(&ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void FFmpegMuxerPlugin::CloseFd()
|
||||
{
|
||||
if (fd_ != -1) {
|
||||
AVCODEC_LOGD("close fd");
|
||||
close(fd_);
|
||||
fd_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t FFmpegMuxerPlugin::IoRead(void *opaque, uint8_t *buf, int bufSize)
|
||||
{
|
||||
auto ioCtx = static_cast<IOContext*>(opaque);
|
||||
if (ioCtx && ioCtx->fd_ != -1) {
|
||||
int64_t ret = lseek(ioCtx->fd_, ioCtx->pos_, SEEK_SET);
|
||||
if (ret != -1) {
|
||||
ssize_t size = read(ioCtx->fd_, buf, bufSize);
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
ioCtx->pos_ += size;
|
||||
if (ioCtx->pos_ > ioCtx->end_) {
|
||||
ioCtx->end_ = ioCtx->pos_;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t FFmpegMuxerPlugin::IoWrite(void *opaque, uint8_t *buf, int bufSize)
|
||||
{
|
||||
auto ioCtx = static_cast<IOContext*>(opaque);
|
||||
if (ioCtx && ioCtx->fd_ != -1) {
|
||||
int64_t ret = lseek(ioCtx->fd_, ioCtx->pos_, SEEK_SET);
|
||||
if (ret != -1) {
|
||||
ssize_t size = write(ioCtx->fd_, buf, bufSize);
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
ioCtx->pos_ += size;
|
||||
if (ioCtx->pos_ > ioCtx->end_) {
|
||||
ioCtx->end_ = ioCtx->pos_;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t FFmpegMuxerPlugin::IoSeek(void *opaque, int64_t offset, int whence)
|
||||
{
|
||||
auto ioContext = static_cast<IOContext*>(opaque);
|
||||
uint64_t newPos = 0;
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
newPos = static_cast<uint64_t>(offset);
|
||||
ioContext->pos_ = newPos;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
newPos = ioContext->pos_ + offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
case AVSEEK_SIZE:
|
||||
newPos = ioContext->end_ + offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (whence != AVSEEK_SIZE) {
|
||||
ioContext->pos_ = newPos;
|
||||
}
|
||||
return newPos;
|
||||
}
|
||||
|
||||
int32_t FFmpegMuxerPlugin::IoOpen(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
|
||||
{
|
||||
AVCODEC_LOGD("IoOpen flags %{public}d", flags);
|
||||
*pb = InitAvIoCtx(static_cast<IOContext*>(s->pb->opaque)->fd_, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FFmpegMuxerPlugin::IoClose(AVFormatContext *s, AVIOContext *pb)
|
||||
{
|
||||
avio_flush(pb);
|
||||
DeInitAvIoCtx(pb);
|
||||
}
|
||||
} // Ffmpeg
|
||||
} // Plugin
|
||||
} // Media
|
||||
} // OHOS
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 FFMPEG_MUXER_PLUGIN_H
|
||||
#define FFMPEG_MUXER_PLUGIN_H
|
||||
|
||||
#include "muxer_plugin.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "libavformat/avformat.h"
|
||||
#include "libavutil/opt.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
namespace Ffmpeg {
|
||||
class FFmpegMuxerPlugin : public MuxerPlugin {
|
||||
public:
|
||||
explicit FFmpegMuxerPlugin(std::string name, int32_t fd);
|
||||
~FFmpegMuxerPlugin() override;
|
||||
|
||||
Status SetLocation(float latitude, float longitude) override;
|
||||
Status SetRotation(int32_t rotation) override;
|
||||
Status AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) override;
|
||||
Status Start() override;
|
||||
Status WriteSampleBuffer(uint8_t *sampleBuffer, const TrackSampleInfo &info) override;
|
||||
Status Stop() override;
|
||||
|
||||
private:
|
||||
Status SetCodecParameterOfTrack(AVStream *stream, const MediaDescription &trackDesc);
|
||||
static int32_t IoRead(void *opaque, uint8_t *buf, int bufSize);
|
||||
static int32_t IoWrite(void *opaque, uint8_t *buf, int bufSize);
|
||||
static int64_t IoSeek(void *opaque, int64_t offset, int whence);
|
||||
static AVIOContext *InitAvIoCtx(int32_t fd, int writeFlags);
|
||||
static void DeInitAvIoCtx(AVIOContext *ptr);
|
||||
static int32_t IoOpen(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options);
|
||||
static void IoClose(AVFormatContext *s, AVIOContext *pb);
|
||||
void CloseFd();
|
||||
|
||||
private:
|
||||
struct IOContext {
|
||||
int32_t fd_ {-1};
|
||||
int64_t pos_ {0};
|
||||
int64_t end_ {0};
|
||||
};
|
||||
int32_t fd_ {-1};
|
||||
std::shared_ptr<AVPacket> cachePacket_ {};
|
||||
std::shared_ptr<AVOutputFormat> outputFormat_ {};
|
||||
std::shared_ptr<AVFormatContext> formatContext_ {};
|
||||
int32_t rotation_ { 0 };
|
||||
};
|
||||
} // Ffmpeg
|
||||
} // Plugin
|
||||
} // Media
|
||||
} // OHOS
|
||||
#endif // FFMPEG_MUXER_PLUGIN_H
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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 "ffmpeg_utils.h"
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include "avcodec_info.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
namespace Ffmpeg {
|
||||
// Internal definitions
|
||||
namespace {
|
||||
/* time scale microsecond */
|
||||
constexpr int32_t TIME_SCALE_US = 1000000;
|
||||
|
||||
/* MIME to AVCodecID */
|
||||
std::unordered_map<std::string_view, AVCodecID> g_mimeToCodecId = {
|
||||
{CodecMimeType::AUDIO_MPEG, AV_CODEC_ID_MP3},
|
||||
{CodecMimeType::AUDIO_FLAC, AV_CODEC_ID_FLAC},
|
||||
{CodecMimeType::AUDIO_RAW, AV_CODEC_ID_PCM_S16LE},
|
||||
{CodecMimeType::AUDIO_AAC, AV_CODEC_ID_AAC},
|
||||
{CodecMimeType::AUDIO_VORBIS, AV_CODEC_ID_VORBIS},
|
||||
{CodecMimeType::AUDIO_OPUS, AV_CODEC_ID_OPUS},
|
||||
{CodecMimeType::AUDIO_AMR_NB, AV_CODEC_ID_AMR_NB},
|
||||
{CodecMimeType::AUDIO_AMR_WB, AV_CODEC_ID_AMR_WB},
|
||||
{CodecMimeType::VIDEO_AVC, AV_CODEC_ID_H264},
|
||||
{CodecMimeType::VIDEO_MPEG4, AV_CODEC_ID_MPEG4},
|
||||
{CodecMimeType::IMAGE_JPG, AV_CODEC_ID_MJPEG},
|
||||
{CodecMimeType::IMAGE_PNG, AV_CODEC_ID_PNG},
|
||||
{CodecMimeType::IMAGE_BMP, AV_CODEC_ID_BMP},
|
||||
};
|
||||
} // namespace
|
||||
|
||||
bool Mime2CodecId(const std::string_view &mime, AVCodecID &codecId)
|
||||
{
|
||||
auto it = g_mimeToCodecId.find(mime);
|
||||
if (it != g_mimeToCodecId.end()) {
|
||||
codecId = it->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReplaceDelimiter(const std::string &delmiters, char newDelimiter, std::string &str)
|
||||
{
|
||||
for (auto it = str.begin(); it != str.end(); ++it) {
|
||||
if (delmiters.find(newDelimiter) != std::string::npos) {
|
||||
*it = newDelimiter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> SplitString(const char* str, char delimiter)
|
||||
{
|
||||
std::vector<std::string> rtv;
|
||||
if (str) {
|
||||
SplitString(std::string(str), delimiter).swap(rtv);
|
||||
}
|
||||
return rtv;
|
||||
}
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &str, char delimiter)
|
||||
{
|
||||
if (str.empty()) {
|
||||
return {};
|
||||
}
|
||||
std::vector<std::string> rtv;
|
||||
std::string::size_type startPos = 0;
|
||||
std::string::size_type endPos = str.find_first_of(delimiter, startPos);
|
||||
while (startPos != endPos) {
|
||||
rtv.emplace_back(str.substr(startPos, endPos - startPos));
|
||||
if (endPos == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
startPos = endPos + 1;
|
||||
endPos = str.find_first_of(delimiter, startPos);
|
||||
}
|
||||
return rtv;
|
||||
}
|
||||
|
||||
std::string AVStrError(int errnum)
|
||||
{
|
||||
char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0};
|
||||
av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
||||
return std::string(errbuf);
|
||||
}
|
||||
|
||||
int64_t ConvertTimeFromFFmpeg(int64_t pts, AVRational base)
|
||||
{
|
||||
int64_t out;
|
||||
if (pts == AV_NOPTS_VALUE) {
|
||||
out = -1;
|
||||
} else {
|
||||
AVRational bq = {1, TIME_SCALE_US};
|
||||
out = av_rescale_q(pts, base, bq);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int64_t ConvertTimeToFFmpeg(int64_t timestampUs, AVRational base)
|
||||
{
|
||||
int64_t result;
|
||||
if (base.num == 0) {
|
||||
result = AV_NOPTS_VALUE;
|
||||
} else {
|
||||
AVRational bq = {1, TIME_SCALE_US};
|
||||
result = av_rescale_q(timestampUs, bq, base);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace Ffmpeg
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 FFMPEG_UTILS_H
|
||||
#define FFMPEG_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/pixfmt.h"
|
||||
#include "libswresample/swresample.h"
|
||||
#include "libswscale/swscale.h"
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
namespace Ffmpeg {
|
||||
bool Mime2CodecId(const std::string_view &mime, AVCodecID &codecId);
|
||||
|
||||
void ReplaceDelimiter(const std::string &delmiters, char newDelimiter, std::string &str);
|
||||
std::vector<std::string> SplitString(const char* str, char delimiter);
|
||||
std::vector<std::string> SplitString(const std::string &str, char delimiter);
|
||||
|
||||
std::string AVStrError(int errnum);
|
||||
|
||||
/**
|
||||
* Convert time from ffmpeg to time in HST_TIME_BASE.
|
||||
* @param pts ffmpeg time
|
||||
* @param base ffmpeg time_base
|
||||
* @return time in HST_TIME_BASE
|
||||
*/
|
||||
int64_t ConvertTimeFromFFmpeg(int64_t pts, AVRational base);
|
||||
|
||||
/**
|
||||
* Convert time in TIME_BASE to ffmpeg time.
|
||||
* @param time time in HST_TIME_BASE
|
||||
* @param base ffmpeg time_base
|
||||
* @return time in ffmpeg.
|
||||
*/
|
||||
int64_t ConvertTimeToFFmpeg(int64_t timestampUs, AVRational base);
|
||||
} // namespace Ffmpeg
|
||||
} // namespace Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // FFMPEG_UTILS_H
|
@ -7,4 +7,4 @@
|
||||
"secon" : "u:r:media_service:s0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_MUXER
|
||||
#include "i_avmuxer.h"
|
||||
#include "i_muxer_service.h"
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_SOURCE
|
||||
@ -99,8 +99,28 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_MUXER
|
||||
virtual std::shared_ptr<IAVMuxer> CreateMuxerService() = 0;
|
||||
virtual int32_t DestroyMuxerService(std::shared_ptr<IAVMuxer> muxer) = 0;
|
||||
/**
|
||||
* @brief Create an muxer service.
|
||||
*
|
||||
* All muxer functions must be created and obtained first.
|
||||
*
|
||||
* @return Returns a valid pointer if the setting is successful;
|
||||
* @since 10
|
||||
* @version 4.0
|
||||
*/
|
||||
virtual std::shared_ptr<IMuxerService> CreateMuxerService() = 0;
|
||||
|
||||
/**
|
||||
* @brief Destroy a muxer service.
|
||||
*
|
||||
* call the API to destroy the muxer service.
|
||||
*
|
||||
* @param pointer to the muxer service.
|
||||
* @return Returns a valid pointer if the setting is successful;
|
||||
* @since 10
|
||||
* @version 4.0
|
||||
*/
|
||||
virtual int32_t DestroyMuxerService(std::shared_ptr<IMuxerService> muxer) = 0;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_SOURCE
|
||||
@ -114,7 +134,7 @@ public:
|
||||
/**
|
||||
* @brief IAVCodecService singleton
|
||||
*
|
||||
* Create Recorder Service and Player Service Through the Avcodec Service.
|
||||
* Create Muxer and Demuxer Service Through the AVCodec Service.
|
||||
*
|
||||
* @return Returns IAVCodecService singleton;
|
||||
* @since 4.0
|
||||
|
@ -1,28 +0,0 @@
|
||||
#ifndef I_MUXER_SERVICE_H
|
||||
#define I_MUXER_SERVICE_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "format.h"
|
||||
#include "avcodec_common.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class IAVMuxer {
|
||||
public:
|
||||
virtual ~IAVMuxer() = default;
|
||||
|
||||
// 业务
|
||||
virtual int32_t Init() = 0;
|
||||
virtual int32_t SetLocation(float latitude, float longitude) = 0;
|
||||
virtual int32_t SetRotation(int32_t rotation) = 0;
|
||||
virtual int32_t SetParameter(const Format &generalFormat) = 0;
|
||||
virtual int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) = 0;
|
||||
virtual int32_t Start() = 0;
|
||||
virtual int32_t WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer,
|
||||
AVCodecBufferInfo info) = 0;
|
||||
virtual int32_t Stop() = 0;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // I_MUXER_SERVICE_H
|
42
services/include/i_muxer_service.h
Normal file
42
services/include/i_muxer_service.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 I_MUXER_SERVICE_H
|
||||
#define I_MUXER_SERVICE_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "avsharedmemory.h"
|
||||
#include "media_description.h"
|
||||
#include "av_common.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class IMuxerService {
|
||||
public:
|
||||
virtual ~IMuxerService() = default;
|
||||
|
||||
virtual int32_t InitParameter(int32_t fd, OutputFormat format) = 0;
|
||||
virtual int32_t SetLocation(float latitude, float longitude) = 0;
|
||||
virtual int32_t SetRotation(int32_t rotation) = 0;
|
||||
virtual int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) = 0;
|
||||
virtual int32_t Start() = 0;
|
||||
virtual int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) = 0;
|
||||
virtual int32_t Stop() = 0;
|
||||
virtual void Release() = 0;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // I_MUXER_SERVICE_H
|
@ -81,12 +81,16 @@ config("av_codec_service_config") {
|
||||
"//foundation/multimedia/av_codec/services/dfx/include/",
|
||||
"//foundation/multimedia/av_codec/services/engine/",
|
||||
"//foundation/multimedia/av_codec/services/engine/avcodeclist",
|
||||
"//foundation/multimedia/av_codec/services/engine/muxer",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/core",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/interface",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/plugins/",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/plugins/demuxer/",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/plugins/demuxer/ffmpeg_demuxer/",
|
||||
"//foundation/multimedia/av_codec/services/include/",
|
||||
"//foundation/multimedia/av_codec/services/services/",
|
||||
"//foundation/multimedia/av_codec/services/services/factory",
|
||||
"//foundation/multimedia/av_codec/services/services/avcodeclist/",
|
||||
"//foundation/multimedia/av_codec/services/services/avcodeclist/client",
|
||||
"//foundation/multimedia/av_codec/services/services/avcodeclist/ipc",
|
||||
@ -106,9 +110,9 @@ config("av_codec_service_config") {
|
||||
"//foundation/multimedia/av_codec/services/services/demuxer/ipc/",
|
||||
"//foundation/multimedia/av_codec/services/services/demuxer/server/",
|
||||
"//foundation/multimedia/av_codec/services/services/muxer/",
|
||||
"//foundation/multimedia/av_codec/services/services/muxer/client/include",
|
||||
"//foundation/multimedia/av_codec/services/services/muxer/ipc/include",
|
||||
"//foundation/multimedia/av_codec/services/services/muxer/server/include",
|
||||
"//foundation/multimedia/av_codec/services/services/muxer/client",
|
||||
"//foundation/multimedia/av_codec/services/services/muxer/ipc",
|
||||
"//foundation/multimedia/av_codec/services/services/muxer/server",
|
||||
"//foundation/multimedia/av_codec/services/services/sa_avcodec/",
|
||||
"//foundation/multimedia/av_codec/services/services/sa_avcodec/client/",
|
||||
"//foundation/multimedia/av_codec/services/services/sa_avcodec/ipc/",
|
||||
@ -131,6 +135,17 @@ config("av_codec_service_config") {
|
||||
if (target_cpu == "arm") {
|
||||
cflags += [ "-DBINDER_IPC_32BIT" ]
|
||||
}
|
||||
|
||||
if (target_cpu == "arm64") {
|
||||
av_codec_plugin_path = "\"/system/lib64/media/av_codec_plugins\""
|
||||
} else {
|
||||
av_codec_plugin_path = "\"/system/lib/media/av_codec_plugins\""
|
||||
}
|
||||
|
||||
defines += [
|
||||
"AV_CODEC_PLUGIN_PATH=${av_codec_plugin_path}",
|
||||
"AV_CODEC_PLUGIN_FILE_TAIL=\".z.so\"",
|
||||
]
|
||||
}
|
||||
|
||||
ohos_shared_library("av_codec_service") {
|
||||
@ -155,6 +170,10 @@ ohos_shared_library("av_codec_service") {
|
||||
"sa_avcodec/ipc/avcodec_service_stub.cpp",
|
||||
"sa_avcodec/server/avcodec_server.cpp",
|
||||
"sa_avcodec/server/avcodec_server_manager.cpp",
|
||||
"//foundation/multimedia/av_codec/services/engine/muxer/muxer_engine_impl.cpp",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/core/muxer_factory.cpp",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/core/muxer.cpp",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/core/plugin_loader.cpp",
|
||||
]
|
||||
|
||||
|
||||
@ -174,8 +193,8 @@ ohos_shared_library("av_codec_service") {
|
||||
}
|
||||
if (multimedia_av_codec_support_muxer) {
|
||||
sources += [
|
||||
"muxer/ipc/avmuxer_stub.cpp",
|
||||
"muxer/server/avmuxer_server.cpp",
|
||||
"muxer/ipc/muxer_service_stub.cpp",
|
||||
"muxer/server/muxer_server.cpp",
|
||||
]
|
||||
}
|
||||
|
||||
@ -184,6 +203,7 @@ ohos_shared_library("av_codec_service") {
|
||||
"$AV_CODEC_ROOT_DIR/services/dfx:av_codec_service_dfx",
|
||||
"$AV_CODEC_ROOT_DIR/services/utils:av_codec_format",
|
||||
"$AV_CODEC_ROOT_DIR/services/utils:av_codec_service_utils",
|
||||
"$AV_CODEC_ROOT_DIR/services/engine:av_codec_engine_package",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
|
47
services/services/factory/i_muxer_engine.h
Normal file
47
services/services/factory/i_muxer_engine.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 IMUXER_ENGINE_H
|
||||
#define IMUXER_ENGINE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "avsharedmemory.h"
|
||||
#include "media_description.h"
|
||||
#include "av_common.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class IMuxerEngine {
|
||||
public:
|
||||
virtual ~IMuxerEngine() = default;
|
||||
virtual int32_t SetLocation(float latitude, float longitude) = 0;
|
||||
virtual int32_t SetRotation(int32_t rotation) = 0;
|
||||
virtual int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) = 0;
|
||||
virtual int32_t Start() = 0;
|
||||
virtual int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) = 0;
|
||||
virtual int32_t Stop() = 0;
|
||||
virtual int32_t DumpInfo(int32_t fd) = 0;
|
||||
};
|
||||
|
||||
class __attribute__((visibility("default"))) IMuxerEngineFactory {
|
||||
public:
|
||||
static std::shared_ptr<IMuxerEngine> CreateMuxerEngine(int32_t appUid, int32_t appPid, int32_t fd, OutputFormat format);
|
||||
private:
|
||||
IMuxerEngineFactory() = default;
|
||||
~IMuxerEngineFactory() = default;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // IMUXER_ENGINE_H
|
@ -13,31 +13,30 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <mutex>
|
||||
#include "avmuxer_client.h"
|
||||
#include "muxer_client.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_log.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVMuxerClient"};
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MuxerClient"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
std::shared_ptr<AVMuxerClient> AVMuxerClient::Create(const sptr<IAVMuxerService> &ipcProxy)
|
||||
std::shared_ptr<MuxerClient> MuxerClient::Create(const sptr<IStandardMuxerService> &ipcProxy)
|
||||
{
|
||||
std::shared_ptr<AVMuxerClient> muxerClient = std::make_shared<AVMuxerClient>(ipcProxy);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient != nullptr, nullptr, "Failed to create muxer client");
|
||||
std::shared_ptr<MuxerClient> muxerClient = std::make_shared<MuxerClient>(ipcProxy);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient != nullptr, nullptr, "Create muxer client failed");
|
||||
return muxerClient;
|
||||
}
|
||||
|
||||
AVMuxerClient::AVMuxerClient(const sptr<IAVMuxerService> &ipcProxy)
|
||||
MuxerClient::MuxerClient(const sptr<IStandardMuxerService> &ipcProxy)
|
||||
: muxerProxy_(ipcProxy)
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
AVMuxerClient::~AVMuxerClient()
|
||||
MuxerClient::~MuxerClient()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (muxerProxy_ != nullptr) {
|
||||
@ -47,67 +46,67 @@ AVMuxerClient::~AVMuxerClient()
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
void AVMuxerClient::AVCodecServerDied()
|
||||
void MuxerClient::AVCodecServerDied()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
muxerProxy_ = nullptr;
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::Init()
|
||||
int32_t MuxerClient::InitParameter(int32_t fd, OutputFormat format)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerProxy_->Init();
|
||||
return muxerProxy_->InitParameter(fd, format);
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::SetLocation(float latitude, float longitude)
|
||||
int32_t MuxerClient::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerProxy_->SetLocation(latitude, longitude);
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::SetRotation(int32_t rotation)
|
||||
int32_t MuxerClient::SetRotation(int32_t rotation)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerProxy_->SetRotation(rotation);
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::SetParameter(const Format &generalFormat)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "codec service does not exist.");
|
||||
return muxerProxy_->SetParameter(generalFormat);
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::AddTrack(uint32_t &trackIndex, const Format &trackFormat)
|
||||
int32_t MuxerClient::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerProxy_->AddTrack(trackIndex, trackFormat);
|
||||
return muxerProxy_->AddTrack(trackIndex, trackDesc);
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::Start()
|
||||
int32_t MuxerClient::Start()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerProxy_->Start();
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info)
|
||||
int32_t MuxerClient::WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr, AVCS_ERR_INVALID_VAL, "SampleBuffer is nullptr");
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr, AVCS_ERR_INVALID_VAL, "sampleBuffer is nullptr");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerProxy_->WriteSampleBuffer(trackIndex, sampleBuffer, info);
|
||||
return muxerProxy_->WriteSampleBuffer(sampleBuffer, info);
|
||||
}
|
||||
|
||||
int32_t AVMuxerClient::Stop()
|
||||
int32_t MuxerClient::Stop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerProxy_->Stop();
|
||||
}
|
||||
|
||||
void MuxerClient::Release()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_LOG(muxerProxy_ != nullptr, "Muxer Service does not exist");
|
||||
muxerProxy_->Release();
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -16,30 +16,31 @@
|
||||
#ifndef MUXER_CLIENT_H
|
||||
#define MUXER_CLIENT_H
|
||||
|
||||
#include "i_avmuxer.h"
|
||||
#include "i_avmuxer_service.h"
|
||||
#include <mutex>
|
||||
#include "i_muxer_service.h"
|
||||
#include "i_standard_muxer_service.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerClient : public IAVMuxer, public NoCopyable {
|
||||
class MuxerClient : public IMuxerService, public NoCopyable {
|
||||
public:
|
||||
static std::shared_ptr<AVMuxerClient> Create(const sptr<IAVMuxerService> &ipcProxy);
|
||||
explicit AVMuxerClient(const sptr<IAVMuxerService> &ipcProxy);
|
||||
~AVMuxerClient();
|
||||
static std::shared_ptr<MuxerClient> Create(const sptr<IStandardMuxerService> &ipcProxy);
|
||||
explicit MuxerClient(const sptr<IStandardMuxerService> &ipcProxy);
|
||||
~MuxerClient();
|
||||
|
||||
int32_t Init() override;
|
||||
int32_t InitParameter(int32_t fd, OutputFormat format) override;
|
||||
int32_t SetLocation(float latitude, float longitude) override;
|
||||
int32_t SetRotation(int32_t rotation) override;
|
||||
int32_t SetParameter(const Format &generalFormat) override;
|
||||
int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) override;
|
||||
int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) override;
|
||||
int32_t Start() override;
|
||||
int32_t WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info) override;
|
||||
int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) override;
|
||||
int32_t Stop() override;
|
||||
void Release() override;
|
||||
|
||||
void AVCodecServerDied();
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
sptr<IAVMuxerService> muxerProxy_ = nullptr;
|
||||
sptr<IStandardMuxerService> muxerProxy_ = nullptr;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* 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 "avmuxer_proxy.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avsharedmemory_ipc.h"
|
||||
#include "avcodec_parcel.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVMuxerProxy"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
AVMuxerProxy::AVMuxerProxy(const sptr<IRemoteObject> &impl)
|
||||
: IRemoteProxy<IAVMuxerService>(impl)
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
AVMuxerProxy::~AVMuxerProxy()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::DestroyStub()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(DESTROY_STUB, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call DestroyStub");
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::Init()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(INIT, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call Init");
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor");
|
||||
|
||||
data.WriteFloat(latitude);
|
||||
data.WriteFloat(longitude);
|
||||
int32_t ret = Remote()->SendRequest(SET_LOCATION, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call SetLocation");
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::SetRotation(int32_t rotation)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor");
|
||||
|
||||
data.WriteInt32(rotation);
|
||||
int32_t ret = Remote()->SendRequest(SET_ROTATION, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call SetRotation");
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
|
||||
int32_t AVMuxerProxy::SetParameter(const Format &generalFormat)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor");
|
||||
|
||||
AVCodecParcel::Marshalling(data, generalFormat);
|
||||
int32_t ret = Remote()->SendRequest(SET_PARAMETER, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_INVALID_OPERATION, "SetParameter failed");
|
||||
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::AddTrack(uint32_t &trackIndex, const Format &trackFormat)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor");
|
||||
|
||||
data.WriteInt32(trackIndex);
|
||||
AVCodecParcel::Marshalling(data, trackFormat);
|
||||
int32_t ret = Remote()->SendRequest(ADD_TRACK, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call AddTrack");
|
||||
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::Start()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(START, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call Start");
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr, AVCS_ERR_INVALID_VAL, "sampleBuffer is nullptr");
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor!");
|
||||
data.WriteInt32(trackIndex);
|
||||
WriteAVSharedMemoryToParcel(sampleBuffer, data);
|
||||
data.WriteInt64(info.presentationTimeUs);
|
||||
data.WriteInt32(info.size);
|
||||
data.WriteInt32(info.offset);
|
||||
// data.WriteInt32(info.flag);
|
||||
|
||||
int32_t ret = Remote()->SendRequest(WRITE_SAMPLE_BUFFER, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call WriteTrackSample");
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t AVMuxerProxy::Stop()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(AVMuxerProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Failed to write descriptor!");
|
||||
|
||||
int ret = Remote()->SendRequest(STOP, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call Stop");
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -1,252 +0,0 @@
|
||||
/*
|
||||
* 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 "avmuxer_stub.h"
|
||||
#include "unistd.h"
|
||||
#include "avcodec_server_manager.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "avsharedmemory_ipc.h"
|
||||
#include "avcodec_parcel.h"
|
||||
#include "avcodec_xcollie.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVMuxerStub"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
sptr<AVMuxerStub> AVMuxerStub::Create()
|
||||
{
|
||||
sptr<AVMuxerStub> muxerStub = new(std::nothrow) AVMuxerStub();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerStub != nullptr, nullptr, "Failed to create muxer service stub");
|
||||
|
||||
int32_t ret = muxerStub->InitStub();
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Failed to init AVMuxerStub");
|
||||
return muxerStub;
|
||||
}
|
||||
|
||||
AVMuxerStub::AVMuxerStub()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
AVMuxerStub::~AVMuxerStub()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::InitStub()
|
||||
{
|
||||
muxerServer_ = AVMuxerServer::Create();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Failed to create muxer server");
|
||||
|
||||
muxerFuncs_[INIT] = &AVMuxerStub::Init;
|
||||
muxerFuncs_[SET_LOCATION] = &AVMuxerStub::SetLocation;
|
||||
muxerFuncs_[SET_ROTATION] = &AVMuxerStub::SetRotation;
|
||||
muxerFuncs_[SET_PARAMETER] = &AVMuxerStub::SetParameter;
|
||||
muxerFuncs_[ADD_TRACK] = &AVMuxerStub::AddTrack;
|
||||
muxerFuncs_[START] = &AVMuxerStub::Start;
|
||||
muxerFuncs_[WRITE_SAMPLE_BUFFER] = &AVMuxerStub::WriteSampleBuffer;
|
||||
muxerFuncs_[STOP] = &AVMuxerStub::Stop;
|
||||
muxerFuncs_[DESTROY_STUB] = &AVMuxerStub::DestroyStub;
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::DestroyStub()
|
||||
{
|
||||
muxerServer_ = nullptr;
|
||||
AVCodecServerManager::GetInstance().DestroyStubObject(AVCodecServerManager::MUXER, AsObject());
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int AVMuxerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
|
||||
{
|
||||
AVCODEC_LOGI("Stub: OnRemoteRequest of code: %{public}u is received", code);
|
||||
|
||||
auto remoteDescriptor = data.ReadInterfaceToken();
|
||||
if (AVMuxerStub::GetDescriptor() != remoteDescriptor) {
|
||||
AVCODEC_LOGE("Invalid descriptor");
|
||||
return AVCS_ERR_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
auto itFunc = muxerFuncs_.find(code);
|
||||
if (itFunc != muxerFuncs_.end()) {
|
||||
auto memberFunc = itFunc->second;
|
||||
if (memberFunc != nullptr) {
|
||||
int32_t ret = -1;
|
||||
COLLIE_LISTEN(ret = (this->*memberFunc)(data, reply),
|
||||
"AVMuxerStub::OnRemoteRequest");
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call memberFunc");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
}
|
||||
AVCODEC_LOGW("Failed to find corresponding function");
|
||||
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::Init()
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->Init();
|
||||
}
|
||||
|
||||
|
||||
int32_t AVMuxerStub::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->SetLocation(latitude, longitude);
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::SetRotation(int32_t rotation)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->SetRotation(rotation);
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::SetParameter(const Format &generalFormat)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->SetParameter(generalFormat);
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::AddTrack(uint32_t &trackIndex, const Format &trackFormat)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->AddTrack(trackIndex, trackFormat);
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::Start()
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->Start();
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->WriteSampleBuffer(trackIndex, sampleBuffer, info);
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::Stop()
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "muxer service is nullptr");
|
||||
return muxerServer_->Stop();
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::DumpInfo(int32_t fd)
|
||||
{
|
||||
std::string dumpInfo;
|
||||
dumpInfo += "# AVMuxerStub";
|
||||
GetDumpInfo(dumpInfo);
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(fd != -1, AVCS_ERR_INVALID_VAL, "Attempt to write to a invalid fd: %{public}d", fd);
|
||||
write(fd, dumpInfo.c_str(), dumpInfo.size());
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::Init(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
// TODO: 补充LOG说明
|
||||
(void)data;
|
||||
(void)reply;
|
||||
bool ret = reply.WriteInt32(Init());
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::DestroyStub(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
bool ret = reply.WriteInt32(DestroyStub());
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::SetLocation(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
float latitude = data.ReadFloat();
|
||||
float longitude = data.ReadFloat();
|
||||
bool ret = reply.WriteInt32(SetLocation(latitude, longitude));
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::SetRotation(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
int32_t rotation = data.ReadInt32();
|
||||
bool ret = reply.WriteInt32(SetRotation(rotation));
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::SetParameter(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
Format format;
|
||||
AVCodecParcel::Unmarshalling(data, format);
|
||||
bool ret = reply.WriteInt32(SetParameter(format));
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::AddTrack(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
Format generalFormat;
|
||||
uint32_t trackIndex = data.ReadInt32();
|
||||
(void)AVCodecParcel::Unmarshalling(data, generalFormat);
|
||||
bool ret = reply.WriteInt32(AddTrack(trackIndex, generalFormat));
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::Start(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
bool ret = reply.WriteInt32(Start());
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::WriteSampleBuffer(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
(void)reply;
|
||||
uint32_t trackIndex = data.ReadInt32();
|
||||
std::shared_ptr<AVSharedMemory> sampleBuffer = ReadAVSharedMemoryFromParcel(data);
|
||||
AVCodecBufferInfo bufferInfo;
|
||||
bufferInfo.presentationTimeUs = data.ReadInt64();
|
||||
bufferInfo.size = data.ReadInt32();
|
||||
bufferInfo.offset = data.ReadInt32();
|
||||
bool ret = reply.WriteInt32(WriteSampleBuffer(trackIndex, sampleBuffer, bufferInfo));
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::Stop(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
bool ret = reply.WriteInt32(Stop());
|
||||
CHECK_AND_RETURN_RET_LOG(ret, AVCS_ERR_INVALID_OPERATION, "MessageParcel write failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerStub::GetDumpInfo(std::string& dumpInfo)
|
||||
{
|
||||
dumpInfo += "## pid: " + std::to_string(getpid());
|
||||
dumpInfo += "## uid: " + std::to_string(getuid());
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -16,39 +16,37 @@
|
||||
#ifndef I_STANDARD_MUXER_SERVICE_H
|
||||
#define I_STANDARD_MUXER_SERVICE_H
|
||||
|
||||
#include "avcodec_info.h"
|
||||
#include "avcodec_common.h"
|
||||
#include "i_muxer_service.h"
|
||||
#include "iremote_proxy.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class IAVMuxerService : public IRemoteBroker {
|
||||
class IStandardMuxerService : public IRemoteBroker {
|
||||
public:
|
||||
virtual ~IAVMuxerService() = default;
|
||||
|
||||
virtual int32_t Init() = 0;
|
||||
virtual ~IStandardMuxerService() = default;
|
||||
virtual int32_t InitParameter(int32_t fd, OutputFormat format) = 0;
|
||||
virtual int32_t SetLocation(float latitude, float longitude) = 0;
|
||||
virtual int32_t SetRotation(int32_t rotation) = 0;
|
||||
virtual int32_t SetParameter(const Format &generalFormat) = 0;
|
||||
virtual int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) = 0;
|
||||
virtual int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) = 0;
|
||||
virtual int32_t Start() = 0;
|
||||
virtual int32_t WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info) = 0;
|
||||
virtual int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) = 0;
|
||||
virtual int32_t Stop() = 0;
|
||||
virtual void Release() = 0;
|
||||
virtual int32_t DestroyStub() = 0;
|
||||
|
||||
virtual int32_t DestroyStub() = 0;
|
||||
enum MuxerServiceMsg {
|
||||
INIT,
|
||||
INIT_PARAMETER = 0,
|
||||
SET_LOCATION,
|
||||
SET_ROTATION,
|
||||
SET_PARAMETER,
|
||||
ADD_TRACK,
|
||||
START,
|
||||
WRITE_SAMPLE_BUFFER,
|
||||
STOP,
|
||||
DESTROY_STUB,
|
||||
RELEASE,
|
||||
DESTROY,
|
||||
};
|
||||
|
||||
DECLARE_INTERFACE_DESCRIPTOR(u"IAVMuxerService");
|
||||
|
||||
DECLARE_INTERFACE_DESCRIPTOR(u"IStandardMuxerServiceq1a");
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
181
services/services/muxer/ipc/muxer_service_proxy.cpp
Normal file
181
services/services/muxer/ipc/muxer_service_proxy.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 "muxer_service_proxy.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "avsharedmemory_ipc.h"
|
||||
#include "avcodec_parcel.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MuxerServiceProxy"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
MuxerServiceProxy::MuxerServiceProxy(const sptr<IRemoteObject> &impl)
|
||||
: IRemoteProxy<IStandardMuxerService>(impl)
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
MuxerServiceProxy::~MuxerServiceProxy()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::InitParameter(int32_t fd, OutputFormat format)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!");
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteFileDescriptor(fd), AVCS_ERR_UNKNOWN, "WriteFileDescriptor failed!");
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteInt32(format), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
|
||||
int error = Remote()->SendRequest(INIT_PARAMETER, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(error == AVCS_ERR_OK, error, "Call InitParameter failed, error: %{public}d", error);
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!!");
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteFloat(latitude), AVCS_ERR_UNKNOWN, "WriteFloat failed!");
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteFloat(longitude), AVCS_ERR_UNKNOWN, "WriteFloat failed!");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(SET_LOCATION, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "SetLocation failed, error: %{public}d", ret);
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::SetRotation(int32_t rotation)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!!");
|
||||
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteInt32(rotation), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(SET_ROTATION, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "SetRotation failed, error: %{public}d", ret);
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!!");
|
||||
|
||||
AVCodecParcel::Marshalling(data, trackDesc);
|
||||
|
||||
int32_t ret = Remote()->SendRequest(ADD_TRACK, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "AddTrack failed, error: %{public}d", ret);
|
||||
trackIndex = reply.ReadInt32();
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::Start()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!!");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(START, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Start failed, error: %{public}d", ret);
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!!");
|
||||
|
||||
WriteAVSharedMemoryToParcel(sampleBuffer, data);
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteUint32(info.trackIndex), AVCS_ERR_UNKNOWN, "Write track index failed!");
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteInt64(info.timeUs), AVCS_ERR_UNKNOWN, "Write timeUs failed!");
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteUint32(info.size), AVCS_ERR_UNKNOWN, "Write size failed!");
|
||||
CHECK_AND_RETURN_RET_LOG(data.WriteUint32(info.flags), AVCS_ERR_UNKNOWN, "Write flags failed!");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(WRITE_SAMPLE_BUFFER, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "WriteSampleBuffer failed, error: %{public}d", ret);
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::Stop()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!!");
|
||||
|
||||
int32_t ret = Remote()->SendRequest(STOP, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Stop failed, error: %{public}d", ret);
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceProxy::DestroyStub()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_RET_LOG(token, AVCS_ERR_INVALID_OPERATION, "Write descriptor failed!!");
|
||||
|
||||
int ret = Remote()->SendRequest(DESTROY, data, reply, option);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Call DestroyStub failed, error: %{public}d", ret);
|
||||
return reply.ReadInt32();
|
||||
}
|
||||
|
||||
void MuxerServiceProxy::Release()
|
||||
{
|
||||
MessageParcel data;
|
||||
MessageParcel reply;
|
||||
MessageOption option;
|
||||
|
||||
bool token = data.WriteInterfaceToken(MuxerServiceProxy::GetDescriptor());
|
||||
CHECK_AND_RETURN_LOG(token, "Write descriptor failed!");
|
||||
|
||||
int ret = Remote()->SendRequest(RELEASE, data, reply, option);
|
||||
CHECK_AND_RETURN_LOG(ret == AVCS_ERR_OK, " Call Release failed, error: %{public}d", ret);
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -16,27 +16,26 @@
|
||||
#ifndef MUXER_SERVICE_PROXY_H
|
||||
#define MUXER_SERVICE_PROXY_H
|
||||
|
||||
#include "i_avmuxer_service.h"
|
||||
#include "i_standard_muxer_service.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerProxy : public IRemoteProxy<IAVMuxerService>, public NoCopyable {
|
||||
class MuxerServiceProxy : public IRemoteProxy<IStandardMuxerService>, public NoCopyable {
|
||||
public:
|
||||
explicit AVMuxerProxy(const sptr<IRemoteObject> &impl);
|
||||
virtual ~AVMuxerProxy();
|
||||
explicit MuxerServiceProxy(const sptr<IRemoteObject> &impl);
|
||||
virtual ~MuxerServiceProxy();
|
||||
|
||||
int32_t Init() override;
|
||||
int32_t InitParameter(int32_t fd, OutputFormat format) override;
|
||||
int32_t SetLocation(float latitude, float longitude) override;
|
||||
int32_t SetRotation(int32_t rotation) override;
|
||||
int32_t SetParameter(const Format &generalFormat) override;
|
||||
int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) override;
|
||||
int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) override;
|
||||
int32_t Start() override;
|
||||
int32_t WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info) override;
|
||||
int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) override;
|
||||
int32_t Stop() override;
|
||||
|
||||
void Release() override;
|
||||
int32_t DestroyStub() override;
|
||||
private:
|
||||
static inline BrokerDelegator<AVMuxerProxy> delegator_;
|
||||
static inline BrokerDelegator<MuxerServiceProxy> delegator_;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
227
services/services/muxer/ipc/muxer_service_stub.cpp
Normal file
227
services/services/muxer/ipc/muxer_service_stub.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 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 "muxer_service_stub.h"
|
||||
#include "avcodec_server_manager.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "avsharedmemory_ipc.h"
|
||||
#include "avcodec_parcel.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MuxerServiceStub"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
sptr<MuxerServiceStub> MuxerServiceStub::Create()
|
||||
{
|
||||
sptr<MuxerServiceStub> muxerStub = new(std::nothrow) MuxerServiceStub();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerStub != nullptr, nullptr, "Create muxer service stub failed");
|
||||
|
||||
int32_t ret = muxerStub->Init();
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Init MuxerServiceStub failed to ");
|
||||
return muxerStub;
|
||||
}
|
||||
|
||||
MuxerServiceStub::MuxerServiceStub()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
MuxerServiceStub::~MuxerServiceStub()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::Init()
|
||||
{
|
||||
muxerServer_ = MuxerServer::Create();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Create muxer server failed");
|
||||
|
||||
muxerFuncs_[INIT_PARAMETER] = &MuxerServiceStub::InitParameter;
|
||||
muxerFuncs_[SET_LOCATION] = &MuxerServiceStub::SetLocation;
|
||||
muxerFuncs_[SET_ROTATION] = &MuxerServiceStub::SetRotation;
|
||||
muxerFuncs_[ADD_TRACK] = &MuxerServiceStub::AddTrack;
|
||||
muxerFuncs_[START] = &MuxerServiceStub::Start;
|
||||
muxerFuncs_[WRITE_SAMPLE_BUFFER] = &MuxerServiceStub::WriteSampleBuffer;
|
||||
muxerFuncs_[STOP] = &MuxerServiceStub::Stop;
|
||||
muxerFuncs_[RELEASE] = &MuxerServiceStub::Release;
|
||||
muxerFuncs_[DESTROY] = &MuxerServiceStub::DestroyStub;
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int MuxerServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
|
||||
{
|
||||
auto remoteDescriptor = data.ReadInterfaceToken();
|
||||
if (MuxerServiceStub::GetDescriptor() != remoteDescriptor) {
|
||||
AVCODEC_LOGE("Invalid descriptor");
|
||||
return AVCS_ERR_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
auto itFunc = muxerFuncs_.find(code);
|
||||
if (itFunc != muxerFuncs_.end()) {
|
||||
auto memberFunc = itFunc->second;
|
||||
if (memberFunc != nullptr) {
|
||||
int32_t ret = (this->*memberFunc)(data, reply);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call memberFunc");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
}
|
||||
AVCODEC_LOGW("Failed to find corresponding function");
|
||||
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::InitParameter(int32_t fd, OutputFormat format)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerServer_->InitParameter(fd, format);
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerServer_->SetLocation(latitude, longitude);
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::SetRotation(int32_t rotation)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerServer_->SetRotation(rotation);
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerServer_->AddTrack(trackIndex, trackDesc);
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::Start()
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerServer_->Start();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr, AVCS_ERR_INVALID_VAL, "sampleData is nullptr");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerServer_->WriteSampleBuffer(sampleBuffer, info);
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::Stop()
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return muxerServer_->Stop();
|
||||
}
|
||||
|
||||
void MuxerServiceStub::Release()
|
||||
{
|
||||
CHECK_AND_RETURN_LOG(muxerServer_ != nullptr, "Muxer Service does not exist");
|
||||
muxerServer_->Release();
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::DestroyStub()
|
||||
{
|
||||
muxerServer_ = nullptr;
|
||||
AVCodecServerManager::GetInstance().DestroyStubObject(AVCodecServerManager::MUXER, AsObject());
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::DumpInfo(int32_t fd)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer_ != nullptr, AVCS_ERR_NO_MEMORY, "Muxer Service does not exist");
|
||||
return std::static_pointer_cast<MuxerServer>(muxerServer_)->DumpInfo(fd);
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::InitParameter(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
int32_t fd = data.ReadFileDescriptor();
|
||||
OutputFormat format = static_cast<OutputFormat>(data.ReadInt32());
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(InitParameter(fd, format)), AVCS_ERR_UNKNOWN, "Reply InitParameter failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::SetLocation(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
float latitude = data.ReadFloat();
|
||||
float longitude = data.ReadFloat();
|
||||
int32_t ret = SetLocation(latitude, longitude);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(ret), AVCS_ERR_UNKNOWN, "Reply SetLocation failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::SetRotation(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
int32_t rotation = data.ReadInt32();
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(SetRotation(rotation)), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::AddTrack(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
MediaDescription trackDesc;
|
||||
(void)AVCodecParcel::Unmarshalling(data, trackDesc);
|
||||
int32_t trackIndex = -1;
|
||||
int32_t ret = AddTrack(trackIndex, trackDesc);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(trackIndex), AVCS_ERR_UNKNOWN, "Reply AddTrack failed!");
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(ret), AVCS_ERR_UNKNOWN, "Reply AddTrack failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::Start(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(Start()), AVCS_ERR_UNKNOWN, "Reply Start failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::WriteSampleBuffer(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
std::shared_ptr<AVSharedMemory> sampleBuffer = ReadAVSharedMemoryFromParcel(data);
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr, AVCS_ERR_UNKNOWN, "Read sampleBuffer from parcel failed!");
|
||||
TrackSampleInfo info;
|
||||
info.trackIndex = data.ReadUint32();
|
||||
info.timeUs = data.ReadInt64();
|
||||
info.size = data.ReadUint32();
|
||||
info.flags = data.ReadUint32();
|
||||
int32_t ret = WriteSampleBuffer(sampleBuffer, info);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(ret), AVCS_ERR_UNKNOWN, "Reply WriteSampleBuffer failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::Stop(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(Stop()), AVCS_ERR_UNKNOWN, "Reply Stop failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::Release(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
(void)reply;
|
||||
Release();
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServiceStub::DestroyStub(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
(void)data;
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(DestroyStub()), AVCS_ERR_UNKNOWN, "Reply DestroyStub failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -16,50 +16,46 @@
|
||||
#ifndef MUXER_SERVICE_STUB_H
|
||||
#define MUXER_SERVICE_STUB_H
|
||||
|
||||
#include <string>
|
||||
#include "i_avmuxer_service.h"
|
||||
#include "avmuxer_server.h"
|
||||
#include "i_standard_muxer_service.h"
|
||||
#include "muxer_server.h"
|
||||
#include "iremote_stub.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerStub : public IRemoteStub<IAVMuxerService>, public NoCopyable {
|
||||
class MuxerServiceStub : public IRemoteStub<IStandardMuxerService>, public NoCopyable {
|
||||
public:
|
||||
static sptr<AVMuxerStub> Create();
|
||||
virtual ~AVMuxerStub();
|
||||
static sptr<MuxerServiceStub> Create();
|
||||
virtual ~MuxerServiceStub();
|
||||
int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
|
||||
using MuxerStubFunc = int32_t(AVMuxerStub::*)(MessageParcel &data, MessageParcel &reply);
|
||||
using MuxerStubFunc = int32_t(MuxerServiceStub::*)(MessageParcel &data, MessageParcel &reply);
|
||||
|
||||
int32_t Init() override;
|
||||
int32_t InitParameter(int32_t fd, OutputFormat format) override;
|
||||
int32_t SetLocation(float latitude, float longitude) override;
|
||||
int32_t SetRotation(int32_t rotation) override;
|
||||
int32_t SetParameter(const Format &generalFormat) override;
|
||||
int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) override;
|
||||
int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) override;
|
||||
int32_t Start() override;
|
||||
int32_t WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info) override;
|
||||
int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) override;
|
||||
int32_t Stop() override;
|
||||
|
||||
int32_t DumpInfo(int32_t fd);
|
||||
void Release() override;
|
||||
int32_t DestroyStub() override;
|
||||
int32_t DumpInfo(int32_t fd);
|
||||
|
||||
private:
|
||||
AVMuxerStub();
|
||||
int32_t InitStub();
|
||||
int32_t Init(MessageParcel &data, MessageParcel &reply);
|
||||
MuxerServiceStub();
|
||||
int32_t Init();
|
||||
int32_t InitParameter(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t SetLocation(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t SetRotation(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t SetParameter(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t AddTrack(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t Start(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t WriteSampleBuffer(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t Stop(MessageParcel &data, MessageParcel &reply);
|
||||
|
||||
int32_t GetDumpInfo(std::string& dumpInfo);
|
||||
int32_t Release(MessageParcel &data, MessageParcel &reply);
|
||||
int32_t DestroyStub(MessageParcel &data, MessageParcel &reply);
|
||||
|
||||
std::mutex mutex_;
|
||||
std::shared_ptr<IAVMuxer> muxerServer_ = nullptr;
|
||||
std::shared_ptr<IMuxerService> muxerServer_ {nullptr};
|
||||
std::map<uint32_t, MuxerStubFunc> muxerFuncs_;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif
|
||||
#endif // MUXER_SERVICE_STUB_H
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* 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 "avmuxer_server.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_log.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVMuxerServer"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
std::shared_ptr<IAVMuxer> AVMuxerServer::Create()
|
||||
{
|
||||
std::shared_ptr<AVMuxerServer> muxerServer = std::make_shared<AVMuxerServer>();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer != nullptr, nullptr, "Muxer Service does not exist");
|
||||
int32_t ret = muxerServer->InitServer();
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Failed to init muxer server");
|
||||
return muxerServer;
|
||||
}
|
||||
|
||||
AVMuxerServer::AVMuxerServer()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
AVMuxerServer::~AVMuxerServer()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::InitServer()
|
||||
{
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::Init()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
// TODO:achieve it
|
||||
(void)latitude;
|
||||
(void)longitude;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::SetRotation(int32_t rotation)
|
||||
{
|
||||
// TODO:achieve it
|
||||
(void)rotation;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::SetParameter(const Format &generalFormat)
|
||||
{
|
||||
// TODO:achieve it
|
||||
(void)generalFormat;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::AddTrack(uint32_t &trackIndex, const Format &trackFormat)
|
||||
{
|
||||
// TODO:achieve it
|
||||
(void)trackIndex;
|
||||
(void)trackFormat;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::Start()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info)
|
||||
{
|
||||
// TODO:achieve it
|
||||
(void)trackIndex;
|
||||
(void)sampleBuffer;
|
||||
(void)info;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t AVMuxerServer::Stop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
118
services/services/muxer/server/muxer_server.cpp
Normal file
118
services/services/muxer/server/muxer_server.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 "muxer_server.h"
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_log.h"
|
||||
#include "ipc_skeleton.h"
|
||||
|
||||
namespace {
|
||||
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MuxerServer"};
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
std::shared_ptr<IMuxerService> MuxerServer::Create()
|
||||
{
|
||||
std::shared_ptr<MuxerServer> muxerServer = std::make_shared<MuxerServer>();
|
||||
CHECK_AND_RETURN_RET_LOG(muxerServer != nullptr, nullptr, "Muxer Service does not exist");
|
||||
return muxerServer;
|
||||
}
|
||||
|
||||
MuxerServer::MuxerServer()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
appUid_ = IPCSkeleton::GetCallingUid();
|
||||
appPid_ = IPCSkeleton::GetCallingPid();
|
||||
}
|
||||
|
||||
MuxerServer::~MuxerServer()
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
|
||||
muxerEngine_ = nullptr;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::InitParameter(int32_t fd, OutputFormat format)
|
||||
{
|
||||
muxerEngine_ = IMuxerEngineFactory::CreateMuxerEngine(appUid_, appPid_, fd, format);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "Create muxer engine failed");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::SetLocation(float latitude, float longitude)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "muxer engine does not exist");
|
||||
int32_t ret = muxerEngine_->SetLocation(latitude, longitude);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call SetLocation");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::SetRotation(int32_t rotation)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "muxer engine does not exist");
|
||||
int32_t ret = muxerEngine_->SetRotation(rotation);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call SetRotation");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "muxer engine does not exist");
|
||||
int32_t ret = muxerEngine_->AddTrack(trackIndex, trackDesc);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call AddTrack");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::Start()
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "muxer engine does not exist");
|
||||
int32_t ret = muxerEngine_->Start();
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call Start");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(sampleBuffer != nullptr, AVCS_ERR_INVALID_VAL, "sampleData is nullptr");
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "muxer engine does not exist");
|
||||
int32_t ret = muxerEngine_->WriteSampleBuffer(sampleBuffer, info);
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call WriteSampleBuffer");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::Stop()
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "muxer engine does not exist");
|
||||
int32_t ret = muxerEngine_->Stop();
|
||||
CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Failed to call Stop");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
void MuxerServer::Release()
|
||||
{
|
||||
CHECK_AND_RETURN_LOG(muxerEngine_ != nullptr, "muxer engine does not exist");
|
||||
(void)muxerEngine_->Stop();
|
||||
muxerEngine_ = nullptr;
|
||||
}
|
||||
|
||||
int32_t MuxerServer::DumpInfo(int32_t fd)
|
||||
{
|
||||
CHECK_AND_RETURN_RET_LOG(muxerEngine_ != nullptr, AVCS_ERR_INVALID_OPERATION, "muxer engine does not exist");
|
||||
return muxerEngine_->DumpInfo(fd);
|
||||
}
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -17,31 +17,32 @@
|
||||
#define MUXER_SERVER_H
|
||||
|
||||
#include <mutex>
|
||||
#include "i_avmuxer.h"
|
||||
#include "i_muxer_service.h"
|
||||
#include "i_muxer_engine.h"
|
||||
#include "nocopyable.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerServer : public IAVMuxer, public NoCopyable {
|
||||
namespace Media {
|
||||
class MuxerServer : public IMuxerService, public NoCopyable {
|
||||
public:
|
||||
static std::shared_ptr<IAVMuxer> Create();
|
||||
AVMuxerServer();
|
||||
~AVMuxerServer();
|
||||
static std::shared_ptr<IMuxerService> Create();
|
||||
MuxerServer();
|
||||
~MuxerServer();
|
||||
|
||||
int32_t Init() override;
|
||||
int32_t InitParameter(int32_t fd, OutputFormat format) override;
|
||||
int32_t SetLocation(float latitude, float longitude) override;
|
||||
int32_t SetRotation(int32_t rotation) override;
|
||||
int32_t SetParameter(const Format &generalFormat) override;
|
||||
int32_t AddTrack(uint32_t &trackIndex, const Format &trackFormat) override;
|
||||
int32_t AddTrack(int32_t &trackIndex, const MediaDescription &trackDesc) override;
|
||||
int32_t Start() override;
|
||||
int32_t WriteSampleBuffer(uint32_t trackIndex, const std::shared_ptr<AVSharedMemory> &sampleBuffer, AVCodecBufferInfo info) override;
|
||||
int32_t WriteSampleBuffer(std::shared_ptr<AVSharedMemory> sampleBuffer, const TrackSampleInfo &info) override;
|
||||
int32_t Stop() override;
|
||||
void Release() override;
|
||||
int32_t DumpInfo(int32_t fd);
|
||||
|
||||
private:
|
||||
int32_t InitServer();
|
||||
std::mutex mutex_;
|
||||
// std::shared_ptr<IAVMuxerEngine> avmuxerEngine_ = nullptr;
|
||||
// uint32_t trackNum_ = 0;
|
||||
std::shared_ptr<IMuxerEngine> muxerEngine_ = nullptr;
|
||||
int32_t appUid_ = 0;
|
||||
int32_t appPid_ = 0;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
@ -21,9 +21,6 @@
|
||||
#ifdef SUPPORT_DEMUXER
|
||||
#include "i_avdemuxer_service.h"
|
||||
#endif
|
||||
#ifdef SUPPORT_MUXER
|
||||
#include "i_avmuxer_service.h"
|
||||
#endif
|
||||
#ifdef SUPPORT_CODEC
|
||||
#include "i_standard_codec_service.h"
|
||||
#endif
|
||||
@ -165,33 +162,33 @@ int32_t AVCodecClient::DestroyDemuxerService(std::shared_ptr<IAVDemuxer> demuxer
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_MUXER
|
||||
std::shared_ptr<IAVMuxer> AVCodecClient::CreateMuxerService()
|
||||
std::shared_ptr<IMuxerService> AVCodecClient::CreateMuxerService()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!IsAlived()) {
|
||||
AVCODEC_LOGE("av_codec service does not exist.");
|
||||
AVCODEC_LOGE("avcodec service does not exist.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sptr<IRemoteObject> object = avCodecProxy_->GetSubSystemAbility(
|
||||
IStandardAVCodecService::AVCodecSystemAbility::AVCODEC_MUXER, listenerStub_->AsObject());
|
||||
CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "Muxer proxy object is nullptr.");
|
||||
CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "muxer proxy object is nullptr.");
|
||||
|
||||
sptr<IAVMuxerService> muxerProxy = iface_cast<IAVMuxerService>(object);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy != nullptr, nullptr, "Muxer proxy is nullptr.");
|
||||
sptr<IStandardMuxerService> muxerProxy = iface_cast<IStandardMuxerService>(object);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerProxy != nullptr, nullptr, "muxer proxy is nullptr.");
|
||||
|
||||
std::shared_ptr<AVMuxerClient> muxerClient = AVMuxerClient::Create(muxerProxy);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient != nullptr, nullptr, "Failed to create muxer client.");
|
||||
std::shared_ptr<MuxerClient> muxer = MuxerClient::Create(muxerProxy);
|
||||
CHECK_AND_RETURN_RET_LOG(muxer != nullptr, nullptr, "failed to create muxer client.");
|
||||
|
||||
muxerClientList_.push_back(muxerClient);
|
||||
return muxerClient;
|
||||
muxerClientList_.push_back(muxer);
|
||||
return muxer;
|
||||
}
|
||||
|
||||
int32_t AVCodecClient::DestroyMuxerService(std::shared_ptr<IAVMuxer> muxerClient)
|
||||
int32_t AVCodecClient::DestroyMuxerService(std::shared_ptr<IMuxerService> muxer)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
CHECK_AND_RETURN_RET_LOG(muxerClient != nullptr, AVCS_ERR_NO_MEMORY, "muxer client is nullptr.");
|
||||
muxerClientList_.remove(muxerClient);
|
||||
CHECK_AND_RETURN_RET_LOG(muxer != nullptr, AVCS_ERR_NO_MEMORY, "input muxer is nullptr.");
|
||||
muxerClientList_.remove(muxer);
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
#endif
|
||||
@ -237,7 +234,7 @@ sptr<IStandardAVCodecService> AVCodecClient::GetAVCodecProxy()
|
||||
CHECK_AND_RETURN_RET_LOG(samgr != nullptr, nullptr, "system ability manager is nullptr.");
|
||||
|
||||
sptr<IRemoteObject> object = nullptr;
|
||||
COLLIE_LISTEN(object = samgr->GetSystemAbility(OHOS::AVCODEC_SERVICE_ID),
|
||||
COLLIE_LISTEN(object = samgr->GetSystemAbility(OHOS::AV_CODEC_SERVICE_ID),
|
||||
"AVCodecClient::GetAVCodecProxy");
|
||||
CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "avcodec object is nullptr.");
|
||||
|
||||
@ -295,9 +292,9 @@ void AVCodecClient::DoAVCodecServerDied()
|
||||
#endif
|
||||
#ifdef SUPPORT_MUXER
|
||||
for (auto &it : muxerClientList_) {
|
||||
auto muxerClient = std::static_pointer_cast<AVMuxerClient>(it);
|
||||
if (muxerClient != nullptr) {
|
||||
muxerClient->AVCodecServerDied();
|
||||
auto muxer = std::static_pointer_cast<MuxerClient>(it);
|
||||
if (muxer != nullptr) {
|
||||
muxer->AVCodecServerDied();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -25,7 +25,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_MUXER
|
||||
#include "avmuxer_client.h"
|
||||
#include "muxer_client.h"
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_CODEC
|
||||
@ -51,8 +51,8 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_MUXER
|
||||
std::shared_ptr<IAVMuxer> CreateMuxerService() override;
|
||||
int32_t DestroyMuxerService(std::shared_ptr<IAVMuxer> muxerClient) override;
|
||||
std::shared_ptr<IMuxerService> CreateMuxerService() override;
|
||||
int32_t DestroyMuxerService(std::shared_ptr<IMuxerService> muxer) override;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_CODEC
|
||||
@ -80,7 +80,7 @@ private:
|
||||
std::list<std::shared_ptr<IAVDemuxer>> demuxerClientList_;
|
||||
#endif
|
||||
#ifdef SUPPORT_MUXER
|
||||
std::list<std::shared_ptr<IAVMuxer>> muxerClientList_;
|
||||
std::list<std::shared_ptr<IMuxerService>> muxerClientList_;
|
||||
#endif
|
||||
#ifdef SUPPORT_CODEC
|
||||
std::list<std::shared_ptr<ICodecService>> codecClientList_;
|
||||
|
@ -47,7 +47,7 @@ bool AVCodecParcel::Marshalling(MessageParcel &parcel, const Format &format)
|
||||
break;
|
||||
case FORMAT_TYPE_ADDR:
|
||||
(void)parcel.WriteInt32(static_cast<int32_t>(it->second.size));
|
||||
(void)parcel.WriteBuffer(reinterpret_cast<const void *>(it->second.addr), it->second.size);
|
||||
(void)parcel.WriteUnpadBuffer(reinterpret_cast<const void *>(it->second.addr), it->second.size);
|
||||
break;
|
||||
default:
|
||||
AVCODEC_LOGE("fail to Marshalling Key: %{public}s", it->first.c_str());
|
||||
@ -55,6 +55,7 @@ bool AVCodecParcel::Marshalling(MessageParcel &parcel, const Format &format)
|
||||
}
|
||||
AVCODEC_LOGD("success to Marshalling Key: %{public}s", it->first.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -82,7 +83,7 @@ bool AVCodecParcel::Unmarshalling(MessageParcel &parcel, Format &format)
|
||||
break;
|
||||
case FORMAT_TYPE_ADDR: {
|
||||
auto addrSize = parcel.ReadInt32();
|
||||
auto addr = parcel.ReadBuffer(static_cast<size_t>(addrSize));
|
||||
auto addr = parcel.ReadUnpadBuffer(static_cast<size_t>(addrSize));
|
||||
if (addr == nullptr) {
|
||||
AVCODEC_LOGE("fail to ReadBuffer Key: %{public}s", key.c_str());
|
||||
return false;
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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 I_STANDARD_AVCODEC_LISTENER_H
|
||||
#define I_STANDARD_AVCODEC_LISTENER_H
|
||||
|
||||
|
@ -26,7 +26,7 @@ constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVCodecSer
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
REGISTER_SYSTEM_ABILITY_BY_ID(AVCodecServer, AVCODEC_SERVICE_ID, true)
|
||||
REGISTER_SYSTEM_ABILITY_BY_ID(AVCodecServer, AV_CODEC_SERVICE_ID, true)
|
||||
AVCodecServer::AVCodecServer(int32_t systemAbilityId, bool runOnCreate) : SystemAbility(systemAbilityId, runOnCreate)
|
||||
{
|
||||
AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "avdemuxer_stub.h"
|
||||
#endif
|
||||
#ifdef SUPPORT_MUXER
|
||||
#include "avmuxer_stub.h"
|
||||
#include "muxer_service_stub.h"
|
||||
#endif
|
||||
#ifdef SUPPORT_SOURCE
|
||||
#include "source_service_stub.h"
|
||||
@ -100,10 +100,10 @@ int32_t AVCodecServerManager::Dump(int32_t fd, const std::vector<std::u16string>
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_MUXER
|
||||
dumpString += "------------------AVMuxerServer------------------\n";
|
||||
dumpString += "------------------MuxerServer------------------\n";
|
||||
if (WriteInfo(fd, dumpString, dumperTbl_[StubType::MUXER],
|
||||
argSets.find(u"muxer") != argSets.end()) != OHOS::NO_ERROR) {
|
||||
AVCODEC_LOGW("Failed to write AVMuxerServer information");
|
||||
AVCODEC_LOGW("Failed to write MuxerServer information");
|
||||
return OHOS::INVALID_OPERATION;
|
||||
}
|
||||
#endif
|
||||
@ -285,19 +285,19 @@ sptr<IRemoteObject> AVCodecServerManager::CreateMuxerStubObject()
|
||||
"Please release the applied resources.", muxerStubMap_.size());
|
||||
return nullptr;
|
||||
}
|
||||
sptr<AVMuxerStub> stub = AVMuxerStub::Create();
|
||||
if (stub == nullptr) {
|
||||
AVCODEC_LOGE("Failed to create AVMuxerStub");
|
||||
sptr<MuxerServiceStub> muxerStub = MuxerServiceStub::Create();
|
||||
if (muxerStub == nullptr) {
|
||||
AVCODEC_LOGE("Create MuxerServiceStub failed");
|
||||
return nullptr;
|
||||
}
|
||||
sptr<IRemoteObject> object = stub->AsObject();
|
||||
sptr<IRemoteObject> object = muxerStub->AsObject();
|
||||
if (object != nullptr) {
|
||||
pid_t pid = IPCSkeleton::GetCallingPid();
|
||||
muxerStubMap_[object] = pid;
|
||||
|
||||
Dumper dumper;
|
||||
dumper.entry_ = [stub](int32_t fd) -> int32_t {
|
||||
return stub->DumpInfo(fd);
|
||||
dumper.entry_ = [muxer = muxerStub](int32_t fd) -> int32_t {
|
||||
return muxer->DumpInfo(fd);
|
||||
};
|
||||
dumper.pid_ = pid;
|
||||
dumper.uid_ = IPCSkeleton::GetCallingUid();
|
||||
@ -379,7 +379,8 @@ void AVCodecServerManager::DestroyStubObject(StubType type, sptr<IRemoteObject>
|
||||
case MUXER: {
|
||||
auto it = find_if(muxerStubMap_.begin(), muxerStubMap_.end(), compare_func);
|
||||
if (it != muxerStubMap_.end()) {
|
||||
AVCODEC_LOGD("destroy muxer stub services(%{public}zu) pid(%{public}d).", muxerStubMap_.size(), pid);
|
||||
AVCODEC_LOGD("destroy muxer stub services(%{public}zu) pid(%{public}d).",
|
||||
muxerStubMap_.size(), pid);
|
||||
(void)muxerStubMap_.erase(it);
|
||||
return;
|
||||
}
|
||||
|
@ -146,19 +146,19 @@ int32_t SourceServiceStub::DumpInfo(int32_t fd)
|
||||
int32_t SourceServiceStub::Init(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
std::string uri = data.ReadString();
|
||||
CHECK_AND_RETURN_RET(reply.WriteInt32(Init(uri)), AVCS_ERR_UNKNOWN);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(Init(uri)), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t SourceServiceStub::GetTrackCount(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
CHECK_AND_RETURN_RET(reply.WriteInt32(GetTrackCount()), AVCS_ERR_UNKNOWN);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(GetTrackCount()), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t SourceServiceStub::Destroy(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
CHECK_AND_RETURN_RET(reply.WriteInt32(Destroy()), AVCS_ERR_UNKNOWN);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(Destroy()), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ int32_t SourceServiceStub::SetParameter(MessageParcel &data, MessageParcel &repl
|
||||
Format param;
|
||||
(void)AVCodecParcel::Unmarshalling(data, param);
|
||||
uint32_t trackId = data.ReadUint32();
|
||||
CHECK_AND_RETURN_RET(reply.WriteInt32(SetParameter(param, trackId)), AVCS_ERR_UNKNOWN);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(SetParameter(param, trackId)), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
@ -175,20 +175,20 @@ int32_t SourceServiceStub::GetTrackFormat(MessageParcel &data, MessageParcel &re
|
||||
{
|
||||
uint32_t trackId = data.ReadUint32();
|
||||
Format format;
|
||||
CHECK_AND_RETURN_RET(reply.WriteInt32(GetTrackFormat(format, trackId)), AVCS_ERR_UNKNOWN);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(GetTrackFormat(format, trackId)), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
AVCodecParcel::Marshalling(reply, format);
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t SourceServiceStub::GetSourceAttr(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
CHECK_AND_RETURN_RET(reply.WriteUint64(GetSourceAttr()), AVCS_ERR_UNKNOWN);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteUint64(GetSourceAttr()), AVCS_ERR_UNKNOWN, "WriteUint64 failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
int32_t SourceServiceStub::DestroyStub(MessageParcel &data, MessageParcel &reply)
|
||||
{
|
||||
CHECK_AND_RETURN_RET(reply.WriteInt32(DestroyStub()), AVCS_ERR_UNKNOWN);
|
||||
CHECK_AND_RETURN_RET_LOG(reply.WriteInt32(DestroyStub()), AVCS_ERR_UNKNOWN, "WriteInt32 failed!");
|
||||
return AVCS_ERR_OK;
|
||||
}
|
||||
|
||||
|
146
services/utils/include/block_queue.h
Normal file
146
services/utils/include/block_queue.h
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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 UTILS_BLOCK_QUEUE_H
|
||||
#define UTILS_BLOCK_QUEUE_H
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <queue>
|
||||
#include "avcodec_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace {
|
||||
constexpr size_t DEFAULT_QUEUE_SIZE = 10;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class BlockQueue {
|
||||
public:
|
||||
explicit BlockQueue(std::string name, size_t capacity = DEFAULT_QUEUE_SIZE)
|
||||
: name_(std::move(name)), capacity_(capacity), isActive_(true)
|
||||
{
|
||||
}
|
||||
|
||||
~BlockQueue() = default;
|
||||
|
||||
size_t Size()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
return que_.size();
|
||||
}
|
||||
|
||||
size_t Capacity()
|
||||
{
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
size_t Empty()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
return que_.empty();
|
||||
}
|
||||
|
||||
bool Push(const T& block)
|
||||
{
|
||||
AVCODEC_LOGD("block queue %{public}s Push enter.", name_.c_str());
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (!isActive_) {
|
||||
AVCODEC_LOGD("block queue %{public}s is inactive for Push.", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
if (que_.size() >= capacity_) {
|
||||
AVCODEC_LOGD("block queue %{public}s is full, please waiting for Pop.", name_.c_str());
|
||||
condFull_.wait(lock, [this] { return !isActive_ || que_.size() < capacity_; });
|
||||
}
|
||||
if (!isActive_) {
|
||||
AVCODEC_LOGD("block queue %{public}s: inactive: %{public}d, isFull: %{public}d.",
|
||||
name_.c_str(), isActive_.load(), que_.size() < capacity_);
|
||||
return false;
|
||||
}
|
||||
que_.push(block);
|
||||
condEmpty_.notify_one();
|
||||
AVCODEC_LOGD("block queue %{public}s Push ok.", name_.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
T Pop()
|
||||
{
|
||||
AVCODEC_LOGD("block queue %{public}s Pop enter.", name_.c_str());
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (que_.empty() && !isActive_) {
|
||||
AVCODEC_LOGD("block queue %{public}s is inactive for Pop.", name_.c_str());
|
||||
return {};
|
||||
} else if (que_.empty() && isActive_) {
|
||||
AVCODEC_LOGD("block queue %{public}s is empty, please waiting for Push.", name_.c_str());
|
||||
condEmpty_.wait(lock, [this] { return !isActive_ || !que_.empty(); });
|
||||
}
|
||||
if (que_.empty()) {
|
||||
AVCODEC_LOGD("block queue %{public}s: inactive: %{public}d, size: %{public}d.",
|
||||
name_.c_str(), isActive_.load(), que_.size());
|
||||
return {};
|
||||
}
|
||||
T element = que_.front();
|
||||
que_.pop();
|
||||
condFull_.notify_one();
|
||||
AVCODEC_LOGD("block queue %{public}s Pop ok.", name_.c_str());
|
||||
return element;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
ClearUnprotected();
|
||||
}
|
||||
|
||||
void SetActive(bool active, bool cleanData = true)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
AVCODEC_LOGD("SetActive %{public}s: %{public}d.", name_.c_str(), isActive_.load());
|
||||
isActive_ = active;
|
||||
if (!active) {
|
||||
if (cleanData) {
|
||||
ClearUnprotected();
|
||||
}
|
||||
condEmpty_.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void ClearUnprotected()
|
||||
{
|
||||
if (que_.empty()) {
|
||||
return;
|
||||
}
|
||||
bool needNotify = que_.size() == capacity_;
|
||||
std::queue<T>().swap(que_);
|
||||
if (needNotify) {
|
||||
condFull_.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex mutex_;
|
||||
std::condition_variable condFull_;
|
||||
std::condition_variable condEmpty_;
|
||||
std::queue<T> que_;
|
||||
std::string name_;
|
||||
const size_t capacity_;
|
||||
std::atomic<bool> isActive_;
|
||||
const OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "BlockQueue"};
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // !UTILS_BLOCK_QUEUE_H
|
@ -14,17 +14,21 @@
|
||||
import("//build/ohos.gni")
|
||||
import("//foundation/multimedia/av_codec/config.gni")
|
||||
|
||||
group("av_codec_demo_test") {
|
||||
testonly = true
|
||||
deps = []
|
||||
if (multimedia_av_codec_support_test) {
|
||||
deps += [ "nativedemo:av_codec_demo" ]
|
||||
}
|
||||
}
|
||||
|
||||
group("av_codec_unit_test") {
|
||||
testonly = true
|
||||
deps = []
|
||||
}
|
||||
|
||||
group("av_codec_fuzz_test") {
|
||||
testonly = true
|
||||
deps = []
|
||||
}
|
||||
|
||||
group("av_codec_demo_test") {
|
||||
testonly = true
|
||||
deps = [ "//foundation/multimedia/av_codec/test/nativedemo:av_codec_demo" ]
|
||||
if (multimedia_av_codec_support_test) {
|
||||
deps += [
|
||||
"unittest:av_muxer_unit_test",
|
||||
"unittest:format_unit_test",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -16,18 +16,21 @@ import("//foundation/multimedia/av_codec/config.gni")
|
||||
|
||||
ohos_executable("av_codec_demo") {
|
||||
include_dirs = [
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/avmuxer",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c",
|
||||
"//foundation/multimedia/av_codec/interfaces/inner_api/native",
|
||||
"//foundation/multimedia/av_codec/services/services/factory",
|
||||
"//foundation/multimedia/av_codec/services/engine/plugin/core",
|
||||
"//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",
|
||||
"//foundation/multimedia/av_codec/interfaces/inner_api/native",
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c",
|
||||
"//foundation/multimedia/av_codec/services/utils/include",
|
||||
"//foundation/multimedia/av_codec/services/dfx/include",
|
||||
]
|
||||
|
||||
cflags = [
|
||||
"-Wall",
|
||||
"-std=c++17",
|
||||
"-fno-rtti",
|
||||
"-fno-exceptions",
|
||||
"-fno-common",
|
||||
@ -48,15 +51,27 @@ ohos_executable("av_codec_demo") {
|
||||
"-Wno-deprecated-declarations",
|
||||
]
|
||||
|
||||
cflags_cc = cflags
|
||||
cflags_cc += ["-std=c++17"]
|
||||
|
||||
sources = [
|
||||
"./av_codec_demo.cpp",
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/av_codec_demo.cpp",
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/avmuxer/avmuxer_demo_base.cpp",
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/avmuxer/avmuxer_demo.cpp",
|
||||
"//foundation/multimedia/av_codec/test/nativedemo/avmuxer/avmuxer_engine_demo.cpp",
|
||||
"//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 = [
|
||||
"//foundation/multimedia/av_codec/interfaces/kits/c:native_av_codec_avmuxer",
|
||||
"//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"
|
||||
]
|
||||
|
||||
|
125
test/nativedemo/avmuxer/avmuxer_demo.cpp
Normal file
125
test/nativedemo/avmuxer/avmuxer_demo.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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 "avmuxer_demo.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "avcodec_errors.h"
|
||||
|
||||
namespace {
|
||||
extern "C" {
|
||||
extern char *RUN_NORMAL;
|
||||
extern char *RUN_MUL_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
|
||||
int AVMuxerDemo::DoWriteSampleBuffer(uint8_t *sampleBuffer, TrackSampleInfo &info)
|
||||
{
|
||||
if (avmuxer_ != nullptr &&
|
||||
avmuxer_->WriteSampleBuffer(sampleBuffer, info) == AVCS_ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AVMuxerDemo::DoAddTrack(int32_t &trackIndex, MediaDescription &trackDesc)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = avmuxer_->AddTrack(trackIndex, trackDesc)) != AVCS_ERR_OK) {
|
||||
std::cout<<"AVMuxerDemo::DoAddTrack failed! ret:"<<ret<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVMuxerDemo::DoRunMuxer(const std::string &runMode)
|
||||
{
|
||||
std::string outFileName = "mux_" + runMode + "_" + audioType_ + "_" + videoType_ + "_" + coverType_ + "." + format_;
|
||||
outFd_ = open(outFileName.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (outFd_ < 0) {
|
||||
std::cout << "Open file failed! filePath is: " << outFileName << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout<<"==== open success! =====\noutputFileName: "<<outFileName<<"\n============"<<std::endl;
|
||||
|
||||
avmuxer_ = AVMuxerFactory::CreateAVMuxer(outFd_, outputFormat_);
|
||||
if (avmuxer_ == nullptr) {
|
||||
std::cout << "avmuxer_ is null" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout << "create muxer success " << avmuxer_ << std::endl;
|
||||
|
||||
if (avmuxer_->SetLocation(10, 10) != AVCS_ERR_OK
|
||||
|| avmuxer_->SetRotation(0) != AVCS_ERR_OK) {
|
||||
std::cout<<"set failed!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
AddAudioTrack(audioParams_);
|
||||
AddVideoTrack(videoParams_);
|
||||
AddCoverTrack(coverParams_);
|
||||
|
||||
std::cout << "add track success" << std::endl;
|
||||
|
||||
if (avmuxer_->Start() != AVCS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "start muxer success" << std::endl;
|
||||
|
||||
if (coverParams_ != nullptr) {
|
||||
WriteCoverSample();
|
||||
}
|
||||
|
||||
std::cout<<"AVMuxerDemo::DoRunMuxer runMode is : "<<runMode<<std::endl;
|
||||
if (runMode.compare(RUN_NORMAL) == 0) {
|
||||
WriteTrackSample();
|
||||
} else if (runMode.compare(RUN_MUL_THREAD) == 0) {
|
||||
std::vector<std::thread> vecThread;
|
||||
vecThread.emplace_back(MulThdWriteTrackSample, this, audioTrackId_, audioFile_);
|
||||
vecThread.emplace_back(MulThdWriteTrackSample, this, videoTrackId_, videoFile_);
|
||||
for (uint32_t i = 0; i < vecThread.size(); ++i) {
|
||||
vecThread[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "write muxer success" << std::endl;
|
||||
|
||||
if (avmuxer_->Stop() != AVCS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
std::cout << "stop muxer success" << std::endl;
|
||||
}
|
||||
|
||||
void AVMuxerDemo::DoRunMuxer()
|
||||
{
|
||||
DoRunMuxer(std::string(RUN_NORMAL));
|
||||
}
|
||||
|
||||
void AVMuxerDemo::DoRunMultiThreadCase()
|
||||
{
|
||||
DoRunMuxer(std::string(RUN_MUL_THREAD));
|
||||
}
|
||||
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
38
test/nativedemo/avmuxer/avmuxer_demo.h
Normal file
38
test/nativedemo/avmuxer/avmuxer_demo.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 AVMUXER_DEMO_H
|
||||
#define AVMUXER_DEMO_H
|
||||
|
||||
#include "avmuxer.h"
|
||||
#include "avmuxer_demo_base.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerDemo /*: public NoCopyable*/ : public AVMuxerDemoBase {
|
||||
public:
|
||||
AVMuxerDemo() = default;
|
||||
~AVMuxerDemo() = default;
|
||||
private:
|
||||
void DoRunMuxer() override;
|
||||
int DoWriteSampleBuffer(uint8_t *sampleBuffer, TrackSampleInfo &info) override;
|
||||
int DoAddTrack(int32_t &trackIndex, MediaDescription &trackDesc) override;
|
||||
void DoRunMultiThreadCase() override;
|
||||
void DoRunMuxer(const std::string &runMode);
|
||||
std::shared_ptr<AVMuxer> avmuxer_;
|
||||
};
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // AVMUXER_DEMO_H
|
501
test/nativedemo/avmuxer/avmuxer_demo_base.cpp
Normal file
501
test/nativedemo/avmuxer/avmuxer_demo_base.cpp
Normal file
@ -0,0 +1,501 @@
|
||||
/*
|
||||
* 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 "avmuxer_demo_base.h"
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "avcodec_errors.h"
|
||||
#include "avcodec_common.h"
|
||||
|
||||
namespace {
|
||||
// constexpr uint32_t DATA_AUDIO_ID = 0;
|
||||
// constexpr uint32_t DATA_VIDEO_ID = 1;
|
||||
extern "C" {
|
||||
extern AudioTrackParam g_audioMpegPar;
|
||||
extern AudioTrackParam g_audioAacPar;
|
||||
extern VideoTrackParam g_videoH264Par;
|
||||
extern VideoTrackParam g_videoMpeg4Par;
|
||||
extern VideoTrackParam g_jpegCoverPar;
|
||||
extern VideoTrackParam g_pngCoverPar;
|
||||
extern VideoTrackParam g_bmpCoverPar;
|
||||
}
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
AVMuxerDemoBase::AVMuxerDemoBase()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<std::ifstream> OpenFile(const std::string &filePath)
|
||||
{
|
||||
auto file = std::make_shared<std::ifstream>();
|
||||
file->open(filePath, std::ios::in | std::ios::binary);
|
||||
if (file->is_open()) {
|
||||
return file;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int AVMuxerDemoBase::SelectMode()
|
||||
{
|
||||
// TODO:add muxer mode select
|
||||
int num;
|
||||
|
||||
std::cout<<"\nplease select muxer type: 0.mp4 1.m4a"<<std::endl;
|
||||
std::cin>>num;
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
format_ = "mp4";
|
||||
outputFormat_ = OUTPUT_FORMAT_MPEG_4;
|
||||
break;
|
||||
case 1:
|
||||
format_ = "m4a";
|
||||
outputFormat_ = OUTPUT_FORMAT_M4A;
|
||||
break;
|
||||
default:
|
||||
format_ = "mp4";
|
||||
outputFormat_ = OUTPUT_FORMAT_MPEG_4;
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout<<"\nplease select audio file: 0.noAudio 1.aac 2.mpeg"<<std::endl;
|
||||
std::cin>>num;
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
audioType_ = "noAudio";
|
||||
audioParams_ = nullptr;
|
||||
break;
|
||||
case 1:
|
||||
audioType_ = "aac";
|
||||
audioParams_ = &g_audioAacPar;
|
||||
break;
|
||||
case 2:
|
||||
audioType_ = "mpeg";
|
||||
audioParams_ = &g_audioMpegPar;
|
||||
break;
|
||||
default:
|
||||
videoType_ = "noAudio";
|
||||
audioParams_ = nullptr;
|
||||
std::cout<<"do not support audio type index: "<<num<<", set to noAudio"<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout<<"please select video file:0.noVideo 1.h264 2.mpeg4"<<std::endl;
|
||||
std::cin>>num;
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
videoType_ = "noVideo";
|
||||
videoParams_ = nullptr;
|
||||
break;
|
||||
case 1:
|
||||
videoType_ = "h264";
|
||||
videoParams_ = &g_videoH264Par;
|
||||
break;
|
||||
case 2:
|
||||
videoType_ = "mpeg4";
|
||||
videoParams_ = &g_videoMpeg4Par;
|
||||
break;
|
||||
default:
|
||||
videoType_ = "noVideo";
|
||||
videoParams_ = nullptr;
|
||||
std::cout<<"do not support video type index: "<<", set to noVideo"<<num<<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout<<"please select cover file:0.NoCover 1.jpg 2.png 3.bmp"<<std::endl;
|
||||
std::cin>>num;
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
coverType_ = "noCover";
|
||||
coverParams_ = nullptr;
|
||||
break;
|
||||
case 1:
|
||||
coverType_ = "jpg";
|
||||
coverParams_ = &g_jpegCoverPar;
|
||||
break;
|
||||
case 2:
|
||||
coverType_ = "png";
|
||||
coverParams_ = &g_pngCoverPar;
|
||||
break;
|
||||
case 3:
|
||||
coverType_ = "bmp";
|
||||
coverParams_ = &g_bmpCoverPar;
|
||||
break;
|
||||
default:
|
||||
coverType_ = "noCover";
|
||||
coverParams_ = nullptr;
|
||||
std::cout<<"do not support cover type index: "<<", set to noCover"<<num<<std::endl;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AVMuxerDemoBase::SelectModeAndOpenFile()
|
||||
{
|
||||
if (SelectMode() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (audioParams_ != nullptr) {
|
||||
audioFile_ = OpenFile(audioParams_->fileName);
|
||||
if (audioFile_ == nullptr) {
|
||||
std::cout<<"open audio file failed! file name:"<<audioParams_->fileName<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
std::cout<<"open audio file success! file name:"<<audioParams_->fileName<<std::endl;
|
||||
}
|
||||
|
||||
if (videoParams_ != nullptr) {
|
||||
videoFile_ = OpenFile(videoParams_->fileName);
|
||||
if (videoFile_ == nullptr) {
|
||||
std::cout<<"open video file failed! file name:"<<videoParams_->fileName<<std::endl;
|
||||
Reset();
|
||||
return -1;
|
||||
}
|
||||
std::cout<<"video file success! file name:"<<videoParams_->fileName<<std::endl;
|
||||
}
|
||||
|
||||
if (coverParams_ != nullptr) {
|
||||
coverFile_ = OpenFile(coverParams_->fileName);
|
||||
if (coverFile_ == nullptr) {
|
||||
std::cout<<"open cover file failed! file name:"<<coverParams_->fileName<<std::endl;
|
||||
Reset();
|
||||
return -1;
|
||||
}
|
||||
std::cout<<"cover file success! file name:"<<coverParams_->fileName<<std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::Reset()
|
||||
{
|
||||
if (outFd_ > 0) {
|
||||
close(outFd_);
|
||||
outFd_ = -1;
|
||||
}
|
||||
if (audioFile_ != nullptr) {
|
||||
audioFile_->close();
|
||||
audioFile_ = nullptr;
|
||||
}
|
||||
if (videoFile_ != nullptr) {
|
||||
videoFile_->close();
|
||||
videoFile_ = nullptr;
|
||||
}
|
||||
if (coverFile_ != nullptr) {
|
||||
coverFile_->close();
|
||||
coverFile_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::RunCase()
|
||||
{
|
||||
if (SelectModeAndOpenFile() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DoRunMuxer();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::RunMultiThreadCase()
|
||||
{
|
||||
std::cout<<"==== start AVMuxerDemoBase::RunMultiThreadCase ==="<<std::endl;
|
||||
if (SelectModeAndOpenFile() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DoRunMultiThreadCase();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::WriteSingleTrackSample(uint32_t trackId, std::shared_ptr<std::ifstream> file)
|
||||
{
|
||||
if (file == nullptr) {
|
||||
std::cout<<"AVMuxerDemoBase::WriteTrackSample file si nullptr"<<std::endl;
|
||||
return;
|
||||
}
|
||||
uint32_t flags = 0;
|
||||
uint32_t dataSize = 0;
|
||||
unsigned char *avMuxerDemoBuffer = nullptr;
|
||||
uint32_t avMuxerDemoBufferSize = 0;
|
||||
TrackSampleInfo info {trackId, 0, 0 ,0};
|
||||
while(1) {
|
||||
file->read((char *)&info.timeUs, sizeof(info.timeUs));
|
||||
if (file->eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
file->read((char *)&flags, sizeof(flags));
|
||||
if (file->eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
file->read((char *)&dataSize, sizeof(dataSize));
|
||||
if (file->eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != nullptr && dataSize > avMuxerDemoBufferSize) {
|
||||
delete [] avMuxerDemoBuffer;
|
||||
avMuxerDemoBuffer = nullptr;
|
||||
avMuxerDemoBufferSize = 0;
|
||||
}
|
||||
if (avMuxerDemoBuffer == nullptr) {
|
||||
avMuxerDemoBuffer = new unsigned char[dataSize];
|
||||
avMuxerDemoBufferSize = dataSize;
|
||||
}
|
||||
|
||||
file->read((char *)avMuxerDemoBuffer, dataSize);
|
||||
if(file->eof()) {
|
||||
break;
|
||||
}
|
||||
info.size = dataSize;
|
||||
|
||||
info.flags = 0;
|
||||
if (flags != 0) {
|
||||
info.flags |= AVCODEC_BUFFER_FLAG_SYNC_FRAME;
|
||||
}
|
||||
|
||||
// std::cout<<"tracker id:"<<trackId<<" pts:"<<info.pts<<std::endl;
|
||||
if (DoWriteSampleBuffer((uint8_t*)avMuxerDemoBuffer, info) != 0) {
|
||||
std::cout<<"DoWriteSampleBuffer failed!"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != nullptr) {
|
||||
delete[] avMuxerDemoBuffer;
|
||||
avMuxerDemoBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::WriteAvTrackSample()
|
||||
{
|
||||
if (audioFile_ == nullptr || videoFile_ == nullptr) {
|
||||
std::cout<<"AVMuxerDemoBase::WriteTrackSample audioFile_ or videoFile_ is nullptr!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
uint32_t dataSize = 0;
|
||||
uint32_t flags = 0;
|
||||
uint64_t audioPts = 0;
|
||||
uint64_t videoPts = 0;
|
||||
TrackSampleInfo info {0, 0, 0 ,0};
|
||||
std::shared_ptr<std::ifstream> curFile = nullptr;
|
||||
unsigned char *avMuxerDemoBuffer = nullptr;
|
||||
uint32_t avMuxerDemoBufferSize = 0;
|
||||
audioFile_->read((char *)&audioPts, sizeof(audioPts));
|
||||
if (audioFile_->eof()) {
|
||||
return;
|
||||
}
|
||||
videoFile_->read((char *)&videoPts, sizeof(videoPts));
|
||||
if (videoFile_->eof()) {
|
||||
return;
|
||||
}
|
||||
while (1) {
|
||||
if (audioPts > videoPts) {
|
||||
curFile = videoFile_;
|
||||
info.trackIndex = videoTrackId_;
|
||||
info.timeUs = videoPts;
|
||||
} else {
|
||||
curFile = audioFile_;
|
||||
info.trackIndex = audioTrackId_;
|
||||
info.timeUs = audioPts;
|
||||
}
|
||||
|
||||
curFile->read((char *)&flags, sizeof(flags));
|
||||
if (curFile->eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
curFile->read((char *)&dataSize, sizeof(dataSize));
|
||||
if (curFile->eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != nullptr && dataSize > avMuxerDemoBufferSize) {
|
||||
delete [] avMuxerDemoBuffer;
|
||||
avMuxerDemoBuffer = nullptr;
|
||||
avMuxerDemoBufferSize = 0;
|
||||
}
|
||||
if (avMuxerDemoBuffer == nullptr) {
|
||||
avMuxerDemoBuffer = new unsigned char[dataSize];
|
||||
avMuxerDemoBufferSize = dataSize;
|
||||
}
|
||||
curFile->read((char *)avMuxerDemoBuffer, dataSize);
|
||||
if(curFile->eof()) {
|
||||
break;
|
||||
}
|
||||
info.size = dataSize;
|
||||
|
||||
info.flags = 0;
|
||||
if (flags != 0) {
|
||||
info.flags |= AVCODEC_BUFFER_FLAG_SYNC_FRAME;
|
||||
}
|
||||
|
||||
if (DoWriteSampleBuffer((uint8_t*)avMuxerDemoBuffer, info) != 0) {
|
||||
std::cout<<"DoWriteSampleBuffer failed!"<<std::endl;
|
||||
}
|
||||
if (curFile == audioFile_) {
|
||||
audioFile_->read((char *)&audioPts, sizeof(audioPts));
|
||||
if (audioFile_->eof()) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
videoFile_->read((char *)&videoPts, sizeof(videoPts));
|
||||
if (videoFile_->eof()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != nullptr) {
|
||||
delete [] avMuxerDemoBuffer;
|
||||
avMuxerDemoBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::WriteTrackSample()
|
||||
{
|
||||
if (audioFile_ != nullptr && videoFile_ != nullptr && audioTrackId_ >= 0 && videoTrackId_ >= 0) {
|
||||
std::cout<<"AVMuxerDemoBase::WriteTrackSample write AUDIO and VIDEO sample"<<std::endl;
|
||||
std::cout<<"audio trackId:"<<audioTrackId_<<" video trackId:"<<videoTrackId_<<std::endl;
|
||||
WriteAvTrackSample();
|
||||
} else if (audioFile_ != nullptr && audioTrackId_ >= 0) {
|
||||
std::cout<<"AVMuxerDemoBase::WriteTrackSample write AUDIO sample"<<std::endl;
|
||||
WriteSingleTrackSample(audioTrackId_, audioFile_);
|
||||
} else if (videoFile_ != nullptr && videoTrackId_ >= 0) {
|
||||
std::cout<<"AVMuxerDemoBase::WriteTrackSample write VIDEO sample"<<std::endl;
|
||||
WriteSingleTrackSample(videoTrackId_, videoFile_);
|
||||
} else {
|
||||
std::cout<<"AVMuxerDemoBase::WriteTrackSample don't write AUDIO and VIDEO track!!"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::MulThdWriteTrackSample(AVMuxerDemoBase *muxerBase, uint32_t trackId, std::shared_ptr<std::ifstream> file)
|
||||
{
|
||||
muxerBase->WriteSingleTrackSample(trackId, file);
|
||||
}
|
||||
|
||||
void AVMuxerDemoBase::WriteCoverSample()
|
||||
{
|
||||
std::cout<<"AVMuxerDemoBase::WriteCoverSample"<<std::endl;
|
||||
if (coverFile_ == nullptr) {
|
||||
std::cout<<"AVMuxerDemoBase::WriteCoverSample coverFile_ is nullptr!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
TrackSampleInfo info {coverTrackId_, 0, 0 ,0};
|
||||
coverFile_->seekg(0, std::ios::end);
|
||||
info.size = coverFile_->tellg();
|
||||
coverFile_->seekg(0, std::ios::beg);
|
||||
if (info.size <= 0) {
|
||||
std::cout<<"AVMuxerDemoBase::WriteCoverSample coverFile_ size is 0!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char *avMuxerDemoBuffer = new unsigned char[info.size];
|
||||
coverFile_->read((char *)avMuxerDemoBuffer, info.size);
|
||||
if (DoWriteSampleBuffer((uint8_t*)avMuxerDemoBuffer, info) != AVCS_ERR_OK) {
|
||||
delete [] avMuxerDemoBuffer;
|
||||
std::cout<<"WriteCoverSample error"<<std::endl;
|
||||
return;
|
||||
}
|
||||
delete [] avMuxerDemoBuffer;
|
||||
}
|
||||
|
||||
int AVMuxerDemoBase::AddVideoTrack(VideoTrackParam *param)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
std::cout<<"AVMuxerDemoBase::AddVideoTrack video is not select!"<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
MediaDescription videoParams;
|
||||
videoParams.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, param->mimeType);
|
||||
videoParams.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, param->width);
|
||||
videoParams.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, param->height);
|
||||
|
||||
int extSize = 0;
|
||||
char buffer[100] {0};
|
||||
// fread(&extSize, sizeof(extSize), 1, g_avBinStrNewFd);
|
||||
videoFile_->read((char*)&extSize, sizeof(extSize));
|
||||
if (extSize > 0 && extSize < 100) {
|
||||
// fread(buffer, extSize, 1, g_avBinStrNewFd);
|
||||
videoFile_->read((char*)buffer, extSize);
|
||||
videoParams.PutBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, (uint8_t *)buffer, extSize);
|
||||
} else {
|
||||
std::cout<<"AVMuxerDemoBase::AddVideoTrack DoAddTrack failed!"<<std::endl;
|
||||
}
|
||||
|
||||
if (DoAddTrack(videoTrackId_, videoParams) != AVCS_ERR_OK) {
|
||||
return -1;
|
||||
}
|
||||
std::cout << "AVMuxerDemoBase::AddVideoTrack video trackId is: " << videoTrackId_ << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AVMuxerDemoBase::AddAudioTrack(AudioTrackParam *param)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
std::cout<<"AVMuxerDemoBase::AddAudioTrack audio is not select!"<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
MediaDescription audioParams;
|
||||
audioParams.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, param->mimeType);
|
||||
audioParams.PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, param->sampleRate);
|
||||
audioParams.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, param->channels);
|
||||
|
||||
int extSize = 0;
|
||||
char buffer[100] {0};
|
||||
audioFile_->read((char*)&extSize, sizeof(extSize));
|
||||
if (extSize > 0 && extSize < 100) {
|
||||
audioFile_->read((char*)buffer, extSize);
|
||||
audioParams.PutBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, (uint8_t *)buffer, extSize);
|
||||
} else {
|
||||
std::cout<<"AVMuxerDemoBase::AddAudioTrack error extSize:"<<extSize<<std::endl;
|
||||
}
|
||||
|
||||
if (DoAddTrack(audioTrackId_, audioParams) != 0) {
|
||||
std::cout<<"AVMuxerDemoBase::AddAudioTrack DoAddTrack failed!"<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
std::cout << "AVMuxerDemoBase::AddAudioTrack audio trackId is: " << audioTrackId_ << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AVMuxerDemoBase::AddCoverTrack(VideoTrackParam *param)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
std::cout<<"AVMuxerDemoBase::AddCoverTrack cover is not select!"<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
MediaDescription coverParams;
|
||||
coverParams.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, param->mimeType);
|
||||
coverParams.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, param->width);
|
||||
coverParams.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, param->height);
|
||||
|
||||
if (DoAddTrack(coverTrackId_, coverParams) != AVCS_ERR_OK) {
|
||||
return -1;
|
||||
}
|
||||
std::cout << "AVMuxerDemoBase::AddCoverTrack video trackId is: " << coverTrackId_ << std::endl;
|
||||
return 0;
|
||||
}
|
||||
} // Media
|
||||
} // OHOS
|
65
test/nativedemo/avmuxer/avmuxer_demo_base.h
Normal file
65
test/nativedemo/avmuxer/avmuxer_demo_base.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 AVMUXER_DEMO_BASE
|
||||
#define AVMUXER_DEMO_BASE
|
||||
|
||||
#include <string>
|
||||
#include "av_common.h"
|
||||
#include "media_description.h"
|
||||
#include "avmuxer_demo_common.h"
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerDemoBase {
|
||||
public:
|
||||
AVMuxerDemoBase();
|
||||
virtual ~AVMuxerDemoBase() = default;
|
||||
void RunCase();
|
||||
void RunMultiThreadCase();
|
||||
protected:
|
||||
virtual void DoRunMuxer() = 0;
|
||||
virtual void DoRunMultiThreadCase()= 0;
|
||||
virtual int DoWriteSampleBuffer(uint8_t *sampleBuffer, TrackSampleInfo &info) = 0;
|
||||
virtual int DoAddTrack(int32_t &trackIndex, MediaDescription &trackDesc) = 0;
|
||||
int AddVideoTrack(VideoTrackParam *param);
|
||||
int AddAudioTrack(AudioTrackParam *param);
|
||||
int AddCoverTrack(VideoTrackParam *param);
|
||||
void WriteTrackSample();
|
||||
void WriteAvTrackSample();
|
||||
void WriteSingleTrackSample(uint32_t trackId, std::shared_ptr<std::ifstream> file);
|
||||
void WriteCoverSample();
|
||||
int SelectMode();
|
||||
int SelectModeAndOpenFile();
|
||||
void Reset();
|
||||
static void MulThdWriteTrackSample(AVMuxerDemoBase *muxerBase, uint32_t trackId, std::shared_ptr<std::ifstream> file);
|
||||
|
||||
int32_t videoTrackId_ {-1};
|
||||
int32_t audioTrackId_ {-1};
|
||||
int32_t coverTrackId_ {-1};
|
||||
std::shared_ptr<std::ifstream> audioFile_ {nullptr};
|
||||
std::shared_ptr<std::ifstream> videoFile_ {nullptr};
|
||||
std::shared_ptr<std::ifstream> coverFile_ {nullptr};
|
||||
AudioTrackParam *audioParams_ {nullptr};
|
||||
VideoTrackParam *videoParams_ {nullptr};
|
||||
VideoTrackParam *coverParams_ {nullptr};
|
||||
std::string videoType_ = std::string("");
|
||||
std::string audioType_ = std::string("");
|
||||
std::string coverType_ = std::string("");
|
||||
std::string format_ = std::string("");
|
||||
int32_t outFd_ {-1};
|
||||
OutputFormat outputFormat_ {OUTPUT_FORMAT_MPEG_4};
|
||||
};
|
||||
} // Media
|
||||
} // OHOS
|
||||
#endif
|
68
test/nativedemo/avmuxer/avmuxer_demo_common.c
Normal file
68
test/nativedemo/avmuxer/avmuxer_demo_common.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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 "avmuxer_demo_common.h"
|
||||
|
||||
struct AudioTrackParam g_audioMpegPar = {
|
||||
.fileName = "mpeg_44100_2.bin",
|
||||
.mimeType = "audio/mpeg",
|
||||
.sampleRate = 44100,
|
||||
.channels = 2,
|
||||
};
|
||||
|
||||
struct AudioTrackParam g_audioAacPar = {
|
||||
.fileName = "aac_44100_2.bin",
|
||||
.mimeType = "audio/mp4a-latm",
|
||||
.sampleRate = 44100,
|
||||
.channels = 2,
|
||||
};
|
||||
|
||||
struct VideoTrackParam g_videoH264Par = {
|
||||
.fileName = "h264_640_360.bin",
|
||||
.mimeType = "video/avc",
|
||||
.width = 640,
|
||||
.height = 360,
|
||||
};
|
||||
|
||||
struct VideoTrackParam g_videoMpeg4Par = {
|
||||
.fileName = "mpeg4_720_480.bin",
|
||||
.mimeType = "video/mp4v-es",
|
||||
.width = 720,
|
||||
.height = 480,
|
||||
};
|
||||
|
||||
struct VideoTrackParam g_jpegCoverPar = {
|
||||
.fileName = "greatwall.jpg",
|
||||
.mimeType = "image/jpeg",
|
||||
.width = 352,
|
||||
.height = 288,
|
||||
};
|
||||
|
||||
struct VideoTrackParam g_pngCoverPar = {
|
||||
.fileName = "greatwall.png",
|
||||
.mimeType = "image/png",
|
||||
.width = 352,
|
||||
.height = 288,
|
||||
};
|
||||
|
||||
struct VideoTrackParam g_bmpCoverPar = {
|
||||
.fileName = "greatwall.bmp",
|
||||
.mimeType = "image/bmp",
|
||||
.width = 352,
|
||||
.height = 288,
|
||||
};
|
||||
|
||||
const char *RUN_NORMAL = "normal";
|
||||
const char *RUN_MUL_THREAD = "multhrd";
|
42
test/nativedemo/avmuxer/avmuxer_demo_common.h
Normal file
42
test/nativedemo/avmuxer/avmuxer_demo_common.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 AVMUXER_DEMO_COMMON_H
|
||||
#define AVMUXER_DEMO_COMMON_H
|
||||
|
||||
// only for demo
|
||||
typedef struct AudioTrackParam {
|
||||
const char *fileName;
|
||||
const char *mimeType;
|
||||
int sampleRate;
|
||||
int channels;
|
||||
} AudioTrackParam;
|
||||
|
||||
typedef struct VideoTrackParam {
|
||||
const char *fileName;
|
||||
const char *mimeType;
|
||||
int width;
|
||||
int height;
|
||||
} VideoTrackParam;
|
||||
|
||||
typedef struct FdListStr {
|
||||
int start[0];
|
||||
int outputFd;
|
||||
int inAudioFd;
|
||||
int inVideoFd;
|
||||
int inCoverFd;
|
||||
} FdListStr;
|
||||
|
||||
#endif
|
139
test/nativedemo/avmuxer/avmuxer_engine_demo.cpp
Normal file
139
test/nativedemo/avmuxer/avmuxer_engine_demo.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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 "avmuxer_engine_demo.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include "securec.h"
|
||||
#include "avcodec_errors.h"
|
||||
#include "avsharedmemorybase.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
|
||||
namespace {
|
||||
extern "C" {
|
||||
extern char *RUN_NORMAL;
|
||||
extern char *RUN_MUL_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
int AVMuxerEngineDemo::DoWriteSampleBuffer(uint8_t *sampleBuffer, TrackSampleInfo &info)
|
||||
{
|
||||
std::shared_ptr<AVSharedMemoryBase> sharedSampleBuffer =
|
||||
std::make_shared<AVSharedMemoryBase>(info.size, AVSharedMemory::FLAGS_READ_ONLY, "sampleBuffer");
|
||||
int32_t ret = sharedSampleBuffer->Init();
|
||||
if (ret != AVCS_ERR_OK) {
|
||||
std::cout<<"AVMuxerEngineDemo::DoWriteSampleBuffer shared memory Init failed!"<<std::endl;
|
||||
}
|
||||
|
||||
errno_t rc = memcpy_s(sharedSampleBuffer->GetBase(), sharedSampleBuffer->GetSize(), sampleBuffer, info.size);
|
||||
if (rc != EOK) {
|
||||
std::cout<<"AVMuxerEngineDemo::DoWriteSampleBuffer memcpy_s failed!"<<std::endl;
|
||||
}
|
||||
|
||||
if (avmuxer_ != nullptr &&
|
||||
avmuxer_->WriteSampleBuffer(sharedSampleBuffer, info) == AVCS_ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AVMuxerEngineDemo::DoAddTrack(int32_t &trackIndex, MediaDescription &trackDesc)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = avmuxer_->AddTrack(trackIndex, trackDesc)) != AVCS_ERR_OK) {
|
||||
std::cout<<"AVMuxerDemo::DoAddTrack failed! ret:"<<ret<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVMuxerEngineDemo::DoRunMuxer(const std::string &runMode)
|
||||
{
|
||||
std::string outFileName = "engine_mux_" + runMode + "_" + audioType_ + "_" + videoType_ + "_" + coverType_ + "." + format_;
|
||||
outFd_ = open(outFileName.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (outFd_ < 0) {
|
||||
std::cout << "Open file failed! filePath is: " << outFileName << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout<<"==== open success! =====\noutputFileName: "<<outFileName<<"\n============"<<std::endl;
|
||||
|
||||
avmuxer_ = IMuxerEngineFactory::CreateMuxerEngine(-1, -1, outFd_, outputFormat_);
|
||||
if (avmuxer_ == nullptr) {
|
||||
std::cout << "avmuxer_ is null" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout << "create muxer success " << avmuxer_ << std::endl;
|
||||
|
||||
if (avmuxer_->SetLocation(10, 10) != AVCS_ERR_OK
|
||||
|| avmuxer_->SetRotation(0) != AVCS_ERR_OK) {
|
||||
std::cout<<"set failed!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
AddAudioTrack(audioParams_);
|
||||
AddVideoTrack(videoParams_);
|
||||
AddCoverTrack(coverParams_);
|
||||
|
||||
std::cout << "add track success" << std::endl;
|
||||
|
||||
if (avmuxer_->Start() != AVCS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "start muxer success" << std::endl;
|
||||
|
||||
if (coverParams_ != nullptr) {
|
||||
WriteCoverSample();
|
||||
}
|
||||
|
||||
std::cout<<"AVMuxerDemo::DoRunMuxer runMode is : "<<runMode<<std::endl;
|
||||
if (runMode.compare(RUN_NORMAL) == 0) {
|
||||
WriteTrackSample();
|
||||
} else if (runMode.compare(RUN_MUL_THREAD) == 0) {
|
||||
std::vector<std::thread> vecThread;
|
||||
vecThread.emplace_back(MulThdWriteTrackSample, this, audioTrackId_, audioFile_);
|
||||
vecThread.emplace_back(MulThdWriteTrackSample, this, videoTrackId_, videoFile_);
|
||||
for (uint32_t i = 0; i < vecThread.size(); ++i) {
|
||||
vecThread[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "write muxer success" << std::endl;
|
||||
|
||||
if (avmuxer_->Stop() != AVCS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
std::cout << "stop muxer success" << std::endl;
|
||||
}
|
||||
|
||||
void AVMuxerEngineDemo::DoRunMuxer()
|
||||
{
|
||||
DoRunMuxer(std::string(RUN_NORMAL));
|
||||
}
|
||||
|
||||
void AVMuxerEngineDemo::DoRunMultiThreadCase()
|
||||
{
|
||||
DoRunMuxer(std::string(RUN_MUL_THREAD));
|
||||
}
|
||||
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
38
test/nativedemo/avmuxer/avmuxer_engine_demo.h
Normal file
38
test/nativedemo/avmuxer/avmuxer_engine_demo.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 AVMUXER_ENGINE_DEMO_H
|
||||
#define AVMUXER_ENGINE_DEMO_H
|
||||
|
||||
#include "avmuxer_demo_base.h"
|
||||
#include "i_muxer_engine.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
class AVMuxerEngineDemo /*: public NoCopyable*/ : public AVMuxerDemoBase {
|
||||
public:
|
||||
AVMuxerEngineDemo() = default;
|
||||
~AVMuxerEngineDemo() = default;
|
||||
private:
|
||||
void DoRunMuxer() override;
|
||||
int DoWriteSampleBuffer(uint8_t *sampleBuffer, TrackSampleInfo &info) override;
|
||||
int DoAddTrack(int32_t &trackIndex, MediaDescription &trackDesc) override;
|
||||
void DoRunMultiThreadCase() override;
|
||||
void DoRunMuxer(const std::string &runMode);
|
||||
std::shared_ptr<IMuxerEngine> avmuxer_;
|
||||
};
|
||||
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // AVMUXER_DEMO_H
|
153
test/nativedemo/avmuxer/avmuxer_ffmpeg_demo.cpp
Normal file
153
test/nativedemo/avmuxer/avmuxer_ffmpeg_demo.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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 "avmuxer_ffmpeg_demo.h"
|
||||
#include <dlfcn.h>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
const char *FFMPEG_REGISTER_FUNC_NAME = "register_FFmpegMuxer";
|
||||
const char *FFMPEG_UNREGISTER_FUNC_NAME = "unregister_FFmpegMuxer";
|
||||
const char *FFMPEG_LIB_PATH = "/system/lib/media/av_codec_plugins/libav_codec_plugin_FFmpegMuxer.z.so";
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
Status AVMuxerFFmpegDemo::FfmpegRegister::AddPlugin(const PluginDefBase& def)
|
||||
{
|
||||
auto& tempDef = (MuxerPluginDef&)def;
|
||||
std::cout<<"find plugin apiVersion:"<<tempDef.apiVersion;
|
||||
std::cout<<" |pluginType:"<<(int32_t)tempDef.pluginType;
|
||||
std::cout<<" |name:"<<tempDef.name;
|
||||
std::cout<<" |description:"<<tempDef.description;
|
||||
std::cout<<" |rank:"<<tempDef.rank;
|
||||
std::cout<<" |sniffer:"<<(void*)tempDef.sniffer;
|
||||
std::cout<<" |creator:"<<(void*)tempDef.creator;
|
||||
std::cout<<std::endl;
|
||||
plugins.push_back(tempDef);
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
|
||||
AVMuxerFFmpegDemo::AVMuxerFFmpegDemo()
|
||||
{
|
||||
register_ = std::make_shared<FfmpegRegister>();
|
||||
}
|
||||
|
||||
int AVMuxerFFmpegDemo::DoAddTrack(int32_t &trackIndex, MediaDescription ¶m)
|
||||
{
|
||||
int32_t tempTrackId = 0;
|
||||
ffmpegMuxer_->AddTrack(tempTrackId, param);
|
||||
if (tempTrackId < 0) {
|
||||
std::cout<<"AVMuxerFFmpegDemo::DoAddTrack failed! trackId:"<<tempTrackId<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
trackIndex = tempTrackId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVMuxerFFmpegDemo::DoRunMuxer()
|
||||
{
|
||||
GetFfmpegRegister();
|
||||
if (register_->plugins.size() <= 0) {
|
||||
std::cout<<"regist muxers failed!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t maxProb = 0;
|
||||
MuxerPluginDef pluginDef{};
|
||||
for (auto& plugin : register_->plugins) {
|
||||
if (plugin.pluginType == PluginType::MUXER) {
|
||||
auto prob = plugin.sniffer(plugin.name, outputFormat_);
|
||||
if (prob > maxProb) {
|
||||
maxProb = prob;
|
||||
pluginDef = plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginDef.creator == nullptr) {
|
||||
std::cout<<"no plugins matching output format - "<< outputFormat_ <<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string outFileName = "ffmpeg_mux_" + audioType_ + "_" + videoType_ + "_" + coverType_ + "." + format_;
|
||||
outFd_ = open(outFileName.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (outFd_ < 0) {
|
||||
std::cout<<"create muxer output file failed! fd:"<<outFd_<<std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout<<"==== open success! =====\noutputFileName: "<<outFileName<<"\n============"<<std::endl;
|
||||
|
||||
ffmpegMuxer_ = pluginDef.creator(pluginDef.name, outFd_);
|
||||
if (ffmpegMuxer_ == nullptr) {
|
||||
std::cout<<"ffmpegMuxer create failed!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
ffmpegMuxer_->SetLocation(10, 10);
|
||||
ffmpegMuxer_->SetRotation(90);
|
||||
|
||||
AddAudioTrack(audioParams_);
|
||||
AddVideoTrack(videoParams_);
|
||||
|
||||
ffmpegMuxer_->Start();
|
||||
WriteTrackSample();
|
||||
ffmpegMuxer_->Stop();
|
||||
}
|
||||
|
||||
void AVMuxerFFmpegDemo::DoRunMultiThreadCase()
|
||||
{
|
||||
std::cout<<"ffmpeg plugin demo is not support multi-thread write!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int AVMuxerFFmpegDemo::DoWriteSampleBuffer(uint8_t *sampleBuffer, TrackSampleInfo &info)
|
||||
{
|
||||
if(ffmpegMuxer_ != nullptr &&
|
||||
ffmpegMuxer_->WriteSampleBuffer(sampleBuffer, info) == Status::NO_ERROR) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AVMuxerFFmpegDemo::GetFfmpegRegister()
|
||||
{
|
||||
dlHandle_ = ::dlopen(FFMPEG_LIB_PATH, RTLD_NOW | RTLD_LOCAL);
|
||||
if (dlHandle_ == nullptr) {
|
||||
std::cout<<"AVMuxerFFmpegDemo::GetFfmpegRegister dlHandle_ is nullptr!"<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
registerFunc_ = (RegisterFunc)(::dlsym(dlHandle_, FFMPEG_REGISTER_FUNC_NAME));
|
||||
unregisterFunc_ = (UnregisterFunc)(::dlsym(dlHandle_, FFMPEG_UNREGISTER_FUNC_NAME));
|
||||
if (registerFunc_ == nullptr || unregisterFunc_ == nullptr) {
|
||||
std::cout<<"get dl function failed! registerFunc_:"<<(void*)registerFunc_;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((int32_t)registerFunc_(register_) != 0) {
|
||||
std::cout<<"ffmpeg register failed!"<<std::endl;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
58
test/nativedemo/avmuxer/avmuxer_ffmpeg_demo.h
Normal file
58
test/nativedemo/avmuxer/avmuxer_ffmpeg_demo.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 AVMUXER_FFMPEG_DEMO_H
|
||||
#define AVMUXER_FFMPEG_DEMO_H
|
||||
|
||||
#include <vector>
|
||||
#include "avmuxer.h"
|
||||
#include "muxer_plugin.h"
|
||||
#include "avmuxer_demo_base.h"
|
||||
#include "plugin_definition.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Media {
|
||||
namespace Plugin {
|
||||
|
||||
class AVMuxerFFmpegDemo /*: public NoCopyable*/ : public AVMuxerDemoBase {
|
||||
public:
|
||||
AVMuxerFFmpegDemo();
|
||||
~AVMuxerFFmpegDemo() = default;
|
||||
private:
|
||||
struct FfmpegRegister : PackageRegister {
|
||||
Status AddPlugin(const PluginDefBase& def) override;
|
||||
Status AddPackage(const PackageDef& def) override {
|
||||
(void)def;
|
||||
return Status::NO_ERROR;
|
||||
}
|
||||
std::vector<MuxerPluginDef> plugins;
|
||||
};
|
||||
|
||||
void DoRunMuxer() override;
|
||||
int GetFfmpegRegister();
|
||||
int DoWriteSampleBuffer(uint8_t *sampleBuffer, TrackSampleInfo &info) override;
|
||||
int DoAddTrack(int32_t &trackIndex, MediaDescription &trackDesc) override;
|
||||
void DoRunMultiThreadCase() override;
|
||||
|
||||
std::shared_ptr<MuxerPlugin> ffmpegMuxer_ {nullptr};
|
||||
std::shared_ptr<FfmpegRegister> register_ {nullptr};
|
||||
void *dlHandle_ {nullptr};
|
||||
RegisterFunc registerFunc_ {nullptr};
|
||||
UnregisterFunc unregisterFunc_ {nullptr};
|
||||
};
|
||||
} // Plugin
|
||||
} // namespace Media
|
||||
} // namespace OHOS
|
||||
#endif // AVMUXER_FFMPEG_DEMO_H
|
665
test/nativedemo/avmuxer/native_avmuxer_demo.c
Normal file
665
test/nativedemo/avmuxer/native_avmuxer_demo.c
Normal file
@ -0,0 +1,665 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "securec.h"
|
||||
#include "native_avcodec_base.h"
|
||||
#include "native_averrors.h"
|
||||
#include "native_avformat.h"
|
||||
#include "native_avmuxer.h"
|
||||
#include "avmuxer_demo_common.h"
|
||||
|
||||
|
||||
#define NORMAL 0
|
||||
#define THREAD 1
|
||||
|
||||
struct WriteTrackSampleParam {
|
||||
OH_AVMuxer *muxer;
|
||||
int trackId;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct MuxerParam {
|
||||
int outputFormat;
|
||||
char outputFormatType[20];
|
||||
int runMode;
|
||||
char runModeType[20];
|
||||
AudioTrackParam *audioParams;
|
||||
char audioType[20];
|
||||
VideoTrackParam *videoParams;
|
||||
char videoType[20];
|
||||
VideoTrackParam *coverParams;
|
||||
char coverType[20];
|
||||
};
|
||||
|
||||
extern char *RUN_NORMAL;
|
||||
extern char *RUN_MUL_THREAD;
|
||||
extern AudioTrackParam g_audioMpegPar;
|
||||
extern AudioTrackParam g_audioAacPar;
|
||||
extern VideoTrackParam g_videoH264Par;
|
||||
extern VideoTrackParam g_videoMpeg4Par;
|
||||
extern VideoTrackParam g_jpegCoverPar;
|
||||
extern VideoTrackParam g_pngCoverPar;
|
||||
extern VideoTrackParam g_bmpCoverPar;
|
||||
|
||||
static struct MuxerParam g_muxerParam = {
|
||||
.outputFormat = AV_OUTPUT_FORMAT_UNKNOWN,
|
||||
.outputFormatType = "",
|
||||
.runMode = NORMAL,
|
||||
.runModeType = "",
|
||||
.audioParams = NULL,
|
||||
.audioType = "",
|
||||
.videoParams = NULL,
|
||||
.videoType = "",
|
||||
.coverParams = NULL,
|
||||
.coverType = "",
|
||||
};
|
||||
|
||||
int AddTrackAudio(OH_AVMuxer *muxer, const AudioTrackParam *param, int fdInput)
|
||||
{
|
||||
if (fdInput < 0) {
|
||||
printf("unselect audio, fd is %d\n", fdInput);
|
||||
return -1;
|
||||
}
|
||||
OH_AVFormat *formatAudio = OH_AVFormat_Create();
|
||||
if (formatAudio == NULL) {
|
||||
printf("audio format failed!\n");
|
||||
return AV_ERR_NO_MEMORY;
|
||||
}
|
||||
int extraSize = 0;
|
||||
unsigned char buffer[100] = {0};
|
||||
read(fdInput, (void*)&extraSize, sizeof(extraSize));
|
||||
if (extraSize <= 100 && extraSize > 0) {
|
||||
read(fdInput, buffer, extraSize);
|
||||
OH_AVFormat_SetBuffer(formatAudio, OH_MD_KEY_CODEC_CONFIG, buffer, extraSize);
|
||||
}
|
||||
printf("AddTrackAudio audio metadata size: %d\n", extraSize);
|
||||
OH_AVFormat_SetStringValue(formatAudio, OH_MD_KEY_CODEC_MIME, param->mimeType);
|
||||
OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_SAMPLE_RATE, param->sampleRate);
|
||||
OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_CHANNEL_COUNT, param->channels);
|
||||
int trackIndex = -1;
|
||||
int ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, formatAudio);
|
||||
OH_AVFormat_Destroy(formatAudio);
|
||||
if (ret != AV_ERR_OK) {
|
||||
printf("AddTrackAudio failed! mime: %s\n", param->mimeType);
|
||||
return -1;
|
||||
}
|
||||
printf("AddTrackAudio success! trackIndex: %d\n", trackIndex);
|
||||
return trackIndex;
|
||||
}
|
||||
|
||||
int AddTrackVideo(OH_AVMuxer *muxer, const VideoTrackParam *param, int fdInput)
|
||||
{
|
||||
if (fdInput < 0) {
|
||||
printf("unselect video, fd is %d\n", fdInput);
|
||||
return -1;
|
||||
}
|
||||
OH_AVFormat *formatVideo = OH_AVFormat_Create();
|
||||
if (formatVideo == NULL) {
|
||||
printf("video format failed!\n");
|
||||
return AV_ERR_NO_MEMORY;
|
||||
}
|
||||
int extraSize = 0;
|
||||
unsigned char buffer[100] = {0};
|
||||
read(fdInput, (void*)&extraSize, sizeof(extraSize));
|
||||
if (extraSize <= 100 && extraSize > 0) {
|
||||
read(fdInput, buffer, extraSize);
|
||||
OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, extraSize);
|
||||
}
|
||||
printf("AddTrackVideo video metadata size: %d\n", extraSize);
|
||||
OH_AVFormat_SetStringValue(formatVideo, OH_MD_KEY_CODEC_MIME, param->mimeType);
|
||||
OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_WIDTH, param->width);
|
||||
OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_HEIGHT, param->height);
|
||||
int trackIndex = -1;
|
||||
int ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, formatVideo);
|
||||
OH_AVFormat_Destroy(formatVideo);
|
||||
if (ret != AV_ERR_OK) {
|
||||
printf("AddTrackVideo failed! mime: %s\n", param->mimeType);
|
||||
return -1;
|
||||
}
|
||||
printf("AddTrackVideo success! trackIndex: %d\n", trackIndex);
|
||||
return trackIndex;
|
||||
}
|
||||
|
||||
int AddTrackCover(OH_AVMuxer *muxer, const VideoTrackParam *param, int fdInput)
|
||||
{
|
||||
if (fdInput < 0) {
|
||||
printf("unselect cover, fd is %d\n", fdInput);
|
||||
return -1;
|
||||
}
|
||||
|
||||
OH_AVFormat *formatCover = OH_AVFormat_Create();
|
||||
if (formatCover == NULL) {
|
||||
printf("cover format failed!\n");
|
||||
return AV_ERR_NO_MEMORY;
|
||||
}
|
||||
OH_AVFormat_SetStringValue(formatCover, OH_MD_KEY_CODEC_MIME, param->mimeType);
|
||||
OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_WIDTH, param->width);
|
||||
OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_HEIGHT, param->height);
|
||||
int trackIndex = -1;
|
||||
int ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, formatCover);
|
||||
OH_AVFormat_Destroy(formatCover);
|
||||
if (ret != AV_ERR_OK) {
|
||||
printf("AddTrackCover failed! mime: %s\n", param->mimeType);
|
||||
return -1;
|
||||
}
|
||||
printf("AddTrackCover success! trackIndex: %d\n", trackIndex);
|
||||
return trackIndex;
|
||||
}
|
||||
|
||||
void WriteSingleTrackSample(OH_AVMuxer *muxer, int trackId, int fd)
|
||||
{
|
||||
if (muxer == NULL || fd < 0 || trackId < 0) {
|
||||
printf("WriteSingleTrackSample muxer is null or fd < 0, fd:%d\n", fd);
|
||||
return;
|
||||
}
|
||||
int ret = 0;
|
||||
int dataSize = 0;
|
||||
int flags = 0;
|
||||
unsigned char *avMuxerDemoBuffer = NULL;
|
||||
int avMuxerDemoBufferSize = 0;
|
||||
OH_AVCodecBufferAttr info;
|
||||
memset_s(&info, sizeof(info), 0, sizeof(info));
|
||||
while (1) {
|
||||
ret = read(fd, (void*)&info.pts, sizeof(info.pts));
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = read(fd, (void*)&flags, sizeof(flags));
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// read frame buffer
|
||||
ret = read(fd, (void*)&dataSize, sizeof(dataSize));
|
||||
if (ret <= 0 || dataSize < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != NULL && dataSize > avMuxerDemoBufferSize) {
|
||||
free(avMuxerDemoBuffer);
|
||||
avMuxerDemoBufferSize = 0;
|
||||
avMuxerDemoBuffer = NULL;
|
||||
}
|
||||
if (avMuxerDemoBuffer == NULL) {
|
||||
avMuxerDemoBuffer = malloc(dataSize);
|
||||
avMuxerDemoBufferSize = dataSize;
|
||||
if (avMuxerDemoBuffer == NULL) {
|
||||
printf("error malloc memory! %d\n", dataSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = read(fd, (void*)avMuxerDemoBuffer, dataSize);
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
info.size = dataSize;
|
||||
|
||||
info.flags = 0;
|
||||
if (flags != 0) {
|
||||
info.flags |= AVCODEC_BUFFER_FLAGS_SYNC_FRAME;
|
||||
}
|
||||
|
||||
if (OH_AVMuxer_WriteSampleBuffer(muxer, trackId, avMuxerDemoBuffer, info) != AV_ERR_OK) {
|
||||
printf("OH_AVMuxer_WriteSampleBuffer error!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != NULL) {
|
||||
free(avMuxerDemoBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void *ThreadWriteTrackSample(void *param)
|
||||
{
|
||||
struct WriteTrackSampleParam *wrTrackParam = (struct WriteTrackSampleParam *)param;
|
||||
WriteSingleTrackSample(wrTrackParam->muxer, wrTrackParam->trackId, wrTrackParam->fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void WriteTrackSample(OH_AVMuxer *muxer, int audioTrackIndex, int videoTrackIndex, FdListStr *fdStr)
|
||||
{
|
||||
if (fdStr == NULL || fdStr->inAudioFd < 0 || fdStr->inVideoFd < 0) {
|
||||
printf("WriteTrackSample start failed!\n");
|
||||
return;
|
||||
}
|
||||
printf("WriteTrackSample\n");
|
||||
int dataSize = 0;
|
||||
int ret = 0;
|
||||
int trackId = 0;
|
||||
int curFd = 0;
|
||||
int flags = 0;
|
||||
int64_t audioPts = 0;
|
||||
int64_t videoPts = 0;
|
||||
OH_AVCodecBufferAttr info;
|
||||
memset_s(&info, sizeof(info), 0, sizeof(info));
|
||||
unsigned char *avMuxerDemoBuffer = NULL;
|
||||
int avMuxerDemoBufferSize = 0;
|
||||
|
||||
ret = read(fdStr->inAudioFd, (void*)&audioPts, sizeof(audioPts));
|
||||
if (ret <= 0) {
|
||||
return;
|
||||
}
|
||||
ret = read(fdStr->inVideoFd, (void*)&videoPts, sizeof(videoPts));
|
||||
if (ret <= 0) {
|
||||
return;
|
||||
}
|
||||
while (1) {
|
||||
if (audioPts > videoPts) { // write video
|
||||
info.pts = videoPts;
|
||||
trackId = videoTrackIndex;
|
||||
curFd = fdStr->inVideoFd;
|
||||
} else { // write audio
|
||||
info.pts = audioPts;
|
||||
trackId = audioTrackIndex;
|
||||
curFd = fdStr->inAudioFd;
|
||||
}
|
||||
|
||||
// read flags
|
||||
ret = read(curFd, (void*)&flags, sizeof(flags));
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
info.flags = 0;
|
||||
if (flags != 0) {
|
||||
info.flags |= AVCODEC_BUFFER_FLAGS_SYNC_FRAME;
|
||||
}
|
||||
|
||||
// read frame buffer
|
||||
ret = read(curFd, (void*)&dataSize, sizeof(dataSize));
|
||||
if (ret <= 0 || dataSize < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != NULL && dataSize > avMuxerDemoBufferSize) {
|
||||
free(avMuxerDemoBuffer);
|
||||
avMuxerDemoBufferSize = 0;
|
||||
avMuxerDemoBuffer = NULL;
|
||||
}
|
||||
if (avMuxerDemoBuffer == NULL) {
|
||||
avMuxerDemoBuffer = malloc(dataSize);
|
||||
avMuxerDemoBufferSize = dataSize;
|
||||
if (avMuxerDemoBuffer == NULL) {
|
||||
printf("error malloc memory! %d\n", dataSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = read(curFd, (void*)avMuxerDemoBuffer, dataSize);
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
info.size = dataSize;
|
||||
|
||||
if (OH_AVMuxer_WriteSampleBuffer(muxer, trackId, avMuxerDemoBuffer, info) != AV_ERR_OK) {
|
||||
printf("OH_AVMuxer_WriteSampleBuffer error!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (curFd == fdStr->inVideoFd) {
|
||||
ret = read(fdStr->inVideoFd, (void*)&videoPts, sizeof(videoPts));
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret = read(fdStr->inAudioFd, (void*)&audioPts, sizeof(audioPts));
|
||||
if (ret <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (avMuxerDemoBuffer != NULL) {
|
||||
free(avMuxerDemoBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteTrackCover(OH_AVMuxer *muxer, int coverTrackIndex, int fdInput)
|
||||
{
|
||||
printf("WriteTrackCover\n");
|
||||
OH_AVCodecBufferAttr info;
|
||||
memset_s(&info, sizeof(info), 0, sizeof(info));
|
||||
struct stat fileStat;
|
||||
fstat(fdInput, &fileStat);
|
||||
info.size = fileStat.st_size;
|
||||
unsigned char *avMuxerDemoBuffer = malloc(info.size);
|
||||
if (avMuxerDemoBuffer == NULL) {
|
||||
printf("malloc memory error! size: %d \n", info.size);
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = read(fdInput, avMuxerDemoBuffer, info.size);
|
||||
if (ret <= 0) {
|
||||
free(avMuxerDemoBuffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (OH_AVMuxer_WriteSampleBuffer(muxer, coverTrackIndex, avMuxerDemoBuffer, info) != AV_ERR_OK) {
|
||||
free(avMuxerDemoBuffer);
|
||||
printf("OH_AVMuxer_WriteSampleBuffer error!\n");
|
||||
return;
|
||||
}
|
||||
free(avMuxerDemoBuffer);
|
||||
}
|
||||
|
||||
int GetInputNum(int defaultNum)
|
||||
{
|
||||
int num = defaultNum;
|
||||
num = getchar();
|
||||
if (num == '\n') { // default
|
||||
num = defaultNum;
|
||||
} else {
|
||||
ungetc(num, stdin);
|
||||
scanf("%d", &num);
|
||||
fflush(stdin);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
void NativeSelectMuxerType()
|
||||
{
|
||||
int num;
|
||||
|
||||
printf("\nplese select muxer type : 0.mp4 1.m4a\n");
|
||||
num = GetInputNum(0);
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_MPEG_4;
|
||||
snprintf(g_muxerParam.outputFormatType, sizeof(g_muxerParam.outputFormatType), "%s", "mp4");
|
||||
break;
|
||||
case 1:
|
||||
g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_M4A;
|
||||
snprintf(g_muxerParam.outputFormatType, sizeof(g_muxerParam.outputFormatType), "%s", "m4a");
|
||||
break;
|
||||
default:
|
||||
g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_MPEG_4;
|
||||
snprintf(g_muxerParam.outputFormatType, sizeof(g_muxerParam.outputFormatType), "%s", "mp4");
|
||||
break;
|
||||
}
|
||||
printf("select mode:%d\n", num);
|
||||
}
|
||||
|
||||
void NativeSelectRunMode()
|
||||
{
|
||||
int num;
|
||||
|
||||
printf("\nplese select audio vide wrtie mode:\n");
|
||||
printf("0. audio video write in sample thread\n");
|
||||
printf("1. audio video write in different thread\n");
|
||||
num = GetInputNum(0);
|
||||
switch (num)
|
||||
{
|
||||
case 0:
|
||||
g_muxerParam.runMode = NORMAL;
|
||||
snprintf(g_muxerParam.runModeType, sizeof(g_muxerParam.runModeType), "%s", RUN_NORMAL);
|
||||
break;
|
||||
case 1:
|
||||
g_muxerParam.runMode = THREAD;
|
||||
snprintf(g_muxerParam.runModeType, sizeof(g_muxerParam.runModeType), "%s", RUN_MUL_THREAD);
|
||||
break;
|
||||
default:
|
||||
g_muxerParam.runMode = NORMAL;
|
||||
snprintf(g_muxerParam.runModeType, sizeof(g_muxerParam.runModeType), "%s", RUN_NORMAL);
|
||||
break;
|
||||
}
|
||||
printf("select mode:%d\n", num);
|
||||
}
|
||||
|
||||
void NativeSelectAudio()
|
||||
{
|
||||
int num;
|
||||
|
||||
printf("\nplese select audio mode: 0.noAudio 1.aac 2.mpeg\n");
|
||||
num = GetInputNum(1);
|
||||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
g_muxerParam.audioParams = &g_audioAacPar;
|
||||
snprintf(g_muxerParam.audioType, sizeof(g_muxerParam.audioType), "%s", "aac");
|
||||
break;
|
||||
case 2:
|
||||
g_muxerParam.audioParams = &g_audioMpegPar;
|
||||
snprintf(g_muxerParam.audioType, sizeof(g_muxerParam.audioType), "%s", "mpeg");
|
||||
break;
|
||||
default:
|
||||
g_muxerParam.audioParams = NULL;
|
||||
snprintf(g_muxerParam.audioType, sizeof(g_muxerParam.audioType), "%s", "noAudio");
|
||||
break;
|
||||
}
|
||||
printf("select mode:%d\n", num);
|
||||
}
|
||||
|
||||
void NativeSelectVideo()
|
||||
{
|
||||
int num;
|
||||
|
||||
printf("\nplese select video mode: 0.noVideo 1.h264 2.mpeg4\n");
|
||||
num = GetInputNum(1);
|
||||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
g_muxerParam.videoParams = &g_videoH264Par;
|
||||
snprintf(g_muxerParam.videoType, sizeof(g_muxerParam.videoType), "%s", "h264");
|
||||
break;
|
||||
case 2:
|
||||
g_muxerParam.videoParams = &g_videoMpeg4Par;
|
||||
snprintf(g_muxerParam.videoType, sizeof(g_muxerParam.videoType), "%s", "mpeg4");
|
||||
break;
|
||||
default:
|
||||
g_muxerParam.videoParams = NULL;
|
||||
snprintf(g_muxerParam.videoType, sizeof(g_muxerParam.videoType), "%s", "noVideo");
|
||||
break;
|
||||
}
|
||||
printf("select mode:%d\n", num);
|
||||
}
|
||||
|
||||
void NativeSelectCover()
|
||||
{
|
||||
int num;
|
||||
|
||||
printf("\nplese select cover mode: 0.noCover 1.jpg 2.png 3.bmp\n");
|
||||
num = GetInputNum(1);
|
||||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
g_muxerParam.coverParams = &g_jpegCoverPar;
|
||||
snprintf(g_muxerParam.coverType, sizeof(g_muxerParam.coverType), "%s", "jpg");
|
||||
break;
|
||||
case 2:
|
||||
g_muxerParam.coverParams = &g_pngCoverPar;
|
||||
snprintf(g_muxerParam.coverType, sizeof(g_muxerParam.coverType), "%s", "png");
|
||||
break;
|
||||
case 3:
|
||||
g_muxerParam.coverParams = &g_bmpCoverPar;
|
||||
snprintf(g_muxerParam.coverType, sizeof(g_muxerParam.coverType), "%s", "bmp");
|
||||
break;
|
||||
default:
|
||||
g_muxerParam.coverParams = NULL;
|
||||
snprintf(g_muxerParam.coverType, sizeof(g_muxerParam.coverType), "%s", "noCover");
|
||||
break;
|
||||
}
|
||||
printf("select mode:%d\n", num);
|
||||
}
|
||||
|
||||
void NativeSelectMode()
|
||||
{
|
||||
if (g_muxerParam.outputFormat != AV_OUTPUT_FORMAT_UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeSelectMuxerType();
|
||||
NativeSelectRunMode();
|
||||
NativeSelectAudio();
|
||||
NativeSelectVideo();
|
||||
NativeSelectCover();
|
||||
}
|
||||
|
||||
int OpenAllInputFile(FdListStr *fdStr)
|
||||
{
|
||||
if (!fdStr) {
|
||||
printf("fdStr is null!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_muxerParam.audioParams) {
|
||||
fdStr->inAudioFd = open(g_muxerParam.audioParams->fileName, O_RDONLY);
|
||||
if (fdStr->inAudioFd < 0) {
|
||||
printf("open %s failed!!\n", g_muxerParam.audioParams->fileName);
|
||||
} else {
|
||||
printf("open file %s success, -fd:%d, -flags %x\n", g_muxerParam.audioParams->fileName,
|
||||
fdStr->inAudioFd, fcntl(fdStr->inAudioFd, F_GETFL, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_muxerParam.videoParams) {
|
||||
fdStr->inVideoFd = open(g_muxerParam.videoParams->fileName, O_RDONLY);
|
||||
if (fdStr->inVideoFd < 0) {
|
||||
printf("open %s failed!!\n", g_muxerParam.videoParams->fileName);
|
||||
} else {
|
||||
printf("open file %s success, -fd:%d, -flags %x\n", g_muxerParam.videoParams->fileName,
|
||||
fdStr->inVideoFd, fcntl(fdStr->inVideoFd, F_GETFL, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_muxerParam.coverParams) {
|
||||
fdStr->inCoverFd = open(g_muxerParam.coverParams->fileName, O_RDONLY);
|
||||
if (fdStr->inCoverFd < 0) {
|
||||
printf("open %s failed!!\n", g_muxerParam.coverParams->fileName);
|
||||
} else {
|
||||
printf("open file %s success, -fd:%d, -flags %x\n", g_muxerParam.coverParams->fileName,
|
||||
fdStr->inCoverFd, fcntl(fdStr->inCoverFd, F_GETFL, 0));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DoRunMuxer(FdListStr *fdStr, OH_AVMuxer *muxer)
|
||||
{
|
||||
if (fdStr == NULL || muxer == NULL) {
|
||||
printf("fdStr or muxer is null!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (OH_AVMuxer_SetLocation(muxer, 10, 10) != AV_ERR_OK
|
||||
|| OH_AVMuxer_SetRotation(muxer, 0) != AV_ERR_OK ) {
|
||||
printf("set failed!\n");
|
||||
return -1;
|
||||
}
|
||||
int audioTrackIndex = AddTrackAudio(muxer, g_muxerParam.audioParams, fdStr->inAudioFd);
|
||||
int videoTrackIndex = AddTrackVideo(muxer, g_muxerParam.videoParams, fdStr->inVideoFd);
|
||||
int coverTrackIndex = AddTrackCover(muxer, g_muxerParam.coverParams, fdStr->inCoverFd);
|
||||
|
||||
if (OH_AVMuxer_Start(muxer) != AV_ERR_OK) {
|
||||
printf("start muxer failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (coverTrackIndex >= 0) {
|
||||
WriteTrackCover(muxer, coverTrackIndex, fdStr->inCoverFd);
|
||||
}
|
||||
|
||||
if (g_muxerParam.runMode == NORMAL) {
|
||||
printf("== write audio video sample in same thread\n");
|
||||
if (audioTrackIndex >= 0 && videoTrackIndex >= 0) {
|
||||
WriteTrackSample(muxer, audioTrackIndex, videoTrackIndex, fdStr);
|
||||
} else if (audioTrackIndex >= 0) {
|
||||
WriteSingleTrackSample(muxer, audioTrackIndex, fdStr->inAudioFd);
|
||||
} else if (videoTrackIndex >= 0) {
|
||||
WriteSingleTrackSample(muxer, videoTrackIndex, fdStr->inVideoFd);
|
||||
}
|
||||
} else if (g_muxerParam.runMode == THREAD) {
|
||||
printf("== write audio video sample in different thread\n");
|
||||
pthread_t auThread;
|
||||
pthread_t viThread;
|
||||
|
||||
struct WriteTrackSampleParam audioThParam = {muxer, audioTrackIndex, fdStr->inAudioFd};
|
||||
struct WriteTrackSampleParam videoThparam = {muxer, videoTrackIndex, fdStr->inVideoFd};
|
||||
pthread_create(&auThread, NULL, ThreadWriteTrackSample, &audioThParam);
|
||||
pthread_create(&viThread, NULL, ThreadWriteTrackSample, &videoThparam);
|
||||
|
||||
pthread_join(viThread, NULL);
|
||||
pthread_join(auThread, NULL);
|
||||
}
|
||||
|
||||
if (OH_AVMuxer_Stop(muxer) != AV_ERR_OK) {
|
||||
printf("stop muxer failed!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("native avmuxer finish! fd:out:%d, audio:%d, video:%d, cover:%d\n",
|
||||
fdStr->outputFd, fdStr->inAudioFd, fdStr->inVideoFd, fdStr->inCoverFd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CloseAllFd(FdListStr *fdStr)
|
||||
{
|
||||
printf("close fd : [");
|
||||
int fdTotalCount = sizeof(*fdStr) /sizeof(fdStr->start[0]);
|
||||
for (int i = 0; i < fdTotalCount; i++) {
|
||||
printf("%d, ", fdStr->start[i]);
|
||||
if (fdStr->start[i] > 0) {
|
||||
close(fdStr->start[i]);
|
||||
fdStr->start[i] = -1;
|
||||
}
|
||||
}
|
||||
printf("\b\b]\n");
|
||||
}
|
||||
|
||||
int RunNativeMuxer(const char *out)
|
||||
{
|
||||
FdListStr fdStr;
|
||||
int fdTotalCount = sizeof(fdStr) /sizeof(fdStr.start[0]);
|
||||
printf("fd list total size is %d\n", fdTotalCount);
|
||||
for (int i = 0; i < fdTotalCount; i++) {
|
||||
fdStr.start[i] = -1;
|
||||
}
|
||||
|
||||
if (OpenAllInputFile(&fdStr) < 0) {
|
||||
CloseAllFd(&fdStr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char outFileName[100] = {0};
|
||||
snprintf(outFileName, sizeof(outFileName), "%s_%s_%s_%s_%s.%s",
|
||||
out, g_muxerParam.runModeType, g_muxerParam.audioType, g_muxerParam.videoType,
|
||||
g_muxerParam.coverType, g_muxerParam.outputFormatType);
|
||||
|
||||
fdStr.outputFd = open(outFileName, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (fdStr.outputFd < 0) {
|
||||
printf("open file failed! filePath is: %s %d\n", outFileName, fdStr.outputFd);
|
||||
CloseAllFd(&fdStr);
|
||||
return -1;
|
||||
}
|
||||
printf("open file %s success, -fd:%d, -flags %x\n", outFileName, fdStr.outputFd, fcntl(fdStr.outputFd, F_GETFL, 0));
|
||||
|
||||
OH_AVMuxer *muxer = OH_AVMuxer_Create(fdStr.outputFd, g_muxerParam.outputFormat);
|
||||
DoRunMuxer(&fdStr, muxer);
|
||||
|
||||
if (muxer != NULL) {
|
||||
OH_AVMuxer_Destroy(muxer);
|
||||
muxer = NULL;
|
||||
}
|
||||
|
||||
CloseAllFd(&fdStr);
|
||||
|
||||
return 0;
|
||||
}
|
BIN
test/nativedemo/resources/aac_44100_2.bin
Normal file
BIN
test/nativedemo/resources/aac_44100_2.bin
Normal file
Binary file not shown.
BIN
test/nativedemo/resources/greatwall.jpg
Normal file
BIN
test/nativedemo/resources/greatwall.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
test/nativedemo/resources/h264_640_360.bin
Normal file
BIN
test/nativedemo/resources/h264_640_360.bin
Normal file
Binary file not shown.
BIN
test/nativedemo/resources/mpeg4_720_480.bin
Normal file
BIN
test/nativedemo/resources/mpeg4_720_480.bin
Normal file
Binary file not shown.
BIN
test/nativedemo/resources/mpeg_44100_2.bin
Normal file
BIN
test/nativedemo/resources/mpeg_44100_2.bin
Normal file
Binary file not shown.
89
test/unittest/BUILD.gn
Normal file
89
test/unittest/BUILD.gn
Normal file
@ -0,0 +1,89 @@
|
||||
# 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.
|
||||
|
||||
import("//build/test.gni")
|
||||
import("//foundation/multimedia/av_codec/config.gni")
|
||||
|
||||
AV_CODE_ROOT_DIR = "//foundation/multimedia/av_codec"
|
||||
module_output_path = "av_codec"
|
||||
|
||||
av_codec_unittest_include_dirs = [
|
||||
"$AV_CODE_ROOT_DIR/interfaces/inner_api/native",
|
||||
"$AV_CODE_ROOT_DIR/interfaces/interfaces/inner_api/native",
|
||||
]
|
||||
|
||||
av_codec_unittest_cflags = [
|
||||
"-std=c++17",
|
||||
"-fno-rtti",
|
||||
"-fno-exceptions",
|
||||
"-Wall",
|
||||
"-fno-common",
|
||||
"-fstack-protector-strong",
|
||||
"-Wshadow",
|
||||
"-FPIC",
|
||||
"-FS",
|
||||
"-O2",
|
||||
"-D_FORTIFY_SOURCE=2",
|
||||
"-fvisibility=hidden",
|
||||
"-Wformat=2",
|
||||
"-Wdate-time",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
"-Wimplicit-fallthrough",
|
||||
"-Wsign-compare",
|
||||
"-Wunused-parameter",
|
||||
]
|
||||
|
||||
##################################################################################################################
|
||||
ohos_unittest("av_muxer_unit_test") {
|
||||
module_out_path = module_output_path
|
||||
include_dirs = av_codec_unittest_include_dirs
|
||||
include_dirs += [
|
||||
"./",
|
||||
]
|
||||
cflags = av_codec_unittest_cflags
|
||||
|
||||
if (multimedia_av_codec_support_muxer) {
|
||||
sources = [
|
||||
"./avmuxer_test/avmuxer_unittest.cpp",
|
||||
]
|
||||
}
|
||||
|
||||
external_deps = [
|
||||
"multimedia_av_codec:av_codec_client",
|
||||
]
|
||||
|
||||
resource_config_file = "$AV_CODE_ROOT_DIR/test/unittest/ohos_test.xml"
|
||||
}
|
||||
|
||||
##################################################################################################################
|
||||
ohos_unittest("format_unit_test") {
|
||||
module_out_path = module_output_path
|
||||
include_dirs = av_codec_unittest_include_dirs
|
||||
include_dirs += [
|
||||
"./",
|
||||
]
|
||||
cflags = av_codec_unittest_cflags
|
||||
|
||||
if (multimedia_av_codec_support_muxer) {
|
||||
sources = [
|
||||
"./format_unit_test.cpp",
|
||||
]
|
||||
}
|
||||
|
||||
public_deps = [
|
||||
"$AV_CODE_ROOT_DIR/services/utils:av_codec_format",
|
||||
]
|
||||
|
||||
resource_config_file = "$AV_CODE_ROOT_DIR/test/unittest/ohos_test.xml"
|
||||
}
|
257
test/unittest/avmuxer_test/avmuxer_unittest.cpp
Normal file
257
test/unittest/avmuxer_test/avmuxer_unittest.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
#include "avmuxer.h"
|
||||
#include "avcodec_info.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Media;
|
||||
|
||||
static const std::string TEST_FILE_PATH = "./";
|
||||
|
||||
class AvmuxerUnitTest : public testing::Test {
|
||||
public:
|
||||
// SetUpTestCase: Called before all test cases
|
||||
static void SetUpTestCase(void);
|
||||
// TearDownTestCase: Called after all test case
|
||||
static void TearDownTestCase(void);
|
||||
// SetUp: Called before each test cases
|
||||
void SetUp(void);
|
||||
// TearDown: Called after each test cases
|
||||
void TearDown(void);
|
||||
protected:
|
||||
int32_t fd_ {-1};
|
||||
std::shared_ptr<std::ifstream> avDataFile_ {nullptr};
|
||||
std::shared_ptr<AVMuxer> avmuxer_ {nullptr};
|
||||
uint8_t buffer_[3] = {'a', 'a', 'a'};
|
||||
};
|
||||
|
||||
void AvmuxerUnitTest::SetUpTestCase() {}
|
||||
|
||||
void AvmuxerUnitTest::TearDownTestCase() {}
|
||||
|
||||
void AvmuxerUnitTest::SetUp()
|
||||
{
|
||||
avDataFile_ = std::make_shared<std::ifstream>();
|
||||
avDataFile_->open("avDataMpegMpeg4.bin", std::ios::in | std::ios::binary);
|
||||
if (avDataFile_ == nullptr) {
|
||||
std::cout<<"open avDataMpegMpeg4.bin failed!"<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void AvmuxerUnitTest::TearDown()
|
||||
{
|
||||
if (avDataFile_ != nullptr) {
|
||||
avDataFile_->close();
|
||||
avDataFile_ = nullptr;
|
||||
}
|
||||
|
||||
if (fd_ >= 0) {
|
||||
close(fd_);
|
||||
fd_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Muxer_AddTrack_001
|
||||
* @tc.desc: Muxer AddTrack add audio track
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(AvmuxerUnitTest, Muxer_Create_001, TestSize.Level0)
|
||||
{
|
||||
std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_001.mp4");
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
OutputFormat outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_EQ(avmuxer, nullptr);
|
||||
|
||||
close(fd_);
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
|
||||
outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_EQ(avmuxer, nullptr);
|
||||
|
||||
close(fd_);
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_NE(avmuxer, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Muxer_AddTrack_001
|
||||
* @tc.desc: Muxer AddTrack add audio track
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(AvmuxerUnitTest, Muxer_AddTrack_001, TestSize.Level0)
|
||||
{
|
||||
int audioTrackId = -1;
|
||||
int ret = 0;
|
||||
std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_001.mp4");
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
OutputFormat outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_NE(avmuxer, nullptr);
|
||||
|
||||
std::shared_ptr<MediaDescription> audioParams = std::make_shared<MediaDescription>();
|
||||
audioParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::AUDIO_MPEG);
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, 44100);
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, 2);
|
||||
ret = avmuxer->AddTrack(audioTrackId, *audioParams);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_GE(audioTrackId, 0);
|
||||
|
||||
audioParams = std::make_shared<MediaDescription>();
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, 44100);
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, 2);
|
||||
ret = avmuxer->AddTrack(audioTrackId, *audioParams);
|
||||
EXPECT_NE(ret, 0);
|
||||
|
||||
audioParams = std::make_shared<MediaDescription>();
|
||||
audioParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::AUDIO_MPEG);
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, 2);
|
||||
ret = avmuxer->AddTrack(audioTrackId, *audioParams);
|
||||
EXPECT_NE(ret, 0);
|
||||
|
||||
audioParams = std::make_shared<MediaDescription>();
|
||||
audioParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::AUDIO_MPEG);
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, 44100);
|
||||
ret = avmuxer->AddTrack(audioTrackId, *audioParams);
|
||||
EXPECT_NE(ret, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Muxer_AddTrack_002
|
||||
* @tc.desc: Muxer AddTrack add video track
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(AvmuxerUnitTest, Muxer_AddTrack_002, TestSize.Level0)
|
||||
{
|
||||
int videoTrackId = -1;
|
||||
int ret = 0;
|
||||
std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_002.mp4");
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
OutputFormat outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_NE(avmuxer, nullptr);
|
||||
|
||||
std::shared_ptr<MediaDescription> videoParams = std::make_shared<MediaDescription>();
|
||||
videoParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::VIDEO_MPEG4);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, 352);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, 288);
|
||||
ret = avmuxer->AddTrack(videoTrackId, *videoParams);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_GE(videoTrackId, 0);
|
||||
|
||||
videoParams = std::make_shared<MediaDescription>();
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, 352);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, 288);
|
||||
ret = avmuxer->AddTrack(videoTrackId, *videoParams);
|
||||
EXPECT_NE(ret, 0);
|
||||
|
||||
videoParams = std::make_shared<MediaDescription>();
|
||||
videoParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::VIDEO_MPEG4);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, 288);
|
||||
ret = avmuxer->AddTrack(videoTrackId, *videoParams);
|
||||
EXPECT_NE(ret, 0);
|
||||
|
||||
videoParams = std::make_shared<MediaDescription>();
|
||||
videoParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::VIDEO_MPEG4);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, 352);
|
||||
ret = avmuxer->AddTrack(videoTrackId, *videoParams);
|
||||
EXPECT_NE(ret, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Muxer_AddTrack_003
|
||||
* @tc.desc: Muxer AddTrack after Start()
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(AvmuxerUnitTest, Muxer_AddTrack_003, TestSize.Level0)
|
||||
{
|
||||
int audioTrackId = -1;
|
||||
int videoTrackId = -1;
|
||||
int ret = 0;
|
||||
std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_003.mp4");
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
OutputFormat outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_NE(avmuxer, nullptr);
|
||||
|
||||
std::shared_ptr<MediaDescription> videoParams = std::make_shared<MediaDescription>();
|
||||
videoParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::VIDEO_MPEG4);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, 352);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, 288);
|
||||
videoParams->PutBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, buffer_, 3);
|
||||
ret = avmuxer->AddTrack(videoTrackId, *videoParams);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_GE(videoTrackId, 0);
|
||||
|
||||
avmuxer->Start();
|
||||
std::shared_ptr<MediaDescription> audioParams = std::make_shared<MediaDescription>();
|
||||
audioParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::AUDIO_MPEG);
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, 44100);
|
||||
audioParams->PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, 2);
|
||||
ret = avmuxer->AddTrack(audioTrackId, *audioParams);
|
||||
EXPECT_NE(ret, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Muxer_Start_001
|
||||
* @tc.desc: Muxer Start after Stop()
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(AvmuxerUnitTest, Muxer_Start_001, TestSize.Level0)
|
||||
{
|
||||
std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_003.mp4");
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
OutputFormat outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_NE(avmuxer, nullptr);
|
||||
|
||||
std::shared_ptr<MediaDescription> videoParams = std::make_shared<MediaDescription>();
|
||||
videoParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::VIDEO_MPEG4);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, 352);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, 288);
|
||||
videoParams->PutBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, buffer_, 3);
|
||||
|
||||
EXPECT_NE(avmuxer->Start(), 0);
|
||||
int32_t videoTrackId = -1;
|
||||
int ret = avmuxer->AddTrack(videoTrackId, *videoParams);
|
||||
ASSERT_EQ(ret, 0);
|
||||
EXPECT_GE(videoTrackId, 0);
|
||||
EXPECT_EQ(avmuxer->Start(), 0);
|
||||
EXPECT_NE(avmuxer->Start(), 0);
|
||||
EXPECT_EQ(avmuxer->Stop(), 0);
|
||||
EXPECT_NE(avmuxer->Start(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Muxer_Stop_001
|
||||
* @tc.desc: Muxer Stop() before Start
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(AvmuxerUnitTest, Muxer_Stop_001, TestSize.Level0)
|
||||
{
|
||||
std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_003.mp4");
|
||||
fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
OutputFormat outputFormat = OUTPUT_FORMAT_MPEG_4;
|
||||
std::shared_ptr<AVMuxer> avmuxer = AVMuxerFactory::CreateAVMuxer(fd_, outputFormat);
|
||||
ASSERT_NE(avmuxer, nullptr);
|
||||
|
||||
std::shared_ptr<MediaDescription> videoParams = std::make_shared<MediaDescription>();
|
||||
videoParams->PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, CodecMimeType::VIDEO_MPEG4);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, 352);
|
||||
videoParams->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, 288);
|
||||
videoParams->PutBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, buffer_, 3);
|
||||
int32_t videoTrackId = -1;
|
||||
int ret = avmuxer->AddTrack(videoTrackId, *videoParams);
|
||||
ASSERT_EQ(ret, 0);
|
||||
EXPECT_GE(videoTrackId, 0);
|
||||
EXPECT_NE(avmuxer->Stop(), 0);
|
||||
EXPECT_EQ(avmuxer->Start(), 0);
|
||||
EXPECT_EQ(avmuxer->Stop(), 0);
|
||||
EXPECT_NE(avmuxer->Stop(), 0);
|
||||
}
|
117
test/unittest/format_unit_test.cpp
Normal file
117
test/unittest/format_unit_test.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <gtest/gtest.h>
|
||||
#include "format.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS::Media;
|
||||
|
||||
namespace {
|
||||
constexpr float EPSINON_FLOAT = 0.0001;
|
||||
constexpr double EPSINON_DOUBLE = 0.0001;
|
||||
} // namespace FormatTestParam
|
||||
|
||||
class FormatUnitTest : public testing::Test {
|
||||
public:
|
||||
// SetUpTestCase: Called before all test cases
|
||||
static void SetUpTestCase(void);
|
||||
// TearDownTestCase: Called after all test case
|
||||
static void TearDownTestCase(void);
|
||||
// SetUp: Called before each test cases
|
||||
void SetUp(void);
|
||||
// TearDown: Called after each test cases
|
||||
void TearDown(void);
|
||||
|
||||
std::unique_ptr<Format> format_ {nullptr};
|
||||
};
|
||||
|
||||
void FormatUnitTest::SetUpTestCase() {}
|
||||
|
||||
void FormatUnitTest::TearDownTestCase() {}
|
||||
|
||||
void FormatUnitTest::SetUp()
|
||||
{
|
||||
format_ = std::make_unique<Format>();
|
||||
}
|
||||
|
||||
void FormatUnitTest::TearDown()
|
||||
{
|
||||
format_ = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Format_Value_0100
|
||||
* @tc.desc: format put and get value
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI5OX06 issueI5P8N0
|
||||
*/
|
||||
HWTEST_F(FormatUnitTest, Format_Value_0100, TestSize.Level0)
|
||||
{
|
||||
const std::string_view intKey = "IntKey";
|
||||
const std::string_view longKey = "LongKey";
|
||||
const std::string_view floatKey = "FloatKey";
|
||||
const std::string_view doubleKey = "DoubleKey";
|
||||
const std::string_view stringKey = "StringKey";
|
||||
|
||||
int32_t intValue = 1;
|
||||
int64_t longValue = 1;
|
||||
float floatValue = 1.0;
|
||||
double doubleValue = 1.0;
|
||||
const std::string stringValue = "StringValue";
|
||||
|
||||
int32_t getIntValue = 0;
|
||||
int64_t getLongValue = 0;
|
||||
float getFloatValue = 0.0;
|
||||
double getDoubleValue = 0.0;
|
||||
std::string getStringValue = "";
|
||||
|
||||
ASSERT_TRUE(format_ != nullptr);
|
||||
ASSERT_TRUE(format_->PutIntValue(intKey, intValue));
|
||||
ASSERT_TRUE(format_->GetIntValue(intKey, getIntValue));
|
||||
ASSERT_TRUE(intValue == getIntValue);
|
||||
ASSERT_FALSE(format_->GetLongValue(intKey, getLongValue));
|
||||
|
||||
ASSERT_TRUE(format_->PutLongValue(longKey, intValue));
|
||||
ASSERT_TRUE(format_->GetLongValue(longKey, getLongValue));
|
||||
ASSERT_TRUE(longValue == getLongValue);
|
||||
ASSERT_FALSE(format_->GetIntValue(longKey, getIntValue));
|
||||
|
||||
ASSERT_TRUE(format_->PutFloatValue(floatKey, floatValue));
|
||||
ASSERT_TRUE(format_->GetFloatValue(floatKey, getFloatValue));
|
||||
ASSERT_TRUE(fabs(floatValue - getFloatValue) < EPSINON_FLOAT);
|
||||
ASSERT_FALSE(format_->GetDoubleValue(floatKey, getDoubleValue));
|
||||
|
||||
ASSERT_TRUE(format_->PutDoubleValue(doubleKey, doubleValue));
|
||||
ASSERT_TRUE(format_->GetDoubleValue(doubleKey, getDoubleValue));
|
||||
ASSERT_TRUE(fabs(doubleValue - getDoubleValue) < EPSINON_DOUBLE);
|
||||
ASSERT_FALSE(format_->GetFloatValue(doubleKey, getFloatValue));
|
||||
|
||||
ASSERT_TRUE(format_->PutStringValue(stringKey, stringValue.c_str()));
|
||||
ASSERT_TRUE(format_->GetStringValue(stringKey, getStringValue));
|
||||
ASSERT_TRUE(stringValue == getStringValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: Format_Buffer_0100
|
||||
* @tc.desc: format put and get buffer
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI5OWXY issueI5OXCD
|
||||
*/
|
||||
HWTEST_F(FormatUnitTest, Format_Buffer_0100, TestSize.Level0)
|
||||
{
|
||||
constexpr size_t size = 3;
|
||||
const std::string_view key = "BufferKey";
|
||||
uint8_t buffer[size] = {'a', 'b', 'b'};
|
||||
|
||||
ASSERT_TRUE(format_->PutBuffer(key, buffer, size));
|
||||
uint8_t *getBuffer;
|
||||
size_t getSize;
|
||||
ASSERT_TRUE(format_->GetBuffer(key, &getBuffer, getSize));
|
||||
ASSERT_TRUE(size == getSize);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
ASSERT_TRUE(buffer[i] == getBuffer[i]);
|
||||
}
|
||||
|
||||
std::string getString;
|
||||
ASSERT_FALSE(format_->GetStringValue(key, getString));
|
||||
}
|
20
test/unittest/ohos_test.xml
Normal file
20
test/unittest/ohos_test.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<configuration ver="2.0">
|
||||
<target name="av_muxer_unit_test">
|
||||
</target>
|
||||
</configuration>
|
Loading…
x
Reference in New Issue
Block a user