h264parse: Add support for passing stereoscopic/multiview info

Pass any multiview info from the container or SEI info downstream
This commit is contained in:
Jan Schmidt 2015-05-30 01:38:16 +10:00
parent e8908f5aee
commit 08c73f9cc7
2 changed files with 154 additions and 5 deletions

View file

@ -112,6 +112,8 @@ static GstCaps *gst_h264_parse_get_caps (GstBaseParse * parse,
static gboolean gst_h264_parse_event (GstBaseParse * parse, GstEvent * event);
static gboolean gst_h264_parse_src_event (GstBaseParse * parse,
GstEvent * event);
static void gst_h264_parse_update_src_caps (GstH264Parse * h264parse,
GstCaps * caps);
static void
gst_h264_parse_class_init (GstH264ParseClass * klass)
@ -209,6 +211,10 @@ gst_h264_parse_reset_stream_info (GstH264Parse * h264parse)
h264parse->have_pps = FALSE;
h264parse->have_sps = FALSE;
h264parse->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
h264parse->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
h264parse->first_in_bundle = TRUE;
h264parse->align = GST_H264_PARSE_ALIGN_NONE;
h264parse->format = GST_H264_PARSE_FORMAT_NONE;
@ -550,15 +556,133 @@ gst_h264_parse_process_sei (GstH264Parse * h264parse, GstH264NalUnit * nalu)
/* Additional messages that are not innerly useful to the
* element but for debugging purposes */
case GST_H264_SEI_STEREO_VIDEO_INFO:
GST_LOG_OBJECT (h264parse, "stereo video information message");
case GST_H264_SEI_STEREO_VIDEO_INFO:{
GstVideoMultiviewMode mview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
GstVideoMultiviewFlags mview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
GST_LOG_OBJECT (h264parse, "Stereo video information %u %u %u %u %u %u",
sei.payload.stereo_video_info.field_views_flag,
sei.payload.stereo_video_info.top_field_is_left_view_flag,
sei.payload.stereo_video_info.current_frame_is_left_view_flag,
sei.payload.stereo_video_info.next_frame_is_second_view_flag,
sei.payload.stereo_video_info.left_view_self_contained_flag,
sei.payload.stereo_video_info.right_view_self_contained_flag);
if (sei.payload.stereo_video_info.field_views_flag) {
mview_mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
if (!sei.payload.stereo_video_info.top_field_is_left_view_flag)
mview_mode |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
} else {
mview_mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
if (sei.payload.stereo_video_info.next_frame_is_second_view_flag) {
/* Mark current frame as first in bundle */
h264parse->first_in_bundle = TRUE;
if (!sei.payload.stereo_video_info.current_frame_is_left_view_flag)
mview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
}
}
if (mview_mode != h264parse->multiview_mode ||
mview_flags != h264parse->multiview_flags) {
h264parse->multiview_mode = mview_mode;
h264parse->multiview_flags = mview_flags;
/* output caps need to be changed */
gst_h264_parse_update_src_caps (h264parse, NULL);
}
break;
case GST_H264_SEI_FRAME_PACKING:
GST_LOG_OBJECT (h264parse, "frame packing arrangement message: type %d",
}
case GST_H264_SEI_FRAME_PACKING:{
GstVideoMultiviewMode mview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
GstVideoMultiviewFlags mview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
GST_LOG_OBJECT (h264parse,
"frame packing arrangement message: id %u cancelled %u "
"type %u quincunx %u content_interpretation %d flip %u "
"right_first %u field_views %u is_frame0 %u",
sei.payload.frame_packing.frame_packing_id,
sei.payload.frame_packing.frame_packing_cancel_flag,
sei.payload.frame_packing.frame_packing_type,
sei.payload.frame_packing.quincunx_sampling_flag,
sei.payload.frame_packing.content_interpretation_type,
sei.payload.frame_packing.spatial_flipping_flag,
sei.payload.frame_packing.frame0_flipped_flag,
sei.payload.frame_packing.field_views_flag,
sei.payload.frame_packing.current_frame_is_frame0_flag);
/* Only IDs from 0->255 and 512->2^31-1 are valid. Ignore others */
if ((sei.payload.frame_packing.frame_packing_id >= 256 &&
sei.payload.frame_packing.frame_packing_id < 512) ||
(sei.payload.frame_packing.frame_packing_id >= (1U << 31)))
break; /* ignore */
if (!sei.payload.frame_packing.frame_packing_cancel_flag) {
/* Cancel flag sets things back to no-info */
if (sei.payload.frame_packing.content_interpretation_type == 2)
mview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
switch (sei.payload.frame_packing.frame_packing_type) {
case 0:
mview_mode = GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD;
break;
case 1:
mview_mode = GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED;
break;
case 2:
mview_mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
break;
case 3:
if (sei.payload.frame_packing.quincunx_sampling_flag)
mview_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX;
else
mview_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
if (sei.payload.frame_packing.spatial_flipping_flag) {
/* One of the views is flopped. */
if (sei.payload.frame_packing.frame0_flipped_flag !=
! !(mview_flags &
GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST))
/* the left view is flopped */
mview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED;
else
mview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED;
}
break;
case 4:
mview_mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
if (sei.payload.frame_packing.spatial_flipping_flag) {
/* One of the views is flipped, */
if (sei.payload.frame_packing.frame0_flipped_flag !=
! !(mview_flags &
GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST))
/* the left view is flipped */
mview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED;
else
mview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED;
}
break;
case 5:
if (sei.payload.frame_packing.content_interpretation_type == 0)
mview_mode = GST_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME;
else
mview_mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
break;
default:
GST_DEBUG_OBJECT (h264parse, "Invalid frame packing type %u",
sei.payload.frame_packing.frame_packing_type);
break;
}
}
if (mview_mode != h264parse->multiview_mode ||
mview_flags != h264parse->multiview_flags) {
h264parse->multiview_mode = mview_mode;
h264parse->multiview_flags = mview_flags;
/* output caps need to be changed */
gst_h264_parse_update_src_caps (h264parse, NULL);
}
break;
}
}
}
g_array_free (messages, TRUE);
}
@ -1616,6 +1740,10 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
gint width, height;
GstClockTime latency;
const gchar *caps_mview_mode = NULL;
GstVideoMultiviewMode mview_mode = h264parse->multiview_mode;
GstVideoMultiviewFlags mview_flags = h264parse->multiview_flags;
fps_num = h264parse->fps_num;
fps_den = h264parse->fps_den;
@ -1632,6 +1760,21 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
else
height = h264parse->height;
/* Pass through or set output stereo/multiview config */
if (s && gst_structure_has_field (s, "multiview-mode")) {
caps_mview_mode = gst_structure_get_string (s, "multiview-mode");
mview_mode =
gst_video_multiview_mode_from_caps_string (caps_mview_mode);
gst_structure_get_flagset (s, "multiview-flags", &mview_flags, NULL);
}
if (mview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
caps_mview_mode = gst_video_multiview_mode_to_caps_string (mview_mode);
gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
caps_mview_mode, "multiview-flags",
GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, mview_flags,
GST_FLAG_SET_MASK_EXACT, NULL);
}
gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
"height", G_TYPE_INT, height, NULL);

View file

@ -28,6 +28,7 @@
#include <gst/gst.h>
#include <gst/base/gstbaseparse.h>
#include <gst/codecparsers/gsth264parser.h>
#include <gst/video/video.h>
G_BEGIN_DECLS
@ -121,6 +122,11 @@ struct _GstH264Parse
GstClockTime pending_key_unit_ts;
GstEvent *force_key_unit_event;
/* Stereo / multiview info */
GstVideoMultiviewMode multiview_mode;
GstVideoMultiviewFlags multiview_flags;
gboolean first_in_bundle;
};
struct _GstH264ParseClass