]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/matroska.c
mov fourccs for handling FCP files by (Baptiste COUDURIER )(baptiste.coudurier smartj...
[ffmpeg] / libavformat / matroska.c
index 9d80302f2cdd3a87f534e67b76e4dc2cdf5ef859..699c043996187284a985182204c9c5e97b076e9b 100644 (file)
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 /**
@@ -29,6 +29,7 @@
 #include "avformat.h"
 /* For codec_get_bmp_id and codec_get_wav_id. */
 #include "avi.h"
+#include "intfloat_readwrite.h"
 
 /* EBML version supported */
 #define EBML_VERSION 1
@@ -186,6 +187,7 @@ typedef enum {
 #define MATROSKA_CODEC_ID_VIDEO_MPEG4_SP     "V_MPEG4/ISO/SP"
 #define MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP    "V_MPEG4/ISO/ASP"
 #define MATROSKA_CODEC_ID_VIDEO_MPEG4_AP     "V_MPEG4/ISO/AP"
+#define MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC    "V_MPEG4/ISO/AVC"
 #define MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3    "V_MPEG4/MS/V3"
 #define MATROSKA_CODEC_ID_VIDEO_MPEG1        "V_MPEG1"
 #define MATROSKA_CODEC_ID_VIDEO_MPEG2        "V_MPEG2"
@@ -378,7 +380,7 @@ ebml_read_num (MatroskaDemuxContext *matroska,
         if (!url_feof(pb)) {
             offset_t pos = url_ftell(pb);
             av_log(matroska->ctx, AV_LOG_ERROR,
-                   "Read error at pos. %llu (0x%llx)\n",
+                   "Read error at pos. %"PRIu64" (0x%"PRIx64")\n",
                    pos, pos);
         }
         return AVERROR_IO; /* EOS or actual I/O error */
@@ -392,7 +394,7 @@ ebml_read_num (MatroskaDemuxContext *matroska,
     if (read > max_size) {
         offset_t pos = url_ftell(pb) - 1;
         av_log(matroska->ctx, AV_LOG_ERROR,
-               "Invalid EBML number size tag 0x%02x at pos %llu (0x%llx)\n",
+               "Invalid EBML number size tag 0x%02x at pos %"PRIu64" (0x%"PRIx64")\n",
                (uint8_t) total, pos, pos);
         return AVERROR_INVALIDDATA;
     }
@@ -536,7 +538,7 @@ ebml_read_uint (MatroskaDemuxContext *matroska,
     if (size < 1 || size > 8) {
         offset_t pos = url_ftell(pb);
         av_log(matroska->ctx, AV_LOG_ERROR,
-               "Invalid uint element size %d at position %lld (0x%llx)\n",
+               "Invalid uint element size %d at position %"PRId64" (0x%"PRIx64")\n",
                 size, pos, pos);
         return AVERROR_INVALIDDATA;
     }
@@ -570,7 +572,7 @@ ebml_read_sint (MatroskaDemuxContext *matroska,
     if (size < 1 || size > 8) {
         offset_t pos = url_ftell(pb);
         av_log(matroska->ctx, AV_LOG_ERROR,
-               "Invalid sint element size %d at position %lld (0x%llx)\n",
+               "Invalid sint element size %d at position %"PRId64" (0x%"PRIx64")\n",
                 size, pos, pos);
         return AVERROR_INVALIDDATA;
     }
@@ -596,8 +598,8 @@ ebml_read_sint (MatroskaDemuxContext *matroska,
 
 static int
 ebml_read_float (MatroskaDemuxContext *matroska,
-                uint32_t             *id,
-                double               *num)
+                 uint32_t             *id,
+                 double               *num)
 {
     ByteIOContext *pb = &matroska->ctx->pb;
     int size, res;
@@ -608,42 +610,21 @@ ebml_read_float (MatroskaDemuxContext *matroska,
         return res;
     size = rlength;
 
-    if (size != 4 && size != 8 && size != 10) {
+    if (size == 4) {
+        *num= av_int2flt(get_be32(pb));
+    } else if(size==8){
+        *num= av_int2dbl(get_be64(pb));
+    } else if(size==10){
+        av_log(matroska->ctx, AV_LOG_ERROR,
+               "FIXME! 10-byte floats unimplemented\n");
+        return AVERROR_UNKNOWN;
+    } else{
         offset_t pos = url_ftell(pb);
         av_log(matroska->ctx, AV_LOG_ERROR,
-               "Invalid float element size %d at position %llu (0x%llx)\n",
+               "Invalid float element size %d at position %"PRIu64" (0x%"PRIx64")\n",
                size, pos, pos);
         return AVERROR_INVALIDDATA;
     }
-    if (size == 10) {
-        av_log(matroska->ctx, AV_LOG_ERROR,
-               "FIXME! 10-byte floats unimplemented\n");
-        return AVERROR_UNKNOWN;
-    }
-
-    if (size == 4) {
-        float f;
-
-        while (size-- > 0)
-#ifdef WORDS_BIGENDIAN
-            ((uint8_t *) &f)[3 - size] = get_byte(pb);
-#else
-            ((uint8_t *) &f)[size] = get_byte(pb);
-#endif
-
-        *num = f;
-    } else {
-        double d;
-
-        while (size-- > 0)
-#ifdef WORDS_BIGENDIAN
-            ((uint8_t *) &d)[7 - size] = get_byte(pb);
-#else
-            ((uint8_t *) &d)[size] = get_byte(pb);
-#endif
-
-        *num = d;
-    }
 
     return 0;
 }
@@ -669,14 +650,14 @@ ebml_read_ascii (MatroskaDemuxContext *matroska,
 
     /* ebml strings are usually not 0-terminated, so we allocate one
      * byte more, read the string and NULL-terminate it ourselves. */
-    if (!(*str = av_malloc(size + 1))) {
+    if (size < 0 || !(*str = av_malloc(size + 1))) {
         av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation failed\n");
         return AVERROR_NOMEM;
     }
     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. %llu (0x%llx)\n", pos, pos);
+               "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
         return AVERROR_IO;
     }
     (*str)[size] = '\0';
@@ -773,7 +754,7 @@ ebml_read_binary (MatroskaDemuxContext *matroska,
     if (get_buffer(pb, *binary, *size) != *size) {
         offset_t pos = url_ftell(pb);
         av_log(matroska->ctx, AV_LOG_ERROR,
-               "Read error at pos. %llu (0x%llx)\n", pos, pos);
+               "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos);
         return AVERROR_IO;
     }
 
@@ -816,9 +797,6 @@ matroska_ebmlnum_uint (uint8_t  *data,
         n++;
     }
 
-    if (!total)
-        return AVERROR_INVALIDDATA;
-
     if (read == num_ffs)
         *num = (uint64_t)-1;
     else
@@ -897,7 +875,7 @@ ebml_read_header (MatroskaDemuxContext *matroska,
                     return res;
                 if (num > EBML_VERSION) {
                     av_log(matroska->ctx, AV_LOG_ERROR,
-                           "EBML version %llu (> %d) is not supported\n",
+                           "EBML version %"PRIu64" (> %d) is not supported\n",
                            num, EBML_VERSION);
                     return AVERROR_INVALIDDATA;
                 }
@@ -912,7 +890,7 @@ ebml_read_header (MatroskaDemuxContext *matroska,
                     return res;
                 if (num > sizeof(uint64_t)) {
                     av_log(matroska->ctx, AV_LOG_ERROR,
-                           "Integers of size %llu (> %d) not supported\n",
+                           "Integers of size %"PRIu64" (> %zd) not supported\n",
                            num, sizeof(uint64_t));
                     return AVERROR_INVALIDDATA;
                 }
@@ -927,8 +905,8 @@ ebml_read_header (MatroskaDemuxContext *matroska,
                     return res;
                 if (num > sizeof(uint32_t)) {
                     av_log(matroska->ctx, AV_LOG_ERROR,
-                           "IDs of size %llu (> %u) not supported\n",
-                           num, sizeof(uint32_t));
+                           "IDs of size %"PRIu64" (> %zu) not supported\n",
+                            num, sizeof(uint32_t));
                     return AVERROR_INVALIDDATA;
                 }
                 break;
@@ -1684,7 +1662,7 @@ matroska_parse_index (MatroskaDemuxContext *matroska)
                             break;
                         }
 
-                        /* position in the file + track to which it 
+                        /* position in the file + track to which it
                          * belongs */
                         case MATROSKA_ID_CUETRACKPOSITION:
                             if ((res = ebml_read_master(matroska, &id)) < 0)
@@ -1890,7 +1868,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
 
                 if (!seek_id || seek_pos == (uint64_t) -1) {
                     av_log(matroska->ctx, AV_LOG_INFO,
-                           "Incomplete seekhead entry (0x%x/%llu)\n",
+                           "Incomplete seekhead entry (0x%x/%"PRIu64")\n",
                            seek_id, seek_pos);
                     break;
                 }
@@ -1920,7 +1898,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
                                    "cannot parse further.\n", EBML_MAX_DEPTH);
                             return AVERROR_UNKNOWN;
                         }
-                            
+
                         level.start = 0;
                         level.length = (uint64_t)-1;
                         matroska->levels[matroska->num_levels] = level;
@@ -1933,7 +1911,7 @@ matroska_parse_seekhead (MatroskaDemuxContext *matroska)
                         if (id != seek_id) {
                             av_log(matroska->ctx, AV_LOG_INFO,
                                    "We looked for ID=0x%x but got "
-                                   "ID=0x%x (pos=%llu)",
+                                   "ID=0x%x (pos=%"PRIu64")",
                                    seek_id, id, seek_pos +
                                    matroska->segment_start);
                             goto finish;
@@ -2151,6 +2129,8 @@ matroska_read_header (AVFormatContext    *s,
         enum CodecID codec_id;
         MatroskaTrack *track;
         AVStream *st;
+        void *extradata = NULL;
+        int extradata_size = 0;
 
         for (i = 0; i < matroska->num_tracks; i++) {
             track = matroska->tracks[i];
@@ -2183,6 +2163,9 @@ matroska_read_header (AVFormatContext    *s,
                        !strcmp(track->codec_id,
                                MATROSKA_CODEC_ID_VIDEO_MPEG4_AP))
                 codec_id = CODEC_ID_MPEG4;
+            else if (!strcmp(track->codec_id,
+                             MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC))
+                codec_id = CODEC_ID_H264;
 /*             else if (!strcmp(track->codec_id, */
 /*                              MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) */
 /*                 codec_id = CODEC_ID_???; */
@@ -2197,7 +2180,7 @@ matroska_read_header (AVFormatContext    *s,
 
             /* This is the MS compatibility mode which stores a
              * WAVEFORMATEX in the CodecPrivate. */
-            else if (!strcmp(track->codec_id, 
+            else if (!strcmp(track->codec_id,
                              MATROSKA_CODEC_ID_AUDIO_ACM) &&
                 (track->codec_priv_size >= 18) &&
                 (track->codec_priv != NULL)) {
@@ -2236,12 +2219,19 @@ matroska_read_header (AVFormatContext    *s,
 /*                              MATROSKA_CODEC_ID_AUDIO_DTS)) */
 /*                 codec_id = CODEC_ID_DTS; */
             else if (!strcmp(track->codec_id,
-                             MATROSKA_CODEC_ID_AUDIO_VORBIS))
+                             MATROSKA_CODEC_ID_AUDIO_VORBIS)) {
+                extradata_size = track->codec_priv_size;
+                if(extradata_size) {
+                    extradata = av_malloc(extradata_size);
+                    if(extradata == NULL)
+                        return AVERROR_NOMEM;
+                    memcpy(extradata, track->codec_priv, extradata_size);
+                }
                 codec_id = CODEC_ID_VORBIS;
-            else if (!strcmp(track->codec_id,
-                             MATROSKA_CODEC_ID_AUDIO_MPEG2) ||
-                     !strcmp(track->codec_id,
-                             MATROSKA_CODEC_ID_AUDIO_MPEG4))
+            else if (!strcmp(track->codec_id,
+                               MATROSKA_CODEC_ID_AUDIO_MPEG2) ||
+                       !strcmp(track->codec_id,
+                               MATROSKA_CODEC_ID_AUDIO_MPEG4))
                 codec_id = CODEC_ID_AAC;
             else
                 codec_id = CODEC_ID_NONE;
@@ -2260,34 +2250,46 @@ matroska_read_header (AVFormatContext    *s,
                 return AVERROR_NOMEM;
             av_set_pts_info(st, 24, 1, 1000); /* 24 bit pts in ms */
 
-            st->codec.codec_id = codec_id;
+            st->codec->codec_id = codec_id;
+
+            if(extradata){
+                st->codec->extradata = extradata;
+                st->codec->extradata_size = extradata_size;
+            } 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;
+                st->codec->extradata_size = track->codec_priv_size;
+                memcpy(st->codec->extradata, track->codec_priv,
+                       track->codec_priv_size);
+            }
 
             if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
                 MatroskaVideoTrack *videotrack = (MatroskaVideoTrack *)track;
 
-                st->codec.codec_type = CODEC_TYPE_VIDEO;
-                st->codec.codec_tag = videotrack->fourcc;
-                st->codec.width = videotrack->pixel_width;
-                st->codec.height = videotrack->pixel_height;
+                st->codec->codec_type = CODEC_TYPE_VIDEO;
+                st->codec->codec_tag = videotrack->fourcc;
+                st->codec->width = videotrack->pixel_width;
+                st->codec->height = videotrack->pixel_height;
                 if (videotrack->display_width == 0)
-                    st->codec.sample_aspect_ratio.num =
+                    st->codec->sample_aspect_ratio.num =
                         videotrack->pixel_width;
                 else
-                    st->codec.sample_aspect_ratio.num =
+                    st->codec->sample_aspect_ratio.num =
                         videotrack->display_width;
                 if (videotrack->display_height == 0)
-                    st->codec.sample_aspect_ratio.num =
+                    st->codec->sample_aspect_ratio.num =
                         videotrack->pixel_height;
                 else
-                    st->codec.sample_aspect_ratio.num =
+                    st->codec->sample_aspect_ratio.num =
                         videotrack->display_height;
 
             } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
                 MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *)track;
 
-                st->codec.codec_type = CODEC_TYPE_AUDIO;
-                st->codec.sample_rate = audiotrack->samplerate;
-                st->codec.channels = audiotrack->channels;
+                st->codec->codec_type = CODEC_TYPE_AUDIO;
+                st->codec->sample_rate = audiotrack->samplerate;
+                st->codec->channels = audiotrack->channels;
             }
 
             /* What do we do with private data? E.g. for Vorbis. */
@@ -2341,6 +2343,7 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
                 uint32_t *lace_size = NULL;
                 int n, track, flags, laces = 0;
                 uint64_t num;
+                int64_t pos= url_ftell(&matroska->ctx->pb);
 
                 if ((res = ebml_read_binary(matroska, &id, &data, &size)) < 0)
                     break;
@@ -2364,6 +2367,10 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
                     av_free(origdata);
                     break;
                 }
+                if(matroska->ctx->streams[ matroska->tracks[track]->stream_index ]->discard >= AVDISCARD_ALL){
+                    av_free(origdata);
+                    break;
+                }
 
                 /* time (relative to cluster time) */
                 time = ((data[0] << 8) | data[1]) * matroska->time_scale;
@@ -2478,6 +2485,7 @@ matroska_parse_blockgroup (MatroskaDemuxContext *matroska,
                             matroska->tracks[track]->stream_index;
 
                         pkt->pts = timecode / 1000000; /* ns to ms */
+                        pkt->pos= pos;
 
                         matroska_queue_packet(matroska, pkt);
                     }
@@ -2533,7 +2541,7 @@ matroska_parse_cluster (MatroskaDemuxContext *matroska)
     uint64_t cluster_time = 0;
 
     av_log(matroska->ctx, AV_LOG_DEBUG,
-           "parsing cluster at %lld\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))) {
@@ -2668,6 +2676,10 @@ matroska_read_close (AVFormatContext *s)
         av_free(track);
     }
 
+    for (n = 0; n < s->nb_streams; n++) {
+        av_free(s->streams[n]->codec->extradata);
+    }
+
     memset(matroska, 0, sizeof(MatroskaDemuxContext));
 
     return 0;