?FFMPEG函數(shù)分析av_read_frame()
點(diǎn)擊關(guān)注,與你共同成長!

FFMPEG函數(shù)分析av_read_frame()
簡介
對于視頻的編解碼來說,要對數(shù)據(jù)進(jìn)行解碼,那么首先要獲取視頻幀的壓縮數(shù)據(jù)。
av_read_frame()的作用就是獲取視頻的數(shù)據(jù)。
注:av_read_frame()獲取視頻的一幀,不存在半幀說法。但可以獲取音頻的若干幀。
說明①:av_read_frame()函數(shù)是ffmpeg新型的用法,就用法之所以被拋棄,就是因?yàn)橐郧矮@取的數(shù)據(jù)可能不是完整的,而av_read_frame()保證了視頻數(shù)據(jù)一幀的完整性。
說明②:查看API的改變可以看到,從2012-03-20開始,Deprecate av_read_packet(), use av_read_frame()
返回流的下一幀。
*此函數(shù)返回存儲在文件中的內(nèi)容,但不驗(yàn)證解碼器是否有有效幀。
它將把文件中存儲的內(nèi)容拆分為幀,并為每個調(diào)用返回一個幀。
它不會省略有效幀之間的無效數(shù)據(jù),以便給解碼器最大可能的解碼信息。
如果pkt->buf為NULL,那么直到下一個av_read_frame()或直到avformat_close_input(),包都是有效的。
否則數(shù)據(jù)包將無限期有效。在這兩種情況下,當(dāng)不再需要包時(shí),必須使用av_free_packet釋放包。
對于視頻,數(shù)據(jù)包只包含一幀。
對于音頻,如果每個幀具有已知的固定大小(例如PCM或ADPCM數(shù)據(jù)),則它包含整數(shù)幀數(shù)。
如果音頻幀有一個可變的大小(例如MPEG音頻),那么它包含一幀。
在AVStream中,pkt->pts、pkt->dts和pkt->持續(xù)時(shí)間總是被設(shè)置為恰當(dāng)?shù)闹怠?br>time_base單元(猜測格式是否不能提供它們)。
如果視頻格式為B-frames,pkt->pts可以是AV_NOPTS_VALUE,所以如果不解壓縮有效負(fù)載,最好依賴pkt->dts。
int?av_read_frame(AVFormatContext?*s,?AVPacket?*pkt);
參數(shù)說明
*AVFormatContext s :文件格式上下文,輸入的AVFormatContext
*AVPacket pkt:這個值不能傳NULL,必須是一個空間,輸出的AVPacket
返回值:return 0 is OK, <0 on error or end of file
av_read_frame()函數(shù)源碼位于 lib/avformat/utils.c
int?av_read_frame(AVFormatContext?*s,?AVPacket?*pkt)
{
????const?int?genpts?=?s->flags?&?AVFMT_FLAG_GENPTS;
????int?eof?=?0;
????int?ret;
????AVStream?*st;
????if?(!genpts)?{
????????ret?=?s->internal->packet_buffer
????????????????ff_packet_list_get(&s->internal->packet_buffer,
????????????????????????????????????????&s->internal->packet_buffer_end,?pkt)
??????????????:?read_frame_internal(s,?pkt);
????????if?(ret?0)
????????????return?ret;
????????goto?return_packet;
????}
????for?(;;)?{
????????AVPacketList?*pktl?=?s->internal->packet_buffer;
????????if?(pktl)?{
????????????AVPacket?*next_pkt?=?&pktl->pkt;
????????????if?(next_pkt->dts?!=?AV_NOPTS_VALUE)?{
????????????????int?wrap_bits?=?s->streams[next_pkt->stream_index]->pts_wrap_bits;
????????????????//?last?dts?seen?for?this?stream.?if?any?of?packets?following
????????????????//?current?one?had?no?dts,?we?will?set?this?to?AV_NOPTS_VALUE.
????????????????int64_t?last_dts?=?next_pkt->dts;
????????????????av_assert2(wrap_bits?<=?64);
????????????????while?(pktl?&&?next_pkt->pts?==?AV_NOPTS_VALUE)?{
????????????????????if?(pktl->pkt.stream_index?==?next_pkt->stream_index?&&
????????????????????????av_compare_mod(next_pkt->dts,?pktl->pkt.dts,?2ULL?<(wrap_bits?-?1))?0)?{
????????????????????????if?(av_compare_mod(pktl->pkt.pts,?pktl->pkt.dts,?2ULL?<(wrap_bits?-?1)))?{
????????????????????????????//?not?B-frame
????????????????????????????next_pkt->pts?=?pktl->pkt.dts;
????????????????????????}
????????????????????????if?(last_dts?!=?AV_NOPTS_VALUE)?{
????????????????????????????//?Once?last?dts?was?set?to?AV_NOPTS_VALUE,?we?don't?change?it.
????????????????????????????last_dts?=?pktl->pkt.dts;
????????????????????????}
????????????????????}
????????????????????pktl?=?pktl->next;
????????????????}
????????????????if?(eof?&&?next_pkt->pts?==?AV_NOPTS_VALUE?&&?last_dts?!=?AV_NOPTS_VALUE)?{
????????????????????//?Fixing?the?last?reference?frame?had?none?pts?issue?(For?MXF?etc).
????????????????????//?We?only?do?this?when
????????????????????//?1.?eof.
????????????????????//?2.?we?are?not?able?to?resolve?a?pts?value?for?current?packet.
????????????????????//?3.?the?packets?for?this?stream?at?the?end?of?the?files?had?valid?dts.
????????????????????next_pkt->pts?=?last_dts?+?next_pkt->duration;
????????????????}
????????????????pktl?=?s->internal->packet_buffer;
????????????}
????????????/*?read?packet?from?packet?buffer,?if?there?is?data?*/
????????????st?=?s->streams[next_pkt->stream_index];
????????????if?(!(next_pkt->pts?==?AV_NOPTS_VALUE?&&?st->discard???????????????????next_pkt->dts?!=?AV_NOPTS_VALUE?&&?!eof))?{
????????????????ret?=?ff_packet_list_get(&s->internal->packet_buffer,
???????????????????????????????????????????????&s->internal->packet_buffer_end,?pkt);
????????????????goto?return_packet;
????????????}
????????}
????????ret?=?read_frame_internal(s,?pkt);
????????if?(ret?0)?{
????????????if?(pktl?&&?ret?!=?AVERROR(EAGAIN))?{
????????????????eof?=?1;
????????????????continue;
????????????}?else
????????????????return?ret;
????????}
????????ret?=?ff_packet_list_put(&s->internal->packet_buffer,
?????????????????????????????????&s->internal->packet_buffer_end,
?????????????????????????????????pkt,?FF_PACKETLIST_FLAG_REF_PACKET);
????????av_packet_unref(pkt);
????????if?(ret?0)
????????????return?ret;
????}
return_packet:
????st?=?s->streams[pkt->stream_index];
????if?((s->iformat->flags?&?AVFMT_GENERIC_INDEX)?&&?pkt->flags?&?AV_PKT_FLAG_KEY)?{
????????ff_reduce_index(s,?st->index);
????????av_add_index_entry(st,?pkt->pos,?pkt->dts,?0,?0,?AVINDEX_KEYFRAME);
????}
????if?(is_relative(pkt->dts))
????????pkt->dts?-=?RELATIVE_TS_BASE;
????if?(is_relative(pkt->pts))
????????pkt->pts?-=?RELATIVE_TS_BASE;
????return?ret;
}

以上,便是今天的分享,希望大家喜歡,覺得內(nèi)容不錯的,歡迎「分享」「贊」或者點(diǎn)擊「在看」支持,謝謝各位。
評論
圖片
表情
