Partially based on a patch by Aurelien Jacobs <[email protected]>.
---
 libavformat/matroska.h    |   7 +++
 libavformat/matroskadec.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+)

diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index d8f4f8e..81f4dfd 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -80,6 +80,13 @@
 #define MATROSKA_ID_TRACKTYPE  0x83
 #define MATROSKA_ID_TRACKAUDIO 0xE1
 #define MATROSKA_ID_TRACKVIDEO 0xE0
+#define MATROSKA_ID_TRACKOPERATION 0xE2
+#define MATROSKA_ID_TRACKCOMBINEPLANES 0xE3
+#define MATROSKA_ID_TRACKPLANE 0xE4
+#define MATROSKA_ID_TRACKPLANEUID 0xE5
+#define MATROSKA_ID_TRACKPLANETYPE 0xE6
+#define MATROSKA_ID_TRACKJOINBLOCKS 0xE9
+#define MATROSKA_ID_TRACKJOINUID 0xED
 #define MATROSKA_ID_CODECID    0x86
 #define MATROSKA_ID_CODECPRIVATE 0x63A2
 #define MATROSKA_ID_CODECNAME  0x258688
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index c55eb2c..6a2e990 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -45,6 +45,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/lzo.h"
 #include "libavutil/mathematics.h"
+#include "libavutil/stereo3d.h"
 
 #include "libavcodec/bytestream.h"
 #include "libavcodec/flac.h"
@@ -116,6 +117,19 @@ typedef struct {
     MatroskaTrackCompression compression;
 } MatroskaTrackEncoding;
 
