matroska: implement support for ProRes
authorLuca Barbato <lu_zero@gentoo.org>
Fri, 14 Sep 2012 22:59:05 +0000 (00:59 +0200)
committerLuca Barbato <lu_zero@gentoo.org>
Wed, 19 Sep 2012 18:34:14 +0000 (20:34 +0200)
Support Matroska native formatting.

On demuxing prepend a Frame container atom (32bit big endian encoded
frame size and 'icpf' string).
On muxing remove it.

libavformat/matroska.c
libavformat/matroskadec.c
libavformat/matroskaenc.c

index 652e4d0..edb7ab7 100644 (file)
@@ -71,6 +71,7 @@ const CodecTags ff_mkv_codec_tags[]={
     {"V_MPEG4/ISO/SP"   , AV_CODEC_ID_MPEG4},
     {"V_MPEG4/ISO/AVC"  , AV_CODEC_ID_H264},
     {"V_MPEG4/MS/V3"    , AV_CODEC_ID_MSMPEG4V3},
+    {"V_PRORES"         , AV_CODEC_ID_PRORES},
     {"V_REAL/RV10"      , AV_CODEC_ID_RV10},
     {"V_REAL/RV20"      , AV_CODEC_ID_RV20},
     {"V_REAL/RV30"      , AV_CODEC_ID_RV30},
index 69a8c7f..c00ebaa 100644 (file)
@@ -37,6 +37,7 @@
 #include "isom.h"
 #include "rm.h"
 #include "matroska.h"
+#include "libavcodec/bytestream.h"
 #include "libavcodec/mpeg4audio.h"
 #include "libavutil/intfloat.h"
 #include "libavutil/intreadwrite.h"
@@ -1966,6 +1967,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
                 MatroskaTrackEncoding *encodings = track->encodings.elem;
                 uint32_t pkt_size = lace_size[n];
                 uint8_t *pkt_data = data;
+                int offset = 0;
 
                 if (encodings && encodings->scope & 1) {
                     res = matroska_decode_buffer(&pkt_data, &pkt_size, track);
@@ -1973,15 +1975,24 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
                         break;
                 }
 
+                if (st->codec->codec_id == AV_CODEC_ID_PRORES)
+                    offset = 8;
+
                 pkt = av_mallocz(sizeof(AVPacket));
                 /* XXX: prevent data copy... */
-                if (av_new_packet(pkt, pkt_size) < 0) {
+                if (av_new_packet(pkt, pkt_size + offset) < 0) {
                     av_free(pkt);
                     res = AVERROR(ENOMEM);
                     break;
                 }
 
-                memcpy(pkt->data, pkt_data, pkt_size);
+                if (st->codec->codec_id == AV_CODEC_ID_PRORES) {
+                    uint8_t *buf = pkt->data;
+                    bytestream_put_be32(&buf, pkt_size);
+                    bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
+                }
+
+                memcpy(pkt->data + offset, pkt_data, pkt_size);
 
                 if (pkt_data != data)
                     av_free(pkt_data);
index 521f6b5..3e32943 100644 (file)
@@ -1050,7 +1050,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
     MatroskaMuxContext *mkv = s->priv_data;
     AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
     uint8_t *data = NULL;
-    int size = pkt->size;
+    int offset = 0, size = pkt->size;
     int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
 
     av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
@@ -1061,12 +1061,20 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
         ff_avc_parse_nal_units_buf(pkt->data, &data, &size);
     else
         data = pkt->data;
+
+    if (codec->codec_id == AV_CODEC_ID_PRORES) {
+        /* Matroska specification requires to remove the first QuickTime atom
+         */
+        size -= 8;
+        offset = 8;
+    }
+
     put_ebml_id(pb, blockid);
     put_ebml_num(pb, size+4, 0);
     avio_w8(pb, 0x80 | (pkt->stream_index + 1));     // this assumes stream_index is less than 126
     avio_wb16(pb, ts - mkv->cluster_pts);
     avio_w8(pb, flags);
-    avio_write(pb, data, size);
+    avio_write(pb, data + offset, size);
     if (data != pkt->data)
         av_free(data);
 }