|
|
@ -1156,13 +1156,6 @@ matroska_parse_info (MatroskaDemuxContext *matroska) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int res = ebml_parse(matroska, matroska_info, matroska, MATROSKA_ID_INFO, 0); |
|
|
|
int res = ebml_parse(matroska, matroska_info, matroska, MATROSKA_ID_INFO, 0); |
|
|
|
|
|
|
|
|
|
|
|
if (matroska->duration) |
|
|
|
|
|
|
|
matroska->ctx->duration = matroska->duration * matroska->time_scale |
|
|
|
|
|
|
|
* 1000 / AV_TIME_BASE; |
|
|
|
|
|
|
|
if (matroska->title) |
|
|
|
|
|
|
|
strncpy(matroska->ctx->title, matroska->title, |
|
|
|
|
|
|
|
sizeof(matroska->ctx->title)-1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1246,77 +1239,10 @@ matroska_decode_buffer(uint8_t** buf, int* buf_size, MatroskaTrack *track) |
|
|
|
static int |
|
|
|
static int |
|
|
|
matroska_parse_tracks (MatroskaDemuxContext *matroska) |
|
|
|
matroska_parse_tracks (MatroskaDemuxContext *matroska) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MatroskaTrack *tracks; |
|
|
|
|
|
|
|
int i, res; |
|
|
|
int i, res; |
|
|
|
|
|
|
|
|
|
|
|
res = ebml_parse(matroska, matroska_tracks, matroska, MATROSKA_ID_TRACKS, 0); |
|
|
|
res = ebml_parse(matroska, matroska_tracks, matroska, MATROSKA_ID_TRACKS, 0); |
|
|
|
|
|
|
|
|
|
|
|
tracks = matroska->tracks.elem; |
|
|
|
|
|
|
|
for (i=0; i<matroska->tracks.nb_elem; i++) { |
|
|
|
|
|
|
|
MatroskaTrack *track = &tracks[i]; |
|
|
|
|
|
|
|
EbmlList *encodings_list = &tracks->encodings; |
|
|
|
|
|
|
|
MatroskaTrackEncoding *encodings = encodings_list->elem; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (track->type != MATROSKA_TRACK_TYPE_VIDEO && |
|
|
|
|
|
|
|
track->type != MATROSKA_TRACK_TYPE_AUDIO && |
|
|
|
|
|
|
|
track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_INFO, |
|
|
|
|
|
|
|
"Unknown or unsupported track type %"PRIu64"\n", |
|
|
|
|
|
|
|
track->type); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { |
|
|
|
|
|
|
|
if (!track->default_duration) |
|
|
|
|
|
|
|
track->default_duration = 1000000000/track->video.frame_rate; |
|
|
|
|
|
|
|
if (!track->video.display_width) |
|
|
|
|
|
|
|
track->video.display_width = track->video.pixel_width; |
|
|
|
|
|
|
|
if (!track->video.display_height) |
|
|
|
|
|
|
|
track->video.display_height = track->video.pixel_height; |
|
|
|
|
|
|
|
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { |
|
|
|
|
|
|
|
if (!track->audio.out_samplerate) |
|
|
|
|
|
|
|
track->audio.out_samplerate = track->audio.samplerate; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (encodings_list->nb_elem > 1) { |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, |
|
|
|
|
|
|
|
"Multiple combined encodings no supported"); |
|
|
|
|
|
|
|
} else if (encodings_list->nb_elem == 1) { |
|
|
|
|
|
|
|
if (encodings[0].type || |
|
|
|
|
|
|
|
(encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP && |
|
|
|
|
|
|
|
#ifdef CONFIG_ZLIB |
|
|
|
|
|
|
|
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB && |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
#ifdef CONFIG_BZLIB |
|
|
|
|
|
|
|
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB && |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO)) { |
|
|
|
|
|
|
|
encodings[0].scope = 0; |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, |
|
|
|
|
|
|
|
"Unsupported encoding type"); |
|
|
|
|
|
|
|
} else if (track->codec_priv.size && encodings[0].scope&2) { |
|
|
|
|
|
|
|
uint8_t *codec_priv = track->codec_priv.data; |
|
|
|
|
|
|
|
int offset = matroska_decode_buffer(&track->codec_priv.data, |
|
|
|
|
|
|
|
&track->codec_priv.size, |
|
|
|
|
|
|
|
track); |
|
|
|
|
|
|
|
if (offset < 0) { |
|
|
|
|
|
|
|
track->codec_priv.data = NULL; |
|
|
|
|
|
|
|
track->codec_priv.size = 0; |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, |
|
|
|
|
|
|
|
"Failed to decode codec private data\n"); |
|
|
|
|
|
|
|
} else if (offset > 0) { |
|
|
|
|
|
|
|
track->codec_priv.data = av_malloc(track->codec_priv.size + offset); |
|
|
|
|
|
|
|
memcpy(track->codec_priv.data, |
|
|
|
|
|
|
|
encodings[0].compression.settings.data, offset); |
|
|
|
|
|
|
|
memcpy(track->codec_priv.data+offset, codec_priv, |
|
|
|
|
|
|
|
track->codec_priv.size); |
|
|
|
|
|
|
|
track->codec_priv.size += offset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (codec_priv != track->codec_priv.data) |
|
|
|
|
|
|
|
av_free(codec_priv); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1425,40 +1351,10 @@ static int |
|
|
|
matroska_parse_attachments(AVFormatContext *s) |
|
|
|
matroska_parse_attachments(AVFormatContext *s) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MatroskaDemuxContext *matroska = s->priv_data; |
|
|
|
MatroskaDemuxContext *matroska = s->priv_data; |
|
|
|
EbmlList *attachements_list = &matroska->attachments; |
|
|
|
|
|
|
|
MatroskaAttachement *attachements; |
|
|
|
|
|
|
|
int i, j, res; |
|
|
|
int i, j, res; |
|
|
|
|
|
|
|
|
|
|
|
res = ebml_parse(matroska, matroska_attachments, matroska, MATROSKA_ID_ATTACHMENTS, 0); |
|
|
|
res = ebml_parse(matroska, matroska_attachments, matroska, MATROSKA_ID_ATTACHMENTS, 0); |
|
|
|
|
|
|
|
|
|
|
|
attachements = attachements_list->elem; |
|
|
|
|
|
|
|
for (j=0; j<attachements_list->nb_elem; j++) { |
|
|
|
|
|
|
|
if (!(attachements[j].filename && attachements[j].mime && |
|
|
|
|
|
|
|
attachements[j].bin.data && attachements[j].bin.size > 0)) { |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n"); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
AVStream *st = av_new_stream(s, matroska->num_streams++); |
|
|
|
|
|
|
|
if (st == NULL) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
st->filename = av_strdup(attachements[j].filename); |
|
|
|
|
|
|
|
st->codec->codec_id = CODEC_ID_NONE; |
|
|
|
|
|
|
|
st->codec->codec_type = CODEC_TYPE_ATTACHMENT; |
|
|
|
|
|
|
|
st->codec->extradata = av_malloc(attachements[j].bin.size); |
|
|
|
|
|
|
|
if(st->codec->extradata == NULL) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
st->codec->extradata_size = attachements[j].bin.size; |
|
|
|
|
|
|
|
memcpy(st->codec->extradata, attachements[j].bin.data, attachements[j].bin.size); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) { |
|
|
|
|
|
|
|
if (!strncmp(ff_mkv_mime_tags[i].str, attachements[j].mime, |
|
|
|
|
|
|
|
strlen(ff_mkv_mime_tags[i].str))) { |
|
|
|
|
|
|
|
st->codec->codec_id = ff_mkv_mime_tags[i].id; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1466,19 +1362,10 @@ static int |
|
|
|
matroska_parse_chapters(AVFormatContext *s) |
|
|
|
matroska_parse_chapters(AVFormatContext *s) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MatroskaDemuxContext *matroska = s->priv_data; |
|
|
|
MatroskaDemuxContext *matroska = s->priv_data; |
|
|
|
EbmlList *chapters_list = &matroska->chapters; |
|
|
|
|
|
|
|
MatroskaChapter *chapters; |
|
|
|
|
|
|
|
int i, res; |
|
|
|
int i, res; |
|
|
|
|
|
|
|
|
|
|
|
res = ebml_parse(matroska, matroska_chapters, matroska, MATROSKA_ID_CHAPTERS, 0); |
|
|
|
res = ebml_parse(matroska, matroska_chapters, matroska, MATROSKA_ID_CHAPTERS, 0); |
|
|
|
|
|
|
|
|
|
|
|
chapters = chapters_list->elem; |
|
|
|
|
|
|
|
for (i=0; i<chapters_list->nb_elem; i++) |
|
|
|
|
|
|
|
if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid) |
|
|
|
|
|
|
|
ff_new_chapter(s, chapters[i].uid, (AVRational){1, 1000000000}, |
|
|
|
|
|
|
|
chapters[i].start, chapters[i].end, |
|
|
|
|
|
|
|
chapters[i].title); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1512,6 +1399,10 @@ matroska_read_header (AVFormatContext *s, |
|
|
|
AVFormatParameters *ap) |
|
|
|
AVFormatParameters *ap) |
|
|
|
{ |
|
|
|
{ |
|
|
|
MatroskaDemuxContext *matroska = s->priv_data; |
|
|
|
MatroskaDemuxContext *matroska = s->priv_data; |
|
|
|
|
|
|
|
EbmlList *attachements_list = &matroska->attachments; |
|
|
|
|
|
|
|
MatroskaAttachement *attachements; |
|
|
|
|
|
|
|
EbmlList *chapters_list = &matroska->chapters; |
|
|
|
|
|
|
|
MatroskaChapter *chapters; |
|
|
|
MatroskaTrack *tracks; |
|
|
|
MatroskaTrack *tracks; |
|
|
|
EbmlList *index_list; |
|
|
|
EbmlList *index_list; |
|
|
|
MatroskaIndex *index; |
|
|
|
MatroskaIndex *index; |
|
|
@ -1643,18 +1534,85 @@ matroska_read_header (AVFormatContext *s, |
|
|
|
if (ebml_peek_id(matroska, NULL) != MATROSKA_ID_CLUSTER) |
|
|
|
if (ebml_peek_id(matroska, NULL) != MATROSKA_ID_CLUSTER) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (matroska->duration) |
|
|
|
|
|
|
|
matroska->ctx->duration = matroska->duration * matroska->time_scale |
|
|
|
|
|
|
|
* 1000 / AV_TIME_BASE; |
|
|
|
|
|
|
|
if (matroska->title) |
|
|
|
|
|
|
|
strncpy(matroska->ctx->title, matroska->title, |
|
|
|
|
|
|
|
sizeof(matroska->ctx->title)-1); |
|
|
|
|
|
|
|
|
|
|
|
tracks = matroska->tracks.elem; |
|
|
|
tracks = matroska->tracks.elem; |
|
|
|
for (i=0; i < matroska->tracks.nb_elem; i++) { |
|
|
|
for (i=0; i < matroska->tracks.nb_elem; i++) { |
|
|
|
MatroskaTrack *track = &tracks[i]; |
|
|
|
MatroskaTrack *track = &tracks[i]; |
|
|
|
enum CodecID codec_id = CODEC_ID_NONE; |
|
|
|
enum CodecID codec_id = CODEC_ID_NONE; |
|
|
|
|
|
|
|
EbmlList *encodings_list = &tracks->encodings; |
|
|
|
|
|
|
|
MatroskaTrackEncoding *encodings = encodings_list->elem; |
|
|
|
uint8_t *extradata = NULL; |
|
|
|
uint8_t *extradata = NULL; |
|
|
|
int extradata_size = 0; |
|
|
|
int extradata_size = 0; |
|
|
|
int extradata_offset = 0; |
|
|
|
int extradata_offset = 0; |
|
|
|
|
|
|
|
|
|
|
|
/* Apply some sanity checks. */ |
|
|
|
/* Apply some sanity checks. */ |
|
|
|
|
|
|
|
if (track->type != MATROSKA_TRACK_TYPE_VIDEO && |
|
|
|
|
|
|
|
track->type != MATROSKA_TRACK_TYPE_AUDIO && |
|
|
|
|
|
|
|
track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_INFO, |
|
|
|
|
|
|
|
"Unknown or unsupported track type %"PRIu64"\n", |
|
|
|
|
|
|
|
track->type); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
if (track->codec_id == NULL) |
|
|
|
if (track->codec_id == NULL) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { |
|
|
|
|
|
|
|
if (!track->default_duration) |
|
|
|
|
|
|
|
track->default_duration = 1000000000/track->video.frame_rate; |
|
|
|
|
|
|
|
if (!track->video.display_width) |
|
|
|
|
|
|
|
track->video.display_width = track->video.pixel_width; |
|
|
|
|
|
|
|
if (!track->video.display_height) |
|
|
|
|
|
|
|
track->video.display_height = track->video.pixel_height; |
|
|
|
|
|
|
|
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { |
|
|
|
|
|
|
|
if (!track->audio.out_samplerate) |
|
|
|
|
|
|
|
track->audio.out_samplerate = track->audio.samplerate; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (encodings_list->nb_elem > 1) { |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, |
|
|
|
|
|
|
|
"Multiple combined encodings no supported"); |
|
|
|
|
|
|
|
} else if (encodings_list->nb_elem == 1) { |
|
|
|
|
|
|
|
if (encodings[0].type || |
|
|
|
|
|
|
|
(encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP && |
|
|
|
|
|
|
|
#ifdef CONFIG_ZLIB |
|
|
|
|
|
|
|
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB && |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
#ifdef CONFIG_BZLIB |
|
|
|
|
|
|
|
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB && |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO)) { |
|
|
|
|
|
|
|
encodings[0].scope = 0; |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, |
|
|
|
|
|
|
|
"Unsupported encoding type"); |
|
|
|
|
|
|
|
} else if (track->codec_priv.size && encodings[0].scope&2) { |
|
|
|
|
|
|
|
uint8_t *codec_priv = track->codec_priv.data; |
|
|
|
|
|
|
|
int offset = matroska_decode_buffer(&track->codec_priv.data, |
|
|
|
|
|
|
|
&track->codec_priv.size, |
|
|
|
|
|
|
|
track); |
|
|
|
|
|
|
|
if (offset < 0) { |
|
|
|
|
|
|
|
track->codec_priv.data = NULL; |
|
|
|
|
|
|
|
track->codec_priv.size = 0; |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, |
|
|
|
|
|
|
|
"Failed to decode codec private data\n"); |
|
|
|
|
|
|
|
} else if (offset > 0) { |
|
|
|
|
|
|
|
track->codec_priv.data = av_malloc(track->codec_priv.size + offset); |
|
|
|
|
|
|
|
memcpy(track->codec_priv.data, |
|
|
|
|
|
|
|
encodings[0].compression.settings.data, offset); |
|
|
|
|
|
|
|
memcpy(track->codec_priv.data+offset, codec_priv, |
|
|
|
|
|
|
|
track->codec_priv.size); |
|
|
|
|
|
|
|
track->codec_priv.size += offset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (codec_priv != track->codec_priv.data) |
|
|
|
|
|
|
|
av_free(codec_priv); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for(j=0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++){ |
|
|
|
for(j=0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++){ |
|
|
|
if(!strncmp(ff_mkv_codec_tags[j].str, track->codec_id, |
|
|
|
if(!strncmp(ff_mkv_codec_tags[j].str, track->codec_id, |
|
|
|
strlen(ff_mkv_codec_tags[j].str))){ |
|
|
|
strlen(ff_mkv_codec_tags[j].str))){ |
|
|
@ -1825,6 +1783,41 @@ matroska_read_header (AVFormatContext *s, |
|
|
|
} |
|
|
|
} |
|
|
|
res = 0; |
|
|
|
res = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
attachements = attachements_list->elem; |
|
|
|
|
|
|
|
for (j=0; j<attachements_list->nb_elem; j++) { |
|
|
|
|
|
|
|
if (!(attachements[j].filename && attachements[j].mime && |
|
|
|
|
|
|
|
attachements[j].bin.data && attachements[j].bin.size > 0)) { |
|
|
|
|
|
|
|
av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n"); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
AVStream *st = av_new_stream(s, matroska->num_streams++); |
|
|
|
|
|
|
|
if (st == NULL) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
st->filename = av_strdup(attachements[j].filename); |
|
|
|
|
|
|
|
st->codec->codec_id = CODEC_ID_NONE; |
|
|
|
|
|
|
|
st->codec->codec_type = CODEC_TYPE_ATTACHMENT; |
|
|
|
|
|
|
|
st->codec->extradata = av_malloc(attachements[j].bin.size); |
|
|
|
|
|
|
|
if(st->codec->extradata == NULL) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
st->codec->extradata_size = attachements[j].bin.size; |
|
|
|
|
|
|
|
memcpy(st->codec->extradata, attachements[j].bin.data, attachements[j].bin.size); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) { |
|
|
|
|
|
|
|
if (!strncmp(ff_mkv_mime_tags[i].str, attachements[j].mime, |
|
|
|
|
|
|
|
strlen(ff_mkv_mime_tags[i].str))) { |
|
|
|
|
|
|
|
st->codec->codec_id = ff_mkv_mime_tags[i].id; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
chapters = chapters_list->elem; |
|
|
|
|
|
|
|
for (i=0; i<chapters_list->nb_elem; i++) |
|
|
|
|
|
|
|
if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid) |
|
|
|
|
|
|
|
ff_new_chapter(s, chapters[i].uid, (AVRational){1, 1000000000}, |
|
|
|
|
|
|
|
chapters[i].start, chapters[i].end, |
|
|
|
|
|
|
|
chapters[i].title); |
|
|
|
|
|
|
|
|
|
|
|
index_list = &matroska->index; |
|
|
|
index_list = &matroska->index; |
|
|
|
index = index_list->elem; |
|
|
|
index = index_list->elem; |
|
|
|
for (i=0; i<index_list->nb_elem; i++) { |
|
|
|
for (i=0; i<index_list->nb_elem; i++) { |
|
|
|