您的位置:首页 > 其它

ffmpeg分析系列之七(打开输入的流)

2011-07-19 10:53 337 查看
err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);
int av_open_input_stream(
AVFormatContext **ic_ptr, // 输出参数: 格式上下文
ByteIOContext *pb,
// 字节IO上下文
const char *filename, // 文件名
AVInputFormat *fmt,
// 输入的格式
AVFormatParameters *ap) // 格式参数, 调用时为NULL
{
int err;
AVFormatContext *ic;
AVFormatParameters default_ap;
// 使用缺省的格式参数
if(!ap){
ap=&default_ap;
memset(ap, 0, sizeof(default_ap));
}

if(!ap->prealloced_context)
ic = avformat_alloc_context(); // 分配格式上下文
else
ic = *ic_ptr;
if (!ic) {
err = AVERROR(ENOMEM);
goto fail;
}
// 初始化格式上下文
ic->iformat = fmt; // 格式
ic->pb = pb; // 字节IO上下文
ic->duration = AV_NOPTS_VALUE;
ic->start_time = AV_NOPTS_VALUE;
av_strlcpy(ic->filename, filename, sizeof(ic->filename)); // 文件名

/* 分配私有数据 */
if (fmt->priv_data_size > 0) {
ic->priv_data = av_mallocz(fmt->priv_data_size);
if (!ic->priv_data) {
err = AVERROR(ENOMEM);
goto fail;
}
} else {
ic->priv_data = NULL;
}
// 读首部
if (ic->iformat->read_header) {
err = ic->iformat->read_header(ic, ap);
if (err < 0)
goto fail;
}
// 获得数据偏移
if (pb && !ic->data_offset)
ic->data_offset = url_ftell(ic->pb);

#if LIBAVFORMAT_VERSION_MAJOR < 53
ff_metadata_demux_compat(ic);
#endif
// 原始的包缓冲剩余的大小
ic->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
// 输出参数: 格式上下文
*ic_ptr = ic;return 0;
}
具体请参看
ffmpeg分析系列之三(输入输出格式)
格式上下文结构:
typedef struct AVFormatContext {
const AVClass *av_class; /**< Set by avformat_alloc_context. */
// 省略部分内容}
AV类结构:
typedef struct {
/**
* The name of the class; usually it is the same name as the
* context structure type to which the AVClass is associated.
*/
const char* class_name;

/**
* A pointer to a function which returns the name of a context
* instance ctx associated with the class.
*/
const char* (*item_name)(void* ctx);

/**
* a pointer to the first option specified in the class if any or NULL
*
* @see av_set_default_options()
*/
const struct AVOption *option;

/**
* LIBAVUTIL_VERSION with which this structure was created.
* This is used to allow fields to be added without requiring major
* version bumps everywhere.
*/

int version;
} AVClass;
进入avformat_alloc_context函数, 分配格式上下文:
AVFormatContext *avformat_alloc_context(void){AVFormatContext *ic;ic = av_malloc(sizeof(AVFormatContext));if (!ic) return ic;avformat_get_context_defaults(ic);ic->av_class = &av_format_context_class;return ic;}
static const AVClass av_format_context_class = { "AVFormatContext", format_to_name, options, LIBAVUTIL_VERSION_INT };
进入avformat_get_context_defaults函数, 格式获得缺省上下文:
static void avformat_get_context_defaults(AVFormatContext *s){memset(s, 0, sizeof(AVFormatContext));s->av_class = &av_format_context_class;av_opt_set_defaults(s);}
av_opt_set_defaults函数就不分析了.下面继续分析:
err = ic->iformat->read_header(ic, ap)
以输入格式为libavformat/raw.c下的h264_demuxer为例:
AVInputFormat h264_demuxer = {"h264",NULL_IF_CONFIG_SMALL("raw H.264 video format"),0,h264_probe,video_read_header,ff_raw_read_partial_packet,.flags= AVFMT_GENERIC_INDEX,.extensions = "h26l,h264,264", //FIXME remove after writing mpeg4_probe.value = CODEC_ID_H264,};
会调用video_read_header函数:
static int video_read_header(AVFormatContext *s,AVFormatParameters *ap){AVStream *st;st = av_new_stream(s, 0); // 格式上下文增加一个流if (!st)return AVERROR(ENOMEM);
// 初始化流st->codec->codec_type = AVMEDIA_TYPE_VIDEO; // 编码编码器类型st->codec->codec_id = s->iformat->value; // 为 CODEC_ID_H264st->need_parsing = AVSTREAM_PARSE_FULL; // 需要全分析/* for MJPEG, specify frame rate *//* for MPEG-4 specify it, too (most MPEG-4 streams do not have the fixed_vop_rate set ...)*/if (ap->time_base.num) {
st->codec->time_base= ap->time_base;} else if ( st->codec->codec_id == CODEC_ID_MJPEG ||st->codec->codec_id == CODEC_ID_MPEG4 ||st->codec->codec_id == CODEC_ID_DIRAC ||st->codec->codec_id == CODEC_ID_DNXHD ||st->codec->codec_id == CODEC_ID_H264) {st->codec->time_base= (AVRational){1,25}; // 设置时基}av_set_pts_info(st, 64, 1, 1200000); // 设置PTS(显示时间截)信息return 0;}
进入av_new_stream函数:
AVStream *av_new_stream(AVFormatContext *s, int id){AVStream *st;int i;
// 格式上下文不能太多流if (s->nb_streams >= MAX_STREAMS)return NULL;
// 分配一个流st = av_mallocz(sizeof(AVStream));if (!st)return NULL;
// 分配解码器上下文st->codec= avcodec_alloc_context();if (s->iformat) {/* no default bitrate if decoding */st->codec->bit_rate = 0;}st->index = s->nb_streams; // 流索引st->id = id; // ID, 为0st->start_time = AV_NOPTS_VALUE; // 开始时间st->duration = AV_NOPTS_VALUE;/* we set the current DTS to 0 so that formats without any timestampsbut durations get some timestamps, formats with some unknowntimestamps have their first few packets buffered and thetimestamps corrected before they are returned to the user */st->cur_dts = 0; // 当前的解码时间截st->first_dts = AV_NOPTS_VALUE; // 起始的解码时间截st->probe_packets = MAX_PROBE_PACKETS; // 探测的最大包数/* default pts setting is MPEG-like */
av_set_pts_info(st, 33, 1, 90000); // 设置PTS显示时间截信息st->last_IP_pts = AV_NOPTS_VALUE;for(i=0; i<MAX_REORDER_DELAY+1; i++)st->pts_buffer[i]= AV_NOPTS_VALUE;st->reference_dts = AV_NOPTS_VALUE;st->sample_aspect_ratio = (AVRational){0,1};s->streams[s->nb_streams++] = st; // 记录流, 同时流数加一return st;}
分配编码解码器上下文:
static const AVClass av_codec_context_class = { "AVCodecContext", context_to_name, options, LIBAVUTIL_VERSION_INT };
void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){int flags=0;memset(s, 0, sizeof(AVCodecContext));s->av_class= &av_codec_context_class;s->codec_type = codec_type;if(codec_type == AVMEDIA_TYPE_AUDIO)flags= AV_OPT_FLAG_AUDIO_PARAM;else if(codec_type == AVMEDIA_TYPE_VIDEO)flags= AV_OPT_FLAG_VIDEO_PARAM;else if(codec_type == AVMEDIA_TYPE_SUBTITLE)flags= AV_OPT_FLAG_SUBTITLE_PARAM;av_opt_set_defaults2(s, flags, flags);s->time_base= (AVRational){0,1};s->get_buffer= avcodec_default_get_buffer;s->release_buffer= avcodec_default_release_buffer;s->get_format= avcodec_default_get_format;s->execute= avcodec_default_execute;s->execute2= avcodec_default_execute2;s->sample_aspect_ratio= (AVRational){0,1};s->pix_fmt= PIX_FMT_NONE;s->sample_fmt= SAMPLE_FMT_NONE;s->palctrl = NULL;s->reget_buffer= avcodec_default_reget_buffer;s->reordered_opaque= AV_NOPTS_VALUE;}AVCodecContext *avcodec_alloc_context2(enum AVMediaType codec_type){AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));if(avctx==NULL) return NULL;avcodec_get_context_defaults2(avctx, codec_type);return avctx;}void avcodec_get_context_defaults(AVCodecContext *s){avcodec_get_context_defaults2(s, AVMEDIA_TYPE_UNKNOWN);}AVCodecContext *avcodec_alloc_context(void){return avcodec_alloc_context2(AVMEDIA_TYPE_UNKNOWN);}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: