diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 0ee13b3783..6ad4822ab7 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -731,12 +731,61 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) g_free (data); break; } + case GST_MATROSKA_ID_VIDEOSTEREOMODE: + { + guint64 num; + + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) + break; + + GST_DEBUG_OBJECT (demux, "StereoMode: %" G_GUINT64_FORMAT, num); + + switch (num) { + case GST_MATROSKA_STEREO_MODE_SBS_RL: + videocontext->multiview_flags = + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST; + /* fall through */ + case GST_MATROSKA_STEREO_MODE_SBS_LR: + videocontext->multiview_mode = + GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE; + break; + case GST_MATROSKA_STEREO_MODE_TB_RL: + videocontext->multiview_flags = + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST; + /* fall through */ + case GST_MATROSKA_STEREO_MODE_TB_LR: + videocontext->multiview_mode = + GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM; + break; + case GST_MATROSKA_STEREO_MODE_CHECKER_RL: + videocontext->multiview_flags = + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST; + /* fall through */ + case GST_MATROSKA_STEREO_MODE_CHECKER_LR: + videocontext->multiview_mode = + GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD; + break; + case GST_MATROSKA_STEREO_MODE_FBF_RL: + videocontext->multiview_flags = + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST; + /* fall through */ + case GST_MATROSKA_STEREO_MODE_FBF_LR: + videocontext->multiview_mode = + GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME; + /* FIXME: In frame-by-frame mode, left/right frame buffers are + * laced within one block, and we'll need to apply FIRST_IN_BUNDLE + * accordingly. See http://www.matroska.org/technical/specs/index.html#StereoMode */ + GST_FIXME_OBJECT (demux, + "Frame-by-frame stereoscopic mode not fully implemented"); + break; + } + break; + } default: GST_WARNING_OBJECT (demux, "Unknown TrackVideo subelement 0x%x - ignoring", id); /* fall through */ - case GST_MATROSKA_ID_VIDEOSTEREOMODE: case GST_MATROSKA_ID_VIDEODISPLAYUNIT: case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM: case GST_MATROSKA_ID_VIDEOPIXELCROPTOP: diff --git a/gst/matroska/matroska-ids.c b/gst/matroska/matroska-ids.c index 65af1cc4c5..52e5dc30d1 100644 --- a/gst/matroska/matroska-ids.c +++ b/gst/matroska/matroska-ids.c @@ -59,6 +59,9 @@ gst_matroska_track_init_video_context (GstMatroskaTrackContext ** p_context) video_context->fourcc = 0; video_context->default_fps = 0.0; video_context->earliest_time = GST_CLOCK_TIME_NONE; + video_context->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE; + video_context->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE; + return TRUE; } diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h index 41315a052b..661a4a1b0f 100644 --- a/gst/matroska/matroska-ids.h +++ b/gst/matroska/matroska-ids.h @@ -23,6 +23,7 @@ #define __GST_MATROSKA_IDS_H__ #include +#include #include "ebml-ids.h" @@ -489,6 +490,16 @@ typedef enum { GST_MATROSKA_VIDEOTRACK_INTERLACED = (GST_MATROSKA_TRACK_SHIFT<<0) } GstMatroskaVideoTrackFlags; +typedef enum { + GST_MATROSKA_STEREO_MODE_SBS_LR = 0x1, + GST_MATROSKA_STEREO_MODE_TB_RL = 0x2, + GST_MATROSKA_STEREO_MODE_TB_LR = 0x3, + GST_MATROSKA_STEREO_MODE_CHECKER_RL = 0x4, + GST_MATROSKA_STEREO_MODE_CHECKER_LR = 0x5, + GST_MATROSKA_STEREO_MODE_SBS_RL = 0x9, + GST_MATROSKA_STEREO_MODE_FBF_LR = 0xD, + GST_MATROSKA_STEREO_MODE_FBF_RL = 0xE +} GstMatroskaStereoMode; typedef struct _GstMatroskaTrackContext GstMatroskaTrackContext; @@ -571,6 +582,9 @@ typedef struct _GstMatroskaTrackVideoContext { GstMatroskaAspectRatioMode asr_mode; guint32 fourcc; + GstVideoMultiviewMode multiview_mode; + GstVideoMultiviewFlags multiview_flags; + /* QoS */ GstClockTime earliest_time; diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index 0e28ed3214..f555f0df95 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -929,7 +929,7 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) GstMatroskaPad *collect_pad; GstStructure *structure; const gchar *mimetype; - const gchar *interlace_mode; + const gchar *interlace_mode, *s; const GValue *value = NULL; GstBuffer *codec_buf = NULL; gint width, height, pixel_width, pixel_height; @@ -1002,6 +1002,14 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) videocontext->display_height = 0; } + /* Collect stereoscopic info, if any */ + if ((s = gst_structure_get_string (structure, "multiview-mode"))) + videocontext->multiview_mode = + gst_video_multiview_mode_from_caps_string (s); + gst_structure_get_flagset (structure, "multiview-flags", + &videocontext->multiview_flags, NULL); + + skip_details: videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE; @@ -2432,6 +2440,53 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux, gst_ebml_write_binary (ebml, GST_MATROSKA_ID_VIDEOCOLOURSPACE, (gpointer) & fcc_le, 4); } + if (videocontext->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) { + guint64 stereo_mode = 0; + + switch (videocontext->multiview_mode) { + case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE: + if (videocontext->multiview_flags & + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST) + stereo_mode = GST_MATROSKA_STEREO_MODE_SBS_RL; + else + stereo_mode = GST_MATROSKA_STEREO_MODE_SBS_LR; + break; + case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM: + if (videocontext->multiview_flags & + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST) + stereo_mode = GST_MATROSKA_STEREO_MODE_TB_RL; + else + stereo_mode = GST_MATROSKA_STEREO_MODE_TB_LR; + break; + case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD: + if (videocontext->multiview_flags & + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST) + stereo_mode = GST_MATROSKA_STEREO_MODE_CHECKER_RL; + else + stereo_mode = GST_MATROSKA_STEREO_MODE_CHECKER_LR; + break; + case GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME: + if (videocontext->multiview_flags & + GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST) + stereo_mode = GST_MATROSKA_STEREO_MODE_FBF_RL; + else + stereo_mode = GST_MATROSKA_STEREO_MODE_FBF_LR; + /* FIXME: In frame-by-frame mode, left/right frame buffers need to be + * laced within one block. See http://www.matroska.org/technical/specs/index.html#StereoMode */ + GST_FIXME_OBJECT (mux, + "Frame-by-frame stereoscopic mode not fully implemented"); + break; + default: + GST_WARNING_OBJECT (mux, + "Multiview mode %d not supported in Matroska/WebM", + videocontext->multiview_mode); + break; + } + + if (stereo_mode != 0) + gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOSTEREOMODE, + stereo_mode); + } gst_ebml_write_master_finish (ebml, master); break;