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