ffmpeg笔记

ffmpeg demuxer的调用方法

View Code
调用者可以指定文件读取protocol,通过s->pb来指定
调用者也可以指定文件解析器demuxer,通过s->iformat来指定
//参数ps包含一切媒体相关的上下文结构,有它就有了一切,本函数如果打开媒体成功, 
//会返回一个AVFormatContext的实例. 
//参数filename是媒体文件名或URL. 
//参数fmt是要打开的媒体格式的操作结构,因为是读,所以是inputFormat.此处可以 
//传入一个调用者定义的inputFormat,对应命令行中的 -f xxx段,如果指定了它, 
//在打开文件中就不会探测文件的实际格式了,以它为准了. 
//参数options是对某种格式的一些操作,是为了在命令行中可以对不同的格式传入 
//特殊的操作参数而建的, 为了了解流程,完全可以无视它. 
int avformat_open_input(AVFormatContext **ps, 
        const char *filename, 
        AVInputFormat *fmt, 
        AVDictionary **options)   

ffmpeg及时退出方法

View Code
if (ff_check_interrupt(&ic->interrupt_callback)){
            ret= AVERROR_EXIT;
            av_log(ic, AV_LOG_DEBUG, "interrupted\n");
            break;
        }

计算PTS流程

View Code
在文件头中读取和设置时间戳信息:
     读取scale和rate生成时间基
ast->scale = get_le32(pb);   
ast->rate = get_le32(pb);
av_set_pts_info(st, 64, ast->scale, ast->rate);
 先在TAG “strh”中读取nb_frames,
st->nb_frames = get_le32(pb);
之后将duration设置为视频流的帧数:           
if(ast->sample_size == 0){
                st->duration = st->nb_frames;
            }
最后在函数av_estimate_timings_from_pts生成时长信息
 每次读帧的时候来计算时间戳
Pts默认的初始化在函数av_get_packet(pb, pkt, size)中实现,最终通过调用
av_new_packet(pkt, size)------> av_init_packet(pkt)----> pkt->pts   = AV_NOPTS_VALUE; pkt->dts   = AV_NOPTS_VALUE;

读到帧时,音视频都通过compute_pkt_fields(s, st, st->parser, pkt);函数来计算。其中frame_offset作为后面的dts,而dts进一步作为pts,在AVI文件中pts等于dts

计算duration流程

View Code
av_find_stream_info->获取流信息
     +av_estimate_timings->计算时间
         + av_estimate_timings_from_pts
          +av_estimate_timings_from_bit_rate
fill_all_stream_timings

    计算bitrate流程
    Seek的流程
    读包的流程
    查找codec信息的流程
    主要数据结构的使用,以及其作用

解析头后,保存文件的偏移

View Code
在avformat_open_input中解析id3v2,并保存文件偏移:
        //保存数据区开始的位置 
    if (!(s->flags & AVFMT_FLAG_PRIV_OPT) && s->pb && !s->data_offset) 
        s->data_offset = avio_tell(s->pb);  

Seek的流程

View Code
Seek的策略:
1. 如果文件有索引,而且索引是准确的,则直接跟据文件的索引seek到相应位置。
     av_seek_frame-->iformat->read_seek
2. 如果没找到索引,但可以通过位置取到时间戳,则通过二分查找法能找到相应位置。
     av_seek_frame-->av_seek_frame_binary-->av_gen_search
3. 如果前两种情况都不可行,那只能逐个读包,直到读到期望的时间戳才停止。
     av_seek_frame-->av_seek_frame_generic-->av_read_frame
注意会使用二分法查找,所以索引表中会有最后一个index

    .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH,这个选项会禁止在框架层上做Bin seek,或gen seek,而直接在demuxer里完成精确的seek操作。

二分查找seek

View Code
二分查找函数ff_seek_frame_binary的流程:
1. 在当前索引中找出pos_min和pos_max
2. 调用ff_gen_search
后续再补充详细流程...
posted @ 2012-07-17 00:23  yeeman  阅读(850)  评论(0编辑  收藏  举报