过年最后一天了啧啧啧,今天也怕是看不完这个的。

开始吧。

/* open a given stream. Return 0 if OK */
static int stream_component_open(VideoState *is, int stream_index)

打开指定stream_index的流,并将流里的内容放到is里,就是这么回事儿吧。

开局又是先对一堆变量声明初始化之类的。

然后判断了下stream_index是否正常(在is->ic->nb_streams)之内,不正常直接return -1。

avctx = avcodec_alloc_context3(NULL);
if (!avctx)
    return AVERROR(ENOMEM);

ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
if (ret < 0)
    goto fail;
avctx->pkt_timebase = ic->streams[stream_index]->time_base;

初始化编解码器上下文AVCodecContext。先分配空间,然后根据stream的codecpar即编解码器参数,来初始化avctx的内容。然后并设置了timebase

codec = avcodec_find_decoder(avctx->codec_id);

switch(avctx->codec_type){
    case AVMEDIA_TYPE_AUDIO   : is->last_audio_stream    = stream_index; forced_codec_name =    audio_codec_name; break;
    case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = subtitle_codec_name; break;
    case AVMEDIA_TYPE_VIDEO   : is->last_video_stream    = stream_index; forced_codec_name =    video_codec_name; break;
}
if (forced_codec_name)
    codec = avcodec_find_decoder_by_name(forced_codec_name);
if (!codec) {
    if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
                                  "No codec could be found with name '%s'\n", forced_codec_name);
    else                   av_log(NULL, AV_LOG_WARNING,
                                  "No decoder could be found for codec %s\n", avcodec_get_name(avctx->codec_id));
    ret = AVERROR(EINVAL);
    goto fail;
}

avctx->codec_id = codec->id;

获取解码器的部分,并且这里还会记录一下上一个使用的流last_xxx_stream。还有会设置是否有强制使用的编解码器,应该是ffplay的选项设置的。 最后查看下是否找到。并赋上codec id。

if (stream_lowres > codec->max_lowres) {
    av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
            codec->max_lowres);
    stream_lowres = codec->max_lowres;
}
avctx->lowres = stream_lowres;

lowers,即low resolution,低分辨率。很明显是video领域的东西,所以这里直接跳过了。

if (fast)
    avctx->flags2 |= AV_CODEC_FLAG2_FAST;

这是个不符合规范的编解码加速方式,AV_CODEC_FLAG2_FAST,需要fast来启用,应该也是个ffplay option。

碎碎念,工作太难了,更没时间干别的事了。虽然ffplay debug系列的最初设想是一天一个板块,01 02 03,这种跟记日记的方式一样,但看来现在一天之内是没有时间做的了,所以一个部分的内容只能分散到一段时间内来做了,所以不是日记喽。我这么说的时候就说明今天已经要结束了。还有,我讨厌工作啧啧啧…


啊哈,时隔16日,我又回来辣。

昨天和今晚又把之前debug的部分回顾了一下,今天继续继续。


ret = filter_codec_opts(codec_opts, avctx->codec_id, ic,
                            ic->streams[stream_index], codec, &opts, NULL);
if (ret < 0)
    goto fail;

很好,第一个就没动力看了,十一点了,睡了先。

filter_codec_opts用于筛选options,符合给定codec_id的options,从codec_opts中。

if (!av_dict_get(opts, "threads", NULL, 0))
    av_dict_set(&opts, "threads", "auto", 0);
if (stream_lowres)
    av_dict_set_int(&opts, "lowres", stream_lowres, 0);

av_dict_set(&opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);

然后看得到的opts中有没有threads,没有就设为auto,还有lowres,以及设了个flags为+copy_opaque的项。

if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
    ret = create_hwaccel(&avctx->hw_device_ctx);
    if (ret < 0)
        goto fail;
}

查看是不是video流,是的话用硬件加速。

if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
    goto fail;
}
ret = check_avoptions(opts);
if (ret < 0)
    goto fail;

avcodec_open2打开编解码器,用codec接收,并用opts选项设置codec属性。

check_avoptions用来看是否还存在opts没用。

is->eof = 0;
ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;

eof设为0,当前流的discard设为default,default即丢弃无用的packet,如size为0的。

然后是一段switch处理,这里就只看audio的了。

is->audio_filter_src.freq           = avctx->sample_rate;
ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &avctx->ch_layout);
if (ret < 0)
    goto fail;
is->audio_filter_src.fmt            = avctx->sample_fmt;

这里是依次获取采样率,通道布局,样本格式。

AVFilterContext *sink;
if ((ret = configure_audio_filters(is, afilters, 0)) < 0)

configure_audio_filters很好,又是个大的。