Bug#757185: Fwd: [PATCH 4/6] mkv: parse stereo mode on decoding

Vittorio Giovara vittorio.giovara at gmail.com
Fri Aug 15 12:52:55 UTC 2014


Hi,
relying on metadata is fragile and there is no way to track its
behaviour between various versions. Also metedata is useful for
textual information and stereoscopic types are certainly not textual.
Thus I have designed an API which works exactly like rotation,
replaygain and others container level information to offer the same
(if not more stable and more powerful as frames gets tagged as well)
functionality.
Please see the patch below for an example on the matroska demuxer.
Cheers,
Vittorio

---------- Forwarded message ----------
From: Vittorio Giovara <vittorio.giovara at gmail.com>
Date: Fri, Aug 15, 2014 at 11:51 AM
Subject: [PATCH 4/6] mkv: parse stereo mode on decoding
To: libav-devel at libav.org


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

Bump the doctype version supported.
---
 libavformat/matroska.c    | 70 +++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/matroska.h    |  3 ++
 libavformat/matroskadec.c | 10 +++++--
 3 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/libavformat/matroska.c b/libavformat/matroska.c
index 9628abc..0c3e845 100644
--- a/libavformat/matroska.c
+++ b/libavformat/matroska.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */

+#include "libavutil/stereo3d.h"
+
 #include "matroska.h"

 const CodecTags ff_mkv_codec_tags[]={
@@ -103,3 +105,71 @@ const AVMetadataConv ff_mkv_metadata_conv[] = {
     { "PART_NUMBER"   , "track"  },
     { 0 }
 };
+
+int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode)
+{
+    AVPacketSideData *sd, *tmp;
+    AVStereo3D *stereo;
+
+    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);
+
+    // note: the missing breaks are intentional
+    switch (stereo_mode) {
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO:
+        stereo->type = AV_STEREO3D_2D;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT:
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT:
+        stereo->type = AV_STEREO3D_SIDEBYSIDE;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP:
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM:
+        stereo->type = AV_STEREO3D_TOPBOTTOM;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL:
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR:
+        stereo->type = AV_STEREO3D_CHECKERBOARD;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL:
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR:
+        stereo->type = AV_STEREO3D_LINES;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL:
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR:
+        stereo->type = AV_STEREO3D_COLUMNS;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL:
+        stereo->flags |= AV_STEREO3D_FLAG_INVERT;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR:
+        stereo->type = AV_STEREO3D_FRAMESEQUENCE;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_CYAN_RED:
+        stereo->type = AV_STEREO3D_ANAGLYPH_CYAN_RED;
+        break;
+    case MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG:
+        stereo->type = AV_STEREO3D_ANAGLYPH_GREEN_MAGENTA;
+        break;
+    }
+
+    return 0;
+}
diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 667f92a..d8f4f8e 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -237,6 +237,7 @@ typedef enum {
   MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG = 12,
   MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR = 13,
   MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL = 14,
+  MATROSKA_VIDEO_STEREOMODE_TYPE_NB,
 } MatroskaVideoStereoModeType;

 /*
@@ -255,4 +256,6 @@ extern const CodecTags ff_mkv_codec_tags[];
 extern const CodecMime ff_mkv_mime_tags[];
 extern const AVMetadataConv ff_mkv_metadata_conv[];

+int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType
stereo_mode);
+
 #endif /* AVFORMAT_MATROSKA_H */
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 9ffb80a..f5c545f 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -123,6 +123,7 @@ typedef struct {
     uint64_t pixel_width;
     uint64_t pixel_height;
     uint64_t fourcc;
+    uint64_t stereo_mode;
 } MatroskaTrackVideo;

 typedef struct {
@@ -319,7 +320,7 @@ static EbmlSyntax matroska_track_video[] = {
     { MATROSKA_ID_VIDEOPIXELCROPR,     EBML_NONE },
     { MATROSKA_ID_VIDEODISPLAYUNIT,    EBML_NONE },
     { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE },
-    { MATROSKA_ID_VIDEOSTEREOMODE,     EBML_NONE },
+    { MATROSKA_ID_VIDEOSTEREOMODE,     EBML_UINT,  0,
offsetof(MatroskaTrackVideo, stereo_mode), { .u =
MATROSKA_VIDEO_STEREOMODE_TYPE_NB } },
     { MATROSKA_ID_VIDEOASPECTRATIO,    EBML_NONE },
     { 0 }
 };
@@ -1786,6 +1787,11 @@ static int matroska_parse_tracks(AVFormatContext *s)
                 av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
                           1000000000, track->default_duration, 30000);
             }
+            if (track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) {
+                int ret = ff_mkv_stereo3d_conv(st, track->video.stereo_mode);
+                if (ret < 0)
+                    return ret;
+            }
         } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
             st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
             st->codec->sample_rate = track->audio.out_samplerate;
@@ -1821,7 +1827,7 @@ static int matroska_read_header(AVFormatContext *s)
         ebml.version         > EBML_VERSION      ||
         ebml.max_size        > sizeof(uint64_t)  ||
         ebml.id_length       > sizeof(uint32_t)  ||
-        ebml.doctype_version > 2) {
+        ebml.doctype_version > 3) {
         av_log(matroska->ctx, AV_LOG_ERROR,
                "EBML header using unsupported features\n"
                "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n",
--
1.8.5.2 (Apple Git-48)



-- 
Vittorio



More information about the pkg-multimedia-maintainers mailing list