#include <framework/mlt_log.h>
#include <framework/mlt_deque.h>
#include <framework/mlt_factory.h>
+#include <framework/mlt_cache.h>
// ffmpeg Header files
#include <avformat.h>
struct producer_avformat_s
{
- struct mlt_producer_s parent;
+ mlt_producer parent;
AVFormatContext *dummy_context;
AVFormatContext *audio_format;
AVFormatContext *video_format;
static int producer_open( producer_avformat this, mlt_profile profile, char *file );
static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index );
static void producer_format_close( void *context );
+static void producer_avformat_close( producer_avformat );
static void producer_close( mlt_producer parent );
#ifdef VDPAU
if ( !skip && file )
{
// Construct the producer
+ mlt_producer producer = calloc( 1, sizeof( struct mlt_producer_s ) );
producer_avformat this = calloc( 1, sizeof( struct producer_avformat_s ) );
// Initialise it
- if ( mlt_producer_init( &this->parent, this ) == 0 )
+ if ( mlt_producer_init( producer, this ) == 0 )
{
- mlt_producer producer = &this->parent;
+ this->parent = producer;
// Get the properties
mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
// Register our get_frame implementation
producer->get_frame = producer_get_frame;
- this->resample_factor = 1.0;
-
// Open the file
if ( producer_open( this, profile, file ) != 0 )
{
}
else
{
- // Close the file to release resources for large playlists - reopen later as needed
- producer_format_close( this->dummy_context );
- this->dummy_context = NULL;
- producer_format_close( this->audio_format );
- this->audio_format = NULL;
- producer_format_close( this->video_format );
- this->video_format = NULL;
-
// Default the user-selectable indices from the auto-detected indices
mlt_properties_set_int( properties, "audio_index", this->audio_index );
mlt_properties_set_int( properties, "video_index", this->video_index );
+
+#ifdef VDPAU
+ mlt_service_cache_set_size( MLT_PRODUCER_SERVICE(producer), "producer_avformat", 5 );
+#endif
+ mlt_service_cache_put( MLT_PRODUCER_SERVICE(producer), "producer_avformat", this, 0, (mlt_destructor) producer_avformat_close );
}
return producer;
}
AVFormatContext *context = NULL;
// Get the properties
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
+ mlt_properties properties = MLT_PRODUCER_PROPERTIES( this->parent );
// We will treat everything with the producer fps
double fps = mlt_profile_fps( profile );
}
mlt_log_verbose( NULL, "[producer avformat] audio: total_streams %d max_stream %d total_channels %d max_channels %d\n",
this->audio_streams, this->audio_max_stream, this->total_channels, this->max_channel );
+
+ // Other audio-specific initializations
+ this->resample_factor = 1.0;
}
static inline void convert_image( AVFrame *frame, uint8_t *buffer, int pix_fmt, mlt_image_format *format, int width, int height )
{
// Get the producer
producer_avformat this = mlt_frame_pop_service( frame );
- mlt_producer producer = &this->parent;
+ mlt_producer producer = this->parent;
// Get the properties from the frame
mlt_properties frame_properties = MLT_FRAME_PROPERTIES( frame );
if ( source_fps > 0 )
mlt_properties_set_double( properties, "source_fps", source_fps );
else
- mlt_properties_set_double( properties, "source_fps", mlt_producer_get_fps( &this->parent ) );
+ mlt_properties_set_double( properties, "source_fps", mlt_producer_get_fps( this->parent ) );
}
return this->video_codec && this->video_index > -1;
}
static void producer_set_up_video( producer_avformat this, mlt_frame frame )
{
// Get the producer
- mlt_producer producer = &this->parent;
+ mlt_producer producer = this->parent;
// Get the properties
mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
mlt_position position = mlt_properties_get_position( MLT_FRAME_PROPERTIES( frame ), "avformat_position" );
// Calculate the real time code
- double real_timecode = producer_time_of_frame( &this->parent, position );
+ double real_timecode = producer_time_of_frame( this->parent, position );
// Get the source fps
- double source_fps = mlt_properties_get_double( MLT_PRODUCER_PROPERTIES( &this->parent ), "source_fps" );
+ double source_fps = mlt_properties_get_double( MLT_PRODUCER_PROPERTIES( this->parent ), "source_fps" );
// Number of frames to ignore (for ffwd)
int ignore = 0;
static void producer_set_up_audio( producer_avformat this, mlt_frame frame )
{
// Get the producer
- mlt_producer producer = &this->parent;
+ mlt_producer producer = this->parent;
// Get the properties
mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
{
// Access the private data
- producer_avformat this = producer->child;
+ mlt_cache_item cache_item = mlt_service_cache_get( MLT_PRODUCER_SERVICE(producer), "producer_avformat" );
+ producer_avformat this = mlt_cache_item_data( cache_item, NULL );
// Create an empty frame
*frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
+
+ if ( *frame )
+ mlt_properties_set_data( MLT_FRAME_PROPERTIES(*frame), "avformat_cache", cache_item, 0, (mlt_destructor) mlt_cache_item_close, NULL );
+ else
+ mlt_cache_item_close( cache_item );
// Update timecode on the frame we're creating
mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
// Set the position of this producer
mlt_properties_set_position( MLT_FRAME_PROPERTIES( *frame ), "avformat_position", mlt_producer_frame( producer ) );
+
+ // If cache miss
+ if ( !this )
+ {
+ this = calloc( 1, sizeof( struct producer_avformat_s ) );
+ producer->child = this;
+ this->parent = producer;
+ mlt_service_cache_put( MLT_PRODUCER_SERVICE(producer), "producer_avformat", this, 0, (mlt_destructor) producer_avformat_close );
+ }
// Set up the video
producer_set_up_video( this, *frame );
return 0;
}
-static void producer_close( mlt_producer parent )
+static void producer_avformat_close( producer_avformat this )
{
- // Obtain this
- producer_avformat this = parent->child;
-
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "producer_avformat_close\n" );
// Close the file
av_free( this->av_frame );
int i;
#ifdef VDPAU
vdpau_producer_close( this );
#endif
+ free( this );
+}
+static void producer_close( mlt_producer parent )
+{
// Close the parent
parent->close = NULL;
mlt_producer_close( parent );
// Free the memory
- free( this );
+ free( parent );
}
static int vdpau_init( producer_avformat this )
{
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "vdpau_init\n" );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "vdpau_init\n" );
int success = 0;
- mlt_properties properties = MLT_PRODUCER_PROPERTIES( &this->parent );
+ mlt_properties properties = MLT_PRODUCER_PROPERTIES( this->parent );
Display *display = (Display*) strtol( mlt_environment( "x11_display" ), NULL, 16 );
if ( !display || mlt_properties_get_int( properties, "novdpau" ) )
return success;
int screen = mlt_properties_get_int( properties, "x11_screen" );
VdpDevice device;
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "X11 Display = %p\n", display );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "X11 Display = %p\n", display );
if ( VDP_STATUS_OK == create_device( display, screen, &device, &vdp_get_proc_address ) )
{
// Allocate the global VDPAU context
}
if ( !success )
{
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "VDPAU failed to initialize device\n" );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "VDPAU failed to initialize device\n" );
dlclose( object );
}
}
else
{
success = 1;
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "VDPAU already initialized\n" );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "VDPAU already initialized\n" );
}
if ( g_vdpau && g_vdpau->producer != this )
return success;
}
+static enum PixelFormat vdpau_get_format( struct AVCodecContext *s, const enum PixelFormat *fmt )
+{
+ return PIX_FMT_VDPAU_H264;
+}
+
static int vdpau_get_buffer( AVCodecContext *codec_context, AVFrame *frame )
{
int error = 0;
producer_avformat this = codec_context->opaque;
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "vdpau_get_buffer\n" );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "vdpau_get_buffer\n" );
if ( g_vdpau->producer == this && mlt_deque_count( this->vdpau->deque ) )
{
}
else
{
- mlt_log_warning( MLT_PRODUCER_SERVICE(&this->parent), "VDPAU surface underrun\n" );
+ mlt_log_warning( MLT_PRODUCER_SERVICE(this->parent), "VDPAU surface underrun\n" );
error = -1;
}
}
else
{
- mlt_log_warning( MLT_PRODUCER_SERVICE(&this->parent), "VDPAU surface underrun\n" );
+ mlt_log_warning( MLT_PRODUCER_SERVICE(this->parent), "VDPAU surface underrun\n" );
error = -1;
}
{
producer_avformat this = codec_context->opaque;
struct vdpau_render_state *render = (struct vdpau_render_state*) frame->data[0];
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "vdpau_release_buffer (%x)\n", render->surface );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "vdpau_release_buffer (%x)\n", render->surface );
int i;
render->state &= ~FF_VDPAU_STATE_USED_FOR_REFERENCE;
if ( status != VDP_STATUS_OK )
{
this->vdpau->is_decoded = 0;
- mlt_log_warning( MLT_PRODUCER_SERVICE(&this->parent), "VDPAU failed to decode (%s)\n",
+ mlt_log_warning( MLT_PRODUCER_SERVICE(this->parent), "VDPAU failed to decode (%s)\n",
vdp_get_error_string( status ) );
}
else
static int vdpau_decoder_init( producer_avformat this )
{
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "vdpau_decoder_init\n" );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "vdpau_decoder_init\n" );
int success = 1;
this->video_codec->opaque = this;
+ this->video_codec->get_format = vdpau_get_format;
this->video_codec->get_buffer = vdpau_get_buffer;
this->video_codec->release_buffer = vdpau_release_buffer;
this->video_codec->draw_horiz_band = vdpau_draw_horiz;
this->video_codec->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
+ this->video_codec->pix_fmt = PIX_FMT_VDPAU_H264;
VdpDecoderProfile profile = VDP_DECODER_PROFILE_H264_HIGH;
uint32_t max_references = this->video_codec->refs;
if ( VDP_STATUS_OK == vdp_surface_create( g_vdpau->device, VDP_CHROMA_TYPE_420,
this->video_codec->width, this->video_codec->height, &this->vdpau->render_states[i].surface ) )
{
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "successfully created VDPAU surface %x\n",
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "successfully created VDPAU surface %x\n",
this->vdpau->render_states[i].surface );
mlt_deque_push_back( this->vdpau->deque, &this->vdpau->render_states[i] );
}
else
{
- mlt_log_info( MLT_PRODUCER_SERVICE(&this->parent), "failed to create VDPAU surface %dx%d\n",
+ mlt_log_info( MLT_PRODUCER_SERVICE(this->parent), "failed to create VDPAU surface %dx%d\n",
this->video_codec->width, this->video_codec->height );
while ( mlt_deque_count( this->vdpau->deque ) )
{
{
success = 0;
g_vdpau->decoder = VDP_INVALID_HANDLE;
- mlt_log_error( MLT_PRODUCER_SERVICE(&this->parent), "VDPAU failed to initialize decoder (%s)\n",
+ mlt_log_error( MLT_PRODUCER_SERVICE(this->parent), "VDPAU failed to initialize decoder (%s)\n",
vdp_get_error_string( status ) );
}
{
if ( this->vdpau )
{
- mlt_log_debug( MLT_PRODUCER_SERVICE(&this->parent), "vdpau_producer_close\n" );
+ mlt_log_debug( MLT_PRODUCER_SERVICE(this->parent), "vdpau_producer_close\n" );
int i;
for ( i = 0; i < MAX_VDPAU_SURFACES; i++ )
{