From: Jan Schmidt Date: Wed, 10 Jun 2015 14:22:54 +0000 (+1000) Subject: matroska: Implement basic stereoscopic video support X-Git-Tag: 1.19.3~509^2~3540 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ec5bc9dccb5eb6bd3d9fa3b266b416149df6449c;p=platform%2Fupstream%2Fgstreamer.git matroska: Implement basic stereoscopic video support Implement support for the packed video formats WebM uses, not all the values that Matroska might use. In practice, it's really hard to find any samples in the wild of any. Supported in both the muxer and demuxer. --- 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;