typedef struct MatroskaSubtitleTrack {
MatroskaTrack track;
-
- int ass;
//..
} MatroskaSubtitleTrack;
matroska->num_packets++;
}
+/*
+ * Free all packets in our internal queue.
+ */
+static void
+matroska_clear_queue (MatroskaDemuxContext *matroska)
+{
+ if (matroska->packets) {
+ int n;
+ for (n = 0; n < matroska->num_packets; n++) {
+ av_free_packet(matroska->packets[n]);
+ av_free(matroska->packets[n]);
+ }
+ av_free(matroska->packets);
+ matroska->packets = NULL;
+ matroska->num_packets = 0;
+ }
+}
+
/*
* Autodetecting...
/* colorspace (only matters for raw video)
* fourcc */
- case MATROSKA_ID_VIDEOCOLOURSPACE: {
+ case MATROSKA_ID_VIDEOCOLORSPACE: {
uint64_t num;
if ((res = ebml_read_uint(matroska, &id,
&num)) < 0)
return res;
}
+static int
+matroska_parse_attachments(AVFormatContext *s)
+{
+ MatroskaDemuxContext *matroska = s->priv_data;
+ int res = 0;
+ uint32_t id;
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "parsing attachments...\n");
+
+ while (res == 0) {
+ if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
+ res = AVERROR(EIO);
+ break;
+ } else if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_ATTACHEDFILE: {
+ char* name = NULL;
+ char* mime = NULL;
+ uint8_t* data = NULL;
+ int i, data_size = 0;
+ AVStream *st;
+
+ 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) {
+ matroska->level_up--;
+ break;
+ }
+
+ switch (id) {
+ case MATROSKA_ID_FILENAME:
+ res = ebml_read_utf8 (matroska, &id, &name);
+ break;
+
+ case MATROSKA_ID_FILEMIMETYPE:
+ res = ebml_read_ascii (matroska, &id, &mime);
+ break;
+
+ case MATROSKA_ID_FILEDATA:
+ res = ebml_read_binary(matroska, &id, &data, &data_size);
+ break;
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown attachedfile ID 0x%x\n", id);
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ if (!(name && mime && data && data_size > 0)) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
+ break;
+ }
+
+ st = av_new_stream(s, matroska->num_streams++);
+ if (st == NULL)
+ return AVERROR(ENOMEM);
+ st->filename = av_strdup(name);
+ st->codec->codec_id = CODEC_ID_NONE;
+ st->codec->codec_type = CODEC_TYPE_ATTACHMENT;
+ st->codec->extradata = av_malloc(data_size);
+ if(st->codec->extradata == NULL)
+ return AVERROR(ENOMEM);
+ st->codec->extradata_size = data_size;
+ memcpy(st->codec->extradata, data, data_size);
+
+ for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) {
+ if (!strncmp(ff_mkv_mime_tags[i].str, mime,
+ strlen(ff_mkv_mime_tags[i].str))) {
+ st->codec->codec_id = ff_mkv_mime_tags[i].id;
+ break;
+ }
+ }
+
+ av_log(matroska->ctx, AV_LOG_DEBUG, "new attachment: %s, %s, size %d \n", name, mime, data_size);
+ break;
+ }
+
+ default:
+ av_log(matroska->ctx, AV_LOG_INFO,
+ "Unknown attachments ID 0x%x\n", id);
+ /* fall-through */
+
+ case EBML_ID_VOID:
+ res = ebml_read_skip(matroska);
+ break;
+ }
+
+ if (matroska->level_up) {
+ matroska->level_up--;
+ break;
+ }
+ }
+
+ return res;
+}
+
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
static int
break;
}
+ case MATROSKA_ID_ATTACHMENTS: {
+ if ((res = ebml_read_master(matroska, &id)) < 0)
+ break;
+ res = matroska_parse_attachments(s);
+ break;
+ }
+
case MATROSKA_ID_CLUSTER: {
/* Do not read the master - this will be done in the next
* call to matroska_read_packet. */
if (track->codec_id == NULL)
continue;
- for(j=0; ff_mkv_codec_tags[j].str; 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,
strlen(ff_mkv_codec_tags[j].str))){
codec_id= ff_mkv_codec_tags[j].id;
return AVERROR(ENOMEM);
init_put_byte(&b, extradata, extradata_size, 1,
NULL, NULL, NULL, NULL);
- put_buffer(&b, (uint8_t *) "TTA1", 4);
+ put_buffer(&b, "TTA1", 4);
put_le16(&b, 1);
put_le16(&b, audiotrack->channels);
put_le16(&b, audiotrack->bitdepth);
}
}
- else if (codec_id == CODEC_ID_TEXT) {
- MatroskaSubtitleTrack *subtrack=(MatroskaSubtitleTrack *)track;
- if (!strcmp(track->codec_id, "S_TEXT/ASS") ||
- !strcmp(track->codec_id, "S_TEXT/SSA") ||
- !strcmp(track->codec_id, "S_ASS") ||
- !strcmp(track->codec_id, "S_SSA"))
- subtrack->ass = 1;
- }
-
if (codec_id == CODEC_ID_NONE) {
av_log(matroska->ctx, AV_LOG_INFO,
"Unknown/unsupported CodecID %s.\n",
av_free(origdata);
return res;
}
- if (matroska->tracks[track]->stream_index < 0)
+ if (matroska->tracks[track]->stream_index < 0) {
+ av_free(origdata);
return res;
+ }
st = matroska->ctx->streams[matroska->tracks[track]->stream_index];
if (st->discard >= AVDISCARD_ALL) {
av_free(origdata);
is_keyframe = flags & 0x80 ? PKT_FLAG_KEY : 0;
if (matroska->skip_to_keyframe) {
- if (!is_keyframe || st != matroska->skip_to_stream)
+ if (!is_keyframe || st != matroska->skip_to_stream) {
+ av_free(origdata);
return res;
+ }
matroska->skip_to_keyframe = 0;
}
} else {
int offset = 0;
- if (st->codec->codec_id == CODEC_ID_TEXT
- && ((MatroskaSubtitleTrack *)(matroska->tracks[track]))->ass) {
- int i;
- for (i=0; i<8 && data[offset]; offset++)
- if (data[offset] == ',')
- i++;
- }
-
pkt = av_mallocz(sizeof(AVPacket));
/* XXX: prevent data copy... */
if (av_new_packet(pkt, lace_size[n]-offset) < 0) {
if (index < 0)
return 0;
+ matroska_clear_queue(matroska);
+
/* do the seek */
url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET);
matroska->skip_to_keyframe = !(flags & AVSEEK_FLAG_ANY);
matroska->skip_to_stream = st;
- matroska->num_packets = 0;
matroska->peek_id = 0;
return 0;
}
av_free(matroska->muxing_app);
av_free(matroska->index);
- if (matroska->packets != NULL) {
- for (n = 0; n < matroska->num_packets; n++) {
- av_free_packet(matroska->packets[n]);
- av_free(matroska->packets[n]);
- }
- av_free(matroska->packets);
- }
+ matroska_clear_queue(matroska);
for (n = 0; n < matroska->num_tracks; n++) {
MatroskaTrack *track = matroska->tracks[n];