]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/matroskadec.c
Rework link property configuration system.
[ffmpeg] / libavformat / matroskadec.c
index b1785294b64c3be96a0fe9a3c6515decdac9ce9a..d9fdcec283f64ecf8e6828eda0a88f5721364264 100644 (file)
@@ -94,7 +94,6 @@ typedef struct MatroskaAudioTrack {
 
 typedef struct MatroskaSubtitleTrack {
     MatroskaTrack track;
-
     //..
 } MatroskaSubtitleTrack;
 
@@ -175,7 +174,7 @@ typedef struct MatroskaDemuxContext {
 static int
 ebml_read_element_level_up (MatroskaDemuxContext *matroska)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     offset_t pos = url_ftell(pb);
     int num = 0;
 
@@ -207,7 +206,7 @@ ebml_read_num (MatroskaDemuxContext *matroska,
                int                   max_size,
                uint64_t             *number)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     int len_mask = 0x80, read = 1, n = 1;
     int64_t total = 0;
 
@@ -222,7 +221,7 @@ ebml_read_num (MatroskaDemuxContext *matroska,
                    "Read error at pos. %"PRIu64" (0x%"PRIx64")\n",
                    pos, pos);
         }
-        return AVERROR_IO; /* EOS or actual I/O error */
+        return AVERROR(EIO); /* EOS or actual I/O error */
     }
 
     /* get the length of the EBML number */
