From 198bf1c129810332759afdfa01de9c108c90d966 Mon Sep 17 00:00:00 2001 From: wangshi Date: Mon, 15 Apr 2024 15:19:42 +0800 Subject: [PATCH 1/3] add ffmpeg decode Signed-off-by: wangshi --- .../entry/src/main/cpp/CMakeLists.txt | 10 + .../napitutorials/entry/src/main/cpp/init.cpp | 2 +- .../ffmpegcase/manager/plugin_manager.cpp | 1 - .../ncpp/ffmpegcase/render/plugin_render.cpp | 435 +++++++++++++++++- .../ncpp/ffmpegcase/render/plugin_render.h | 3 + .../main/ets/interface/XComponentContext.d.ts | 20 +- .../entry/src/main/ets/pages/ncpp/NcppMgr.ets | 4 + .../ets/pages/ncpp/ffmpegfuncs/eglfuncs.ets | 127 +++++ .../pages/ncpp/ffmpegfuncs/ffmpegfuncs.ets | 67 +-- .../main/resources/base/element/string.json | 4 + .../resources/base/profile/main_pages.json | 3 +- .../main/resources/en_US/element/string.json | 4 + .../main/resources/zh_CN/element/string.json | 4 + 13 files changed, 643 insertions(+), 41 deletions(-) create mode 100644 examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/eglfuncs.ets diff --git a/examples/napitutorials/entry/src/main/cpp/CMakeLists.txt b/examples/napitutorials/entry/src/main/cpp/CMakeLists.txt index 91ad5c03..e4a6c947 100644 --- a/examples/napitutorials/entry/src/main/cpp/CMakeLists.txt +++ b/examples/napitutorials/entry/src/main/cpp/CMakeLists.txt @@ -4,11 +4,13 @@ project(NapiSample) set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) set(CJSON_LIB_PATH ${NATIVERENDER_ROOT_PATH}/../../../libs/${OHOS_ARCH}) +set(FFMPEG_LIB_PATH ${NATIVERENDER_ROOT_PATH}/../../../libs/${OHOS_ARCH}) add_definitions(-DOHOS_PLATFORM) include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include ${NATIVERENDER_ROOT_PATH}/thirdparty/cJSON/${OHOS_ARCH}/include + ${NATIVERENDER_ROOT_PATH}/thirdparty/FFmpeg/${OHOS_ARCH}/include ${NATIVERENDER_ROOT_PATH}/ncpp/ffmpegcase) add_library(entry SHARED @@ -87,12 +89,20 @@ find_library( uv ) +# ${FFMPEG_LIB_PATH}/libavcodec.so +# ${FFMPEG_LIB_PATH}/libavformat.so +# ${FFMPEG_LIB_PATH}/libavdevice.so +# ${FFMPEG_LIB_PATH}/libavfilter.so +# ${FFMPEG_LIB_PATH}/libavutil.so target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so librawfile.z.so libhilog_ndk.z.so ${CJSON_LIB_PATH}/libcjson.so + ${FFMPEG_LIB_PATH}/libavformat.so + ${FFMPEG_LIB_PATH}/libavcodec.so + ${FFMPEG_LIB_PATH}/libavutil.so ${EGL-lib} ${GLES-lib} ${hilog-lib} diff --git a/examples/napitutorials/entry/src/main/cpp/init.cpp b/examples/napitutorials/entry/src/main/cpp/init.cpp index 996ec015..345c85db 100644 --- a/examples/napitutorials/entry/src/main/cpp/init.cpp +++ b/examples/napitutorials/entry/src/main/cpp/init.cpp @@ -69,7 +69,7 @@ static napi_value Init(napi_env env, napi_value exports) {"getContext", nullptr, NativeXComponentSample::PluginManager::GetContext, nullptr, nullptr, nullptr, napi_default, nullptr} }; - napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + napi_define_properties(env, exports, sizeof(descArr) / sizeof(descArr[0]), descArr); NativeXComponentSample::PluginManager::GetInstance()->Export(env, exports); size_t len = sizeof(descArr) / sizeof(napi_property_descriptor); diff --git a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/manager/plugin_manager.cpp b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/manager/plugin_manager.cpp index f4f59a0f..e8ff56a4 100644 --- a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/manager/plugin_manager.cpp +++ b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/manager/plugin_manager.cpp @@ -14,7 +14,6 @@ */ #include "plugin_manager.h" - #include #include #include diff --git a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp index 8ce644e0..1f1dc47e 100644 --- a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp +++ b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp @@ -13,16 +13,97 @@ * limitations under the License. */ +#include #include #include #include #include #include - #include "../common/common.h" #include "../manager/plugin_manager.h" #include "plugin_render.h" +extern "C" { + #include "libavformat/avformat.h" + #include "libavcodec/avcodec.h" + + // 自定义 avio_read_packet 函数 + int custom_avio_read_packet(void *opaque, uint8_t *buf, int buf_size) { + FILE *file = ((FILE *)opaque); // 将 void 指针转换为 int 指针,并取得文件描述符 + if (!file) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "custom_avio_read_packet file is null"); + return AVERROR_EOF; + } + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "PluginRender", "read_packet %{public}d", buf_size); + size_t bytes_read = fread(buf, 1, buf_size, file); // 从文件描述符中读取数据 + if (bytes_read <= 0) { + if (feof(file)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "custom_avio_read_packet file eof %{public}zu", + bytes_read); + return AVERROR_EOF; + } else { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "custom_avio_read_packet file eio"); + return AVERROR_EOF; + } + } + + if (buf_size > bytes_read) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "read end %{public}zu", bytes_read); + return 0; + } + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "PluginRender", "read_packet bytes[%{public}zu],bufsize[%{public}d]", + bytes_read, buf_size); + return (int)bytes_read; + } + + int open_codec_context(int *stream_idx, AVCodecContext **dec_ctx, AVFormatContext *fmt_ctx, + enum AVMediaType type) { + int ret, stream_index; + AVStream *st; + const AVCodec *dec = NULL; + + ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); + if (ret < 0) { + fprintf(stderr, "Could not find %s stream in input file '%s'\n", av_get_media_type_string(type), + "srcfile"); + return ret; + } else { + stream_index = ret; + st = fmt_ctx->streams[stream_index]; + + /* find decoder for the stream */ + dec = avcodec_find_decoder(st->codecpar->codec_id); + if (!dec) { + fprintf(stderr, "Failed to find %s codec\n", av_get_media_type_string(type)); + return AVERROR(EINVAL); + } + + /* Allocate a codec context for the decoder */ + *dec_ctx = avcodec_alloc_context3(dec); + if (!*dec_ctx) { + fprintf(stderr, "Failed to allocate the %s codec context\n", av_get_media_type_string(type)); + return AVERROR(ENOMEM); + } + + /* Copy codec parameters from input stream to output codec context */ + if ((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) { + fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n", + av_get_media_type_string(type)); + return ret; + } + + /* Init the decoders */ + if ((ret = avcodec_open2(*dec_ctx, dec, NULL)) < 0) { + fprintf(stderr, "Failed to open %s codec\n", av_get_media_type_string(type)); + return ret; + } + *stream_idx = stream_index; + } + + return 0; + } +} + namespace NativeXComponentSample { namespace { constexpr int32_t NUM_9 = 9; @@ -41,7 +122,7 @@ namespace { constexpr int32_t NUM_18 = 18; void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { - OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB"); + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "Callback", "OnSurfaceCreatedCB"); if ((component == nullptr) || (window == nullptr)) { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB: component or window is null"); @@ -257,15 +338,357 @@ void PluginRender::Export(napi_env env, napi_value exports) } napi_property_descriptor desc[] = { - {"drawPattern", nullptr, PluginRender::NapiDrawPattern, nullptr, nullptr, - nullptr, napi_default, nullptr}, - {"getStatus", nullptr, PluginRender::TestGetXComponentStatus, nullptr, nullptr, - nullptr, napi_default, nullptr}}; + {"drawPattern", nullptr, PluginRender::NapiDrawPattern, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"getStatus", nullptr, PluginRender::TestGetXComponentStatus, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"play", nullptr, PluginRender::NapiPlay, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"stop", nullptr, PluginRender::NapiStop, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"getInfo", nullptr, PluginRender::NapiGetInfo, nullptr, nullptr, nullptr, napi_default, nullptr}, + }; if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: napi_define_properties failed"); } } +// NAPI registration method type napi_callback. If no value is returned, nullptr is returned. +napi_value PluginRender::NapiPlay(napi_env env, napi_callback_info info) { + size_t argc = NUM_3; + napi_value args[NUM_3]; + uint32_t fd = 0; + uint32_t foff = 0; + uint32_t flen = 0; + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: env or info is null"); + return nullptr; + } + + napi_value thisArg; + if (napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_get_cb_info fail"); + return nullptr; + } + + napi_get_value_uint32(env, args[0], &fd); + napi_get_value_uint32(env, args[1], &foff); + napi_get_value_uint32(env, args[NUM_2], &flen); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", + "fd:%{public}d, foff:%{public}d, flen:%{public}d!", fd, foff, flen); + + napi_value exportInstance; + if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", + "NapiDrawPattern: napi_get_named_property fail"); + return nullptr; + } + + OH_NativeXComponent *nativeXComponent = nullptr; + if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_unwrap fail"); + return nullptr; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", + "NapiDrawPattern: Unable to get XComponent id"); + return nullptr; + } + + std::string id(idStr); + PluginRender *render = PluginRender::GetInstance(id); + if (render != nullptr) { + render->eglCore_->fd_ = fd; + render->eglCore_->foff_ = foff; + render->eglCore_->flen_ = flen; + render->eglCore_->DrawBmp(fd, foff, flen); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->eglCore_->Draw() executed"); + } + return nullptr; +} + +// NAPI registration method type napi_callback. If no value is returned, nullptr is returned. +napi_value PluginRender::NapiStop(napi_env env, napi_callback_info info) { + size_t argc = NUM_3; + napi_value args[NUM_3]; + uint32_t fd = 0; + uint32_t foff = 0; + uint32_t flen = 0; + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: env or info is null"); + return nullptr; + } + + napi_value thisArg; + if (napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_get_cb_info fail"); + return nullptr; + } + + napi_get_value_uint32(env, args[0], &fd); + napi_get_value_uint32(env, args[1], &foff); + napi_get_value_uint32(env, args[NUM_2], &flen); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", + "fd:%{public}d, foff:%{public}d, flen:%{public}d!", fd, foff, flen); + + napi_value exportInstance; + if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", + "NapiDrawPattern: napi_get_named_property fail"); + return nullptr; + } + + OH_NativeXComponent *nativeXComponent = nullptr; + if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawPattern: napi_unwrap fail"); + return nullptr; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", + "NapiDrawPattern: Unable to get XComponent id"); + return nullptr; + } + + std::string id(idStr); + PluginRender *render = PluginRender::GetInstance(id); + if (render != nullptr) { + render->eglCore_->fd_ = fd; + render->eglCore_->foff_ = foff; + render->eglCore_->flen_ = flen; + render->eglCore_->DrawBmp(fd, foff, flen); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->eglCore_->Draw() executed"); + } + return nullptr; +} + +struct RescontCallbackData { + napi_async_work asyncWork = nullptr; + napi_deferred deferred = nullptr; + napi_ref callback = nullptr; + unsigned char *buffer = 0; + uint32_t fd = 0; + uint32_t foff = 0; + uint32_t flen = 0; + uint32_t blen = 0; + napi_value result = nullptr; + +}; + +static void RescontExecuteCB(napi_env env, void *data) { + RescontCallbackData *callbackData = reinterpret_cast(data); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", + "RescontExecuteCB blen:%{public}d", callbackData->fd); + + int ret = 0; + uint32_t fbufLen = 8192; + unsigned char *fbuf = (unsigned char *)av_malloc(fbufLen); + char dumpBuf[256]; + + uint32_t fd = callbackData->fd; + uint32_t foff = callbackData->foff; + uint32_t flen = callbackData->flen; + + AVFormatContext *formatContext = NULL; + AVIOContext *avioContext = nullptr; + AVCodecContext *video_dec_ctx = NULL; + AVCodecContext *audio_dec_ctx = NULL; + AVFrame *frame = NULL; + AVPacket *pkt = NULL; + int video_frame_count = 0; + int audio_frame_count = 0; + + int video_stream_idx = -1; + int audio_stream_idx = -1; + + FILE *file = fdopen(fd, "r"); + if (file == NULL) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiGetInfo fdopen failed!"); + free(fbuf); + return; + } + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "fdopen "); + // 取文件 + if (fseek(file, foff, SEEK_SET) != 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiGetInfo fseek failed!"); + fclose(file); + free(fbuf); + return; + } + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "fseek %{public}ld", foff); + avioContext = avio_alloc_context(fbuf, fbufLen, 0, (void *)file, &custom_avio_read_packet, NULL, NULL); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "avio_alloc_context"); + if (!avioContext) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "avio_alloc_context failed"); + av_free(avioContext->buffer); + avio_context_free(&avioContext); + fclose(file); + return; + } + + formatContext = avformat_alloc_context(); + if (!formatContext) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "avformat_alloc_context failed"); + av_free(avioContext->buffer); + avio_context_free(&avioContext); + fclose(file); + return; + } + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "avformat_alloc_context"); + formatContext->pb = avioContext; + ret = avformat_open_input(&formatContext, NULL, NULL, NULL); + if (ret < 0) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "avformat_open_input err %{public}d", ret); + avformat_free_context(formatContext); + av_free(avioContext->buffer); + avio_context_free(&avioContext); + fclose(file); + return; + } + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "avformat_open_input"); + // 获取流信息 + ret = avformat_find_stream_info(formatContext, NULL); + if (ret < 0) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "avformat_find_stream_info err %{public}d", + ret); + avformat_close_input(&formatContext); + fclose(file); + return; + } + + napi_value videoRes; + napi_value audioRes; + if (open_codec_context(&video_stream_idx, &video_dec_ctx, formatContext, AVMEDIA_TYPE_VIDEO) >= 0) { + avcodec_string(dumpBuf, sizeof(dumpBuf), video_dec_ctx, 0); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "video[%{public}s]", dumpBuf); + napi_create_string_utf8(env, dumpBuf, strlen(dumpBuf), &videoRes); + } + if (open_codec_context(&audio_stream_idx, &audio_dec_ctx, formatContext, AVMEDIA_TYPE_AUDIO) >= 0) { + avcodec_string(dumpBuf, sizeof(dumpBuf), audio_dec_ctx, 0); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "audio[%{public}s]", dumpBuf); + napi_create_string_utf8(env, dumpBuf, strlen(dumpBuf), &audioRes); + } + + napi_value instance; + napi_create_object(env, &instance); + napi_set_named_property(env, instance, "videoDec", videoRes); + napi_set_named_property(env, instance, "audioDec", audioRes); + callbackData->result = instance; +} + +static void RescontCompleteCB(napi_env env, napi_status status, void *data) { + RescontCallbackData *callbackData = reinterpret_cast(data); + napi_value result = callbackData->result; + if (callbackData->result != nullptr) { + napi_resolve_deferred(env, callbackData->deferred, result); + } else { + napi_reject_deferred(env, callbackData->deferred, result); + } + + napi_delete_async_work(env, callbackData->asyncWork); + delete callbackData; +} + +// NAPI registration method type napi_callback. If no value is returned, nullptr is returned. +napi_value PluginRender::NapiGetInfo(napi_env env, napi_callback_info info) { + size_t argc = NUM_3; + napi_value args[NUM_3]; + uint32_t fd = 0; + uint32_t foff = 0; + uint32_t flen = 0; + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiGetInfo"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiGetInfo: env or info is null"); + return nullptr; + } + + napi_value thisArg; + if (napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiGetInfo: napi_get_cb_info fail"); + return nullptr; + } + + napi_get_value_uint32(env, args[0], &fd); + napi_get_value_uint32(env, args[1], &foff); + napi_get_value_uint32(env, args[NUM_2], &flen); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", + "fd:%{public}d, foff:%{public}d, flen:%{public}d!", fd, foff, flen); + + napi_value exportInstance; + if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", + "NapiGetInfo: napi_get_named_property fail"); + return nullptr; + } + + OH_NativeXComponent *nativeXComponent = nullptr; + if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiGetInfo: napi_unwrap fail"); + return nullptr; + } + + char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; + uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; + if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", + "NapiGetInfo: Unable to get XComponent id"); + return nullptr; + } + + std::string id(idStr); + PluginRender *render = PluginRender::GetInstance(id); + if (render != nullptr) { + render->eglCore_->fd_ = fd; + render->eglCore_->foff_ = foff; + render->eglCore_->flen_ = flen; + + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + napi_create_promise(env, &deferred, &promise); + + auto callbackData = new RescontCallbackData(); + callbackData->deferred = deferred; + + void *arrayData = nullptr; + size_t length = 0; + napi_valuetype result = napi_undefined; + napi_typeof(env, args[0], &result); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "napi_valuetype :%{public}d", result); + napi_typedarray_type type = napi_int8_array; + + napi_value arraybuffer = nullptr; + size_t byteOffset = 0; + napi_get_typedarray_info(env, args[0], &type, &length, &arrayData, &arraybuffer, &byteOffset); + + callbackData->buffer = (unsigned char *)arrayData; + callbackData->fd = fd; + callbackData->foff = foff; + callbackData->flen = flen; + callbackData->blen = length; + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", + "AsyncRescont buffer:%{public}p", callbackData->buffer); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", + "AsyncRescont blen:%{public}d", callbackData->blen); + + napi_value resourceName = nullptr; + napi_create_string_utf8(env, "RescontAsyncCallback", NAPI_AUTO_LENGTH, &resourceName); + // 创建异步任务 + napi_create_async_work(env, nullptr, resourceName, RescontExecuteCB, RescontCompleteCB, callbackData, + &callbackData->asyncWork); + // 将异步任务加入队列 + napi_queue_async_work(env, callbackData->asyncWork); + + return promise; + } + return nullptr; +} + // NAPI registration method type napi_callback. If no value is returned, nullptr is returned. napi_value PluginRender::NapiDrawPattern(napi_env env, napi_callback_info info) { diff --git a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.h b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.h index e019286a..f00522e9 100644 --- a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.h +++ b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.h @@ -37,6 +37,9 @@ public: static PluginRender* GetInstance(std::string& id); static void Release(std::string& id); static napi_value NapiDrawPattern(napi_env env, napi_callback_info info); + static napi_value NapiStop(napi_env env, napi_callback_info info); + static napi_value NapiPlay(napi_env env, napi_callback_info info); + static napi_value NapiGetInfo(napi_env env, napi_callback_info info); static napi_value TestGetXComponentStatus(napi_env env, napi_callback_info info); void Export(napi_env env, napi_value exports); void OnSurfaceChanged(OH_NativeXComponent* component, void* window); diff --git a/examples/napitutorials/entry/src/main/ets/interface/XComponentContext.d.ts b/examples/napitutorials/entry/src/main/ets/interface/XComponentContext.d.ts index 0b092cbe..0ee31e2d 100644 --- a/examples/napitutorials/entry/src/main/ets/interface/XComponentContext.d.ts +++ b/examples/napitutorials/entry/src/main/ets/interface/XComponentContext.d.ts @@ -13,13 +13,21 @@ * limitations under the License. */ -export default interface XComponentContext { - drawPattern(a: number, b: number, c: number): void; - - getStatus(): XComponentContextStatus; -}; - type XComponentContextStatus = { hasDraw: boolean, hasChangeColor: boolean, }; + +type FFmpegDes = { + videoDec: string; + audioDec: string; +}; + +export interface XComponentContext { + drawPattern(a: number, b: number, c: number): void; + play(a: number, b: number, c: number): void; + stop(a: number, b: number, c: number): void; + getInfo(a: number, b: number, c: number): Promise; + getStatus(): XComponentContextStatus; +}; + diff --git a/examples/napitutorials/entry/src/main/ets/pages/ncpp/NcppMgr.ets b/examples/napitutorials/entry/src/main/ets/pages/ncpp/NcppMgr.ets index dfb3aa9b..e7786bee 100644 --- a/examples/napitutorials/entry/src/main/ets/pages/ncpp/NcppMgr.ets +++ b/examples/napitutorials/entry/src/main/ets/pages/ncpp/NcppMgr.ets @@ -34,6 +34,10 @@ const FFMPEG_MANAGEMENT: ThirdLevelCategory = childNodes: [ { title: $r('app.string.napi_egl_texture_bmp'), + url: 'pages/ncpp/ffmpegfuncs/eglfuncs' + }, + { + title: $r('app.string.napi_ffmpeg_decode'), url: 'pages/ncpp/ffmpegfuncs/ffmpegfuncs' } ] diff --git a/examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/eglfuncs.ets b/examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/eglfuncs.ets new file mode 100644 index 00000000..288ee588 --- /dev/null +++ b/examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/eglfuncs.ets @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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 router from '@ohos.router'; +import image from '@ohos.multimedia.image'; +import Logger from '../../../util/Logger'; +import { TitleBar } from '../../../common/TitleBar' +import hilog from '@ohos.hilog'; +import {XComponentContext} from "../../../interface/XComponentContext.d" +import resourceManager from '@ohos.resourceManager'; + +const TAG: string = 'napi_ffmpegcase'; + +@Entry +@Component +struct eglfuncs { + private btnFontColor: Resource = $r('app.color.white'); + @State isSetInstance: Boolean = false; + @State currentStatus: string = "init"; + private xComponentContext: XComponentContext | undefined = undefined; + private resfname: string = 'tj.bmp' + private mp4fname: string = 'test1.mp4' + + build() { + Column() { + Row() { + Text('Native XComponent Sample') + .fontSize('24fp') + .fontWeight(500) + .margin({ + left: 24, + top: 12 + }) + } + .margin({ top: 24 }) + .width('100%') + .height(56) + + Column({ space: 10 }) { + XComponent({ + id: 'xcomponentId', + type: XComponentType.SURFACE, + libraryname: 'entry' + }) + .onLoad((xComponentContext) => { + this.xComponentContext = xComponentContext as XComponentContext; + this.currentStatus = "index"; + }) + .onDestroy(() => { + console.log('onDestroy'); + }) + .id("xcomponent") + + Text(this.currentStatus) + .fontSize('24fp') + .fontWeight(500) + } + .onClick(() => { + let hasChangeColor: boolean = false; + if (this.xComponentContext && this.xComponentContext.getStatus()) { + hasChangeColor = this.xComponentContext.getStatus().hasChangeColor; + } + if (hasChangeColor) { + this.currentStatus = "change color"; + } + }) + .margin({ + top: 27, + left: 12, + right: 12 + }) + .height('40%') + .width('90%') + + Row() { + Column() { + Button('Draw Img') + .fontSize('16fp') + .fontWeight(500) + .margin({ bottom: 24 }) + .onClick(() => { + getContext().resourceManager.getRawFd(this.resfname) + .then((value: resourceManager.RawFileDescriptor) => { + let fd = value.fd; + let offset = value.offset; + let length = value.length; + hilog.info(0x0000, 'testTag', `getRawFd ${fd} ${offset} ${length}`); + + if (this.xComponentContext) { + this.xComponentContext.drawPattern(fd, offset, length); + + let hasDraw: boolean = false; + if (this.xComponentContext.getStatus()) { + hasDraw = this.xComponentContext.getStatus().hasDraw; + } + if (hasDraw) { + this.currentStatus = "draw star"; + } + } + }) + + }) + .width('53.6%') + .height(40) + } + } + .width('100%') + .justifyContent(FlexAlign.Center) + .alignItems(VerticalAlign.Bottom) + .layoutWeight(1) + } + .width('100%') + .height('100%') + } +} diff --git a/examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/ffmpegfuncs.ets b/examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/ffmpegfuncs.ets index 77310200..260ba8eb 100644 --- a/examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/ffmpegfuncs.ets +++ b/examples/napitutorials/entry/src/main/ets/pages/ncpp/ffmpegfuncs/ffmpegfuncs.ets @@ -18,7 +18,7 @@ import image from '@ohos.multimedia.image'; import Logger from '../../../util/Logger'; import { TitleBar } from '../../../common/TitleBar' import hilog from '@ohos.hilog'; -import XComponentContext from "../../../interface/XComponentContext.d" +import {XComponentContext, FFmpegDes} from "../../../interface/XComponentContext.d" import resourceManager from '@ohos.resourceManager'; const TAG: string = 'napi_ffmpegcase'; @@ -29,13 +29,16 @@ struct ffmpegfuncs { private btnFontColor: Resource = $r('app.color.white'); @State isSetInstance: Boolean = false; @State currentStatus: string = "init"; + @State videoDec: string = ""; + @State audioDec: string = ""; private xComponentContext: XComponentContext | undefined = undefined; private resfname: string = 'tj.bmp' + private mp4fname: string = 'test1.mp4' build() { Column() { Row() { - Text('Native XComponent Sample') + Text('FFmpeg Sample') .fontSize('24fp') .fontWeight(500) .margin({ @@ -65,6 +68,16 @@ struct ffmpegfuncs { Text(this.currentStatus) .fontSize('24fp') .fontWeight(500) + TextArea({text: this.videoDec}) + .fontSize('18fp') + .fontWeight(500) + .height(120) + .enabled(false) + TextArea({text:this.audioDec}) + .fontSize('18fp') + .fontWeight(500) + .height(120) + .enabled(false) } .onClick(() => { let hasChangeColor: boolean = false; @@ -84,33 +97,35 @@ struct ffmpegfuncs { .width('90%') Row() { - Button('Draw Star') - .fontSize('16fp') - .fontWeight(500) - .margin({ bottom: 24 }) - .onClick(() => { - getContext().resourceManager.getRawFd(this.resfname) - .then((value: resourceManager.RawFileDescriptor) => { - let fd = value.fd; - let offset = value.offset; - let length = value.length; - hilog.info(0x0000, 'testTag', `getRawFd ${fd} ${offset} ${length}`); + Column() { + Button('OpenMp4') + .fontSize('16fp') + .fontWeight(500) + .margin({ bottom: 24 }) + .onClick(() => { + getContext().resourceManager.getRawFd(this.mp4fname) + .then((value: resourceManager.RawFileDescriptor) => { + let fd = value.fd; + let offset = value.offset; + let length = value.length; + hilog.info(0x0000, 'testTag', `getRawFd ${fd} ${offset} ${length}`); - if (this.xComponentContext) { - this.xComponentContext.drawPattern(fd, offset, length); - let hasDraw: boolean = false; - if (this.xComponentContext.getStatus()) { - hasDraw = this.xComponentContext.getStatus().hasDraw; + if (this.xComponentContext) { + this.xComponentContext.getInfo(fd, offset, length).then((des: FFmpegDes) => { + hilog.info(0x0000, 'testTag', `getInfo ${JSON.stringify(des)}`); + hilog.info(0x0000, 'testTag', `video ${des.videoDec}`); + hilog.info(0x0000, 'testTag', `audio ${des.audioDec}`); + this.currentStatus = "getInfo"; + this.videoDec = des.videoDec; + this.audioDec = des.audioDec; + }); } - if (hasDraw) { - this.currentStatus = "draw star"; - } - } - }) + }) - }) - .width('53.6%') - .height(40) + }) + .width('53.6%') + .height(40) + } } .width('100%') .justifyContent(FlexAlign.Center) diff --git a/examples/napitutorials/entry/src/main/resources/base/element/string.json b/examples/napitutorials/entry/src/main/resources/base/element/string.json index 8dd0f9e4..fb8ce6f4 100644 --- a/examples/napitutorials/entry/src/main/resources/base/element/string.json +++ b/examples/napitutorials/entry/src/main/resources/base/element/string.json @@ -936,6 +936,10 @@ "name": "napi_egl_texture_bmp", "value": "EGL Texture Render" }, + { + "name": "napi_ffmpeg_decode", + "value": "FFmpeg Decode" + }, { "name": "napi_opencv_gray", "value": "OpenCV Convert Color" diff --git a/examples/napitutorials/entry/src/main/resources/base/profile/main_pages.json b/examples/napitutorials/entry/src/main/resources/base/profile/main_pages.json index fc31edb2..d74a8cd7 100644 --- a/examples/napitutorials/entry/src/main/resources/base/profile/main_pages.json +++ b/examples/napitutorials/entry/src/main/resources/base/profile/main_pages.json @@ -65,8 +65,9 @@ "pages/javascript/jsabstractops/napicoercetobool", "pages/javascript/jsabstractops/napicoercetonumber", "pages/ncpp/cjsonfuncs/cjsonfuncs", + "pages/ncpp/ffmpegfuncs/eglfuncs", "pages/ncpp/ffmpegfuncs/ffmpegfuncs", - "pages/ncpp/opencvfuncs/opencvfuncs" + "pages/ncpp/opencvfuncs/opencvfuncs", "pages/javascript/jsabstractops/napicoercetoobject", "pages/javascript/jsabstractops/napicoercetostring" ] diff --git a/examples/napitutorials/entry/src/main/resources/en_US/element/string.json b/examples/napitutorials/entry/src/main/resources/en_US/element/string.json index 908cf845..17fab7d9 100644 --- a/examples/napitutorials/entry/src/main/resources/en_US/element/string.json +++ b/examples/napitutorials/entry/src/main/resources/en_US/element/string.json @@ -936,6 +936,10 @@ "name": "napi_egl_texture_bmp", "value": "EGL Texture Render" }, + { + "name": "napi_ffmpeg_decode", + "value": "FFmpeg Decode" + }, { "name": "napi_opencv_gray", "value": "OpenCV Convert Color" diff --git a/examples/napitutorials/entry/src/main/resources/zh_CN/element/string.json b/examples/napitutorials/entry/src/main/resources/zh_CN/element/string.json index 20a1851c..2a9175fd 100644 --- a/examples/napitutorials/entry/src/main/resources/zh_CN/element/string.json +++ b/examples/napitutorials/entry/src/main/resources/zh_CN/element/string.json @@ -5460,6 +5460,10 @@ "name": "napi_egl_texture_bmp", "value": "EGL材质渲染" }, + { + "name": "napi_ffmpeg_decode", + "value": "FFmpeg解码" + }, { "name": "napi_opencv_gray", "value": "灰度化相片" -- Gitee From ec9970bdfcfe6c16d96a522b1b76a8b7df53ac14 Mon Sep 17 00:00:00 2001 From: wangshi Date: Mon, 15 Apr 2024 16:00:05 +0800 Subject: [PATCH 2/3] fix code check Signed-off-by: wangshi --- .../ncpp/ffmpegcase/render/plugin_render.cpp | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp index 1f1dc47e..ce5e4436 100644 --- a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp +++ b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include +#include #include #include #include @@ -28,7 +28,8 @@ extern "C" { #include "libavcodec/avcodec.h" // 自定义 avio_read_packet 函数 - int custom_avio_read_packet(void *opaque, uint8_t *buf, int buf_size) { + int custom_avio_read_packet(void *opaque, uint8_t *buf, int buf_size) + { FILE *file = ((FILE *)opaque); // 将 void 指针转换为 int 指针,并取得文件描述符 if (!file) { OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "custom_avio_read_packet file is null"); @@ -57,8 +58,10 @@ extern "C" { } int open_codec_context(int *stream_idx, AVCodecContext **dec_ctx, AVFormatContext *fmt_ctx, - enum AVMediaType type) { - int ret, stream_index; + enum AVMediaType type) + { + int ret = 0; + int stream_index = 0; AVStream *st; const AVCodec *dec = NULL; @@ -350,7 +353,8 @@ void PluginRender::Export(napi_env env, napi_value exports) } // NAPI registration method type napi_callback. If no value is returned, nullptr is returned. -napi_value PluginRender::NapiPlay(napi_env env, napi_callback_info info) { +napi_value PluginRender::NapiPlay(napi_env env, napi_callback_info info) +{ size_t argc = NUM_3; napi_value args[NUM_3]; uint32_t fd = 0; @@ -409,7 +413,8 @@ napi_value PluginRender::NapiPlay(napi_env env, napi_callback_info info) { } // NAPI registration method type napi_callback. If no value is returned, nullptr is returned. -napi_value PluginRender::NapiStop(napi_env env, napi_callback_info info) { +napi_value PluginRender::NapiStop(napi_env env, napi_callback_info info) +{ size_t argc = NUM_3; napi_value args[NUM_3]; uint32_t fd = 0; @@ -471,18 +476,18 @@ struct RescontCallbackData { napi_async_work asyncWork = nullptr; napi_deferred deferred = nullptr; napi_ref callback = nullptr; - unsigned char *buffer = 0; + unsigned char *buffer = nullptr; uint32_t fd = 0; uint32_t foff = 0; uint32_t flen = 0; uint32_t blen = 0; napi_value result = nullptr; - }; -static void RescontExecuteCB(napi_env env, void *data) { +static void RescontExecuteCB(napi_env env, void *data) +{ RescontCallbackData *callbackData = reinterpret_cast(data); - OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "RescontExecuteCB blen:%{public}d", callbackData->fd); int ret = 0; @@ -496,15 +501,15 @@ static void RescontExecuteCB(napi_env env, void *data) { AVFormatContext *formatContext = NULL; AVIOContext *avioContext = nullptr; - AVCodecContext *video_dec_ctx = NULL; - AVCodecContext *audio_dec_ctx = NULL; + AVCodecContext *videoDecCtx = NULL; + AVCodecContext *audioDecCtx = NULL; AVFrame *frame = NULL; AVPacket *pkt = NULL; - int video_frame_count = 0; - int audio_frame_count = 0; + int videoFrameCount = 0; + int audioFrameCount = 0; - int video_stream_idx = -1; - int audio_stream_idx = -1; + int videoStreamIdx = -1; + int audioStreamIdx = -1; FILE *file = fdopen(fd, "r"); if (file == NULL) { @@ -563,13 +568,13 @@ static void RescontExecuteCB(napi_env env, void *data) { napi_value videoRes; napi_value audioRes; - if (open_codec_context(&video_stream_idx, &video_dec_ctx, formatContext, AVMEDIA_TYPE_VIDEO) >= 0) { - avcodec_string(dumpBuf, sizeof(dumpBuf), video_dec_ctx, 0); + if (open_codec_context(&videoStreamIdx, &videoDecCtx, formatContext, AVMEDIA_TYPE_VIDEO) >= 0) { + avcodec_string(dumpBuf, sizeof(dumpBuf), videoDecCtx, 0); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "video[%{public}s]", dumpBuf); napi_create_string_utf8(env, dumpBuf, strlen(dumpBuf), &videoRes); } - if (open_codec_context(&audio_stream_idx, &audio_dec_ctx, formatContext, AVMEDIA_TYPE_AUDIO) >= 0) { - avcodec_string(dumpBuf, sizeof(dumpBuf), audio_dec_ctx, 0); + if (open_codec_context(&audioStreamIdx, &audioDecCtx, formatContext, AVMEDIA_TYPE_AUDIO) >= 0) { + avcodec_string(dumpBuf, sizeof(dumpBuf), audioDecCtx, 0); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "audio[%{public}s]", dumpBuf); napi_create_string_utf8(env, dumpBuf, strlen(dumpBuf), &audioRes); } @@ -581,7 +586,8 @@ static void RescontExecuteCB(napi_env env, void *data) { callbackData->result = instance; } -static void RescontCompleteCB(napi_env env, napi_status status, void *data) { +static void RescontCompleteCB(napi_env env, napi_status status, void *data) +{ RescontCallbackData *callbackData = reinterpret_cast(data); napi_value result = callbackData->result; if (callbackData->result != nullptr) { @@ -595,7 +601,8 @@ static void RescontCompleteCB(napi_env env, napi_status status, void *data) { } // NAPI registration method type napi_callback. If no value is returned, nullptr is returned. -napi_value PluginRender::NapiGetInfo(napi_env env, napi_callback_info info) { +napi_value PluginRender::NapiGetInfo(napi_env env, napi_callback_info info) +{ size_t argc = NUM_3; napi_value args[NUM_3]; uint32_t fd = 0; -- Gitee From 777ce65ce6851af639938e68010346f6f7f527ae Mon Sep 17 00:00:00 2001 From: wangshi Date: Mon, 15 Apr 2024 17:07:37 +0800 Subject: [PATCH 3/3] fix code check Signed-off-by: wangshi --- .../ncpp/ffmpegcase/render/plugin_render.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp index ce5e4436..4dce0422 100644 --- a/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp +++ b/examples/napitutorials/entry/src/main/cpp/ncpp/ffmpegcase/render/plugin_render.cpp @@ -28,19 +28,19 @@ extern "C" { #include "libavcodec/avcodec.h" // 自定义 avio_read_packet 函数 - int custom_avio_read_packet(void *opaque, uint8_t *buf, int buf_size) + int custom_avio_read_packet(void *opaque, uint8_t *buf, int bufSize) { FILE *file = ((FILE *)opaque); // 将 void 指针转换为 int 指针,并取得文件描述符 if (!file) { OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "custom_avio_read_packet file is null"); return AVERROR_EOF; } - OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "PluginRender", "read_packet %{public}d", buf_size); - size_t bytes_read = fread(buf, 1, buf_size, file); // 从文件描述符中读取数据 - if (bytes_read <= 0) { + OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "PluginRender", "read_packet %{public}d", bufSize); + size_t bytesRead = fread(buf, 1, bufSize, file); // 从文件描述符中读取数据 + if (bytesRead <= 0) { if (feof(file)) { OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "custom_avio_read_packet file eof %{public}zu", - bytes_read); + bytesRead); return AVERROR_EOF; } else { OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "custom_avio_read_packet file eio"); @@ -48,31 +48,31 @@ extern "C" { } } - if (buf_size > bytes_read) { - OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "read end %{public}zu", bytes_read); + if (bufSize > bytesRead) { + OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "PluginRender", "read end %{public}zu", bytesRead); return 0; } OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "PluginRender", "read_packet bytes[%{public}zu],bufsize[%{public}d]", - bytes_read, buf_size); - return (int)bytes_read; + bytesRead, bufSize); + return (int)bytesRead; } - int open_codec_context(int *stream_idx, AVCodecContext **dec_ctx, AVFormatContext *fmt_ctx, - enum AVMediaType type) + int open_codec_context(int *streamIdx, AVCodecContext **decCtx, AVFormatContext *fmtCtx, + enum AVMediaType type) { int ret = 0; - int stream_index = 0; + int streamIndex = 0; AVStream *st; const AVCodec *dec = NULL; - ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); + ret = av_find_best_stream(fmtCtx, type, -1, -1, NULL, 0); if (ret < 0) { fprintf(stderr, "Could not find %s stream in input file '%s'\n", av_get_media_type_string(type), "srcfile"); return ret; } else { - stream_index = ret; - st = fmt_ctx->streams[stream_index]; + streamIndex = ret; + st = fmtCtx->streams[streamIndex]; /* find decoder for the stream */ dec = avcodec_find_decoder(st->codecpar->codec_id); @@ -82,25 +82,25 @@ extern "C" { } /* Allocate a codec context for the decoder */ - *dec_ctx = avcodec_alloc_context3(dec); - if (!*dec_ctx) { + *decCtx = avcodec_alloc_context3(dec); + if (!*decCtx) { fprintf(stderr, "Failed to allocate the %s codec context\n", av_get_media_type_string(type)); return AVERROR(ENOMEM); } /* Copy codec parameters from input stream to output codec context */ - if ((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) { + if ((ret = avcodec_parameters_to_context(*decCtx, st->codecpar)) < 0) { fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n", av_get_media_type_string(type)); return ret; } /* Init the decoders */ - if ((ret = avcodec_open2(*dec_ctx, dec, NULL)) < 0) { + if ((ret = avcodec_open2(*decCtx, dec, NULL)) < 0) { fprintf(stderr, "Failed to open %s codec\n", av_get_media_type_string(type)); return ret; } - *stream_idx = stream_index; + *streamIdx = streamIndex; } return 0; -- Gitee