mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
codecparsers: h264: parse MVC syntax elements.
https://bugzilla.gnome.org/show_bug.cgi?id=685215 Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
068cba5df6
commit
c1deab84e6
2 changed files with 177 additions and 13 deletions
|
@ -204,6 +204,8 @@ static gboolean
|
|||
gst_h264_parse_nalu_header (GstH264NalUnit * nalu)
|
||||
{
|
||||
guint8 *data = nalu->data + nalu->offset;
|
||||
guint8 svc_extension_flag;
|
||||
GstBitReader br;
|
||||
|
||||
if (nalu->size < 1)
|
||||
return FALSE;
|
||||
|
@ -211,6 +213,37 @@ gst_h264_parse_nalu_header (GstH264NalUnit * nalu)
|
|||
nalu->type = (data[0] & 0x1f);
|
||||
nalu->ref_idc = (data[0] & 0x60) >> 5;
|
||||
nalu->idr_pic_flag = (nalu->type == 5 ? 1 : 0);
|
||||
nalu->header_bytes = 1;
|
||||
|
||||
switch (nalu->type) {
|
||||
case GST_H264_NAL_PREFIX_UNIT:
|
||||
case GST_H264_NAL_SLICE_EXT:
|
||||
if (nalu->size < 4)
|
||||
return FALSE;
|
||||
gst_bit_reader_init (&br, nalu->data + nalu->offset + nalu->header_bytes,
|
||||
nalu->size - nalu->header_bytes);
|
||||
|
||||
svc_extension_flag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||
if (!svc_extension_flag) { /* MVC */
|
||||
GstH264NalUnitExtensionMVC *const mvc = &nalu->extension.mvc;
|
||||
|
||||
nalu->extension_type = GST_H264_NAL_EXTENSION_MVC;
|
||||
mvc->non_idr_flag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||
mvc->priority_id = gst_bit_reader_get_bits_uint8_unchecked (&br, 6);
|
||||
mvc->view_id = gst_bit_reader_get_bits_uint16_unchecked (&br, 10);
|
||||
mvc->temporal_id = gst_bit_reader_get_bits_uint8_unchecked (&br, 3);
|
||||
mvc->anchor_pic_flag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||
mvc->inter_view_flag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||
|
||||
/* Update IdrPicFlag (H.7.4.1.1) */
|
||||
nalu->idr_pic_flag = !mvc->non_idr_flag;
|
||||
}
|
||||
nalu->header_bytes += 3;
|
||||
break;
|
||||
default:
|
||||
nalu->extension_type = GST_H264_NAL_EXTENSION_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG ("Nal type %u, ref_idc %u", nalu->type, nalu->ref_idc);
|
||||
return TRUE;
|
||||
|
@ -497,7 +530,7 @@ error:
|
|||
|
||||
static gboolean
|
||||
slice_parse_ref_pic_list_modification_1 (GstH264SliceHdr * slice,
|
||||
NalReader * nr, guint list)
|
||||
NalReader * nr, guint list, gboolean is_mvc)
|
||||
{
|
||||
GstH264RefPicListModification *entries;
|
||||
guint8 *ref_pic_list_modification_flag, *n_ref_pic_list_modification;
|
||||
|
@ -526,7 +559,11 @@ slice_parse_ref_pic_list_modification_1 (GstH264SliceHdr * slice,
|
|||
slice->max_pic_num - 1);
|
||||
} else if (modification_of_pic_nums_idc == 2) {
|
||||
READ_UE (nr, entries[i].value.long_term_pic_num);
|
||||
}
|
||||
} else if (is_mvc && (modification_of_pic_nums_idc == 4 ||
|
||||
modification_of_pic_nums_idc == 5)) {
|
||||
READ_UE (nr, entries[i].value.abs_diff_view_idx_minus1);
|
||||
} else
|
||||
continue;
|
||||
entries[i++].modification_of_pic_nums_idc = modification_of_pic_nums_idc;
|
||||
}
|
||||
}
|
||||
|
@ -540,15 +577,16 @@ error:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
slice_parse_ref_pic_list_modification (GstH264SliceHdr * slice, NalReader * nr)
|
||||
slice_parse_ref_pic_list_modification (GstH264SliceHdr * slice, NalReader * nr,
|
||||
gboolean is_mvc)
|
||||
{
|
||||
if (!GST_H264_IS_I_SLICE (slice) && !GST_H264_IS_SI_SLICE (slice)) {
|
||||
if (!slice_parse_ref_pic_list_modification_1 (slice, nr, 0))
|
||||
if (!slice_parse_ref_pic_list_modification_1 (slice, nr, 0, is_mvc))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GST_H264_IS_B_SLICE (slice)) {
|
||||
if (!slice_parse_ref_pic_list_modification_1 (slice, nr, 1))
|
||||
if (!slice_parse_ref_pic_list_modification_1 (slice, nr, 1, is_mvc))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -1288,9 +1326,11 @@ gst_h264_parse_sps_data (NalReader * nr, GstH264SPS * sps,
|
|||
READ_UINT8 (nr, sps->constraint_set1_flag, 1);
|
||||
READ_UINT8 (nr, sps->constraint_set2_flag, 1);
|
||||
READ_UINT8 (nr, sps->constraint_set3_flag, 1);
|
||||
READ_UINT8 (nr, sps->constraint_set4_flag, 1);
|
||||
READ_UINT8 (nr, sps->constraint_set5_flag, 1);
|
||||
|
||||
/* skip reserved_zero_4bits */
|
||||
if (!nal_reader_skip (nr, 4))
|
||||
/* skip reserved_zero_2bits */
|
||||
if (!nal_reader_skip (nr, 2))
|
||||
goto error;
|
||||
|
||||
READ_UINT8 (nr, sps->level_idc, 8);
|
||||
|
@ -1300,7 +1340,8 @@ gst_h264_parse_sps_data (NalReader * nr, GstH264SPS * sps,
|
|||
if (sps->profile_idc == 100 || sps->profile_idc == 110 ||
|
||||
sps->profile_idc == 122 || sps->profile_idc == 244 ||
|
||||
sps->profile_idc == 44 || sps->profile_idc == 83 ||
|
||||
sps->profile_idc == 86) {
|
||||
sps->profile_idc == 86 || sps->profile_idc == 118 ||
|
||||
sps->profile_idc == 128) {
|
||||
READ_UE_ALLOWED (nr, sps->chroma_format_idc, 0, 3);
|
||||
if (sps->chroma_format_idc == 3)
|
||||
READ_UINT8 (nr, sps->separate_colour_plane_flag, 1);
|
||||
|
@ -1449,7 +1490,8 @@ gst_h264_parse_sps (GstH264NalUnit * nalu, GstH264SPS * sps,
|
|||
INITIALIZE_DEBUG_CATEGORY;
|
||||
GST_DEBUG ("parsing SPS");
|
||||
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size - 1);
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + nalu->header_bytes,
|
||||
nalu->size - nalu->header_bytes);
|
||||
|
||||
if (!gst_h264_parse_sps_data (&nr, sps, parse_vui_params))
|
||||
goto error;
|
||||
|
@ -1464,6 +1506,67 @@ error:
|
|||
return GST_H264_PARSER_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h264_parser_parse_subset_sps:
|
||||
* @nalparser: a #GstH264NalParser
|
||||
* @nalu: The #GST_H264_NAL_SUBSET_SPS #GstH264NalUnit to parse
|
||||
* @sps: The #GstH264SPS to fill.
|
||||
* @parse_vui_params: Whether to parse the vui_params or not
|
||||
*
|
||||
* Parses @data, and fills in the @sps structure.
|
||||
*
|
||||
* Returns: a #GstH264ParserResult
|
||||
*/
|
||||
GstH264ParserResult
|
||||
gst_h264_parser_parse_subset_sps (GstH264NalParser * nalparser,
|
||||
GstH264NalUnit * nalu, GstH264SPS * sps, gboolean parse_vui_params)
|
||||
{
|
||||
GstH264ParserResult res;
|
||||
|
||||
res = gst_h264_parse_subset_sps (nalu, sps, parse_vui_params);
|
||||
if (res == GST_H264_PARSER_OK) {
|
||||
GST_DEBUG ("adding sequence parameter set with id: %d to array", sps->id);
|
||||
|
||||
nalparser->sps[sps->id] = *sps;
|
||||
nalparser->last_sps = &nalparser->sps[sps->id];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h264_parse_subset_sps:
|
||||
* @nalu: The #GST_H264_NAL_SUBSET_SPS #GstH264NalUnit to parse
|
||||
* @sps: The #GstH264SPS to fill.
|
||||
* @parse_vui_params: Whether to parse the vui_params or not
|
||||
*
|
||||
* Parses @data, and fills in the @sps structure.
|
||||
*
|
||||
* Returns: a #GstH264ParserResult
|
||||
*/
|
||||
GstH264ParserResult
|
||||
gst_h264_parse_subset_sps (GstH264NalUnit * nalu, GstH264SPS * sps,
|
||||
gboolean parse_vui_params)
|
||||
{
|
||||
NalReader nr;
|
||||
|
||||
INITIALIZE_DEBUG_CATEGORY;
|
||||
GST_DEBUG ("parsing Subset SPS");
|
||||
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + nalu->header_bytes,
|
||||
nalu->size - nalu->header_bytes);
|
||||
|
||||
if (!gst_h264_parse_sps_data (&nr, sps, parse_vui_params))
|
||||
goto error;
|
||||
|
||||
sps->valid = TRUE;
|
||||
return GST_H264_PARSER_OK;
|
||||
|
||||
error:
|
||||
GST_WARNING ("error parsing \"Subset sequence parameter set\"");
|
||||
sps->valid = FALSE;
|
||||
return GST_H264_PARSER_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h264_parse_pps:
|
||||
* @nalparser: a #GstH264NalParser
|
||||
|
@ -1491,7 +1594,8 @@ gst_h264_parse_pps (GstH264NalParser * nalparser, GstH264NalUnit * nalu,
|
|||
INITIALIZE_DEBUG_CATEGORY;
|
||||
GST_DEBUG ("parsing PPS");
|
||||
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size - 1);
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + nalu->header_bytes,
|
||||
nalu->size - nalu->header_bytes);
|
||||
|
||||
READ_UE_ALLOWED (&nr, pps->id, 0, GST_H264_MAX_PPS_COUNT - 1);
|
||||
READ_UE_ALLOWED (&nr, sps_id, 0, GST_H264_MAX_SPS_COUNT - 1);
|
||||
|
@ -1676,7 +1780,8 @@ gst_h264_parser_parse_slice_hdr (GstH264NalParser * nalparser,
|
|||
}
|
||||
|
||||
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size - 1);
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + nalu->header_bytes,
|
||||
nalu->size - nalu->header_bytes);
|
||||
|
||||
READ_UE (&nr, slice->first_mb_in_slice);
|
||||
READ_UE (&nr, slice->type);
|
||||
|
@ -1768,7 +1873,8 @@ gst_h264_parser_parse_slice_hdr (GstH264NalParser * nalparser,
|
|||
}
|
||||
}
|
||||
|
||||
if (!slice_parse_ref_pic_list_modification (slice, &nr))
|
||||
if (!slice_parse_ref_pic_list_modification (slice, &nr,
|
||||
GST_H264_IS_MVC_NALU (nalu)))
|
||||
goto error;
|
||||
|
||||
if ((pps->weighted_pred_flag && (GST_H264_IS_P_SLICE (slice)
|
||||
|
@ -1846,7 +1952,8 @@ gst_h264_parser_parse_sei (GstH264NalParser * nalparser, GstH264NalUnit * nalu,
|
|||
GstH264ParserResult res;
|
||||
|
||||
GST_DEBUG ("parsing SEI nal");
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + 1, nalu->size - 1);
|
||||
nal_reader_init (&nr, nalu->data + nalu->offset + nalu->header_bytes,
|
||||
nalu->size - nalu->header_bytes);
|
||||
*messages = g_array_new (FALSE, FALSE, sizeof (GstH264SEIMessage));
|
||||
|
||||
do {
|
||||
|
|
|
@ -48,6 +48,9 @@ G_BEGIN_DECLS
|
|||
#define GST_H264_IS_SP_SLICE(slice) (((slice)->type % 5) == GST_H264_SP_SLICE)
|
||||
#define GST_H264_IS_SI_SLICE(slice) (((slice)->type % 5) == GST_H264_SI_SLICE)
|
||||
|
||||
#define GST_H264_IS_MVC_NALU(nalu) \
|
||||
((nalu)->extension_type == GST_H264_NAL_EXTENSION_MVC)
|
||||
|
||||
/**
|
||||
* GstH264Profile:
|
||||
* @GST_H264_PROFILE_BASELINE: Baseline profile (A.2.1)
|
||||
|
@ -131,6 +134,19 @@ typedef enum
|
|||
GST_H264_NAL_SLICE_EXT = 20
|
||||
} GstH264NalUnitType;
|
||||
|
||||
/**
|
||||
* GstH264NalUnitExtensionType:
|
||||
* @GST_H264_NAL_EXTENSION_NONE: No NAL unit header extension is available
|
||||
* @GST_H264_NAL_EXTENSION_MVC: NAL unit header extension for MVC (Annex H)
|
||||
*
|
||||
* Indicates the type of H.264 NAL unit extension.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GST_H264_NAL_EXTENSION_NONE = 0,
|
||||
GST_H264_NAL_EXTENSION_MVC,
|
||||
} GstH264NalUnitExtensionType;
|
||||
|
||||
/**
|
||||
* GstH264ParserResult:
|
||||
* @GST_H264_PARSER_OK: The parsing succeded
|
||||
|
@ -221,6 +237,7 @@ typedef enum
|
|||
typedef struct _GstH264NalParser GstH264NalParser;
|
||||
|
||||
typedef struct _GstH264NalUnit GstH264NalUnit;
|
||||
typedef struct _GstH264NalUnitExtensionMVC GstH264NalUnitExtensionMVC;
|
||||
|
||||
typedef struct _GstH264SPS GstH264SPS;
|
||||
typedef struct _GstH264PPS GstH264PPS;
|
||||
|
@ -239,6 +256,29 @@ typedef struct _GstH264BufferingPeriod GstH264BufferingPeriod;
|
|||
typedef struct _GstH264RecoveryPoint GstH264RecoveryPoint;
|
||||
typedef struct _GstH264SEIMessage GstH264SEIMessage;
|
||||
|
||||
/**
|
||||
* GstH264NalUnitExtensionMVC:
|
||||
* @non_idr_flag: If equal to 0, it specifies that the current access
|
||||
* unit is an IDR access unit
|
||||
* @priority_id: The priority identifier for the NAL unit
|
||||
* @view_id: The view identifier for the NAL unit
|
||||
* @temporal_id: The temporal identifier for the NAL unit
|
||||
* @anchor_pic_flag: If equal to 1, it specifies that the current
|
||||
* access unit is an anchor access unit
|
||||
* @inter_view_flag: If equal to 0, it specifies that the current view
|
||||
* component is not used for inter-view prediction by any other view
|
||||
* component in the current access unit
|
||||
*/
|
||||
struct _GstH264NalUnitExtensionMVC
|
||||
{
|
||||
guint8 non_idr_flag;
|
||||
guint8 priority_id;
|
||||
guint16 view_id;
|
||||
guint8 temporal_id;
|
||||
guint8 anchor_pic_flag;
|
||||
guint8 inter_view_flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH264NalUnit:
|
||||
* @ref_idc: not equal to 0 specifies that the content of the NAL unit
|
||||
|
@ -257,6 +297,7 @@ typedef struct _GstH264SEIMessage GstH264SEIMessage;
|
|||
* @valid: If the nal unit is valid, which means it has
|
||||
* already been parsed
|
||||
* @data: The data from which the Nalu has been parsed
|
||||
* @header_bytes: The size of the NALU header in bytes
|
||||
*
|
||||
* Structure defining the Nal unit headers
|
||||
*/
|
||||
|
@ -273,6 +314,12 @@ struct _GstH264NalUnit
|
|||
gboolean valid;
|
||||
|
||||
guint8 *data;
|
||||
|
||||
guint8 header_bytes;
|
||||
guint8 extension_type;
|
||||
union {
|
||||
GstH264NalUnitExtensionMVC mvc;
|
||||
} extension;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -439,6 +486,8 @@ struct _GstH264SPS
|
|||
guint8 constraint_set1_flag;
|
||||
guint8 constraint_set2_flag;
|
||||
guint8 constraint_set3_flag;
|
||||
guint8 constraint_set4_flag;
|
||||
guint8 constraint_set5_flag;
|
||||
guint8 level_idc;
|
||||
|
||||
guint8 chroma_format_idc;
|
||||
|
@ -556,6 +605,8 @@ struct _GstH264RefPicListModification
|
|||
guint32 abs_diff_pic_num_minus1;
|
||||
/* if modification_of_pic_nums_idc == 2 */
|
||||
guint32 long_term_pic_num;
|
||||
/* if modification_of_pic_nums_idc == 4 || 5 */
|
||||
guint32 abs_diff_view_idx_minus1;
|
||||
} value;
|
||||
};
|
||||
|
||||
|
@ -768,6 +819,9 @@ GstH264ParserResult gst_h264_parser_parse_slice_hdr (GstH264NalParser *nalpars
|
|||
GstH264SliceHdr *slice, gboolean parse_pred_weight_table,
|
||||
gboolean parse_dec_ref_pic_marking);
|
||||
|
||||
GstH264ParserResult gst_h264_parser_parse_subset_sps (GstH264NalParser *nalparser, GstH264NalUnit *nalu,
|
||||
GstH264SPS *sps, gboolean parse_vui_params);
|
||||
|
||||
GstH264ParserResult gst_h264_parser_parse_sps (GstH264NalParser *nalparser, GstH264NalUnit *nalu,
|
||||
GstH264SPS *sps, gboolean parse_vui_params);
|
||||
|
||||
|
@ -779,6 +833,9 @@ GstH264ParserResult gst_h264_parser_parse_sei (GstH264NalParser *nalpars
|
|||
|
||||
void gst_h264_nal_parser_free (GstH264NalParser *nalparser);
|
||||
|
||||
GstH264ParserResult gst_h264_parse_subset_sps (GstH264NalUnit *nalu,
|
||||
GstH264SPS *sps, gboolean parse_vui_params);
|
||||
|
||||
GstH264ParserResult gst_h264_parse_sps (GstH264NalUnit *nalu,
|
||||
GstH264SPS *sps, gboolean parse_vui_params);
|
||||
|
||||
|
|
Loading…
Reference in a new issue