diff --git a/frameworks/js/metadatahelper/avimagegenerator_napi.cpp b/frameworks/js/metadatahelper/avimagegenerator_napi.cpp index 2f708fc99f4ddd823b2a39a757e90f2b96613445..f6427330706dae381447bbc583058ab5b62b89a0 100644 --- a/frameworks/js/metadatahelper/avimagegenerator_napi.cpp +++ b/frameworks/js/metadatahelper/avimagegenerator_napi.cpp @@ -65,6 +65,7 @@ napi_value AVImageGeneratorNapi::Init(napi_env env, napi_value exports) napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("fetchFrameByTime", JsFetchFrameAtTime), + DECLARE_NAPI_FUNCTION("fetchScaledFrameByTime", JsFetchScaledFrameAtTime), DECLARE_NAPI_FUNCTION("release", JsRelease), DECLARE_NAPI_GETTER_SETTER("fdSrc", JsGetAVFileDescriptor, JsSetAVFileDescriptor), @@ -213,7 +214,7 @@ napi_value AVImageGeneratorNapi::JsFetchFrameAtTime(napi_env env, napi_callback_ napi_value args[maxArgs] = { nullptr }; napi_value result = nullptr; napi_get_undefined(env, &result); - + AVImageGeneratorNapi *napi = AVImageGeneratorNapi::GetJsInstanceWithParameter(env, info, argCount, args); CHECK_AND_RETURN_RET_LOG(napi != nullptr, result, "failed to GetJsInstance"); @@ -250,6 +251,115 @@ napi_value AVImageGeneratorNapi::JsFetchFrameAtTime(napi_env env, napi_callback_ return result; } +int32_t AVImageGeneratorNapi::GetFetchScaledFrameArgs(std::unique_ptr &asyncCtx, + napi_env env, napi_value timeUs, napi_value option, + napi_value outputSize) +{ + napi_status ret = napi_get_value_int64(env, timeUs, &asyncCtx->timeUs_); + if (ret != napi_ok) { + asyncCtx->SignError(MSERR_INVALID_VAL, "failed to get timeUs"); + return MSERR_INVALID_VAL; + } + ret = napi_get_value_int32(env, option, &asyncCtx->option_); + if (ret != napi_ok) { + asyncCtx->SignError(MSERR_INVALID_VAL, "failed to get option"); + return MSERR_INVALID_VAL; + } + + int32_t width = 0; + int32_t height = 0; + if (outputSize == nullptr) { + MEDIA_LOGI("User has not set outputSize"); + } else { + if (!CommonNapi::GetPropertyInt32(env, outputSize, "width", width)) { + MEDIA_LOGW("User has not set width"); + } + if (!CommonNapi::GetPropertyInt32(env, outputSize, "height", height)) { + MEDIA_LOGW("User has not set height"); + } + } + + asyncCtx->param_.dstWidth = width; + asyncCtx->param_.dstHeight = height; + asyncCtx->param_.colorFormat = PixelFormat::UNKNOWN; + MEDIA_LOGI("searchMode=%{public}d width=%{public}d height=%{public}d GetFetchScaledFrameArgs", + asyncCtx->option_, width, height); + return MSERR_OK; +} + +napi_value AVImageGeneratorNapi::VerifyTheParameters(napi_env env, napi_callback_info info, + std::unique_ptr &promiseCtx) +{ + size_t argCount = ARG_THREE; + const int32_t maxArgs = ARG_THREE; // timeUs: number, options: AVImageQueryOptions, param: PixelMapParams + const int32_t argOutputSizeIndex = ARG_TWO; + napi_value args[maxArgs] = { nullptr }; + napi_value result = nullptr; + CHECK_AND_RETURN_RET_LOG(env != nullptr, result, "env is null"); + napi_get_undefined(env, &result); + + AVImageGeneratorNapi *napi = AVImageGeneratorNapi::GetJsInstanceWithParameter(env, info, argCount, args); + CHECK_AND_RETURN_RET_LOG(napi != nullptr, result, "failed to GetJsInstance"); + + promiseCtx = std::make_unique(env); + CHECK_AND_RETURN_RET_LOG(promiseCtx != nullptr, nullptr, "promiseCtx is null"); + promiseCtx->napi = napi; + promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result); + + napi_valuetype valueType = napi_undefined; + bool notParamValid = argCount < argOutputSizeIndex; + if (notParamValid) { + promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "VerifyTheParameters"); + return nullptr; + } + if (argCount == maxArgs) { + notParamValid = napi_typeof(env, args[argOutputSizeIndex], &valueType) != napi_ok || + valueType != napi_object || promiseCtx->napi->GetFetchScaledFrameArgs(promiseCtx, env, args[ARG_ZERO], + args[ARG_ONE], args[ARG_TWO]) != MSERR_OK; + } else { + notParamValid = promiseCtx->napi->GetFetchScaledFrameArgs( + promiseCtx, env, args[ARG_ZERO], args[ARG_ONE], nullptr) != MSERR_OK; + } + if (notParamValid) { + promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "VerifyTheParameters"); + return nullptr; + } + + if (napi->state_ != HelperState::HELPER_STATE_RUNNABLE) { + promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, + "Current state is not runnable, can't fetchScaledFrame."); + return nullptr; + } + return result; +} + +napi_value AVImageGeneratorNapi::JsFetchScaledFrameAtTime(napi_env env, napi_callback_info info) +{ + MediaTrace trace("AVImageGeneratorNapi::JsFetchScaledFrameAtTime"); + MEDIA_LOGI("JsFetchScaledFrameAtTime in"); + std::unique_ptr promiseCtx = nullptr; + napi_value result = VerifyTheParameters(env, info, promiseCtx); + CHECK_AND_RETURN_RET_LOG(result != nullptr, result, "failed to VerifyTheParameters"); + + napi_value resource = nullptr; + napi_create_string_utf8(env, "JsFetchScaledFrameAtTime", NAPI_AUTO_LENGTH, &resource); + NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void *data) { + auto asyncCtx = reinterpret_cast(data); + CHECK_AND_RETURN_LOG(asyncCtx && asyncCtx->napi && !asyncCtx->errFlag, + "Invalid AVImageGeneratorAsyncContext."); + CHECK_AND_RETURN_LOG(asyncCtx->napi->helper_ != nullptr, "Invalid AVImageGeneratorNapi."); + auto pixelMap = asyncCtx->napi->helper_-> + FetchScaledFrameYuv(asyncCtx->timeUs_, asyncCtx->option_, asyncCtx->param_); + asyncCtx->pixel_ = pixelMap; + if (asyncCtx->pixel_ == nullptr) { + asyncCtx->SignError(MSERR_EXT_API9_UNSUPPORT_FORMAT, "JsFetchScaledFrameAtTime failed."); + } + }, CreatePixelMapComplete, static_cast(promiseCtx.get()), &promiseCtx->work)); + NAPI_CALL(env, napi_queue_async_work(env, promiseCtx->work)); + promiseCtx.release(); + return result; +} + void AVImageGeneratorNapi::CreatePixelMapComplete(napi_env env, napi_status status, void *data) { napi_value result = nullptr; diff --git a/frameworks/js/metadatahelper/avimagegenerator_napi.h b/frameworks/js/metadatahelper/avimagegenerator_napi.h index ffcefe5a9c322f13e07cbe132c5649ad8790f054..f9f96da027c4bb0b1415ef042fc7a01dc58748d8 100644 --- a/frameworks/js/metadatahelper/avimagegenerator_napi.h +++ b/frameworks/js/metadatahelper/avimagegenerator_napi.h @@ -37,6 +37,7 @@ private: static void Destructor(napi_env env, void *nativeObject, void *finalize); static napi_value JsCreateAVImageGenerator(napi_env env, napi_callback_info info); static napi_value JsFetchFrameAtTime(napi_env env, napi_callback_info info); + static napi_value JsFetchScaledFrameAtTime(napi_env env, napi_callback_info info); static napi_value JsRelease(napi_env env, napi_callback_info info); /** * url: string @@ -55,6 +56,8 @@ private: static void CreatePixelMapComplete(napi_env env, napi_status status, void *data); static void CommonCallbackRoutine(napi_env env, AVImageGeneratorAsyncContext* &asyncContext, const napi_value &valueParam); + static napi_value VerifyTheParameters(napi_env env, napi_callback_info info, + std::unique_ptr &promiseCtx); static bool CheckSystemApp(napi_env env); @@ -71,6 +74,8 @@ private: int32_t GetFetchFrameArgs(std::unique_ptr &asyncCtx, napi_env env, napi_value timeUs, napi_value option, napi_value params); + int32_t GetFetchScaledFrameArgs(std::unique_ptr &asyncCtx, napi_env env, + napi_value timeUs, napi_value option, napi_value outputSize); void SetAVFileDescriptorTask(std::shared_ptr& avHelper, AVFileDescriptor& fileDescriptor); std::string GetCurrentState(); diff --git a/frameworks/native/avmetadatahelper/avmetadatahelper_impl.cpp b/frameworks/native/avmetadatahelper/avmetadatahelper_impl.cpp index c94c1f770f644b21280da975ecd2d6081a6f59c5..72e71672066818349295f3ce0c82d2e457c71a4f 100644 --- a/frameworks/native/avmetadatahelper/avmetadatahelper_impl.cpp +++ b/frameworks/native/avmetadatahelper/avmetadatahelper_impl.cpp @@ -804,6 +804,34 @@ std::shared_ptr AVMetadataHelperImpl::FetchFrameAtTime( return pixelMap; } +void AVMetadataHelperImpl::ScalePixelMapWithEqualRatio( + std::shared_ptr &pixelMap, PixelMapInfo &info, const PixelMapParams ¶m) +{ + CHECK_AND_RETURN_LOG(pixelMap != nullptr, "pixelMap is nullptr"); + int32_t srcWidth = pixelMap->GetWidth(); + int32_t srcHeight = pixelMap->GetHeight(); + int32_t dstWidth = info.rotation % NUM_180 == 0 ? param.dstWidth : param.dstHeight; + int32_t dstHeight = info.rotation % NUM_180 == 0 ? param.dstHeight : param.dstWidth; + + bool needScale = (dstWidth > 0 || dstHeight > 0) && (srcWidth > 0 && srcHeight > 0) && + (dstWidth <= srcWidth && dstHeight <= srcHeight) && (dstWidth < srcWidth || dstHeight < srcHeight); + CHECK_AND_RETURN(needScale); + + float widthFactor = dstWidth > 0 ? (1.0f * dstWidth) / srcWidth : 1.0f; + float heightFactor = dstHeight > 0 ? (1.0f * dstHeight) / srcHeight : 1.0f; + + if (dstWidth == 0) { + widthFactor = heightFactor; + } else if (dstHeight == 0) { + heightFactor = widthFactor; + } + pixelMap->scale(widthFactor, heightFactor, AntiAliasingOption::LOW); + MEDIA_LOGI("srcWidth: %{public}d, srcHeight : %{public}d, dstWidth: %{public}d, dstHeight: %{public}d," + "widthFactor: %{public}f, HeightFactor: %{public}f, finalWidth: %{public}d, finalHeight : %{public}d", + srcWidth, srcHeight, dstWidth, dstHeight, widthFactor, heightFactor, + pixelMap->GetWidth(), pixelMap->GetHeight()); +} + void AVMetadataHelperImpl::ScalePixelMap( std::shared_ptr &pixelMap, PixelMapInfo &info, const PixelMapParams ¶m) { @@ -820,6 +848,18 @@ void AVMetadataHelperImpl::ScalePixelMap( std::shared_ptr AVMetadataHelperImpl::FetchFrameYuv(int64_t timeUs, int32_t option, const PixelMapParams ¶m) +{ + return FetchFrameBase(timeUs, option, param, FrameScaleMode::NORMAL_RATIO); +} + +std::shared_ptr AVMetadataHelperImpl::FetchScaledFrameYuv(int64_t timeUs, int32_t option, + const PixelMapParams ¶m) +{ + return FetchFrameBase(timeUs, option, param, FrameScaleMode::ASPECT_RATIO); +} + +std::shared_ptr AVMetadataHelperImpl::FetchFrameBase(int64_t timeUs, int32_t option, + const PixelMapParams ¶m, int32_t scaleMode) { std::shared_ptr avMetadataHelperService = avMetadataHelperService_; CHECK_AND_RETURN_RET_LOG(avMetadataHelperService != nullptr, nullptr, "avmetadatahelper service does not exist."); @@ -841,7 +881,7 @@ std::shared_ptr AVMetadataHelperImpl::FetchFrameYuv(int64_t timeUs, in DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_PIXEMAP); - ScalePixelMap(pixelMap, pixelMapInfo, param); + ScalePixelMapByMode(pixelMap, pixelMapInfo, param, scaleMode); DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_AFTER_SCLAE); @@ -855,6 +895,22 @@ std::shared_ptr AVMetadataHelperImpl::FetchFrameYuv(int64_t timeUs, in return pixelMap; } +void AVMetadataHelperImpl::ScalePixelMapByMode(std::shared_ptr &pixelMap, PixelMapInfo &info, + const PixelMapParams ¶m, int32_t scaleMode) +{ + CHECK_AND_RETURN_LOG(pixelMap != nullptr, "pixelMap is nullptr"); + switch (scaleMode) { + case FrameScaleMode::NORMAL_RATIO: + ScalePixelMap(pixelMap, info, param); + break; + case FrameScaleMode::ASPECT_RATIO: + ScalePixelMapWithEqualRatio(pixelMap, info, param); + break; + default: + break; + } +} + int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time) { CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, 0, "avmetadatahelper service does not exist."); diff --git a/frameworks/native/avmetadatahelper/avmetadatahelper_impl.h b/frameworks/native/avmetadatahelper/avmetadatahelper_impl.h index bd4cca861b80a853bfb5e464483e86ffbe3d2b62..84ab8188a41208ca8f2cc7fbac3d211cdd95528a 100644 --- a/frameworks/native/avmetadatahelper/avmetadatahelper_impl.h +++ b/frameworks/native/avmetadatahelper/avmetadatahelper_impl.h @@ -48,6 +48,7 @@ public: std::shared_ptr FetchArtPicture() override; std::shared_ptr FetchFrameAtTime(int64_t timeUs, int32_t option, const PixelMapParams ¶m) override; std::shared_ptr FetchFrameYuv(int64_t timeUs, int32_t option, const PixelMapParams ¶m) override; + std::shared_ptr FetchScaledFrameYuv(int64_t timeUs, int32_t option, const PixelMapParams ¶m) override; void Release() override; int32_t Init(); int32_t SetHelperCallback(const std::shared_ptr &callback) override; @@ -107,7 +108,13 @@ private: void SetPixelMapYuvInfo(sptr &surfaceBuffer, std::shared_ptr pixelMap, PixelMapInfo &pixelMapInfo, bool needModifyStride); std::string pixelFormatToString(PixelFormat pixelFormat); + static void ScalePixelMapByMode(std::shared_ptr &pixelMap, PixelMapInfo &info, + const PixelMapParams ¶m, int32_t scaleMode); static void ScalePixelMap(std::shared_ptr &pixelMap, PixelMapInfo &info, const PixelMapParams ¶m); + static void ScalePixelMapWithEqualRatio(std::shared_ptr &pixelMap, PixelMapInfo &info, + const PixelMapParams ¶m); + std::shared_ptr FetchFrameBase(int64_t timeUs, int32_t option, + const PixelMapParams ¶m, int32_t scaleMode); int32_t CopySurfaceBufferToPixelMap(sptr &SurfaceBuffer, std::shared_ptr pixelMap, PixelMapInfo &pixelMapInfo); diff --git a/frameworks/native/avmetadatahelper/test/unittest/include/avmetadata_mock.h b/frameworks/native/avmetadatahelper/test/unittest/include/avmetadata_mock.h index 704fc901ce84cdbfa33ce4ac68d9536de60a6c5f..08b213e383f3f06de32356ef947b230ab98b17eb 100644 --- a/frameworks/native/avmetadatahelper/test/unittest/include/avmetadata_mock.h +++ b/frameworks/native/avmetadatahelper/test/unittest/include/avmetadata_mock.h @@ -96,6 +96,7 @@ public: std::unordered_map ResolveMetadata(); std::shared_ptr FetchFrameAtTime(int64_t timeUs, int32_t option, PixelMapParams param); std::shared_ptr FetchFrameYuv(int64_t timeUs, int32_t option, PixelMapParams param); + std::shared_ptr FetchScaledFrameYuv(int64_t timeUs, int32_t option, PixelMapParams param); std::shared_ptr FetchArtPicture(); void Release(); void FrameToFile(std::shared_ptr frame, const char *fileName, int64_t timeUs, int32_t queryOption); diff --git a/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_mock.cpp b/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_mock.cpp index 25e6d706d502b052c47bb0b55e6433f2c7e62e3c..9b13f52178c1ff6b48aef9c1ceafd97333db8941 100644 --- a/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_mock.cpp +++ b/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_mock.cpp @@ -121,6 +121,12 @@ std::shared_ptr AVMetadataMock::FetchFrameYuv(int64_t timeUs, int32_t return avMetadataHelper_->FetchFrameYuv(timeUs, option, param); } +std::shared_ptr AVMetadataMock::FetchScaledFrameYuv(int64_t timeUs, int32_t option, PixelMapParams param) +{ + UNITTEST_INFO_LOG("%s", __FUNCTION__); + return avMetadataHelper_->FetchScaledFrameYuv(timeUs, option, param); +} + std::shared_ptr AVMetadataMock::FetchArtPicture() { UNITTEST_INFO_LOG("%s", __FUNCTION__); diff --git a/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_unit_test.cpp b/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_unit_test.cpp index c08ea40d4ce8f91d22fdeaecc70e72206e29ca7c..d61e72e5a271997366d19241a6cd4600cd1dacc2 100644 --- a/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_unit_test.cpp +++ b/frameworks/native/avmetadatahelper/test/unittest/src/avmetadata_unit_test.cpp @@ -892,5 +892,143 @@ HWTEST_F(AVMetadataUnitTest, FetchFrameYuv_API_0200, Level2) ASSERT_EQ(pixelMap->GetWidth(), 1080); ASSERT_EQ(pixelMap->GetHeight(), 2336); } + +/** + * @tc.number : FetchScaledFrameYuv_API_0100 + * @tc.name : FetchScaledFrameYuv H264_AAC.mp4 custom scaling + * @tc.desc : FetchScaledFrameYuv API +*/ +HWTEST_F(AVMetadataUnitTest, FetchScaledFrameYuv_API_0100, Level2) +{ + std::string uri = AVMetadataTestBase::GetInstance().GetMountPath() + + std::string("H264_AAC.mp4"); + std::shared_ptr helper = std::make_shared(); + ASSERT_NE(nullptr, helper); + ASSERT_EQ(true, helper->CreateAVMetadataHelper()); + ASSERT_EQ(MSERR_OK, helper->SetSource(uri, 0, 0, AVMetadataUsage::AV_META_USAGE_PIXEL_MAP)); + int64_t time = 0; + PixelMapParams param; + param.dstWidth = 300; + param.dstHeight = 200; + auto pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 300); + ASSERT_EQ(pixelMap->GetHeight(), 200); +} + +/** + * @tc.number : FetchScaledFrameYuv_API_0200 + * @tc.name : FetchScaledFrameYuv H264_AAC.mp4 side scaling + * @tc.desc : FetchScaledFrameYuv API +*/ +HWTEST_F(AVMetadataUnitTest, FetchScaledFrameYuv_API_0200, Level2) +{ + std::string uri = AVMetadataTestBase::GetInstance().GetMountPath() + + std::string("H264_AAC.mp4"); + std::shared_ptr helper = std::make_shared(); + ASSERT_NE(nullptr, helper); + ASSERT_EQ(true, helper->CreateAVMetadataHelper()); + ASSERT_EQ(MSERR_OK, helper->SetSource(uri, 0, 0, AVMetadataUsage::AV_META_USAGE_PIXEL_MAP)); + int64_t time = 0; + PixelMapParams param; + param.dstWidth = 300; + param.dstHeight = -1; + auto pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 300); + ASSERT_EQ(pixelMap->GetHeight(), 480); + + param.dstWidth = -1; + param.dstHeight = 200; + pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 720); + ASSERT_EQ(pixelMap->GetHeight(), 200); +} + +/** + * @tc.number : FetchScaledFrameYuv_API_0300 + * @tc.name : FetchScaledFrameYuv H264_AAC.mp4 no scaling + * @tc.desc : FetchScaledFrameYuv API +*/ +HWTEST_F(AVMetadataUnitTest, FetchScaledFrameYuv_API_0300, Level2) +{ + std::string uri = AVMetadataTestBase::GetInstance().GetMountPath() + + std::string("H264_AAC.mp4"); + std::shared_ptr helper = std::make_shared(); + ASSERT_NE(nullptr, helper); + ASSERT_EQ(true, helper->CreateAVMetadataHelper()); + ASSERT_EQ(MSERR_OK, helper->SetSource(uri, 0, 0, AVMetadataUsage::AV_META_USAGE_PIXEL_MAP)); + int64_t time = 0; + PixelMapParams param; + auto pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 720); + ASSERT_EQ(pixelMap->GetHeight(), 480); + + param.dstWidth = -1; + param.dstHeight = -1; + pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 720); + ASSERT_EQ(pixelMap->GetHeight(), 480); + + param.dstWidth = 0; + param.dstHeight = 0; + pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 720); + ASSERT_EQ(pixelMap->GetHeight(), 480); +} + +/** + * @tc.number : FetchScaledFrameYuv_API_0400 + * @tc.name : FetchScaledFrameYuv H264_AAC.mp4 proportional scaling + * @tc.desc : FetchScaledFrameYuv API +*/ +HWTEST_F(AVMetadataUnitTest, FetchScaledFrameYuv_API_0400, Level2) +{ + std::string uri = AVMetadataTestBase::GetInstance().GetMountPath() + + std::string("H264_AAC.mp4"); + std::shared_ptr helper = std::make_shared(); + ASSERT_NE(nullptr, helper); + ASSERT_EQ(true, helper->CreateAVMetadataHelper()); + ASSERT_EQ(MSERR_OK, helper->SetSource(uri, 0, 0, AVMetadataUsage::AV_META_USAGE_PIXEL_MAP)); + int64_t time = 0; + PixelMapParams param; + param.dstWidth = 360; + param.dstHeight = 0; + auto pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 360); + ASSERT_EQ(pixelMap->GetHeight(), 240); + + param.dstWidth = 0; + param.dstHeight = 240; + pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 360); + ASSERT_EQ(pixelMap->GetHeight(), 240); +} + +/** + * @tc.number : FetchScaledFrameYuv_API_0500 + * @tc.name : FetchScaledFrameYuv H264_AAC.mp4 abnormal + * @tc.desc : FetchScaledFrameYuv API +*/ +HWTEST_F(AVMetadataUnitTest, FetchScaledFrameYuv_API_0500, Level2) +{ + std::string uri = AVMetadataTestBase::GetInstance().GetMountPath() + + std::string("H264_AAC.mp4"); + std::shared_ptr helper = std::make_shared(); + ASSERT_NE(nullptr, helper); + ASSERT_EQ(true, helper->CreateAVMetadataHelper()); + ASSERT_EQ(MSERR_OK, helper->SetSource(uri, 0, 0, AVMetadataUsage::AV_META_USAGE_PIXEL_MAP)); + int64_t time = 0; + PixelMapParams param; + param.dstWidth = 1000; + param.dstHeight = 200; + auto pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 720); + ASSERT_EQ(pixelMap->GetHeight(), 480); + + param.dstWidth = 500; + param.dstHeight = 1000; + pixelMap = helper->FetchScaledFrameYuv(time, 0, param); + ASSERT_EQ(pixelMap->GetWidth(), 720); + ASSERT_EQ(pixelMap->GetHeight(), 480); +} } // namespace Media } // namespace OHOS \ No newline at end of file diff --git a/interfaces/inner_api/native/avmetadatahelper.h b/interfaces/inner_api/native/avmetadatahelper.h index d7c57c26ed07a1f3c4f95c4b6fac9cd541e7bd5e..e52eefdf9e96f0e62e683a141b4f425726492d2d 100644 --- a/interfaces/inner_api/native/avmetadatahelper.h +++ b/interfaces/inner_api/native/avmetadatahelper.h @@ -310,6 +310,23 @@ enum AVMetadataQueryOption : int32_t { AV_META_QUERY_CLOSEST, }; +/** + * @brief Enumeration for frame scaling modes. + * + * This enum defines the different ways in which a frame can be scaled. + */ +enum FrameScaleMode : int32_t { + /** + * This mode is used to shrink a frame based on user-defined width and height settings. + */ + NORMAL_RATIO, + /** + * This mode is used to scale a frame based on user-defined width and height settings, + * while also supporting aspect ratio scaling. + */ + ASPECT_RATIO, +}; + /** * @brief Provides the definition of the returned pixelmap's configuration */ @@ -455,6 +472,24 @@ public: */ virtual std::shared_ptr FetchFrameYuv(int64_t timeUs, int32_t option, const PixelMapParams ¶m) = 0; + /** + * Fetch a representative video frame near a given timestamp by considering the given + * option if possible, and return a pixelmap with given parameters. This method must be + * called after the SetSource. Additionally, this method supports maintaining aspect ratio + * scaling when resizing the pixelmap. + * @param timeUs The time position in microseconds where the frame will be fetched. + * When fetching the frame at the given time position, there is no guarantee that + * the video source has a frame located at the position. When this happens, a frame + * nearby will be returned. If timeUs is negative, time position and option will ignored, + * and any frame that the implementation considers as representative may be returned. + * @param option the hint about how to fetch a frame, see {@link AVMetadataQueryOption} + * @param param the desired configuration of returned pixelmap, see {@link PixelMapParams}. + * @return Returns a pixelmap containing a scaled video frame, which can be null, if such a + * frame cannot be fetched. + */ + virtual std::shared_ptr FetchScaledFrameYuv(int64_t timeUs, int32_t option, + const PixelMapParams ¶m) = 0; + /** * all meta data. * This method must be called after the SetSource.