1. 程式人生 > >分析av_read_frame、av_read_frame_internal和av_read_packet的主要步驟

分析av_read_frame、av_read_frame_internal和av_read_packet的主要步驟

/*av_read_frame
1.先判斷快取[s->packet_buffer, s->packet_buffer_end)中是否存在packet
2.快取中沒有packet時呼叫av_read_frame_internal
*/
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{
	pktl = s->packet_buffer;
	if (pktl) 
	{
		AVPacket *next_pkt= &pktl->pkt;
		/* read packet from packet buffer, if there is data */
		*pkt = *next_pkt;
		s->packet_buffer = pktl->next;
		av_free(pktl);
		return 0;
	}

	return av_read_frame_internal(s, pkt);
}

/*av_read_frame_internal
1.先判斷快取s->cur_st->cur_pkt中是否可以再Pasre出packet
2.不能Pasre出packet時呼叫av_read_packet,並設定到s->cur_st->cur_pkt
*/
static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
{
	AVStream *st;
	int len, ret, i;

	av_init_packet(pkt);

	for(;;) 
	{
		/* select current input stream component */
		st = s->cur_st;
		if (st) 
		{
			if (!st->need_parsing || !st->parser) 
			{
				/* no parsing needed: we just output the packet as is */
				/* raw data support */
				*pkt = st->cur_pkt; st->cur_pkt.data= NULL;
				compute_pkt_fields(s, st, NULL, pkt);
				s->cur_st = NULL;
				break;
			} 
			else if (st->cur_len > 0 && st->discard < AVDISCARD_ALL) 
			{
				len = av_parser_parse(st->parser, st->codec, &pkt->data, &pkt->size,
					st->cur_ptr, st->cur_len,
					st->cur_pkt.pts, st->cur_pkt.dts);
				st->cur_pkt.pts = AV_NOPTS_VALUE;
				st->cur_pkt.dts = AV_NOPTS_VALUE;
				/* increment read pointer */
				st->cur_ptr += len;
				st->cur_len -= len;
			}
		} 
		else 
		{
			AVPacket cur_pkt;
			/* read next packet */
			ret = av_read_packet(s, &cur_pkt);

			st = s->streams[cur_pkt.stream_index];
			st->cur_pkt= cur_pkt;

			s->cur_st = st;
			st->cur_ptr = st->cur_pkt.data;
			st->cur_len = st->cur_pkt.size;
		}
	}
	return 0;
}

/*av_read_packet
1.先判斷快取[s->raw_packet_buffer, s->raw_packet_buffer_end)中是否存在packet
2.快取中沒有packet時呼叫s->iformat->read_packet(s, pkt);
3.呼叫add_to_pktbuf將packet加入[s->raw_packet_buffer, s->raw_packet_buffer_end)中
*/

int av_read_packet(AVFormatContext *s, AVPacket *pkt)
{
	int ret;
	AVStream *st;

	for(;;)
	{
		AVPacketList *pktl = s->raw_packet_buffer;

		if (pktl) 
		{
			*pkt = pktl->pkt;
			s->raw_packet_buffer = pktl->next;
			av_free(pktl);
			return 0;
		}

		av_init_packet(pkt);

		//如果是AVI format,則最終呼叫avidec.c的avi_read_packet
		ret= s->iformat->read_packet(s, pkt);
		if (ret < 0)
			return ret;

		add_to_pktbuf(&s->raw_packet_buffer, pkt, &s->raw_packet_buffer_end);
	}
}

/*要點:
1.av_read_frame中快取的[s->packet_buffer, s->packet_buffer_end)是經過parse後的
2.av_read_packet中快取的[s->raw_packet_buffer, s->raw_packet_buffer_end)是從源讀入的Packet,是Raw Data
3.av_read_frame_internal中parse的是Raw Data的Packet,關鍵在 len = av_parser_parse(st->parser, st->codec, 
&pkt->data, &pkt->size,	//解析後輸出的Packet,應該是one frame
st->cur_ptr, st->cur_len,//從源讀入的Raw Data的Packet
st->cur_pkt.pts, st->cur_pkt.dts);
4. s->parser->parser_parse函式是為了從raw packet中重構frame

*/