hlssink,hlssink2: Ensure writing ENDLIST tag at the end

hlssink* elements could be finalized without EOS event, and in that case
the final playlist might not include the EXT-X-ENDLIST tag.
Since missing ENDLIST tag means it's live stream, but we did't intend it,
hlssink* elements should put the tag at the end.
This commit is contained in:
Seungha Yang 2019-10-01 15:36:29 +09:00
parent 71ff8236b5
commit d763aeee4b
5 changed files with 30 additions and 0 deletions

View file

@ -209,6 +209,8 @@ gst_hls_sink_reset (GstHlsSink * sink)
sink->playlist =
gst_m3u8_playlist_new (GST_M3U8_PLAYLIST_VERSION, sink->playlist_length,
FALSE);
sink->state = GST_M3U8_PLAYLIST_RENDER_INIT;
}
static gboolean
@ -304,6 +306,7 @@ gst_hls_sink_handle_message (GstBin * bin, GstMessage * message)
g_free (entry_location);
gst_hls_sink_write_playlist (sink);
sink->state |= GST_M3U8_PLAYLIST_RENDER_STARTED;
/* multifilesink is starting a new file. It means that upstream sent a key
* unit and we can schedule the next key unit now.
@ -321,6 +324,7 @@ gst_hls_sink_handle_message (GstBin * bin, GstMessage * message)
case GST_MESSAGE_EOS:{
sink->playlist->end_list = TRUE;
gst_hls_sink_write_playlist (sink);
sink->state |= GST_M3U8_PLAYLIST_RENDER_ENDED;
break;
}
default:
@ -355,6 +359,12 @@ gst_hls_sink_change_state (GstElement * element, GstStateChange trans)
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* drain playlist with #EXT-X-ENDLIST */
if (sink->playlist && (sink->state & GST_M3U8_PLAYLIST_RENDER_STARTED) &&
!(sink->state & GST_M3U8_PLAYLIST_RENDER_ENDED)) {
sink->playlist->end_list = TRUE;
gst_hls_sink_write_playlist (sink);
}
gst_hls_sink_reset (sink);
break;
case GST_STATE_CHANGE_READY_TO_NULL:

View file

@ -54,6 +54,7 @@ struct _GstHlsSink
GstSegment segment;
gboolean waiting_fku;
GstClockTime last_running_time;
GstM3U8PlaylistRenderState state;
};
struct _GstHlsSinkClass

View file

@ -227,6 +227,8 @@ gst_hls_sink2_reset (GstHlsSink2 * sink)
g_queue_foreach (&sink->old_locations, (GFunc) g_free, NULL);
g_queue_clear (&sink->old_locations);
sink->state = GST_M3U8_PLAYLIST_RENDER_INIT;
}
static void
@ -288,6 +290,7 @@ gst_hls_sink2_handle_message (GstBin * bin, GstMessage * message)
g_free (entry_location);
gst_hls_sink2_write_playlist (sink);
sink->state |= GST_M3U8_PLAYLIST_RENDER_STARTED;
g_queue_push_tail (&sink->old_locations,
g_strdup (sink->current_location));
@ -305,6 +308,7 @@ gst_hls_sink2_handle_message (GstBin * bin, GstMessage * message)
case GST_MESSAGE_EOS:{
sink->playlist->end_list = TRUE;
gst_hls_sink2_write_playlist (sink);
sink->state |= GST_M3U8_PLAYLIST_RENDER_ENDED;
break;
}
default:
@ -397,6 +401,13 @@ gst_hls_sink2_change_state (GstElement * element, GstStateChange trans)
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* drain playlist with #EXT-X-ENDLIST */
if (sink->playlist && (sink->state & GST_M3U8_PLAYLIST_RENDER_STARTED) &&
!(sink->state & GST_M3U8_PLAYLIST_RENDER_ENDED)) {
sink->playlist->end_list = TRUE;
gst_hls_sink2_write_playlist (sink);
}
/* fall-through */
case GST_STATE_CHANGE_READY_TO_NULL:
gst_hls_sink2_reset (sink);
break;

View file

@ -55,6 +55,7 @@ struct _GstHlsSink2
gchar *current_location;
GstClockTime current_running_time_start;
GQueue old_locations;
GstM3U8PlaylistRenderState state;
};
struct _GstHlsSink2Class

View file

@ -41,6 +41,13 @@ struct _GstM3U8Playlist
GQueue *entries;
};
typedef enum
{
GST_M3U8_PLAYLIST_RENDER_INIT = (1 << 0),
GST_M3U8_PLAYLIST_RENDER_STARTED = (1 << 1),
GST_M3U8_PLAYLIST_RENDER_ENDED = (1 << 2),
} GstM3U8PlaylistRenderState;
GstM3U8Playlist * gst_m3u8_playlist_new (guint version,
guint window_size,