[vlmc-devel] [PATCH] Integrate libVLC consumer into VLMC
Hugo Beauzée-Luyssen
hugo at beauzee.fr
Fri Jul 22 11:08:44 CEST 2016
Hi,
On 07/22/2016 09:15 AM, yikei lu wrote:
> 2016-07-22 15:41 GMT+09:00 Paweł Goliński <golpaw1 at gmail.com>:
>> Dnia 22.07.2016 o godz. 06:22 yikei lu <luyikei.qmltu at gmail.com> napisał(a):
>>
>>> 2016-07-22 3:07 GMT+09:00 Pawel Golinski <golpaw1 at gmail.com>:
>>>
>>> Hi ! Thanks for the patch.
>>>
>>>> ---
>>>> src/Backend/MLT/MLTBackend.cpp | 15 +
>>>> src/Backend/MLT/modules/libvlc/consumer_libvlc.c | 559 +++++++++++++++++++++
>>>> src/Backend/MLT/modules/libvlc/consumer_libvlc.yml | 70 +++
>>>> .../MLT/modules/libvlc/consumer_libvlc_window.yml | 39 ++
>>>> src/CMakeLists.txt | 8 +-
>>>> 5 files changed, 689 insertions(+), 2 deletions(-)
>>>> create mode 100644 src/Backend/MLT/modules/libvlc/consumer_libvlc.c
>>>> create mode 100644 src/Backend/MLT/modules/libvlc/consumer_libvlc.yml
>>>> create mode 100644 src/Backend/MLT/modules/libvlc/consumer_libvlc_window.yml
>>>>
>>>> diff --git a/src/Backend/MLT/MLTBackend.cpp b/src/Backend/MLT/MLTBackend.cpp
>>>> index 3d39930..c466995 100644
>>>> --- a/src/Backend/MLT/MLTBackend.cpp
>>>> +++ b/src/Backend/MLT/MLTBackend.cpp
>>>> @@ -5,6 +5,7 @@
>>>> * Copyright (C) 2008-2016 VideoLAN
>>>> *
>>>> * Authors: Yikei Lu <luyikei.qmltu at gmail.com>
>>>> + * Pawel Golinski <golpaw1 at gmail.com>
>>>> *
>>>> * This program is free software; you can redistribute it and/or
>>>> * modify it under the terms of the GNU General Public License
>>>> @@ -43,6 +44,15 @@ using namespace Backend::MLT;
>>>> static Backend::IBackend::LogHandler staticLogHandler;
>>>> static std::mutex logMutex;
>>>>
>>>> +extern "C" mlt_consumer consumer_libvlc_init( mlt_profile profile, mlt_service_type type, const char *id, const void *arg );
>>>> +
>>>> +static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
>>>> +{
>>>> + char file[ 4096 ];
>>>> + snprintf( file, 4096, "%s%s", MLT_MODULES_PATH, (char*)data );
>>>> + return mlt_properties_parse_yaml( file );
>>>> +}
>>>> +
>>>> IBackend*
>>>> Backend::instance()
>>>> {
>>>> @@ -54,6 +64,11 @@ MLTBackend::MLTBackend()
>>>> m_mltRepo = Mlt::Factory::init();
>>>> m_profile.setFrameRate( 2997, 100 );
>>>>
>>>> + m_mltRepo->register_service( consumer_type, "libvlc", (mlt_register_callback)consumer_libvlc_init );
>>>> + m_mltRepo->register_service( consumer_type, "libvlc_window", (mlt_register_callback)consumer_libvlc_init );
>>>> + m_mltRepo->register_metadata( consumer_type, "libvlc", metadata, (void*)"/libvlc/consumer_libvlc.yml" );
>>>> + m_mltRepo->register_metadata( consumer_type, "libvlc_window", metadata, (void*)"/libvlc/consumer_libvlc_window.yml" );
>>>> +
>>>
>>> I think you should make factory.c and do registration there like other
>>> modules do. Not in MLTBackend.
>>
>> Why?
>> We're using MLT that is already compiled so we need to register plugins at runtime.
>> This is the least complex way to do that and it's 100% correct.
>
> As I said, I think it might be better idea to have a separated
> repository to maintain libvlc consumer/producer so that you don't have
> to make changes on VLMC every time you want to change mlt
> consumer/producer. I have to see how Hugo and JB think though :)
>
I agree, I'd rather have a specific repo for those. So far, your
personal github is enough, and if need be, we will create a repo on
code.videolan.org ultimately.
I'd like to have that code merged upstream however.
> Also, it doesn't matter if MLT is complied.
>
> In mlt_repository.c
> -----------------------------------
> // Iterate over files
> for ( i = 0; i < count; i++ )
> ...
> const char *object_name = mlt_properties_get_value( dir, i);
> ...
> // Open the shared object
> void *object = dlopen( object_name, flags );
> ...
> // Get the registration function
> mlt_repository_callback symbol_ptr = dlsym( object, "mlt_register" );
> -----------------------------------
>
> You see they try to open all the shared objects in the repository folder.
>
> Regards,
>
>
>>
>>>
>>>> for ( int i = 0; i < m_mltRepo->filters()->count(); ++i )
>>>> {
>>>> auto pro = std::unique_ptr<Mlt::Properties>( m_mltRepo->metadata( filter_type, m_mltRepo->filters()->get_name( i ) ) );
>>>> diff --git a/src/Backend/MLT/modules/libvlc/consumer_libvlc.c b/src/Backend/MLT/modules/libvlc/consumer_libvlc.c
>>>> new file mode 100644
>>>> index 0000000..a34f8fa
>>>> --- /dev/null
>>>> +++ b/src/Backend/MLT/modules/libvlc/consumer_libvlc.c
>>>> @@ -0,0 +1,559 @@
>>>> +/*****************************************************************************
>>>> + * consumer_libvlc.c: libVLC consumer plugin for MLT
>>>> + *****************************************************************************
>>>> + * Copyright (C) 2008-2016 VideoLAN
>>>> + *
>>>> + * Authors: Pawel Golinski <golpaw1 at gmail.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU General Public License
>>>> + * as published by the Free Software Foundation; either version 2
>>>> + * of the License, or (at your option) any later version.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * along with this program; if not, write to the Free Software
>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
>>>> + *****************************************************************************/
>>>> +
>>>> +#include <framework/mlt.h>
>>>> +
>>>> +#include <vlc/vlc.h>
>>>> +
>>>> +#include <stdio.h>
>>>> +#include <stdlib.h>
>>>> +#include <assert.h>
>>>> +#include <string.h>
>>>> +
>>>> +#define VIDEO_COOKIE 0
>>>> +#define AUDIO_COOKIE 1
>>>> +
>>>> +#define INITIAL_POSITION -1
>>>> +
>>>> +// Debug code
>>>> +
>>>> +pthread_mutex_t log_mutex;
>>>> +
>>>> +static void log_cb( void *data, int level, const libvlc_log_t *ctx, const char *fmt, va_list args )
>>>> +{
>>>> + pthread_mutex_lock( &log_mutex );
>>>> + printf( "VLC LOG: " );
>>>> + vprintf( fmt, args );
>>>> + printf( "\n" );
>>>> + pthread_mutex_unlock( &log_mutex );
>>>> +}
>>>> +
>>>> +typedef struct consumer_libvlc_s *consumer_libvlc;
>>>
>>> You should use VlmcLogger.
>>>
>>>> +
>>>> +struct consumer_libvlc_s
>>>> +{
>>>> + mlt_consumer parent;
>>>> + libvlc_instance_t *vlc;
>>>> + libvlc_media_t *media;
>>>> + libvlc_media_player_t *media_player;
>>>> + libvlc_event_manager_t *mp_manager;
>>>> + int64_t latest_video_pts;
>>>> + int64_t latest_audio_pts;
>>>> + mlt_deque frame_queue;
>>>> + pthread_mutex_t queue_mutex;
>>>> + mlt_position video_position;
>>>> + mlt_position audio_position;
>>>> + void *video_imem_data;
>>>> + void *audio_imem_data;
>>>> + int running;
>>>> + int output_to_window;
>>>> +};
>>>> +
>>>> +static void setup_vlc( consumer_libvlc self );
>>>> +static void setup_vlc_sout( consumer_libvlc self );
>>>> +static int setup_vlc_window( consumer_libvlc self );
>>>> +static int imem_get( void *data, const char* cookie, int64_t *dts, int64_t *pts,
>>>> + unsigned *flags, size_t *bufferSize, void **buffer );
>>>> +static void imem_release( void *data, const char* cookie, size_t buffSize, void *buffer );
>>>> +static int consumer_start( mlt_consumer parent );
>>>> +static int consumer_stop( mlt_consumer parent );
>>>> +static int consumer_is_stopped( mlt_consumer parent );
>>>> +static void consumer_close( mlt_consumer parent );
>>>> +static void consumer_purge( mlt_consumer parent );
>>>> +static void mp_callback( const struct libvlc_event_t *evt, void *data );
>>>> +
>>>> +mlt_consumer consumer_libvlc_init( mlt_profile profile, mlt_service_type type, const char *id, const void *arg )
>>>> +{
>>>> + int err;
>>>> + mlt_consumer parent = NULL;
>>>> + consumer_libvlc self = NULL;
>>>> +
>>>> + // Allocate the consumer data structures
>>>> + parent = calloc( 1, sizeof( struct mlt_consumer_s ) );
>>>> + self = calloc( 1, sizeof( struct consumer_libvlc_s ) );
>>>> + assert( parent != NULL && self != NULL );
>>>> + err = mlt_consumer_init( parent, self, profile );
>>>> + assert( err == 0 );
>>>> +
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( parent );
>>>> + mlt_properties_set_lcnumeric( properties, "C" );
>>>> + self->parent = parent;
>>>> +
>>>> + // Set default libVLC specific properties
>>>> + mlt_properties_set( properties, "input_vcodec", "RGBA" );
>>>> + mlt_properties_set( properties, "input_acodec", "s16l" );
>>>> + mlt_properties_set( properties, "output_vcodec", "mp2v" );
>>>> + mlt_properties_set( properties, "output_acodec", "mpga" );
>>>> + mlt_properties_set_int( properties, "output_vb", 8000000 );
>>>> + mlt_properties_set_int( properties, "output_ab", 128000 );
>>>> + if ( self->output_to_window )
>>>> + mlt_properties_set_data( properties, "output_dst", arg, 0, NULL, NULL );
>>>> + else
>>>> + mlt_properties_set( properties, "output_dst", ( char* )arg );
>>>> + mlt_properties_set( properties, "output_mux", "ps" );
>>>> + mlt_properties_set( properties, "output_access", "file" );
>>>> +
>>>> + self->vlc = libvlc_new( 0, NULL );
>>>> + assert( self->vlc != NULL );
>>>> +
>>>> + // Debug code
>>>> + libvlc_log_set( self->vlc, log_cb, NULL );
>>>> + pthread_mutex_init( &log_mutex, NULL );
>>>> +
>>>> + self->frame_queue = mlt_deque_init( );
>>>> + assert( self->frame_queue != NULL );
>>>> +
>>>> + pthread_mutex_init( &self->queue_mutex, NULL );
>>>> +
>>>> + parent->start = consumer_start;
>>>> + parent->stop = consumer_stop;
>>>> + parent->is_stopped = consumer_is_stopped;
>>>> + parent->close = consumer_close;
>>>> + parent->purge = consumer_purge;
>>>> +
>>>> + // Set output_to_window flag if needed
>>>> + if ( !strcmp( id, "libvlc_window" ) )
>>>> + self->output_to_window = 1;
>>>> +
>>>> + return parent;
>>>> +}
>>>> +
>>>> +static void setup_vlc( consumer_libvlc self )
>>>> +{
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( self->parent );
>>>> +
>>>> + // imem setup phase
>>>> +
>>>> + // Allocate buffers
>>>> + char imem_video_conf[ 512 ];
>>>> + char imem_audio_conf[ 512 ];
>>>> + char imem_get_conf[ 512 ];
>>>> + char imem_release_conf[ 512 ];
>>>> + char imem_data_conf[ 512 ];
>>>> +
>>>> + // We will create media using imem MRL
>>>> + sprintf( imem_video_conf, "imem://width=%i:height=%i:dar=%s:fps=%s/1:cookie=0:codec=%s:cat=2:caching=0",
>>>> + mlt_properties_get_int( properties, "width" ),
>>>> + mlt_properties_get_int( properties, "height" ),
>>>> + mlt_properties_get( properties, "display_ratio" ),
>>>> + mlt_properties_get( properties, "fps" ),
>>>> + mlt_properties_get( properties, "input_vcodec" ) );
>>>> +
>>>> + // Audio stream will be added as input slave
>>>> + sprintf( imem_audio_conf, ":input-slave=imem://cookie=1:cat=1:codec=%s:samplerate=%d:channels=%d:caching=0",
>>>> + mlt_properties_get( properties, "input_acodec" ),
>>>> + mlt_properties_get_int( properties, "frequency" ),
>>>> + mlt_properties_get_int( properties, "channels" ) );
>>>> +
>>>> + // This configures imem callbacks
>>>> + sprintf( imem_get_conf,
>>>> + ":imem-get=%" PRIdPTR,
>>>> + (intptr_t)(void*)&imem_get );
>>>> +
>>>> + sprintf( imem_release_conf,
>>>> + ":imem-release=%" PRIdPTR,
>>>> + (intptr_t)(void*)&imem_release );
>>>> +
>>>> + sprintf( imem_data_conf,
>>>> + ":imem-data=%" PRIdPTR,
>>>> + (intptr_t)(void*)self );
>>>> +
>>>> + // Create media...
>>>> + self->media = libvlc_media_new_location( self->vlc, imem_video_conf );
>>>> + assert( self->media != NULL );
>>>> +
>>>> + // ...and apply configuration parameters.
>>>> + libvlc_media_add_option( self->media, imem_audio_conf );
>>>> + libvlc_media_add_option( self->media, imem_get_conf );
>>>> + libvlc_media_add_option( self->media, imem_release_conf );
>>>> + libvlc_media_add_option( self->media, imem_data_conf );
>>>> +
>>>> + // Setup sout chain if we're not outputting to window
>>>> + if ( !self->output_to_window )
>>>> + {
>>>> + setup_vlc_sout( self );
>>>> + }
>>>> +}
>>>> +
>>>> +static void setup_vlc_sout( consumer_libvlc self )
>>>> +{
>>>> + assert( self->media != NULL );
>>>> +
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( self->parent );
>>>> +
>>>> + char sout_conf[ 512 ];
>>>> +
>>>> + // This configures file output
>>>> + sprintf( sout_conf, ":sout=#transcode{"
>>>> + "vcodec=%s,fps=%s,width=%d,height=%d,vb=%d,"
>>>> + "acodec=%s,channels=%d,samplerate=%d,ab=%d}"
>>>> + ":standard{access=%s,mux=%s,dst=\"%s\"}",
>>>> + mlt_properties_get( properties, "output_vcodec" ),
>>>> + mlt_properties_get( properties, "fps" ),
>>>> + mlt_properties_get_int( properties, "width" ),
>>>> + mlt_properties_get_int( properties, "height" ),
>>>> + mlt_properties_get_int( properties, "output_vb" ),
>>>> + mlt_properties_get( properties, "output_acodec" ),
>>>> + mlt_properties_get_int( properties, "channels" ),
>>>> + mlt_properties_get_int( properties, "frequency" ),
>>>> + mlt_properties_get_int( properties, "output_ab" ),
>>>> + mlt_properties_get( properties, "output_access" ),
>>>> + mlt_properties_get( properties, "output_mux" ),
>>>> + mlt_properties_get( properties, "output_dst" ) );
>>>> +
>>>> + libvlc_media_add_option( self->media, sout_conf );
>>>> +}
>>>> +
>>>> +static int setup_vlc_window( consumer_libvlc self )
>>>> +{
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( self->parent );
>>>> +
>>>> + char *window_type = mlt_properties_get( properties, "window_type" );
>>>> + void *window_handle = mlt_properties_get_data( properties, "output_dst", NULL );
>>>> +
>>>> + if ( window_type != NULL && window_handle != NULL )
>>>> + {
>>>> + if ( !strcmp( window_type, "nsobject") )
>>>> + {
>>>> + libvlc_media_player_set_nsobject( self->media_player, window_handle );
>>>> + }
>>>> + else if ( !strcmp( window_type, "xwindow" ) )
>>>> + {
>>>> + libvlc_media_player_set_xwindow( self->media_player, ( uint32_t )window_handle );
>>>> + }
>>>> + else if ( !strcmp( window_type, "hwnd" ) )
>>>> + {
>>>> + libvlc_media_player_set_hwnd( self->media_player, window_handle );
>>>> + }
>>>> + else
>>>> + {
>>>> + // Some unknown window_type was passed
>>>> + return 1;
>>>> + }
>>>> +
>>>> + // Setup finished successfully
>>>> + return 0;
>>>> + }
>>>> + else
>>>> + {
>>>> + // We failed to get window_type and/or window_handle
>>>> + return 1;
>>>> + }
>>>> +}
>>>> +
>>>> +static int imem_get( void *data, const char* cookie, int64_t *dts, int64_t *pts,
>>>> + uint32_t *flags, size_t *bufferSize, void **buffer )
>>>> +{
>>>> + consumer_libvlc self = data;
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( self->parent );
>>>> + mlt_frame frame = NULL;
>>>> + // Whether or not fetched frame need releasing
>>>> + int cleanup_frame = 0;
>>>> + *buffer = NULL;
>>>> +
>>>> + int cookie_int = cookie[ 0 ] - '0';
>>>> +
>>>> + // Get data if needed
>>>> + pthread_mutex_lock( &self->queue_mutex );
>>>> +
>>>> + frame = mlt_deque_pop_front( self->frame_queue );
>>>> +
>>>> + // If we got frame from queue, we need to release it later
>>>> + if ( frame != NULL )
>>>> + cleanup_frame = 1;
>>>> + else
>>>> + frame = mlt_consumer_get_frame( self->parent );
>>>> +
>>>> + if ( cookie_int == AUDIO_COOKIE && self->running )
>>>> + {
>>>> + assert( frame != NULL );
>>>> + mlt_position current_position = mlt_frame_original_position( frame );
>>>> +
>>>> + // We terminate imem if we got repeated frame, as this means pause
>>>> + if ( current_position == self->audio_position )
>>>> + {
>>>> + self->running = 0;
>>>> + pthread_mutex_unlock( &self->queue_mutex );
>>>> + return 1;
>>>> + }
>>>> + else
>>>> + {
>>>> + // Update position
>>>> + self->audio_position = current_position;
>>>> +
>>>> + // This is used to pass frames to imem_release() if they need cleanup
>>>> + self->audio_imem_data = NULL;
>>>> +
>>>> + mlt_audio_format afmt = mlt_audio_s16;
>>>> + double fps = mlt_properties_get_double( properties, "fps" );
>>>> + int frequency = mlt_properties_get_int( properties, "frequency" );
>>>> + int channels = mlt_properties_get_int( properties, "channels" );
>>>> + int samples = mlt_sample_calculator( fps, frequency, self->audio_position );
>>>> + double pts_diff = ( double )samples / ( double )frequency * 1000000.0;
>>>> +
>>>> + mlt_frame_get_audio( frame, buffer, &afmt, &frequency, &channels, &samples );
>>>> + *bufferSize = samples * sizeof( int16_t ) * channels;
>>>> +
>>>> + *pts = self->latest_audio_pts + pts_diff + 0.5;
>>>> + *dts = *pts;
>>>> +
>>>> + self->latest_audio_pts = *pts;
>>>> +
>>>> + if ( cleanup_frame )
>>>> + self->audio_imem_data = frame;
>>>> + else
>>>> + mlt_deque_push_back( self->frame_queue, frame );
>>>> + }
>>>> + }
>>>> + else if ( cookie_int == VIDEO_COOKIE && self->running )
>>>> + {
>>>> + assert( frame != NULL );
>>>> + mlt_position current_position = mlt_frame_original_position( frame );
>>>> +
>>>> + if ( current_position == self->video_position )
>>>> + {
>>>> + self->running = 0;
>>>> + pthread_mutex_unlock( &self->queue_mutex );
>>>> + return 1;
>>>> + }
>>>> + else
>>>> + {
>>>> + self->video_position = current_position;
>>>> +
>>>> + self->video_imem_data = NULL;
>>>> +
>>>> + double fps = mlt_properties_get_double( properties, "fps" );
>>>> + double pts_diff = 1.0 / fps * 1000000.0;
>>>> +
>>>> + mlt_image_format vfmt = mlt_image_rgb24a;
>>>> + int width = mlt_properties_get_int( properties, "width" );
>>>> + int height = mlt_properties_get_int( properties, "height" );
>>>> + mlt_frame_get_image( frame, ( uint8_t ** )buffer, &vfmt, &width, &height, 0 );
>>>> + *bufferSize = mlt_image_format_size( vfmt, width, height, NULL );
>>>> +
>>>> + *pts = self->latest_video_pts + pts_diff;
>>>> + *dts = *pts;
>>>> +
>>>> + self->latest_video_pts = *pts;
>>>> +
>>>> + if ( cleanup_frame )
>>>> + self->video_imem_data = frame;
>>>> + else
>>>> + mlt_deque_push_back( self->frame_queue, frame );
>>>> + }
>>>> + }
>>>> + else if ( self->running )
>>>> + {
>>>> + // Invalid cookie
>>>> + assert( 0 );
>>>> + }
>>>> + pthread_mutex_unlock( &self->queue_mutex );
>>>> +
>>>> + assert( frame != NULL );
>>>> + if ( *buffer == NULL )
>>>> + return 1;
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void imem_release( void *data, const char* cookie, size_t buffSize, void *buffer )
>>>> +{
>>>> + consumer_libvlc self = data;
>>>> +
>>>> + int cookie_int = cookie[ 0 ] - '0';
>>>> +
>>>> + if ( cookie_int == VIDEO_COOKIE && self->running )
>>>> + {
>>>> + if ( self->video_imem_data )
>>>> + {
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( self->parent );
>>>> + mlt_frame frame = self->video_imem_data;
>>>> + mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
>>>> + self->video_imem_data = NULL;
>>>> + }
>>>> + }
>>>> + else if ( cookie_int == AUDIO_COOKIE && self->running )
>>>> + {
>>>> + if ( self->audio_imem_data )
>>>> + {
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( self->parent );
>>>> + mlt_frame frame = self->audio_imem_data;
>>>> + mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
>>>> + self->audio_imem_data = NULL;
>>>> +
>>>> + }
>>>> + }
>>>> + else if ( self->running )
>>>> + {
>>>> + // Invalid cookie
>>>> + assert( 0 );
>>>> + }
>>>> +}
>>>> +
>>>> +static void mp_callback( const struct libvlc_event_t *evt, void *data )
>>>> +{
>>>> + consumer_libvlc self = data;
>>>> + assert( self != NULL );
>>>> +
>>>> + switch ( evt->type )
>>>> + {
>>>> + case libvlc_MediaPlayerStopped:
>>>> + self->running = 0;
>>>> + break;
>>>> +
>>>> + default:
>>>> + assert( 0 );
>>>> + }
>>>> +}
>>>> +
>>>> +static int consumer_start( mlt_consumer parent )
>>>> +{
>>>> + int err;
>>>> +
>>>> + consumer_libvlc self = parent->child;
>>>> + assert( self != NULL );
>>>> +
>>>> + mlt_properties properties = MLT_CONSUMER_PROPERTIES( self->parent );
>>>> +
>>>> +
>>>> + if ( consumer_is_stopped( parent ) )
>>>> + {
>>>> + // Free all previous resources
>>>> + if ( self->media_player )
>>>> + {
>>>> + libvlc_media_player_release( self->media_player );
>>>> + self->media_player = NULL;
>>>> + }
>>>> + if ( self->media )
>>>> + {
>>>> + libvlc_media_release( self->media );
>>>> + self->media = NULL;
>>>> + }
>>>> +
>>>> + // Apply properties to new media
>>>> + setup_vlc( self );
>>>> + self->media_player = libvlc_media_player_new_from_media( self->media );
>>>> + assert( self->media_player != NULL );
>>>> +
>>>> + // Set window output if we're using it
>>>> + if ( self->output_to_window )
>>>> + {
>>>> + err = setup_vlc_window( self );
>>>> +
>>>> + if ( err )
>>>> + {
>>>> + char error_msg[] = "Wrong window_type and/or output_dst parameters supplied.\n";
>>>> + char *window_type = mlt_properties_get( properties, "window_type" );
>>>> + mlt_log_error( MLT_CONSUMER_SERVICE( self->parent ), error_msg );
>>>> + mlt_events_fire( properties, "consumer-fatal-error", NULL );
>>>> + return err;
>>>> + }
>>>> + }
>>>> +
>>>> + // Catch media_player stop
>>>> + self->mp_manager = libvlc_media_player_event_manager( self->media_player );
>>>> + assert( self->mp_manager != NULL );
>>>> + libvlc_event_attach( self->mp_manager, libvlc_MediaPlayerStopped, &mp_callback, self );
>>>> +
>>>> + // Reset play heads
>>>> + self->video_position = INITIAL_POSITION;
>>>> + self->audio_position = INITIAL_POSITION;
>>>> +
>>>> + // Run media player
>>>> + self->running = 1;
>>>> + err = libvlc_media_player_play( self->media_player );
>>>> +
>>>> + // If we failed to play, we're not running
>>>> + if ( err ) {
>>>> + self->running = 0;
>>>> + }
>>>> +
>>>> + return err;
>>>> + }
>>>> + return 1;
>>>> +}
>>>> +
>>>> +static int consumer_stop( mlt_consumer parent )
>>>> +{
>>>> + consumer_libvlc self = parent->child;
>>>> + assert( self != NULL );
>>>> +
>>>> + if ( self->media_player )
>>>> + {
>>>> + self->running = 0;
>>>> + libvlc_media_player_stop( self->media_player );
>>>> + }
>>>> +
>>>> + // Reset pts counters
>>>> + self->latest_video_pts = 0;
>>>> + self->latest_audio_pts = 0;
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static int consumer_is_stopped( mlt_consumer parent )
>>>> +{
>>>> + consumer_libvlc self = parent->child;
>>>> + assert( self != NULL );
>>>> +
>>>> + if ( self->media_player )
>>>> + {
>>>> + return !self->running;
>>>> + }
>>>> +
>>>> + return 1;
>>>> +}
>>>> +
>>>> +static void consumer_purge( mlt_consumer parent )
>>>> +{
>>>> + // We do nothing here, we purge on stop()
>>>> +}
>>>> +
>>>> +static void consumer_close( mlt_consumer parent )
>>>> +{
>>>> + if ( parent == NULL )
>>>> + {
>>>> + return;
>>>> + }
>>>> +
>>>> + consumer_libvlc self = parent->child;
>>>> +
>>>> + if ( self != NULL )
>>>> + {
>>>> + consumer_stop( parent );
>>>> +
>>>> + if ( self->media_player )
>>>> + libvlc_media_player_release( self->media_player );
>>>> +
>>>> + if ( self->media )
>>>> + libvlc_media_release( self->media );
>>>> +
>>>> + if ( self->vlc )
>>>> + libvlc_release( self->vlc );
>>>> +
>>>> + pthread_mutex_destroy( &self->queue_mutex );
>>>> + free( self );
>>>> + }
>>>> +
>>>> + parent->close = NULL;
>>>> + mlt_consumer_close( parent );
>>>> +}
>>>> diff --git a/src/Backend/MLT/modules/libvlc/consumer_libvlc.yml b/src/Backend/MLT/modules/libvlc/consumer_libvlc.yml
>>>> new file mode 100644
>>>> index 0000000..2776715
>>>> --- /dev/null
>>>> +++ b/src/Backend/MLT/modules/libvlc/consumer_libvlc.yml
>>>> @@ -0,0 +1,70 @@
>>>> +schema_version: 0.1
>>>> +type: consumer
>>>> +identifier: libvlc
>>>> +title: libVLC
>>>> +version: 1
>>>> +creator: Pawel Golinski
>>>> +license: GNU GPL
>>>> +language: en
>>>> +tags:
>>>> + - Audio
>>>> + - Video
>>>> +description: >
>>>> + libVLC video and audio output module. It uses VLC "standard" module.
>>>> + It can be set up using usual MLT consumer properties and additional
>>>> + libVLC specific properties described here.
>>>> +parameters:
>>>> + - identifier: output_dst
>>>> + argument: yes
>>>> + title: File/URL
>>>> + type: string
>>>> + description: "sout-standard-dst" option
>>>> + required: yes
>>>> +
>>>> + - identifier: input_vcodec
>>>> + title: Input vcodec
>>>> + type: string
>>>> + description: Format, in which raw video frames will be supplied to the consumer.
>>>> + default: RGBA
>>>> +
>>>> + - identifier: input_acodec
>>>> + title: Input acodec
>>>> + type: string
>>>> + description: Format, in which raw audio frames will be supplied to the consumer.
>>>> + default: s16l
>>>> +
>>>> + - identifier: output_vcodec
>>>> + title: Output vcodec.
>>>> + type: string
>>>> + description: "sout-transcode-vcodec" option
>>>> + default: mp2v
>>>> +
>>>> + - identifier: output_acodec
>>>> + title: Output acodec.
>>>> + type: string
>>>> + description: "sout-transcode-acodec" option
>>>> + default: mpga
>>>> +
>>>> + - identifier: output_vb
>>>> + title: Output video bitrate.
>>>> + type: integer
>>>> + description: "sout-transcode-vb" option
>>>> + default: 8000000
>>>> +
>>>> + - identifier: output_ab
>>>> + title: Output audio bitrate.
>>>> + type: integer
>>>> + description: "sout-transcode-ab" option
>>>> + default: 128000
>>>> +
>>>> + - identifier: output_mux
>>>> + title: Output muxer.
>>>> + type: string
>>>> + description: "sout-standard-mux" option
>>>> + default: ps
>>>> +
>>>> + - identifier: output_access
>>>> + title: Output method.
>>>> + type: string
>>>> + description: "sout-standard-access" option
>>>> + default: file
>>>> diff --git a/src/Backend/MLT/modules/libvlc/consumer_libvlc_window.yml b/src/Backend/MLT/modules/libvlc/consumer_libvlc_window.yml
>>>> new file mode 100644
>>>> index 0000000..d2b7410
>>>> --- /dev/null
>>>> +++ b/src/Backend/MLT/modules/libvlc/consumer_libvlc_window.yml
>>>> @@ -0,0 +1,39 @@
>>>> +schema_version: 0.1
>>>> +type: consumer
>>>> +identifier: libvlc_window
>>>> +title: libVLC Window
>>>> +version: 1
>>>> +creator: Pawel Golinski
>>>> +license: GNU GPL
>>>> +language: en
>>>> +tags:
>>>> + - Audio
>>>> + - Video
>>>> +description: >
>>>> + libVLC video and audio output module. It uses VLC window output.
>>>> + It can be set up using usual MLT consumer properties and additional
>>>> + libVLC specific properties described here.
>>>> +parameters:
>>>> + - identifier: output_dst
>>>> + argument: yes
>>>> + title: Window handle
>>>> + description: Window, to which libVLC should render the media.
>>>> + required: yes
>>>> +
>>>> + - identifier: window_type
>>>> + title: Window type
>>>> + type: string
>>>> + description: Type of the window, the output_dst points to (xwindow/nsobject/hwnd)
>>>> + required: yes
>>>> +
>>>> + - identifier: input_vcodec
>>>> + title: Input vcodec
>>>> + type: string
>>>> + description: Format, in which raw video frames will be supplied to the consumer.
>>>> + default: RGBA
>>>> +
>>>> + - identifier: input_acodec
>>>> + title: Input acodec
>>>> + type: string
>>>> + description: Format, in which raw audio frames will be supplied to the consumer.
>>>> + default: s16l
>>>> \ No newline at end of file
>>>> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
>>>> index a85cf0a..be37f15 100644
>>>> --- a/src/CMakeLists.txt
>>>> +++ b/src/CMakeLists.txt
>>>> @@ -55,6 +55,9 @@ INCLUDE_DIRECTORIES(${FREI0R_INCLUDE_DIR})
>>>> # Instruct CMake to run moc automatically when needed.
>>>> SET(CMAKE_AUTOMOC ON)
>>>>
>>>> +SET(MLT_MODULES Backend/MLT/modules)
>>>> +ADD_DEFINITIONS(-DMLT_MODULES_PATH="${CMAKE_CURRENT_BINARY_DIR}/src/${MLT_MODULES}")
>>>> +
>>>> SET(VLMC_SRCS
>>>> Commands/Commands.cpp
>>>> Backend/IBackend.h
>>>> @@ -74,6 +77,7 @@ SET(VLMC_SRCS
>>>> Backend/MLT/MLTFilter.cpp
>>>> Backend/MLT/MLTTransition.cpp
>>>> Backend/MLT/MLTMultiTrack.cpp
>>>> + Backend/MLT/modules/libvlc/consumer_libvlc.c
>>>> EffectsEngine/EffectHelper.cpp
>>>> Library/Library.cpp
>>>> Library/MediaContainer.cpp
>>>> @@ -314,14 +318,14 @@ ENDIF(UNIX)
>>>>
>>>> if( APPLE )
>>>> set(APPLICATION_BUNDLE ${CMAKE_BINARY_DIR}/bin/vlmc.app)
>>>> - set(APPLICATION_LIB_DIR ${LIBVLC_LIB_DIR})
>>>> + set(APPLICATION_LIB_DIR ${LIBVLC_LIBRARY_DIRS})
>>>>
>>>> # re-enable this when we start addressing redistribution
>>>> # message(STATUS "Looking for bundle ${APPLICATION_BUNDLE} with library path ${APPLICATION_LIB_DIR}")
>>>> # install(CODE "include(BundleUtilities)
>>>> add_custom_command(TARGET vlmc
>>>> POST_BUILD
>>>> - COMMAND ${CMAKE_SOURCE_DIR}/cmake/FixBundle.sh ${APPLICATION_BUNDLE}/Contents/MacOS ${LIBVLC_LIB_DIR}
>>>> + COMMAND ${CMAKE_SOURCE_DIR}/cmake/FixBundle.sh ${APPLICATION_BUNDLE}/Contents/MacOS ${LIBVLC_LIBRARY_DIRS}
>>>
>>> Why did you rename LIB to LIBRARY?
>>
>> Shoot. That's remains from another patch :/ (which needs to be merged asap btw because compilation is broken on OS X)
>>
Speaking of which, I'll probably push the switch to autotools today, but
might need some help fixing things on MacOS.
>>>
>>>> COMMENT "Fixing application bundle for local run")
>>>> # fixup_bundle(\"${APPLICATION_BUNDLE}\" \"\" \"${APPLICATION_LIB_DIR}\")" COMPONENT Runtime)
>>>> endif()
>>>> --
>>>> 2.7.4 (Apple Git-66)
>>>
>>> Maybe it's a good idea to have a separated repository or make it
>>> merged into the official mlt repository.
>>
>> I don't think guys at mlt would want to maintain these plugins so probably official mlt repo is not an option.
>>
I beg to differ :)
>>> But I have to see how others
>>> think :)
>>>
>>>> _______________________________________________
>>>> Vlmc-devel mailing list
>>>> Vlmc-devel at videolan.org
>>>> https://mailman.videolan.org/listinfo/vlmc-devel
>>> _______________________________________________
>>> Vlmc-devel mailing list
>>> Vlmc-devel at videolan.org
>>> https://mailman.videolan.org/listinfo/vlmc-devel
>> _______________________________________________
>> Vlmc-devel mailing list
>> Vlmc-devel at videolan.org
>> https://mailman.videolan.org/listinfo/vlmc-devel
> _______________________________________________
> Vlmc-devel mailing list
> Vlmc-devel at videolan.org
> https://mailman.videolan.org/listinfo/vlmc-devel
>
More information about the Vlmc-devel
mailing list