mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-21 03:20:22 +00:00
basevideodecoder: add API to drop a frame and post a QoS message on the bus
https://bugzilla.gnome.org/show_bug.cgi?id=640017 API: gst_base_video_decoder_drop_frame()
This commit is contained in:
parent
f27800d598
commit
f40c93efb0
2 changed files with 113 additions and 26 deletions
|
@ -969,6 +969,9 @@ gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder,
|
||||||
base_video_decoder->current_frame = NULL;
|
base_video_decoder->current_frame = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base_video_decoder->dropped = 0;
|
||||||
|
base_video_decoder->processed = 0;
|
||||||
|
|
||||||
GST_BASE_VIDEO_CODEC (base_video_decoder)->system_frame_number = 0;
|
GST_BASE_VIDEO_CODEC (base_video_decoder)->system_frame_number = 0;
|
||||||
base_video_decoder->base_picture_number = 0;
|
base_video_decoder->base_picture_number = 0;
|
||||||
|
|
||||||
|
@ -1365,30 +1368,12 @@ gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder)
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void
|
||||||
* gst_base_video_decoder_finish_frame:
|
gst_base_video_decoder_prepare_finish_frame (GstBaseVideoDecoder *
|
||||||
* @base_video_decoder: a #GstBaseVideoDecoder
|
base_video_decoder, GstVideoFrame * frame)
|
||||||
* @frame: a decoded #GstVideoFrame
|
|
||||||
*
|
|
||||||
* @frame should have a valid decoded data buffer, whose metadata fields
|
|
||||||
* are then appropriately set according to frame data and pushed downstream.
|
|
||||||
* If no output data is provided, @frame is considered skipped.
|
|
||||||
* In any case, the frame is considered finished and released.
|
|
||||||
*
|
|
||||||
* Returns: a #GstFlowReturn resulting from sending data downstream
|
|
||||||
*/
|
|
||||||
GstFlowReturn
|
|
||||||
gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
|
|
||||||
GstVideoFrame * frame)
|
|
||||||
{
|
{
|
||||||
GstVideoState *state = &GST_BASE_VIDEO_CODEC (base_video_decoder)->state;
|
|
||||||
GstBuffer *src_buffer;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
GList *l, *events = NULL;
|
GList *l, *events = NULL;
|
||||||
|
|
||||||
GST_LOG_OBJECT (base_video_decoder, "finish frame");
|
|
||||||
GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
|
|
||||||
|
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
GST_LOG_OBJECT (base_video_decoder, "n %d in %d out %d",
|
GST_LOG_OBJECT (base_video_decoder, "n %d in %d out %d",
|
||||||
g_list_length (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames),
|
g_list_length (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames),
|
||||||
|
@ -1474,8 +1459,106 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base_video_decoder->last_timestamp = frame->presentation_timestamp;
|
base_video_decoder->last_timestamp = frame->presentation_timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
/* no buffer data means this frame is skipped/dropped */
|
static void
|
||||||
|
gst_base_video_decoder_do_finish_frame (GstBaseVideoDecoder * dec,
|
||||||
|
GstVideoFrame * frame)
|
||||||
|
{
|
||||||
|
GST_BASE_VIDEO_CODEC (dec)->frames =
|
||||||
|
g_list_remove (GST_BASE_VIDEO_CODEC (dec)->frames, frame);
|
||||||
|
|
||||||
|
if (frame->src_buffer)
|
||||||
|
gst_buffer_unref (frame->src_buffer);
|
||||||
|
|
||||||
|
gst_base_video_codec_free_frame (frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_video_decoder_drop_frame:
|
||||||
|
* @dec: a #GstBaseVideoDecoder
|
||||||
|
* @frame: the #GstVideoFrame to drop
|
||||||
|
*
|
||||||
|
* Similar to gst_base_video_decoder_finish_frame(), but drops @frame in any
|
||||||
|
* case and posts a QoS message with the frame's details on the bus.
|
||||||
|
* In any case, the frame is considered finished and released.
|
||||||
|
*
|
||||||
|
* Returns: a #GstFlowReturn, usually GST_FLOW_OK.
|
||||||
|
*
|
||||||
|
* Since: 0.10.23
|
||||||
|
*/
|
||||||
|
GstFlowReturn
|
||||||
|
gst_base_video_decoder_drop_frame (GstBaseVideoDecoder * dec,
|
||||||
|
GstVideoFrame * frame)
|
||||||
|
{
|
||||||
|
GstClockTime stream_time, jitter, earliest_time, qostime, timestamp;
|
||||||
|
GstSegment *segment;
|
||||||
|
GstMessage *qos_msg;
|
||||||
|
gdouble proportion;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (dec, "drop frame");
|
||||||
|
|
||||||
|
GST_BASE_VIDEO_CODEC_STREAM_LOCK (dec);
|
||||||
|
|
||||||
|
gst_base_video_decoder_prepare_finish_frame (dec, frame);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (dec, "dropping frame %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (frame->presentation_timestamp));
|
||||||
|
|
||||||
|
dec->dropped++;
|
||||||
|
|
||||||
|
/* post QoS message */
|
||||||
|
timestamp = frame->presentation_timestamp;
|
||||||
|
proportion = GST_BASE_VIDEO_CODEC (dec)->proportion;
|
||||||
|
segment = &GST_BASE_VIDEO_CODEC (dec)->segment;
|
||||||
|
stream_time =
|
||||||
|
gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp);
|
||||||
|
qostime = gst_segment_to_running_time (segment, GST_FORMAT_TIME, timestamp);
|
||||||
|
earliest_time = GST_BASE_VIDEO_CODEC (dec)->earliest_time;
|
||||||
|
jitter = GST_CLOCK_DIFF (qostime, earliest_time);
|
||||||
|
qos_msg = gst_message_new_qos (GST_OBJECT_CAST (dec), FALSE,
|
||||||
|
qostime, stream_time, timestamp, GST_CLOCK_TIME_NONE);
|
||||||
|
gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000);
|
||||||
|
gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS,
|
||||||
|
dec->processed, dec->dropped);
|
||||||
|
gst_element_post_message (GST_ELEMENT_CAST (dec), qos_msg);
|
||||||
|
|
||||||
|
/* now free the frame */
|
||||||
|
gst_base_video_decoder_do_finish_frame (dec, frame);
|
||||||
|
|
||||||
|
GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (dec);
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_base_video_decoder_finish_frame:
|
||||||
|
* @base_video_decoder: a #GstBaseVideoDecoder
|
||||||
|
* @frame: a decoded #GstVideoFrame
|
||||||
|
*
|
||||||
|
* @frame should have a valid decoded data buffer, whose metadata fields
|
||||||
|
* are then appropriately set according to frame data and pushed downstream.
|
||||||
|
* If no output data is provided, @frame is considered skipped.
|
||||||
|
* In any case, the frame is considered finished and released.
|
||||||
|
*
|
||||||
|
* Returns: a #GstFlowReturn resulting from sending data downstream
|
||||||
|
*/
|
||||||
|
GstFlowReturn
|
||||||
|
gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
|
||||||
|
GstVideoFrame * frame)
|
||||||
|
{
|
||||||
|
GstVideoState *state = &GST_BASE_VIDEO_CODEC (base_video_decoder)->state;
|
||||||
|
GstBuffer *src_buffer;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (base_video_decoder, "finish frame");
|
||||||
|
GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
|
||||||
|
|
||||||
|
gst_base_video_decoder_prepare_finish_frame (base_video_decoder, frame);
|
||||||
|
|
||||||
|
base_video_decoder->processed++;
|
||||||
|
|
||||||
|
/* no buffer data means this frame is skipped */
|
||||||
if (!frame->src_buffer) {
|
if (!frame->src_buffer) {
|
||||||
GST_DEBUG_OBJECT (base_video_decoder, "skipping frame %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (base_video_decoder, "skipping frame %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (frame->presentation_timestamp));
|
GST_TIME_ARGS (frame->presentation_timestamp));
|
||||||
|
@ -1584,9 +1667,8 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
GST_BASE_VIDEO_CODEC (base_video_decoder)->frames =
|
|
||||||
g_list_remove (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames, frame);
|
gst_base_video_decoder_do_finish_frame (base_video_decoder, frame);
|
||||||
gst_base_video_codec_free_frame (frame);
|
|
||||||
|
|
||||||
GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
|
GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,10 @@ struct _GstBaseVideoDecoder
|
||||||
int reorder_depth;
|
int reorder_depth;
|
||||||
int distance_from_sync;
|
int distance_from_sync;
|
||||||
|
|
||||||
|
/* qos messages: frames dropped/processed */
|
||||||
|
guint dropped;
|
||||||
|
guint processed;
|
||||||
|
|
||||||
/* FIXME before moving to base */
|
/* FIXME before moving to base */
|
||||||
void *padding[GST_PADDING_LARGE];
|
void *padding[GST_PADDING_LARGE];
|
||||||
};
|
};
|
||||||
|
@ -267,7 +271,8 @@ GstClockTimeDiff gst_base_video_decoder_get_max_decode_time (
|
||||||
GstVideoFrame *frame);
|
GstVideoFrame *frame);
|
||||||
GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder *base_video_decoder,
|
GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder *base_video_decoder,
|
||||||
GstVideoFrame *frame);
|
GstVideoFrame *frame);
|
||||||
|
GstFlowReturn gst_base_video_decoder_drop_frame (GstBaseVideoDecoder *dec,
|
||||||
|
GstVideoFrame *frame);
|
||||||
GType gst_base_video_decoder_get_type (void);
|
GType gst_base_video_decoder_get_type (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
Loading…
Reference in a new issue