ffmpeg4.2.2打开输入文件/网络流是怎么获取流信息的

文章没啥干货,就只是自己一个疑问的记录。

在工作中解决一个bug,继而引发关于流信息是怎么获取的,是在avformat_open_input()函数中已经获取了?还是要去avformat_find_stream_info()函数中获取?

先看nb_streams值是在哪变化的,看变量声明得知是avformat_new_stream()中修改的

/**
     * Number of elements in AVFormatContext.streams.
     *
     * Set by avformat_new_stream(), must not be modified by any other code.
     * 由avformat_new_stream()设置,不能被任何其他代码修改。  
     */

再寻找哪些函数调用了avformat_new_stream(),找到avformat_open_input()中的一行调用s->iformat->read_header(s),查看函数声明

/**
* Read the format header and initialize the AVFormatContext
* structure. Return 0 if OK. 'avformat_new_stream' should be
* called to create new streams.
*/
读取格式头文件并初始化AVFormatContext结构。如果OK则返回0。调用“avformat_new_stream”来创建新的流。  

根据这位老哥的文章:avformat_find_stream_info() 函数源码解析

老哥原话:

   //接下来就需要从网络/文件中读取 packet,这个函数里面做的事情很多,拿 flv 来举例子,执行完 read_frame_internal() 函数,正常情况下,音视频对应的 AVStream 结构体会被创建,并且 ic->nb_streams,也就是流的个数也会是正常的值,比如如果包含音频和视频,nb_streams 的值会是 2。

跟踪源码:

avformat_find_stream_info() ->  read_frame_internal()  -> ff_read_packet() -> flv_read_packet()

拿flv举例,在flv_read_packet()中(文件是flvdec.c)

    if (i == s->nb_streams) {
        static const enum AVMediaType stream_types[] = {AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_SUBTITLE, AVMEDIA_TYPE_DATA};
        st = create_stream(s, stream_types[stream_type]);
        if (!st)
            return AVERROR(ENOMEM);
    }

static AVStream *create_stream(AVFormatContext *s, int codec_type)
{
    FLVContext *flv   = s->priv_data;
    AVStream *st = avformat_new_stream(s, NULL);
    if (!st)
        return NULL;
    st->codecpar->codec_type = codec_type;
    if (s->nb_streams>=3 ||(   s->nb_streams=

我看源码里,aac,avi是read_head发现的流信息,flv是read_packet发现的流信息,rtsp也是read_head时

        /* NOTE: A new stream can be added there if no header in file
         * (AVFMTCTX_NOHEADER). */
        ret = read_frame_internal(ic, &pkt1);

在ffmpeg源码中有这么一段注释,可是flv不是有格式头吗?不太懂。。。

====================================================================

avformat_find_stream_info 是 FFmpeg 用于获取媒体文件音视频信息的函数,它的原型如下: ``` int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); ``` 其,ic 是一个 AVFormatContext 结构体指针,表示要进行音视频信息获取的媒体文件的格式上下文;options 是一个 AVDictionary 结构体指针,表示附加的选项参数,可选。 avformat_find_stream_info 函数的作用是获取媒体文件音视频信息,并将信息存储在 AVFormatContext 结构体。在调用此函数之后,可以通过遍历 AVFormatContext 结构体的 streams 数组来获取每个音视频详细信息,包括编解码器参数、的类型(音频或视频)、的时长、帧率等。 使用 avformat_find_stream_info 函数时,需要先调用 avformat_open_input 函数打开要读取的媒体文件,并使用 avformat_alloc_context 函数创建一个 AVFormatContext 结构体。然后,可以使用 avformat_find_stream_info 函数获取音视频信息。函数返回值表示是否获取成功,如果返回值小于 0,表示获取失败,可以通过 av_strerror 函数将错误码转换为错误信息进行查看。 下面是一个示例代码,演示了如何使用 avformat_find_stream_info 函数获取音视频信息: ```c AVFormatContext *fmt_ctx = NULL; int ret = avformat_open_input(&fmt_ctx, "test.mp4", NULL, NULL); if (ret < 0) { // 打开媒体文件失败 return; } ret = avformat_find_stream_info(fmt_ctx, NULL); if (ret < 0) { // 获取音视频信息失败 avformat_close_input(&fmt_ctx); return; } // 遍历音视频信息 for (int i = 0; i < fmt_ctx->nb_streams; i++) { AVCodecParameters *codecpar = fmt_ctx->streams[i]->codecpar; if (codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { // 音频信息 printf("Audio Stream: sample_rate=%d, channels=%d\n", codecpar->sample_rate, codecpar->channels); } else if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { // 视频信息 printf("Video Stream: width=%d, height=%d, fps=%f\n", codecpar->width, codecpar->height, av_q2d(fmt_ctx->streams[i]->avg_frame_rate)); } } avformat_close_input(&fmt_ctx); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值