Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: libavformat/matroskadec.c

Issue 9317107: FFmpeg merge diff after patches. (Closed) Base URL: ssh://gerrit.chromium.org:29418/chromium/third_party/ffmpeg.git@master
Patch Set: Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: libavformat/matroskadec.c
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index df54762c5ec279150dbf5482fcae5a2a211a312f..fd569be1874744038866b7a9b7865c210eb5add5 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -35,13 +35,17 @@
/* For ff_codec_get_id(). */
#include "riff.h"
#include "isom.h"
+#if CONFIG_SIPR_DECODER
#include "rm.h"
+#endif
#include "matroska.h"
#include "libavcodec/mpeg4audio.h"
#include "libavutil/intfloat.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/avstring.h"
+#if HAVE_LZO1X_999_COMPRESS
#include "libavutil/lzo.h"
+#endif
#include "libavutil/dict.h"
#if CONFIG_ZLIB
#include <zlib.h>
@@ -224,6 +228,11 @@ typedef struct {
} MatroskaLevel;
typedef struct {
+ uint64_t timecode;
+ EbmlList blocks;
+} MatroskaCluster;
+
+typedef struct {
AVFormatContext *ctx;
/* EBML stuff */
@@ -258,6 +267,10 @@ 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;
} MatroskaDemuxContext;
typedef struct {
@@ -267,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} },
@@ -542,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 *matroska_doctypes[] = { "matroska", "webm" };
/*
@@ -668,9 +708,10 @@ static int ebml_read_float(AVIOContext *pb, int size, double *num)
static int ebml_read_ascii(AVIOContext *pb, int size, char **str)
{
av_free(*str);
+ *str = NULL;
/* EBML strings are usually not 0-terminated, so we allocate one
* byte more, read the string and NULL-terminate it ourselves. */
- if (!(*str = av_malloc(size + 1)))
+ if (size < 0 || !(*str = av_malloc(size + 1)))
return AVERROR(ENOMEM);
if (avio_read(pb, (uint8_t *) *str, size) != size) {
av_freep(str);
@@ -978,6 +1019,7 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
switch (encodings[0].compression.algo) {
case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP:
return encodings[0].compression.settings.size;
+#if HAVE_LZO1X_999_COMPRESS
case MATROSKA_TRACK_ENCODING_COMP_LZO:
do {
olen = pkt_size *= 3;
@@ -988,6 +1030,7 @@ static int matroska_decode_buffer(uint8_t** buf, int* buf_size,
goto failed;
pkt_size -= olen;
break;
+#endif
#if CONFIG_ZLIB
case MATROSKA_TRACK_ENCODING_COMP_ZLIB: {
z_stream zstream = {0};
@@ -1340,6 +1383,7 @@ static int matroska_read_header(AVFormatContext *s)
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
ebml.version, ebml.doctype, ebml.doctype_version);
}
+ av_dict_set(&s->metadata, "doctype", ebml.doctype, 0);
for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++)
if (!strcmp(ebml.doctype, matroska_doctypes[i]))
break;
@@ -1402,14 +1446,17 @@ static int matroska_read_header(AVFormatContext *s)
"Multiple combined encodings not supported");
} else if (encodings_list->nb_elem == 1) {
if (encodings[0].type ||
- (encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP &&
+ (encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP
#if CONFIG_ZLIB
- encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB &&
+ && encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB
#endif
#if CONFIG_BZLIB
- encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB &&
+ && encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB
+#endif
+#if HAVE_LZO1X_999_COMPRESS
+ && encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO
#endif
- encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO)) {
+ )) {
encodings[0].scope = 0;
av_log(matroska->ctx, AV_LOG_ERROR,
"Unsupported encoding type");
@@ -1537,11 +1584,13 @@ static int matroska_read_header(AVFormatContext *s)
st->codec->block_align = track->audio.coded_framesize;
track->codec_priv.size = 0;
} else {
+#if CONFIG_SIPR_DECODER
if (codec_id == CODEC_ID_SIPR && flavor < 4) {
const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 };
track->audio.sub_packet_size = ff_sipr_subpk_size[flavor];
st->codec->bit_rate = sipr_bit_rate[flavor];
}
+#endif
st->codec->block_align = track->audio.sub_packet_size;
extradata_offset = 78;
}
@@ -1621,6 +1670,8 @@ static int matroska_read_header(AVFormatContext *s)
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
st->codec->sample_rate = track->audio.out_samplerate;
+ if (st->codec->sample_rate <= 0)
+ st->codec->sample_rate = 1;
st->codec->channels = track->audio.channels;
if (st->codec->codec_id != CODEC_ID_AAC)
st->need_parsing = AVSTREAM_PARSE_HEADERS;
@@ -1699,6 +1750,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;
@@ -1887,8 +1939,10 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
memcpy(track->audio.buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
if (++track->audio.sub_packet_cnt >= h) {
+#if CONFIG_SIPR_DECODER
if (st->codec->codec_id == CODEC_ID_SIPR)
ff_rm_reorder_sipr_data(track->audio.buf, h, w);
+#endif
track->audio.sub_packet_cnt = 0;
track->audio.pkt_cnt = h*w / a;
}
@@ -2001,17 +2055,71 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
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 agiain. */
+ 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;
+ 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_read_packet(AVFormatContext *s, AVPacket *pkt)
{
MatroskaDemuxContext *matroska = s->priv_data;
+ int ret = 0;
- while (matroska_deliver_packet(matroska, pkt)) {
+ while (!ret && matroska_deliver_packet(matroska, pkt)) {
if (matroska->done)
return AVERROR_EOF;
- matroska_parse_cluster(matroska);
+ ret = matroska_parse_cluster_incremental(matroska);
}
- return 0;
+ return ret;
}
static int matroska_read_seek(AVFormatContext *s, int stream_index,
@@ -2082,6 +2190,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;

Powered by Google App Engine
This is Rietveld 408576698