summaryrefslogtreecommitdiff
path: root/gst-libs/gst
diff options
context:
space:
mode:
authorHe Junyan <junyan.he@intel.com>2021-05-11 16:59:07 +0800
committerHe Junyan <junyan.he@intel.com>2021-06-10 22:22:14 +0800
commit9f02c3fa4ccf66d0258608ce9eda3051706a835e (patch)
tree7dc771a7f14b38166285807624b9cc83148f9bbb /gst-libs/gst
parent26143333899382035e66f0360019c67d4a252e78 (diff)
Decoder: H264: Add the support for frame packing arrangement SEI message.
Frame packing arrangement SEI message is an alternative simple stereo 3D manner for AVC. We need to recognize that SEI message and report the correct 3D caps. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/420>
Diffstat (limited to 'gst-libs/gst')
-rw-r--r--gst-libs/gst/vaapi/gstvaapidecoder_h264.c166
1 files changed, 161 insertions, 5 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c
index 8c3b9b09..01b1797e 100644
--- a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c
+++ b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c
@@ -46,6 +46,7 @@ typedef struct _GstVaapiFrameStore GstVaapiFrameStore;
typedef struct _GstVaapiFrameStoreClass GstVaapiFrameStoreClass;
typedef struct _GstVaapiParserInfoH264 GstVaapiParserInfoH264;
typedef struct _GstVaapiPictureH264 GstVaapiPictureH264;
+typedef struct _GstVaapiStereo3DInfo GstVaapiStereo3DInfo;
// Used for field_poc[]
#define TOP_FIELD 0
@@ -461,6 +462,24 @@ gst_vaapi_frame_store_has_inter_view (GstVaapiFrameStore * fs)
(GstVaapiMiniObject *)(new_fs))
/* ------------------------------------------------------------------------- */
+/* --- H.264 3D Info --- */
+/* ------------------------------------------------------------------------- */
+/**
+ * GstVaapiStereo3DInfo:
+ * @mode: the #GstVideoMultiviewMode.
+ * @flags: the #GstVideoMultiviewFlags.
+ * @id: the id number.
+ * @repetition_period: 0 means once, 1 means always, >1 compare with poc.
+ */
+struct _GstVaapiStereo3DInfo
+{
+ GstVideoMultiviewMode mode;
+ GstVideoMultiviewFlags flags;
+ guint id;
+ guint repetition_period;
+};
+
+/* ------------------------------------------------------------------------- */
/* --- H.264 Decoder --- */
/* ------------------------------------------------------------------------- */
@@ -539,6 +558,8 @@ struct _GstVaapiDecoderH264Private
gboolean force_low_latency;
gboolean base_only;
+
+ GstVaapiStereo3DInfo stereo_info;
};
/**
@@ -1332,6 +1353,8 @@ gst_vaapi_decoder_h264_create (GstVaapiDecoder * base_decoder)
priv->prev_pic_structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
priv->progressive_sequence = TRUE;
priv->top_field_first = FALSE;
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_MONO;
+ priv->stereo_info.flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
return TRUE;
}
@@ -1555,11 +1578,15 @@ ensure_context (GstVaapiDecoderH264 * decoder, GstH264SPS * sps)
if (reset_context) {
switch (num_views) {
case 1:
- /* Frame-packed mode details should be copied from the parser
- * if we set NONE */
- gst_vaapi_decoder_set_multiview_mode (base_decoder,
- num_views, GST_VIDEO_MULTIVIEW_MODE_NONE,
- GST_VIDEO_MULTIVIEW_FLAGS_NONE);
+ /* Frame-packed mode details should be used if we got */
+ if (priv->stereo_info.mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
+ gst_vaapi_decoder_set_multiview_mode (base_decoder,
+ 2, priv->stereo_info.mode, priv->stereo_info.flags);
+ } else {
+ gst_vaapi_decoder_set_multiview_mode (base_decoder,
+ num_views, GST_VIDEO_MULTIVIEW_MODE_NONE,
+ GST_VIDEO_MULTIVIEW_FLAGS_NONE);
+ }
break;
case 2: /* Assume stereo */
if (profile == GST_VAAPI_PROFILE_H264_STEREO_HIGH) {
@@ -1964,6 +1991,132 @@ decode_pps (GstVaapiDecoderH264 * decoder, GstVaapiDecoderUnit * unit)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
}
+static gboolean
+decode_sei_frame_packing (GstVaapiDecoderH264 * decoder,
+ const GstH264FramePacking * frame_packing)
+{
+ GstVaapiDecoderH264Private *const priv = &decoder->priv;
+ GstVideoMultiviewMode saved_mode = priv->stereo_info.mode;
+ GstVideoMultiviewFlags saved_flags = priv->stereo_info.flags;
+ gboolean left = TRUE;
+ gboolean frame_revert = FALSE;
+
+ /* Only IDs from 0->255 and 512->2^31-1 are valid. Ignore others */
+ if ((frame_packing->frame_packing_id >= 256 &&
+ frame_packing->frame_packing_id < 512) ||
+ (frame_packing->frame_packing_id >= (1U << 31)))
+ return FALSE;
+
+ if (frame_packing->frame_packing_cancel_flag) {
+ if (priv->stereo_info.id == frame_packing->frame_packing_id)
+ priv->stereo_info = (GstVaapiStereo3DInfo) {
+ GST_VIDEO_MULTIVIEW_MODE_MONO, GST_VIDEO_MULTIVIEW_FLAGS_NONE, 256, 0};
+ return TRUE;
+ }
+
+ if (frame_packing->frame_packing_repetition_period != 1) {
+ GST_WARNING ("SEI: repetition_period != 1 is not unsupported");
+ return FALSE;
+ }
+
+ if (frame_packing->frame_packing_type > GST_H264_FRAME_PACKING_NONE) {
+ GST_WARNING ("SEI: unsupported frame_packing_type %d",
+ frame_packing->frame_packing_type);
+ return FALSE;
+ }
+
+ if (frame_packing->content_interpretation_type >= 3) {
+ GST_WARNING ("SEI: unsupported content_interpretation_type %d",
+ frame_packing->frame_packing_type);
+ return FALSE;
+ }
+
+ /* TODO: frame frame0/1_grid_position_x/y are ignored now. */
+
+ priv->stereo_info = (GstVaapiStereo3DInfo) {
+ GST_VIDEO_MULTIVIEW_MODE_MONO, GST_VIDEO_MULTIVIEW_FLAGS_NONE, 256, 0};
+
+ switch (frame_packing->frame_packing_type) {
+ case GST_H264_FRAME_PACKING_CHECKERBOARD_INTERLEAVING:
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD;
+ break;
+ case GST_H264_FRAME_PACKING_COLUMN_INTERLEAVING:
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED;
+ break;
+ case GST_H264_FRAME_PACKING_ROW_INTERLEAVING:
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
+ break;
+ case GST_H264_FRAME_PACKING_SIDE_BY_SIDE:
+ if (frame_packing->quincunx_sampling_flag) {
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX;
+ } else {
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
+ }
+ break;
+ case GST_H264_FRMAE_PACKING_TOP_BOTTOM:
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
+ break;
+ case GST_H264_FRAME_PACKING_TEMPORAL_INTERLEAVING:
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
+ break;
+ default:
+ priv->stereo_info.mode = GST_VIDEO_MULTIVIEW_MODE_MONO;
+ break;
+ }
+
+ /* Spec does not describe multi-IDs case, we just keep one valid */
+ priv->stereo_info.id = frame_packing->frame_packing_id;
+ priv->stereo_info.repetition_period =
+ frame_packing->frame_packing_repetition_period;
+
+ if (frame_packing->content_interpretation_type == 2)
+ frame_revert = TRUE;
+
+ if (frame_packing->frame_packing_type ==
+ GST_H264_FRAME_PACKING_TEMPORAL_INTERLEAVING) {
+ if (frame_packing->current_frame_is_frame0_flag) {
+ left = TRUE;
+ } else {
+ left = FALSE;
+ }
+
+ if (frame_revert)
+ left = !left;
+ }
+
+ if (!left)
+ priv->stereo_info.flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
+
+ if (frame_packing->frame_packing_type == GST_H264_FRAME_PACKING_SIDE_BY_SIDE
+ && frame_packing->spatial_flipping_flag) {
+ if (frame_packing->frame0_flipped_flag !=
+ ((priv->stereo_info.flags &
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST) != 0)) {
+ priv->stereo_info.flags |= GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED;
+ } else {
+ priv->stereo_info.flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED;
+ }
+ }
+ if (frame_packing->frame_packing_type == GST_H264_FRMAE_PACKING_TOP_BOTTOM
+ && frame_packing->spatial_flipping_flag !=
+ ((priv->stereo_info.flags &
+ GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST) != 0)) {
+ if (frame_packing->frame0_flipped_flag) {
+ priv->stereo_info.flags |= GST_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED;
+ } else {
+ priv->stereo_info.flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED;
+ }
+ }
+
+ if (saved_mode != priv->stereo_info.mode
+ || saved_flags != priv->stereo_info.flags) {
+ gst_vaapi_decoder_set_multiview_mode (GST_VAAPI_DECODER_CAST (decoder),
+ 2, priv->stereo_info.mode, priv->stereo_info.flags);
+ }
+
+ return TRUE;
+}
+
static GstVaapiDecoderStatus
decode_sei (GstVaapiDecoderH264 * decoder, GstVaapiDecoderUnit * unit)
{
@@ -1984,6 +2137,9 @@ decode_sei (GstVaapiDecoderH264 * decoder, GstVaapiDecoderUnit * unit)
priv->pic_structure = pic_timing->pic_struct;
break;
}
+ case GST_H264_SEI_FRAME_PACKING:
+ decode_sei_frame_packing (decoder, &sei->payload.frame_packing);
+ break;
default:
break;
}