summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/libs/gst-plugins-base-libs-sections.txt23
-rw-r--r--gst-libs/gst/video/Makefile.am6
-rw-r--r--gst-libs/gst/video/gstvideoencoder.c13
-rw-r--r--gst-libs/gst/video/video-frame.h23
-rw-r--r--gst-libs/gst/video/video-info.c97
-rw-r--r--gst-libs/gst/video/video-info.h172
-rw-r--r--gst-libs/gst/video/video-multiview.c451
-rw-r--r--gst-libs/gst/video/video-multiview.h83
-rw-r--r--gst-libs/gst/video/video.h1
-rw-r--r--tests/check/libs/video.c85
-rw-r--r--win32/common/libgstvideo.def12
11 files changed, 939 insertions, 27 deletions
diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt
index 06f2ad641..d94ac4c46 100644
--- a/docs/libs/gst-plugins-base-libs-sections.txt
+++ b/docs/libs/gst-plugins-base-libs-sections.txt
@@ -2389,6 +2389,9 @@ GST_TYPE_VIDEO_COLOR_PRIMARIES
<SUBSECTION>
GstVideoInfo
GstVideoInterlaceMode
+GstVideoMultiviewMode
+GstVideoMultiviewFramePacking
+GstVideoMultiviewFlags
GstVideoFlags
GST_VIDEO_INFO_FORMAT
GST_VIDEO_INFO_NAME
@@ -2425,6 +2428,8 @@ GST_VIDEO_INFO_COMP_PSTRIDE
GST_VIDEO_INFO_COMP_POFFSET
GST_VIDEO_INFO_CHROMA_SITE
GST_VIDEO_INFO_COLORIMETRY
+GST_VIDEO_INFO_MULTIVIEW_FLAGS
+GST_VIDEO_INFO_MULTIVIEW_MODE
gst_video_info_init
gst_video_info_set_format
gst_video_info_from_caps
@@ -2437,6 +2442,13 @@ gst_video_interlace_mode_get_type
GST_TYPE_VIDEO_INTERLACE_MODE
gst_video_flags_get_type
GST_TYPE_VIDEO_FLAGS
+GST_TYPE_VIDEO_MULTIVIEW_FLAGS
+GST_TYPE_VIDEO_MULTIVIEW_FLAGSET
+GST_TYPE_VIDEO_MULTIVIEW_FRAME_PACKING
+GST_TYPE_VIDEO_MULTIVIEW_MODE
+gst_video_multiview_mode_get_type
+gst_video_multiview_flagset_get_type
+gst_video_multiview_frame_packing_get_type
#video-frame.h
<SUBSECTION>
@@ -2505,6 +2517,17 @@ gst_video_converter_frame
gst_video_dither_method_get_type
GST_TYPE_VIDEO_DITHER_METHOD
+#video-multiview.h
+<SUBSECTION>
+gst_video_multiview_get_mono_modes
+gst_video_multiview_get_unpacked_modes
+gst_video_multiview_get_doubled_height_modes
+gst_video_multiview_get_doubled_size_modes
+gst_video_multiview_get_doubled_width_modes
+gst_video_multiview_mode_from_caps_string
+gst_video_multiview_mode_to_caps_string
+gst_video_multiview_video_info_change_mode
+
#video-enumtypes.h
<SUBSECTION Standard>
gst_color_balance_type_get_type
diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am
index 7ac5f4455..8200b005e 100644
--- a/gst-libs/gst/video/Makefile.am
+++ b/gst-libs/gst/video/Makefile.am
@@ -45,7 +45,8 @@ libgstvideo_@GST_API_VERSION@_la_SOURCES = \
gstvideoutilsprivate.c \
video-resampler.c \
video-blend.c \
- video-overlay-composition.c
+ video-overlay-composition.c \
+ video-multiview.c
nodist_libgstvideo_@GST_API_VERSION@_la_SOURCES = $(BUILT_SOURCES)
@@ -76,7 +77,8 @@ libgstvideo_@GST_API_VERSION@include_HEADERS = \
gstvideoutils.h \
video-resampler.h \
video-blend.h \
- video-overlay-composition.h
+ video-overlay-composition.h \
+ video-multiview.h
nodist_libgstvideo_@GST_API_VERSION@include_HEADERS = $(built_headers)
noinst_HEADERS = gstvideoutilsprivate.h
diff --git a/gst-libs/gst/video/gstvideoencoder.c b/gst-libs/gst/video/gstvideoencoder.c
index 0f85cd9a4..f7cc98b94 100644
--- a/gst-libs/gst/video/gstvideoencoder.c
+++ b/gst-libs/gst/video/gstvideoencoder.c
@@ -565,6 +565,9 @@ _new_output_state (GstCaps * caps, GstVideoCodecState * reference)
tgt->par_d = ref->par_d;
tgt->fps_n = ref->fps_n;
tgt->fps_d = ref->fps_d;
+
+ GST_VIDEO_INFO_MULTIVIEW_MODE (tgt) = GST_VIDEO_INFO_MULTIVIEW_MODE (ref);
+ GST_VIDEO_INFO_MULTIVIEW_FLAGS (tgt) = GST_VIDEO_INFO_MULTIVIEW_FLAGS (ref);
}
return state;
@@ -1517,6 +1520,16 @@ gst_video_encoder_negotiate_default (GstVideoEncoder * encoder)
if (state->codec_data)
gst_caps_set_simple (state->caps, "codec_data", GST_TYPE_BUFFER,
state->codec_data, NULL);
+
+ if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
+ const gchar *caps_mview_mode =
+ gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
+ (info));
+
+ gst_caps_set_simple (state->caps, "multiview-mode", G_TYPE_STRING,
+ caps_mview_mode, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
+ GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), GST_FLAG_SET_MASK_EXACT, NULL);
+ }
encoder->priv->output_state_changed = FALSE;
}
diff --git a/gst-libs/gst/video/video-frame.h b/gst-libs/gst/video/video-frame.h
index 929ebab8a..27d5e4410 100644
--- a/gst-libs/gst/video/video-frame.h
+++ b/gst-libs/gst/video/video-frame.h
@@ -35,6 +35,10 @@ typedef struct _GstVideoFrame GstVideoFrame;
* @GST_VIDEO_FRAME_FLAG_TFF: The video frame has the top field first
* @GST_VIDEO_FRAME_FLAG_RFF: The video frame has the repeat flag
* @GST_VIDEO_FRAME_FLAG_ONEFIELD: The video frame has one field
+ * @GST_VIDEO_FRAME_FLAG_MULTIPLE_VIEW: The video contains one or
+ * more non-mono views
+ * @GST_VIDEO_FRAME_FLAG_FIRST_IN_BUNDLE: The video frame is the first
+ * in a set of corresponding views provided as sequential frames.
*
* Extra video frame flags
*/
@@ -43,7 +47,9 @@ typedef enum {
GST_VIDEO_FRAME_FLAG_INTERLACED = (1 << 0),
GST_VIDEO_FRAME_FLAG_TFF = (1 << 1),
GST_VIDEO_FRAME_FLAG_RFF = (1 << 2),
- GST_VIDEO_FRAME_FLAG_ONEFIELD = (1 << 3)
+ GST_VIDEO_FRAME_FLAG_ONEFIELD = (1 << 3),
+ GST_VIDEO_FRAME_FLAG_MULTIPLE_VIEW = (1 << 4),
+ GST_VIDEO_FRAME_FLAG_FIRST_IN_BUNDLE = (1 << 5)
} GstVideoFrameFlags;
/* circular dependency, need to include this after defining the enums */
@@ -136,9 +142,19 @@ gboolean gst_video_frame_copy_plane (GstVideoFrame *dest, const GstVideoFr
* @GST_VIDEO_BUFFER_FLAG_ONEFIELD: If the #GstBuffer is interlaced, then only the
* first field (as defined by the %GST_VIDEO_BUFFER_TFF
* flag setting) is to be displayed.
+ * @GST_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW: The #GstBuffer contains one or more specific views,
+ * such as left or right eye view. This flags is set on
+ * any buffer that contains non-mono content - even for
+ * streams that contain only a single viewpoint. In mixed
+ * mono / non-mono streams, the absense of the flag marks
+ * mono buffers.
+ * @GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE: When conveying stereo/multiview content with
+ * frame-by-frame methods, this flag marks the first buffer
+ * in a bundle of frames that belong together.
* @GST_VIDEO_BUFFER_FLAG_LAST: Offset to define more flags
*
- * Additional video buffer flags.
+ * Additional video buffer flags. These flags can potentially be used on any
+ * buffers carrying video data - even encoded data.
*/
typedef enum {
GST_VIDEO_BUFFER_FLAG_INTERLACED = (GST_BUFFER_FLAG_LAST << 0),
@@ -146,6 +162,9 @@ typedef enum {
GST_VIDEO_BUFFER_FLAG_RFF = (GST_BUFFER_FLAG_LAST << 2),
GST_VIDEO_BUFFER_FLAG_ONEFIELD = (GST_BUFFER_FLAG_LAST << 3),
+ GST_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW = (GST_BUFFER_FLAG_LAST << 4),
+ GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE = (GST_BUFFER_FLAG_LAST << 5),
+
GST_VIDEO_BUFFER_FLAG_LAST = (GST_BUFFER_FLAG_LAST << 8)
} GstVideoBufferFlags;
diff --git a/gst-libs/gst/video/video-info.c b/gst-libs/gst/video/video-info.c
index 5b9b380cb..0aa9ebb53 100644
--- a/gst-libs/gst/video/video-info.c
+++ b/gst-libs/gst/video/video-info.c
@@ -52,6 +52,7 @@ gst_video_info_init (GstVideoInfo * info)
info->fps_d = 1;
info->par_n = 1;
info->par_d = 1;
+ GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
}
#define MAKE_COLORIMETRY(r,m,t,p) { \
@@ -140,6 +141,7 @@ gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
info->finfo = gst_video_format_get_info (format);
info->width = width;
info->height = height;
+ info->views = 1;
set_default_colorimetry (info);
@@ -210,7 +212,7 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
GstStructure *structure;
const gchar *s;
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
- gint width = 0, height = 0, views;
+ gint width = 0, height = 0;
gint fps_n, fps_d;
gint par_n, par_d;
@@ -266,15 +268,38 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
info->fps_d = 1;
}
+ if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
+ &par_n, &par_d)) {
+ info->par_n = par_n;
+ info->par_d = par_d;
+ } else {
+ info->par_n = 1;
+ info->par_d = 1;
+ }
+
if ((s = gst_structure_get_string (structure, "interlace-mode")))
info->interlace_mode = gst_video_interlace_mode_from_string (s);
else
info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
- if (gst_structure_get_int (structure, "views", &views))
- info->views = views;
- else
- info->views = 1;
+ {
+ if ((s = gst_structure_get_string (structure, "multiview-mode")))
+ GST_VIDEO_INFO_MULTIVIEW_MODE (info) =
+ gst_video_multiview_mode_from_caps_string (s);
+ else
+ GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
+
+ gst_structure_get_flagset (structure, "multiview-flags",
+ &GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), NULL);
+
+ if (!gst_structure_get_int (structure, "views", &info->views))
+ info->views = 1;
+
+ /* At one point, I tried normalising the half-aspect flag here,
+ * but it behaves weird for GstVideoInfo operations other than
+ * directly converting to/from caps - sometimes causing the
+ * PAR to be doubled/halved too many times */
+ }
if ((s = gst_structure_get_string (structure, "chroma-site")))
info->chroma_site = gst_video_chroma_from_string (s);
@@ -294,14 +319,6 @@ gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
set_default_colorimetry (info);
}
- if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
- &par_n, &par_d)) {
- info->par_n = par_n;
- info->par_d = par_d;
- } else {
- info->par_n = 1;
- info->par_d = 1;
- }
fill_planes (info);
return TRUE;
@@ -375,6 +392,14 @@ gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
return FALSE;
if (GST_VIDEO_INFO_CHROMA_SITE (info) != GST_VIDEO_INFO_CHROMA_SITE (other))
return FALSE;
+ if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) !=
+ GST_VIDEO_INFO_MULTIVIEW_MODE (other))
+ return FALSE;
+ if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) !=
+ GST_VIDEO_INFO_MULTIVIEW_FLAGS (other))
+ return FALSE;
+ if (GST_VIDEO_INFO_VIEWS (info) != GST_VIDEO_INFO_VIEWS (other))
+ return FALSE;
for (i = 0; i < info->finfo->n_planes; i++) {
if (info->stride[i] != other->stride[i])
@@ -400,6 +425,7 @@ gst_video_info_to_caps (GstVideoInfo * info)
GstCaps *caps;
const gchar *format;
gchar *color;
+ gint par_n, par_d;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (info->finfo != NULL, NULL);
@@ -411,12 +437,53 @@ gst_video_info_to_caps (GstVideoInfo * info)
caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, format,
"width", G_TYPE_INT, info->width,
- "height", G_TYPE_INT, info->height,
- "pixel-aspect-ratio", GST_TYPE_FRACTION, info->par_n, info->par_d, NULL);
+ "height", G_TYPE_INT, info->height, NULL);
+
+ par_n = info->par_n;
+ par_d = info->par_d;
gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
gst_video_interlace_mode_to_string (info->interlace_mode), NULL);
+ if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
+ const gchar *caps_str = NULL;
+
+ /* If the half-aspect flag is set, applying it into the PAR of the
+ * resulting caps now seems safe, and helps with automatic behaviour
+ * in elements that aren't explicitly multiview aware */
+ if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
+ GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
+ GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &=
+ ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
+ switch (GST_VIDEO_INFO_MULTIVIEW_MODE (info)) {
+ case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
+ case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
+ case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
+ case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
+ par_n *= 2; /* double the width / half the height */
+ break;
+ case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
+ case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
+ par_d *= 2; /* half the width / double the height */
+ break;
+ default:
+ break;
+ }
+ }
+
+ caps_str =
+ gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
+ (info));
+ if (caps_str != NULL) {
+ gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
+ caps_str, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
+ GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), GST_FLAG_SET_MASK_EXACT, NULL);
+ }
+ }
+
+ gst_caps_set_simple (caps, "pixel-aspect-ratio",
+ GST_TYPE_FRACTION, par_n, par_d, NULL);
+
if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
gst_video_chroma_to_string (info->chroma_site), NULL);
diff --git a/gst-libs/gst/video/video-info.h b/gst-libs/gst/video/video-info.h
index 20c653b8d..d1d2611d9 100644
--- a/gst-libs/gst/video/video-info.h
+++ b/gst-libs/gst/video/video-info.h
@@ -59,6 +59,159 @@ const gchar * gst_video_interlace_mode_to_string (GstVideoInterlaceM
GstVideoInterlaceMode gst_video_interlace_mode_from_string (const gchar * mode);
/**
+ * GstVideoMultiviewMode:
+ * @GST_VIDEO_MULTIVIEW_MODE_NONE: A special value indicating
+ * no multiview information. Used in GstVideoInfo and other places to
+ * indicate that no specific multiview handling has been requested or
+ * provided. This value is never carried on caps.
+ * @GST_VIDEO_MULTIVIEW_MODE_MONO: All frames are monoscopic.
+ * @GST_VIDEO_MULTIVIEW_MODE_LEFT: All frames represent a left-eye view.
+ * @GST_VIDEO_MULTIVIEW_MODE_RIGHT: All frames represent a right-eye view.
+ * @GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE: Left and right eye views are
+ * provided in the left and right half of the frame respectively.
+ * @GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX: Left and right eye
+ * views are provided in the left and right half of the frame, but
+ * have been sampled using quincunx method, with half-pixel offset
+ * between the 2 views.
+ * @GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED: Alternating vertical
+ * columns of pixels represent the left and right eye view respectively.
+ * @GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED: Alternating horizontal
+ * rows of pixels represent the left and right eye view respectively.
+ * @GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM: The top half of the frame
+ * contains the left eye, and the bottom half the right eye.
+ * @GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD: Pixels are arranged with
+ * alternating pixels representing left and right eye views in a
+ * checkerboard fashion.
+ * @GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME: Left and right eye views
+ * are provided in separate frames alternately.
+ * @GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME: Multiple
+ * independent views are provided in separate frames in sequence.
+ * This method only applies to raw video buffers at the moment.
+ * Specific view identification is via the #GstVideoMultiviewMeta
+ * and #GstVideoMeta(s) on raw video buffers.
+ * @GST_VIDEO_MULTIVIEW_MODE_SEPARATED: Multiple views are
+ * provided as separate #GstMemory framebuffers attached to each
+ * #GstBuffer, described by the #GstVideoMultiviewMeta
+ * and #GstVideoMeta(s)
+ *
+ * All possible stereoscopic 3D and multiview representations.
+ * In conjunction with #GstVideoMultiviewFlags, describes how
+ * multiview content is being transported in the stream.
+ */
+typedef enum {
+ GST_VIDEO_MULTIVIEW_MODE_NONE = -1,
+ GST_VIDEO_MULTIVIEW_MODE_MONO = 0,
+ /* Single view modes */
+ GST_VIDEO_MULTIVIEW_MODE_LEFT,
+ GST_VIDEO_MULTIVIEW_MODE_RIGHT,
+ /* Stereo view modes */
+ GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE,
+ GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX,
+ GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED,
+ GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED,
+ GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM,
+ GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD,
+ /* Padding for new frame packing modes */
+
+ GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME = 32,
+ /* Multivew mode(s) */
+ GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME,
+ GST_VIDEO_MULTIVIEW_MODE_SEPARATED
+ /* future expansion for annotated modes */
+} GstVideoMultiviewMode;
+
+/**
+ * GstVideoMultiviewFramePacking:
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_NONE: A special value indicating
+ * no frame packing info.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_MONO: All frames are monoscopic.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_LEFT: All frames represent a left-eye view.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_RIGHT: All frames represent a right-eye view.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_SIDE_BY_SIDE: Left and right eye views are
+ * provided in the left and right half of the frame respectively.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_SIDE_BY_SIDE_QUINCUNX: Left and right eye
+ * views are provided in the left and right half of the frame, but
+ * have been sampled using quincunx method, with half-pixel offset
+ * between the 2 views.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_COLUMN_INTERLEAVED: Alternating vertical
+ * columns of pixels represent the left and right eye view respectively.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_ROW_INTERLEAVED: Alternating horizontal
+ * rows of pixels represent the left and right eye view respectively.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_TOP_BOTTOM: The top half of the frame
+ * contains the left eye, and the bottom half the right eye.
+ * @GST_VIDEO_MULTIVIEW_FRAME_PACKING_CHECKERBOARD: Pixels are arranged with
+ * alternating pixels representing left and right eye views in a
+ * checkerboard fashion.
+ *
+ * #GstVideoMultiviewFramePacking represents the subset of #GstVideoMultiviewMode
+ * values that can be applied to any video frame without needing extra metadata.
+ * It can be used by elements that provide a property to override the
+ * multiview interpretation of a video stream when the video doesn't contain
+ * any markers.
+ *
+ * This enum is used (for example) on playbin, to re-interpret a played
+ * video stream as a stereoscopic video. The individual enum values are
+ * equivalent to and have the same value as the matching #GstVideoMultiviewMode.
+ *
+ */
+typedef enum {
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_NONE = GST_VIDEO_MULTIVIEW_MODE_NONE,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_MONO = GST_VIDEO_MULTIVIEW_MODE_MONO,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_LEFT = GST_VIDEO_MULTIVIEW_MODE_LEFT,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_RIGHT = GST_VIDEO_MULTIVIEW_MODE_RIGHT,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_SIDE_BY_SIDE = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_SIDE_BY_SIDE_QUINCUNX = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_COLUMN_INTERLEAVED = GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_ROW_INTERLEAVED = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_TOP_BOTTOM = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM,
+ GST_VIDEO_MULTIVIEW_FRAME_PACKING_CHECKERBOARD = GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD
+} GstVideoMultiviewFramePacking;
+
+#define GST_VIDEO_MULTIVIEW_MAX_FRAME_PACKING GST_VIDEO_MULTIVIEW_FRAME_PACKING_CHECKERBOARD
+
+/**
+ * GstVideoMultiviewFlags:
+ * @GST_VIDEO_MULTIVIEW_FLAGS_NONE: No flags
+ * @GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST: For stereo streams, the
+ * normal arrangement of left and right views is reversed.
+ * @GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED: The left view is vertically
+ * mirrored.
+ * @GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED: The left view is horizontally
+ * mirrored.
+ * @GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED: The right view is
+ * vertically mirrored.
+ * @GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED: The right view is
+ * horizontally mirrored.
+ * @GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT: For frame-packed
+ * multiview modes, indicates that the individual
+ * views have been encoded with half the true width or height
+ * and should be scaled back up for display. This flag
+ * is used for overriding input layout interpretation
+ * by adjusting pixel-aspect-ratio.
+ * For side-by-side, column interleaved or checkerboard packings, the
+ * pixel width will be doubled. For row interleaved and top-bottom
+ * encodings, pixel height will be doubled.
+ * @GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO: The video stream contains both
+ * mono and multiview portions, signalled on each buffer by the
+ * absence or presence of the @GST_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW
+ * buffer flag.
+ *
+ * GstVideoMultiviewFlags are used to indicate extra properties of a
+ * stereo/multiview stream beyond the frame layout and buffer mapping
+ * that is conveyed in the #GstMultiviewMode.
+ */
+typedef enum {
+ GST_VIDEO_MULTIVIEW_FLAGS_NONE = 0,
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST = (1 << 0),
+ GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED = (1 << 1),
+ GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED = (1 << 2),
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED = (1 << 3),
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED = (1 << 4),
+ GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT = (1 << 14),
+ GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO = (1 << 15)
+} GstVideoMultiviewFlags;
+
+/**
* GstVideoFlags:
* @GST_VIDEO_FLAG_NONE: no flags
* @GST_VIDEO_FLAG_VARIABLE_FPS: a variable fps is selected, fps_n and fps_d
@@ -91,6 +244,8 @@ typedef enum {
* @fps_d: the framerate demnominator
* @offset: offsets of the planes
* @stride: strides of the planes
+ * @multiview_mode: delivery mode for multiple views. (Since 1.6)
+ * @multiview_flags: flags for multiple views configuration (Since 1.6)
*
* Information describing image properties. This information can be filled
* in from GstCaps with gst_video_info_from_caps(). The information is also used
@@ -120,8 +275,16 @@ struct _GstVideoInfo {
gsize offset[GST_VIDEO_MAX_PLANES];
gint stride[GST_VIDEO_MAX_PLANES];
- /*< private >*/
- gpointer _gst_reserved[GST_PADDING];
+ /* Union preserves padded struct size for backwards compat
+ * Consumer code should use the accessor macros for fields */
+ union {
+ struct {
+ GstVideoMultiviewMode multiview_mode;
+ GstVideoMultiviewFlags multiview_flags;
+ } abi;
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
+ } ABI;
};
/* general info */
@@ -147,6 +310,9 @@ struct _GstVideoInfo {
#define GST_VIDEO_INFO_COLORIMETRY(i) ((i)->colorimetry)
#define GST_VIDEO_INFO_CHROMA_SITE(i) ((i)->chroma_site)
+#define GST_VIDEO_INFO_MULTIVIEW_MODE(i) ((i)->ABI.abi.multiview_mode)
+#define GST_VIDEO_INFO_MULTIVIEW_FLAGS(i) ((i)->ABI.abi.multiview_flags)
+
/* dealing with GstVideoInfo flags */
#define GST_VIDEO_INFO_FLAG_IS_SET(i,flag) ((GST_VIDEO_INFO_FLAGS(i) & (flag)) == (flag))
#define GST_VIDEO_INFO_FLAG_SET(i,flag) (GST_VIDEO_INFO_FLAGS(i) |= (flag))
@@ -184,7 +350,7 @@ gboolean gst_video_info_convert (GstVideoInfo *info,
GstFormat dest_format,
gint64 *dest_value);
gboolean gst_video_info_is_equal (const GstVideoInfo *info,
- const GstVideoInfo *other);
+ const GstVideoInfo *other);
#include <gst/video/video.h>
diff --git a/gst-libs/gst/video/video-multiview.c b/gst-libs/gst/video/video-multiview.c
new file mode 100644
index 000000000..a0f409217
--- /dev/null
+++ b/gst-libs/gst/video/video-multiview.c
@@ -0,0 +1,451 @@
+/* GStreamer
+ * Copyright (C) <2015> Jan Schmidt <jan@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include "video.h"
+
+GType
+gst_video_multiview_flagset_get_type (void)
+{
+ static volatile GType type = 0;
+
+ if (g_once_init_enter (&type)) {
+ GType _type = gst_flagset_register (GST_TYPE_VIDEO_MULTIVIEW_FLAGS);
+ g_once_init_leave (&type, _type);
+ }
+ return type;
+}
+
+
+/* Caps mnemonics for the various multiview representations */
+
+static const struct mview_map_t
+{
+ const gchar *caps_repr;
+ GstVideoMultiviewMode mode;
+} gst_multiview_modes[] = {
+ {
+ "mono", GST_VIDEO_MULTIVIEW_MODE_MONO}, {
+ "left", GST_VIDEO_MULTIVIEW_MODE_LEFT}, {
+ "right", GST_VIDEO_MULTIVIEW_MODE_RIGHT}, {
+ "side-by-side", GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE}, {
+ "side-by-side-quincunx", GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX}, {
+ "column-interleaved", GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED}, {
+ "row-interleaved", GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED}, {
+ "top-bottom", GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM}, {
+ "checkerboard", GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD}, {
+ "frame-by-frame", GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME}, {
+ "multiview-frame-by-frame",
+ GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME}, {
+ "separated", GST_VIDEO_MULTIVIEW_MODE_SEPARATED}
+};
+
+/**
+ * gst_video_multiview_mode_to_caps_string:
+ * @mview_mode: A #GstVideoMultiviewMode value
+ *
+ * Returns: The caps string representation of the mode, or NULL if invalid.
+ *
+ * Given a #GstVideoMultiviewMode returns the multiview-mode caps string
+ * for insertion into a caps structure
+ *
+ * Since: 1.6
+ */
+const gchar *
+gst_video_multiview_mode_to_caps_string (GstVideoMultiviewMode mview_mode)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (gst_multiview_modes); i++) {
+ if (gst_multiview_modes[i].mode == mview_mode) {
+ return gst_multiview_modes[i].caps_repr;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * gst_video_multiview_mode_from_caps_string:
+ * @caps_mview_mode: multiview-mode field string from caps
+ *
+ * Returns: The #GstVideoMultiviewMode value
+ *
+ * Given a string from a caps multiview-mode field,
+ * output the corresponding #GstVideoMultiviewMode
+ * or #GST_VIDEO_MULTIVIEW_MODE_NONE
+ *
+ * Since: 1.6
+ */
+GstVideoMultiviewMode
+gst_video_multiview_mode_from_caps_string (const gchar * caps_mview_mode)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (gst_multiview_modes); i++) {
+ if (g_str_equal (gst_multiview_modes[i].caps_repr, caps_mview_mode)) {
+ return gst_multiview_modes[i].mode;
+ }
+ }
+
+ GST_ERROR ("Invalid multiview info %s", caps_mview_mode);
+ g_warning ("Invalid multiview info %s", caps_mview_mode);
+
+ return GST_VIDEO_MULTIVIEW_MODE_NONE;
+}
+
+/* Array of mono, unpacked, double-height and double-width modes */
+static GValue mode_values[5];
+
+static void
+init_mview_mode_vals (void)
+{
+ static gsize mview_mode_vals_init = 0;
+
+ if (g_once_init_enter (&mview_mode_vals_init)) {
+ GValue item = { 0, };
+ GValue *list;
+
+ g_value_init (&item, G_TYPE_STRING);
+
+ /* Mono modes */
+ list = mode_values;
+ g_value_init (list, GST_TYPE_LIST);
+ g_value_set_static_string (&item, "mono");
+ gst_value_list_append_value (list, &item);
+ g_value_set_static_string (&item, "left");
+ gst_value_list_append_value (list, &item);
+ g_value_set_static_string (&item, "right");
+ gst_value_list_append_value (list, &item);
+
+ /* Unpacked modes - ones split across buffers or memories */
+ list = mode_values + 1;
+ g_value_init (list, GST_TYPE_LIST);
+ g_value_set_static_string (&item, "separated");
+ gst_value_list_append_value (list, &item);
+ g_value_set_static_string (&item, "frame-by-frame");
+ gst_value_list_append_value (list, &item);
+ g_value_set_static_string (&item, "multiview-frame-by-frame");
+ gst_value_list_append_value (list, &item);
+
+ /* Double height modes */
+ list = mode_values + 2;
+ g_value_init (list, GST_TYPE_LIST);
+ g_value_set_static_string (&item, "top-bottom");
+ gst_value_list_append_value (list, &item);
+ g_value_set_static_string (&item, "row-interleaved");
+ gst_value_list_append_value (list, &item);
+
+ /* Double width modes */
+ list = mode_values + 3;
+ g_value_init (list, GST_TYPE_LIST);
+ g_value_set_static_string (&item, "side-by-side");
+ gst_value_list_append_value (list, &item);
+ g_value_set_static_string (&item, "side-by-side-quincunx");
+ gst_value_list_append_value (list, &item);
+ g_value_set_static_string (&item, "column-interleaved");
+ gst_value_list_append_value (list, &item);
+
+ /* Double size (both width & height) modes */
+ list = mode_values + 4;
+ g_value_init (list, GST_TYPE_LIST);
+ g_value_set_static_string (&item, "checkerboard");
+ gst_value_list_append_value (list, &item);
+
+ g_value_unset (&item);
+ g_once_init_leave (&mview_mode_vals_init, 1);
+ }
+}
+
+/**
+ * gst_video_multiview_get_mono_modes:
+ *
+ * Returns: A const #GValue containing a list of mono video modes
+ *
+ * Utility function that returns a #GValue with a GstList of mono video
+ * modes (mono/left/right) for use in caps negotiations.
+ *
+ * Since: 1.6
+ */
+const GValue *
+gst_video_multiview_get_mono_modes (void)
+{
+ init_mview_mode_vals ();
+ return mode_values;
+}
+
+/**
+ * gst_video_multiview_get_unpacked_modes:
+ *
+ * Returns: A const #GValue containing a list of 'unpacked' stereo video modes
+ *
+ * Utility function that returns a #GValue with a GstList of unpacked
+ * stereo video modes (separated/frame-by-frame/frame-by-frame-multiview)
+ * for use in caps negotiations.
+ *
+ * Since: 1.6
+ */
+const GValue *
+gst_video_multiview_get_unpacked_modes (void)
+{
+ init_mview_mode_vals ();
+ return mode_values + 1;
+}
+
+/**
+ * gst_video_multiview_get_doubled_height_modes:
+ *
+ * Returns: A const #GValue containing a list of stereo video modes
+ *
+ * Utility function that returns a #GValue with a GstList of packed stereo
+ * video modes with double the height of a single view for use in
+ * caps negotiations. Currently this is top-bottom and row-interleaved.
+ *
+ * Since: 1.6
+ */
+const GValue *
+gst_video_multiview_get_doubled_height_modes (void)
+{
+ init_mview_mode_vals ();
+ return mode_values + 2;
+}
+
+/**
+ * gst_video_multiview_get_doubled_width_modes:
+ *
+ * Returns: A const #GValue containing a list of stereo video modes
+ *
+ * Utility function that returns a #GValue with a GstList of packed stereo
+ * video modes with double the width of a single view for use in
+ * caps negotiations. Currently this is side-by-side, side-by-side-quincunx
+ * and column-interleaved.
+ *
+ * Since: 1.6
+ */
+const GValue *
+gst_video_multiview_get_doubled_width_modes (void)
+{
+ init_mview_mode_vals ();
+ return mode_values + 3;
+}
+
+/**
+ * gst_video_multiview_get_doubled_size_modes:
+ *
+ * Returns: A const #GValue containing a list of stereo video modes
+ *
+ * Utility function that returns a #GValue with a GstList of packed
+ * stereo video modes that have double the width/height of a single
+ * view for use in caps negotiation. Currently this is just
+ * 'checkerboard' layout.
+ *
+ * Since: 1.6
+ */
+const GValue *
+gst_video_multiview_get_doubled_size_modes (void)
+{
+ init_mview_mode_vals ();
+ return mode_values + 4;
+}
+
+static void
+gst_video_multiview_separated_video_info_from_packed (GstVideoInfo * info)
+{
+ GstVideoMultiviewMode mview_mode;
+
+ mview_mode = GST_VIDEO_INFO_MULTIVIEW_MODE (info);
+
+ /* Normalise the half-aspect flag by adjusting PAR */
+ switch (mview_mode) {
+ case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
+ case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
+ case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
+ case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
+ info->width /= 2;
+ info->views *= 2;
+ GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_SEPARATED;
+ if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
+ GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT)
+ info->par_n *= 2;
+ break;
+ case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
+ case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
+ info->height /= 2;
+ info->views *= 2;
+ GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_SEPARATED;
+ if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
+ GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT)
+ info->par_d *= 2;
+ break;
+ default:
+ /* Mono/left/right/frame-by-frame/already separated */
+ break;
+ }
+ GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &=
+ ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
+}
+
+static void
+gst_video_multiview_separated_video_info_to_packed (GstVideoInfo * info,
+ GstVideoMultiviewMode packed_mview_mode,
+ GstVideoMultiviewFlags packed_mview_flags)
+{
+ /* Convert single-frame info to a packed mode */
+ GST_VIDEO_INFO_MULTIVIEW_MODE (info) = packed_mview_mode;
+ GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = packed_mview_flags;
+
+ switch (packed_mview_mode) {
+ case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
+ case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
+ case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
+ case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
+ info->width *= 2;
+ info->views /= 2;
+ if (packed_mview_flags & GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT)
+ info->par_d *= 2;
+ break;
+ case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
+ case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
+ info->height *= 2;
+ info->views /= 2;
+ if (packed_mview_flags & GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT)
+ info->par_n *= 2;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * gst_video_multiview_video_info_change_mode:
+ * @info: A #GstVideoInfo structure to operate on
+ * @out_mview_mode: A #GstVideoMultiviewMode value
+ * @out_mview_flags: A set of #GstVideoMultiviewFlags
+ *
+ * Utility function that transforms the width/height/PAR
+ * and multiview mode and flags of a #GstVideoInfo into
+ * the requested mode.
+ *
+ * Since: 1.6
+ */
+void
+gst_video_multiview_video_info_change_mode (GstVideoInfo * info,
+ GstVideoMultiviewMode out_mview_mode,
+ GstVideoMultiviewFlags out_mview_flags)
+{
+ gst_video_multiview_separated_video_info_from_packed (info);
+ gst_video_multiview_separated_video_info_to_packed (info, out_mview_mode,
+ out_mview_flags);
+}
+
+#if 0 /* Multiview meta disabled for now */
+GType
+gst_video_multiview_meta_api_get_type (void)
+{
+ static volatile GType type = 0;
+ static const gchar *tags[] =
+ { GST_META_TAG_VIDEO_STR, GST_META_TAG_MEMORY_STR,
+ NULL
+ };
+
+ if (g_once_init_enter (&type)) {
+ GType _type = gst_meta_api_type_register ("GstVideoMultiviewMetaAPI", tags);
+ g_once_init_leave (&type, _type);
+ }
+ return type;
+}
+
+static void
+gst_video_multiview_meta_free (GstVideoMultiviewMeta * mview_meta,
+ GstBuffer * buffer)
+{
+ g_free (mview_meta->view_info);
+}
+
+/* video multiview metadata */
+const GstMetaInfo *
+gst_video_multiview_meta_get_info (void)
+{
+ static const GstMetaInfo *video_meta_info = NULL;
+
+ if (g_once_init_enter (&video_meta_info)) {
+ const GstMetaInfo *meta =
+ gst_meta_register (GST_VIDEO_MULTIVIEW_META_API_TYPE,
+ "GstVideoMultiviewMeta",
+ sizeof (GstVideoMultiviewMeta),
+ (GstMetaInitFunction) NULL,
+ (GstMetaFreeFunction) gst_video_multiview_meta_free,
+ NULL);
+ g_once_init_leave (&video_meta_info, meta);
+ }
+
+ return video_meta_info;
+}
+
+
+GstVideoMultiviewMeta *
+gst_buffer_add_video_multiview_meta (GstBuffer * buffer, guint n_views)
+{
+ GstVideoMultiviewMeta *meta;
+
+ meta =
+ (GstVideoMultiviewMeta *) gst_buffer_add_meta (buffer,
+ GST_VIDEO_MULTIVIEW_META_INFO, NULL);
+
+ if (!meta)
+ return NULL;
+
+ meta->view_info = g_new0 (GstVideoMultiviewViewInfo, n_views);
+ meta->n_views = n_views;
+
+ return meta;
+}
+
+void
+gst_video_multiview_meta_set_n_views (GstVideoMultiviewMeta * mview_meta,
+ guint n_views)
+{
+ guint i;
+
+ mview_meta->view_info =
+ g_renew (GstVideoMultiviewViewInfo, mview_meta->view_info, n_views);
+
+ if (mview_meta->view_info == NULL) {
+ if (n_views > 0)
+ g_warning ("Failed to allocate GstVideoMultiview data");
+ mview_meta->n_views = 0;
+ return;
+ }
+
+ /* Make sure new entries are zero */
+ for (i = mview_meta->n_views; i < n_views; i++) {
+ GstVideoMultiviewViewInfo *info = mview_meta->view_info + i;
+
+ info->meta_id = 0;
+ info->view_label = GST_VIDEO_MULTIVIEW_VIEW_UNKNOWN;
+ }
+ mview_meta->n_views = n_views;
+}
+
+#endif
diff --git a/gst-libs/gst/video/video-multiview.h b/gst-libs/gst/video/video-multiview.h
new file mode 100644
index 000000000..ec2596212
--- /dev/null
+++ b/gst-libs/gst/video/video-multiview.h
@@ -0,0 +1,83 @@
+/* GStreamer
+ * Copyright (C) <2015> Jan Schmidt <jan@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_VIDEO_MULTIVIEW_H__
+#define __GST_VIDEO_MULTIVIEW_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VIDEO_MULTIVIEW_FLAGSET (gst_video_multiview_flagset_get_type())
+GType gst_video_multiview_flagset_get_type (void);
+
+const gchar * gst_video_multiview_mode_to_caps_string (GstVideoMultiviewMode mview_mode);
+GstVideoMultiviewMode gst_video_multiview_mode_from_caps_string (const gchar * caps_mview_mode);
+
+const GValue *gst_video_multiview_get_mono_modes(void);
+const GValue *gst_video_multiview_get_unpacked_modes(void);
+const GValue *gst_video_multiview_get_doubled_height_modes(void);
+const GValue *gst_video_multiview_get_doubled_width_modes(void);
+const GValue *gst_video_multiview_get_doubled_size_modes(void);
+
+void gst_video_multiview_video_info_change_mode (GstVideoInfo *info,
+ GstVideoMultiviewMode out_mview_mode, GstVideoMultiviewFlags out_mview_flags);
+
+#if 0 /* Place-holder for later MVC support */
+#define GST_VIDEO_MULTIVIEW_META_API_TYPE (gst_video_multiview_meta_api_get_type())
+#define GST_VIDEO_MULTIVIEW_META_INFO (gst_video_multiview_meta_get_info())
+
+typedef struct _GstVideoMultiviewMeta GstVideoMultiviewMeta;
+typedef struct _GstVideoMultiviewViewInfo GstVideoMultiviewViewInfo;
+
+GType gst_video_multiview_meta_api_get_type (void);
+const GstMetaInfo * gst_video_multiview_meta_get_info (void);
+
+GstVideoMultiviewMeta * gst_buffer_add_video_multiview_meta (GstBuffer *buffer, guint n_views);
+#define gst_buffer_get_video_multiview_meta(b) ((GstVideoMultiviewMeta *)gst_buffer_get_meta((b),GST_VIDEO_MULTIVIEW_META_API_TYPE))
+
+void gst_video_multiview_meta_set_n_views (GstVideoMultiviewMeta *mview_meta, guint n_views);
+
+typedef enum {
+ GST_VIDEO_MULTIVIEW_VIEW_UNKNOWN = 0,
+ GST_VIDEO_MULTIVIEW_VIEW_MONO = 1,
+ GST_VIDEO_MULTIVIEW_VIEW_LEFT = 2,
+ GST_VIDEO_MULTIVIEW_VIEW_RIGHT = 3
+} GstVideoMultiviewViewLabel;
+
+struct _GstVideoMultiviewViewInfo {
+ GstVideoMultiviewViewLabel view_label;
+
+ guint meta_id; /* id of the GstVideoMeta for this view */
+
+ /*< private >*/
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstVideoMultiviewMeta {
+ GstMeta meta;
+
+ guint n_views;
+ GstVideoMultiviewViewInfo *view_info;
+};
+#endif
+
+G_END_DECLS
+
+#endif
diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h
index b6235b1e8..5399182be 100644
--- a/gst-libs/gst/video/video.h
+++ b/gst-libs/gst/video/video.h
@@ -32,6 +32,7 @@ typedef struct _GstVideoAlignment GstVideoAlignment;
#include <gst/video/video-enumtypes.h>
#include <gst/video/video-converter.h>
#include <gst/video/video-scaler.h>
+#include <gst/video/video-multiview.h>
G_BEGIN_DECLS
diff --git a/tests/check/libs/video.c b/tests/check/libs/video.c
index 0f13f303a..98b5e2663 100644
--- a/tests/check/libs/video.c
+++ b/tests/check/libs/video.c
@@ -743,11 +743,15 @@ GST_START_TEST (test_parse_caps_rgb)
GstCaps *caps, *caps2;
caps = gst_caps_from_string (formats[i].tmpl_caps_string);
+ fail_unless (caps != NULL);
gst_caps_set_simple (caps, "width", G_TYPE_INT, 2 * (i + 1), "height",
G_TYPE_INT, i + 1, "framerate", GST_TYPE_FRACTION, 15, 1,
"pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
"interlace-mode", G_TYPE_STRING, "progressive",
- "colorimetry", G_TYPE_STRING, "1:1:0:0", NULL);
+ "colorimetry", G_TYPE_STRING, "1:1:0:0",
+ "multiview-mode", G_TYPE_STRING, "mono",
+ "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, 0,
+ GST_FLAG_SET_MASK_EXACT, NULL);
g_assert (gst_caps_is_fixed (caps));
GST_DEBUG ("testing caps: %" GST_PTR_FORMAT, caps);
@@ -760,10 +764,14 @@ GST_START_TEST (test_parse_caps_rgb)
/* make sure they're serialised back correctly */
caps2 = gst_video_info_to_caps (&vinfo);
- fail_unless (caps != NULL);
- fail_unless (gst_caps_is_equal (caps, caps2),
- "caps [%" GST_PTR_FORMAT "] not equal to caps2 [%" GST_PTR_FORMAT "]",
- caps, caps2);
+ fail_unless (caps2 != NULL);
+ if (!gst_caps_is_equal (caps, caps2)) {
+ gchar *caps1s = gst_caps_to_string (caps);
+ gchar *caps2s = gst_caps_to_string (caps2);
+ fail ("caps [%s] not equal to caps2 [%s]", caps1s, caps2s);
+ g_free (caps1s);
+ g_free (caps2s);
+ }
gst_caps_unref (caps);
gst_caps_unref (caps2);
@@ -772,6 +780,72 @@ GST_START_TEST (test_parse_caps_rgb)
GST_END_TEST;
+GST_START_TEST (test_parse_caps_multiview)
+{
+ gint i, j;
+ GstVideoMultiviewMode modes[] = {
+ GST_VIDEO_MULTIVIEW_MODE_MONO,
+ GST_VIDEO_MULTIVIEW_MODE_LEFT,
+ GST_VIDEO_MULTIVIEW_MODE_RIGHT,
+ GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE,
+ GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX,
+ GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED,
+ GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED,
+ GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM,
+ GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD,
+ GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME,
+ GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME,
+ GST_VIDEO_MULTIVIEW_MODE_SEPARATED,
+ };
+ GstVideoMultiviewFlags flags[] = {
+ GST_VIDEO_MULTIVIEW_FLAGS_NONE,
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
+ GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED,
+ GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED,
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED,
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED,
+ GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO,
+ GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO |
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST,
+ GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO |
+ GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED
+ };
+
+ for (i = 0; i < G_N_ELEMENTS (modes); i++) {
+ for (j = 0; j < G_N_ELEMENTS (flags); j++) {
+ GstVideoInfo vinfo;
+ GstCaps *caps;
+
+ gst_video_info_init (&vinfo);
+ gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_I420, 320, 240);
+
+ vinfo.multiview_mode = modes[i];
+ vinfo.multiview_flags = flags[j];
+
+ caps = gst_video_info_to_caps (&vinfo);
+ fail_if (caps == NULL);
+ GST_LOG ("mview mode %d flags %x -> caps %" GST_PTR_FORMAT,
+ modes[i], flags[j], caps);
+
+ fail_unless (gst_video_info_from_caps (&vinfo, caps));
+
+ GST_LOG ("mview mode %d flags %x -> info mode %d flags %x",
+ modes[i], flags[j], vinfo.multiview_mode, vinfo.multiview_flags);
+
+ fail_unless (vinfo.multiview_mode == modes[i],
+ "Expected multiview mode %d got mode %d", modes[i],
+ vinfo.multiview_mode);
+ fail_unless (vinfo.multiview_flags == flags[j],
+ "Expected multiview flags 0x%x got 0x%x", flags[j],
+ vinfo.multiview_flags);
+
+ gst_caps_unref (caps);
+ }
+ }
+}
+
+GST_END_TEST;
+
GST_START_TEST (test_events)
{
GstEvent *e;
@@ -2576,6 +2650,7 @@ video_suite (void)
tcase_add_test (tc_chain, test_video_formats_pack_unpack);
tcase_add_test (tc_chain, test_dar_calc);
tcase_add_test (tc_chain, test_parse_caps_rgb);
+ tcase_add_test (tc_chain, test_parse_caps_multiview);
tcase_add_test (tc_chain, test_events);
tcase_add_test (tc_chain, test_convert_frame);
tcase_add_test (tc_chain, test_convert_frame_async);
diff --git a/win32/common/libgstvideo.def b/win32/common/libgstvideo.def
index 7e039c632..651970efb 100644
--- a/win32/common/libgstvideo.def
+++ b/win32/common/libgstvideo.def
@@ -193,6 +193,18 @@ EXPORTS
gst_video_meta_map
gst_video_meta_transform_scale_get_quark
gst_video_meta_unmap
+ gst_video_multiview_flags_get_type
+ gst_video_multiview_flagset_get_type
+ gst_video_multiview_frame_packing_get_type
+ gst_video_multiview_get_doubled_height_modes
+ gst_video_multiview_get_doubled_size_modes
+ gst_video_multiview_get_doubled_width_modes
+ gst_video_multiview_get_mono_modes
+ gst_video_multiview_get_unpacked_modes
+ gst_video_multiview_mode_from_caps_string
+ gst_video_multiview_mode_get_type
+ gst_video_multiview_mode_to_caps_string
+ gst_video_multiview_video_info_change_mode
gst_video_orientation_get_hcenter
gst_video_orientation_get_hflip
gst_video_orientation_get_type