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
This commit is contained in:
Aurelien Jacobs 2008-05-08 21:47:31 +00:00
parent 40d0e665d0
commit 53a1e82bd2
2 changed files with 171 additions and 2 deletions

View File

@ -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.

View File

@ -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;