ff_read_packet函数也是会判断缓存是否有数据,若有则从缓存中取出,若没有,则调用demuxer的read_packet来读取数据。ff_read_packet()中最关键的地方就是调用了AVInputFormat的read_packet()方法。AVInputFormat的read_packet()是一个函数指针,指向当前的AVInputFormat的读取数据的函数,比如flv的flv_read_packet,flv_read_packet()的代码比较长,但是逻辑比较简单。它的主要功能就是根据FLV文件格式的规范,逐层解析Tag以及TagData,获取Tag以及TagData中的信息。
ff_read_packet的缓存和av_read_frame函数里的缓存是不一样的,ff_read_packet的缓存为AVFormatInternal::raw_packet_buffer,在av_read_frame函数里缓存则为
AVFormatInternal::packet_buffer,简单的理解为在codec被识别之前用raw_packet_buffer缓存,codec识别后用packet_buffer。
int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, i, err;
AVStream *st;
/*这里是不断从队列中取出一个pkt(raw buffer只要有数据)返回给上层和不断的读取数据
加入到raw buffer */
for (;;) {
AVPacketList *pktl = s->internal->raw_packet_buffer; //获取pkt节点
if (pktl) {
*pkt = pktl->pkt; //得到AVPacket包
st = s->streams[pkt->stream_index];
if (s->internal->raw_packet_buffer_remaining_size <= 0)
if ((err = probe_codec(s, st, NULL)) < 0)
return err;
if (st->request_probe <= 0) { //-1是probe完成,0是不要probe
s->internal->raw_packet_buffer = pktl->next;
s->internal->raw_packet_buffer_remaining_size += pkt->size; //归还队列空间
av_free(pktl);
return 0;
}
}
//raw_packet_buffer中没有pkt,自己去读/
//先赋个初值
pkt->data = NULL;
pkt->size = 0;
av_init_packet(pkt);
//0表示成功,小于0表示错误,pkt就在这里获取到。
ret = s->iformat->read_packet(s, pkt);
if (ret < 0) {
/* Some demuxers return FFERROR_REDO when they consume
data and discard it (ignored streams, junk, extradata).
We must re-call the demuxer to get the real packet. */
if (ret == FFERROR_REDO)
continue;
if (!pktl || ret == AVERROR(EAGAIN))
return ret;
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->probe_packets || st->request_probe > 0)
if ((err = probe_codec(s, st, NULL)) < 0)
return err;
av_assert0(st->request_probe <= 0);
}
continue;
}
err = av_packet_make_refcounted(pkt);
if (err < 0)
return err;
//读取成功,判断是否需要丢弃
if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) &&
(pkt->flags & AV_PKT_FLAG_CORRUPT)) {
av_log(s, AV_LOG_WARNING,
"Dropped corrupted packet (stream = %d)\n",
pkt->stream_index);
av_packet_unref(pkt);
continue;
}
if (pkt->stream_index >= (unsigned)s->nb_streams) {
av_log(s, AV_LOG_ERROR, "Invalid stream index %d\n", pkt->stream_index);
continue;
}
//得到读取到的这个包所在的stream,以为pkt获取时间戳
st = s->streams[pkt->stream_index];
if (update_wrap_reference(s, st, pkt->stream_index, pkt) && st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) {
// correct first time stamps to negative values
if (!is_relative(st->first_dts))
st->first_dts = wrap_timestamp(st, st->first_dts);
if (!is_relative(st->start_time))
st->start_time = wrap_timestamp(st, st->start_time);
if (!is_relative(st->cur_dts))
st->cur_dts = wrap_timestamp(st, st->cur_dts);
}
pkt->dts = wrap_timestamp(st, pkt->dts);
pkt->pts = wrap_timestamp(st, pkt->pts);
force_codec_ids(s, st);
/* TODO: audio: time filter; video: frame reordering (pts != dts) */
if (s->use_wallclock_as_timestamps)
pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base);
if (!pktl && st->request_probe <= 0)
return ret;
//给raw buff存入数据
err = ff_packet_list_put(&s->internal->raw_packet_buffer,
&s->internal->raw_packet_buffer_end,
pkt, 0);
if (err)
return err;
s->internal->raw_packet_buffer_remaining_size -= pkt->size;
if ((err = probe_codec(s, st, pkt)) < 0)
return err;
}
}