Browse code

matroskadec: parse stereo mode on decoding

Convert the Matroska stereo format to the Stereo3D format, and add a
Stereo3D side data to the stream.

Bump the doctype version supported.

Bug-Id: 728 / https://bugs.debian.org/757185

Vittorio Giovara authored on 2014/08/13 06:28:49
Showing 4 changed files
... ...
@@ -32,6 +32,7 @@ version <next>:
32 32
 - request icecast metadata by default
33 33
 - support for using metadata in stream specifiers in avtools
34 34
 - Aliases and defaults for Ogg subtypes (opus, spx)
35
+- matroska 3d support
35 36
 
36 37
 
37 38
 version 10:
... ...
@@ -19,6 +19,8 @@
19 19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 20
  */
21 21
 
22
+#include "libavutil/stereo3d.h"
23
+
22 24
 #include "matroska.h"
23 25
 
24 26
 const CodecTags ff_mkv_codec_tags[]={
... ...
@@ -103,3 +105,65 @@ const AVMetadataConv ff_mkv_metadata_conv[] = {
103 103
     { "PART_NUMBER"   , "track"  },
104 104
     { 0 }
105 105
 };
106
+
107
+int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode)
108
+{
109
+    AVPacketSideData *sd, *tmp;
110
+    AVStereo3D *stereo;
111
+
112
+    stereo = av_stereo3d_alloc();
113
+    if (!stereo)
114
+        return AVERROR(ENOMEM);
115
+
116
+    tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp));
117
+    if (!tmp) {
118
+        av_freep(&stereo);
119
+        return AVERROR(ENOMEM);
120
+    }
121
+    st->side_data = tmp;
122
+    st->nb_side_data++;
123
+
124
+    sd = &st->side_data[st->nb_side_data - 1];
125
+    sd->type = AV_PKT_DATA_STEREO3D;
126
+    sd->data = (uint8_t *)stereo;
127
+    sd->size = sizeof(*stereo);
128
+
129
+    // note: the missing breaks are intentional
130
+    switch (stereo_mode) {
131
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO:
132
+        stereo->type = AV_STEREO3D_2D;
133
+        break;
134
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT:
135
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
136
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT:
137
+        stereo->type = AV_STEREO3D_SIDEBYSIDE;
138
+        break;
139
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP:
140
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
141
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM:
142
+        stereo->type = AV_STEREO3D_TOPBOTTOM;
143
+        break;
144
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL:
145
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
146
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR:
147
+        stereo->type = AV_STEREO3D_CHECKERBOARD;
148
+        break;
149
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL:
150
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
151
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR:
152
+        stereo->type = AV_STEREO3D_LINES;
153
+        break;
154
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL:
155
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
156
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR:
157
+        stereo->type = AV_STEREO3D_COLUMNS;
158
+        break;
159
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL:
160
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
161
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR:
162
+        stereo->type = AV_STEREO3D_FRAMESEQUENCE;
163
+        break;
164
+    }
165
+
166
+    return 0;
167
+}
... ...
@@ -237,6 +237,7 @@ typedef enum {
237 237
   MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG = 12,
238 238
   MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR = 13,
239 239
   MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL = 14,
240
+  MATROSKA_VIDEO_STEREOMODE_TYPE_NB,
240 241
 } MatroskaVideoStereoModeType;
241 242
 
242 243
 /*
... ...
@@ -255,4 +256,6 @@ extern const CodecTags ff_mkv_codec_tags[];
255 255
 extern const CodecMime ff_mkv_mime_tags[];
256 256
 extern const AVMetadataConv ff_mkv_metadata_conv[];
257 257
 
258
+int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode);
259
+
258 260
 #endif /* AVFORMAT_MATROSKA_H */
... ...
@@ -123,6 +123,7 @@ typedef struct {
123 123
     uint64_t pixel_width;
124 124
     uint64_t pixel_height;
125 125
     uint64_t fourcc;
126
+    uint64_t stereo_mode;
126 127
 } MatroskaTrackVideo;
127 128
 
128 129
 typedef struct {
... ...
@@ -319,7 +320,7 @@ static EbmlSyntax matroska_track_video[] = {
319 319
     { MATROSKA_ID_VIDEOPIXELCROPR,     EBML_NONE },
320 320
     { MATROSKA_ID_VIDEODISPLAYUNIT,    EBML_NONE },
321 321
     { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE },
322
-    { MATROSKA_ID_VIDEOSTEREOMODE,     EBML_NONE },
322
+    { MATROSKA_ID_VIDEOSTEREOMODE,     EBML_UINT,  0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } },
323 323
     { MATROSKA_ID_VIDEOASPECTRATIO,    EBML_NONE },
324 324
     { 0 }
325 325
 };
... ...
@@ -1786,6 +1787,13 @@ static int matroska_parse_tracks(AVFormatContext *s)
1786 1786
                 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
1787 1787
                           1000000000, track->default_duration, 30000);
1788 1788
             }
1789
+            // add stream level stereo3d side data if it is a supported format
1790
+            if (track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB &&
1791
+                track->video.stereo_mode != 10 && track->video.stereo_mode != 12) {
1792
+                int ret = ff_mkv_stereo3d_conv(st, track->video.stereo_mode);
1793
+                if (ret < 0)
1794
+                    return ret;
1795
+            }
1789 1796
         } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
1790 1797
             st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
1791 1798
             st->codec->sample_rate = track->audio.out_samplerate;
... ...
@@ -1821,7 +1829,7 @@ static int matroska_read_header(AVFormatContext *s)
1821 1821
         ebml.version         > EBML_VERSION      ||
1822 1822
         ebml.max_size        > sizeof(uint64_t)  ||
1823 1823
         ebml.id_length       > sizeof(uint32_t)  ||
1824
-        ebml.doctype_version > 2) {
1824
+        ebml.doctype_version > 3) {
1825 1825
         av_log(matroska->ctx, AV_LOG_ERROR,
1826 1826
                "EBML header using unsupported features\n"
1827 1827
                "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",