1 /* GStreamer split muxer bin 2 * Copyright (C) 2014-2019 Jan Schmidt <jan@centricular.com> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #ifndef __GST_SPLITMUXSINK_H__ 21 #define __GST_SPLITMUXSINK_H__ 22 23 #include <gst/gst.h> 24 #include <gst/pbutils/pbutils.h> 25 #include <gst/base/base.h> 26 27 G_BEGIN_DECLS 28 #define GST_TYPE_SPLITMUX_SINK (gst_splitmux_sink_get_type()) 29 #define GST_SPLITMUX_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SPLITMUX_SINK,GstSplitMuxSink)) 30 #define GST_SPLITMUX_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SPLITMUX_SINK,GstSplitMuxSinkClass)) 31 #define GST_IS_SPLITMUX_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPLITMUX_SINK)) 32 #define GST_IS_SPLITMUX_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPLITMUX_SINK)) 33 typedef struct _GstSplitMuxSink GstSplitMuxSink; 34 typedef struct _GstSplitMuxSinkClass GstSplitMuxSinkClass; 35 36 GType gst_splitmux_sink_get_type (void); 37 38 typedef enum _SplitMuxInputState 39 { 40 SPLITMUX_INPUT_STATE_STOPPED, 41 SPLITMUX_INPUT_STATE_COLLECTING_GOP_START, /* Waiting for the next ref ctx keyframe */ 42 SPLITMUX_INPUT_STATE_WAITING_GOP_COLLECT, /* Waiting for all streams to collect GOP */ 43 SPLITMUX_INPUT_STATE_FINISHING_UP /* Got EOS from reference ctx, send everything */ 44 } SplitMuxInputState; 45 46 typedef enum _SplitMuxOutputState 47 { 48 SPLITMUX_OUTPUT_STATE_STOPPED, 49 SPLITMUX_OUTPUT_STATE_AWAITING_COMMAND, /* Waiting first command packet from input */ 50 SPLITMUX_OUTPUT_STATE_OUTPUT_GOP, /* Outputting a collected GOP */ 51 SPLITMUX_OUTPUT_STATE_ENDING_FILE, /* Finishing the current fragment */ 52 SPLITMUX_OUTPUT_STATE_ENDING_STREAM, /* Finishing up the entire stream due to input EOS */ 53 SPLITMUX_OUTPUT_STATE_START_NEXT_FILE /* Restarting after ENDING_FILE */ 54 } SplitMuxOutputState; 55 56 typedef struct _SplitMuxOutputCommand 57 { 58 gboolean start_new_fragment; /* Whether to start a new fragment before advancing output ts */ 59 GstClockTimeDiff max_output_ts; /* Set the limit to stop GOP output */ 60 } SplitMuxOutputCommand; 61 62 typedef struct _MqStreamBuf 63 { 64 gboolean keyframe; 65 GstClockTimeDiff run_ts; 66 guint64 buf_size; 67 GstClockTime duration; 68 } MqStreamBuf; 69 70 typedef struct { 71 /* For the very first GOP if it was created from a GAP event */ 72 gboolean from_gap; 73 74 /* Minimum start time (PTS or DTS) of the GOP */ 75 GstClockTimeDiff start_time; 76 /* Start time (PTS) of the GOP */ 77 GstClockTimeDiff start_time_pts; 78 /* Minimum start timecode of the GOP */ 79 GstVideoTimeCode *start_tc; 80 81 /* Number of bytes we've collected into the GOP */ 82 guint64 total_bytes; 83 /* Number of bytes from the reference context 84 * that we've collected into the GOP */ 85 guint64 reference_bytes; 86 87 gboolean sent_fku; 88 } InputGop; 89 90 typedef struct _MqStreamCtx 91 { 92 GstSplitMuxSink *splitmux; 93 94 guint q_overrun_id; 95 guint sink_pad_block_id; 96 guint src_pad_block_id; 97 gulong fragment_block_id; 98 99 gboolean is_reference; 100 101 gboolean flushing; 102 gboolean in_eos; 103 gboolean out_eos; 104 gboolean out_eos_async_done; 105 gboolean need_unblock; 106 gboolean caps_change; 107 gboolean is_releasing; 108 109 GstSegment in_segment; 110 GstSegment out_segment; 111 112 GstClockTimeDiff in_running_time; 113 GstClockTimeDiff out_running_time; 114 115 GstElement *q; 116 GQueue queued_bufs; 117 118 GstPad *sinkpad; 119 GstPad *srcpad; 120 121 GstBuffer *cur_out_buffer; 122 GstEvent *pending_gap; 123 } MqStreamCtx; 124 125 struct _GstSplitMuxSink 126 { 127 GstBin parent; 128 129 GMutex state_lock; 130 gboolean shutdown; 131 132 GMutex lock; 133 134 GCond input_cond; 135 GCond output_cond; 136 137 gdouble mux_overhead; 138 139 GstClockTime threshold_time; 140 guint64 threshold_bytes; 141 guint max_files; 142 gboolean send_keyframe_requests; 143 gchar *threshold_timecode_str; 144 /* created from threshold_timecode_str */ 145 GstVideoTimeCodeInterval *tc_interval; 146 GstClockTime alignment_threshold; 147 /* expected running time of next force keyframe unit event */ 148 GstClockTime next_fku_time; 149 150 gboolean reset_muxer; 151 152 GstElement *muxer; 153 GstElement *sink; 154 155 GstElement *provided_muxer; 156 157 GstElement *provided_sink; 158 GstElement *active_sink; 159 160 gboolean ready_for_output; 161 162 gchar *location; 163 guint fragment_id; 164 guint start_index; 165 GList *contexts; 166 167 SplitMuxInputState input_state; 168 GstClockTimeDiff max_in_running_time; 169 GstClockTimeDiff max_in_running_time_dts; 170 171 /* Number of bytes sent to the 172 * current fragment */ 173 guint64 fragment_total_bytes; 174 /* Number of bytes for the reference 175 * stream in this fragment */ 176 guint64 fragment_reference_bytes; 177 178 /* Minimum start time (PTS or DTS) of the current fragment */ 179 GstClockTimeDiff fragment_start_time; 180 /* Start time (PTS) of the current fragment */ 181 GstClockTimeDiff fragment_start_time_pts; 182 /* Minimum start timecode of the current fragment */ 183 GstVideoTimeCode *fragment_start_tc; 184 185 /* Oldest GOP at head, newest GOP at tail */ 186 GQueue pending_input_gops; 187 188 /* expected running time of next fragment in timecode mode */ 189 GstClockTime next_fragment_start_tc_time; 190 191 GQueue out_cmd_q; /* Queue of commands for output thread */ 192 193 SplitMuxOutputState output_state; 194 GstClockTimeDiff max_out_running_time; 195 196 guint64 muxed_out_bytes; 197 198 MqStreamCtx *reference_ctx; 199 /* Count of queued keyframes in the reference ctx */ 200 guint queued_keyframes; 201 202 gboolean switching_fragment; 203 204 gboolean have_video; 205 206 gboolean need_async_start; 207 gboolean async_pending; 208 209 gboolean use_robust_muxing; 210 gboolean muxer_has_reserved_props; 211 212 gboolean split_requested; 213 gboolean do_split_next_gop; 214 GstQueueArray *times_to_split; 215 216 /* Async finalize options */ 217 gboolean async_finalize; 218 gchar *muxer_factory; 219 gchar *muxer_preset; 220 GstStructure *muxer_properties; 221 gchar *sink_factory; 222 gchar *sink_preset; 223 GstStructure *sink_properties; 224 225 GstStructure *muxerpad_map; 226 }; 227 228 struct _GstSplitMuxSinkClass 229 { 230 GstBinClass parent_class; 231 232 /* actions */ 233 void (*split_now) (GstSplitMuxSink * splitmux); 234 void (*split_after) (GstSplitMuxSink * splitmux); 235 void (*split_at_running_time) (GstSplitMuxSink * splitmux, GstClockTime split_time); 236 }; 237 238 GST_ELEMENT_REGISTER_DECLARE (splitmuxsink); 239 240 G_END_DECLS 241 #endif /* __GST_SPLITMUXSINK_H__ */ 242