@ -48,6 +48,7 @@ typedef struct PulseData {
pa_threaded_mainloop * mainloop ;
pa_context * context ;
pa_stream * stream ;
size_t pa_frame_size ;
TimeFilter * timefilter ;
int last_period ;
@ -250,6 +251,7 @@ static av_cold int pulse_read_header(AVFormatContext *s)
goto unlock_and_fail ;
}
pd - > fragment_size = queried_attr - > fragsize ;
pd - > pa_frame_size = pa_frame_size ( & ss ) ;
pa_threaded_mainloop_unlock ( pd - > mainloop ) ;
@ -261,7 +263,7 @@ static av_cold int pulse_read_header(AVFormatContext *s)
avpriv_set_pts_info ( st , 64 , 1 , 1000000 ) ; /* 64 bits pts in us */
pd - > timefilter = ff_timefilter_new ( 1000000.0 / pd - > sample_rate ,
1000 , 1.5E-6 ) ;
pd - > fragment_size / pd - > pa_frame_size , 1.5E-6 ) ;
if ( ! pd - > timefilter ) {
pulse_close ( s ) ;
@ -286,12 +288,13 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
int64_t dts ;
pa_usec_t latency ;
int negative ;
ptrdiff_t pos = 0 ;
pa_threaded_mainloop_lock ( pd - > mainloop ) ;
CHECK_DEAD_GOTO ( pd , ret , unlock_and_fail ) ;
while ( ! read_data ) {
while ( pos < pd - > fragment_size ) {
int r ;
r = pa_stream_peek ( pd - > stream , & read_data , & read_length ) ;
@ -305,43 +308,51 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt)
* silence , but that wouldn ' t work for compressed streams . */
r = pa_stream_drop ( pd - > stream ) ;
CHECK_SUCCESS_GOTO ( ret , r = = 0 , unlock_and_fail ) ;
} else {
if ( ! pos ) {
if ( av_new_packet ( pkt , pd - > fragment_size ) < 0 ) {
ret = AVERROR ( ENOMEM ) ;
goto unlock_and_fail ;
}
dts = av_gettime ( ) ;
pa_operation_unref ( pa_stream_update_timing_info ( pd - > stream , NULL , NULL ) ) ;
if ( pa_stream_get_latency ( pd - > stream , & latency , & negative ) > = 0 ) {
if ( negative ) {
dts + = latency ;
} else
dts - = latency ;
} else {
av_log ( s , AV_LOG_WARNING , " pa_stream_get_latency() failed \n " ) ;
}
}
if ( pkt - > size - pos < read_length ) {
if ( pos )
break ;
pa_stream_drop ( pd - > stream ) ;
/* Oversized fragment??? */
ret = AVERROR_EXTERNAL ;
goto unlock_and_fail ;
}
memcpy ( pkt - > data + pos , read_data , read_length ) ;
pos + = read_length ;
pa_stream_drop ( pd - > stream ) ;
}
}
if ( av_new_packet ( pkt , read_length ) < 0 ) {
ret = AVERROR ( ENOMEM ) ;
goto unlock_and_fail ;
}
dts = av_gettime ( ) ;
pa_operation_unref ( pa_stream_update_timing_info ( pd - > stream , NULL , NULL ) ) ;
if ( pa_stream_get_latency ( pd - > stream , & latency , & negative ) > = 0 ) {
enum AVCodecID codec_id =
s - > audio_codec_id = = AV_CODEC_ID_NONE ? DEFAULT_CODEC_ID : s - > audio_codec_id ;
int frame_size = ( ( av_get_bits_per_sample ( codec_id ) > > 3 ) * pd - > channels ) ;
int frame_duration = read_length / frame_size ;
if ( negative ) {
dts + = latency ;
} else
dts - = latency ;
if ( pd - > wallclock )
pkt - > pts = ff_timefilter_update ( pd - > timefilter , dts , pd - > last_period ) ;
pa_threaded_mainloop_unlock ( pd - > mainloop ) ;
pd - > last_period = frame_duration ;
} else {
av_log ( s , AV_LOG_WARNING , " pa_stream_get_latency() failed \n " ) ;
}
av_shrink_packet ( pkt , pos ) ;
memcpy ( pkt - > data , read_data , read_length ) ;
pa_stream_drop ( pd - > stream ) ;
if ( pd - > wallclock )
pkt - > pts = ff_timefilter_update ( pd - > timefilter , dts , pd - > last_period ) ;
pd - > last_period = pkt - > size / pd - > pa_frame_size ;
pa_threaded_mainloop_unlock ( pd - > mainloop ) ;
return 0 ;
unlock_and_fail :
av_packet_unref ( pkt ) ;
pa_threaded_mainloop_unlock ( pd - > mainloop ) ;
return ret ;
}