From e74f915c0b4705b0e08f08cc865d1a616b98d99d Mon Sep 17 00:00:00 2001 From: zzm Date: Sat, 24 May 2025 08:46:16 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E3=80=91=EF=BC=9Amp4=E5=B0=81=E8=A3=85=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E7=94=B5=E5=BD=B1=E6=A8=A1=E5=BC=8F=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zzm --- .../capi/avcodec/native_avcodec_base.cpp | 3 + .../inner_api/native/media_description.h | 3 + interfaces/kits/c/native_avcodec_base.h | 6 + .../modules/muxer/media_muxer.cpp | 23 ++ .../muxer/ffmpeg_muxer_plugin.cpp | 149 +++++++++++- .../muxer/ffmpeg_muxer_plugin.h | 5 + .../avmuxer_test/avmuxer_unit_test.cpp | 215 ++++++++++++++++++ .../unittest/avmuxer_test/avmuxer_unit_test.h | 2 + 8 files changed, 403 insertions(+), 3 deletions(-) diff --git a/frameworks/native/capi/avcodec/native_avcodec_base.cpp b/frameworks/native/capi/avcodec/native_avcodec_base.cpp index 35c0f4329..73930cf5e 100644 --- a/frameworks/native/capi/avcodec/native_avcodec_base.cpp +++ b/frameworks/native/capi/avcodec/native_avcodec_base.cpp @@ -95,6 +95,9 @@ const char *OH_MD_KEY_LANGUAGE = "language"; const char *OH_MD_KEY_DESCRIPTION = "description"; const char *OH_MD_KEY_LYRICS = "lyrics"; const char *OH_MD_KEY_TRACK_COUNT = "track_count"; +const char *OH_MD_KEY_REFERENCE_TRACK_IDS = "reference_track_ids"; +const char *OH_MD_KEY_TRACK_REFERENCE_TYPE = "track_reference_type"; +const char *OH_MD_KEY_TRACK_DESCRIPTION = "track_description"; const char *OH_MD_KEY_AUDIO_COMPRESSION_LEVEL = "audio_compression_level"; const char *OH_MD_KEY_AUDIO_OBJECT_NUMBER = "audio_object_number_key"; diff --git a/interfaces/inner_api/native/media_description.h b/interfaces/inner_api/native/media_description.h index 3a8bd2cab..bd20ae817 100644 --- a/interfaces/inner_api/native/media_description.h +++ b/interfaces/inner_api/native/media_description.h @@ -295,6 +295,9 @@ public: * are configured in stable quality rate control mode. */ static constexpr std::string_view MD_KEY_VIDEO_ENCODER_SQR_FACTOR = "sqr_factor"; + static constexpr std::string_view MD_KEY_REFERENCE_TRACK_IDS = "reference_track_ids"; + static constexpr std::string_view MD_KEY_TRACK_REFERENCE_TYPE = "track_reference_type"; + static constexpr std::string_view MD_KEY_TRACK_DESCRIPTION = "track_description"; private: MediaDescriptionKey() = delete; ~MediaDescriptionKey() = delete; diff --git a/interfaces/kits/c/native_avcodec_base.h b/interfaces/kits/c/native_avcodec_base.h index c8e098b3f..e007f84e3 100644 --- a/interfaces/kits/c/native_avcodec_base.h +++ b/interfaces/kits/c/native_avcodec_base.h @@ -799,6 +799,10 @@ extern const char *OH_MD_KEY_CREATION_TIME; */ extern const char *OH_MD_KEY_VIDEO_ENCODER_ROI_PARAMS; +extern const char *OH_MD_KEY_TRACK_REFERENCE_TYPE; +extern const char *OH_MD_KEY_TRACK_DESCRIPTION; +extern const char *OH_MD_KEY_REFERENCE_TRACK_IDS; + /** * @brief Media type. * @syscap SystemCapability.Multimedia.Media.CodecBase @@ -814,6 +818,8 @@ typedef enum OH_MediaType { * @since 12 */ MEDIA_TYPE_SUBTITLE = 2, + MEDIA_TYPE_TIMED_METADATA = 5, + MEDIA_TYPE_AUXILIARY = 6, } OH_MediaType; /** diff --git a/services/media_engine/modules/muxer/media_muxer.cpp b/services/media_engine/modules/muxer/media_muxer.cpp index 0a5b1dfe9..250fb48f6 100644 --- a/services/media_engine/modules/muxer/media_muxer.cpp +++ b/services/media_engine/modules/muxer/media_muxer.cpp @@ -73,6 +73,10 @@ const std::map> MUX_MIME_INFO = { const std::map> MUX_MIME_INFO_EXT = { {MimeType::AUDIO_AAC, {Tag::AUDIO_AAC_IS_ADTS, Tag::MEDIA_PROFILE}}, }; + +const std::set MUX_AUXILIARY_TRACK_INFO = { + Tag::REFERENCE_TRACK_IDS, Tag::TRACK_REFERENCE_TYPE, Tag::TRACK_DESCRIPTION, +}; } namespace OHOS { @@ -498,6 +502,25 @@ bool MediaMuxer::CheckKeysExt(const std::string &mimeType, const std::shared_ptr } } } + + if (!ret) { + return ret; + } + + // auxiliary track + Plugins::MediaType mediaType = Plugins::MediaType::UNKNOWN; + if (!trackDesc->Get(mediaType)) { + MEDIA_LOG_W("missing media type"); + } + + if (mediaType == Plugins::MediaType::AUXILIARY) { + for (auto &key : MUX_AUXILIARY_TRACK_INFO) { + if (trackDesc->Find(key.c_str()) == trackDesc->end()) { + ret = false; + MEDIA_LOG_E("The auxiliary track key %{public}s not contained.", key.data()); + } + } + } return ret; } diff --git a/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.cpp b/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.cpp index 3febb502c..c46b87e4f 100644 --- a/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.cpp +++ b/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.cpp @@ -36,6 +36,8 @@ using namespace Ffmpeg; std::map> g_pluginOutputFmt; std::set g_supportedMuxer = {"mp4", "ipod", "amr", "mp3", "wav", "adts"}; +const std::set SUPPORTED_TRACK_REF_TYPE = {"hint", "cdsc", "font", "hind", "vdep", "vplx", + "subt", "thmb", "auxl", "cdtg", "shsc", "aest"}; constexpr float LATITUDE_MIN = -90.0f; constexpr float LATITUDE_MAX = 90.0f; constexpr float LONGITUDE_MIN = -180.0f; @@ -692,6 +694,78 @@ Status FFmpegMuxerPlugin::CheckAacParam(const std::shared_ptr &trackDesc) return ret; } +bool FFmpegMuxerPlugin::CheckTrackReferenceType(const std::shared_ptr &trackDesc, std::string &trackRefType) +{ + if (trackDesc->Find(Tag::TRACK_REFERENCE_TYPE) != trackDesc->end()) { + trackDesc->Get(trackRefType); + if (SUPPORTED_TRACK_REF_TYPE.count(trackRefType) == 0) { + MEDIA_LOG_E(" track reference type is not supported."); + return false; + } + } else { + MEDIA_LOG_E("missing track reference type."); + return false; + } + return true; +} + +bool FFmpegMuxerPlugin::CheckTrackDescription(const std::shared_ptr &trackDesc, std::string &trackDescription) +{ + if (trackDesc->Find(Tag::TRACK_DESCRIPTION) != trackDesc->end()) { + trackDesc->Get(trackDescription); + if (trackDescription.compare(0, 16, "com.openharmony.") != 0) { // 16 "com.openharmony." length + MEDIA_LOG_E("track description key %{public}s must com.openharmony.xxx!", trackDescription.c_str()); + return false; + } + } else { + MEDIA_LOG_E("missing track description."); + return false; + } + return true; +} + +bool FFmpegMuxerPlugin::CheckReferenceTrackIDS(const std::shared_ptr &trackDesc, std::string &toStringTrackId) +{ + std::vector vTrackIDs; + if (trackDesc->Find(Tag::REFERENCE_TRACK_IDS) != trackDesc->end()) { + trackDesc->Get(vTrackIDs); + int32_t *trackIDs = reinterpret_cast(vTrackIDs.data()); + for (uint8_t i = 0; i < vTrackIDs.size() / sizeof(int32_t); i++) { + if (i > 0) { + toStringTrackId += ','; + } + toStringTrackId += std::to_string(trackIDs[i]); + } + } else { + MEDIA_LOG_E("missing track ids."); + return false; + } + return true; +} + +Status FFmpegMuxerPlugin::SetAuxiliaryMeta(const std::shared_ptr &trackDesc, AVStream* st) +{ + // Check track reference type + std::string trackRefType; + bool ret = CheckTrackReferenceType(trackDesc, trackRefType); + FALSE_RETURN_V_MSG_E(ret, Status::ERROR_INVALID_PARAMETER, "get track reference type failed."); + av_dict_set(&st->metadata, "track_reference_type", trackRefType.c_str(), 0); + + // Check track description + std::string trackDescription; + ret = CheckTrackDescription(trackDesc, trackDescription); + FALSE_RETURN_V_MSG_E(ret, Status::ERROR_INVALID_PARAMETER, "get track description failed."); + av_dict_set(&st->metadata, "handler_name", trackDescription.c_str(), 0); + + // Check track IDs + std::string trackIDs; + ret = CheckReferenceTrackIDS(trackDesc, trackIDs); + FALSE_RETURN_V_MSG_E(ret, Status::ERROR_INVALID_PARAMETER, "get track ids failed."); + av_dict_set(&st->metadata, "reference_track_ids", trackIDs.c_str(), 0); + + return Status::NO_ERROR; +} + Status FFmpegMuxerPlugin::AddAudioTrack(int32_t &trackIndex, const std::shared_ptr &trackDesc, AVCodecID codeID) { int32_t sampleRate = 0; @@ -820,6 +894,60 @@ Status FFmpegMuxerPlugin::AddTimedMetaTrack( return Status::NO_ERROR; } +Status FFmpegMuxerPlugin::AddVideoAuxiliaryTrack(int32_t &trackIndex, const std::shared_ptr &trackDesc, + AVCodecID codeID, bool isCover) +{ + constexpr int32_t maxLength = 65535; + constexpr int32_t maxVideoDelay = 16; + int32_t width = 0; + int32_t height = 0; + bool ret = trackDesc->Get(width); + FALSE_RETURN_V_MSG_E(ret && width > 0 && width <= maxLength, Status::ERROR_INVALID_PARAMETER, + "get video width failed! width:%{public}d", width); + ret = trackDesc->Get(height); + FALSE_RETURN_V_MSG_E((ret && height > 0 && height <= maxLength), Status::ERROR_INVALID_PARAMETER, + "get video height failed! height:%{public}d", height); + + auto st = avformat_new_stream(formatContext_.get(), nullptr); + FALSE_RETURN_V_MSG_E(st != nullptr, Status::ERROR_NO_MEMORY, "avformat_new_stream failed!"); + ResetCodecParameter(st->codecpar); + st->codecpar->codec_type = AVMEDIA_TYPE_AUXILIARY; + st->codecpar->codec_id = codeID; + st->codecpar->codec_tag = codeID == AV_CODEC_ID_HEVC ? MKTAG('h', 'v', 'c', '1') : 0; + st->codecpar->width = width; + st->codecpar->height = height; + int32_t videoDelay = 0; + if (trackDesc->Find(Tag::VIDEO_DELAY) != trackDesc->end()) { + trackDesc->Get(videoDelay); + FALSE_RETURN_V_MSG_E(videoDelay >= 0, Status::ERROR_MISMATCHED_TYPE, + "get video delay failed! video delay:%{public}d", videoDelay); + st->codecpar->video_delay = videoDelay; + } + + SetAuxiliaryMeta(trackDesc, st); + + trackIndex = st->index; + if (isCover) { + st->disposition = AV_DISPOSITION_ATTACHED_PIC; + } + double frameRate = 0; + if (trackDesc->Find(Tag::VIDEO_FRAME_RATE) != trackDesc->end()) { + trackDesc->Get(frameRate); + FALSE_RETURN_V_MSG_E(frameRate > 0, Status::ERROR_MISMATCHED_TYPE, + "get video frame rate failed! video frame rate:%{public}lf", frameRate); + st->avg_frame_rate = {static_cast(frameRate), 1}; + } + FALSE_RETURN_V_MSG_E((videoDelay > 0 && videoDelay <= maxVideoDelay && frameRate > 0) || videoDelay == 0, + Status::ERROR_MISMATCHED_TYPE, "If the video delayed, the frame rate is required. " + "The delay is greater than or equal to 0 and less than or equal to 16."); + + auto retColor = SetCodecParameterColor(st, trackDesc); + FALSE_RETURN_V_MSG_E(retColor == Status::NO_ERROR, retColor, "set color failed!"); + auto retCuva = SetCodecParameterCuva(st, trackDesc); + FALSE_RETURN_V_MSG_E(retCuva == Status::NO_ERROR, retCuva, "set cuva failed!"); + return SetCodecParameterOfVideoTrack(st, trackDesc); +} + Status FFmpegMuxerPlugin::AddTrack(int32_t &trackIndex, const std::shared_ptr &trackDesc) { FALSE_RETURN_V_MSG_E(!isWriteHeader_, Status::ERROR_WRONG_STATE, "AddTrack failed! muxer has start!"); @@ -840,12 +968,24 @@ Status FFmpegMuxerPlugin::AddTrack(int32_t &trackIndex, const std::shared_ptrFind(Tag::MEDIA_TYPE) != trackDesc->end()) { + FALSE_RETURN_V_MSG_E(trackDesc->Get(mediaType), Status::ERROR_INVALID_DATA, + "get mediaType failed."); + } else { + MEDIA_LOG_E("missing mediaType"); + } if (!mimeType.compare(0, mimeTypeLen, "audio")) { ret = AddAudioTrack(trackIndex, trackDesc, codeID); FALSE_RETURN_V_MSG_E(ret == Status::NO_ERROR, ret, "AddAudioTrack failed!"); } else if (!mimeType.compare(0, mimeTypeLen, "video")) { - ret = AddVideoTrack(trackIndex, trackDesc, codeID, false); - FALSE_RETURN_V_MSG_E(ret == Status::NO_ERROR, ret, "AddVideoTrack failed!"); + if (mediaType == Plugins::MediaType::AUXILIARY) { + ret = AddVideoAuxiliaryTrack(trackIndex, trackDesc, codeID, false); + FALSE_RETURN_V_MSG_E(ret == Status::NO_ERROR, ret, "AddVideoAuxiliaryTrack failed!"); + } else { + ret = AddVideoTrack(trackIndex, trackDesc, codeID, false); + FALSE_RETURN_V_MSG_E(ret == Status::NO_ERROR, ret, "AddVideoTrack failed!"); + } } else if (!mimeType.compare(0, mimeTypeLen, "image")) { ret = AddVideoTrack(trackIndex, trackDesc, codeID, true); FALSE_RETURN_V_MSG_E(ret == Status::NO_ERROR, ret, "AddCoverTrack failed!"); @@ -887,7 +1027,10 @@ Status FFmpegMuxerPlugin::Start() if (rotation_ != VIDEO_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) { + if (formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + ((formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUXILIARY) && + (formatContext_->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264 || + formatContext_->streams[i]->codecpar->codec_id == AV_CODEC_ID_H265))) { av_dict_set(&formatContext_->streams[i]->metadata, "rotate", rotate.c_str(), 0); FALSE_LOG_MSG(SetDisplayMatrix(formatContext_->streams[i]) == Status::NO_ERROR, "set rotation failed!"); diff --git a/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.h b/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.h index aa1fd81d0..30cdb8f5e 100644 --- a/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.h +++ b/services/media_engine/plugins/ffmpeg_adapter/muxer/ffmpeg_muxer_plugin.h @@ -68,9 +68,14 @@ private: void SetSeiLogInfo(); Status SetDisplayMatrix(AVStream* stream); Status SetCodecParameterTimedMeta(AVStream* stream, const std::shared_ptr &trackDesc); + static bool CheckTrackReferenceType(const std::shared_ptr &trackDesc, std::string &trackRefType); + static bool CheckTrackDescription(const std::shared_ptr &trackDesc, std::string &trackDescription); + static bool CheckReferenceTrackIDS(const std::shared_ptr &trackDesc, std::string &toStringTrackId); + Status SetAuxiliaryMeta(const std::shared_ptr &trackDesc, AVStream* st); Status AddAudioTrack(int32_t &trackIndex, const std::shared_ptr &trackDesc, AVCodecID codeID); Status AddVideoTrack(int32_t &trackIndex, const std::shared_ptr &trackDesc, AVCodecID codeID, bool isCover); Status AddTimedMetaTrack(int32_t &trackIndex, const std::shared_ptr &trackDesc, AVCodecID codeID); + Status AddVideoAuxiliaryTrack(int32_t &trackIndex, const std::shared_ptr &trackDesc, AVCodecID codeID, bool isCover); Status WriteNormal(uint32_t trackIndex, const std::shared_ptr &sample); Status WriteVideoSample(uint32_t trackIndex, const std::shared_ptr &sample); std::vector TransAnnexbToMp4(const uint8_t *sample, int32_t size); diff --git a/test/unittest/avmuxer_test/avmuxer_unit_test.cpp b/test/unittest/avmuxer_test/avmuxer_unit_test.cpp index 95b5effdc..333acc6e3 100644 --- a/test/unittest/avmuxer_test/avmuxer_unit_test.cpp +++ b/test/unittest/avmuxer_test/avmuxer_unit_test.cpp @@ -43,6 +43,10 @@ const std::string HEVC_LIB_PATH = std::string(AV_CODEC_PATH) + "/libav_codec_hev constexpr uint32_t AVCODEC_BUFFER_FLAGS_DISPOSABLE_EXT_TEST = 1 << 6; const std::string TIMED_METADATA_TRACK_MIMETYPE = "meta/timed-metadata"; const std::string TIMED_METADATA_KEY = "com.openharmony.timed_metadata.test"; +const std::string TRACK_REF_TYPE_DEPTH = "vdep"; +const std::string TRACK_REF_TYPE_PREY = "auxl"; +const std::string AUXILIARY_DEPTH_TRACK_KEY = "com.openharmony.moviemode.depth"; +const std::string AUXILIARY_PREY_TRACK_KEY = "com.openharmony.moviemode.prey"; } // namespace void AVMuxerUnitTest::SetUpTestCase() {} @@ -154,6 +158,26 @@ int32_t AVMuxerUnitTest::WriteSample(sptr bqProducer, return -1; } +void AVMuxerUnitTest::AuxiliaryWriteSample(int32_t trackId) +{ + inputFile_ = std::make_shared(LOGINFO_INPUT_FILE_PATH, std::ios::binary); + + int32_t extSize = 0; + inputFile_->read(reinterpret_cast(&extSize), sizeof(extSize)); + if (extSize > 0) { + std::vector buffer(extSize); + inputFile_->read(reinterpret_cast(buffer.data()), extSize); + } + + bool eosFlag = false; + uint32_t flag = AVCODEC_BUFFER_FLAGS_SYNC_FRAME; + ret = WriteSample(trackId, inputFile_, eosFlag, flag); + while (!eosFlag && (ret == 0)) { + ret = WriteSample(trackId, inputFile_, eosFlag, flag); + } + ASSERT_EQ(ret, 0); +} + namespace { /** * @tc.name: Muxer_Create_001 @@ -2004,6 +2028,197 @@ HWTEST_F(AVMuxerUnitTest, Muxer_AAC_005, TestSize.Level0) ret = (ret == AV_ERR_OK) ? AV_ERR_OK : AV_ERR_INVALID_VAL; ASSERT_EQ(ret, AV_ERR_INVALID_VAL); } + +/** + * @tc.name: Muxer_AddTrack_Auxiliary_001 + * @tc.desc: Muxer AddTrack video Auxiliary track. + * @tc.type: FUNC + */ +HWTEST_F(AVMuxerUnitTest, Muxer_AddTrack_Auxiliary_001, TestSize.Level0) { + int32_t trackId = -1; + int32_t trackIdDepth = -1; + std::vector vDepth = {0}; + int32_t *trackIdsDepth = vDepth.data(); + std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_Auxiliary.mp4"); + OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_MPEG_4; + + fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); + bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat); + ASSERT_TRUE(isCreated); + + std::shared_ptr videoParams = + FormatMockFactory::CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_HEVC, TEST_WIDTH, TEST_HEIGHT); + + int32_t ret = avmuxer_->AddTrack(trackId, videoParams); + ASSERT_EQ(ret, 0); + ASSERT_GE(trackId, 0); + + std::shared_ptr metadataParamsDepth = FormatMockFactory::CreateFormat(); + metadataParamsDepth->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_HEVC); + metadataParamsDepth->PutIntValue(OH_MD_KEY_WIDTH, TEST_WIDTH); + metadataParamsDepth->PutIntValue(OH_MD_KEY_HEIGHT, TEST_HEIGHT); + metadataParamsDepth->PutIntValue(OH_MD_KEY_TRACK_TYPE, static_cast(OH_MediaType::MEDIA_TYPE_AUXILIARY)); + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_REFERENCE_TYPE, TRACK_REF_TYPE_DEPTH); + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_DESCRIPTION, AUXILIARY_DEPTH_TRACK_KEY); + metadataParamsDepth->PutBuffer(OH_MD_KEY_REFERENCE_TRACK_IDS, reinterpret_cast(trackIdsDepth), + sizeof(int32_t) * vDepth.size()); + + ret = avmuxer_->AddTrack(trackIdDepth, metadataParamsDepth); + ASSERT_EQ(ret, AV_ERR_OK); + ASSERT_GE(trackIdDepth, 1); +} + +/** + * @tc.name: Muxer_AddTrack_Auxiliary_002 + * @tc.desc: Muxer AddTrack video Auxiliary track(no parameter). + * @tc.type: FUNC + */ +HWTEST_F(AVMuxerUnitTest, Muxer_AddTrack_Auxiliary_002, TestSize.Level0) { + int32_t trackId = -1; + int32_t trackIdDepth = -1; + std::vector vDepth = {0}; + int32_t *trackIdsDepth = vDepth.data(); + std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_Auxiliary.mp4"); + OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_MPEG_4; + + fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); + bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat); + ASSERT_TRUE(isCreated); + + std::shared_ptr videoParams = + FormatMockFactory::CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_HEVC, TEST_WIDTH, TEST_HEIGHT); + + int32_t ret = avmuxer_->AddTrack(trackId, videoParams); + ASSERT_EQ(ret, 0); + ASSERT_GE(trackId, 0); + + std::shared_ptr metadataParamsDepth = FormatMockFactory::CreateFormat(); + metadataParamsDepth->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_HEVC); + metadataParamsDepth->PutIntValue(OH_MD_KEY_WIDTH, TEST_WIDTH); + metadataParamsDepth->PutIntValue(OH_MD_KEY_HEIGHT, TEST_HEIGHT); + + metadataParamsDepth->PutIntValue(OH_MD_KEY_TRACK_TYPE, static_cast(OH_MediaType::MEDIA_TYPE_AUXILIARY)); + ret = avmuxer_->AddTrack(trackIdDepth, metadataParamsDepth); + ASSERT_NE(ret, AV_ERR_OK); + + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_REFERENCE_TYPE, TRACK_REF_TYPE_DEPTH); + ret = avmuxer_->AddTrack(trackIdDepth, metadataParamsDepth); + ASSERT_NE(ret, AV_ERR_OK); + + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_DESCRIPTION, AUXILIARY_DEPTH_TRACK_KEY); + ret = avmuxer_->AddTrack(trackIdDepth, metadataParamsDepth); + ASSERT_NE(ret, AV_ERR_OK); + + metadataParamsDepth->PutBuffer(OH_MD_KEY_REFERENCE_TRACK_IDS, reinterpret_cast(trackIdsDepth), + sizeof(int32_t) * vDepth.size()); + ret = avmuxer_->AddTrack(trackIdDepth, metadataParamsDepth); + ASSERT_EQ(ret, AV_ERR_OK); +} + +/** + * @tc.name: Muxer_AddTrack_Auxiliary_003 + * @tc.desc: Muxer AddTrack video Auxiliary track(H264 video). + * @tc.type: FUNC + */ +HWTEST_F(AVMuxerUnitTest, Muxer_AddTrack_Auxiliary_003, TestSize.Level0) { + int32_t trackId = -1; + int32_t trackIdDepth = -1; + std::vector vDepth = {0}; + int32_t *trackIdsDepth = vDepth.data(); + std::string outputFile = TEST_FILE_PATH + std::string("Muxer_AddTrack_Auxiliary.mp4"); + OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_MPEG_4; + + fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); + bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat); + ASSERT_TRUE(isCreated); + + std::shared_ptr videoParams = + FormatMockFactory::CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, TEST_WIDTH, TEST_HEIGHT); + + int32_t ret = avmuxer_->AddTrack(trackId, videoParams); + ASSERT_EQ(ret, 0); + ASSERT_GE(trackId, 0); + + std::shared_ptr metadataParamsDepth = FormatMockFactory::CreateFormat(); + metadataParamsDepth->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_AVC); + metadataParamsDepth->PutIntValue(OH_MD_KEY_WIDTH, TEST_WIDTH); + metadataParamsDepth->PutIntValue(OH_MD_KEY_HEIGHT, TEST_HEIGHT); + metadataParamsDepth->PutIntValue(OH_MD_KEY_TRACK_TYPE, static_cast(OH_MediaType::MEDIA_TYPE_AUXILIARY)); + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_REFERENCE_TYPE, TRACK_REF_TYPE_DEPTH); + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_DESCRIPTION, AUXILIARY_DEPTH_TRACK_KEY); + metadataParamsDepth->PutBuffer(OH_MD_KEY_REFERENCE_TRACK_IDS, reinterpret_cast(trackIdsDepth), + sizeof(int32_t) * vDepth.size()); + + ret = avmuxer_->AddTrack(trackIdDepth, metadataParamsDepth); + ASSERT_EQ(ret, AV_ERR_OK); + ASSERT_GE(trackIdDepth, 1); +} + +/** + * @tc.name: Muxer_Add_Video_Auxiliary + * @tc.desc: Muxer add video Auxiliary. + * @tc.type: FUNC + */ +HWTEST_F(AVMuxerUnitTest, Muxer_Add_Video_Auxiliary, TestSize.Level0) { + int32_t trackId = -1; + int32_t trackIdDepth = -1; + int32_t trackIdPrey = -1; + std::vector vDepth = {0}; + int32_t *trackIdsDepth = vDepth.data(); + std::vector vPrey = {0, 1}; + int32_t *trackIdsPrey = vPrey.data(); + std::string outputFile = TEST_FILE_PATH + std::string("Muxer_Add_Video_Auxiliary.mp4"); + OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_MPEG_4; + + fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); + bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat); + ASSERT_TRUE(isCreated); + + std::shared_ptr videoParams = + FormatMockFactory::CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_HEVC, TEST_WIDTH, TEST_HEIGHT); + + int32_t ret = avmuxer_->AddTrack(trackId, videoParams); + ASSERT_EQ(ret, 0); + ASSERT_GE(trackId, 0); + + // create auxiliary format depth track + std::shared_ptr metadataParamsDepth = FormatMockFactory::CreateFormat(); + metadataParamsDepth->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_HEVC); + metadataParamsDepth->PutIntValue(OH_MD_KEY_WIDTH, TEST_WIDTH); + metadataParamsDepth->PutIntValue(OH_MD_KEY_HEIGHT, TEST_HEIGHT); + metadataParamsDepth->PutIntValue(OH_MD_KEY_TRACK_TYPE, static_cast(OH_MediaType::MEDIA_TYPE_AUXILIARY)); + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_REFERENCE_TYPE, TRACK_REF_TYPE_DEPTH); + metadataParamsDepth->PutStringValue(OH_MD_KEY_TRACK_DESCRIPTION, AUXILIARY_DEPTH_TRACK_KEY); + metadataParamsDepth->PutBuffer(OH_MD_KEY_REFERENCE_TRACK_IDS, reinterpret_cast(trackIdsDepth), + sizeof(int32_t) * vDepth.size()); + + ret = avmuxer_->AddTrack(trackIdDepth, metadataParamsDepth); + ASSERT_EQ(ret, AV_ERR_OK); + ASSERT_GE(trackIdDepth, 1); + + // create auxiliary format prey track + std::shared_ptr metadataParamsPrey = FormatMockFactory::CreateFormat(); + metadataParamsPrey->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_HEVC); + metadataParamsPrey->PutIntValue(OH_MD_KEY_WIDTH, TEST_WIDTH); + metadataParamsPrey->PutIntValue(OH_MD_KEY_HEIGHT, TEST_HEIGHT); + metadataParamsPrey->PutIntValue(OH_MD_KEY_TRACK_TYPE, static_cast(OH_MediaType::MEDIA_TYPE_AUXILIARY)); + metadataParamsPrey->PutStringValue(OH_MD_KEY_TRACK_REFERENCE_TYPE, TRACK_REF_TYPE_PREY); + metadataParamsPrey->PutStringValue(OH_MD_KEY_TRACK_DESCRIPTION, AUXILIARY_PREY_TRACK_KEY); + metadataParamsPrey->PutBuffer(OH_MD_KEY_REFERENCE_TRACK_IDS, reinterpret_cast(trackIdsPrey), + sizeof(int32_t) * vPrey.size()); + + ret = avmuxer_->AddTrack(trackIdPrey, metadataParamsPrey); + ASSERT_EQ(ret, AV_ERR_OK); + ASSERT_GE(trackIdPrey, 2); + + ASSERT_EQ(avmuxer_->Start(), 0); + + AuxiliaryWriteSample(trackId); + AuxiliaryWriteSample(trackIdDepth); + AuxiliaryWriteSample(trackIdPrey); + + ASSERT_EQ(avmuxer_->Stop(), 0); +} #ifdef AVMUXER_UNITTEST_CAPI /** * @tc.name: Muxer_Destroy_001 diff --git a/test/unittest/avmuxer_test/avmuxer_unit_test.h b/test/unittest/avmuxer_test/avmuxer_unit_test.h index 3a384cafd..e4000312c 100644 --- a/test/unittest/avmuxer_test/avmuxer_unit_test.h +++ b/test/unittest/avmuxer_test/avmuxer_unit_test.h @@ -40,6 +40,8 @@ public: int32_t WriteSample(sptr bqProducer, std::shared_ptr file, bool &eosFlag); + + void AuxiliaryWriteSample(int32_t trackId); protected: std::shared_ptr avmuxer_ {nullptr}; -- Gitee From 35fa6786e695ebc7db7aef297c297d4e1219feb7 Mon Sep 17 00:00:00 2001 From: zzm Date: Sat, 24 May 2025 14:37:40 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E3=80=91=EF=BC=9A=E5=91=8A=E8=AD=A6=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zzm --- test/unittest/avmuxer_test/avmuxer_unit_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/avmuxer_test/avmuxer_unit_test.cpp b/test/unittest/avmuxer_test/avmuxer_unit_test.cpp index 333acc6e3..862b7160e 100644 --- a/test/unittest/avmuxer_test/avmuxer_unit_test.cpp +++ b/test/unittest/avmuxer_test/avmuxer_unit_test.cpp @@ -171,7 +171,7 @@ void AVMuxerUnitTest::AuxiliaryWriteSample(int32_t trackId) bool eosFlag = false; uint32_t flag = AVCODEC_BUFFER_FLAGS_SYNC_FRAME; - ret = WriteSample(trackId, inputFile_, eosFlag, flag); + int32_t ret = WriteSample(trackId, inputFile_, eosFlag, flag); while (!eosFlag && (ret == 0)) { ret = WriteSample(trackId, inputFile_, eosFlag, flag); } -- Gitee