av_find_stream_info()中是要不斷的讀取數據包,解碼獲得相應的信息
其中:
st->codec->codec_type:0:視頻,1:音頻,2:數據
st->codec->codec_id: 音視頻編解碼類型對應的值
ic->nb_streams: 表示包里面包含的流的總數
pkt->stream_index: 表示每個流的索引號,例如音頻的為0,視頻的為2
pkt->size: 表示每個包的大小
read_size: 表示pkt->size的累計和
pkt->duration: 相鄰兩個包的時間差,例如對於mp3,44100采樣率,1152點/幀,duration =26; 視頻幀率為25,duration = 40
st->info->codec_info_duration : 每個流從開始到解析到當前幀的時間和
probesize = ic->probesize2: 解析緩沖區的大小
max_analyze_duration: 解析的時間范圍
avformat_find_stream_info() ->
read_frame_internal() ->
ff_read_packet() -> //讀取packet里面的數據
parse_packet()-> //解析packet包里面的數據
ff_read_packet():
對於flv封裝格式,對應函數flv_read_packet功能:
讀取flv tag header,可以得到tag屬於音頻,視頻或者metadata。
如果屬於metadata tag,則解析meta data數據;
如果屬於audio tag,則不僅需要解析11 字節的tag header,另外需要解析緊跟着tag header的一個字節的數據,可以得到編碼格式(SoundFormat),采樣率(SoundRate),采樣點大小(SoundSize),聲音類型(SoundType)。
如果屬於video tag,同樣不僅需要解析11 字節的tag header,另外需要解析緊跟着tag header的一個字節的數據,得到編碼格式(frame type),幀類型(CodeID);如果對於AVC編碼,還需要解析一個字節的數據,即得到包類型(AVCPacketType)的值。
對於第一次解析到的AVC視頻流,需要調用create_stream(),使ic->nb_streams值加1,接着執行flv_set_video_codec(),如果AVCPacketType()是SPS包,則從flv_read_packet()返回,並且返回值為-11. 因此會執行
if (ret == AVERROR(EAGAIN))
continue;
緊接着執行第二次調用read_frame_internal(),ff_read_packet(),此時解析到的是video tag,然后調用av_get_packet(),將讀到的這兩個packet的數據保存到AVPacket指針變量里面,最后read_frame_internal()調用parse_packet()。
parse_packet():
執行av_parser_parse2()解析packet包里面的數據,通過調用s->parser->parser_parse()實際對數據進行解析。對於h264,實際調用h264_parse()這個函數進行真正的解析操作,即通過調用parse_nal_units()解析得到NAL的值,以及SPS的信息。 在SPS中,可以解析到profile, level,width,height,SAR,frame rate(timing info)。
fps_analyze_framecount = 20;
if (av_q2d(st->time_base) > 0.0005)
fps_analyze_framecount *= 2;
/* variable fps and no guess at the real fps */
if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&
st->info->duration_count < fps_analyze_framecount &&
st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
break;
所以需要檢測40 幀視頻圖像。