FFmpeg(2)-avformat_open_input()函数详解并示例打开mp4文件

一. 解封装

pts 是显示的时间 dts是解码的时间, 这个时间是用来做同步。

  1. av_register_all(), 注册所有的格式。包括解封装格式和加封装格式。
  2. avformat_network_init(), 用于初始化网络。FFmpeg本身也支持解封装RTSP的数据,如果要解封装网络数据格式,则可调用该函数。
  3. avformat_open_input()。打开一个文件并解析。可解析的内容包括:视频流、音频流、视频流参数、音频流参数、视频帧索引。
  4. avformat_find_stream_info(),查找格式和索引。有些早期格式它的索引并没有放到头当中,需要你到后面探测,就会用到此函数。
  5. av_find_best_stream(), 当视频被解封装出来后,需要分开处理音频和视频,需要找到对应的音频流和视频流
  6. 解封装后涉及到的结构体:

AVFormatContext: 封装的上下文

AVStream : 存放的是音频流或视频流的参数信息

AVPacket: 针对于具体的解封装完后的一个一个的数据包。

av_read_frame() 用于读取一个AVPacket,AVPacket里面包含了这个包的pts,dts,还有这个包的stream index(它是音频还是视频),是否是关键帧,AVPacket把h264数据的间隔符去掉了。

二.avformat_open_input()函数详解及mp4文件打开示例

2.1 avformat_open_input函数详解

该函数用于打开一个输入的封装器。在调用该函数之前,须确保av_register_all()和avformat_network_init()已调用。

参数说明:

AVFormatContext **ps, 格式化的上下文。要注意,如果传入的是一个AVFormatContext*的指针,则该空间须自己手动清理,若传入的指针为空,则FFmpeg会内部自己创建。

const char *url, 传入的地址。支持http,RTSP,以及普通的本地文件。地址最终会存入到AVFormatContext结构体当中。

AVInputFormat *fmt, 指定输入的封装格式。一般传NULL,由FFmpeg自行探测。

AVDictionary **options, 其它参数设置。它是一个字典,用于参数传递,不传则写NULL。参见:libavformat/options_table.h,其中包含了它支持的参数设置。

2.2 mp4文件打开示例

复制代码

extern "C" JNIEXPORT jstring
JNICALL
Java_com_yuneec_yongdaimi_ff_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    hello += avcodec_configuration();

    // 初始化解封装
    av_register_all();
    // 初始化网络
    avformat_network_init();
    // 打开文件
    AVFormatContext *ic = NULL;
    char path[] = "sdcard/1080.mp4";
    int ret = avformat_open_input(&ic, path, 0, 0);
    if (ret == 0) {
        LOGI("avformat_open_input() called success.");
    } else {
        LOGE("avformat_open_input() called failed: %s", av_err2str(ret));
    }
    return env->NewStringUTF(hello.c_str());
}

复制代码

PS:

1.这里用到了avformat_open_input()函数,需要包含其对应的头文件: #include <libavformat/avformat.h> ;

2.代码中还用到了 av_err2str() 这个函数,因此CMakeLists.txt中还需要包含它所对应的 libavutil.so 库,相关的CMakeLists.txt如下:

复制代码

# avcodec
add_library(avcodec SHARED IMPORTED)
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FF}/libavcodec.so)

# avformat
add_library(avformat SHARED IMPORTED)
set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${FF}/libavformat.so)

# avutil
add_library(avutil SHARED IMPORTED)
set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${FF}/libavutil.so)

复制代码

另外,不要忘记添加链接:

复制代码

target_link_libraries( # Specifies the target library.
                       native-lib
                       avcodec
                       avformat
                       avutil

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

复制代码

« 上一篇:FFmpeg(1)-创建支持FFmpeg的AS项目
» 下一篇:FFmpeg(3)-AVFormatContext 结构体内容分析

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
avformat_open_input 函数FFmpeg 中的一个重要函数,用于打开输入媒体文件,创建一个 AVFormatContext 结构体,并且为每个流分配一个 AVStream 结构体。该函数的使用方法如下: 1. 初始化 AVFormatContext 结构体 首先需要初始化一个 AVFormatContext 结构体,可以使用 avformat_alloc_context 函数来分配内存空间。 2. 打开输入文件 调用 avformat_open_input 函数打开输入媒体文件,并将文件的信息存储在 AVFormatContext 结构体中。该函数的原型如下: ```c int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options); ``` 其中,参数 ps 是一个指向 AVFormatContext 指针的指针,url 是输入媒体文件的路径,fmt 是一个 AVInputFormat 结构体指针,用于指定输入媒体文件的格式,如果设置为 NULL,则会自动检测输入文件的格式。options 是一个 AVDictionary 结构体指针,用于设置一些额外的选项,例如设置输入缓冲区大小等。 3. 检查 AVFormatContext 结构体 调用 avformat_find_stream_info 函数来检查 AVFormatContext 结构体,并获取媒体文件的一些基本信息,例如流的数量、每个流的编码格式等等。该函数的原型如下: ```c int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); ``` 其中,参数 ic 是一个指向 AVFormatContext 结构体的指针,options 是一个 AVDictionary 结构体指针,用于设置一些额外的选项。 4. 获取流的信息 遍历 AVFormatContext 结构体中的每个 AVStream 结构体,获取每个流的详细信息,例如编码格式、码率、时长等等。 下面是一个简单的示例代码,演示了如何使用 avformat_open_input 函数打开一个媒体文件,并获取每个流的信息: ```c #include <libavformat/avformat.h> int main(int argc, char* argv[]) { AVFormatContext* formatContext = NULL; int ret = avformat_open_input(&formatContext, "input.mp4", NULL, NULL); if (ret < 0) { printf("Failed to open input file!\n"); return -1; } ret = avformat_find_stream_info(formatContext, NULL); if (ret < 0) { printf("Failed to find stream info!\n"); return -1; } for (int i = 0; i < formatContext->nb_streams; i++) { AVCodecParameters* codecParam = formatContext->streams[i]->codecpar; printf("stream %d: codec_id=%d, codec_name=%s, bitrate=%lld, duration=%lld\n", i, codecParam->codec_id, avcodec_get_name(codecParam->codec_id), formatContext->bit_rate, formatContext->duration); } avformat_close_input(&formatContext); return 0; } ``` 在这个示例代码中,我们使用 avformat_open_input 函数打开了一个名为 input.mp4 的媒体文件,然后遍历了 AVFormatContext 结构体中的每个流,并打印出每个流的编码格式、码率和时长等信息。 需要注意的是,avformat_open_input 函数只是打开了输入媒体文件,并创建了一个 AVFormatContext 结构体,但并没有开始解码媒体文件。要想解码媒体文件,需要使用其他的函数,例如 av_read_frame 函数来读取媒体文件的每一帧数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值