14.read_frame_internal
static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
{
...
//初始化packet
av_init_packet(pkt);
while (!got_packet && !s->parse_queue) {
...
/* read next packet */
/*
这个会调用format的read packet.
例如mkv的,稍后再对这个API进行深入剖析,这个API每次读取一个block data<==>AVPacket
AVInputFormat ff_matroska_demuxer = {
...
.read_packet = matroska_read_packet,
...
};
*/
ret = ff_read_packet(s, &cur_pkt);
if (ret < 0) {
if (ret == AVERROR(EAGAIN))
return ret;
/* flush the parsers */
for (i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
if (st->parser && st->need_parsing)
parse_packet(s, NULL, st->index);
}
/* all remaining packets are now in parse_queue =>
* really terminate parsing */
break;
}
ret = 0;
st = s->streams[cur_pkt.stream_index];
...
}
15.matroska_read_packet
static int matroska_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MatroskaDemuxContext *matroska = s->priv_data;
/*
从之前读取好的avpacket中,将packet[0] copy给pkt
static int matroska_deliver_packet(MatroskaDemuxContext *matroska,
AVPacket *pkt)
{
//第一次读,matroska->num_packets 为0,返回-1
if (matroska->num_packets > 0) {
//如果num_packets >0 说明有parse好的AVPacket,直接copy
memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
av_free(matroska->packets[0]);
if (matroska->num_packets > 1) {
void *newpackets;
//如果有多个,把指针数组往前移.
memmove(&matroska->packets[0], &matroska->packets[1],
(matroska->num_packets - 1) * sizeof(AVPacket *));
//把指针数组进行调整,调整前数组大小是num_packets,调整之后,
//数组大小为num_packets -1
newpackets = av_realloc(matroska->packets,
(matroska->num_packets - 1) *
sizeof(AVPacket *));
if (newpackets)
matroska->packets = newpackets;
} else {
//如果只有一个,会直接释放数组
av_freep(&matroska->packets);
matroska->prev_pkt = NULL;
}
//num减1
matroska->num_packets--;
return 0;
}
return -1;
}
*/
while (matroska_deliver_packet(matroska, pkt)) {
//第一次读,while条件是-1,需要重新parse cluster,读取avpacket,
//下面介绍 matroska_parse_cluster
int64_t pos = avio_tell(matroska->ctx->pb);
if (matroska->done)
return AVERROR_EOF;
if (matroska_parse_cluster(matroska) < 0)
matroska_resync(matroska, pos);
}
return 0;
}
static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
{
...
/*
static EbmlSyntax matroska_cluster[] = {
{ MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) },
{ MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
{ MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
{ MATROSKA_ID_CLUSTERPOSITION, EBML_NONE },
{ MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE },
{ 0 }
};
static EbmlSyntax matroska_clusters[] = {
{ MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, { .n = matroska_cluster } },
{ MATROSKA_ID_INFO, EBML_NONE },
{ MATROSKA_ID_CUES, EBML_NONE },
{ MATROSKA_ID_TAGS, EBML_NONE },
{ MATROSKA_ID_SEEKHEAD, EBML_NONE },
{ 0 }
};
只需要parse matroska_cluster 的ebml item以及其子ebml item.
一个cluster通常包含多个 block group或者 多个simple block.
ebml_parse这个API前面有介绍过,现在跳过.
*/
res = ebml_parse(matroska, matroska_clusters, &cluster);
blocks_list = &cluster.blocks;
blocks = blocks_list->elem;
//对每一个block parse,下面介绍 matroska_parse_block
for (i = 0; i < blocks_list->nb_elem; i++)
if (blocks[i].bin.size > 0 && blocks[i].bin.data) {
int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1;
res = matroska_parse_block(matroska, blocks[i].bin.data,
blocks[i].bin.size, blocks[i].bin.pos,
cluster.timecode, blocks[i].duration,
is_keyframe, NULL, 0, 0, pos,
blocks[i].discard_padding);
}
ebml_free(matroska_cluster, &cluster);
return res;
}
static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
int size, int64_t pos, uint64_t cluster_time,
uint64_t block_duration, int is_keyframe,
uint8_t *additional, uint64_t additional_id, int additional_size,
int64_t cluster_pos, int64_t discard_padding)
{
...
//找到这个block 中num 对应的track,matroska中,一个block只能对应一个track.
//前面在parse track时候,有将track信息保存在matroska中
track = matroska_find_track_by_num(matroska, num);
if (!track || !track->stream) {
av_log(matroska->ctx, AV_LOG_INFO,
"Invalid stream %"PRIu64" or size %u\n", num, size);
return AVERROR_INVALIDDATA;
} else if (size <= 3)
return 0;
st = track->stream;
if (st->discard >= AVDISCARD_ALL)
return res;
av_assert1(block_duration != AV_NOPTS_VALUE);
block_time = sign_extend(AV_RB16(data), 16);//读取block_time 的偏移量
//跳过已经parse过的内容
data += 2;
flags = *data++;
size -= 3;
if (is_keyframe == -1)
is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0;
//根据cluster time和 block_time(偏移量) 计算当前block的 timecode.
if (cluster_time != (uint64_t) -1 &&
(block_time >= 0 || cluster_time >= -block_time)) {
timecode = cluster_time + block_time - track->codec_delay;
if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE &&
timecode < track->end_timecode)
is_keyframe = 0; /* overlapping subtitles are not key frame */
if (is_keyframe)
av_add_index_entry(st, cluster_pos, timecode, 0, 0,
AVINDEX_KEYFRAME);
}
...
//parse lace,带蕾丝是ebml里的一种比较常见的数据储存.通常将多个frame,放在一个block中
//每个frame 由一个蕾丝组成,这个API就是找到每个蕾丝的边界
//有3中蕾丝类型.具体参考matroska官方文档. 如果不带lace,
//可以将这个block当着一个lace.
res = matroska_parse_laces(matroska, &data, &size, (flags & 0x06) >> 1,
&lace_size, &laces);
...
//对每个lace parse
for (n = 0; n < laces; n++) {
//计算每个lace的duration
int64_t lace_duration = block_duration*(n+1) / laces - block_duration*n / laces;
if (lace_size[n] > size) {
av_log(matroska->ctx, AV_LOG_ERROR, "Invalid packet size\n");
break;
}
if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
st->codec->codec_id == AV_CODEC_ID_COOK ||
st->codec->codec_id == AV_CODEC_ID_SIPR ||
st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
st->codec->block_align && track->audio.sub_packet_size) {
res = matroska_parse_rm_audio(matroska, track, st, data,
lace_size[n],
timecode, pos);
if (res)
goto end;
} else if (st->codec->codec_id == AV_CODEC_ID_WEBVTT) {
res = matroska_parse_webvtt(matroska, track, st,
data, lace_size[n],
timecode, lace_duration,
pos);
if (res)
goto end;
} else {
//接下来介绍 matroska_parse_frame
res = matroska_parse_frame(matroska, track, st, data, lace_size[n],
timecode, lace_duration, pos,
!n ? is_keyframe : 0,
additional, additional_id, additional_size,
discard_padding);
if (res)
goto end;
}
...
}
...
}
static int matroska_parse_frame(MatroskaDemuxContext *matroska,
MatroskaTrack *track, AVStream *st,
uint8_t *data, int pkt_size,
uint64_t timecode, uint64_t lace_duration,
int64_t pos, int is_keyframe,
uint8_t *additional, uint64_t additional_id, int additional_size,
int64_t discard_padding)
{
MatroskaTrackEncoding *encodings = track->encodings.elem;
uint8_t *pkt_data = data;
int offset = 0, res;
AVPacket *pkt;
//有些block data数据是压缩的,在送到decoder之前,需要解压缩,需要预处理
//是否压缩,以及压缩类型,在read_header 中都能获取
if (encodings && !encodings->type && encodings->scope & 1) {
res = matroska_decode_buffer(&pkt_data, &pkt_size, track);
if (res < 0)
return res;
}
...
//特定的codec类型处理
...
//分配AVPacket
pkt = av_mallocz(sizeof(AVPacket));
/* XXX: prevent data copy... */
if (av_new_packet(pkt, pkt_size + offset) < 0) {
av_free(pkt);
res = AVERROR(ENOMEM);
goto fail;
}
if (st->codec->codec_id == AV_CODEC_ID_PRORES && offset == 8) {
uint8_t *buf = pkt->data;
bytestream_put_be32(&buf, pkt_size);
bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
}
memcpy(pkt->data + offset, pkt_data, pkt_size);
...
//一坨子操作就是填充AVPacket
...
//将pkt添加到matroska->packets,同时matroska->num_packets 加1
//经过以上操作,才得到matroska->num_packets > 0,这样最开始的那个while循环,才能拿到一个
//AVPacket,退出循环
dynarray_add(&matroska->packets, &matroska->num_packets, pkt);
matroska->prev_pkt = pkt;
return 0;
...
}