+typedef struct MatroskaTrackCombinePlanes {
+    EbmlList plane;
+} MatroskaTrackCombinePlanes;
+
+typedef struct MatroskaTrackJoinBlocks {
+    uint64_t uid;
+} MatroskaTrackJoinBlocks;
+
+typedef struct MatroskaTrackPlane {
+    uint64_t uid;
+    uint64_t type;
+} MatroskaTrackPlane;
+
 typedef struct {
     double   frame_rate;
     uint64_t display_width;
@@ -143,6 +157,11 @@ typedef struct {
     uint8_t *buf;
 } MatroskaTrackAudio;
 
+typedef struct MatroskaTrackOperation {
+    EbmlList combine_planes;
+    EbmlList join_blocks;
+} MatroskaTrackOperation;
+
 typedef struct {
     uint64_t num;
     uint64_t uid;
@@ -157,6 +176,7 @@ typedef struct {
     uint64_t flag_forced;
     MatroskaTrackVideo video;
     MatroskaTrackAudio audio;
+    MatroskaTrackOperation operation;
     EbmlList encodings;
     uint64_t codec_delay;
 
@@ -333,6 +353,28 @@ static EbmlSyntax matroska_track_audio[] = {
     { 0 }
 };
 
+static EbmlSyntax matroska_track_plane[] = {
+    { MATROSKA_ID_TRACKPLANEUID,    EBML_UINT, 0, offsetof(MatroskaTrackPlane, 
uid) },
+    { MATROSKA_ID_TRACKPLANETYPE,   EBML_UINT, 0, offsetof(MatroskaTrackPlane, 
type) },
+    { 0 }
+};
+
+static EbmlSyntax matroska_track_combine_planes[] = {
+    { MATROSKA_ID_TRACKPLANE,       EBML_NEST, sizeof(MatroskaTrackPlane), 
offsetof(MatroskaTrackCombinePlanes, plane), { .n = matroska_track_plane } },
+    { 0 }
+};
+
+static EbmlSyntax matroska_track_join_blocks[] = {
+    { MATROSKA_ID_TRACKJOINUID,     EBML_UINT, 0, 
offsetof(MatroskaTrackJoinBlocks, uid) },
+    { 0 }
+};
+
+static EbmlSyntax matroska_track_operation[] = {
+    { MATROSKA_ID_TRACKCOMBINEPLANES,   EBML_NEST, 
sizeof(MatroskaTrackCombinePlanes), offsetof(MatroskaTrackOperation, 
combine_planes), { .n = matroska_track_combine_planes } },
+    { MATROSKA_ID_TRACKJOINBLOCKS,      EBML_NEST, 
sizeof(MatroskaTrackJoinBlocks),    offsetof(MatroskaTrackOperation, 
join_blocks), { .n = matroska_track_join_blocks } },
+    { 0 }
+};
+
 static EbmlSyntax matroska_track_encoding_compression[] = {
     { MATROSKA_ID_ENCODINGCOMPALGO,     EBML_UINT, 0, 
offsetof(MatroskaTrackCompression, algo), { .u = 0 } },
     { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN,  0, 
offsetof(MatroskaTrackCompression, settings) },
@@ -367,6 +409,7 @@ static EbmlSyntax matroska_track[] = {
     { MATROSKA_ID_TRACKFLAGFORCED,       EBML_UINT,  0, 
offsetof(MatroskaTrack, flag_forced),  { .u = 0   } },
     { MATROSKA_ID_TRACKVIDEO,            EBML_NEST,  0, 
offsetof(MatroskaTrack, video),        { .n = matroska_track_video } },
     { MATROSKA_ID_TRACKAUDIO,            EBML_NEST,  0, 
offsetof(MatroskaTrack, audio),        { .n = matroska_track_audio } },
+    { MATROSKA_ID_TRACKOPERATION,        EBML_NEST,  0, 
offsetof(MatroskaTrack, operation),    { .n = matroska_track_operation } },
     { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST,  0, 0,                     
                { .n = matroska_track_encodings } },
     { MATROSKA_ID_TRACKFLAGENABLED,      EBML_NONE },
     { MATROSKA_ID_TRACKFLAGLACING,       EBML_NONE },
@@ -1232,6 +1275,65 @@ static int matroska_merge_packets(AVPacket *out, 
AVPacket *in)
     return 0;
 }
 
+static int matroska_convert_s3dmulti(AVFormatContext *s, MatroskaTrack *track)
+{
+    int i, j;
+    MatroskaDemuxContext *matroska = s->priv_data;
+
+    if (track->operation.combine_planes.nb_elem > 3) {
+        avpriv_report_missing_feature(s,
+                                      "operation.combine_planes.nb_elem > 3 
(%d)",
+                                      track->operation.combine_planes.nb_elem);
+        return 0; // or invalid data or patchwelcome?
+    }
+
+    for (i = 0; i < track->operation.combine_planes.nb_elem; i++) {
+        MatroskaTrackPlane *planes = track->operation.combine_planes.elem;
+        if (planes[i].type > 3)
+            return AVERROR_INVALIDDATA; //same?
+
+        // iterate over the tracks until the uid matches with the plane's
+        for (j = 0; j < matroska->tracks.nb_elem; j++) {
+            MatroskaTrack *tracks = matroska->tracks.elem;
+            if (planes[i].uid == tracks[j].uid) {
+                AVStream *st = s->streams[j];
+                AVStereo3D *stereo;
+                AVPacketSideData *sd, *tmp;
+
+                // do not overwrite side data from the other plane/stream
+                if (av_stream_get_side_data(st, AV_PKT_DATA_STEREO3D, NULL))
+                    continue;
+
+                stereo = av_stereo3d_alloc();
+                if (!stereo)
+                    return AVERROR(ENOMEM);
+
+                tmp = av_realloc_array(st->side_data, st->nb_side_data + 1,
+                                       sizeof(*tmp));
+                if (!tmp) {
+                    av_freep(&stereo);
+                    return AVERROR(ENOMEM);
+                }
+                st->side_data = tmp;
+                st->nb_side_data++;
+
+                sd = &st->side_data[st->nb_side_data - 1];
+                sd->type = AV_PKT_DATA_STEREO3D;
+                sd->data = (uint8_t *)stereo;
+                sd->size = sizeof(*stereo);
+
+                stereo->type = AV_STEREO3D_MULTIVIEW;
+                if (planes[i].type == 0)
+                    stereo->flags |= AV_STEREO3D_FLAG_LEFT;
+                else if (planes[i].type == 1)
+                    stereo->flags |= AV_STEREO3D_FLAG_RIGHT;
+                // type == 2 would mean "background" but it's not part of s3d
+            }
+        }
+    }
+    return 0;
+}
+
 static void matroska_convert_tag(AVFormatContext *s, EbmlList *list,
                                  AVDictionary **metadata, char *prefix)
 {
@@ -1791,6 +1893,10 @@ static int matroska_parse_tracks(AVFormatContext *s)
                 int ret = ff_mkv_stereo3d_conv(st, track->video.stereo_mode);
                 if (ret < 0)
                     return ret;
+            } else if (track->operation.combine_planes.nb_elem) {
+                int ret = matroska_convert_s3dmulti(s, track);
+                if (ret < 0)
+                    return ret;
             }
         } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
             st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
@@ -1834,6 +1940,11 @@ static int matroska_read_header(AVFormatContext *s)
                ebml.version, ebml.doctype, ebml.doctype_version);
         ebml_free(ebml_syntax, &ebml);
         return AVERROR_PATCHWELCOME;
+    } else if (ebml.doctype_version == 3) { /// XXX: can anyone confirm?
+        av_log(matroska->ctx, AV_LOG_WARNING,
+               "EBML header using unsupported features\n"
+               "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
+               ebml.version, ebml.doctype, ebml.doctype_version);
     }
     for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++)
         if (!strcmp(ebml.doctype, matroska_doctypes[i]))
-- 
1.8.5.2 (Apple Git-48)

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to