video: Add multiview/stereo support

Add flags and enums to support multiview signalling in
GstVideoInfo and GstVideoFrame, and the caps serialisation and
deserialisation.

videoencoder: Copy multiview settings from reference input state

Add gst_video_multiview_* support API and GstVideoMultiviewMeta meta

https://bugzilla.gnome.org/show_bug.cgi?id=611157
This commit is contained in:
Jan Schmidt 2015-06-11 11:12:39 +10:00
parent abcaa71485
commit 7c1da700c4
11 changed files with 939 additions and 27 deletions

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -58,6 +58,159 @@ typedef enum {
const gchar * gst_video_interlace_mode_to_string (GstVideoInterlaceMode mode);
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
@ -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>

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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