mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
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.
This commit is contained in:
parent
fff76157d8
commit
ec5bc9dccb
4 changed files with 123 additions and 2 deletions
|
@ -731,12 +731,61 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml)
|
||||||
g_free (data);
|
g_free (data);
|
||||||
break;
|
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:
|
default:
|
||||||
GST_WARNING_OBJECT (demux,
|
GST_WARNING_OBJECT (demux,
|
||||||
"Unknown TrackVideo subelement 0x%x - ignoring", id);
|
"Unknown TrackVideo subelement 0x%x - ignoring", id);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case GST_MATROSKA_ID_VIDEOSTEREOMODE:
|
|
||||||
case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
|
case GST_MATROSKA_ID_VIDEODISPLAYUNIT:
|
||||||
case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
|
case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM:
|
||||||
case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
|
case GST_MATROSKA_ID_VIDEOPIXELCROPTOP:
|
||||||
|
|
|
@ -59,6 +59,9 @@ gst_matroska_track_init_video_context (GstMatroskaTrackContext ** p_context)
|
||||||
video_context->fourcc = 0;
|
video_context->fourcc = 0;
|
||||||
video_context->default_fps = 0.0;
|
video_context->default_fps = 0.0;
|
||||||
video_context->earliest_time = GST_CLOCK_TIME_NONE;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define __GST_MATROSKA_IDS_H__
|
#define __GST_MATROSKA_IDS_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video-info.h>
|
||||||
|
|
||||||
#include "ebml-ids.h"
|
#include "ebml-ids.h"
|
||||||
|
|
||||||
|
@ -489,6 +490,16 @@ typedef enum {
|
||||||
GST_MATROSKA_VIDEOTRACK_INTERLACED = (GST_MATROSKA_TRACK_SHIFT<<0)
|
GST_MATROSKA_VIDEOTRACK_INTERLACED = (GST_MATROSKA_TRACK_SHIFT<<0)
|
||||||
} GstMatroskaVideoTrackFlags;
|
} 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;
|
typedef struct _GstMatroskaTrackContext GstMatroskaTrackContext;
|
||||||
|
|
||||||
|
@ -571,6 +582,9 @@ typedef struct _GstMatroskaTrackVideoContext {
|
||||||
GstMatroskaAspectRatioMode asr_mode;
|
GstMatroskaAspectRatioMode asr_mode;
|
||||||
guint32 fourcc;
|
guint32 fourcc;
|
||||||
|
|
||||||
|
GstVideoMultiviewMode multiview_mode;
|
||||||
|
GstVideoMultiviewFlags multiview_flags;
|
||||||
|
|
||||||
/* QoS */
|
/* QoS */
|
||||||
GstClockTime earliest_time;
|
GstClockTime earliest_time;
|
||||||
|
|
||||||
|
|
|
@ -929,7 +929,7 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
GstMatroskaPad *collect_pad;
|
GstMatroskaPad *collect_pad;
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
const gchar *mimetype;
|
const gchar *mimetype;
|
||||||
const gchar *interlace_mode;
|
const gchar *interlace_mode, *s;
|
||||||
const GValue *value = NULL;
|
const GValue *value = NULL;
|
||||||
GstBuffer *codec_buf = NULL;
|
GstBuffer *codec_buf = NULL;
|
||||||
gint width, height, pixel_width, pixel_height;
|
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;
|
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:
|
skip_details:
|
||||||
|
|
||||||
videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE;
|
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,
|
gst_ebml_write_binary (ebml, GST_MATROSKA_ID_VIDEOCOLOURSPACE,
|
||||||
(gpointer) & fcc_le, 4);
|
(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);
|
gst_ebml_write_master_finish (ebml, master);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue