diff options
author | Aurelien Jacobs <aurel@gnuage.org> | 2008-05-08 21:47:31 +0000 |
---|---|---|
committer | Aurelien Jacobs <aurel@gnuage.org> | 2008-05-08 21:47:31 +0000 |
commit | 53a1e82bd25f926679a165a6c632ccc799fddb3c (patch) | |
tree | 82785f3db0cf12c976594a88ee4ba79550f9e951 | |
parent | 40d0e665d09aca5918c0b70b7045f32fae71f3eb (diff) | |
download | ffmpeg-53a1e82bd25f926679a165a6c632ccc799fddb3c.tar.gz |
matroskadec: add support for track content encoding
Only the header strip method is supported for now.
Originally committed as revision 13082 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavformat/matroska.h | 16 | ||||
-rw-r--r-- | libavformat/matroskadec.c | 157 |
2 files changed, 171 insertions, 2 deletions
diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 370a8bfd89..025eefb3e2 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -89,6 +89,8 @@ #define MATROSKA_ID_TRACKMINCACHE 0x6DE7 #define MATROSKA_ID_TRACKMAXCACHE 0x6DF8 #define MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383 +#define MATROSKA_ID_TRACKCONTENTENCODINGS 0x6D80 +#define MATROSKA_ID_TRACKCONTENTENCODING 0x6240 /* IDs in the trackvideo master */ #define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3 @@ -108,6 +110,13 @@ #define MATROSKA_ID_AUDIOBITDEPTH 0x6264 #define MATROSKA_ID_AUDIOCHANNELS 0x9F +/* IDs in the content encoding master */ +#define MATROSKA_ID_ENCODINGSCOPE 0x5032 +#define MATROSKA_ID_ENCODINGTYPE 0x5033 +#define MATROSKA_ID_ENCODINGCOMPRESSION 0x5034 +#define MATROSKA_ID_ENCODINGCOMPALGO 0x4254 +#define MATROSKA_ID_ENCODINGCOMPSETTINGS 0x4255 + /* ID in the cues master */ #define MATROSKA_ID_POINTENTRY 0xBB @@ -168,6 +177,13 @@ typedef enum { MATROSKA_ASPECT_RATIO_MODE_FIXED = 0x2, } MatroskaAspectRatioMode; +typedef enum { + MATROSKA_TRACK_ENCODING_COMP_ZLIB = 0, + MATROSKA_TRACK_ENCODING_COMP_BZLIB = 1, + MATROSKA_TRACK_ENCODING_COMP_LZO = 2, + MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP = 3, +} MatroskaTrackEncodingCompAlgo; + /* * These aren't in any way "matroska-form" things, * it's just something I use in the muxer/demuxer. diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 25fbdd5967..4899fb4db7 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -55,6 +55,11 @@ typedef struct Track { uint64_t default_duration; MatroskaTrackFlags flags; + + int encoding_scope; + int encoding_algo; + uint8_t *encoding_settings; + int encoding_settings_len; } MatroskaTrack; typedef struct MatroskaVideoTrack { @@ -1428,6 +1433,147 @@ matroska_add_stream (MatroskaDemuxContext *matroska) break; } + case MATROSKA_ID_TRACKCONTENTENCODINGS: { + if ((res = ebml_read_master(matroska, &id)) < 0) + break; + + while (res == 0) { + if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { + res = AVERROR(EIO); + break; + } else if (matroska->level_up > 0) { + matroska->level_up--; + break; + } + + switch (id) { + case MATROSKA_ID_TRACKCONTENTENCODING: { + int encoding_scope = 1; + if ((res = ebml_read_master(matroska, &id)) < 0) + break; + + while (res == 0) { + if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { + res = AVERROR(EIO); + break; + } else if (matroska->level_up > 0) { + matroska->level_up--; + break; + } + + switch (id) { + case MATROSKA_ID_ENCODINGSCOPE: { + uint64_t num; + if ((res = ebml_read_uint(matroska, &id, &num)) < 0) + break; + encoding_scope = num; + break; + } + + case MATROSKA_ID_ENCODINGTYPE: { + uint64_t num; + if ((res = ebml_read_uint(matroska, &id, &num)) < 0) + break; + if (num) + av_log(matroska->ctx, AV_LOG_ERROR, + "Unsupported encoding type"); + break; + } + + case MATROSKA_ID_ENCODINGCOMPRESSION: { + if ((res = ebml_read_master(matroska, &id)) < 0) + break; + + while (res == 0) { + if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { + res = AVERROR(EIO); + break; + } else if (matroska->level_up > 0) { + matroska->level_up--; + break; + } + + switch (id) { + case MATROSKA_ID_ENCODINGCOMPALGO: { + uint64_t num; + if ((res = ebml_read_uint(matroska, &id, &num)) < 0) + break; + if (num != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) + av_log(matroska->ctx, AV_LOG_ERROR, + "Unsupported compression algo"); + track->encoding_algo = num; + break; + } + + case MATROSKA_ID_ENCODINGCOMPSETTINGS: { + uint8_t *data; + int size; + if ((res = ebml_read_binary(matroska, &id, &data, &size) < 0)) + break; + track->encoding_settings = data; + track->encoding_settings_len = size; + break; + } + + default: + av_log(matroska->ctx, AV_LOG_INFO, + "Unknown compression header entry " + "0x%x - ignoring\n", id); + /* pass-through */ + + case EBML_ID_VOID: + res = ebml_read_skip(matroska); + break; + } + + if (matroska->level_up) { + matroska->level_up--; + break; + } + } + break; + } + + default: + av_log(matroska->ctx, AV_LOG_INFO, + "Unknown content encoding header entry " + "0x%x - ignoring\n", id); + /* pass-through */ + + case EBML_ID_VOID: + res = ebml_read_skip(matroska); + break; + } + + if (matroska->level_up) { + matroska->level_up--; + break; + } + } + + track->encoding_scope = encoding_scope; + break; + } + + default: + av_log(matroska->ctx, AV_LOG_INFO, + "Unknown content encodings header entry " + "0x%x - ignoring\n", id); + /* pass-through */ + + case EBML_ID_VOID: + res = ebml_read_skip(matroska); + break; + } + + if (matroska->level_up) { + matroska->level_up--; + break; + } + } + break; + } + default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown track header entry 0x%x - ignoring\n", id); @@ -2551,14 +2697,21 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size, } else { int offset = 0; + if (matroska->tracks[track]->encoding_scope&1 && + matroska->tracks[track]->encoding_algo == MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) { + offset = matroska->tracks[track]->encoding_settings_len; + } + pkt = av_mallocz(sizeof(AVPacket)); /* XXX: prevent data copy... */ - if (av_new_packet(pkt, lace_size[n]-offset) < 0) { + if (av_new_packet(pkt, lace_size[n]+offset) < 0) { res = AVERROR(ENOMEM); n = laces-1; break; } - memcpy (pkt->data, data+offset, lace_size[n]-offset); + if (offset) + memcpy (pkt->data, matroska->tracks[track]->encoding_settings, offset); + memcpy (pkt->data+offset, data, lace_size[n]); if (n == 0) pkt->flags = is_keyframe; |