// avformat header files
#include <avformat.h>
+//
+// This structure should be extended and made globally available in mlt
+//
+
typedef struct
{
int16_t *buffer;
int size;
int used;
+ double time;
+ int frequency;
+ int channels;
}
*sample_fifo, sample_fifo_s;
-sample_fifo sample_fifo_init( )
+sample_fifo sample_fifo_init( int frequency, int channels )
+{
+ sample_fifo this = calloc( 1, sizeof( sample_fifo_s ) );
+ this->frequency = frequency;
+ this->channels = channels;
+ return this;
+}
+
+// sample_fifo_clear and check are temporarily aborted (not working as intended)
+
+void sample_fifo_clear( sample_fifo this, double time )
+{
+ int words = ( float )( time - this->time ) * this->frequency * this->channels;
+ if ( ( int )( ( float )time * 100 ) < ( int )( ( float )this->time * 100 ) && this->used > words && words > 0 )
+ {
+ memmove( this->buffer, &this->buffer[ words ], ( this->used - words ) * sizeof( int16_t ) );
+ this->used -= words;
+ this->time = time;
+ }
+ else if ( ( int )( ( float )time * 100 ) != ( int )( ( float )this->time * 100 ) )
+ {
+ this->used = 0;
+ this->time = time;
+ }
+}
+
+void sample_fifo_check( sample_fifo this, double time )
{
- return calloc( 1, sizeof( sample_fifo_s ) );
+ if ( this->used == 0 )
+ {
+ if ( ( int )( ( float )time * 100 ) < ( int )( ( float )this->time * 100 ) )
+ this->time = time;
+ }
}
void sample_fifo_append( sample_fifo this, int16_t *samples, int count )
this->used -= count;
memmove( this->buffer, &this->buffer[ count ], this->used * sizeof( int16_t ) );
+ this->time += ( double )count / this->channels / this->frequency;
+
return count;
}
mlt_properties_set( properties, "target", arg );
// sample and frame queue
- mlt_properties_set_data( properties, "sample_fifo", sample_fifo_init( ), 0, ( mlt_destructor )sample_fifo_close, NULL );
mlt_properties_set_data( properties, "frame_queue", mlt_deque_init( ), 0, ( mlt_destructor )mlt_deque_close, NULL );
// Set avformat defaults (all lifted from ffmpeg.c)
{
samples = mlt_sample_calculator( fps, frequency, count );
mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
+
+ // Create the fifo if we don't have one
+ if ( fifo == NULL )
+ {
+ fifo = sample_fifo_init( frequency, channels );
+ mlt_properties_set_data( properties, "sample_fifo", fifo, 0, ( mlt_destructor )sample_fifo_close, NULL );
+ }
+
+ // Append the samples
sample_fifo_append( fifo, pcm, samples * channels );
total_time += ( samples * 1000000 ) / frequency;
}
{
// Compute current audio and video time
if (audio_st)
- audio_pts = (double)audio_st->pts.val * oc->pts_num / oc->pts_den;
+ audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
else
audio_pts = 0.0;
if (video_st)
- video_pts = (double)video_st->pts.val * oc->pts_num / oc->pts_den;
+ video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
else
video_pts = 0.0;
// Set the resource property (required for all producers)
mlt_properties_set( properties, "resource", file );
- // TEST: audio sync tweaking
- mlt_properties_set_double( properties, "discrepancy", 1 );
-
// Register our get_frame implementation
this->get_frame = producer_get_frame;
// Find default audio and video streams
find_default_streams( context, &audio_index, &video_index );
+ if ( context->start_time != AV_NOPTS_VALUE )
+ mlt_properties_set_double( properties, "start_time", context->start_time );
+
// Check if we're seekable (something funny about mpeg here :-/)
- if ( strstr( file, ".mpg" ) == NULL && strstr( file, ".mpeg" ) == NULL )
- mlt_properties_set_int( properties, "seekable", av_seek_frame( context, -1, context->start_time ) >= 0 );
- else
- mlt_properties_set_int( properties, "seekable", 1 );
+ mlt_properties_set_int( properties, "seekable", av_seek_frame( context, -1, mlt_properties_get_double( properties, "start_time" ) ) >= 0 );
// Store selected audio and video indexes on properties
mlt_properties_set_int( properties, "audio_index", audio_index );
// We may want to use the source fps if available
double source_fps = mlt_properties_get_double( properties, "source_fps" );
+ // Get the seekable status
+ int seekable = mlt_properties_get_int( properties, "seekable" );
+
// Set the result arguments that we know here (only *buffer is now required)
*format = mlt_image_yuv422;
*width = codec_context->width;
// We're paused - use last image
paused = 1;
}
- else if ( position > expected && ( position - expected ) < 250 )
+ else if ( !seekable && position > expected && ( position - expected ) < 250 )
{
// Fast forward - seeking is inefficient for small distances - just ignore following frames
ignore = position - expected;
else
{
// Set to the real timecode
- av_seek_frame( context, -1, context->start_time + real_timecode * 1000000.0 );
+ av_seek_frame( context, -1, mlt_properties_get_double( properties, "start_time" ) + real_timecode * 1000000.0 );
// Remove the cached info relating to the previous position
mlt_properties_set_double( properties, "current_time", real_timecode );
// We're paused - silence required
paused = 1;
}
- else if ( position > expected && ( position - expected ) < 250 )
+ else if ( !seekable && position > expected && ( position - expected ) < 250 )
{
// Fast forward - seeking is inefficient for small distances - just ignore following frames
ignore = position - expected;
else
{
// Set to the real timecode
- if ( !seekable || av_seek_frame( context, -1, context->start_time + real_timecode * 1000000.0 ) != 0 )
+ if ( av_seek_frame( context, -1, mlt_properties_get_double( properties, "start_time" ) + real_timecode * 1000000.0 ) != 0 )
paused = 1;
// Clear the usage in the audio buffer
// If we're behind, ignore this packet
float current_pts = (float)pkt.pts / 1000000.0;
- double discrepancy = mlt_properties_get_double( properties, "discrepancy" );
- if ( current_pts != 0 && real_timecode != 0 )
- {
- if ( discrepancy != 1 )
- discrepancy = ( discrepancy + ( real_timecode / current_pts ) ) / 2;
- else
- discrepancy = real_timecode / current_pts;
- if ( discrepancy > 0.9 && discrepancy < 1.1 )
- discrepancy = 1.0;
- else
- discrepancy = floor( discrepancy + 0.5 );
-
- if ( discrepancy == 0 )
- discrepancy = 1.0;
-
- mlt_properties_set_double( properties, "discrepancy", discrepancy );
- }
-
- if ( seekable && ( !ignore && discrepancy * current_pts <= ( real_timecode - 0.02 ) ) )
+ if ( seekable && ( !ignore && current_pts <= ( real_timecode - 0.02 ) ) )
ignore = 1;
}