diff options
author | Jan Schmidt <jan@centricular.com> | 2015-06-11 11:12:39 +1000 |
---|---|---|
committer | Jan Schmidt <jan@centricular.com> | 2015-06-11 12:05:00 +1000 |
commit | 7c1da700c45d72592c85b8d05977af8a4929733f (patch) | |
tree | b04a1be3e089787581f520cca53bcebe0dd0019c | |
parent | abcaa7148518dd1dcbe520a32bc3f02a2ab9698c (diff) |
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
-rw-r--r-- | docs/libs/gst-plugins-base-libs-sections.txt | 23 | ||||
-rw-r--r-- | gst-libs/gst/video/Makefile.am | 6 | ||||
-rw-r--r-- | gst-libs/gst/video/gstvideoencoder.c | 13 | ||||
-rw-r--r-- | gst-libs/gst/video/video-frame.h | 23 | ||||
-rw-r--r-- | gst-libs/gst/video/video-info.c | 97 | ||||
-rw-r--r-- | gst-libs/gst/video/video-info.h | 172 | ||||
-rw-r--r-- | gst-libs/gst/video/video-multiview.c | 451 | ||||
-rw-r--r-- | gst-libs/gst/video/video-multiview.h | 83 | ||||
-rw-r--r-- | gst-libs/gst/video/video.h | 1 | ||||
-rw-r--r-- | tests/check/libs/video.c | 85 | ||||
-rw-r--r-- | win32/common/libgstvideo.def | 12 |
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 |