@@ -309,8 +308,6 @@ ebml_peek_id (MatroskaDemuxContext *matroska,
 {
     uint32_t id;
 
-    assert(level_up != NULL);
-
     if (ebml_read_element_id(matroska, &id, level_up) < 0)
         return 0;
 
@@ -326,7 +323,7 @@ static int
 ebml_read_seek (MatroskaDemuxContext *matroska,
                 offset_t              offset)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
 
     /* clear ID cache, if any */
     matroska->peek_id = 0;
@@ -342,7 +339,7 @@ ebml_read_seek (MatroskaDemuxContext *matroska,
 static int
 ebml_read_skip (MatroskaDemuxContext *matroska)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     uint32_t id;
     uint64_t length;
     int res;
@@ -366,7 +363,7 @@ ebml_read_uint (MatroskaDemuxContext *matroska,
                 uint32_t             *id,
                 uint64_t             *num)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     int n = 0, size, res;
     uint64_t rlength;
 
@@ -400,7 +397,7 @@ ebml_read_sint (MatroskaDemuxContext *matroska,
                 uint32_t             *id,
                 int64_t              *num)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     int size, n = 1, negative = 0, res;
     uint64_t rlength;
 
@@ -439,7 +436,7 @@ ebml_read_float (MatroskaDemuxContext *matroska,
                  uint32_t             *id,
                  double               *num)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     int size, res;
     uint64_t rlength;
 
@@ -473,7 +470,7 @@ ebml_read_ascii (MatroskaDemuxContext *matroska,
                  uint32_t             *id,
                  char                **str)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     int size, res;
     uint64_t rlength;
 
@@ -486,13 +483,13 @@ ebml_read_ascii (MatroskaDemuxContext *matroska,
      * byte more, read the string and NULL-terminate it ourselves. */
     if (size < 0 || !(*str = av_malloc(size + 1))) {
         av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation failed\n");
-        return AVERROR_NOMEM;
+        return AVERROR(ENOMEM);
     }
     if (get_buffer(pb, (uint8_t *) *str, size) != size) {
         offset_t pos = url_ftell(pb);
         av_log(matroska->ctx, AV_LOG_ERROR,
                "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
-        return AVERROR_IO;
+        return AVERROR(EIO);
     }
     (*str)[size] = '\0';
 
@@ -535,7 +532,7 @@ static int
 ebml_read_master (MatroskaDemuxContext *matroska,
                   uint32_t             *id)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     uint64_t length;
     MatroskaLevel *level;
     int res;
@@ -548,7 +545,7 @@ ebml_read_master (MatroskaDemuxContext *matroska,
     if (matroska->num_levels >= EBML_MAX_DEPTH) {
         av_log(matroska->ctx, AV_LOG_ERROR,
                "File moves beyond max. allowed depth (%d)\n", EBML_MAX_DEPTH);
-        return AVERROR_NOTSUPP;
+        return AVERROR(ENOSYS);
     }
 
     /* remember level */
@@ -570,7 +567,7 @@ ebml_read_binary (MatroskaDemuxContext *matroska,
                   uint8_t             **binary,
                   int                  *size)
 {
-    ByteIOContext *pb = &matroska->ctx->pb;
+    ByteIOContext *pb = matroska->ctx->pb;
     uint64_t rlength;
     int res;
 
@@ -582,14 +579,14 @@ ebml_read_binary (MatroskaDemuxContext *matroska,
     if (!(*binary = av_malloc(*size))) {
         av_log(matroska->ctx, AV_LOG_ERROR,
                "Memory allocation error\n");
-        return AVERROR_NOMEM;
+        return AVERROR(ENOMEM);
     }
 
     if (get_buffer(pb, *binary, *size) != *size) {
         offset_t pos = url_ftell(pb);
         av_log(matroska->ctx, AV_LOG_ERROR,
                "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
-        return AVERROR_IO;
+        return AVERROR(EIO);
     }
 
     return 0;
@@ -694,7 +691,7 @@ ebml_read_header (MatroskaDemuxContext *matroska,
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &level_up)))
-            return AVERROR_IO;
+            return AVERROR(EIO);
 
         /* end-of-header */
         if (level_up)
@@ -847,6 +844,24 @@ matroska_queue_packet (MatroskaDemuxContext *matroska,
     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...
@@ -904,7 +919,7 @@ matroska_parse_info (MatroskaDemuxContext *matroska)
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -1003,7 +1018,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
     /* try reading the trackentry headers */
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up > 0) {
             matroska->level_up--;
@@ -1076,7 +1091,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
 
                 while (res == 0) {
                     if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-                        res = AVERROR_IO;
+                        res = AVERROR(EIO);
                         break;
                     } else if (matroska->level_up > 0) {
                         matroska->level_up--;
@@ -1090,7 +1105,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
                             if ((res = ebml_read_uint (matroska, &id,
                                                        &num)) < 0)
                                 break;
-                            track->default_duration = num/matroska->time_scale;
+                            track->default_duration = num;
                             break;
                         }
 
@@ -1100,7 +1115,8 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
                             if ((res = ebml_read_float(matroska, &id,
                                                        &num)) < 0)
                                 break;
-                            track->default_duration = 1000000000/(matroska->time_scale*num);
+                            if (!track->default_duration)
+                                track->default_duration = 1000000000/num;
                             break;
                         }
 
@@ -1199,9 +1215,9 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
                             break;
                         }
 
-                        /* colourspace (only matters for raw video)
+                        /* 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)
@@ -1247,7 +1263,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
 
                 while (res == 0) {
                     if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-                        res = AVERROR_IO;
+                        res = AVERROR(EIO);
                         break;
                     } else if (matroska->level_up > 0) {
                         matroska->level_up--;
@@ -1407,7 +1423,7 @@ matroska_add_stream (MatroskaDemuxContext *matroska)
                 uint64_t num;
                 if ((res = ebml_read_uint(matroska, &id, &num)) < 0)
                     break;
-                track->default_duration = num / matroska->time_scale;
+                track->default_duration = num;
                 break;
             }
 
@@ -1445,7 +1461,7 @@ matroska_parse_tracks (MatroskaDemuxContext *matroska)
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -1488,7 +1504,7 @@ matroska_parse_index (MatroskaDemuxContext *matroska)
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -1509,7 +1525,7 @@ matroska_parse_index (MatroskaDemuxContext *matroska)
 
                 while (res == 0) {
                     if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-                        res = AVERROR_IO;
+                        res = AVERROR(EIO);
                         break;
                     } else if (matroska->level_up) {
                         matroska->level_up--;
@@ -1536,7 +1552,7 @@ matroska_parse_index (MatroskaDemuxContext *matroska)
                             while (res == 0) {
                                 if (!(id = ebml_peek_id (matroska,
                                                     &matroska->level_up))) {
-                                    res = AVERROR_IO;
+                                    res = AVERROR(EIO);
                                     break;
                                 } else if (matroska->level_up) {
                                     matroska->level_up--;
@@ -1643,7 +1659,7 @@ matroska_parse_metadata (MatroskaDemuxContext *matroska)
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -1681,7 +1697,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -1698,7 +1714,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
 
                 while (res == 0) {
                     if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-                        res = AVERROR_IO;
+                        res = AVERROR(EIO);
                         break;
                     } else if (matroska->level_up) {
                         matroska->level_up--;
@@ -1748,7 +1764,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
 
                         /* remember the peeked ID and the current position */
                         peek_id_cache = matroska->peek_id;
-                        before_pos = url_ftell(&matroska->ctx->pb);
+                        before_pos = url_ftell(matroska->ctx->pb);
 
                         /* seek */
                         if ((res = ebml_read_seek(matroska, seek_pos +
@@ -1788,14 +1804,14 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
                         switch (id) {
                             case MATROSKA_ID_CUES:
                                 if (!(res = matroska_parse_index(matroska)) ||
-                                    url_feof(&matroska->ctx->pb)) {
+                                    url_feof(matroska->ctx->pb)) {
                                     matroska->index_parsed = 1;
                                     res = 0;
                                 }
                                 break;
                             case MATROSKA_ID_TAGS:
                                 if (!(res = matroska_parse_metadata(matroska)) ||
-                                   url_feof(&matroska->ctx->pb)) {
+                                   url_feof(matroska->ctx->pb)) {
                                     matroska->metadata_parsed = 1;
                                     res = 0;
                                 }
@@ -1849,6 +1865,119 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
     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
@@ -1914,7 +2043,7 @@ matroska_read_header (AVFormatContext    *s,
     /* The next thing is a segment. */
     while (1) {
         if (!(id = ebml_peek_id(matroska, &last_level)))
-            return AVERROR_IO;
+            return AVERROR(EIO);
         if (id == MATROSKA_ID_SEGMENT)
             break;
 
@@ -1931,13 +2060,13 @@ matroska_read_header (AVFormatContext    *s,
      * after the segment ID/length. */
     if ((res = ebml_read_master(matroska, &id)) < 0)
         return res;
-    matroska->segment_start = url_ftell(&s->pb);
+    matroska->segment_start = url_ftell(s->pb);
 
     matroska->time_scale = 1000000;
     /* we've found our segment, start reading the different contents in here */
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -1991,6 +2120,13 @@ matroska_read_header (AVFormatContext    *s,
                 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. */
@@ -2028,13 +2164,11 @@ matroska_read_header (AVFormatContext    *s,
             track = matroska->tracks[i];
             track->stream_index = -1;
 
-            /* libavformat does not really support subtitles.
-             * Also apply some sanity checks. */
-            if ((track->type == MATROSKA_TRACK_TYPE_SUBTITLE) ||
-                (track->codec_id == NULL))
+            /* Apply some sanity checks. */
+            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;
@@ -2077,7 +2211,7 @@ matroska_read_header (AVFormatContext    *s,
                 int sri = matroska_aac_sri(audiotrack->internal_samplerate);
                 extradata = av_malloc(5);
                 if (extradata == NULL)
-                    return AVERROR_NOMEM;
+                    return AVERROR(ENOMEM);
                 extradata[0] = (profile << 3) | ((sri&0x0E) >> 1);
                 extradata[1] = ((sri&0x01) << 7) | (audiotrack->channels<<3);
                 if (strstr(track->codec_id, "SBR")) {
@@ -2089,7 +2223,6 @@ matroska_read_header (AVFormatContext    *s,
                 } else {
                     extradata_size = 2;
                 }
-                track->default_duration = 1024*1000 / audiotrack->internal_samplerate;
             }
 
             else if (codec_id == CODEC_ID_TTA) {
@@ -2098,10 +2231,10 @@ matroska_read_header (AVFormatContext    *s,
                 extradata_size = 30;
                 extradata = av_mallocz(extradata_size);
                 if (extradata == NULL)
-                    return AVERROR_NOMEM;
+                    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);
@@ -2113,7 +2246,6 @@ matroska_read_header (AVFormatContext    *s,
                      codec_id == CODEC_ID_RV30 || codec_id == CODEC_ID_RV40) {
                 extradata_offset = 26;
                 track->codec_priv_size -= extradata_offset;
-                track->flags |= MATROSKA_TRACK_REAL_V;
             }
 
             else if (codec_id == CODEC_ID_RA_144) {
@@ -2158,7 +2290,7 @@ matroska_read_header (AVFormatContext    *s,
             matroska->num_streams++;
             st = av_new_stream(s, track->stream_index);
             if (st == NULL)
-                return AVERROR_NOMEM;
+                return AVERROR(ENOMEM);
             av_set_pts_info(st, 64, matroska->time_scale, 1000*1000*1000); /* 64 bit pts in ns */
 
             st->codec->codec_id = codec_id;
@@ -2168,7 +2300,7 @@ matroska_read_header (AVFormatContext    *s,
 
             if (track->default_duration)
                 av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
-                          track->default_duration, 1000, 30000);
+                          track->default_duration, 1000000000, 30000);
 
             if(extradata){
                 st->codec->extradata = extradata;
@@ -2176,7 +2308,7 @@ matroska_read_header (AVFormatContext    *s,
             } else if(track->codec_priv && track->codec_priv_size > 0){
                 st->codec->extradata = av_malloc(track->codec_priv_size);
                 if(st->codec->extradata == NULL)
-                    return AVERROR_NOMEM;
+                    return AVERROR(ENOMEM);
                 st->codec->extradata_size = track->codec_priv_size;
                 memcpy(st->codec->extradata,track->codec_priv+extradata_offset,
                        track->codec_priv_size);
@@ -2231,12 +2363,6 @@ matroska_read_header (AVFormatContext    *s,
     return res;
 }
 
-static inline int
-rv_offset(uint8_t *data, int slice, int slices)
-{
-    return AV_RL32(data+8*slice+4) + 8*slices;
-}
-
 static int
 matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
                      int64_t pos, uint64_t cluster_time, uint64_t duration,
@@ -2269,15 +2395,17 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
         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);
         return res;
     }
     if (duration == AV_NOPTS_VALUE)
-        duration = matroska->tracks[track]->default_duration;
+        duration = matroska->tracks[track]->default_duration / matroska->time_scale;
 
     /* block_time (relative to cluster time) */
     block_time = AV_RB16(data);
@@ -2285,11 +2413,13 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
     flags = *data++;
     size -= 3;
     if (is_keyframe == -1)
-        is_keyframe = flags & 1 ? PKT_FLAG_KEY : 0;
+        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;
     }
 
@@ -2373,88 +2503,73 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
     }
 
     if (res == 0) {
-        int real_v = matroska->tracks[track]->flags & MATROSKA_TRACK_REAL_V;
         uint64_t timecode = AV_NOPTS_VALUE;
 
-        if (cluster_time != (uint64_t)-1 && cluster_time + block_time >= 0)
+        if (cluster_time != (uint64_t)-1
+            && (block_time >= 0 || cluster_time >= -block_time))
             timecode = cluster_time + block_time;
 
         for (n = 0; n < laces; n++) {
-            int slice, slices = 1;
-
-            if (real_v) {
-                slices = *data++ + 1;
-                lace_size[n]--;
-            }
-
-            for (slice=0; slice<slices; slice++) {
-                int slice_size, slice_offset = 0;
-                if (real_v)
-                    slice_offset = rv_offset(data, slice, slices);
-                if (slice+1 == slices)
-                    slice_size = lace_size[n] - slice_offset;
-                else
-                    slice_size = rv_offset(data, slice+1, slices) - slice_offset;
-
-                if (st->codec->codec_id == CODEC_ID_RA_288 ||
-                    st->codec->codec_id == CODEC_ID_COOK ||
-                    st->codec->codec_id == CODEC_ID_ATRAC3) {
-                    MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)matroska->tracks[track];
-                    int a = st->codec->block_align;
-                    int sps = audiotrack->sub_packet_size;
-                    int cfs = audiotrack->coded_framesize;
-                    int h = audiotrack->sub_packet_h;
-                    int y = audiotrack->sub_packet_cnt;
-                    int w = audiotrack->frame_size;
-                    int x;
-
-                    if (!audiotrack->pkt_cnt) {
-                        if (st->codec->codec_id == CODEC_ID_RA_288)
-                            for (x=0; x<h/2; x++)
-                                memcpy(audiotrack->buf+x*2*w+y*cfs,
-                                       data+x*cfs, cfs);
-                        else
-                            for (x=0; x<w/sps; x++)
-                                memcpy(audiotrack->buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
-
-                        if (++audiotrack->sub_packet_cnt >= h) {
-                            audiotrack->sub_packet_cnt = 0;
-                            audiotrack->pkt_cnt = h*w / a;
-                        }
-                    }
-                    while (audiotrack->pkt_cnt) {
-                        pkt = av_mallocz(sizeof(AVPacket));
-                        av_new_packet(pkt, a);
-                        memcpy(pkt->data, audiotrack->buf
-                               + a * (h*w / a - audiotrack->pkt_cnt--), a);
-                        pkt->pos = pos;
-                        pkt->stream_index = matroska->tracks[track]->stream_index;
-                        matroska_queue_packet(matroska, pkt);
+            if (st->codec->codec_id == CODEC_ID_RA_288 ||
+                st->codec->codec_id == CODEC_ID_COOK ||
+                st->codec->codec_id == CODEC_ID_ATRAC3) {
+                MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)matroska->tracks[track];
+                int a = st->codec->block_align;
+                int sps = audiotrack->sub_packet_size;
+                int cfs = audiotrack->coded_framesize;
+                int h = audiotrack->sub_packet_h;
+                int y = audiotrack->sub_packet_cnt;
+                int w = audiotrack->frame_size;
+                int x;
+
+                if (!audiotrack->pkt_cnt) {
+                    if (st->codec->codec_id == CODEC_ID_RA_288)
+                        for (x=0; x<h/2; x++)
+                            memcpy(audiotrack->buf+x*2*w+y*cfs,
+                                   data+x*cfs, cfs);
+                    else
+                        for (x=0; x<w/sps; x++)
+                            memcpy(audiotrack->buf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), data+x*sps, sps);
+
+                    if (++audiotrack->sub_packet_cnt >= h) {
+                        audiotrack->sub_packet_cnt = 0;
+                        audiotrack->pkt_cnt = h*w / a;
                     }
-                } else {
+                }
+                while (audiotrack->pkt_cnt) {
                     pkt = av_mallocz(sizeof(AVPacket));
-                    /* XXX: prevent data copy... */
-                    if (av_new_packet(pkt, slice_size) < 0) {
-                        res = AVERROR_NOMEM;
-                        n = laces-1;
-                        break;
-                    }
-                    memcpy (pkt->data, data+slice_offset, slice_size);
-
-                    if (n == 0)
-                        pkt->flags = is_keyframe;
-                    pkt->stream_index = matroska->tracks[track]->stream_index;
-
-                    pkt->pts = timecode;
+                    av_new_packet(pkt, a);
+                    memcpy(pkt->data, audiotrack->buf
+                           + a * (h*w / a - audiotrack->pkt_cnt--), a);
                     pkt->pos = pos;
-                    pkt->duration = duration;
-
+                    pkt->stream_index = matroska->tracks[track]->stream_index;
                     matroska_queue_packet(matroska, pkt);
                 }
+            } else {
+                int offset = 0;
+
+                pkt = av_mallocz(sizeof(AVPacket));
+                /* XXX: prevent data copy... */
+                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 (timecode != AV_NOPTS_VALUE)
-                    timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
+                if (n == 0)
+                    pkt->flags = is_keyframe;
+                pkt->stream_index = matroska->tracks[track]->stream_index;
+
+                pkt->pts = timecode;
+                pkt->pos = pos;
+                pkt->duration = duration;
+
+                matroska_queue_packet(matroska, pkt);
             }
+
+            if (timecode != AV_NOPTS_VALUE)
+                timecode = duration ? timecode + duration : AV_NOPTS_VALUE;
             data += lace_size[n];
         }
     }
@@ -2481,7 +2596,7 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -2493,7 +2608,7 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
              * of the harder things, so this code is a bit complicated.
              * See http://www.matroska.org/ for documentation. */
             case MATROSKA_ID_BLOCK: {
-                pos = url_ftell(&matroska->ctx->pb);
+                pos = url_ftell(matroska->ctx->pb);
                 res = ebml_read_binary(matroska, &id, &data, &size);
                 break;
             }
@@ -2501,7 +2616,6 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
             case MATROSKA_ID_BLOCKDURATION: {
                 if ((res = ebml_read_uint(matroska, &id, &duration)) < 0)
                     break;
-                duration /= matroska->time_scale;
                 break;
             }
 
@@ -2556,11 +2670,11 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska)
     int size;
 
     av_log(matroska->ctx, AV_LOG_DEBUG,
-           "parsing cluster at %"PRId64"\n", url_ftell(&matroska->ctx->pb));
+           "parsing cluster at %"PRId64"\n", url_ftell(matroska->ctx->pb));
 
     while (res == 0) {
         if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-            res = AVERROR_IO;
+            res = AVERROR(EIO);
             break;
         } else if (matroska->level_up) {
             matroska->level_up--;
@@ -2585,7 +2699,7 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska)
                 break;
 
             case MATROSKA_ID_SIMPLEBLOCK:
-                pos = url_ftell(&matroska->ctx->pb);
+                pos = url_ftell(matroska->ctx->pb);
                 res = ebml_read_binary(matroska, &id, &data, &size);
                 if (res == 0)
                     res = matroska_parse_block(matroska, data, size, pos,
@@ -2625,12 +2739,12 @@ matroska_read_packet (AVFormatContext *s,
 
         /* Have we already reached the end? */
         if (matroska->done)
-            return AVERROR_IO;
+            return AVERROR(EIO);
 
         res = 0;
         while (res == 0) {
             if (!(id = ebml_peek_id(matroska, &matroska->level_up))) {
-                return AVERROR_IO;
+                return AVERROR(EIO);
             } else if (matroska->level_up) {
                 matroska->level_up--;
                 break;
@@ -2676,11 +2790,12 @@ matroska_read_seek (AVFormatContext *s, int stream_index, int64_t timestamp,
     if (index < 0)
         return 0;
 
+    matroska_clear_queue(matroska);
+
     /* do the seek */
-    url_fseek(&s->pb, st->index_entries[index].pos, SEEK_SET);
+    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;
 }
@@ -2695,13 +2810,7 @@ matroska_read_close (AVFormatContext *s)
     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];