mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 23:36:38 +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
cdcc39455c
commit
a039499bf1
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->dropped = 0;
|
||||
base_video_decoder->processed = 0;
|
||||
|
||||
GST_BASE_VIDEO_CODEC (base_video_decoder)->system_frame_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static void
|
||||
gst_base_video_decoder_prepare_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;
|
||||
|
||||
GST_LOG_OBJECT (base_video_decoder, "finish frame");
|
||||
GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder);
|
||||
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
GST_LOG_OBJECT (base_video_decoder, "n %d in %d out %d",
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
GST_DEBUG_OBJECT (base_video_decoder, "skipping frame %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (frame->presentation_timestamp));
|
||||
|
@ -1584,9 +1667,8 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder,
|
|||
}
|
||||
|
||||
done:
|
||||
GST_BASE_VIDEO_CODEC (base_video_decoder)->frames =
|
||||
g_list_remove (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames, frame);
|
||||
gst_base_video_codec_free_frame (frame);
|
||||
|
||||
gst_base_video_decoder_do_finish_frame (base_video_decoder, frame);
|
||||
|
||||
GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder);
|
||||
|
||||
|
|
|
@ -182,6 +182,10 @@ struct _GstBaseVideoDecoder
|
|||
int reorder_depth;
|
||||
int distance_from_sync;
|
||||
|
||||
/* qos messages: frames dropped/processed */
|
||||
guint dropped;
|
||||
guint processed;
|
||||
|
||||
/* FIXME before moving to base */
|
||||
void *padding[GST_PADDING_LARGE];
|
||||
};
|
||||
|
@ -267,7 +271,8 @@ GstClockTimeDiff gst_base_video_decoder_get_max_decode_time (
|
|||
GstVideoFrame *frame);
|
||||
GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder *base_video_decoder,
|
||||
GstVideoFrame *frame);
|
||||
|
||||
GstFlowReturn gst_base_video_decoder_drop_frame (GstBaseVideoDecoder *dec,
|
||||
GstVideoFrame *frame);
|
||||
GType gst_base_video_decoder_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
Loading…
Reference in a new issue