mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-14 05:12:09 +00:00
basevideoencoder: Implement full support for the new force-key-unit event
Including support for the running-time and count fields.
This commit is contained in:
parent
11b2dea82d
commit
3cb4bbe97e
2 changed files with 150 additions and 39 deletions
|
@ -113,6 +113,34 @@
|
||||||
GST_DEBUG_CATEGORY (basevideoencoder_debug);
|
GST_DEBUG_CATEGORY (basevideoencoder_debug);
|
||||||
#define GST_CAT_DEFAULT basevideoencoder_debug
|
#define GST_CAT_DEFAULT basevideoencoder_debug
|
||||||
|
|
||||||
|
typedef struct _ForcedKeyUnitEvent ForcedKeyUnitEvent;
|
||||||
|
struct _ForcedKeyUnitEvent
|
||||||
|
{
|
||||||
|
GstClockTime running_time;
|
||||||
|
gboolean pending; /* TRUE if this was requested already */
|
||||||
|
gboolean all_headers;
|
||||||
|
guint count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
forced_key_unit_event_free (ForcedKeyUnitEvent * evt)
|
||||||
|
{
|
||||||
|
g_slice_free (ForcedKeyUnitEvent, evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ForcedKeyUnitEvent *
|
||||||
|
forced_key_unit_event_new (GstClockTime running_time, gboolean all_headers,
|
||||||
|
guint count)
|
||||||
|
{
|
||||||
|
ForcedKeyUnitEvent *evt = g_slice_new0 (ForcedKeyUnitEvent);
|
||||||
|
|
||||||
|
evt->running_time = running_time;
|
||||||
|
evt->all_headers = all_headers;
|
||||||
|
evt->count = count;
|
||||||
|
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
static void gst_base_video_encoder_finalize (GObject * object);
|
static void gst_base_video_encoder_finalize (GObject * object);
|
||||||
|
|
||||||
static gboolean gst_base_video_encoder_sink_setcaps (GstPad * pad,
|
static gboolean gst_base_video_encoder_sink_setcaps (GstPad * pad,
|
||||||
|
@ -131,7 +159,6 @@ static const GstQueryType *gst_base_video_encoder_get_query_types (GstPad *
|
||||||
static gboolean gst_base_video_encoder_src_query (GstPad * pad,
|
static gboolean gst_base_video_encoder_src_query (GstPad * pad,
|
||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_do_init (GType object_type)
|
_do_init (GType object_type)
|
||||||
{
|
{
|
||||||
|
@ -178,8 +205,11 @@ gst_base_video_encoder_reset (GstBaseVideoEncoder * base_video_encoder)
|
||||||
|
|
||||||
base_video_encoder->presentation_frame_number = 0;
|
base_video_encoder->presentation_frame_number = 0;
|
||||||
base_video_encoder->distance_from_sync = 0;
|
base_video_encoder->distance_from_sync = 0;
|
||||||
base_video_encoder->force_keyframe = FALSE;
|
|
||||||
base_video_encoder->force_keyframe_pending = FALSE;
|
g_list_foreach (base_video_encoder->force_key_unit,
|
||||||
|
(GFunc) forced_key_unit_event_free, NULL);
|
||||||
|
g_list_free (base_video_encoder->force_key_unit);
|
||||||
|
base_video_encoder->force_key_unit = NULL;
|
||||||
|
|
||||||
base_video_encoder->drained = TRUE;
|
base_video_encoder->drained = TRUE;
|
||||||
base_video_encoder->min_latency = 0;
|
base_video_encoder->min_latency = 0;
|
||||||
|
@ -521,16 +551,25 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder,
|
||||||
case GST_EVENT_CUSTOM_DOWNSTREAM:
|
case GST_EVENT_CUSTOM_DOWNSTREAM:
|
||||||
{
|
{
|
||||||
if (gst_video_event_is_force_key_unit (event)) {
|
if (gst_video_event_is_force_key_unit (event)) {
|
||||||
GST_OBJECT_LOCK (base_video_encoder);
|
GstClockTime running_time;
|
||||||
|
gboolean all_headers;
|
||||||
|
guint count;
|
||||||
|
|
||||||
base_video_encoder->force_keyframe = TRUE;
|
if (gst_video_event_parse_downstream_force_key_unit (event,
|
||||||
gst_video_event_parse_downstream_force_key_unit (event, NULL, NULL,
|
NULL, NULL, &running_time, &all_headers, &count)) {
|
||||||
NULL, &base_video_encoder->force_keyframe_headers, NULL);
|
ForcedKeyUnitEvent *fevt;
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (base_video_encoder);
|
||||||
|
fevt = forced_key_unit_event_new (running_time, all_headers, count);
|
||||||
|
base_video_encoder->force_key_unit =
|
||||||
|
g_list_append (base_video_encoder->force_key_unit, fevt);
|
||||||
|
GST_OBJECT_UNLOCK (base_video_encoder);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (base_video_encoder,
|
GST_DEBUG_OBJECT (base_video_encoder,
|
||||||
"force-keyunit event, all-headers %d",
|
"force-key-unit event: running-time %" GST_TIME_FORMAT
|
||||||
base_video_encoder->force_keyframe_headers);
|
", all_headers %d, count %u",
|
||||||
GST_OBJECT_UNLOCK (base_video_encoder);
|
GST_TIME_ARGS (running_time), all_headers, count);
|
||||||
|
}
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -608,16 +647,26 @@ gst_base_video_encoder_src_event (GstPad * pad, GstEvent * event)
|
||||||
case GST_EVENT_CUSTOM_UPSTREAM:
|
case GST_EVENT_CUSTOM_UPSTREAM:
|
||||||
{
|
{
|
||||||
if (gst_video_event_is_force_key_unit (event)) {
|
if (gst_video_event_is_force_key_unit (event)) {
|
||||||
|
GstClockTime running_time;
|
||||||
|
gboolean all_headers;
|
||||||
|
guint count;
|
||||||
|
|
||||||
|
if (gst_video_event_parse_upstream_force_key_unit (event,
|
||||||
|
&running_time, &all_headers, &count)) {
|
||||||
|
ForcedKeyUnitEvent *fevt;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (base_video_encoder);
|
GST_OBJECT_LOCK (base_video_encoder);
|
||||||
base_video_encoder->force_keyframe = TRUE;
|
fevt = forced_key_unit_event_new (running_time, all_headers, count);
|
||||||
gst_video_event_parse_upstream_force_key_unit (event, NULL,
|
base_video_encoder->force_key_unit =
|
||||||
&base_video_encoder->force_keyframe_headers, NULL);
|
g_list_append (base_video_encoder->force_key_unit, fevt);
|
||||||
GST_OBJECT_UNLOCK (base_video_encoder);
|
GST_OBJECT_UNLOCK (base_video_encoder);
|
||||||
|
|
||||||
gst_event_unref (event);
|
|
||||||
GST_DEBUG_OBJECT (base_video_encoder,
|
GST_DEBUG_OBJECT (base_video_encoder,
|
||||||
"force-keyunit event, all-headers %d",
|
"force-key-unit event: running-time %" GST_TIME_FORMAT
|
||||||
base_video_encoder->force_keyframe_headers);
|
", all_headers %d, count %u",
|
||||||
|
GST_TIME_ARGS (running_time), all_headers, count);
|
||||||
|
}
|
||||||
|
gst_event_unref (event);
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
} else {
|
} else {
|
||||||
ret =
|
ret =
|
||||||
|
@ -774,9 +823,46 @@ gst_base_video_encoder_chain (GstPad * pad, GstBuffer * buf)
|
||||||
frame->presentation_frame_number =
|
frame->presentation_frame_number =
|
||||||
base_video_encoder->presentation_frame_number;
|
base_video_encoder->presentation_frame_number;
|
||||||
base_video_encoder->presentation_frame_number++;
|
base_video_encoder->presentation_frame_number++;
|
||||||
frame->force_keyframe = base_video_encoder->force_keyframe;
|
|
||||||
base_video_encoder->force_keyframe = FALSE;
|
GST_OBJECT_LOCK (base_video_encoder);
|
||||||
base_video_encoder->force_keyframe_pending = TRUE;
|
if (base_video_encoder->force_key_unit) {
|
||||||
|
ForcedKeyUnitEvent *fevt = NULL;
|
||||||
|
GstClockTime running_time;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
running_time = gst_segment_to_running_time (&GST_BASE_VIDEO_CODEC
|
||||||
|
(base_video_encoder)->segment, GST_FORMAT_TIME,
|
||||||
|
GST_BUFFER_TIMESTAMP (buf));
|
||||||
|
|
||||||
|
for (l = base_video_encoder->force_key_unit; l; l = l->next) {
|
||||||
|
ForcedKeyUnitEvent *tmp = l->data;
|
||||||
|
|
||||||
|
/* Skip pending keyunits */
|
||||||
|
if (tmp->pending)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Simple case, keyunit ASAP */
|
||||||
|
if (tmp->running_time == GST_CLOCK_TIME_NONE) {
|
||||||
|
fevt = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Event for before this frame */
|
||||||
|
if (tmp->running_time <= running_time) {
|
||||||
|
fevt = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fevt) {
|
||||||
|
GST_DEBUG_OBJECT (base_video_encoder,
|
||||||
|
"Forcing a key unit at running time %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (running_time));
|
||||||
|
frame->force_keyframe = TRUE;
|
||||||
|
fevt->pending = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (base_video_encoder);
|
||||||
|
|
||||||
GST_BASE_VIDEO_CODEC (base_video_encoder)->frames =
|
GST_BASE_VIDEO_CODEC (base_video_encoder)->frames =
|
||||||
g_list_append (GST_BASE_VIDEO_CODEC (base_video_encoder)->frames, frame);
|
g_list_append (GST_BASE_VIDEO_CODEC (base_video_encoder)->frames, frame);
|
||||||
|
@ -890,38 +976,66 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame->is_sync_point && base_video_encoder->force_keyframe_pending) {
|
if (frame->is_sync_point && base_video_encoder->force_key_unit) {
|
||||||
GstClockTime stream_time;
|
GstClockTime stream_time, running_time;
|
||||||
GstClockTime running_time;
|
|
||||||
GstEvent *ev;
|
GstEvent *ev;
|
||||||
|
ForcedKeyUnitEvent *fevt = NULL;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
base_video_encoder->force_keyframe_pending = FALSE;
|
running_time = gst_segment_to_running_time (&GST_BASE_VIDEO_CODEC
|
||||||
|
|
||||||
running_time =
|
|
||||||
gst_segment_to_running_time (&GST_BASE_VIDEO_CODEC
|
|
||||||
(base_video_encoder)->segment, GST_FORMAT_TIME,
|
(base_video_encoder)->segment, GST_FORMAT_TIME,
|
||||||
frame->presentation_timestamp);
|
frame->presentation_timestamp);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (base_video_encoder);
|
||||||
|
for (l = base_video_encoder->force_key_unit; l; l = l->next) {
|
||||||
|
ForcedKeyUnitEvent *tmp = l->data;
|
||||||
|
|
||||||
|
/* Skip pending keyunits */
|
||||||
|
if (tmp->pending)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Simple case, keyunit ASAP */
|
||||||
|
if (tmp->running_time == GST_CLOCK_TIME_NONE) {
|
||||||
|
fevt = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Event for before this frame */
|
||||||
|
if (tmp->running_time <= running_time) {
|
||||||
|
fevt = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base_video_encoder->force_key_unit =
|
||||||
|
g_list_remove (base_video_encoder->force_key_unit, fevt);
|
||||||
|
GST_OBJECT_UNLOCK (base_video_encoder);
|
||||||
|
|
||||||
|
/* Should really be here */
|
||||||
|
g_assert (fevt);
|
||||||
|
|
||||||
stream_time =
|
stream_time =
|
||||||
gst_segment_to_stream_time (&GST_BASE_VIDEO_CODEC
|
gst_segment_to_stream_time (&GST_BASE_VIDEO_CODEC
|
||||||
(base_video_encoder)->segment, GST_FORMAT_TIME,
|
(base_video_encoder)->segment, GST_FORMAT_TIME,
|
||||||
frame->presentation_timestamp);
|
frame->presentation_timestamp);
|
||||||
|
|
||||||
/* FIXME: Use the correct count */
|
|
||||||
ev = gst_video_event_new_downstream_force_key_unit
|
ev = gst_video_event_new_downstream_force_key_unit
|
||||||
(frame->presentation_timestamp, stream_time, running_time,
|
(frame->presentation_timestamp, stream_time, running_time,
|
||||||
base_video_encoder->force_keyframe_headers, 0);
|
fevt->all_headers, fevt->count);
|
||||||
|
|
||||||
gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), ev);
|
gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), ev);
|
||||||
|
|
||||||
if (base_video_encoder->force_keyframe_headers) {
|
if (fevt->all_headers) {
|
||||||
GST_DEBUG_OBJECT (base_video_encoder, "force_keyframe_headers");
|
|
||||||
if (base_video_encoder->headers) {
|
if (base_video_encoder->headers) {
|
||||||
headers = gst_buffer_ref (base_video_encoder->headers);
|
headers = gst_buffer_ref (base_video_encoder->headers);
|
||||||
headers = gst_buffer_make_writable (headers);
|
headers = gst_buffer_make_writable (headers);
|
||||||
}
|
}
|
||||||
base_video_encoder->force_keyframe_headers = FALSE;
|
|
||||||
}
|
}
|
||||||
GST_LOG_OBJECT (base_video_encoder, "key frame, headers %p", headers);
|
|
||||||
|
GST_DEBUG_OBJECT (base_video_encoder,
|
||||||
|
"Forced key unit: running-time %" GST_TIME_FORMAT
|
||||||
|
", all_headers %d, count %u",
|
||||||
|
GST_TIME_ARGS (running_time), fevt->all_headers, fevt->count);
|
||||||
|
forced_key_unit_event_free (fevt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame->is_sync_point) {
|
if (frame->is_sync_point) {
|
||||||
|
|
|
@ -84,8 +84,6 @@ struct _GstBaseVideoEncoder
|
||||||
guint64 presentation_frame_number;
|
guint64 presentation_frame_number;
|
||||||
int distance_from_sync;
|
int distance_from_sync;
|
||||||
|
|
||||||
gboolean force_keyframe;
|
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* FIXME move to real private part ?
|
/* FIXME move to real private part ?
|
||||||
* (and introduce a context ?) */
|
* (and introduce a context ?) */
|
||||||
|
@ -99,8 +97,7 @@ struct _GstBaseVideoEncoder
|
||||||
|
|
||||||
GstBuffer *headers;
|
GstBuffer *headers;
|
||||||
|
|
||||||
gboolean force_keyframe_pending;
|
GList *force_key_unit; /* List of pending forced keyunits */
|
||||||
gboolean force_keyframe_headers;
|
|
||||||
|
|
||||||
void *padding[GST_PADDING_LARGE];
|
void *padding[GST_PADDING_LARGE];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue