📢 【三方库】ohos_ijkplayer v2.0.9 鸿蒙平台稳定性与质量提升

ohos_ijkplayer v2.0.9 已发布。本次升级聚焦该库稳定性与质量提升,修复回调引用被提前删除导致的崩溃问题,并全面加固视频录制流程的内存安全与线程生命周期管理,兼容升级,开发者无需修改现有代码即可享受本次改进。推荐所有该库用户升级至本版本。

版本概览

类型 内容
稳定性 修复回调引用可能被提前删除导致的崩溃问题 #233
质量提升 优化录屏和截图流程

稳定性提升

修复回调引用可能被提前删除导致的崩溃问题 #233

问题:在 XComponent Surface 销毁(onSurfaceDestroyedCB)时,IJKPlayerNapi::callBackRefMessage_ 通过 napi_delete_reference同步删除,而此前由 messageCallBack 通过 uv_queue_work 投递的 after_message 任务可能仍在 libuv 队列中,并持有指向同一个 callbackRefCallbackContext。当 after_message 在 ref 被删除后执行 napi_get_reference_value(context->env, context->callbackRef, &callback) 时,操作的是已释放的引用,导致崩溃。此外存在多处并发与内存隐患:CallbackContext::obj 为未初始化的裸指针且为浅拷贝(直接指向调用方缓冲区,调用方释放后即悬空);ijkPlayerNapi_ 静态 map 的读写(getInstanceonSurfaceDestroyedCB)无任何锁保护,多线程并发访问存在数据竞争。

修复ijkplayer/src/main/cpp/napi/ijkplayer_napi.cpp +146/-34、ijkplayer_napi.h +2/-0):

  • 新增静态互斥锁 IJKPlayerNapi::mapMutex_,在 getInstance、新增的 getInstanceLockedonSurfaceDestroyedCB 中以 std::lock_guard<std::mutex> 保护 ijkPlayerNapi_ 的全部查找/插入/删除,消除数据竞争。
  • messageCallBack 中对 obj 改为深拷贝(malloc + memcpy),并将 CallbackContext::obj 初始化为 nullptr,避免悬空指针;新增统一的 freeCallbackContext 辅助函数(空指针安全,先 free(obj)delete context)集中释放上下文。
  • after_message 中增加对 contextcontext->envcontext->callbackRef 的空指针校验,并检查 napi_get_reference_value 的返回值(napi_status),失败时调用 freeCallbackContext 释放并提前返回,杜绝对已删除引用的访问。
  • 新增 queueRefCleanup 机制:onSurfaceDestroyedCB 不再同步调用 napi_delete_reference,而是把 ref 删除动作以 uv_work_t 投递到 libuv 事件循环(cleanup_message_ref 回调中执行 napi_delete_reference),确保 ref 仅在 loop 线程上、待所有挂起的 after_message 执行完毕后才被删除,从根因上消除竞态。
  • onSurfaceDestroyedCB 重构为“持锁摘除、解锁后清理”:在锁内将 callBackRefMessage_/envMessage_ 取出并置空、从 map 中 erase;锁外再调用 queueRefCleanup 延迟删 ref,并 delete 实例与 ijkPlayerNapiProxy_,避免持锁销毁引发死锁与 use-after-free。

质量提升

优化录屏和截图流程

针对视频录制管线(软解 record_video_frame 与硬解 RecordMediaCodecVideoFrame 共用的帧采集/编码写入路径,截图 is_screenshot 复用同一帧管线)进行系统性加固,解决分辨率切换时录制概率崩溃(关联 issue #377,MR #231)并补齐多处空指针与内存安全缺陷。主要改动文件:ijkplayer/src/main/cpp/ijkplayer/record/ijkplayer_record.cpp(+150/-20)、ff_ffplay.c(+40/-4)、ffpipenode_ohos_mediacodec_vdec.cpp(-3)。

帧率获取安全化

  • 新增 GetSafeRecordFrameRate(FFPlayer*),在调用 av_guess_frame_rate 前对 ffp->is->icffp->is->video_st 整条指针链做空指针校验,失败时回退到基于 PTS 的 CalculateFrameRate,再回退 DEFAULT_FRAME_RATE;替换 OpenVideoVideoAudioStreamAndAvcodecOpenWriteRecordFile 中所有裸 av_q2d(av_guess_frame_rate(...)) 调用。
  • CalculateFrameRate 增加 ffp/is/video_strecordFramesQueue 的空指针保护,并校验队列有效后再读取 PTS。

录制帧队列内存修复

  • ffp_start_record 修复严重分配错误:recordFramesQueuesizeof(int) 改为 sizeof(RecordFrameData)(原写法缓冲区严重不足,存在越界风险),分配后 memset 清零并检查 malloc 返回值。
  • 启动新录制前先 pthread_join 残留录制线程并重置 srcFormat.width/height = 0;释放旧 recordFilePath 避免泄漏;pthread_create 失败时回滚 recordFilePathrecordFramesQueue 并复位录制状态。

分辨率切换尺寸错乱修复

  • 移除 record_video_frame(软解)与 RecordMediaCodecVideoFrame(硬解)中“每帧覆写 srcFormat.width/height”的逻辑——该写法在分辨率切换后会用旧尺寸误导编码器。
  • StartEncoderWrite 改用编码器实际尺寸 videoCodec->width/height(取自 recordWriteData->video_st.st->codec)作为 sws 输出尺寸,而非易失真的 srcFormat,确保分辨率切换后缩放目标正确。

帧写入健壮性

  • WriteVideoFrameData 增加帧尺寸校验(width/height > 0)、数据缓冲区校验(data0/data1/data2 非空)、目标编码帧 dstFrame 空指针校验,并检查 sws_scale 返回值,失败时打日志并返回,避免向无效内存写入。
  • record_video_frame 增加 data0/data1/data2malloc 失败检查与逐项释放。

编码器收尾与线程同步

  • 新增 FlushVideoEncoder/FlushAudioEncoder:在 ReleaseResources 中先排空编码器残留包(avcodec_encode_video2/avcodec_encode_audio2 传 NULL 帧)再 av_write_trailer,避免尾帧丢失;并增加 fmt 空指针校验。
  • ffp_stop_record 增加 pthread_join 等待录制线程结束,确保资源释放时序正确。
  • FindRecordResult 优化:先查 ijkplayerRecordResultMap,命中即返回,避免不必要的条件变量等待。

兼容性说明

  • 无 Breaking Changes,API 接口保持不变。
  • 仅内部实现优化,现有代码无需修改。
  • 从 v2.0.8 起升级至 v2.0.9 均为兼容性升级。

升级方式

  • 鸿蒙原生:oh-package.json5"@ohos/ijkplayer": "^2.0.9",执行 ohpm install

相关链接

  • 文档:https://gitcode.com/CPF-ApplicationTPC/ohos_ijkplayer/blob/master/README.md
  • CHANGELOG:https://gitcode.com/CPF-ApplicationTPC/ohos_ijkplayer/blob/master/CHANGELOG.md
  • 反馈:https://gitcode.com/CPF-ApplicationTPC/ohos_ijkplayer/issues
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