解决安卓调用ffmpeg函数avformat_open_input进行转码出现打不开文件

本文介绍在Android环境下使用JNI调用FFmpeg解码视频文件时遇到的问题及解决办法。当尝试打开视频文件时出现-13错误,提示为权限被拒绝。最终通过在Android清单文件中添加外部存储读取权限解决了此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

安卓下通过jni调用ffmpeg解码视频文件,结果在c文件中调用avformat_open_input函数打开视频文件时报错

  • 论坛有说是因为ffmpeg版本问题的,但是我3.x.x和2.的都试过一样的打开失败。返回的结果码是-13,但是看源码也没找到-13代表什么。
  • 还好找到如下方法将错误信息打印了出来:
    int err_code;
    char buf[1024];
    if ((err_code = avformat_open_input(&pFormatCtx, input_str, NULL, NULL)) != 0) {
    av_strerror(err_code, buf, 1024);
    LOGE(“Couldn’t open file %s: %d(%s)”, input_str, err_code, buf);
    return -1;
    }
    控制台打印如下:
    这里写图片描述
    Couldn’t open file /storage/emulated/legacy/joy/cuc_ieschool.flv: -13(Permission denied)
  • 原来是因为Permission denied。之前也想过会不会是文件访问权限问题,后来觉得读文件应该不需要吧,而且觉得用c打开文件应该不需要声明权限吧?还是太naive了。
  • 在安卓清单文件加上权限:
    uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE”问题果然随风而去。
FFmpeg是一个强大的跨平台多媒体处理框架,可以用于音频、视频的各种转换操作。在C++中,你可以通过FFmpeg提供的API来编码或解码视频文件,包括将其他格式的音视频转换成MP4。 为了调用FFmpeg API进行转码,你需要包含必要的头文件,并初始化库,然后创建一个`AVFormatContext`结构体来描述输入和输出格式。以下是一个基本的示例,展示了如何将一个视频流转换为MP4: ```cpp #include <ffmpeg/avformat.h> #include <ffmpeg/avcodec.h> // 初始化FFmpeg库 av_register_all(); avcodec_register_all(); int main() { // 创建输入上下文 AVFormatContext* inputCtx = nullptr; if (avformat_open_input(&inputCtx, "input_file.ext", nullptr, nullptr) != 0) { // 处理错误 return -1; } // 检查并打开第一个视频流 int videoStreamIndex = -1; for (int i = 0; i < inputCtx->nb_streams; ++i) { if (inputCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStreamIndex = i; break; } } if (videoStreamIndex == -1) { avformat_close_input(&inputCtx); return -1; } // 创建输出上下文 AVFormatContext* outputCtx = avformat_alloc_context(); outputCtx->oformat = av_guess_format("mp4", nullptr, nullptr); // 添加输出流 AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264); // 假设你要编码为H.264 AVStream* outStream = avformat_new_stream(outputCtx, codec); if (!outStream) { // 处理错误 return -1; } outStream->time_base = inputCtx->streams[videoStreamIndex]->time_base; // 编码设置 AVCodecParameters* params = &codec->default_params; params->width = ...; // 输入视频宽度 params->height = ...; // 输入视频高度 // 更多设置... // 开启编码 if (avcodec_open2(outStream->codec, codec, params) != 0) { // 处理错误 return -1; } // 执行实际的编码 // 这里省略了具体的编码循环和写入MP4数据的部分,通常会用到如libavcodec的AVPacket和AVStreamWrite等函数 // 关闭上下文并保存输出 av_write_frame(outputCtx, nullptr); // 写入一帧完成一个编码包 avio_close(outputCtx->pb); // 关闭输出流 avformat_write_header(outputCtx, nullptr); av_interleaved_write_frame(outputCtx, nullptr); // 将编码后的数据写入文件 avformat_close_input(&inputCtx); avformat_free_context(outputCtx); return 0; } ``` 这只是一个基本的示例,实际使用时需要处理更多的细节,比如错误检查、进度反馈、多线程编码以及文件I/O等。同时,记得安装FFmpeg库,并根据需要调整编码参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值