Android ndk(jni) 使用 ffmpeg 问题和优化记录

发布时间 2023-05-22 10:12:35作者: 西瓜皮不甜

使用关于 av_register_all avcodec_register_all 过时问题

// 旧的代码:
av_register_all();
// 新的代码:
avformat_network_init();

// 旧的代码:
avcodec_register_all();
// 新的代码:
avformat_network_init();

avcodec_copy_context 过时

// 旧的代码:
avcodec_copy_context(dest_codec_ctx, src_codec_ctx);

// 新的代码:(dest_codec_ctx) 中使用 codecpar 字段,而不是 codec 字段。
avcodec_parameters_copy(dest_codec_ctx->codecpar, src_codec_ctx->codecpar);

在 FFmpeg 中,avformat_open_input 函数的返回值是一个表示错误码的整数。以下是一些常见的错误码及其含义:

  • 0 (AVERROR_EOF):输入流已到达末尾,没有更多的数据可读取。

  • 负数值 (AVERROR_xxx):负数的返回值表示发生了错误,错误码的具体值可以参考 FFmpeg 的错误码定义(libavutil/error.h)。

一些常见的错误码包括:

AVERROR_INVALIDDATA (-1094995529):输入数据无效。
AVERROR_NOENT (-2):指定的文件或路径不存在。
AVERROR_IO (-5):输入/输出错误,例如读取或写入文件时发生错误。
AVERROR_NOMEM (-12):内存分配失败。
AVERROR_NOFMT (-541478725):无法识别输入的文件格式。
AVERROR_STREAM_NOT_FOUND (-1381258235):未找到指定的流。
AVERROR_PROTOCOL_NOT_FOUND (-1330794744):未找到指定的协议。
AVERROR_EXIT (-1313558101):用户请求退出。

可以使用这些错误码来检查 avformat_open_input 函数的返回值,并根据需要采取适当的错误处理措施。

char errorBuffer[AV_ERROR_MAX_STRING_SIZE];
    // 获取错误描述
    if (av_strerror(res, errorBuffer, sizeof(errorBuffer)) == 0) {
        MLOG_E_("AVErrorInfo Error:res=%d, ->%s\n",res,errorBuffer);
    } else {
        MLOG_E_("AVErrorInfo Error:res=%d, %s\n",res,"Unknown error occurred.");
    }

问题

播放几分钟后卡死

//设置tcp or udp,默认一般优先tcp再尝试udp
av_dict_set(&opts, "rtsp_transport","tcp", 0); 
//设置超时
av_dict_set(&opts, "stimeout", "20000000", 0);  
//设置最大延时
av_dict_set(&opts, "max_delay", "3000", 0);  
//设置缓存大小
av_dict_set(&opts, "buffer_size", "1024 * 10", 0);  

rtsp视频流加载打开时间长(秒开)

//给定确定的解码器等信息,不调用avformat_find_stream_info()
//或者
AVFormatContext *avFormatCtx;
avFormatCtx->probesize = 500;//500,太小会影响成功率,获取不到信息会加载失败
avFormatCtx->max_analyze_duration = 3 * AV_TIME_BASE;
int res = avformat_find_stream_info(avFormatCtx,NULL);

1