mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
h265decoder: Drain decoder on new_sequence()
Holding previously decoded but not outputted pictures even after new_sequence is not a safe approach in various aspect. However, we cannot drain out DPB on new_sequence() unconditionally, because there is a case where decoder should drop decoded pictures if NoOutputOfPriorPicsFlag is set. To detect NoOutputOfPriorPicsFlag before the new_sequence() call, this patch splits decoding process into two path, one for nal unit parsing in order to detect NoOutputOfPriorPicsFlag and then each nal unit will be decoded. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1937>
This commit is contained in:
parent
9494509ee0
commit
3e49ff0ff5
2 changed files with 184 additions and 140 deletions
|
@ -82,6 +82,8 @@ struct _GstH265DecoderPrivate
|
||||||
guint8 cur_source_scan_type;
|
guint8 cur_source_scan_type;
|
||||||
guint8 cur_duplicate_flag;
|
guint8 cur_duplicate_flag;
|
||||||
|
|
||||||
|
gboolean no_output_of_prior_pics_flag;
|
||||||
|
|
||||||
/* vps/sps/pps of the current slice */
|
/* vps/sps/pps of the current slice */
|
||||||
const GstH265VPS *active_vps;
|
const GstH265VPS *active_vps;
|
||||||
const GstH265SPS *active_sps;
|
const GstH265SPS *active_sps;
|
||||||
|
@ -123,8 +125,20 @@ struct _GstH265DecoderPrivate
|
||||||
GArray *ref_pic_list_tmp;
|
GArray *ref_pic_list_tmp;
|
||||||
GArray *ref_pic_list0;
|
GArray *ref_pic_list0;
|
||||||
GArray *ref_pic_list1;
|
GArray *ref_pic_list1;
|
||||||
|
|
||||||
|
GArray *nalu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
GstH265SPS sps;
|
||||||
|
GstH265Slice slice;
|
||||||
|
} unit;
|
||||||
|
gboolean is_slice;
|
||||||
|
} GstH265DecoderNalUnit;
|
||||||
|
|
||||||
#define UPDATE_FLOW_RETURN(ret,new_ret) G_STMT_START { \
|
#define UPDATE_FLOW_RETURN(ret,new_ret) G_STMT_START { \
|
||||||
if (*(ret) == GST_FLOW_OK) \
|
if (*(ret) == GST_FLOW_OK) \
|
||||||
*(ret) = new_ret; \
|
*(ret) = new_ret; \
|
||||||
|
@ -156,6 +170,7 @@ static void gst_h265_decoder_clear_dpb (GstH265Decoder * self, gboolean flush);
|
||||||
static GstFlowReturn gst_h265_decoder_drain_internal (GstH265Decoder * self);
|
static GstFlowReturn gst_h265_decoder_drain_internal (GstH265Decoder * self);
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_h265_decoder_start_current_picture (GstH265Decoder * self);
|
gst_h265_decoder_start_current_picture (GstH265Decoder * self);
|
||||||
|
static void gst_h265_decoder_clear_nalu (GstH265DecoderNalUnit * nalu);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
||||||
|
@ -192,6 +207,10 @@ gst_h265_decoder_init (GstH265Decoder * self)
|
||||||
sizeof (GstH265Picture *), 32);
|
sizeof (GstH265Picture *), 32);
|
||||||
priv->ref_pic_list1 = g_array_sized_new (FALSE, TRUE,
|
priv->ref_pic_list1 = g_array_sized_new (FALSE, TRUE,
|
||||||
sizeof (GstH265Picture *), 32);
|
sizeof (GstH265Picture *), 32);
|
||||||
|
priv->nalu = g_array_sized_new (FALSE, TRUE, sizeof (GstH265DecoderNalUnit),
|
||||||
|
8);
|
||||||
|
g_array_set_clear_func (priv->nalu,
|
||||||
|
(GDestroyNotify) gst_h265_decoder_clear_nalu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -203,6 +222,7 @@ gst_h265_decoder_finalize (GObject * object)
|
||||||
g_array_unref (priv->ref_pic_list_tmp);
|
g_array_unref (priv->ref_pic_list_tmp);
|
||||||
g_array_unref (priv->ref_pic_list0);
|
g_array_unref (priv->ref_pic_list0);
|
||||||
g_array_unref (priv->ref_pic_list1);
|
g_array_unref (priv->ref_pic_list1);
|
||||||
|
g_array_unref (priv->nalu);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -249,24 +269,6 @@ gst_h265_decoder_stop (GstVideoDecoder * decoder)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_h265_decoder_parse_vps (GstH265Decoder * self, GstH265NalUnit * nalu)
|
|
||||||
{
|
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
|
||||||
GstH265VPS vps;
|
|
||||||
GstH265ParserResult pres;
|
|
||||||
|
|
||||||
pres = gst_h265_parser_parse_vps (priv->parser, nalu, &vps);
|
|
||||||
if (pres != GST_H265_PARSER_OK) {
|
|
||||||
GST_WARNING_OBJECT (self, "Failed to parse VPS, result %d", pres);
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "VPS parsed");
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_h265_decoder_is_crop_rect_changed (GstH265Decoder * self, GstH265SPS * sps)
|
gst_h265_decoder_is_crop_rect_changed (GstH265Decoder * self, GstH265SPS * sps)
|
||||||
{
|
{
|
||||||
|
@ -340,6 +342,14 @@ gst_h265_decoder_process_sps (GstH265Decoder * self, GstH265SPS * sps)
|
||||||
|
|
||||||
g_assert (klass->new_sequence);
|
g_assert (klass->new_sequence);
|
||||||
|
|
||||||
|
if (priv->no_output_of_prior_pics_flag) {
|
||||||
|
gst_h265_decoder_clear_dpb (self, FALSE);
|
||||||
|
} else {
|
||||||
|
ret = gst_h265_decoder_drain_internal (self);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = klass->new_sequence (self, sps, max_dpb_size);
|
ret = klass->new_sequence (self, sps, max_dpb_size);
|
||||||
if (ret != GST_FLOW_OK) {
|
if (ret != GST_FLOW_OK) {
|
||||||
GST_WARNING_OBJECT (self, "subclass does not want accept new sequence");
|
GST_WARNING_OBJECT (self, "subclass does not want accept new sequence");
|
||||||
|
@ -371,53 +381,7 @@ gst_h265_decoder_process_sps (GstH265Decoder * self, GstH265SPS * sps)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstH265ParserResult
|
||||||
gst_h265_decoder_parse_sps (GstH265Decoder * self, GstH265NalUnit * nalu)
|
|
||||||
{
|
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
|
||||||
GstH265SPS sps;
|
|
||||||
GstH265ParserResult pres;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
pres = gst_h265_parse_sps (priv->parser, nalu, &sps, TRUE);
|
|
||||||
if (pres != GST_H265_PARSER_OK) {
|
|
||||||
GST_WARNING_OBJECT (self, "Failed to parse SPS, result %d", pres);
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "SPS parsed");
|
|
||||||
|
|
||||||
ret = gst_h265_decoder_process_sps (self, &sps);
|
|
||||||
if (ret != GST_FLOW_OK) {
|
|
||||||
GST_WARNING_OBJECT (self, "Failed to process SPS");
|
|
||||||
} else if (gst_h265_parser_update_sps (priv->parser,
|
|
||||||
&sps) != GST_H265_PARSER_OK) {
|
|
||||||
GST_WARNING_OBJECT (self, "Failed to update SPS");
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_h265_decoder_parse_pps (GstH265Decoder * self, GstH265NalUnit * nalu)
|
|
||||||
{
|
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
|
||||||
GstH265PPS pps;
|
|
||||||
GstH265ParserResult pres;
|
|
||||||
|
|
||||||
pres = gst_h265_parser_parse_pps (priv->parser, nalu, &pps);
|
|
||||||
if (pres != GST_H265_PARSER_OK) {
|
|
||||||
GST_WARNING_OBJECT (self, "Failed to parse PPS, result %d", pres);
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "PPS parsed");
|
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_h265_decoder_parse_sei (GstH265Decoder * self, GstH265NalUnit * nalu)
|
gst_h265_decoder_parse_sei (GstH265Decoder * self, GstH265NalUnit * nalu)
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
|
@ -432,7 +396,7 @@ gst_h265_decoder_parse_sei (GstH265Decoder * self, GstH265NalUnit * nalu)
|
||||||
/* XXX: Ignore error from SEI parsing, it might be malformed bitstream,
|
/* XXX: Ignore error from SEI parsing, it might be malformed bitstream,
|
||||||
* or our fault. But shouldn't be critical */
|
* or our fault. But shouldn't be critical */
|
||||||
g_clear_pointer (&messages, g_array_unref);
|
g_clear_pointer (&messages, g_array_unref);
|
||||||
return GST_FLOW_OK;
|
return GST_H265_PARSER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < messages->len; i++) {
|
for (i = 0; i < messages->len; i++) {
|
||||||
|
@ -457,7 +421,7 @@ gst_h265_decoder_parse_sei (GstH265Decoder * self, GstH265NalUnit * nalu)
|
||||||
g_array_free (messages, TRUE);
|
g_array_free (messages, TRUE);
|
||||||
GST_LOG_OBJECT (self, "SEI parsed");
|
GST_LOG_OBJECT (self, "SEI parsed");
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_H265_PARSER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -631,31 +595,12 @@ gst_h265_decoder_preprocess_slice (GstH265Decoder * self, GstH265Slice * slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu)
|
gst_h265_decoder_process_slice (GstH265Decoder * self, GstH265Slice * slice)
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
GstH265ParserResult pres = GST_H265_PARSER_OK;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
memset (&priv->current_slice, 0, sizeof (GstH265Slice));
|
priv->current_slice = *slice;
|
||||||
|
|
||||||
pres = gst_h265_parser_parse_slice_hdr (priv->parser, nalu,
|
|
||||||
&priv->current_slice.header);
|
|
||||||
|
|
||||||
if (pres != GST_H265_PARSER_OK) {
|
|
||||||
GST_ERROR_OBJECT (self, "Failed to parse slice header, ret %d", pres);
|
|
||||||
memset (&priv->current_slice, 0, sizeof (GstH265Slice));
|
|
||||||
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTE: gst_h265_parser_parse_slice_hdr() allocates array
|
|
||||||
* GstH265SliceHdr::entry_point_offset_minus1 but we don't use it
|
|
||||||
* in this h265decoder baseclass at the moment
|
|
||||||
*/
|
|
||||||
gst_h265_slice_hdr_free (&priv->current_slice.header);
|
|
||||||
|
|
||||||
priv->current_slice.nalu = *nalu;
|
|
||||||
|
|
||||||
if (priv->current_slice.header.dependent_slice_segment_flag) {
|
if (priv->current_slice.header.dependent_slice_segment_flag) {
|
||||||
GstH265SliceHdr *slice_hdr = &priv->current_slice.header;
|
GstH265SliceHdr *slice_hdr = &priv->current_slice.header;
|
||||||
|
@ -713,24 +658,99 @@ gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu)
|
||||||
return gst_h265_decoder_decode_slice (self);
|
return gst_h265_decoder_decode_slice (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstH265ParserResult
|
||||||
gst_h265_decoder_decode_nal (GstH265Decoder * self, GstH265NalUnit * nalu)
|
gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu)
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstH265ParserResult pres;
|
||||||
|
GstH265Slice slice;
|
||||||
|
GstH265DecoderNalUnit decoder_nalu;
|
||||||
|
|
||||||
|
memset (&slice, 0, sizeof (GstH265Slice));
|
||||||
|
|
||||||
|
pres = gst_h265_parser_parse_slice_hdr (priv->parser, nalu, &slice.header);
|
||||||
|
if (pres != GST_H265_PARSER_OK)
|
||||||
|
return pres;
|
||||||
|
|
||||||
|
/* NOTE: gst_h265_parser_parse_slice_hdr() allocates array
|
||||||
|
* GstH265SliceHdr::entry_point_offset_minus1 but we don't use it
|
||||||
|
* in this h265decoder baseclass at the moment
|
||||||
|
*/
|
||||||
|
gst_h265_slice_hdr_free (&priv->current_slice.header);
|
||||||
|
slice.nalu = *nalu;
|
||||||
|
|
||||||
|
if (nalu->type >= GST_H265_NAL_SLICE_BLA_W_LP &&
|
||||||
|
nalu->type <= GST_H265_NAL_SLICE_CRA_NUT) {
|
||||||
|
slice.rap_pic_flag = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NoRaslOutputFlag == 1 if the current picture is
|
||||||
|
* 1) an IDR picture
|
||||||
|
* 2) a BLA picture
|
||||||
|
* 3) a CRA picture that is the first access unit in the bitstream
|
||||||
|
* 4) first picture that follows an end of sequence NAL unit in decoding order
|
||||||
|
* 5) has HandleCraAsBlaFlag == 1 (set by external means, so not considering )
|
||||||
|
*/
|
||||||
|
if (GST_H265_IS_NAL_TYPE_IDR (nalu->type) ||
|
||||||
|
GST_H265_IS_NAL_TYPE_BLA (nalu->type) ||
|
||||||
|
(GST_H265_IS_NAL_TYPE_CRA (nalu->type) && priv->new_bitstream) ||
|
||||||
|
priv->prev_nal_is_eos) {
|
||||||
|
slice.no_rasl_output_flag = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GST_H265_IS_NAL_TYPE_IRAP (nalu->type)) {
|
||||||
|
slice.intra_pic_flag = TRUE;
|
||||||
|
|
||||||
|
if (slice.no_rasl_output_flag && !priv->new_bitstream) {
|
||||||
|
/* C 3.2 */
|
||||||
|
slice.clear_dpb = TRUE;
|
||||||
|
if (nalu->type == GST_H265_NAL_SLICE_CRA_NUT) {
|
||||||
|
slice.no_output_of_prior_pics_flag = TRUE;
|
||||||
|
} else {
|
||||||
|
slice.no_output_of_prior_pics_flag =
|
||||||
|
slice.header.no_output_of_prior_pics_flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slice.no_output_of_prior_pics_flag)
|
||||||
|
priv->no_output_of_prior_pics_flag = TRUE;
|
||||||
|
|
||||||
|
decoder_nalu.unit.slice = slice;
|
||||||
|
decoder_nalu.is_slice = TRUE;
|
||||||
|
g_array_append_val (priv->nalu, decoder_nalu);
|
||||||
|
|
||||||
|
return GST_H265_PARSER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstH265ParserResult
|
||||||
|
gst_h265_decoder_parse_nalu (GstH265Decoder * self, GstH265NalUnit * nalu)
|
||||||
|
{
|
||||||
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
|
GstH265VPS vps;
|
||||||
|
GstH265SPS sps;
|
||||||
|
GstH265PPS pps;
|
||||||
|
GstH265ParserResult ret = GST_H265_PARSER_OK;
|
||||||
|
GstH265DecoderNalUnit decoder_nalu;
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "Parsed nal type: %d, offset %d, size %d",
|
GST_LOG_OBJECT (self, "Parsed nal type: %d, offset %d, size %d",
|
||||||
nalu->type, nalu->offset, nalu->size);
|
nalu->type, nalu->offset, nalu->size);
|
||||||
|
|
||||||
switch (nalu->type) {
|
switch (nalu->type) {
|
||||||
case GST_H265_NAL_VPS:
|
case GST_H265_NAL_VPS:
|
||||||
ret = gst_h265_decoder_parse_vps (self, nalu);
|
ret = gst_h265_parser_parse_vps (priv->parser, nalu, &vps);
|
||||||
break;
|
break;
|
||||||
case GST_H265_NAL_SPS:
|
case GST_H265_NAL_SPS:
|
||||||
ret = gst_h265_decoder_parse_sps (self, nalu);
|
ret = gst_h265_parser_parse_sps (priv->parser, nalu, &sps, TRUE);
|
||||||
|
if (ret != GST_H265_PARSER_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
memset (&decoder_nalu, 0, sizeof (GstH265DecoderNalUnit));
|
||||||
|
decoder_nalu.unit.sps = sps;
|
||||||
|
g_array_append_val (priv->nalu, decoder_nalu);
|
||||||
break;
|
break;
|
||||||
case GST_H265_NAL_PPS:
|
case GST_H265_NAL_PPS:
|
||||||
ret = gst_h265_decoder_parse_pps (self, nalu);
|
ret = gst_h265_parser_parse_pps (priv->parser, nalu, &pps);
|
||||||
break;
|
break;
|
||||||
case GST_H265_NAL_PREFIX_SEI:
|
case GST_H265_NAL_PREFIX_SEI:
|
||||||
case GST_H265_NAL_SUFFIX_SEI:
|
case GST_H265_NAL_SUFFIX_SEI:
|
||||||
|
@ -769,6 +789,16 @@ gst_h265_decoder_decode_nal (GstH265Decoder * self, GstH265NalUnit * nalu)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_h265_decoder_decode_nalu (GstH265Decoder * self,
|
||||||
|
GstH265DecoderNalUnit * nalu)
|
||||||
|
{
|
||||||
|
if (!nalu->is_slice)
|
||||||
|
return gst_h265_decoder_process_sps (self, &nalu->unit.sps);
|
||||||
|
|
||||||
|
return gst_h265_decoder_process_slice (self, &nalu->unit.slice);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_h265_decoder_format_from_caps (GstH265Decoder * self, GstCaps * caps,
|
gst_h265_decoder_format_from_caps (GstH265Decoder * self, GstCaps * caps,
|
||||||
GstH265DecoderFormat * format, GstH265DecoderAlign * align)
|
GstH265DecoderFormat * format, GstH265DecoderAlign * align)
|
||||||
|
@ -823,6 +853,9 @@ gst_h265_decoder_parse_codec_data (GstH265Decoder * self, const guint8 * data,
|
||||||
GstH265ParserResult pres;
|
GstH265ParserResult pres;
|
||||||
GstH265NalUnit nalu;
|
GstH265NalUnit nalu;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
GstH265VPS vps;
|
||||||
|
GstH265SPS sps;
|
||||||
|
GstH265PPS pps;
|
||||||
|
|
||||||
/* parse the hvcC data */
|
/* parse the hvcC data */
|
||||||
if (size < 23) {
|
if (size < 23) {
|
||||||
|
@ -860,24 +893,30 @@ gst_h265_decoder_parse_codec_data (GstH265Decoder * self, const guint8 * data,
|
||||||
|
|
||||||
switch (nalu.type) {
|
switch (nalu.type) {
|
||||||
case GST_H265_NAL_VPS:
|
case GST_H265_NAL_VPS:
|
||||||
ret = gst_h265_decoder_parse_vps (self, &nalu);
|
pres = gst_h265_parser_parse_vps (priv->parser, &nalu, &vps);
|
||||||
if (ret != GST_FLOW_OK) {
|
if (pres != GST_H265_PARSER_OK) {
|
||||||
GST_WARNING_OBJECT (self, "Failed to parse VPS");
|
GST_WARNING_OBJECT (self, "Failed to parse VPS");
|
||||||
return ret;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GST_H265_NAL_SPS:
|
case GST_H265_NAL_SPS:
|
||||||
ret = gst_h265_decoder_parse_sps (self, &nalu);
|
pres = gst_h265_parser_parse_sps (priv->parser, &nalu, &sps, TRUE);
|
||||||
if (ret != GST_FLOW_OK) {
|
if (pres != GST_H265_PARSER_OK) {
|
||||||
GST_WARNING_OBJECT (self, "Failed to parse SPS");
|
GST_WARNING_OBJECT (self, "Failed to parse SPS");
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gst_h265_decoder_process_sps (self, &sps);
|
||||||
|
if (ret != GST_FLOW_OK) {
|
||||||
|
GST_WARNING_OBJECT (self, "Failed to process SPS");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GST_H265_NAL_PPS:
|
case GST_H265_NAL_PPS:
|
||||||
ret = gst_h265_decoder_parse_pps (self, &nalu);
|
pres = gst_h265_parser_parse_pps (priv->parser, &nalu, &pps);
|
||||||
if (ret != GST_FLOW_OK) {
|
if (pres != GST_H265_PARSER_OK) {
|
||||||
GST_WARNING_OBJECT (self, "Failed to parse PPS");
|
GST_WARNING_OBJECT (self, "Failed to parse PPS");
|
||||||
return ret;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1010,26 +1049,11 @@ gst_h265_decoder_fill_picture_from_slice (GstH265Decoder * self,
|
||||||
const GstH265SliceHdr *slice_hdr = &slice->header;
|
const GstH265SliceHdr *slice_hdr = &slice->header;
|
||||||
const GstH265NalUnit *nalu = &slice->nalu;
|
const GstH265NalUnit *nalu = &slice->nalu;
|
||||||
|
|
||||||
if (nalu->type >= GST_H265_NAL_SLICE_BLA_W_LP &&
|
picture->RapPicFlag = slice->rap_pic_flag;
|
||||||
nalu->type <= GST_H265_NAL_SLICE_CRA_NUT)
|
picture->NoRaslOutputFlag = slice->no_rasl_output_flag;
|
||||||
picture->RapPicFlag = TRUE;
|
picture->IntraPicFlag = slice->intra_pic_flag;
|
||||||
|
picture->NoOutputOfPriorPicsFlag = slice->no_output_of_prior_pics_flag;
|
||||||
/* NoRaslOutputFlag == 1 if the current picture is
|
if (picture->IntraPicFlag) {
|
||||||
* 1) an IDR picture
|
|
||||||
* 2) a BLA picture
|
|
||||||
* 3) a CRA picture that is the first access unit in the bitstream
|
|
||||||
* 4) first picture that follows an end of sequence NAL unit in decoding order
|
|
||||||
* 5) has HandleCraAsBlaFlag == 1 (set by external means, so not considering )
|
|
||||||
*/
|
|
||||||
if (GST_H265_IS_NAL_TYPE_IDR (nalu->type) ||
|
|
||||||
GST_H265_IS_NAL_TYPE_BLA (nalu->type) ||
|
|
||||||
(GST_H265_IS_NAL_TYPE_CRA (nalu->type) && priv->new_bitstream) ||
|
|
||||||
priv->prev_nal_is_eos) {
|
|
||||||
picture->NoRaslOutputFlag = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_H265_IS_NAL_TYPE_IRAP (nalu->type)) {
|
|
||||||
picture->IntraPicFlag = TRUE;
|
|
||||||
priv->associated_irap_NoRaslOutputFlag = picture->NoRaslOutputFlag;
|
priv->associated_irap_NoRaslOutputFlag = picture->NoRaslOutputFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1555,21 +1579,12 @@ gst_h265_decoder_dpb_init (GstH265Decoder * self, const GstH265Slice * slice,
|
||||||
GstH265Picture * picture)
|
GstH265Picture * picture)
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
const GstH265SliceHdr *slice_hdr = &slice->header;
|
|
||||||
const GstH265NalUnit *nalu = &slice->nalu;
|
|
||||||
const GstH265SPS *sps = priv->active_sps;
|
const GstH265SPS *sps = priv->active_sps;
|
||||||
GstH265Picture *to_output;
|
GstH265Picture *to_output;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
/* C 3.2 */
|
/* C 3.2 */
|
||||||
if (GST_H265_IS_NAL_TYPE_IRAP (nalu->type) && picture->NoRaslOutputFlag
|
if (slice->clear_dpb) {
|
||||||
&& !priv->new_bitstream) {
|
|
||||||
if (nalu->type == GST_H265_NAL_SLICE_CRA_NUT)
|
|
||||||
picture->NoOutputOfPriorPicsFlag = TRUE;
|
|
||||||
else
|
|
||||||
picture->NoOutputOfPriorPicsFlag =
|
|
||||||
slice_hdr->no_output_of_prior_pics_flag;
|
|
||||||
|
|
||||||
if (picture->NoOutputOfPriorPicsFlag) {
|
if (picture->NoOutputOfPriorPicsFlag) {
|
||||||
GST_DEBUG_OBJECT (self, "Clear dpb");
|
GST_DEBUG_OBJECT (self, "Clear dpb");
|
||||||
gst_h265_decoder_clear_dpb (self, FALSE);
|
gst_h265_decoder_clear_dpb (self, FALSE);
|
||||||
|
@ -1742,6 +1757,9 @@ gst_h265_decoder_reset_frame_state (GstH265Decoder * self)
|
||||||
priv->cur_pic_struct = GST_H265_SEI_PIC_STRUCT_FRAME;
|
priv->cur_pic_struct = GST_H265_SEI_PIC_STRUCT_FRAME;
|
||||||
priv->cur_source_scan_type = 2;
|
priv->cur_source_scan_type = 2;
|
||||||
priv->cur_duplicate_flag = 0;
|
priv->cur_duplicate_flag = 0;
|
||||||
|
priv->no_output_of_prior_pics_flag = FALSE;
|
||||||
|
priv->current_frame = NULL;
|
||||||
|
g_array_set_size (priv->nalu, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -1755,16 +1773,17 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
||||||
GstH265ParserResult pres;
|
GstH265ParserResult pres;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
GstFlowReturn decode_ret = GST_FLOW_OK;
|
GstFlowReturn decode_ret = GST_FLOW_OK;
|
||||||
|
guint i;
|
||||||
|
|
||||||
GST_LOG_OBJECT (self,
|
GST_LOG_OBJECT (self,
|
||||||
"handle frame, PTS: %" GST_TIME_FORMAT ", DTS: %"
|
"handle frame, PTS: %" GST_TIME_FORMAT ", DTS: %"
|
||||||
GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (in_buf)),
|
GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (in_buf)),
|
||||||
GST_TIME_ARGS (GST_BUFFER_DTS (in_buf)));
|
GST_TIME_ARGS (GST_BUFFER_DTS (in_buf)));
|
||||||
|
|
||||||
priv->current_frame = frame;
|
|
||||||
|
|
||||||
gst_h265_decoder_reset_frame_state (self);
|
gst_h265_decoder_reset_frame_state (self);
|
||||||
|
|
||||||
|
priv->current_frame = frame;
|
||||||
|
|
||||||
if (!gst_buffer_map (in_buf, &map, GST_MAP_READ)) {
|
if (!gst_buffer_map (in_buf, &map, GST_MAP_READ)) {
|
||||||
GST_ELEMENT_ERROR (self, RESOURCE, READ,
|
GST_ELEMENT_ERROR (self, RESOURCE, READ,
|
||||||
("Failed to map memory for reading"), (NULL));
|
("Failed to map memory for reading"), (NULL));
|
||||||
|
@ -1776,8 +1795,10 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
||||||
pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
|
pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
|
||||||
map.data, 0, map.size, priv->nal_length_size, &nalu);
|
map.data, 0, map.size, priv->nal_length_size, &nalu);
|
||||||
|
|
||||||
while (pres == GST_H265_PARSER_OK && decode_ret == GST_FLOW_OK) {
|
while (pres == GST_H265_PARSER_OK) {
|
||||||
decode_ret = gst_h265_decoder_decode_nal (self, &nalu);
|
pres = gst_h265_decoder_parse_nalu (self, &nalu);
|
||||||
|
if (pres != GST_H265_PARSER_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
|
pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
|
||||||
map.data, nalu.offset + nalu.size, map.size, priv->nal_length_size,
|
map.data, nalu.offset + nalu.size, map.size, priv->nal_length_size,
|
||||||
|
@ -1790,19 +1811,26 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
||||||
if (pres == GST_H265_PARSER_NO_NAL_END)
|
if (pres == GST_H265_PARSER_NO_NAL_END)
|
||||||
pres = GST_H265_PARSER_OK;
|
pres = GST_H265_PARSER_OK;
|
||||||
|
|
||||||
while (pres == GST_H265_PARSER_OK && decode_ret == GST_FLOW_OK) {
|
while (pres == GST_H265_PARSER_OK) {
|
||||||
decode_ret = gst_h265_decoder_decode_nal (self, &nalu);
|
pres = gst_h265_decoder_parse_nalu (self, &nalu);
|
||||||
|
if (pres != GST_H265_PARSER_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
pres = gst_h265_parser_identify_nalu (priv->parser,
|
pres = gst_h265_parser_identify_nalu (priv->parser,
|
||||||
map.data, nalu.offset + nalu.size, map.size, &nalu);
|
map.data, nalu.offset + nalu.size, map.size, &nalu);
|
||||||
|
|
||||||
if (pres == GST_H265_PARSER_NO_NAL_END)
|
if (pres == GST_H265_PARSER_NO_NAL_END)
|
||||||
pres = GST_H265_PARSER_OK;
|
pres = GST_H265_PARSER_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nalu->len && decode_ret == GST_FLOW_OK; i++) {
|
||||||
|
GstH265DecoderNalUnit *decoder_nalu =
|
||||||
|
&g_array_index (priv->nalu, GstH265DecoderNalUnit, i);
|
||||||
|
decode_ret = gst_h265_decoder_decode_nalu (self, decoder_nalu);
|
||||||
|
}
|
||||||
|
|
||||||
gst_buffer_unmap (in_buf, &map);
|
gst_buffer_unmap (in_buf, &map);
|
||||||
priv->current_frame = NULL;
|
gst_h265_decoder_reset_frame_state (self);
|
||||||
|
|
||||||
if (decode_ret != GST_FLOW_OK) {
|
if (decode_ret != GST_FLOW_OK) {
|
||||||
if (decode_ret == GST_FLOW_ERROR) {
|
if (decode_ret == GST_FLOW_ERROR) {
|
||||||
|
@ -1832,6 +1860,15 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
||||||
return decode_ret;
|
return decode_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_h265_decoder_clear_nalu (GstH265DecoderNalUnit * nalu)
|
||||||
|
{
|
||||||
|
if (!nalu)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset (nalu, 0, sizeof (GstH265DecoderNalUnit));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_h265_decoder_set_process_ref_pic_lists:
|
* gst_h265_decoder_set_process_ref_pic_lists:
|
||||||
* @decoder: a #GstH265Decoder
|
* @decoder: a #GstH265Decoder
|
||||||
|
|
|
@ -48,6 +48,13 @@ struct _GstH265Slice
|
||||||
|
|
||||||
/* parsed nal unit (doesn't take ownership of raw data) */
|
/* parsed nal unit (doesn't take ownership of raw data) */
|
||||||
GstH265NalUnit nalu;
|
GstH265NalUnit nalu;
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
gboolean rap_pic_flag;
|
||||||
|
gboolean no_rasl_output_flag;
|
||||||
|
gboolean no_output_of_prior_pics_flag;
|
||||||
|
gboolean clear_dpb;
|
||||||
|
gboolean intra_pic_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstH265Picture
|
struct _GstH265Picture
|
||||||
|
|
Loading…
Reference in a new issue