diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-04-24 00:19:55 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-04-24 02:30:41 +0200 |
commit | 3bbf3f7e42247b7a8b34b1e8cc891b59e1327bb8 (patch) | |
tree | bf3b0776b76e0f5c4c331d9d069f16e3c0236a9c /libavformat | |
parent | 2e8f19d26f3ef7e804a7f9f9811e4b538e0a5969 (diff) | |
parent | 7521c4bab28ff3a622171be5b39a6b210f4263f0 (diff) | |
download | ffmpeg-3bbf3f7e42247b7a8b34b1e8cc891b59e1327bb8.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
matroska: Clear prev_pkt between seeks.
avutil: change default buffer size alignment for sample buffer functions
audemux: Add a sanity check for the number of channels
Remove libdirac decoder.
matroska: Add incremental parsing of clusters.
avconv: fix off by one check in complex_filter
mpegts: Try seeking back even for nonseekable protocols
swscale: K&R formatting cosmetics (part III)
Conflicts:
configure
doc/general.texi
doc/platform.texi
ffmpeg.c
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/libdirac.h
libavcodec/libdiracdec.c
libavformat/au.c
libavformat/mpegts.c
libswscale/input.c
tests/ref/seek/lavf_mkv
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/au.c | 2 | ||||
-rw-r--r-- | libavformat/matroskadec.c | 115 |
2 files changed, 110 insertions, 7 deletions
diff --git a/libavformat/au.c b/libavformat/au.c index b66d559d3c..aa52a96ea1 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -150,7 +150,7 @@ static int au_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - if (channels <= 0) { + if (channels == 0 || channels > 64) { av_log(s, AV_LOG_ERROR, "Invalid number of channels %d\n", channels); return AVERROR_INVALIDDATA; } diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 41427fe5eb..355bcbb08c 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -224,6 +224,11 @@ typedef struct { } MatroskaLevel; typedef struct { + uint64_t timecode; + EbmlList blocks; +} MatroskaCluster; + +typedef struct { AVFormatContext *ctx; /* EBML stuff */ @@ -259,6 +264,13 @@ typedef struct { /* File has a CUES element, but we defer parsing until it is needed. */ int cues_parsing_deferred; + + int current_cluster_num_blocks; + int64_t current_cluster_pos; + MatroskaCluster current_cluster; + + /* File has SSA subtitles which prevent incremental cluster parsing. */ + int contains_ssa; } MatroskaDemuxContext; typedef struct { @@ -268,11 +280,6 @@ typedef struct { EbmlBin bin; } MatroskaBlock; -typedef struct { - uint64_t timecode; - EbmlList blocks; -} MatroskaCluster; - static EbmlSyntax ebml_header[] = { { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml,version), {.u=EBML_VERSION} }, { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml,max_size), {.u=8} }, @@ -543,6 +550,38 @@ static EbmlSyntax matroska_clusters[] = { { 0 } }; +static EbmlSyntax matroska_cluster_incremental_parsing[] = { + { 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 }, + { MATROSKA_ID_INFO, EBML_NONE }, + { MATROSKA_ID_CUES, EBML_NONE }, + { MATROSKA_ID_TAGS, EBML_NONE }, + { MATROSKA_ID_SEEKHEAD, EBML_NONE }, + { MATROSKA_ID_CLUSTER, EBML_STOP }, + { 0 } +}; + +static EbmlSyntax matroska_cluster_incremental[] = { + { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) }, + { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, + { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, + { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE }, + { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, + { 0 } +}; + +static EbmlSyntax matroska_clusters_incremental[] = { + { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster_incremental} }, + { MATROSKA_ID_INFO, EBML_NONE }, + { MATROSKA_ID_CUES, EBML_NONE }, + { MATROSKA_ID_TAGS, EBML_NONE }, + { MATROSKA_ID_SEEKHEAD, EBML_NONE }, + { 0 } +}; + static const char *const matroska_doctypes[] = { "matroska", "webm" }; static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) @@ -1693,6 +1732,8 @@ static int matroska_read_header(AVFormatContext *s) st->need_parsing = AVSTREAM_PARSE_HEADERS; } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + if (st->codec->codec_id == CODEC_ID_SSA) + matroska->contains_ssa = 1; } } @@ -1766,6 +1807,7 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, matroska->packets = newpackets; } else { av_freep(&matroska->packets); + matroska->prev_pkt = NULL; } matroska->num_packets--; return 0; @@ -1822,6 +1864,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, st = track->stream; if (st->discard >= AVDISCARD_ALL) return res; + av_assert1(duration != AV_NOPTS_VALUE); if (!duration) duration = track->default_duration / matroska->time_scale; @@ -2066,13 +2109,71 @@ end: return res; } +static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) +{ + EbmlList *blocks_list; + MatroskaBlock *blocks; + int i, res; + res = ebml_parse(matroska, + matroska_cluster_incremental_parsing, + &matroska->current_cluster); + if (res == 1) { + /* New Cluster */ + if (matroska->current_cluster_pos) + ebml_level_end(matroska); + ebml_free(matroska_cluster, &matroska->current_cluster); + memset(&matroska->current_cluster, 0, sizeof(MatroskaCluster)); + matroska->current_cluster_num_blocks = 0; + matroska->current_cluster_pos = avio_tell(matroska->ctx->pb); + matroska->prev_pkt = NULL; + /* sizeof the ID which was already read */ + if (matroska->current_id) + matroska->current_cluster_pos -= 4; + res = ebml_parse(matroska, + matroska_clusters_incremental, + &matroska->current_cluster); + /* Try parsing the block again. */ + if (res == 1) + res = ebml_parse(matroska, + matroska_cluster_incremental_parsing, + &matroska->current_cluster); + } + + if (!res && + matroska->current_cluster_num_blocks < + matroska->current_cluster.blocks.nb_elem) { + blocks_list = &matroska->current_cluster.blocks; + blocks = blocks_list->elem; + + matroska->current_cluster_num_blocks = blocks_list->nb_elem; + i = blocks_list->nb_elem - 1; + if (blocks[i].bin.size > 0 && blocks[i].bin.data) { + int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; + if (!blocks[i].non_simple) + blocks[i].duration = 0; + res = matroska_parse_block(matroska, + blocks[i].bin.data, blocks[i].bin.size, + blocks[i].bin.pos, + matroska->current_cluster.timecode, + blocks[i].duration, is_keyframe, + matroska->current_cluster_pos); + } + } + + if (res < 0) matroska->done = 1; + return res; +} + static int matroska_parse_cluster(MatroskaDemuxContext *matroska) { MatroskaCluster cluster = { 0 }; EbmlList *blocks_list; MatroskaBlock *blocks; int i, res; - int64_t pos = avio_tell(matroska->ctx->pb); + int64_t pos; + if (!matroska->contains_ssa) + return matroska_parse_cluster_incremental(matroska); + pos = avio_tell(matroska->ctx->pb); matroska->prev_pkt = NULL; if (matroska->current_id) pos -= 4; /* sizeof the ID which was already read */ @@ -2129,6 +2230,7 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, avio_seek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET); matroska->current_id = 0; while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) { + matroska->prev_pkt = NULL; matroska_clear_queue(matroska); if (matroska_parse_cluster(matroska) < 0) break; @@ -2187,6 +2289,7 @@ static int matroska_read_close(AVFormatContext *s) for (n=0; n < matroska->tracks.nb_elem; n++) if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) av_free(tracks[n].audio.buf); + ebml_free(matroska_cluster, &matroska->current_cluster); ebml_free(matroska_segment, matroska); return 0; |