diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 625b6f5259..10bf4273b2 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1076,6 +1076,64 @@ error: return GST_H264_PARSER_ERROR; } +/* Parse SEI frame_packing_arrangement() message */ +static GstH264ParserResult +gst_h264_parser_parse_frame_packing (GstH264NalParser * nalparser, + GstH264FramePacking * frame_packing, NalReader * nr, guint payload_size) +{ + guint8 frame_packing_extension_flag; + guint start_pos; + + GST_DEBUG ("parsing \"Frame Packing Arrangement\""); + + start_pos = nal_reader_get_pos (nr); + READ_UE (nr, frame_packing->frame_packing_id); + READ_UINT8 (nr, frame_packing->frame_packing_cancel_flag, 1); + + if (!frame_packing->frame_packing_cancel_flag) { + READ_UINT8 (nr, frame_packing->frame_packing_type, 7); + READ_UINT8 (nr, frame_packing->quincunx_sampling_flag, 1); + READ_UINT8 (nr, frame_packing->content_interpretation_type, 6); + READ_UINT8 (nr, frame_packing->spatial_flipping_flag, 1); + READ_UINT8 (nr, frame_packing->frame0_flipped_flag, 1); + READ_UINT8 (nr, frame_packing->field_views_flag, 1); + READ_UINT8 (nr, frame_packing->current_frame_is_frame0_flag, 1); + READ_UINT8 (nr, frame_packing->frame0_self_contained_flag, 1); + READ_UINT8 (nr, frame_packing->frame1_self_contained_flag, 1); + + if (!frame_packing->quincunx_sampling_flag && + frame_packing->frame_packing_type != + GST_H264_FRAME_PACKING_TEMPORAL_INTERLEAVING) { + READ_UINT8 (nr, frame_packing->frame0_grid_position_x, 4); + READ_UINT8 (nr, frame_packing->frame0_grid_position_y, 4); + READ_UINT8 (nr, frame_packing->frame1_grid_position_x, 4); + READ_UINT8 (nr, frame_packing->frame1_grid_position_y, 4); + } + + /* Skip frame_packing_arrangement_reserved_byte */ + if (!nal_reader_skip (nr, 8)) + goto error; + + READ_UE_ALLOWED (nr, frame_packing->frame_packing_repetition_period, 0, + 16384); + } + + /* All data that follows within a frame packing arrangement SEI message + after the value 1 for frame_packing_arrangement_extension_flag shall + be ignored (D.2.25) */ + READ_UINT8 (nr, frame_packing_extension_flag, 1); + if (!frame_packing_extension_flag) + goto error; + nal_reader_skip_long (nr, + payload_size - (nal_reader_get_pos (nr) - start_pos)); + + return GST_H264_PARSER_OK; + +error: + GST_WARNING ("error parsing \"Frame Packing Arrangement\""); + return GST_H264_PARSER_ERROR; +} + static GstH264ParserResult gst_h264_parser_parse_sei_message (GstH264NalParser * nalparser, NalReader * nr, GstH264SEIMessage * sei) @@ -1125,6 +1183,10 @@ gst_h264_parser_parse_sei_message (GstH264NalParser * nalparser, res = gst_h264_parser_parse_stereo_video_info (nalparser, &sei->payload.stereo_video_info, nr); break; + case GST_H264_SEI_FRAME_PACKING: + res = gst_h264_parser_parse_frame_packing (nalparser, + &sei->payload.frame_packing, nr, payload_size); + break; default: /* Just consume payloadSize bytes, which does not account for emulation prevention bytes */ diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h index 4af62676a8..12853d05bb 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.h +++ b/gst-libs/gst/codecparsers/gsth264parser.h @@ -170,6 +170,30 @@ typedef enum GST_H264_PARSER_NO_NAL_END } GstH264ParserResult; +/** + * GstH264FramePackingType: + * @GST_H264_FRAME_PACKING_NONE: A complete 2D frame without any frame packing + * @GST_H264_FRAME_PACKING_CHECKERBOARD_INTERLEAVING: Checkerboard + * based interleaving + * @GST_H264_FRAME_PACKING_COLUMN_INTERLEAVING: Column based interleaving + * @GST_H264_FRAME_PACKING_ROW_INTERLEAVING: Row based interleaving + * @GST_H264_FRAME_PACKING_SIDE_BY_SIDE: Side-by-side packing + * @GST_H264_FRMAE_PACKING_TOP_BOTTOM: Top-Bottom packing + * @GST_H264_FRAME_PACKING_TEMPORAL_INTERLEAVING: Temporal interleaving + * + * Frame packing arrangement types. + */ +typedef enum +{ + GST_H264_FRAME_PACKING_NONE = 6, + GST_H264_FRAME_PACKING_CHECKERBOARD_INTERLEAVING = 0, + GST_H264_FRAME_PACKING_COLUMN_INTERLEAVING = 1, + GST_H264_FRAME_PACKING_ROW_INTERLEAVING = 2, + GST_H264_FRAME_PACKING_SIDE_BY_SIDE = 3, + GST_H264_FRMAE_PACKING_TOP_BOTTOM = 4, + GST_H264_FRAME_PACKING_TEMPORAL_INTERLEAVING = 5 +} GstH264FramePackingType; + /** * GstH264SEIPayloadType: * @GST_H264_SEI_BUF_PERIOD: Buffering Period SEI Message @@ -184,7 +208,8 @@ typedef enum GST_H264_SEI_BUF_PERIOD = 0, GST_H264_SEI_PIC_TIMING = 1, GST_H264_SEI_RECOVERY_POINT = 6, - GST_H264_SEI_STEREO_VIDEO_INFO = 21 + GST_H264_SEI_STEREO_VIDEO_INFO = 21, + GST_H264_SEI_FRAME_PACKING = 45 /* and more... */ } GstH264SEIPayloadType; @@ -263,6 +288,7 @@ typedef struct _GstH264PicTiming GstH264PicTiming; typedef struct _GstH264BufferingPeriod GstH264BufferingPeriod; typedef struct _GstH264RecoveryPoint GstH264RecoveryPoint; typedef struct _GstH264StereoVideoInfo GstH264StereoVideoInfo; +typedef struct _GstH264FramePacking GstH264FramePacking; typedef struct _GstH264SEIMessage GstH264SEIMessage; /** @@ -844,6 +870,26 @@ struct _GstH264ClockTimestamp guint32 time_offset; }; +struct _GstH264FramePacking +{ + guint32 frame_packing_id; + guint8 frame_packing_cancel_flag; + guint8 frame_packing_type; /* GstH264FramePackingType */ + guint8 quincunx_sampling_flag; + guint8 content_interpretation_type; + guint8 spatial_flipping_flag; + guint8 frame0_flipped_flag; + guint8 field_views_flag; + guint8 current_frame_is_frame0_flag; + guint8 frame0_self_contained_flag; + guint8 frame1_self_contained_flag; + guint8 frame0_grid_position_x; + guint8 frame0_grid_position_y; + guint8 frame1_grid_position_x; + guint8 frame1_grid_position_y; + guint16 frame_packing_repetition_period; +}; + struct _GstH264StereoVideoInfo { guint8 field_views_flag; @@ -897,6 +943,7 @@ struct _GstH264SEIMessage GstH264PicTiming pic_timing; GstH264RecoveryPoint recovery_point; GstH264StereoVideoInfo stereo_video_info; + GstH264FramePacking frame_packing; /* ... could implement more */ } payload; }; diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index c9e9755aed..6e2208fafc 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -534,6 +534,10 @@ gst_h264_parse_process_sei (GstH264Parse * h264parse, GstH264NalUnit * nalu) case GST_H264_SEI_STEREO_VIDEO_INFO: GST_LOG_OBJECT (h264parse, "stereo video information message"); break; + case GST_H264_SEI_FRAME_PACKING: + GST_LOG_OBJECT (h264parse, "frame packing arrangement message: type %d", + sei.payload.frame_packing.frame_packing_type); + break; } } g_array_free (messages, TRUE);