mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-05 02:02:26 +00:00
splitmuxsink: Implement split-after
The behaviour of split-now is to output the current GOP after starting a new file. The newly-added split-after signal will output the current GOP to the old file if possible once a new GOP is opened. https://bugzilla.gnome.org/show_bug.cgi?id=796982
This commit is contained in:
parent
916ad09009
commit
9605028a71
2 changed files with 41 additions and 7 deletions
|
@ -84,6 +84,7 @@ GST_DEBUG_CATEGORY_STATIC (splitmux_debug);
|
||||||
#define GST_SPLITMUX_BROADCAST_OUTPUT(s) g_cond_broadcast (&(s)->output_cond)
|
#define GST_SPLITMUX_BROADCAST_OUTPUT(s) g_cond_broadcast (&(s)->output_cond)
|
||||||
|
|
||||||
static void split_now (GstSplitMuxSink * splitmux);
|
static void split_now (GstSplitMuxSink * splitmux);
|
||||||
|
static void split_after (GstSplitMuxSink * splitmux);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -130,6 +131,7 @@ enum
|
||||||
SIGNAL_FORMAT_LOCATION,
|
SIGNAL_FORMAT_LOCATION,
|
||||||
SIGNAL_FORMAT_LOCATION_FULL,
|
SIGNAL_FORMAT_LOCATION_FULL,
|
||||||
SIGNAL_SPLIT_NOW,
|
SIGNAL_SPLIT_NOW,
|
||||||
|
SIGNAL_SPLIT_AFTER,
|
||||||
SIGNAL_MUXER_ADDED,
|
SIGNAL_MUXER_ADDED,
|
||||||
SIGNAL_SINK_ADDED,
|
SIGNAL_SINK_ADDED,
|
||||||
SIGNAL_LAST
|
SIGNAL_LAST
|
||||||
|
@ -407,7 +409,7 @@ gst_splitmux_sink_class_init (GstSplitMuxSinkClass * klass)
|
||||||
* @splitmux: the #GstSplitMuxSink
|
* @splitmux: the #GstSplitMuxSink
|
||||||
*
|
*
|
||||||
* When called by the user, this action signal splits the video file (and begins a new one) immediately.
|
* When called by the user, this action signal splits the video file (and begins a new one) immediately.
|
||||||
*
|
* The current GOP will be output to the new file.
|
||||||
*
|
*
|
||||||
* Since: 1.14
|
* Since: 1.14
|
||||||
*/
|
*/
|
||||||
|
@ -416,6 +418,20 @@ gst_splitmux_sink_class_init (GstSplitMuxSinkClass * klass)
|
||||||
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSplitMuxSinkClass,
|
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSplitMuxSinkClass,
|
||||||
split_now), NULL, NULL, NULL, G_TYPE_NONE, 0);
|
split_now), NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstSplitMuxSink::split-after:
|
||||||
|
* @splitmux: the #GstSplitMuxSink
|
||||||
|
*
|
||||||
|
* When called by the user, this action signal splits the video file (and begins a new one) immediately.
|
||||||
|
* The current GOP will be output to the old file.
|
||||||
|
*
|
||||||
|
* Since: 1.16
|
||||||
|
*/
|
||||||
|
signals[SIGNAL_SPLIT_AFTER] =
|
||||||
|
g_signal_new ("split-after", G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSplitMuxSinkClass,
|
||||||
|
split_after), NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstSplitMuxSink::muxer-added:
|
* GstSplitMuxSink::muxer-added:
|
||||||
* @splitmux: the #GstSplitMuxSink
|
* @splitmux: the #GstSplitMuxSink
|
||||||
|
@ -439,6 +455,7 @@ gst_splitmux_sink_class_init (GstSplitMuxSinkClass * klass)
|
||||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
klass->split_now = split_now;
|
klass->split_now = split_now;
|
||||||
|
klass->split_after = split_after;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -468,7 +485,8 @@ gst_splitmux_sink_init (GstSplitMuxSink * splitmux)
|
||||||
splitmux->sink_properties = NULL;
|
splitmux->sink_properties = NULL;
|
||||||
|
|
||||||
GST_OBJECT_FLAG_SET (splitmux, GST_ELEMENT_FLAG_SINK);
|
GST_OBJECT_FLAG_SET (splitmux, GST_ELEMENT_FLAG_SINK);
|
||||||
splitmux->split_now = FALSE;
|
splitmux->split_requested = FALSE;
|
||||||
|
splitmux->do_split_next_gop = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1830,7 +1848,7 @@ need_new_fragment (GstSplitMuxSink * splitmux,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* User told us to split now */
|
/* User told us to split now */
|
||||||
if (g_atomic_int_get (&(splitmux->split_now)) == TRUE)
|
if (g_atomic_int_get (&(splitmux->do_split_next_gop)) == TRUE)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (thresh_bytes > 0 && queued_bytes > thresh_bytes)
|
if (thresh_bytes > 0 && queued_bytes > thresh_bytes)
|
||||||
|
@ -1933,7 +1951,7 @@ handle_gathered_gop (GstSplitMuxSink * splitmux)
|
||||||
*sink_running_time = splitmux->reference_ctx->out_running_time;
|
*sink_running_time = splitmux->reference_ctx->out_running_time;
|
||||||
g_object_set_qdata_full (G_OBJECT (splitmux->sink),
|
g_object_set_qdata_full (G_OBJECT (splitmux->sink),
|
||||||
RUNNING_TIME, sink_running_time, g_free);
|
RUNNING_TIME, sink_running_time, g_free);
|
||||||
g_atomic_int_set (&(splitmux->split_now), FALSE);
|
g_atomic_int_set (&(splitmux->do_split_next_gop), FALSE);
|
||||||
/* Tell the output side to start a new fragment */
|
/* Tell the output side to start a new fragment */
|
||||||
GST_INFO_OBJECT (splitmux,
|
GST_INFO_OBJECT (splitmux,
|
||||||
"This GOP (dur %" GST_STIME_FORMAT
|
"This GOP (dur %" GST_STIME_FORMAT
|
||||||
|
@ -2063,6 +2081,13 @@ check_completed_gop (GstSplitMuxSink * splitmux, MqStreamCtx * ctx)
|
||||||
"Collected GOP is complete. Processing (ctx %p)", ctx);
|
"Collected GOP is complete. Processing (ctx %p)", ctx);
|
||||||
/* All pads have a complete GOP, release it into the multiqueue */
|
/* All pads have a complete GOP, release it into the multiqueue */
|
||||||
handle_gathered_gop (splitmux);
|
handle_gathered_gop (splitmux);
|
||||||
|
|
||||||
|
/* The user has requested a split, we can split now that the previous GOP
|
||||||
|
* has been collected to the correct location */
|
||||||
|
if (g_atomic_int_compare_and_exchange (&(splitmux->split_requested), TRUE,
|
||||||
|
FALSE)) {
|
||||||
|
g_atomic_int_set (&(splitmux->do_split_next_gop), TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2955,7 +2980,8 @@ gst_splitmux_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
g_atomic_int_set (&(splitmux->split_now), FALSE);
|
g_atomic_int_set (&(splitmux->split_requested), FALSE);
|
||||||
|
g_atomic_int_set (&(splitmux->do_split_next_gop), FALSE);
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
GST_SPLITMUX_LOCK (splitmux);
|
GST_SPLITMUX_LOCK (splitmux);
|
||||||
splitmux->output_state = SPLITMUX_OUTPUT_STATE_STOPPED;
|
splitmux->output_state = SPLITMUX_OUTPUT_STATE_STOPPED;
|
||||||
|
@ -3038,5 +3064,11 @@ gst_splitmux_sink_ensure_max_files (GstSplitMuxSink * splitmux)
|
||||||
static void
|
static void
|
||||||
split_now (GstSplitMuxSink * splitmux)
|
split_now (GstSplitMuxSink * splitmux)
|
||||||
{
|
{
|
||||||
g_atomic_int_set (&(splitmux->split_now), TRUE);
|
g_atomic_int_set (&(splitmux->do_split_next_gop), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
split_after (GstSplitMuxSink * splitmux)
|
||||||
|
{
|
||||||
|
g_atomic_int_set (&(splitmux->split_requested), TRUE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,8 @@ struct _GstSplitMuxSink
|
||||||
gboolean use_robust_muxing;
|
gboolean use_robust_muxing;
|
||||||
gboolean muxer_has_reserved_props;
|
gboolean muxer_has_reserved_props;
|
||||||
|
|
||||||
gboolean split_now;
|
gboolean split_requested;
|
||||||
|
gboolean do_split_next_gop;
|
||||||
|
|
||||||
/* Async finalize options */
|
/* Async finalize options */
|
||||||
gboolean async_finalize;
|
gboolean async_finalize;
|
||||||
|
@ -187,6 +188,7 @@ struct _GstSplitMuxSinkClass
|
||||||
|
|
||||||
/* actions */
|
/* actions */
|
||||||
void (*split_now) (GstSplitMuxSink * splitmux);
|
void (*split_now) (GstSplitMuxSink * splitmux);
|
||||||
|
void (*split_after) (GstSplitMuxSink * splitmux);
|
||||||
};
|
};
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
Loading…
Reference in a new issue