]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mxf.c
update to libnut API, changes to frame_table_input
[ffmpeg] / libavformat / mxf.c
index d0fb2f0d94012f3d482c3dbb57cc8358a0522f29..7bf0b84c21eebb18f36320e8ad7fa52c6a4b9c90 100644 (file)
@@ -2,18 +2,20 @@
  * MXF demuxer.
  * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>.
  *
- * This library is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -218,6 +220,35 @@ static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv)
     return s->nb_streams == 1 ? 0 : -1;
 }
 
+/* XXX: use AVBitStreamFilter */
+static int mxf_get_d10_aes3_packet(ByteIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length)
+{
+    uint8_t buffer[61444];
+    uint8_t *buf_ptr, *end_ptr, *data_ptr;
+
+    if (length > 61444) /* worst case PAL 1920 samples 8 channels */
+        return -1;
+    get_buffer(pb, buffer, length);
+    av_new_packet(pkt, length);
+    data_ptr = pkt->data;
+    end_ptr = buffer + length;
+    buf_ptr = buffer + 4; /* skip SMPTE 331M header */
+    for (; buf_ptr < end_ptr; buf_ptr += 4) {
+        if (st->codec->bits_per_sample == 24) {
+            data_ptr[0] = (buf_ptr[2] >> 4) | ((buf_ptr[3] & 0x0f) << 4);
+            data_ptr[1] = (buf_ptr[1] >> 4) | ((buf_ptr[2] & 0x0f) << 4);
+            data_ptr[2] = (buf_ptr[0] >> 4) | ((buf_ptr[1] & 0x0f) << 4);
+            data_ptr += 3;
+        } else {
+            data_ptr[0] = (buf_ptr[2] >> 4) | ((buf_ptr[3] & 0x0f) << 4);
+            data_ptr[1] = (buf_ptr[1] >> 4) | ((buf_ptr[2] & 0x0f) << 4);
+            data_ptr += 2;
+        }
+    }
+    pkt->size = data_ptr - pkt->data;
+    return 0;
+}
+
 static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     KLVPacket klv;
@@ -231,9 +262,22 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
         PRINT_KEY("read packet", klv.key);
 #endif
         if (IS_KLV_KEY(klv.key, mxf_essence_element_key)) {
-            av_get_packet(&s->pb, pkt, klv.length);
-            pkt->stream_index = mxf_get_stream_index(s, &klv);
-            return pkt->stream_index == -1 ? -1 : 0;
+            int index = mxf_get_stream_index(s, &klv);
+            if (index < 0) {
+                av_log(s, AV_LOG_ERROR, "error getting stream index\n");
+                url_fskip(&s->pb, klv.length);
+                return -1;
+            }
+            /* check for 8 channels AES3 element */
+            if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) {
+                if (mxf_get_d10_aes3_packet(&s->pb, s->streams[index], pkt, klv.length) < 0) {
+                    av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n");
+                    return -1;
+                }
+            } else
+                av_get_packet(&s->pb, pkt, klv.length);
+            pkt->stream_index = index;
+            return 0;
         } else
             url_fskip(&s->pb, klv.length);
     }
@@ -327,8 +371,10 @@ static int mxf_read_metadata_source_clip(MXFContext *mxf, KLVPacket *klv)
 
         bytes_read += size + 4;
         dprintf("tag 0x%04X, size %d\n", tag, size);
-        if (!size) /* ignore empty tag, needed for some files with empty UMID tag */
+        if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */
+            av_log(mxf->fc, AV_LOG_ERROR, "local tag 0x%04X with 0 size\n", tag);
             continue;
