mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-23 06:26:23 +00:00
h265decoder: Sync with the H264 implementation
This ensures that we get the last reference to picture being outputed, avoiding GstBuffer structure copies and simplifying the buffer management. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1713>
This commit is contained in:
parent
f615677051
commit
f330b5ae62
6 changed files with 286 additions and 125 deletions
|
@ -77,7 +77,7 @@ struct _GstH265DecoderPrivate
|
|||
GstH265Picture *current_picture;
|
||||
GstVideoCodecFrame *current_frame;
|
||||
|
||||
/* Slice (slice header + nalu) currently being processed/decodec */
|
||||
/* Slice (slice header + nalu) currently being processed/decoded */
|
||||
GstH265Slice current_slice;
|
||||
GstH265Slice prev_slice;
|
||||
GstH265Slice prev_independent_slice;
|
||||
|
@ -101,6 +101,9 @@ struct _GstH265DecoderPrivate
|
|||
gboolean associated_irap_NoRaslOutputFlag;
|
||||
gboolean new_bitstream;
|
||||
gboolean prev_nal_is_eos;
|
||||
|
||||
/* Cached array to handle pictures to be outputted */
|
||||
GArray *to_output;
|
||||
};
|
||||
|
||||
#define parent_class gst_h265_decoder_parent_class
|
||||
|
@ -110,6 +113,8 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstH265Decoder, gst_h265_decoder,
|
|||
GST_DEBUG_CATEGORY_INIT (gst_h265_decoder_debug, "h265decoder", 0,
|
||||
"H.265 Video Decoder"));
|
||||
|
||||
static void gst_h265_decoder_finalize (GObject * object);
|
||||
|
||||
static gboolean gst_h265_decoder_start (GstVideoDecoder * decoder);
|
||||
static gboolean gst_h265_decoder_stop (GstVideoDecoder * decoder);
|
||||
static gboolean gst_h265_decoder_set_format (GstVideoDecoder * decoder,
|
||||
|
@ -122,14 +127,16 @@ static GstFlowReturn gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
|||
|
||||
static gboolean gst_h265_decoder_finish_current_picture (GstH265Decoder * self);
|
||||
static void gst_h265_decoder_clear_dpb (GstH265Decoder * self);
|
||||
static gboolean
|
||||
gst_h265_decoder_output_all_remaining_pics (GstH265Decoder * self);
|
||||
static gboolean gst_h265_decoder_drain_internal (GstH265Decoder * self);
|
||||
static gboolean gst_h265_decoder_start_current_picture (GstH265Decoder * self);
|
||||
|
||||
static void
|
||||
gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
||||
{
|
||||
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = GST_DEBUG_FUNCPTR (gst_h265_decoder_finalize);
|
||||
|
||||
decoder_class->start = GST_DEBUG_FUNCPTR (gst_h265_decoder_start);
|
||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h265_decoder_stop);
|
||||
|
@ -144,9 +151,27 @@ gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
|||
static void
|
||||
gst_h265_decoder_init (GstH265Decoder * self)
|
||||
{
|
||||
GstH265DecoderPrivate *priv;
|
||||
|
||||
gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
|
||||
|
||||
self->priv = gst_h265_decoder_get_instance_private (self);
|
||||
self->priv = priv = gst_h265_decoder_get_instance_private (self);
|
||||
|
||||
priv->to_output = g_array_sized_new (FALSE, TRUE,
|
||||
sizeof (GstH265Picture *), 16);
|
||||
g_array_set_clear_func (priv->to_output,
|
||||
(GDestroyNotify) gst_h265_picture_clear);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h265_decoder_finalize (GObject * object)
|
||||
{
|
||||
GstH265Decoder *self = GST_H265_DECODER (object);
|
||||
GstH265DecoderPrivate *priv = self->priv;
|
||||
|
||||
g_array_unref (priv->to_output);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -336,6 +361,7 @@ gst_h265_decoder_decode_slice (GstH265Decoder * self)
|
|||
|
||||
g_assert (klass->decode_slice);
|
||||
|
||||
/* FIXME ref_pic_list0, ref_pic_list1 */
|
||||
return klass->decode_slice (self, picture, slice);
|
||||
}
|
||||
|
||||
|
@ -398,20 +424,19 @@ gst_h265_decoder_parse_slice (GstH265Decoder * self, GstH265NalUnit * nalu,
|
|||
/* This allows accessing the frame from the picture. */
|
||||
picture->system_frame_number = priv->current_frame->system_frame_number;
|
||||
|
||||
priv->current_picture = picture;
|
||||
g_assert (priv->current_frame);
|
||||
|
||||
if (klass->new_picture)
|
||||
ret = klass->new_picture (self, picture);
|
||||
ret = klass->new_picture (self, priv->current_frame, picture);
|
||||
|
||||
if (!ret) {
|
||||
GST_ERROR_OBJECT (self, "subclass does not want accept new picture");
|
||||
priv->current_picture = NULL;
|
||||
gst_h265_picture_unref (picture);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->current_picture = picture;
|
||||
gst_video_codec_frame_set_user_data (priv->current_frame,
|
||||
gst_h265_picture_ref (priv->current_picture),
|
||||
(GDestroyNotify) gst_h265_picture_unref);
|
||||
|
||||
if (!gst_h265_decoder_start_current_picture (self)) {
|
||||
GST_ERROR_OBJECT (self, "start picture failed");
|
||||
return FALSE;
|
||||
|
@ -700,8 +725,8 @@ gst_h265_decoder_drain (GstVideoDecoder * decoder)
|
|||
GstH265DecoderPrivate *priv = self->priv;
|
||||
|
||||
priv->last_ret = GST_FLOW_OK;
|
||||
gst_h265_decoder_output_all_remaining_pics (self);
|
||||
gst_h265_decoder_clear_dpb (self);
|
||||
/* dpb will be cleared by this method */
|
||||
gst_h265_decoder_drain_internal (self);
|
||||
|
||||
return priv->last_ret;
|
||||
}
|
||||
|
@ -1121,13 +1146,17 @@ gst_h265_decoder_clear_dpb (GstH265Decoder * self)
|
|||
|
||||
static void
|
||||
gst_h265_decoder_do_output_picture (GstH265Decoder * self,
|
||||
GstH265Picture * picture)
|
||||
GstH265Picture * picture, gboolean clear_dpb)
|
||||
{
|
||||
GstH265DecoderPrivate *priv = self->priv;
|
||||
GstH265DecoderClass *klass;
|
||||
GstVideoCodecFrame *frame = NULL;
|
||||
|
||||
picture->outputted = TRUE;
|
||||
|
||||
if (clear_dpb && !picture->ref)
|
||||
gst_h265_dpb_delete_by_poc (priv->dpb, picture->pic_order_cnt);
|
||||
|
||||
if (picture->pic_order_cnt < priv->last_output_poc) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"Outputting out of order %d -> %d, likely a broken stream",
|
||||
|
@ -1136,50 +1165,69 @@ gst_h265_decoder_do_output_picture (GstH265Decoder * self,
|
|||
|
||||
priv->last_output_poc = picture->pic_order_cnt;
|
||||
|
||||
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
||||
picture->system_frame_number);
|
||||
|
||||
if (!frame) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"No available codec frame with frame number %d",
|
||||
picture->system_frame_number);
|
||||
priv->last_ret = GST_FLOW_ERROR;
|
||||
gst_h265_picture_unref (picture);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
klass = GST_H265_DECODER_GET_CLASS (self);
|
||||
|
||||
g_assert (klass->output_picture);
|
||||
priv->last_ret = klass->output_picture (self, picture);
|
||||
priv->last_ret = klass->output_picture (self, frame, picture);
|
||||
}
|
||||
|
||||
static gint
|
||||
poc_asc_compare (const GstH265Picture * a, const GstH265Picture * b)
|
||||
poc_asc_compare (const GstH265Picture ** a, const GstH265Picture ** b)
|
||||
{
|
||||
return a->pic_order_cnt > b->pic_order_cnt;
|
||||
return (*a)->pic_order_cnt > (*b)->pic_order_cnt;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h265_decoder_output_all_remaining_pics (GstH265Decoder * self)
|
||||
gst_h265_decoder_drain_internal (GstH265Decoder * self)
|
||||
{
|
||||
GstH265DecoderPrivate *priv = self->priv;
|
||||
GList *to_output = NULL;
|
||||
GList *iter;
|
||||
GArray *to_output = priv->to_output;
|
||||
|
||||
gst_h265_dpb_get_pictures_not_outputted (priv->dpb, &to_output);
|
||||
gst_h265_dpb_delete_outputted (priv->dpb);
|
||||
gst_h265_dpb_get_pictures_not_outputted (priv->dpb, to_output);
|
||||
g_array_sort (to_output, (GCompareFunc) poc_asc_compare);
|
||||
|
||||
to_output = g_list_sort (to_output, (GCompareFunc) poc_asc_compare);
|
||||
while (to_output->len) {
|
||||
GstH265Picture *picture = g_array_index (to_output, GstH265Picture *, 0);
|
||||
|
||||
for (iter = to_output; iter; iter = g_list_next (iter)) {
|
||||
GstH265Picture *picture = (GstH265Picture *) iter->data;
|
||||
/* We want the last reference when outputing so take a ref and then remove
|
||||
* from both arrays. */
|
||||
gst_h265_picture_ref (picture);
|
||||
g_array_remove_index (to_output, 0);
|
||||
gst_h265_dpb_delete_by_poc (priv->dpb, picture->pic_order_cnt);
|
||||
|
||||
GST_LOG_OBJECT (self, "Output picture %p (poc %d)", picture,
|
||||
picture->pic_order_cnt);
|
||||
gst_h265_decoder_do_output_picture (self, picture);
|
||||
gst_h265_decoder_do_output_picture (self, picture, FALSE);
|
||||
picture = NULL;
|
||||
}
|
||||
|
||||
if (to_output)
|
||||
g_list_free_full (to_output, (GDestroyNotify) gst_h265_picture_unref);
|
||||
|
||||
g_array_set_size (to_output, 0);
|
||||
gst_h265_dpb_clear (priv->dpb);
|
||||
priv->last_output_poc = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h265_decoder_check_latency_count (GList * list, guint32 max_latency)
|
||||
gst_h265_decoder_check_latency_count (GArray * array, guint32 max_latency)
|
||||
{
|
||||
GList *iter;
|
||||
gint i;
|
||||
|
||||
for (iter = list; iter; iter = g_list_next (iter)) {
|
||||
GstH265Picture *pic = (GstH265Picture *) iter->data;
|
||||
for (i = 0; i < array->len; i++) {
|
||||
GstH265Picture *pic = g_array_index (array, GstH265Picture *, i);
|
||||
if (!pic->outputted && pic->pic_latency_cnt >= max_latency)
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1263,24 +1311,22 @@ gst_h265_decoder_finish_picture (GstH265Decoder * self,
|
|||
{
|
||||
GstH265DecoderPrivate *priv = self->priv;
|
||||
const GstH265SPS *sps = priv->active_sps;
|
||||
GList *not_outputted = NULL;
|
||||
GArray *not_outputted = priv->to_output;
|
||||
guint num_remaining;
|
||||
GList *iter;
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
gint i;
|
||||
#endif
|
||||
|
||||
GST_LOG_OBJECT (self,
|
||||
"Finishing picture %p (poc %d), entries in DPB %d",
|
||||
picture, picture->pic_order_cnt, gst_h265_dpb_get_size (priv->dpb));
|
||||
|
||||
/* Get all pictures that haven't been outputted yet */
|
||||
gst_h265_dpb_get_pictures_not_outputted (priv->dpb, ¬_outputted);
|
||||
gst_h265_dpb_get_pictures_not_outputted (priv->dpb, not_outputted);
|
||||
|
||||
/* C.5.2.3 */
|
||||
if (picture->output_flag) {
|
||||
for (iter = not_outputted; iter; iter = g_list_next (iter)) {
|
||||
GstH265Picture *other = GST_H265_PICTURE (iter->data);
|
||||
for (i = 0; i < not_outputted->len; i++) {
|
||||
GstH265Picture *other =
|
||||
g_array_index (not_outputted, GstH265Picture *, i);
|
||||
|
||||
if (!other->outputted)
|
||||
other->pic_latency_cnt++;
|
||||
|
@ -1297,40 +1343,29 @@ gst_h265_decoder_finish_picture (GstH265Decoder * self,
|
|||
picture->long_term = FALSE;
|
||||
|
||||
/* Include the one we've just decoded */
|
||||
if (picture->output_flag) {
|
||||
not_outputted =
|
||||
g_list_append (not_outputted, gst_h265_picture_ref (picture));
|
||||
}
|
||||
|
||||
/* Add to dpb and transfer ownership */
|
||||
gst_h265_dpb_add (priv->dpb, picture);
|
||||
if (picture->output_flag)
|
||||
g_array_append_val (not_outputted, picture);
|
||||
|
||||
/* for debugging */
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
GST_TRACE_OBJECT (self, "Before sorting not outputted list");
|
||||
i = 0;
|
||||
for (iter = not_outputted; iter; iter = g_list_next (iter)) {
|
||||
GstH265Picture *tmp = (GstH265Picture *) iter->data;
|
||||
|
||||
for (i = 0; i < not_outputted->len; i++) {
|
||||
GstH265Picture *tmp = g_array_index (not_outputted, GstH265Picture *, i);
|
||||
GST_TRACE_OBJECT (self,
|
||||
"\t%dth picture %p (poc %d)", i, tmp, tmp->pic_order_cnt);
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sort in output order */
|
||||
not_outputted = g_list_sort (not_outputted, (GCompareFunc) poc_asc_compare);
|
||||
g_array_sort (not_outputted, (GCompareFunc) poc_asc_compare);
|
||||
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
GST_TRACE_OBJECT (self,
|
||||
"After sorting not outputted list in poc ascending order");
|
||||
i = 0;
|
||||
for (iter = not_outputted; iter; iter = g_list_next (iter)) {
|
||||
GstH265Picture *tmp = (GstH265Picture *) iter->data;
|
||||
|
||||
for (i = 0; i < not_outputted->len; i++) {
|
||||
GstH265Picture *tmp = g_array_index (not_outputted, GstH265Picture *, i);
|
||||
GST_TRACE_OBJECT (self,
|
||||
"\t%dth picture %p (poc %d)", i, tmp, tmp->pic_order_cnt);
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1339,36 +1374,61 @@ gst_h265_decoder_finish_picture (GstH265Decoder * self,
|
|||
* in DPB afterwards would at least be equal to max_num_reorder_frames.
|
||||
* If the outputted picture is not a reference picture, it doesn't have
|
||||
* to remain in the DPB and can be removed */
|
||||
iter = not_outputted;
|
||||
num_remaining = g_list_length (not_outputted);
|
||||
num_remaining = not_outputted->len;
|
||||
|
||||
while (num_remaining > sps->max_num_reorder_pics[sps->max_sub_layers_minus1]
|
||||
|| (num_remaining &&
|
||||
sps->max_latency_increase_plus1[sps->max_sub_layers_minus1] &&
|
||||
gst_h265_decoder_check_latency_count (iter,
|
||||
gst_h265_decoder_check_latency_count (not_outputted,
|
||||
priv->SpsMaxLatencyPictures))) {
|
||||
GstH265Picture *to_output = GST_H265_PICTURE (iter->data);
|
||||
gboolean clear_dpb = TRUE;
|
||||
GstH265Picture *to_output =
|
||||
g_array_index (not_outputted, GstH265Picture *, 0);
|
||||
|
||||
gst_h265_picture_ref (to_output);
|
||||
g_array_remove_index (not_outputted, 0);
|
||||
|
||||
GST_LOG_OBJECT (self,
|
||||
"Output picture %p (poc %d)", to_output, to_output->pic_order_cnt);
|
||||
gst_h265_decoder_do_output_picture (self, to_output);
|
||||
if (!to_output->ref) {
|
||||
/* Current picture hasn't been inserted into DPB yet, so don't remove it
|
||||
* if we managed to output it immediately */
|
||||
gint outputted_poc = to_output->pic_order_cnt;
|
||||
if (outputted_poc != picture->pic_order_cnt) {
|
||||
GST_LOG_OBJECT (self, "Delete picture %p (poc %d) from DPB",
|
||||
to_output, to_output->pic_order_cnt);
|
||||
gst_h265_dpb_delete_by_poc (priv->dpb, outputted_poc);
|
||||
|
||||
/* Current picture hasn't been inserted into DPB yet, so don't remove it
|
||||
* if we managed to output it immediately */
|
||||
if (picture && to_output == picture) {
|
||||
clear_dpb = FALSE;
|
||||
|
||||
if (picture->ref) {
|
||||
GST_TRACE_OBJECT (self,
|
||||
"Put current picture %p (poc %d) to dpb",
|
||||
picture, picture->pic_order_cnt);
|
||||
gst_h265_dpb_add (priv->dpb, gst_h265_picture_ref (picture));
|
||||
}
|
||||
|
||||
/* and mark current picture as handled */
|
||||
picture = NULL;
|
||||
}
|
||||
|
||||
iter = g_list_next (iter);
|
||||
gst_h265_decoder_do_output_picture (self, to_output, clear_dpb);
|
||||
|
||||
num_remaining--;
|
||||
}
|
||||
|
||||
if (not_outputted)
|
||||
g_list_free_full (not_outputted, (GDestroyNotify) gst_h265_picture_unref);
|
||||
/* If we haven't managed to output the picture that we just decoded, or if
|
||||
* it's a reference picture, we have to store it in DPB */
|
||||
if (picture && (!picture->outputted || picture->ref)) {
|
||||
if (gst_h265_dpb_is_full (priv->dpb)) {
|
||||
/* If we haven't managed to output anything to free up space in DPB
|
||||
* to store this picture, it's an error in the stream */
|
||||
GST_WARNING_OBJECT (self, "Could not free up space in DPB");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_TRACE_OBJECT (self,
|
||||
"Put picture %p (outputted %d, ref %d, poc %d) to dpb",
|
||||
picture, picture->outputted, picture->ref, picture->pic_order_cnt);
|
||||
gst_h265_dpb_add (priv->dpb, gst_h265_picture_ref (picture));
|
||||
}
|
||||
|
||||
g_array_set_size (not_outputted, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1420,7 +1480,12 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
|||
priv->current_frame = frame;
|
||||
priv->last_ret = GST_FLOW_OK;
|
||||
|
||||
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,
|
||||
("Failed to map memory for reading"), (NULL));
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
if (priv->in_format == GST_H265_DECODER_FORMAT_HVC1 ||
|
||||
priv->in_format == GST_H265_DECODER_FORMAT_HEV1) {
|
||||
pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
|
||||
|
@ -1471,3 +1536,22 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
|||
|
||||
return priv->last_ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h265_decoder_get_picture:
|
||||
* @decoder: a #GstH265Decoder
|
||||
* @system_frame_number: a target system frame number of #GstH265Picture
|
||||
*
|
||||
* Retrive DPB and return a #GstH265Picture corresponding to
|
||||
* the @system_frame_number
|
||||
*
|
||||
* Returns: (transfer full): a #GstH265Picture if successful, or %NULL otherwise
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstH265Picture *
|
||||
gst_h265_decoder_get_picture (GstH265Decoder * decoder,
|
||||
guint32 system_frame_number)
|
||||
{
|
||||
return gst_h265_dpb_get_picture (decoder->priv->dpb, system_frame_number);
|
||||
}
|
||||
|
|
|
@ -87,9 +87,7 @@ struct _GstH265Decoder
|
|||
* Called per one #GstH265Picture to notify subclass to finish
|
||||
* decoding process for the #GstH265Picture
|
||||
* @output_picture: Called with a #GstH265Picture which is required to be outputted.
|
||||
* Subclass can retrieve parent #GstVideoCodecFrame by using
|
||||
* gst_video_decoder_get_frame() with system_frame_number
|
||||
* and the #GstVideoCodecFrame must be consumed by subclass via
|
||||
* The #GstVideoCodecFrame must be consumed by subclass via
|
||||
* gst_video_decoder_{finish,drop,release}_frame().
|
||||
*/
|
||||
struct _GstH265DecoderClass
|
||||
|
@ -99,8 +97,14 @@ struct _GstH265DecoderClass
|
|||
gboolean (*new_sequence) (GstH265Decoder * decoder,
|
||||
const GstH265SPS * sps,
|
||||
gint max_dpb_size);
|
||||
|
||||
/**
|
||||
* GstH265Decoder:new_picture:
|
||||
* @decoder: a #GstH265Decoder
|
||||
* @frame: (transfer none): a #GstVideoCodecFrame
|
||||
* @picture: (transfer none): a #GstH265Picture
|
||||
*/
|
||||
gboolean (*new_picture) (GstH265Decoder * decoder,
|
||||
GstVideoCodecFrame * frame,
|
||||
GstH265Picture * picture);
|
||||
|
||||
gboolean (*start_picture) (GstH265Decoder * decoder,
|
||||
|
@ -114,8 +118,14 @@ struct _GstH265DecoderClass
|
|||
|
||||
gboolean (*end_picture) (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture);
|
||||
|
||||
/**
|
||||
* GstH265Decoder:output_picture:
|
||||
* @decoder: a #GstH265Decoder
|
||||
* @frame: (transfer full): a #GstVideoCodecFrame
|
||||
* @picture: (transfer full): a #GstH265Picture
|
||||
*/
|
||||
GstFlowReturn (*output_picture) (GstH265Decoder * decoder,
|
||||
GstVideoCodecFrame * frame,
|
||||
GstH265Picture * picture);
|
||||
|
||||
/*< private >*/
|
||||
|
@ -127,6 +137,10 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstH265Decoder, gst_object_unref)
|
|||
GST_CODECS_API
|
||||
GType gst_h265_decoder_get_type (void);
|
||||
|
||||
GST_CODECS_API
|
||||
GstH265Picture * gst_h265_decoder_get_picture (GstH265Decoder * decoder,
|
||||
guint32 system_frame_number);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_H265_DECODER_H__ */
|
||||
|
|
|
@ -231,6 +231,34 @@ gst_h265_dpb_delete_unused (GstH265Dpb * dpb)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h265_dpb_delete_outputted:
|
||||
* @dpb: a #GstH265Dpb
|
||||
*
|
||||
* Delete already outputted picture, even if they are referenced.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
void
|
||||
gst_h265_dpb_delete_outputted (GstH265Dpb * dpb)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (dpb != NULL);
|
||||
|
||||
for (i = 0; i < dpb->pic_list->len; i++) {
|
||||
GstH265Picture *picture =
|
||||
g_array_index (dpb->pic_list, GstH265Picture *, i);
|
||||
|
||||
if (picture->outputted) {
|
||||
GST_TRACE ("remove picture %p (poc %d) from dpb",
|
||||
picture, picture->pic_order_cnt);
|
||||
g_array_remove_index_fast (dpb->pic_list, i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h265_dpb_delete_by_poc:
|
||||
* @dpb: a #GstH265Dpb
|
||||
|
@ -423,13 +451,13 @@ gst_h265_dpb_get_long_ref_by_poc (GstH265Dpb * dpb, gint poc)
|
|||
/**
|
||||
* gst_h265_dpb_get_pictures_not_outputted:
|
||||
* @dpb: a #GstH265Dpb
|
||||
* @out: (out) (element-type GstH265Picture) (transfer full): a list
|
||||
* of #GstH265Dpb
|
||||
* @out: (out) (element-type GstH265Picture) (transfer full): an array
|
||||
* of #GstH265Picture pointer
|
||||
*
|
||||
* Retrieve all not-outputted pictures from @dpb
|
||||
*/
|
||||
void
|
||||
gst_h265_dpb_get_pictures_not_outputted (GstH265Dpb * dpb, GList ** out)
|
||||
gst_h265_dpb_get_pictures_not_outputted (GstH265Dpb * dpb, GArray * out)
|
||||
{
|
||||
gint i;
|
||||
|
||||
|
@ -440,8 +468,10 @@ gst_h265_dpb_get_pictures_not_outputted (GstH265Dpb * dpb, GList ** out)
|
|||
GstH265Picture *picture =
|
||||
g_array_index (dpb->pic_list, GstH265Picture *, i);
|
||||
|
||||
if (!picture->outputted)
|
||||
*out = g_list_append (*out, gst_h265_picture_ref (picture));
|
||||
if (!picture->outputted) {
|
||||
gst_h265_picture_ref (picture);
|
||||
g_array_append_val (out, picture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,3 +517,34 @@ gst_h265_dpb_is_full (GstH265Dpb * dpb)
|
|||
|
||||
return dpb->pic_list->len >= dpb->max_num_pics;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_h265_dpb_get_picture:
|
||||
* @dpb: a #GstH265Dpb
|
||||
* @system_frame_number The system frame number
|
||||
*
|
||||
* Returns: (transfer full): the picture identified with the specified
|
||||
* @system_frame_number, or %NULL if DPB does not contain a #GstH265Picture
|
||||
* corresponding to the @system_frame_number
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstH265Picture *
|
||||
gst_h265_dpb_get_picture (GstH265Dpb * dpb, guint32 system_frame_number)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (dpb != NULL, NULL);
|
||||
|
||||
for (i = 0; i < dpb->pic_list->len; i++) {
|
||||
GstH265Picture *picture =
|
||||
g_array_index (dpb->pic_list, GstH265Picture *, i);
|
||||
|
||||
if (picture->system_frame_number == system_frame_number) {
|
||||
gst_h265_picture_ref (picture);
|
||||
return picture;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -160,6 +160,9 @@ void gst_h265_dpb_add (GstH265Dpb * dpb,
|
|||
GST_CODECS_API
|
||||
void gst_h265_dpb_delete_unused (GstH265Dpb * dpb);
|
||||
|
||||
GST_CODECS_API
|
||||
void gst_h265_dpb_delete_outputted (GstH265Dpb * dpb);
|
||||
|
||||
GST_CODECS_API
|
||||
void gst_h265_dpb_delete_by_poc (GstH265Dpb * dpb,
|
||||
gint poc);
|
||||
|
@ -188,11 +191,15 @@ GstH265Picture * gst_h265_dpb_get_long_ref_by_poc (GstH265Dpb * dpb,
|
|||
|
||||
GST_CODECS_API
|
||||
void gst_h265_dpb_get_pictures_not_outputted (GstH265Dpb * dpb,
|
||||
GList ** out);
|
||||
GArray * out);
|
||||
|
||||
GST_CODECS_API
|
||||
GArray * gst_h265_dpb_get_pictures_all (GstH265Dpb * dpb);
|
||||
|
||||
GST_CODECS_API
|
||||
GstH265Picture * gst_h265_dpb_get_picture (GstH265Dpb * dpb,
|
||||
guint32 system_frame_number);
|
||||
|
||||
GST_CODECS_API
|
||||
gint gst_h265_dpb_get_size (GstH265Dpb * dpb);
|
||||
|
||||
|
|
|
@ -120,9 +120,9 @@ static gboolean gst_d3d11_h265_dec_src_query (GstVideoDecoder * decoder,
|
|||
static gboolean gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
|
||||
const GstH265SPS * sps, gint max_dpb_size);
|
||||
static gboolean gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture);
|
||||
GstVideoCodecFrame * cframe, GstH265Picture * picture);
|
||||
static GstFlowReturn gst_d3d11_h265_dec_output_picture (GstH265Decoder *
|
||||
decoder, GstH265Picture * picture);
|
||||
decoder, GstVideoCodecFrame * frame, GstH265Picture * picture);
|
||||
static gboolean gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb);
|
||||
static gboolean gst_d3d11_h265_dec_decode_slice (GstH265Decoder * decoder,
|
||||
|
@ -624,7 +624,7 @@ gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
|
|||
|
||||
static gboolean
|
||||
gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture)
|
||||
GstVideoCodecFrame * cframe, GstH265Picture * picture)
|
||||
{
|
||||
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
|
||||
GstBuffer *view_buffer;
|
||||
|
@ -651,10 +651,10 @@ gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
|
|||
|
||||
static GstFlowReturn
|
||||
gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture)
|
||||
GstVideoCodecFrame * frame, GstH265Picture * picture)
|
||||
{
|
||||
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
|
||||
GstVideoCodecFrame *frame = NULL;
|
||||
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
|
||||
GstBuffer *output_buffer = NULL;
|
||||
GstBuffer *view_buffer;
|
||||
|
||||
|
@ -665,16 +665,7 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
|||
|
||||
if (!view_buffer) {
|
||||
GST_ERROR_OBJECT (self, "Could not get output view");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
||||
picture->system_frame_number);
|
||||
|
||||
/* FIXME: Sync with other codec implementation */
|
||||
if (!frame) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't get codec frame");
|
||||
return GST_FLOW_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* if downstream is d3d11 element and forward playback case,
|
||||
|
@ -696,9 +687,7 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
|||
|
||||
if (!output_buffer) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
|
||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
frame->output_buffer = output_buffer;
|
||||
|
@ -710,11 +699,18 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
|||
view_buffer, output_buffer)) {
|
||||
GST_ERROR_OBJECT (self, "Failed to copy buffer");
|
||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gst_h265_picture_unref (picture);
|
||||
|
||||
return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||
|
||||
error:
|
||||
gst_video_decoder_drop_frame (vdec, frame);
|
||||
gst_h265_picture_unref (picture);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -146,9 +146,9 @@ static gboolean gst_nv_h265_dec_src_query (GstVideoDecoder * decoder,
|
|||
static gboolean gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder,
|
||||
const GstH265SPS * sps, gint max_dpb_size);
|
||||
static gboolean gst_nv_h265_dec_new_picture (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture);
|
||||
GstVideoCodecFrame * frame, GstH265Picture * picture);
|
||||
static GstFlowReturn gst_nv_h265_dec_output_picture (GstH265Decoder *
|
||||
decoder, GstH265Picture * picture);
|
||||
decoder, GstVideoCodecFrame * frame, GstH265Picture * picture);
|
||||
static gboolean gst_nv_h265_dec_start_picture (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb);
|
||||
static gboolean gst_nv_h265_dec_decode_slice (GstH265Decoder * decoder,
|
||||
|
@ -414,7 +414,8 @@ gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_nv_h265_dec_new_picture (GstH265Decoder * decoder, GstH265Picture * picture)
|
||||
gst_nv_h265_dec_new_picture (GstH265Decoder * decoder,
|
||||
GstVideoCodecFrame * cframe, GstH265Picture * picture)
|
||||
{
|
||||
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
||||
GstNvDecoderFrame *frame;
|
||||
|
@ -435,11 +436,10 @@ gst_nv_h265_dec_new_picture (GstH265Decoder * decoder, GstH265Picture * picture)
|
|||
|
||||
static GstFlowReturn
|
||||
gst_nv_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||
GstH265Picture * picture)
|
||||
GstVideoCodecFrame * frame, GstH265Picture * picture)
|
||||
{
|
||||
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
||||
GstVideoCodecFrame *frame = NULL;
|
||||
GstBuffer *output_buffer = NULL;
|
||||
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
|
||||
GstNvDecoderFrame *decoder_frame;
|
||||
gboolean ret G_GNUC_UNUSED = FALSE;
|
||||
|
||||
|
@ -450,24 +450,16 @@ gst_nv_h265_dec_output_picture (GstH265Decoder * decoder,
|
|||
(GstNvDecoderFrame *) gst_h265_picture_get_user_data (picture);
|
||||
if (!decoder_frame) {
|
||||
GST_ERROR_OBJECT (self, "No decoder frame in picture %p", picture);
|
||||
return GST_FLOW_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
||||
picture->system_frame_number);
|
||||
if (!frame) {
|
||||
GST_ERROR_OBJECT (self, "Failed to retrieve codec frame");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
output_buffer =
|
||||
gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
|
||||
frame->output_buffer = output_buffer;
|
||||
frame->output_buffer =
|
||||
gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));;
|
||||
|
||||
if (self->output_type == GST_NV_DECOCER_OUTPUT_TYPE_GL) {
|
||||
ret = gst_nv_decoder_finish_frame (self->decoder,
|
||||
GST_NV_DECOCER_OUTPUT_TYPE_GL, self->gl_context,
|
||||
decoder_frame, output_buffer);
|
||||
decoder_frame, frame->output_buffer);
|
||||
|
||||
/* FIXME: This is the case where OpenGL context of downstream glbufferpool
|
||||
* belongs to non-nvidia (or different device).
|
||||
|
@ -483,14 +475,21 @@ gst_nv_h265_dec_output_picture (GstH265Decoder * decoder,
|
|||
if (!ret) {
|
||||
if (!gst_nv_decoder_finish_frame (self->decoder,
|
||||
GST_NV_DECOCER_OUTPUT_TYPE_SYSTEM, NULL, decoder_frame,
|
||||
output_buffer)) {
|
||||
frame->output_buffer)) {
|
||||
GST_ERROR_OBJECT (self, "Failed to finish frame");
|
||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||
return GST_FLOW_ERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
gst_h265_picture_unref (picture);
|
||||
|
||||
return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||
|
||||
error:
|
||||
gst_video_decoder_drop_frame (vdec, frame);
|
||||
gst_h265_picture_unref (picture);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
static GstNvDecoderFrame *
|
||||
|
|
Loading…
Reference in a new issue