使用AVImageGenerator获取视频帧(C/C++)
使用AVImageGenerator可以实现从原始媒体资源中获取指定时间的视频帧,本开发指导将以获取视频帧作为示例,向开发者讲解AVImageGenerator相关功能。
获取视频帧的全流程包含:创建AVImageGenerator对象、设置资源、获取视频帧、销毁资源。
开发步骤及注意事项
在 CMake 脚本中链接动态库。
target_link_libraries(entry PUBLIC libavimage_generator.so libace_napi.z.so)
使用OH_PixelmapNative_ConvertPixelmapNativeToNapi()接口将nativePixelMap对象转换为PixelMapnapi对象、OH_PixelmapNative_Release()接口释放OH_PixelmapNative对象资源,需引入如下头文件。
#include <multimedia/image_framework/image/pixelmap_native.h>
并在 CMake 脚本中链接如下动态库。
target_link_libraries(entry PUBLIC libpixelmap.so libpixelmap_ndk.z.so)
开发者使用系统日志能力时,需引入如下头文件。
#include <hilog/log.h>
并需要在 CMake 脚本中链接如下动态库。
target_link_libraries(entry PUBLIC libhilog_ndk.z.so)
(可选)开发者可以使用OH_AVMetadataExtractor_FetchMetadata()获取媒体资源时长信息OH_AVMETADATA_EXTRACTOR_DURATION,进而选择获取视频帧的时间。使用需引入如下头文件。
#include "multimedia/player_framework/avmetadata_extractor.h"
#include "multimedia/player_framework/avmetadata_extractor_base.h"
并需要在 CMake 脚本中链接如下动态库。
target_link_libraries(entry PUBLIC libavmetadata_extractor.so libnative_media_core.so)
开发者通过引入avimage_generator.h、avimage_generator_base.h和native_averrors.h头文件,使用获取视频帧相关API。
详细的API说明请参考AVImageGenerator API参考。
-
使用OH_AVImageGenerator_Create()创建实例。
#include <multimedia/player_framework/avimage_generator.h>// 创建OH_AVImageGenerator实例。OH_AVImageGenerator* generator = OH_AVImageGenerator_Create(); -
设置视频资源的文件描述符:调用OH_AVImageGenerator_SetFDSource()。
#include "napi/native_api.h"#include <multimedia/player_framework/avimage_generator.h>#include <multimedia/player_framework/native_averrors.h>int64_t offset = 0; // 媒体源在文件描述符中的偏移量。int32_t fileDescribe = -1; // 媒体文件描述符。int32_t fileSize = 0; // 媒体文件大小。// 设置视频资源的文件描述符。OH_AVErrCode avErrCode = OH_AVImageGenerator_SetFDSource(generator, fileDescribe, offset, fileSize);// 异常处理。if (avErrCode != AV_ERR_OK) {OH_AVImageGenerator_Release(generator);napi_throw_error(env, "EFAILED", "SetFDSource failed");return nullptr;} -
(可选)获取媒体资源时长信息,并指定获取视频帧的时间。
#include "napi/native_api.h"#include "multimedia/player_framework/avmetadata_extractor.h"#include "multimedia/player_framework/avmetadata_extractor_base.h"static napi_value OhAVMetadataExtractorGetDuration(napi_env env, napi_callback_info info){int64_t offset = 0;int32_t fileDescribe = -1;int64_t fileSize = 0;// 通过辅助函数,获取输入参数,实现见完整示例。if (!GetGetDurationParams(env, info, offset, fileDescribe, fileSize)) {return nullptr;}OH_AVMetadataExtractor* mainExtractor = OH_AVMetadataExtractor_Create();if (!mainExtractor) {napi_throw_error(env, "EFAILED", "Create metadata extractor failed");return nullptr;}OH_AVErrCode avErrCode = OH_AVMetadataExtractor_SetFDSource(mainExtractor, fileDescribe, offset, fileSize);if (avErrCode != AV_ERR_OK) {OH_AVMetadataExtractor_Release(mainExtractor);napi_throw_error(env, "EFAILED", "SetFDSource for metadata extractor failed");return nullptr;}OH_AVFormat* avMetadata = OH_AVFormat_Create();// 获取资源文件的元数据信息。avErrCode = OH_AVMetadataExtractor_FetchMetadata(mainExtractor, avMetadata);if (avErrCode != AV_ERR_OK) {OH_AVFormat_Destroy(avMetadata);OH_AVMetadataExtractor_Release(mainExtractor);napi_throw_error(env, "EFAILED", "Fetch metadata failed");return nullptr;}int64_t out;// 从元数据中获取资源文件的时长。if (!OH_AVFormat_GetLongValue(avMetadata, OH_AVMETADATA_EXTRACTOR_DURATION, &out)) {OH_AVFormat_Destroy(avMetadata);OH_AVMetadataExtractor_Release(mainExtractor);napi_throw_error(env, "EFAILED", "Get duration failed");return nullptr;}napi_value duration;napi_create_int64(env, out, &duration);OH_AVFormat_Destroy(avMetadata);OH_AVMetadataExtractor_Release(mainExtractor);return duration;} -
获取指定时间的视频帧:调用OH_AVImageGenerator_FetchFrameByTime(),可以获取到一个OH_PixelmapNative对象,该对象可用于图片显示。
使用完成需要调用OH_PixelmapNative_Release释放OH_PixelmapNative对象资源,详细使用方法请参阅Image_NativeModule。
#include "napi/native_api.h"#include <multimedia/image_framework/image/pixelmap_native.h>#include <multimedia/player_framework/avimage_generator.h>#include <multimedia/player_framework/avimage_generator_base.h>#include <multimedia/player_framework/native_averrors.h>// FetchFrameByTime的输入参数。struct FetchFrameParams {int64_t timeUs = 0; // 指定的时间(单位us)。int64_t offset = 0; // 媒体源在文件描述符中的偏移量。int32_t fileDescribe = -1; // 媒体文件描述符。int32_t fileSize = 0; // 媒体文件大小。int32_t options = OH_AVIMAGE_GENERATOR_QUERY_CLOSEST; // OH_AVIMAGE_GENERATOR_QUERY_CLOSEST表示选取离传入时间点最近的关键帧。};static napi_value OhAvImageGeneratorFetchFrameByTime(napi_env env, napi_callback_info info){FetchFrameParams fetchFrameParams;// 通过辅助函数,获取输入参数,实现见完整示例。if (!GetFetchFrameByTimeParams(env, info, fetchFrameParams)) {return nullptr;}int64_t timeUs = fetchFrameParams.timeUs;int64_t offset = fetchFrameParams.offset;int32_t fileDescribe = fetchFrameParams.fileDescribe;int32_t fileSize = fetchFrameParams.fileSize;int32_t options = fetchFrameParams.options;// 创建OH_AVImageGenerator实例。OH_AVImageGenerator* generator = OH_AVImageGenerator_Create();// 异常处理。if (!generator) {napi_throw_error(env, "EFAILED", "Create generator failed");return nullptr;}// 设置视频资源的文件描述符。OH_AVErrCode avErrCode = OH_AVImageGenerator_SetFDSource(generator, fileDescribe, offset, fileSize);// 异常处理。if (avErrCode != AV_ERR_OK) {OH_AVImageGenerator_Release(generator);napi_throw_error(env, "EFAILED", "SetFDSource failed");return nullptr;}// 取指定时间的视频帧。OH_PixelmapNative* pixelMap = nullptr;avErrCode = OH_AVImageGenerator_FetchFrameByTime(generator, timeUs,(OH_AVImageGenerator_QueryOptions)options, &pixelMap);// 异常处理。if (avErrCode != AV_ERR_OK || !pixelMap) {OH_AVImageGenerator_Release(generator);napi_throw_error(env, "EFAILED", "FetchFrameByTime failed");return nullptr;}// 将nativePixelMap对象转换为PixelMapnapi对象。napi_value pixelmapNapi = nullptr;Image_ErrorCode errCode = OH_PixelmapNative_ConvertPixelmapNativeToNapi(env, pixelMap, &pixelmapNapi);// 释放OH_PixelmapNative资源。OH_PixelmapNative_Release(pixelMap);// 释放OH_AVImageGenerator资源。OH_AVImageGenerator_Release(generator);// 异常处理。if (errCode != IMAGE_SUCCESS) {napi_throw_error(env, "EFAILED", "Convert PixelMap failed");return nullptr;}return pixelmapNapi;} -
释放资源:调用OH_AVImageGenerator_Release()销毁实例,释放资源。
// 释放OH_AVImageGenerator资源。OH_AVImageGenerator_Release(generator);
运行示例工程
参考以下示例,获取一个视频指定时间的视频帧。
-
新建工程,下载完整示例工程,并将示例工程的资源复制到对应目录。
AVImageGeneratorNDKentry/src/main/ets/└── pages└── Index.ets (获取缩略图界面)entry/src/main/├── cpp│ ├── types│ │ └── libentry│ │ └── Index.d.ts (NDK函数对应的js映射)│ ├── CMakeLists.txt (CMake脚本)│ └── napi_init.cpp (NDK函数)└── resources├── base│ ├── element│ │ ├── color.json│ │ ├── float.json│ │ └── string.json│ └── media│└── rawfile└── H264_AAC.mp4 (视频资源) -
编译新建工程并运行。