+        }
         switch (tag) {
         case 0x3C0A:
             get_buffer(pb, source_clip->uid, 16);
@@ -631,6 +677,7 @@ static const MXFDataDefinitionUL mxf_data_definition_uls[] = {
 static const MXFCodecUL mxf_codec_uls[] = {
     /* PictureEssenceCoding */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML I-Frame */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL I-Frame */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@HL Long GoP */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* MP@ML Long GoP */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x02,0x03,0x00 }, CODEC_ID_MPEG2VIDEO, Frame }, /* 422P@ML Long GoP */
@@ -669,7 +716,8 @@ static const MXFCodecUL mxf_sound_essence_container_uls[] = {
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01 },        CODEC_ID_MP2, Frame }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x01 },        CODEC_ID_MP2, Frame }, /* MPEG-ES Frame wrapped, 0xc0 MPA stream id */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0xc0,0x02 },        CODEC_ID_MP2,  Clip }, /* MPEG-ES Clip wrapped, 0xc0 MPA stream id */
-  //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 },   CODEC_ID_PCM_AES3, Frame }, /* D-10 Mapping 30Mbps PAL Extended Template */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 },  CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 30Mbps PAL Extended Template */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 },  CODEC_ID_PCM_S16BE, Frame }, /* D-10 Mapping 50Mbps PAL Extended Template */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },       CODEC_ID_NONE, Frame },
 };
 
@@ -848,6 +896,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
             st->codec->width = descriptor->width;
             st->codec->height = descriptor->height;
             st->codec->bits_per_sample = descriptor->bits_per_sample; /* Uncompressed */
+            st->need_parsing = 2; /* only parse headers */
         } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
             container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, &descriptor->essence_container_ul);
             if (st->codec->codec_id == CODEC_ID_NONE)
@@ -866,6 +915,10 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                     st->codec->codec_id = CODEC_ID_PCM_S24BE;
                 else if (descriptor->bits_per_sample == 32)
                     st->codec->codec_id = CODEC_ID_PCM_S32BE;
+                if (descriptor->essence_container_ul[13] == 0x01) /* D-10 Mapping */
+                    st->codec->channels = 8; /* force channels to 8 */
+            } else if (st->codec->codec_id == CODEC_ID_MP2) {
+                st->need_parsing = 1;
             }
         }
         if (container_ul && container_ul->wrapping == Clip) {
@@ -895,11 +948,29 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL },
 };
 
+static int mxf_read_sync(ByteIOContext *pb, const uint8_t *key, unsigned size)
+{
+    int i, b;
+    for (i = 0; i < size && !url_feof(pb); i++) {
+        b = get_byte(pb);
+        if (b == key[0])
+            i = 0;
+        else if (b != key[i])
+            i = -1;
+    }
+    return i == size;
+}
+
 static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     MXFContext *mxf = s->priv_data;
     KLVPacket klv;
 
+    if (!mxf_read_sync(&s->pb, mxf_header_partition_pack_key, 14)) {
+        av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n");
+        return -1;
+    }
+    url_fseek(&s->pb, -14, SEEK_CUR);
     mxf->fc = s;
     while (!url_feof(&s->pb)) {
         const MXFMetadataReadTableEntry *function;
@@ -982,29 +1053,21 @@ static int mxf_probe(AVProbeData *p) {
 static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
 {
     AVStream *st = s->streams[stream_index];
-    offset_t pos = url_ftell(&s->pb);
     int64_t seconds;
-    int i;
 
-    if (!s->bit_rate || sample_time < 0)
+    if (!s->bit_rate)
         return -1;
+    if (sample_time < 0)
+        sample_time = 0;
     seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den);
     url_fseek(&s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET);
-    /* sync on KLV essence element */
-    for (i = 0; i < 12 && url_ftell(&s->pb) < s->file_size; i++) {
-        int b = get_byte(&s->pb);
-        if (b == mxf_essence_element_key[0])
-            i = 0;
-        else if (b != mxf_essence_element_key[i])
-            i = -1;
-    }
-    if (i == 12) { /* found KLV key */
-        url_fseek(&s->pb, -12, SEEK_CUR);
-        av_update_cur_dts(s, st, sample_time);
-        return 0;
-    }
-    url_fseek(&s->pb, pos, SEEK_SET);
-    return -1;
+    if (!mxf_read_sync(&s->pb, mxf_essence_element_key, 12))
+        return -1;
+
+    /* found KLV key */
+    url_fseek(&s->pb, -12, SEEK_CUR);
+    av_update_cur_dts(s, st, sample_time);
+    return 0;
 }
 
 AVInputFormat mxf_demuxer = {