mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-23 14:36:24 +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;
|
GstH265Picture *current_picture;
|
||||||
GstVideoCodecFrame *current_frame;
|
GstVideoCodecFrame *current_frame;
|
||||||
|
|
||||||
/* Slice (slice header + nalu) currently being processed/decodec */
|
/* Slice (slice header + nalu) currently being processed/decoded */
|
||||||
GstH265Slice current_slice;
|
GstH265Slice current_slice;
|
||||||
GstH265Slice prev_slice;
|
GstH265Slice prev_slice;
|
||||||
GstH265Slice prev_independent_slice;
|
GstH265Slice prev_independent_slice;
|
||||||
|
@ -101,6 +101,9 @@ struct _GstH265DecoderPrivate
|
||||||
gboolean associated_irap_NoRaslOutputFlag;
|
gboolean associated_irap_NoRaslOutputFlag;
|
||||||
gboolean new_bitstream;
|
gboolean new_bitstream;
|
||||||
gboolean prev_nal_is_eos;
|
gboolean prev_nal_is_eos;
|
||||||
|
|
||||||
|
/* Cached array to handle pictures to be outputted */
|
||||||
|
GArray *to_output;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define parent_class gst_h265_decoder_parent_class
|
#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,
|
GST_DEBUG_CATEGORY_INIT (gst_h265_decoder_debug, "h265decoder", 0,
|
||||||
"H.265 Video Decoder"));
|
"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_start (GstVideoDecoder * decoder);
|
||||||
static gboolean gst_h265_decoder_stop (GstVideoDecoder * decoder);
|
static gboolean gst_h265_decoder_stop (GstVideoDecoder * decoder);
|
||||||
static gboolean gst_h265_decoder_set_format (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 gboolean gst_h265_decoder_finish_current_picture (GstH265Decoder * self);
|
||||||
static void gst_h265_decoder_clear_dpb (GstH265Decoder * self);
|
static void gst_h265_decoder_clear_dpb (GstH265Decoder * self);
|
||||||
static gboolean
|
static gboolean gst_h265_decoder_drain_internal (GstH265Decoder * self);
|
||||||
gst_h265_decoder_output_all_remaining_pics (GstH265Decoder * self);
|
|
||||||
static gboolean gst_h265_decoder_start_current_picture (GstH265Decoder * self);
|
static gboolean gst_h265_decoder_start_current_picture (GstH265Decoder * self);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
||||||
{
|
{
|
||||||
GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (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->start = GST_DEBUG_FUNCPTR (gst_h265_decoder_start);
|
||||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h265_decoder_stop);
|
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h265_decoder_stop);
|
||||||
|
@ -144,9 +151,27 @@ gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_h265_decoder_init (GstH265Decoder * self)
|
gst_h265_decoder_init (GstH265Decoder * self)
|
||||||
{
|
{
|
||||||
|
GstH265DecoderPrivate *priv;
|
||||||
|
|
||||||
gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
|
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
|
static gboolean
|
||||||
|
@ -336,6 +361,7 @@ gst_h265_decoder_decode_slice (GstH265Decoder * self)
|
||||||
|
|
||||||
g_assert (klass->decode_slice);
|
g_assert (klass->decode_slice);
|
||||||
|
|
||||||
|
/* FIXME ref_pic_list0, ref_pic_list1 */
|
||||||
return klass->decode_slice (self, picture, slice);
|
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. */
|
/* This allows accessing the frame from the picture. */
|
||||||
picture->system_frame_number = priv->current_frame->system_frame_number;
|
picture->system_frame_number = priv->current_frame->system_frame_number;
|
||||||
|
|
||||||
|
priv->current_picture = picture;
|
||||||
|
g_assert (priv->current_frame);
|
||||||
|
|
||||||
if (klass->new_picture)
|
if (klass->new_picture)
|
||||||
ret = klass->new_picture (self, picture);
|
ret = klass->new_picture (self, priv->current_frame, picture);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
GST_ERROR_OBJECT (self, "subclass does not want accept new picture");
|
GST_ERROR_OBJECT (self, "subclass does not want accept new picture");
|
||||||
|
priv->current_picture = NULL;
|
||||||
gst_h265_picture_unref (picture);
|
gst_h265_picture_unref (picture);
|
||||||
return FALSE;
|
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)) {
|
if (!gst_h265_decoder_start_current_picture (self)) {
|
||||||
GST_ERROR_OBJECT (self, "start picture failed");
|
GST_ERROR_OBJECT (self, "start picture failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -700,8 +725,8 @@ gst_h265_decoder_drain (GstVideoDecoder * decoder)
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
|
|
||||||
priv->last_ret = GST_FLOW_OK;
|
priv->last_ret = GST_FLOW_OK;
|
||||||
gst_h265_decoder_output_all_remaining_pics (self);
|
/* dpb will be cleared by this method */
|
||||||
gst_h265_decoder_clear_dpb (self);
|
gst_h265_decoder_drain_internal (self);
|
||||||
|
|
||||||
return priv->last_ret;
|
return priv->last_ret;
|
||||||
}
|
}
|
||||||
|
@ -1121,13 +1146,17 @@ gst_h265_decoder_clear_dpb (GstH265Decoder * self)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_h265_decoder_do_output_picture (GstH265Decoder * self,
|
gst_h265_decoder_do_output_picture (GstH265Decoder * self,
|
||||||
GstH265Picture * picture)
|
GstH265Picture * picture, gboolean clear_dpb)
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
GstH265DecoderClass *klass;
|
GstH265DecoderClass *klass;
|
||||||
|
GstVideoCodecFrame *frame = NULL;
|
||||||
|
|
||||||
picture->outputted = TRUE;
|
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) {
|
if (picture->pic_order_cnt < priv->last_output_poc) {
|
||||||
GST_WARNING_OBJECT (self,
|
GST_WARNING_OBJECT (self,
|
||||||
"Outputting out of order %d -> %d, likely a broken stream",
|
"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;
|
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);
|
klass = GST_H265_DECODER_GET_CLASS (self);
|
||||||
|
|
||||||
g_assert (klass->output_picture);
|
g_assert (klass->output_picture);
|
||||||
priv->last_ret = klass->output_picture (self, picture);
|
priv->last_ret = klass->output_picture (self, frame, picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
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
|
static gboolean
|
||||||
gst_h265_decoder_output_all_remaining_pics (GstH265Decoder * self)
|
gst_h265_decoder_drain_internal (GstH265Decoder * self)
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
GList *to_output = NULL;
|
GArray *to_output = priv->to_output;
|
||||||
GList *iter;
|
|
||||||
|
|
||||||
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)) {
|
/* We want the last reference when outputing so take a ref and then remove
|
||||||
GstH265Picture *picture = (GstH265Picture *) iter->data;
|
* 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,
|
GST_LOG_OBJECT (self, "Output picture %p (poc %d)", picture,
|
||||||
picture->pic_order_cnt);
|
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_array_set_size (to_output, 0);
|
||||||
g_list_free_full (to_output, (GDestroyNotify) gst_h265_picture_unref);
|
gst_h265_dpb_clear (priv->dpb);
|
||||||
|
priv->last_output_poc = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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)) {
|
for (i = 0; i < array->len; i++) {
|
||||||
GstH265Picture *pic = (GstH265Picture *) iter->data;
|
GstH265Picture *pic = g_array_index (array, GstH265Picture *, i);
|
||||||
if (!pic->outputted && pic->pic_latency_cnt >= max_latency)
|
if (!pic->outputted && pic->pic_latency_cnt >= max_latency)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1263,24 +1311,22 @@ gst_h265_decoder_finish_picture (GstH265Decoder * self,
|
||||||
{
|
{
|
||||||
GstH265DecoderPrivate *priv = self->priv;
|
GstH265DecoderPrivate *priv = self->priv;
|
||||||
const GstH265SPS *sps = priv->active_sps;
|
const GstH265SPS *sps = priv->active_sps;
|
||||||
GList *not_outputted = NULL;
|
GArray *not_outputted = priv->to_output;
|
||||||
guint num_remaining;
|
guint num_remaining;
|
||||||
GList *iter;
|
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
|
||||||
gint i;
|
gint i;
|
||||||
#endif
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (self,
|
GST_LOG_OBJECT (self,
|
||||||
"Finishing picture %p (poc %d), entries in DPB %d",
|
"Finishing picture %p (poc %d), entries in DPB %d",
|
||||||
picture, picture->pic_order_cnt, gst_h265_dpb_get_size (priv->dpb));
|
picture, picture->pic_order_cnt, gst_h265_dpb_get_size (priv->dpb));
|
||||||
|
|
||||||
/* Get all pictures that haven't been outputted yet */
|
/* 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 */
|
/* C.5.2.3 */
|
||||||
if (picture->output_flag) {
|
if (picture->output_flag) {
|
||||||
for (iter = not_outputted; iter; iter = g_list_next (iter)) {
|
for (i = 0; i < not_outputted->len; i++) {
|
||||||
GstH265Picture *other = GST_H265_PICTURE (iter->data);
|
GstH265Picture *other =
|
||||||
|
g_array_index (not_outputted, GstH265Picture *, i);
|
||||||
|
|
||||||
if (!other->outputted)
|
if (!other->outputted)
|
||||||
other->pic_latency_cnt++;
|
other->pic_latency_cnt++;
|
||||||
|
@ -1297,40 +1343,29 @@ gst_h265_decoder_finish_picture (GstH265Decoder * self,
|
||||||
picture->long_term = FALSE;
|
picture->long_term = FALSE;
|
||||||
|
|
||||||
/* Include the one we've just decoded */
|
/* Include the one we've just decoded */
|
||||||
if (picture->output_flag) {
|
if (picture->output_flag)
|
||||||
not_outputted =
|
g_array_append_val (not_outputted, picture);
|
||||||
g_list_append (not_outputted, gst_h265_picture_ref (picture));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add to dpb and transfer ownership */
|
|
||||||
gst_h265_dpb_add (priv->dpb, picture);
|
|
||||||
|
|
||||||
/* for debugging */
|
/* for debugging */
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
GST_TRACE_OBJECT (self, "Before sorting not outputted list");
|
GST_TRACE_OBJECT (self, "Before sorting not outputted list");
|
||||||
i = 0;
|
for (i = 0; i < not_outputted->len; i++) {
|
||||||
for (iter = not_outputted; iter; iter = g_list_next (iter)) {
|
GstH265Picture *tmp = g_array_index (not_outputted, GstH265Picture *, i);
|
||||||
GstH265Picture *tmp = (GstH265Picture *) iter->data;
|
|
||||||
|
|
||||||
GST_TRACE_OBJECT (self,
|
GST_TRACE_OBJECT (self,
|
||||||
"\t%dth picture %p (poc %d)", i, tmp, tmp->pic_order_cnt);
|
"\t%dth picture %p (poc %d)", i, tmp, tmp->pic_order_cnt);
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Sort in output order */
|
/* 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
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
GST_TRACE_OBJECT (self,
|
GST_TRACE_OBJECT (self,
|
||||||
"After sorting not outputted list in poc ascending order");
|
"After sorting not outputted list in poc ascending order");
|
||||||
i = 0;
|
for (i = 0; i < not_outputted->len; i++) {
|
||||||
for (iter = not_outputted; iter; iter = g_list_next (iter)) {
|
GstH265Picture *tmp = g_array_index (not_outputted, GstH265Picture *, i);
|
||||||
GstH265Picture *tmp = (GstH265Picture *) iter->data;
|
|
||||||
|
|
||||||
GST_TRACE_OBJECT (self,
|
GST_TRACE_OBJECT (self,
|
||||||
"\t%dth picture %p (poc %d)", i, tmp, tmp->pic_order_cnt);
|
"\t%dth picture %p (poc %d)", i, tmp, tmp->pic_order_cnt);
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
#endif
|
#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.
|
* 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
|
* If the outputted picture is not a reference picture, it doesn't have
|
||||||
* to remain in the DPB and can be removed */
|
* to remain in the DPB and can be removed */
|
||||||
iter = not_outputted;
|
num_remaining = not_outputted->len;
|
||||||
num_remaining = g_list_length (not_outputted);
|
|
||||||
|
|
||||||
while (num_remaining > sps->max_num_reorder_pics[sps->max_sub_layers_minus1]
|
while (num_remaining > sps->max_num_reorder_pics[sps->max_sub_layers_minus1]
|
||||||
|| (num_remaining &&
|
|| (num_remaining &&
|
||||||
sps->max_latency_increase_plus1[sps->max_sub_layers_minus1] &&
|
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))) {
|
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,
|
GST_LOG_OBJECT (self,
|
||||||
"Output picture %p (poc %d)", to_output, to_output->pic_order_cnt);
|
"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
|
||||||
/* Current picture hasn't been inserted into DPB yet, so don't remove it
|
* if we managed to output it immediately */
|
||||||
* if we managed to output it immediately */
|
if (picture && to_output == picture) {
|
||||||
gint outputted_poc = to_output->pic_order_cnt;
|
clear_dpb = FALSE;
|
||||||
if (outputted_poc != picture->pic_order_cnt) {
|
|
||||||
GST_LOG_OBJECT (self, "Delete picture %p (poc %d) from DPB",
|
if (picture->ref) {
|
||||||
to_output, to_output->pic_order_cnt);
|
GST_TRACE_OBJECT (self,
|
||||||
gst_h265_dpb_delete_by_poc (priv->dpb, outputted_poc);
|
"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--;
|
num_remaining--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not_outputted)
|
/* If we haven't managed to output the picture that we just decoded, or if
|
||||||
g_list_free_full (not_outputted, (GDestroyNotify) gst_h265_picture_unref);
|
* 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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1420,7 +1480,12 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
||||||
priv->current_frame = frame;
|
priv->current_frame = frame;
|
||||||
priv->last_ret = GST_FLOW_OK;
|
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 ||
|
if (priv->in_format == GST_H265_DECODER_FORMAT_HVC1 ||
|
||||||
priv->in_format == GST_H265_DECODER_FORMAT_HEV1) {
|
priv->in_format == GST_H265_DECODER_FORMAT_HEV1) {
|
||||||
pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
|
pres = gst_h265_parser_identify_nalu_hevc (priv->parser,
|
||||||
|
@ -1471,3 +1536,22 @@ gst_h265_decoder_handle_frame (GstVideoDecoder * decoder,
|
||||||
|
|
||||||
return priv->last_ret;
|
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
|
* Called per one #GstH265Picture to notify subclass to finish
|
||||||
* decoding process for the #GstH265Picture
|
* decoding process for the #GstH265Picture
|
||||||
* @output_picture: Called with a #GstH265Picture which is required to be outputted.
|
* @output_picture: Called with a #GstH265Picture which is required to be outputted.
|
||||||
* Subclass can retrieve parent #GstVideoCodecFrame by using
|
* The #GstVideoCodecFrame must be consumed by subclass via
|
||||||
* gst_video_decoder_get_frame() with system_frame_number
|
|
||||||
* and the #GstVideoCodecFrame must be consumed by subclass via
|
|
||||||
* gst_video_decoder_{finish,drop,release}_frame().
|
* gst_video_decoder_{finish,drop,release}_frame().
|
||||||
*/
|
*/
|
||||||
struct _GstH265DecoderClass
|
struct _GstH265DecoderClass
|
||||||
|
@ -99,8 +97,14 @@ struct _GstH265DecoderClass
|
||||||
gboolean (*new_sequence) (GstH265Decoder * decoder,
|
gboolean (*new_sequence) (GstH265Decoder * decoder,
|
||||||
const GstH265SPS * sps,
|
const GstH265SPS * sps,
|
||||||
gint max_dpb_size);
|
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,
|
gboolean (*new_picture) (GstH265Decoder * decoder,
|
||||||
|
GstVideoCodecFrame * frame,
|
||||||
GstH265Picture * picture);
|
GstH265Picture * picture);
|
||||||
|
|
||||||
gboolean (*start_picture) (GstH265Decoder * decoder,
|
gboolean (*start_picture) (GstH265Decoder * decoder,
|
||||||
|
@ -114,8 +118,14 @@ struct _GstH265DecoderClass
|
||||||
|
|
||||||
gboolean (*end_picture) (GstH265Decoder * decoder,
|
gboolean (*end_picture) (GstH265Decoder * decoder,
|
||||||
GstH265Picture * picture);
|
GstH265Picture * picture);
|
||||||
|
/**
|
||||||
|
* GstH265Decoder:output_picture:
|
||||||
|
* @decoder: a #GstH265Decoder
|
||||||
|
* @frame: (transfer full): a #GstVideoCodecFrame
|
||||||
|
* @picture: (transfer full): a #GstH265Picture
|
||||||
|
*/
|
||||||
GstFlowReturn (*output_picture) (GstH265Decoder * decoder,
|
GstFlowReturn (*output_picture) (GstH265Decoder * decoder,
|
||||||
|
GstVideoCodecFrame * frame,
|
||||||
GstH265Picture * picture);
|
GstH265Picture * picture);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
|
@ -127,6 +137,10 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstH265Decoder, gst_object_unref)
|
||||||
GST_CODECS_API
|
GST_CODECS_API
|
||||||
GType gst_h265_decoder_get_type (void);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_H265_DECODER_H__ */
|
#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:
|
* gst_h265_dpb_delete_by_poc:
|
||||||
* @dpb: a #GstH265Dpb
|
* @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:
|
* gst_h265_dpb_get_pictures_not_outputted:
|
||||||
* @dpb: a #GstH265Dpb
|
* @dpb: a #GstH265Dpb
|
||||||
* @out: (out) (element-type GstH265Picture) (transfer full): a list
|
* @out: (out) (element-type GstH265Picture) (transfer full): an array
|
||||||
* of #GstH265Dpb
|
* of #GstH265Picture pointer
|
||||||
*
|
*
|
||||||
* Retrieve all not-outputted pictures from @dpb
|
* Retrieve all not-outputted pictures from @dpb
|
||||||
*/
|
*/
|
||||||
void
|
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;
|
gint i;
|
||||||
|
|
||||||
|
@ -440,8 +468,10 @@ gst_h265_dpb_get_pictures_not_outputted (GstH265Dpb * dpb, GList ** out)
|
||||||
GstH265Picture *picture =
|
GstH265Picture *picture =
|
||||||
g_array_index (dpb->pic_list, GstH265Picture *, i);
|
g_array_index (dpb->pic_list, GstH265Picture *, i);
|
||||||
|
|
||||||
if (!picture->outputted)
|
if (!picture->outputted) {
|
||||||
*out = g_list_append (*out, gst_h265_picture_ref (picture));
|
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;
|
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
|
GST_CODECS_API
|
||||||
void gst_h265_dpb_delete_unused (GstH265Dpb * dpb);
|
void gst_h265_dpb_delete_unused (GstH265Dpb * dpb);
|
||||||
|
|
||||||
|
GST_CODECS_API
|
||||||
|
void gst_h265_dpb_delete_outputted (GstH265Dpb * dpb);
|
||||||
|
|
||||||
GST_CODECS_API
|
GST_CODECS_API
|
||||||
void gst_h265_dpb_delete_by_poc (GstH265Dpb * dpb,
|
void gst_h265_dpb_delete_by_poc (GstH265Dpb * dpb,
|
||||||
gint poc);
|
gint poc);
|
||||||
|
@ -188,11 +191,15 @@ GstH265Picture * gst_h265_dpb_get_long_ref_by_poc (GstH265Dpb * dpb,
|
||||||
|
|
||||||
GST_CODECS_API
|
GST_CODECS_API
|
||||||
void gst_h265_dpb_get_pictures_not_outputted (GstH265Dpb * dpb,
|
void gst_h265_dpb_get_pictures_not_outputted (GstH265Dpb * dpb,
|
||||||
GList ** out);
|
GArray * out);
|
||||||
|
|
||||||
GST_CODECS_API
|
GST_CODECS_API
|
||||||
GArray * gst_h265_dpb_get_pictures_all (GstH265Dpb * dpb);
|
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
|
GST_CODECS_API
|
||||||
gint gst_h265_dpb_get_size (GstH265Dpb * dpb);
|
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,
|
static gboolean gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
|
||||||
const GstH265SPS * sps, gint max_dpb_size);
|
const GstH265SPS * sps, gint max_dpb_size);
|
||||||
static gboolean gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
|
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 *
|
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,
|
static gboolean gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
|
||||||
GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb);
|
GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb);
|
||||||
static gboolean gst_d3d11_h265_dec_decode_slice (GstH265Decoder * decoder,
|
static gboolean gst_d3d11_h265_dec_decode_slice (GstH265Decoder * decoder,
|
||||||
|
@ -624,7 +624,7 @@ gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
|
gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
|
||||||
GstH265Picture * picture)
|
GstVideoCodecFrame * cframe, GstH265Picture * picture)
|
||||||
{
|
{
|
||||||
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
|
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
|
||||||
GstBuffer *view_buffer;
|
GstBuffer *view_buffer;
|
||||||
|
@ -651,10 +651,10 @@ gst_d3d11_h265_dec_new_picture (GstH265Decoder * decoder,
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||||
GstH265Picture * picture)
|
GstVideoCodecFrame * frame, GstH265Picture * picture)
|
||||||
{
|
{
|
||||||
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
|
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
|
||||||
GstVideoCodecFrame *frame = NULL;
|
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
|
||||||
GstBuffer *output_buffer = NULL;
|
GstBuffer *output_buffer = NULL;
|
||||||
GstBuffer *view_buffer;
|
GstBuffer *view_buffer;
|
||||||
|
|
||||||
|
@ -665,16 +665,7 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||||
|
|
||||||
if (!view_buffer) {
|
if (!view_buffer) {
|
||||||
GST_ERROR_OBJECT (self, "Could not get output view");
|
GST_ERROR_OBJECT (self, "Could not get output view");
|
||||||
return GST_FLOW_ERROR;
|
goto 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if downstream is d3d11 element and forward playback case,
|
/* if downstream is d3d11 element and forward playback case,
|
||||||
|
@ -696,9 +687,7 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||||
|
|
||||||
if (!output_buffer) {
|
if (!output_buffer) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
|
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
|
||||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
goto error;
|
||||||
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->output_buffer = output_buffer;
|
frame->output_buffer = output_buffer;
|
||||||
|
@ -710,11 +699,18 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||||
view_buffer, output_buffer)) {
|
view_buffer, output_buffer)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to copy buffer");
|
GST_ERROR_OBJECT (self, "Failed to copy buffer");
|
||||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||||
|
goto error;
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_h265_picture_unref (picture);
|
||||||
|
|
||||||
return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
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
|
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,
|
static gboolean gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder,
|
||||||
const GstH265SPS * sps, gint max_dpb_size);
|
const GstH265SPS * sps, gint max_dpb_size);
|
||||||
static gboolean gst_nv_h265_dec_new_picture (GstH265Decoder * decoder,
|
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 *
|
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,
|
static gboolean gst_nv_h265_dec_start_picture (GstH265Decoder * decoder,
|
||||||
GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb);
|
GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb);
|
||||||
static gboolean gst_nv_h265_dec_decode_slice (GstH265Decoder * decoder,
|
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
|
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);
|
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
||||||
GstNvDecoderFrame *frame;
|
GstNvDecoderFrame *frame;
|
||||||
|
@ -435,11 +436,10 @@ gst_nv_h265_dec_new_picture (GstH265Decoder * decoder, GstH265Picture * picture)
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_nv_h265_dec_output_picture (GstH265Decoder * decoder,
|
gst_nv_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||||
GstH265Picture * picture)
|
GstVideoCodecFrame * frame, GstH265Picture * picture)
|
||||||
{
|
{
|
||||||
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
||||||
GstVideoCodecFrame *frame = NULL;
|
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
|
||||||
GstBuffer *output_buffer = NULL;
|
|
||||||
GstNvDecoderFrame *decoder_frame;
|
GstNvDecoderFrame *decoder_frame;
|
||||||
gboolean ret G_GNUC_UNUSED = FALSE;
|
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);
|
(GstNvDecoderFrame *) gst_h265_picture_get_user_data (picture);
|
||||||
if (!decoder_frame) {
|
if (!decoder_frame) {
|
||||||
GST_ERROR_OBJECT (self, "No decoder frame in picture %p", picture);
|
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),
|
frame->output_buffer =
|
||||||
picture->system_frame_number);
|
gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));;
|
||||||
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;
|
|
||||||
|
|
||||||
if (self->output_type == GST_NV_DECOCER_OUTPUT_TYPE_GL) {
|
if (self->output_type == GST_NV_DECOCER_OUTPUT_TYPE_GL) {
|
||||||
ret = gst_nv_decoder_finish_frame (self->decoder,
|
ret = gst_nv_decoder_finish_frame (self->decoder,
|
||||||
GST_NV_DECOCER_OUTPUT_TYPE_GL, self->gl_context,
|
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
|
/* FIXME: This is the case where OpenGL context of downstream glbufferpool
|
||||||
* belongs to non-nvidia (or different device).
|
* belongs to non-nvidia (or different device).
|
||||||
|
@ -483,14 +475,21 @@ gst_nv_h265_dec_output_picture (GstH265Decoder * decoder,
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (!gst_nv_decoder_finish_frame (self->decoder,
|
if (!gst_nv_decoder_finish_frame (self->decoder,
|
||||||
GST_NV_DECOCER_OUTPUT_TYPE_SYSTEM, NULL, decoder_frame,
|
GST_NV_DECOCER_OUTPUT_TYPE_SYSTEM, NULL, decoder_frame,
|
||||||
output_buffer)) {
|
frame->output_buffer)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to finish frame");
|
GST_ERROR_OBJECT (self, "Failed to finish frame");
|
||||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
goto error;
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_h265_picture_unref (picture);
|
||||||
|
|
||||||
return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
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 *
|
static GstNvDecoderFrame *
|
||||||
|
|
Loading…
Reference in a new issue