177 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_sink_dispose); |
186 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_sink_dispose); |
178 |
187 |
179 g_object_class_install_property (gobject_class, PROP_BUFFER_TIME, |
188 g_object_class_install_property (gobject_class, PROP_BUFFER_TIME, |
180 g_param_spec_int64 ("buffer-time", "Buffer Time", |
189 g_param_spec_int64 ("buffer-time", "Buffer Time", |
181 "Size of audio buffer in microseconds", 1, |
190 "Size of audio buffer in microseconds", 1, |
182 G_MAXINT64, DEFAULT_BUFFER_TIME, G_PARAM_READWRITE)); |
191 G_MAXINT64, DEFAULT_BUFFER_TIME, |
|
192 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
183 |
193 |
184 g_object_class_install_property (gobject_class, PROP_LATENCY_TIME, |
194 g_object_class_install_property (gobject_class, PROP_LATENCY_TIME, |
185 g_param_spec_int64 ("latency-time", "Latency Time", |
195 g_param_spec_int64 ("latency-time", "Latency Time", |
186 "Audio latency in microseconds", 1, |
196 "Audio latency in microseconds", 1, |
187 G_MAXINT64, DEFAULT_LATENCY_TIME, G_PARAM_READWRITE)); |
197 G_MAXINT64, DEFAULT_LATENCY_TIME, |
|
198 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
188 |
199 |
189 g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK, |
200 g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK, |
190 g_param_spec_boolean ("provide-clock", "Provide Clock", |
201 g_param_spec_boolean ("provide-clock", "Provide Clock", |
191 "Provide a clock to be used as the global pipeline clock", |
202 "Provide a clock to be used as the global pipeline clock", |
192 DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE)); |
203 DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
193 |
204 |
194 g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD, |
205 g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD, |
195 g_param_spec_enum ("slave-method", "Slave Method", |
206 g_param_spec_enum ("slave-method", "Slave Method", |
196 "Algorithm to use to match the rate of the masterclock", |
207 "Algorithm to use to match the rate of the masterclock", |
197 GST_TYPE_SLAVE_METHOD, DEFAULT_SLAVE_METHOD, G_PARAM_READWRITE)); |
208 GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD, DEFAULT_SLAVE_METHOD, |
|
209 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
|
210 |
|
211 g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL, |
|
212 g_param_spec_boolean ("can-activate-pull", "Allow Pull Scheduling", |
|
213 "Allow pull-based scheduling", DEFAULT_CAN_ACTIVATE_PULL, |
|
214 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
198 |
215 |
199 gstelement_class->change_state = |
216 gstelement_class->change_state = |
200 GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state); |
217 GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state); |
201 gstelement_class->provide_clock = |
218 gstelement_class->provide_clock = |
202 GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock); |
219 GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock); |
295 return NULL; |
316 return NULL; |
296 } |
317 } |
297 } |
318 } |
298 |
319 |
299 static gboolean |
320 static gboolean |
|
321 gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query) |
|
322 { |
|
323 gboolean res = FALSE; |
|
324 GstBaseAudioSink *basesink; |
|
325 |
|
326 basesink = GST_BASE_AUDIO_SINK (gst_pad_get_parent (pad)); |
|
327 |
|
328 switch (GST_QUERY_TYPE (query)) { |
|
329 case GST_QUERY_CONVERT: |
|
330 { |
|
331 GstFormat src_fmt, dest_fmt; |
|
332 gint64 src_val, dest_val; |
|
333 |
|
334 GST_LOG_OBJECT (pad, "query convert"); |
|
335 |
|
336 if (basesink->ringbuffer) { |
|
337 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL); |
|
338 res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val, |
|
339 dest_fmt, &dest_val); |
|
340 if (res) { |
|
341 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); |
|
342 } |
|
343 } |
|
344 break; |
|
345 } |
|
346 default: |
|
347 break; |
|
348 } |
|
349 |
|
350 gst_object_unref (basesink); |
|
351 |
|
352 return res; |
|
353 } |
|
354 |
|
355 static gboolean |
300 gst_base_audio_sink_query (GstElement * element, GstQuery * query) |
356 gst_base_audio_sink_query (GstElement * element, GstQuery * query) |
301 { |
357 { |
302 gboolean res = FALSE; |
358 gboolean res = FALSE; |
303 |
359 GstBaseAudioSink *basesink; |
304 GstBaseAudioSink *basesink = GST_BASE_AUDIO_SINK (element); |
360 |
|
361 basesink = GST_BASE_AUDIO_SINK (element); |
305 |
362 |
306 switch (GST_QUERY_TYPE (query)) { |
363 switch (GST_QUERY_TYPE (query)) { |
307 case GST_QUERY_LATENCY: |
364 case GST_QUERY_LATENCY: |
308 { |
365 { |
309 gboolean live, us_live; |
366 gboolean live, us_live; |
347 GST_TIME_FORMAT, GST_TIME_ARGS (min_l), |
404 GST_TIME_FORMAT, GST_TIME_ARGS (min_l), |
348 GST_TIME_ARGS (min_latency)); |
405 GST_TIME_ARGS (min_latency)); |
349 } else { |
406 } else { |
350 GST_DEBUG_OBJECT (basesink, |
407 GST_DEBUG_OBJECT (basesink, |
351 "peer or we are not live, don't care about latency"); |
408 "peer or we are not live, don't care about latency"); |
352 min_latency = 0; |
409 min_latency = min_l; |
353 max_latency = -1; |
410 max_latency = max_l; |
354 } |
411 } |
355 gst_query_set_latency (query, live, min_latency, max_latency); |
412 gst_query_set_latency (query, live, min_latency, max_latency); |
356 } |
413 } |
357 break; |
414 break; |
358 } |
415 } |
|
416 case GST_QUERY_CONVERT: |
|
417 { |
|
418 GstFormat src_fmt, dest_fmt; |
|
419 gint64 src_val, dest_val; |
|
420 |
|
421 GST_LOG_OBJECT (basesink, "query convert"); |
|
422 |
|
423 if (basesink->ringbuffer) { |
|
424 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL); |
|
425 res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val, |
|
426 dest_fmt, &dest_val); |
|
427 if (res) { |
|
428 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); |
|
429 } |
|
430 } |
|
431 break; |
|
432 } |
359 default: |
433 default: |
360 res = GST_ELEMENT_CLASS (parent_class)->query (element, query); |
434 res = GST_ELEMENT_CLASS (parent_class)->query (element, query); |
361 break; |
435 break; |
362 } |
436 } |
363 |
437 |
674 * we have successfully negotiated a format and thus acquired the |
753 * we have successfully negotiated a format and thus acquired the |
675 * ringbuffer. */ |
754 * ringbuffer. */ |
676 if (gst_ring_buffer_is_acquired (sink->ringbuffer)) |
755 if (gst_ring_buffer_is_acquired (sink->ringbuffer)) |
677 gst_ring_buffer_start (sink->ringbuffer); |
756 gst_ring_buffer_start (sink->ringbuffer); |
678 |
757 |
679 if (sink->next_sample != -1) { |
758 if (sink->priv->eos_time != -1) { |
680 GstClockTime time; |
|
681 |
|
682 /* convert next expected sample to time */ |
|
683 time = |
|
684 gst_util_uint64_scale_int (sink->next_sample, GST_SECOND, |
|
685 sink->ringbuffer->spec.rate); |
|
686 |
|
687 GST_DEBUG_OBJECT (sink, |
759 GST_DEBUG_OBJECT (sink, |
688 "last sample %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, |
760 "last sample time %" GST_TIME_FORMAT, |
689 sink->next_sample, GST_TIME_ARGS (time)); |
761 GST_TIME_ARGS (sink->priv->eos_time)); |
690 |
|
691 /* our time already includes the base_time, _wait_eos() wants a running_time |
|
692 * so we have to subtract the base_time again here. FIXME, store an |
|
693 * unadjusted EOS time so that we don't have to do this. */ |
|
694 GST_OBJECT_LOCK (sink); |
|
695 base_time = GST_ELEMENT_CAST (sink)->base_time; |
|
696 GST_OBJECT_UNLOCK (sink); |
|
697 |
|
698 if (time > base_time) |
|
699 time -= base_time; |
|
700 else |
|
701 time = 0; |
|
702 |
762 |
703 /* wait for the EOS time to be reached, this is the time when the last |
763 /* wait for the EOS time to be reached, this is the time when the last |
704 * sample is played. */ |
764 * sample is played. */ |
705 gst_base_sink_wait_eos (GST_BASE_SINK (sink), time, NULL); |
765 gst_base_sink_wait_eos (GST_BASE_SINK (sink), sink->priv->eos_time, NULL); |
706 |
766 |
707 sink->next_sample = -1; |
767 GST_DEBUG_OBJECT (sink, "drained audio"); |
708 } |
768 } |
709 return TRUE; |
769 return TRUE; |
710 } |
770 } |
711 |
771 |
712 static gboolean |
772 static gboolean |
801 return sample; |
862 return sample; |
802 } |
863 } |
803 |
864 |
804 static GstClockTime |
865 static GstClockTime |
805 clock_convert_external (GstClockTime external, GstClockTime cinternal, |
866 clock_convert_external (GstClockTime external, GstClockTime cinternal, |
806 GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom, |
867 GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom) |
807 GstClockTime us_latency) |
|
808 { |
868 { |
809 /* adjust for rate and speed */ |
869 /* adjust for rate and speed */ |
810 if (external >= cexternal) { |
870 if (external >= cexternal) { |
811 external = |
871 external = |
812 gst_util_uint64_scale (external - cexternal, crate_denom, crate_num); |
872 gst_util_uint64_scale (external - cexternal, crate_denom, crate_num); |
813 external += cinternal; |
873 external += cinternal; |
814 } else { |
874 } else { |
815 external = gst_util_uint64_scale (cexternal - external, |
875 external = |
816 crate_denom, crate_num); |
876 gst_util_uint64_scale (cexternal - external, crate_denom, crate_num); |
817 if (cinternal > external) |
877 if (cinternal > external) |
818 external = cinternal - external; |
878 external = cinternal - external; |
819 else |
879 else |
820 external = 0; |
880 external = 0; |
821 } |
881 } |
822 /* adjust for offset when slaving started */ |
|
823 if (external > us_latency) |
|
824 external -= us_latency; |
|
825 else |
|
826 external = 0; |
|
827 |
|
828 return external; |
882 return external; |
829 } |
883 } |
830 |
884 |
831 /* algorithm to calculate sample positions that will result in resampling to |
885 /* algorithm to calculate sample positions that will result in resampling to |
832 * match the clock rate of the master */ |
886 * match the clock rate of the master */ |
836 GstClockTime * srender_start, GstClockTime * srender_stop) |
890 GstClockTime * srender_start, GstClockTime * srender_stop) |
837 { |
891 { |
838 GstClockTime cinternal, cexternal; |
892 GstClockTime cinternal, cexternal; |
839 GstClockTime crate_num, crate_denom; |
893 GstClockTime crate_num, crate_denom; |
840 |
894 |
|
895 /* FIXME, we can sample and add observations here or use the timeouts on the |
|
896 * clock. No idea which one is better or more stable. The timeout seems more |
|
897 * arbitrary but this one seems more demanding and does not work when there is |
|
898 * no data comming in to the sink. */ |
|
899 #if 0 |
|
900 GstClockTime etime, itime; |
|
901 gdouble r_squared; |
|
902 |
|
903 /* sample clocks and figure out clock skew */ |
|
904 etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink)); |
|
905 itime = gst_audio_clock_get_time (sink->provided_clock); |
|
906 |
|
907 /* add new observation */ |
|
908 gst_clock_add_observation (sink->provided_clock, itime, etime, &r_squared); |
|
909 #endif |
|
910 |
841 /* get calibration parameters to compensate for speed and offset differences |
911 /* get calibration parameters to compensate for speed and offset differences |
842 * when we are slaved */ |
912 * when we are slaved */ |
843 gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, |
913 gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, |
844 &crate_num, &crate_denom); |
914 &crate_num, &crate_denom); |
845 |
915 |
883 gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, |
953 gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, |
884 &crate_num, &crate_denom); |
954 &crate_num, &crate_denom); |
885 |
955 |
886 /* sample clocks and figure out clock skew */ |
956 /* sample clocks and figure out clock skew */ |
887 etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink)); |
957 etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink)); |
888 itime = gst_clock_get_internal_time (sink->provided_clock); |
958 itime = gst_audio_clock_get_time (sink->provided_clock); |
889 |
959 |
890 etime -= cexternal; |
960 GST_DEBUG_OBJECT (sink, |
891 itime -= cinternal; |
961 "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT |
892 |
962 " cinternal %" GST_TIME_FORMAT " cexternal %" GST_TIME_FORMAT, |
|
963 GST_TIME_ARGS (itime), GST_TIME_ARGS (etime), |
|
964 GST_TIME_ARGS (cinternal), GST_TIME_ARGS (cexternal)); |
|
965 |
|
966 /* make sure we never go below 0 */ |
|
967 etime = etime > cexternal ? etime - cexternal : 0; |
|
968 itime = itime > cinternal ? itime - cinternal : 0; |
|
969 |
|
970 /* do itime - etime. |
|
971 * positive value means external clock goes slower |
|
972 * negative value means external clock goes faster */ |
893 skew = GST_CLOCK_DIFF (etime, itime); |
973 skew = GST_CLOCK_DIFF (etime, itime); |
894 if (sink->priv->avg_skew == -1) { |
974 if (sink->priv->avg_skew == -1) { |
895 /* first observation */ |
975 /* first observation */ |
896 sink->priv->avg_skew = skew; |
976 sink->priv->avg_skew = skew; |
897 } else { |
977 } else { |
1013 g_warning ("unknown slaving method %d", sink->priv->slave_method); |
1093 g_warning ("unknown slaving method %d", sink->priv->slave_method); |
1014 break; |
1094 break; |
1015 } |
1095 } |
1016 } |
1096 } |
1017 |
1097 |
|
1098 /* must be called with LOCK */ |
|
1099 static GstFlowReturn |
|
1100 gst_base_audio_sink_sync_latency (GstBaseSink * bsink, GstMiniObject * obj) |
|
1101 { |
|
1102 GstClock *clock; |
|
1103 GstClockReturn status; |
|
1104 GstClockTime time; |
|
1105 GstFlowReturn ret; |
|
1106 GstBaseAudioSink *sink; |
|
1107 GstClockTime itime, etime; |
|
1108 GstClockTime rate_num, rate_denom; |
|
1109 GstClockTimeDiff jitter; |
|
1110 |
|
1111 sink = GST_BASE_AUDIO_SINK (bsink); |
|
1112 |
|
1113 clock = GST_ELEMENT_CLOCK (sink); |
|
1114 if (G_UNLIKELY (clock == NULL)) |
|
1115 goto no_clock; |
|
1116 |
|
1117 /* we provided the global clock, don't need to do anything special */ |
|
1118 if (clock == sink->provided_clock) |
|
1119 goto no_slaving; |
|
1120 |
|
1121 GST_OBJECT_UNLOCK (sink); |
|
1122 |
|
1123 do { |
|
1124 GST_DEBUG_OBJECT (sink, "checking preroll"); |
|
1125 |
|
1126 ret = gst_base_sink_do_preroll (bsink, obj); |
|
1127 if (ret != GST_FLOW_OK) |
|
1128 goto flushing; |
|
1129 |
|
1130 GST_OBJECT_LOCK (sink); |
|
1131 time = sink->priv->us_latency; |
|
1132 GST_OBJECT_UNLOCK (sink); |
|
1133 |
|
1134 /* preroll done, we can sync since we are in PLAYING now. */ |
|
1135 GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %" |
|
1136 GST_TIME_FORMAT, GST_TIME_ARGS (time)); |
|
1137 |
|
1138 /* wait for the clock, this can be interrupted because we got shut down or |
|
1139 * we PAUSED. */ |
|
1140 status = gst_base_sink_wait_clock (bsink, time, &jitter); |
|
1141 |
|
1142 GST_DEBUG_OBJECT (sink, "clock returned %d %" GST_TIME_FORMAT, status, |
|
1143 GST_TIME_ARGS (jitter)); |
|
1144 |
|
1145 /* invalid time, no clock or sync disabled, just continue then */ |
|
1146 if (status == GST_CLOCK_BADTIME) |
|
1147 break; |
|
1148 |
|
1149 /* waiting could have been interrupted and we can be flushing now */ |
|
1150 if (G_UNLIKELY (bsink->flushing)) |
|
1151 goto flushing; |
|
1152 |
|
1153 /* retry if we got unscheduled, which means we did not reach the timeout |
|
1154 * yet. if some other error occures, we continue. */ |
|
1155 } while (status == GST_CLOCK_UNSCHEDULED); |
|
1156 |
|
1157 GST_OBJECT_LOCK (sink); |
|
1158 GST_DEBUG_OBJECT (sink, "latency synced"); |
|
1159 |
|
1160 /* when we prerolled in time, we can accurately set the calibration, |
|
1161 * our internal clock should exactly have been the latency (== the running |
|
1162 * time of the external clock) */ |
|
1163 etime = GST_ELEMENT_CAST (sink)->base_time + time; |
|
1164 itime = gst_audio_clock_get_time (sink->provided_clock); |
|
1165 |
|
1166 if (status == GST_CLOCK_EARLY) { |
|
1167 /* when we prerolled late, we have to take into account the lateness */ |
|
1168 GST_DEBUG_OBJECT (sink, "late preroll, adding jitter"); |
|
1169 etime += jitter; |
|
1170 } |
|
1171 |
|
1172 /* start ringbuffer so we can start slaving right away when we need to */ |
|
1173 gst_ring_buffer_start (sink->ringbuffer); |
|
1174 |
|
1175 GST_DEBUG_OBJECT (sink, |
|
1176 "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT, |
|
1177 GST_TIME_ARGS (itime), GST_TIME_ARGS (etime)); |
|
1178 |
|
1179 /* copy the original calibrated rate but update the internal and external |
|
1180 * times. */ |
|
1181 gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num, |
|
1182 &rate_denom); |
|
1183 gst_clock_set_calibration (sink->provided_clock, itime, etime, |
|
1184 rate_num, rate_denom); |
|
1185 |
|
1186 switch (sink->priv->slave_method) { |
|
1187 case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE: |
|
1188 /* only set as master when we are resampling */ |
|
1189 GST_DEBUG_OBJECT (sink, "Setting clock as master"); |
|
1190 gst_clock_set_master (sink->provided_clock, clock); |
|
1191 break; |
|
1192 case GST_BASE_AUDIO_SINK_SLAVE_SKEW: |
|
1193 case GST_BASE_AUDIO_SINK_SLAVE_NONE: |
|
1194 default: |
|
1195 break; |
|
1196 } |
|
1197 |
|
1198 sink->priv->avg_skew = -1; |
|
1199 sink->next_sample = -1; |
|
1200 sink->priv->eos_time = -1; |
|
1201 |
|
1202 return GST_FLOW_OK; |
|
1203 |
|
1204 /* ERRORS */ |
|
1205 no_clock: |
|
1206 { |
|
1207 GST_DEBUG_OBJECT (sink, "we have no clock"); |
|
1208 return GST_FLOW_OK; |
|
1209 } |
|
1210 no_slaving: |
|
1211 { |
|
1212 GST_DEBUG_OBJECT (sink, "we are not slaved"); |
|
1213 return GST_FLOW_OK; |
|
1214 } |
|
1215 flushing: |
|
1216 { |
|
1217 GST_DEBUG_OBJECT (sink, "we are flushing"); |
|
1218 GST_OBJECT_LOCK (sink); |
|
1219 return GST_FLOW_WRONG_STATE; |
|
1220 } |
|
1221 } |
|
1222 |
1018 static GstFlowReturn |
1223 static GstFlowReturn |
1019 gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) |
1224 gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) |
1020 { |
1225 { |
1021 guint64 in_offset; |
1226 guint64 in_offset; |
1022 GstClockTime time, stop, render_start, render_stop, sample_offset; |
1227 GstClockTime time, stop, render_start, render_stop, sample_offset; |
|
1228 GstClockTimeDiff sync_offset, ts_offset; |
1023 GstBaseAudioSink *sink; |
1229 GstBaseAudioSink *sink; |
1024 GstRingBuffer *ringbuf; |
1230 GstRingBuffer *ringbuf; |
1025 gint64 diff, align, ctime, cstop; |
1231 gint64 diff, align, ctime, cstop; |
1026 guint8 *data; |
1232 guint8 *data; |
1027 guint size; |
1233 guint size; |
1028 guint samples, written; |
1234 guint samples, written; |
1029 gint bps; |
1235 gint bps; |
1030 gint accum; |
1236 gint accum; |
1031 gint out_samples; |
1237 gint out_samples; |
1032 GstClockTime base_time = GST_CLOCK_TIME_NONE, latency; |
1238 GstClockTime base_time, render_delay, latency; |
1033 GstClock *clock; |
1239 GstClock *clock; |
1034 gboolean sync, slaved, align_next; |
1240 gboolean sync, slaved, align_next; |
|
1241 GstFlowReturn ret; |
|
1242 GstSegment clip_seg; |
1035 |
1243 |
1036 sink = GST_BASE_AUDIO_SINK (bsink); |
1244 sink = GST_BASE_AUDIO_SINK (bsink); |
1037 |
1245 |
1038 ringbuf = sink->ringbuffer; |
1246 ringbuf = sink->ringbuffer; |
1039 |
1247 |
1040 /* can't do anything when we don't have the device */ |
1248 /* can't do anything when we don't have the device */ |
1041 if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuf))) |
1249 if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuf))) |
1042 goto wrong_state; |
1250 goto wrong_state; |
1043 |
1251 |
|
1252 /* Wait for upstream latency before starting the ringbuffer, we do this so |
|
1253 * that we can align the first sample of the ringbuffer to the base_time + |
|
1254 * latency. */ |
|
1255 GST_OBJECT_LOCK (sink); |
|
1256 base_time = GST_ELEMENT_CAST (sink)->base_time; |
|
1257 if (G_UNLIKELY (sink->priv->sync_latency)) { |
|
1258 ret = gst_base_audio_sink_sync_latency (bsink, GST_MINI_OBJECT_CAST (buf)); |
|
1259 GST_OBJECT_UNLOCK (sink); |
|
1260 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
|
1261 goto sync_latency_failed; |
|
1262 /* only do this once until we are set back to PLAYING */ |
|
1263 sink->priv->sync_latency = FALSE; |
|
1264 } else { |
|
1265 GST_OBJECT_UNLOCK (sink); |
|
1266 } |
|
1267 |
1044 bps = ringbuf->spec.bytes_per_sample; |
1268 bps = ringbuf->spec.bytes_per_sample; |
1045 |
1269 |
1046 size = GST_BUFFER_SIZE (buf); |
1270 size = GST_BUFFER_SIZE (buf); |
1047 if (G_UNLIKELY (size % bps) != 0) |
1271 if (G_UNLIKELY (size % bps) != 0) |
1048 goto wrong_size; |
1272 goto wrong_size; |
1068 render_start = gst_base_audio_sink_get_offset (sink); |
1290 render_start = gst_base_audio_sink_get_offset (sink); |
1069 render_stop = render_start + samples; |
1291 render_stop = render_start + samples; |
1070 GST_DEBUG_OBJECT (sink, |
1292 GST_DEBUG_OBJECT (sink, |
1071 "Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT, |
1293 "Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT, |
1072 GST_BUFFER_SIZE (buf), render_start); |
1294 GST_BUFFER_SIZE (buf), render_start); |
|
1295 /* we don't have a start so we don't know stop either */ |
|
1296 stop = -1; |
1073 goto no_sync; |
1297 goto no_sync; |
|
1298 } |
|
1299 |
|
1300 /* let's calc stop based on the number of samples in the buffer instead |
|
1301 * of trusting the DURATION */ |
|
1302 stop = time + gst_util_uint64_scale_int (samples, GST_SECOND, |
|
1303 ringbuf->spec.rate); |
|
1304 |
|
1305 /* prepare the clipping segment. Since we will be subtracting ts-offset and |
|
1306 * device-delay later we scale the start and stop with those values so that we |
|
1307 * can correctly clip them */ |
|
1308 clip_seg.format = GST_FORMAT_TIME; |
|
1309 clip_seg.start = bsink->segment.start; |
|
1310 clip_seg.stop = bsink->segment.stop; |
|
1311 clip_seg.duration = -1; |
|
1312 |
|
1313 /* the sync offset is the combination of ts-offset and device-delay */ |
|
1314 latency = gst_base_sink_get_latency (bsink); |
|
1315 ts_offset = gst_base_sink_get_ts_offset (bsink); |
|
1316 render_delay = gst_base_sink_get_render_delay (bsink); |
|
1317 sync_offset = ts_offset - render_delay + latency; |
|
1318 |
|
1319 GST_DEBUG_OBJECT (sink, |
|
1320 "sync-offset %" G_GINT64_FORMAT ", render-delay %" GST_TIME_FORMAT |
|
1321 ", ts-offset %" G_GINT64_FORMAT, sync_offset, |
|
1322 GST_TIME_ARGS (render_delay), ts_offset); |
|
1323 |
|
1324 /* compensate for ts-offset and device-delay when negative we need to |
|
1325 * clip. */ |
|
1326 if (sync_offset < 0) { |
|
1327 clip_seg.start += -sync_offset; |
|
1328 if (clip_seg.stop != -1) |
|
1329 clip_seg.stop += -sync_offset; |
1074 } |
1330 } |
1075 |
1331 |
1076 /* samples should be rendered based on their timestamp. All samples |
1332 /* samples should be rendered based on their timestamp. All samples |
1077 * arriving before the segment.start or after segment.stop are to be |
1333 * arriving before the segment.start or after segment.stop are to be |
1078 * thrown away. All samples should also be clipped to the segment |
1334 * thrown away. All samples should also be clipped to the segment |
1079 * boundaries */ |
1335 * boundaries */ |
1080 /* let's calc stop based on the number of samples in the buffer instead |
1336 if (!gst_segment_clip (&clip_seg, GST_FORMAT_TIME, time, stop, &ctime, |
1081 * of trusting the DURATION */ |
|
1082 if (!gst_segment_clip (&bsink->segment, GST_FORMAT_TIME, time, stop, &ctime, |
|
1083 &cstop)) |
1337 &cstop)) |
1084 goto out_of_segment; |
1338 goto out_of_segment; |
1085 |
1339 |
1086 /* see if some clipping happened */ |
1340 /* see if some clipping happened */ |
1087 diff = ctime - time; |
1341 diff = ctime - time; |
1127 |
1381 |
1128 GST_DEBUG_OBJECT (sink, |
1382 GST_DEBUG_OBJECT (sink, |
1129 "running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, |
1383 "running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, |
1130 GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); |
1384 GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); |
1131 |
1385 |
1132 base_time = gst_element_get_base_time (GST_ELEMENT_CAST (bsink)); |
1386 /* store the time of the last sample, we'll use this to perform sync on the |
1133 |
1387 * last sample when draining the buffer */ |
1134 GST_DEBUG_OBJECT (sink, "base_time %" GST_TIME_FORMAT, |
1388 if (bsink->segment.rate >= 0.0) { |
|
1389 sink->priv->eos_time = render_stop; |
|
1390 } else { |
|
1391 sink->priv->eos_time = render_start; |
|
1392 } |
|
1393 |
|
1394 /* compensate for ts-offset and delay we know this will not underflow because we |
|
1395 * clipped above. */ |
|
1396 GST_DEBUG_OBJECT (sink, |
|
1397 "compensating for sync-offset %" GST_TIME_FORMAT, |
|
1398 GST_TIME_ARGS (sync_offset)); |
|
1399 render_start += sync_offset; |
|
1400 render_stop += sync_offset; |
|
1401 |
|
1402 GST_DEBUG_OBJECT (sink, "adding base_time %" GST_TIME_FORMAT, |
1135 GST_TIME_ARGS (base_time)); |
1403 GST_TIME_ARGS (base_time)); |
1136 |
1404 |
1137 /* add base time to sync against the clock */ |
1405 /* add base time to sync against the clock */ |
1138 render_start += base_time; |
1406 render_start += base_time; |
1139 render_stop += base_time; |
1407 render_stop += base_time; |
1140 |
1408 |
1141 /* compensate for latency */ |
|
1142 latency = gst_base_sink_get_latency (bsink); |
|
1143 GST_DEBUG_OBJECT (sink, |
1409 GST_DEBUG_OBJECT (sink, |
1144 "compensating for latency %" GST_TIME_FORMAT, GST_TIME_ARGS (latency)); |
1410 "after compensation: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, |
1145 |
|
1146 /* add latency to get the timestamp to sync against the pipeline clock */ |
|
1147 render_start += latency; |
|
1148 render_stop += latency; |
|
1149 |
|
1150 GST_DEBUG_OBJECT (sink, |
|
1151 "after latency: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, |
|
1152 GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); |
1411 GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); |
1153 |
1412 |
1154 if ((slaved = clock != sink->provided_clock)) { |
1413 if ((slaved = clock != sink->provided_clock)) { |
1155 /* handle clock slaving */ |
1414 /* handle clock slaving */ |
1156 gst_base_audio_sink_handle_slaving (sink, render_start, render_stop, |
1415 gst_base_audio_sink_handle_slaving (sink, render_start, render_stop, |
|
1416 &render_start, &render_stop); |
|
1417 } else { |
|
1418 /* no slaving needed but we need to adapt to the clock calibration |
|
1419 * parameters */ |
|
1420 gst_base_audio_sink_none_slaving (sink, render_start, render_stop, |
1157 &render_start, &render_stop); |
1421 &render_start, &render_stop); |
1158 } |
1422 } |
1159 |
1423 |
1160 /* and bring the time to the rate corrected offset in the buffer */ |
1424 /* and bring the time to the rate corrected offset in the buffer */ |
1161 render_start = gst_util_uint64_scale_int (render_start, |
1425 render_start = gst_util_uint64_scale_int (render_start, |
1162 ringbuf->spec.rate, GST_SECOND); |
1426 ringbuf->spec.rate, GST_SECOND); |
1163 render_stop = gst_util_uint64_scale_int (render_stop, |
1427 render_stop = gst_util_uint64_scale_int (render_stop, |
1164 ringbuf->spec.rate, GST_SECOND); |
1428 ringbuf->spec.rate, GST_SECOND); |
1165 |
1429 |
|
1430 /* positive playback rate, first sample is render_start, negative rate, first |
|
1431 * sample is render_stop. When no rate conversion is active, render exactly |
|
1432 * the amount of input samples to avoid aligning to rounding errors. */ |
|
1433 if (bsink->segment.rate >= 0.0) { |
|
1434 sample_offset = render_start; |
|
1435 if (bsink->segment.rate == 1.0) |
|
1436 render_stop = sample_offset + samples; |
|
1437 } else { |
|
1438 sample_offset = render_stop; |
|
1439 if (bsink->segment.rate == -1.0) |
|
1440 render_start = sample_offset + samples; |
|
1441 } |
|
1442 |
1166 /* always resync after a discont */ |
1443 /* always resync after a discont */ |
1167 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) { |
1444 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) { |
1168 GST_DEBUG_OBJECT (sink, "resync after discont"); |
1445 GST_DEBUG_OBJECT (sink, "resync after discont"); |
1169 goto no_align; |
1446 goto no_align; |
1170 } |
1447 } |
1171 |
1448 |
|
1449 /* resync when we don't know what to align the sample with */ |
1172 if (G_UNLIKELY (sink->next_sample == -1)) { |
1450 if (G_UNLIKELY (sink->next_sample == -1)) { |
1173 GST_DEBUG_OBJECT (sink, |
1451 GST_DEBUG_OBJECT (sink, |
1174 "no align possible: no previous sample position known"); |
1452 "no align possible: no previous sample position known"); |
1175 goto no_align; |
1453 goto no_align; |
1176 } |
1454 } |
1177 |
1455 |
1178 /* positive playback rate, first sample is render_start, negative rate, first |
1456 /* now try to align the sample to the previous one, first see how big the |
1179 * sample is render_stop */ |
1457 * difference is. */ |
1180 if (bsink->segment.rate >= 1.0) |
|
1181 sample_offset = render_start; |
|
1182 else |
|
1183 sample_offset = render_stop; |
|
1184 |
|
1185 /* now try to align the sample to the previous one */ |
|
1186 if (sample_offset >= sink->next_sample) |
1458 if (sample_offset >= sink->next_sample) |
1187 diff = sample_offset - sink->next_sample; |
1459 diff = sample_offset - sink->next_sample; |
1188 else |
1460 else |
1189 diff = sink->next_sample - sample_offset; |
1461 diff = sink->next_sample - sample_offset; |
1190 |
1462 |
1366 GstFlowReturn ret; |
1633 GstFlowReturn ret; |
1367 |
1634 |
1368 basesink = GST_BASE_SINK (user_data); |
1635 basesink = GST_BASE_SINK (user_data); |
1369 sink = GST_BASE_AUDIO_SINK (user_data); |
1636 sink = GST_BASE_AUDIO_SINK (user_data); |
1370 |
1637 |
|
1638 GST_PAD_STREAM_LOCK (basesink->sinkpad); |
|
1639 |
1371 /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we |
1640 /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we |
1372 will copy twice, once into data, once into DMA */ |
1641 will copy twice, once into data, once into DMA */ |
1373 GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT |
1642 GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT |
1374 " to fill audio buffer", len, basesink->offset); |
1643 " to fill audio buffer", len, basesink->offset); |
1375 ret = gst_pad_pull_range (basesink->sinkpad, basesink->offset, len, &buf); |
1644 ret = |
|
1645 gst_pad_pull_range (basesink->sinkpad, basesink->segment.last_stop, len, |
|
1646 &buf); |
1376 |
1647 |
1377 if (ret != GST_FLOW_OK) { |
1648 if (ret != GST_FLOW_OK) { |
1378 if (ret == GST_FLOW_UNEXPECTED) |
1649 if (ret == GST_FLOW_UNEXPECTED) |
1379 goto eos; |
1650 goto eos; |
1380 else |
1651 else |
1381 goto error; |
1652 goto error; |
1382 } |
1653 } |
1383 |
1654 |
|
1655 GST_PAD_PREROLL_LOCK (basesink->sinkpad); |
|
1656 if (basesink->flushing) |
|
1657 goto flushing; |
|
1658 |
|
1659 /* complete preroll and wait for PLAYING */ |
|
1660 ret = gst_base_sink_do_preroll (basesink, GST_MINI_OBJECT_CAST (buf)); |
|
1661 if (ret != GST_FLOW_OK) |
|
1662 goto preroll_error; |
|
1663 |
1384 if (len != GST_BUFFER_SIZE (buf)) { |
1664 if (len != GST_BUFFER_SIZE (buf)) { |
1385 GST_INFO_OBJECT (basesink, "short read pulling from sink pad: %d<%d", |
1665 GST_INFO_OBJECT (basesink, |
1386 len, GST_BUFFER_SIZE (buf)); |
1666 "got different size than requested from sink pad: %u != %u", len, |
|
1667 GST_BUFFER_SIZE (buf)); |
1387 len = MIN (GST_BUFFER_SIZE (buf), len); |
1668 len = MIN (GST_BUFFER_SIZE (buf), len); |
1388 } |
1669 } |
1389 |
1670 |
1390 basesink->offset += len; |
1671 basesink->segment.last_stop += len; |
1391 |
1672 |
1392 memcpy (data, GST_BUFFER_DATA (buf), len); |
1673 memcpy (data, GST_BUFFER_DATA (buf), len); |
|
1674 GST_PAD_PREROLL_UNLOCK (basesink->sinkpad); |
|
1675 |
|
1676 GST_PAD_STREAM_UNLOCK (basesink->sinkpad); |
1393 |
1677 |
1394 return; |
1678 return; |
1395 |
1679 |
1396 error: |
1680 error: |
1397 { |
1681 { |
1398 GST_WARNING_OBJECT (basesink, "Got flow error but can't return it: %d", |
1682 GST_WARNING_OBJECT (basesink, "Got flow '%s' but can't return it: %d", |
1399 ret); |
1683 gst_flow_get_name (ret), ret); |
|
1684 gst_ring_buffer_pause (rbuf); |
|
1685 GST_PAD_STREAM_UNLOCK (basesink->sinkpad); |
1400 return; |
1686 return; |
1401 } |
1687 } |
1402 eos: |
1688 eos: |
1403 { |
1689 { |
1404 /* FIXME: this is not quite correct; we'll be called endlessly until |
1690 /* FIXME: this is not quite correct; we'll be called endlessly until |
1405 * the sink gets shut down; maybe we should set a flag somewhere, or |
1691 * the sink gets shut down; maybe we should set a flag somewhere, or |
1406 * set segment.stop and segment.duration to the last sample or so */ |
1692 * set segment.stop and segment.duration to the last sample or so */ |
1407 GST_DEBUG_OBJECT (sink, "EOS"); |
1693 GST_DEBUG_OBJECT (sink, "EOS"); |
|
1694 gst_base_audio_sink_drain (sink); |
|
1695 gst_ring_buffer_pause (rbuf); |
1408 gst_element_post_message (GST_ELEMENT_CAST (sink), |
1696 gst_element_post_message (GST_ELEMENT_CAST (sink), |
1409 gst_message_new_eos (GST_OBJECT_CAST (sink))); |
1697 gst_message_new_eos (GST_OBJECT_CAST (sink))); |
1410 gst_base_audio_sink_drain (sink); |
1698 GST_PAD_STREAM_UNLOCK (basesink->sinkpad); |
1411 } |
1699 } |
|
1700 flushing: |
|
1701 { |
|
1702 GST_DEBUG_OBJECT (sink, "we are flushing"); |
|
1703 gst_ring_buffer_pause (rbuf); |
|
1704 GST_PAD_PREROLL_UNLOCK (basesink->sinkpad); |
|
1705 GST_PAD_STREAM_UNLOCK (basesink->sinkpad); |
|
1706 return; |
|
1707 } |
|
1708 preroll_error: |
|
1709 { |
|
1710 GST_DEBUG_OBJECT (sink, "error %s", gst_flow_get_name (ret)); |
|
1711 gst_ring_buffer_pause (rbuf); |
|
1712 GST_PAD_PREROLL_UNLOCK (basesink->sinkpad); |
|
1713 GST_PAD_STREAM_UNLOCK (basesink->sinkpad); |
|
1714 return; |
|
1715 } |
|
1716 } |
|
1717 |
|
1718 static gboolean |
|
1719 gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active) |
|
1720 { |
|
1721 gboolean ret; |
|
1722 GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink); |
|
1723 |
|
1724 if (active) { |
|
1725 GST_DEBUG_OBJECT (basesink, "activating pull"); |
|
1726 |
|
1727 gst_ring_buffer_set_callback (sink->ringbuffer, |
|
1728 gst_base_audio_sink_callback, sink); |
|
1729 |
|
1730 ret = gst_ring_buffer_activate (sink->ringbuffer, TRUE); |
|
1731 } else { |
|
1732 GST_DEBUG_OBJECT (basesink, "deactivating pull"); |
|
1733 gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL); |
|
1734 ret = gst_ring_buffer_activate (sink->ringbuffer, FALSE); |
|
1735 } |
|
1736 |
|
1737 return ret; |
1412 } |
1738 } |
1413 |
1739 |
1414 /* should be called with the LOCK */ |
1740 /* should be called with the LOCK */ |
1415 static GstStateChangeReturn |
1741 static GstStateChangeReturn |
1416 gst_base_audio_sink_async_play (GstBaseSink * basesink) |
1742 gst_base_audio_sink_async_play (GstBaseSink * basesink) |
1417 { |
1743 { |
1418 GstClock *clock; |
|
1419 GstBaseAudioSink *sink; |
1744 GstBaseAudioSink *sink; |
1420 GstClockTime itime, etime; |
|
1421 GstClockTime rate_num, rate_denom; |
|
1422 |
1745 |
1423 sink = GST_BASE_AUDIO_SINK (basesink); |
1746 sink = GST_BASE_AUDIO_SINK (basesink); |
1424 |
1747 |
1425 GST_DEBUG_OBJECT (sink, "ringbuffer may start now"); |
1748 GST_DEBUG_OBJECT (sink, "ringbuffer may start now"); |
|
1749 sink->priv->sync_latency = TRUE; |
1426 gst_ring_buffer_may_start (sink->ringbuffer, TRUE); |
1750 gst_ring_buffer_may_start (sink->ringbuffer, TRUE); |
1427 |
1751 if (basesink->pad_mode == GST_ACTIVATE_PULL) { |
1428 clock = GST_ELEMENT_CLOCK (sink); |
1752 /* we always start the ringbuffer in pull mode immediatly */ |
1429 if (clock == NULL) |
1753 gst_ring_buffer_start (sink->ringbuffer); |
1430 goto done; |
1754 } |
1431 |
1755 |
1432 /* we provided the global clock, don't need to do anything special */ |
|
1433 if (clock == sink->provided_clock) |
|
1434 goto done; |
|
1435 |
|
1436 /* if we are slaved to a clock, we need to set the initial |
|
1437 * calibration */ |
|
1438 /* get external and internal time to set as calibration params */ |
|
1439 etime = gst_clock_get_time (clock); |
|
1440 itime = gst_clock_get_internal_time (sink->provided_clock); |
|
1441 |
|
1442 sink->priv->avg_skew = -1; |
|
1443 sink->next_sample = -1; |
|
1444 |
|
1445 GST_DEBUG_OBJECT (sink, |
|
1446 "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT, |
|
1447 GST_TIME_ARGS (itime), GST_TIME_ARGS (etime)); |
|
1448 |
|
1449 gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num, |
|
1450 &rate_denom); |
|
1451 gst_clock_set_calibration (sink->provided_clock, itime, etime, |
|
1452 rate_num, rate_denom); |
|
1453 |
|
1454 switch (sink->priv->slave_method) { |
|
1455 case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE: |
|
1456 /* only set as master if we need to resample */ |
|
1457 GST_DEBUG_OBJECT (sink, "Setting clock as master"); |
|
1458 gst_clock_set_master (sink->provided_clock, clock); |
|
1459 break; |
|
1460 default: |
|
1461 break; |
|
1462 } |
|
1463 |
|
1464 /* start ringbuffer so we can start slaving right away when we need to */ |
|
1465 gst_ring_buffer_start (sink->ringbuffer); |
|
1466 |
|
1467 done: |
|
1468 return GST_STATE_CHANGE_SUCCESS; |
1756 return GST_STATE_CHANGE_SUCCESS; |
1469 } |
|
1470 |
|
1471 static GstStateChangeReturn |
|
1472 gst_base_audio_sink_do_play (GstBaseAudioSink * sink) |
|
1473 { |
|
1474 GstStateChangeReturn ret; |
|
1475 |
|
1476 GST_OBJECT_LOCK (sink); |
|
1477 ret = gst_base_audio_sink_async_play (GST_BASE_SINK_CAST (sink)); |
|
1478 GST_OBJECT_UNLOCK (sink); |
|
1479 |
|
1480 return ret; |
|
1481 } |
1757 } |
1482 |
1758 |
1483 static GstStateChangeReturn |
1759 static GstStateChangeReturn |
1484 gst_base_audio_sink_change_state (GstElement * element, |
1760 gst_base_audio_sink_change_state (GstElement * element, |
1485 GstStateChange transition) |
1761 GstStateChange transition) |
1488 GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (element); |
1764 GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (element); |
1489 |
1765 |
1490 switch (transition) { |
1766 switch (transition) { |
1491 case GST_STATE_CHANGE_NULL_TO_READY: |
1767 case GST_STATE_CHANGE_NULL_TO_READY: |
1492 if (sink->ringbuffer == NULL) { |
1768 if (sink->ringbuffer == NULL) { |
|
1769 gst_audio_clock_reset (GST_AUDIO_CLOCK (sink->provided_clock), 0); |
1493 sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink); |
1770 sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink); |
1494 } |
1771 } |
1495 if (!gst_ring_buffer_open_device (sink->ringbuffer)) |
1772 if (!gst_ring_buffer_open_device (sink->ringbuffer)) |
1496 goto open_failed; |
1773 goto open_failed; |
1497 break; |
1774 break; |
1498 case GST_STATE_CHANGE_READY_TO_PAUSED: |
1775 case GST_STATE_CHANGE_READY_TO_PAUSED: |
1499 sink->next_sample = -1; |
1776 sink->next_sample = -1; |
1500 sink->priv->last_align = -1; |
1777 sink->priv->last_align = -1; |
|
1778 sink->priv->eos_time = -1; |
1501 gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE); |
1779 gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE); |
1502 gst_ring_buffer_may_start (sink->ringbuffer, FALSE); |
1780 gst_ring_buffer_may_start (sink->ringbuffer, FALSE); |
1503 break; |
1781 break; |
1504 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
1782 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
1505 gst_base_audio_sink_do_play (sink); |
1783 GST_OBJECT_LOCK (sink); |
|
1784 GST_DEBUG_OBJECT (sink, "ringbuffer may start now"); |
|
1785 sink->priv->sync_latency = TRUE; |
|
1786 GST_OBJECT_UNLOCK (sink); |
|
1787 |
|
1788 gst_ring_buffer_may_start (sink->ringbuffer, TRUE); |
|
1789 if (GST_BASE_SINK_CAST (sink)->pad_mode == GST_ACTIVATE_PULL) { |
|
1790 /* we always start the ringbuffer in pull mode immediatly */ |
|
1791 gst_ring_buffer_start (sink->ringbuffer); |
|
1792 } |
1506 break; |
1793 break; |
1507 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
1794 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
1508 /* need to take the lock so we don't interfere with an |
|
1509 * async play */ |
|
1510 GST_OBJECT_LOCK (sink); |
|
1511 /* ringbuffer cannot start anymore */ |
1795 /* ringbuffer cannot start anymore */ |
1512 gst_ring_buffer_may_start (sink->ringbuffer, FALSE); |
1796 gst_ring_buffer_may_start (sink->ringbuffer, FALSE); |
1513 gst_ring_buffer_pause (sink->ringbuffer); |
1797 gst_ring_buffer_pause (sink->ringbuffer); |
|
1798 |
|
1799 GST_OBJECT_LOCK (sink); |
|
1800 sink->priv->sync_latency = FALSE; |
1514 GST_OBJECT_UNLOCK (sink); |
1801 GST_OBJECT_UNLOCK (sink); |
1515 break; |
1802 break; |
1516 case GST_STATE_CHANGE_PAUSED_TO_READY: |
1803 case GST_STATE_CHANGE_PAUSED_TO_READY: |
1517 /* make sure we unblock before calling the parent state change |
1804 /* make sure we unblock before calling the parent state change |
1518 * so it can grab the STREAM_LOCK */ |
1805 * so it can grab the STREAM_LOCK */ |
1528 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
1815 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
1529 /* stop slaving ourselves to the master, if any */ |
1816 /* stop slaving ourselves to the master, if any */ |
1530 gst_clock_set_master (sink->provided_clock, NULL); |
1817 gst_clock_set_master (sink->provided_clock, NULL); |
1531 break; |
1818 break; |
1532 case GST_STATE_CHANGE_PAUSED_TO_READY: |
1819 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
1820 gst_ring_buffer_activate (sink->ringbuffer, FALSE); |
1533 gst_ring_buffer_release (sink->ringbuffer); |
1821 gst_ring_buffer_release (sink->ringbuffer); |
1534 break; |
1822 break; |
1535 case GST_STATE_CHANGE_READY_TO_NULL: |
1823 case GST_STATE_CHANGE_READY_TO_NULL: |
1536 /* we release again here because the aqcuire happens when setting the |
1824 /* we release again here because the aqcuire happens when setting the |
1537 * caps, which happens before we commit the state to PAUSED and thus the |
1825 * caps, which happens before we commit the state to PAUSED and thus the |
1538 * PAUSED->READY state change (see above, where we release the ringbuffer) |
1826 * PAUSED->READY state change (see above, where we release the ringbuffer) |
1539 * might not be called when we get here. */ |
1827 * might not be called when we get here. */ |
|
1828 gst_ring_buffer_activate (sink->ringbuffer, FALSE); |
1540 gst_ring_buffer_release (sink->ringbuffer); |
1829 gst_ring_buffer_release (sink->ringbuffer); |
1541 gst_ring_buffer_close_device (sink->ringbuffer); |
1830 gst_ring_buffer_close_device (sink->ringbuffer); |
|
1831 GST_OBJECT_LOCK (sink); |
|
1832 gst_object_unparent (GST_OBJECT_CAST (sink->ringbuffer)); |
|
1833 sink->ringbuffer = NULL; |
|
1834 GST_OBJECT_UNLOCK (sink); |
1542 break; |
1835 break; |
1543 default: |
1836 default: |
1544 break; |
1837 break; |
1545 } |
1838 } |
1546 |
1839 |