X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fframework%2Fmlt_profile.c;h=4385d7a789be5bf857c1d0b05f170256dce057f0;hb=9e781c515001a2428716557218200b2be634214e;hp=960550e8ce2c71d613ac0be249a8ba3b462a1a71;hpb=9bee7421e4b65a36f9977482a88027e8a5260eeb;p=mlt diff --git a/src/framework/mlt_profile.c b/src/framework/mlt_profile.c index 960550e8..4385d7a7 100644 --- a/src/framework/mlt_profile.c +++ b/src/framework/mlt_profile.c @@ -1,7 +1,10 @@ -/* - * mlt_profile.c -- video output definition - * Copyright (C) 2007 Ushodaya Enterprises Limited - * Author: Dan Dennedy +/** + * \file mlt_profile.c + * \brief video output definition + * \see mlt_profile_s + * + * Copyright (C) 2007-2009 Ushodaya Enterprises Limited + * \author Dan Dennedy * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,18 +21,26 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mlt_profile.h" -#include "mlt_factory.h" -#include "mlt_properties.h" +#include "mlt.h" #include #include #include +#include -#define PROFILES_DIR "/share/mlt/profiles/" -/** Load a profile from the system folder -*/ +/** the default subdirectory of the datadir for holding profiles */ +#define PROFILES_DIR "/profiles/" + +/** Load a profile from the system folder. + * + * The environment variable MLT_PROFILES_PATH overrides the default \p PROFILES_DIR. + * + * \private \memberof mlt_profile_s + * \param name the name of a profile settings file located in the standard location or + * the full path name to a profile settings file + * \return a profile or NULL on error + */ static mlt_profile mlt_profile_select( const char *name ) { @@ -37,20 +48,18 @@ static mlt_profile mlt_profile_select( const char *name ) const char *prefix = getenv( "MLT_PROFILES_PATH" ); mlt_properties properties = mlt_properties_load( name ); mlt_profile profile = NULL; - + // Try to load from file specification if ( properties && mlt_properties_get_int( properties, "width" ) ) { filename = calloc( 1, strlen( name ) + 1 ); } - // Load from $prefix/share/mlt/profiles + // Load from $datadir/mlt/profiles else if ( prefix == NULL ) { - prefix = PREFIX; - filename = calloc( 1, strlen( prefix ) + strlen( PROFILES_DIR ) + strlen( name ) + 2 ); + prefix = mlt_environment( "MLT_DATA" ); + filename = calloc( 1, strlen( prefix ) + strlen( PROFILES_DIR ) + strlen( name ) + 1 ); strcpy( filename, prefix ); - if ( filename[ strlen( filename ) - 1 ] != '/' ) - filename[ strlen( filename ) ] = '/'; strcat( filename, PROFILES_DIR ); } // Use environment variable instead @@ -61,7 +70,7 @@ static mlt_profile mlt_profile_select( const char *name ) if ( filename[ strlen( filename ) - 1 ] != '/' ) filename[ strlen( filename ) ] = '/'; } - + // Finish loading strcat( filename, name ); profile = mlt_profile_load_file( filename ); @@ -74,7 +83,14 @@ static mlt_profile mlt_profile_select( const char *name ) } /** Construct a profile. -*/ + * + * This will never return NULL as it uses the dv_pal settings as hard-coded fallback default. + * + * \public \memberof mlt_profile_s + * \param name the name of a profile settings file located in the standard location or + * the full path name to a profile settings file + * \return a profile + */ mlt_profile mlt_profile_init( const char *name ) { @@ -109,18 +125,44 @@ mlt_profile mlt_profile_init( const char *name ) profile->width = 720; profile->height = 576; profile->progressive = 0; - profile->sample_aspect_num = 59; - profile->sample_aspect_den = 54; + profile->sample_aspect_num = 16; + profile->sample_aspect_den = 15; profile->display_aspect_num = 4; profile->display_aspect_den = 3; + profile->colorspace = 601; } } } return profile; } -/** Load a profile from specific file -*/ +static void set_mlt_normalisation( const char *profile_name ) +{ + if ( profile_name ) + { + if ( strstr( profile_name, "_ntsc" ) || + strstr( profile_name, "_60" ) || + strstr( profile_name, "_5994" ) || + strstr( profile_name, "_2997" ) || + strstr( profile_name, "_30" ) ) + { + mlt_environment_set( "MLT_NORMALISATION", "NTSC" ); + } + else if ( strstr( profile_name, "_pal" ) || + strstr( profile_name, "_50" ) || + strstr( profile_name, "_25" ) ) + { + mlt_environment_set( "MLT_NORMALISATION", "PAL" ); + } + } +} + +/** Load a profile from specific file. + * + * \public \memberof mlt_profile_s + * \param file the full path name to a properties file + * \return a profile or NULL on error + */ mlt_profile mlt_profile_load_file( const char *file ) { @@ -138,6 +180,7 @@ mlt_profile mlt_profile_load_file( const char *file ) // Set MLT_PROFILE to basename char *filename = strdup( file ); mlt_environment_set( "MLT_PROFILE", basename( filename ) ); + set_mlt_normalisation( basename( filename ) ); free( filename ); } mlt_properties_close( properties ); @@ -145,26 +188,16 @@ mlt_profile mlt_profile_load_file( const char *file ) // Set MLT_NORMALISATION to appease legacy modules char *profile_name = mlt_environment( "MLT_PROFILE" ); - if ( profile_name ) - { - if ( strstr( profile_name, "_ntsc" ) || - strstr( profile_name, "_60" ) || - strstr( profile_name, "_30" ) ) - { - mlt_environment_set( "MLT_NORMALISATION", "NTSC" ); - } - else if ( strstr( profile_name, "_pal" ) || - strstr( profile_name, "_50" ) || - strstr( profile_name, "_25" ) ) - { - mlt_environment_set( "MLT_NORMALISATION", "PAL" ); - } - } + set_mlt_normalisation( profile_name ); return profile; } -/** Load a profile from a properties object -*/ +/** Load a profile from a properties object. + * + * \public \memberof mlt_profile_s + * \param properties a properties list + * \return a profile or NULL if out of memory + */ mlt_profile mlt_profile_load_properties( mlt_properties properties ) { @@ -184,16 +217,23 @@ mlt_profile mlt_profile_load_properties( mlt_properties properties ) profile->sample_aspect_den = mlt_properties_get_int( properties, "sample_aspect_den" ); profile->display_aspect_num = mlt_properties_get_int( properties, "display_aspect_num" ); profile->display_aspect_den = mlt_properties_get_int( properties, "display_aspect_den" ); + profile->colorspace = mlt_properties_get_int( properties, "colorspace" ); } return profile; } -/** Load an anonymous profile from string -*/ +/** Load an anonymous profile from string. + * + * \public \memberof mlt_profile_s + * \param string a newline-delimited list of properties as name=value pairs + * \return a profile or NULL if out of memory + */ mlt_profile mlt_profile_load_string( const char *string ) { mlt_properties properties = mlt_properties_new(); + mlt_profile profile = NULL; + if ( properties ) { const char *p = string; @@ -204,45 +244,62 @@ mlt_profile mlt_profile_load_string( const char *string ) p = strchr( p, '\n' ); if ( p ) p++; } + profile = mlt_profile_load_properties( properties ); + mlt_properties_close( properties ); } - return mlt_profile_load_properties( properties ); + return profile; } -/** Get the framerate as float -*/ +/** Get the video frame rate as a floating point value. + * + * \public \memberof mlt_profile_s + * @param profile a profile + * @return the frame rate + */ -double mlt_profile_fps( mlt_profile aprofile ) +double mlt_profile_fps( mlt_profile profile ) { - if ( aprofile ) - return ( double ) aprofile->frame_rate_num / aprofile->frame_rate_den; + if ( profile ) + return ( double ) profile->frame_rate_num / profile->frame_rate_den; else return 0; } -/** Get the sample aspect ratio as float -*/ +/** Get the sample aspect ratio as a floating point value. + * + * \public \memberof mlt_profile_s + * \param profile a profile + * \return the pixel aspect ratio + */ -double mlt_profile_sar( mlt_profile aprofile ) +double mlt_profile_sar( mlt_profile profile ) { - if ( aprofile ) - return ( double ) aprofile->sample_aspect_num / aprofile->sample_aspect_den; + if ( profile ) + return ( double ) profile->sample_aspect_num / profile->sample_aspect_den; else return 0; } -/** Get the display aspect ratio as float -*/ +/** Get the display aspect ratio as floating point value. + * + * \public \memberof mlt_profile_s + * \param profile a profile + * \return the image aspect ratio + */ -double mlt_profile_dar( mlt_profile aprofile ) +double mlt_profile_dar( mlt_profile profile ) { - if ( aprofile ) - return ( double ) aprofile->display_aspect_num / aprofile->display_aspect_den; + if ( profile ) + return ( double ) profile->display_aspect_num / profile->display_aspect_den; else return 0; } -/** Free up the global profile resources -*/ +/** Free up the global profile resources. + * + * \public \memberof mlt_profile_s + * \param profile a profile + */ void mlt_profile_close( mlt_profile profile ) { @@ -255,3 +312,144 @@ void mlt_profile_close( mlt_profile profile ) profile = NULL; } } + +/** Make a copy of a profile. + * + * \public \memberof mlt_profile_s + * \param profile the profile to clone + * \return a copy of the profile + */ + +mlt_profile mlt_profile_clone( mlt_profile profile ) +{ + mlt_profile clone = NULL; + + if ( profile ) + { + clone = calloc( 1, sizeof( *profile ) ); + if ( clone ) + { + memcpy( clone, profile, sizeof( *profile ) ); + clone->description = strdup( profile->description ); + } + } + return clone; +} + + +/** Get the list of profiles. + * + * The caller MUST close the returned properties object! + * Each entry in the list is keyed on its name, and its value is another + * properties object that contains the attributes of the profile. + * \public \memberof mlt_profile_s + * \return a list of profiles + */ + +mlt_properties mlt_profile_list( ) +{ + char *filename = NULL; + const char *prefix = getenv( "MLT_PROFILES_PATH" ); + mlt_properties properties = mlt_properties_new(); + mlt_properties dir = mlt_properties_new(); + int sort = 1; + const char *wildcard = NULL; + int i; + + // Load from $datadir/mlt/profiles if no env var + if ( prefix == NULL ) + { + prefix = mlt_environment( "MLT_DATA" ); + filename = calloc( 1, strlen( prefix ) + strlen( PROFILES_DIR ) + 1 ); + strcpy( filename, prefix ); + strcat( filename, PROFILES_DIR ); + prefix = filename; + } + + mlt_properties_dir_list( dir, prefix, wildcard, sort ); + + for ( i = 0; i < mlt_properties_count( dir ); i++ ) + { + char *filename = mlt_properties_get_value( dir, i ); + char *profile_name = basename( filename ); + if ( profile_name[0] != '.' && strcmp( profile_name, "Makefile" ) && + profile_name[ strlen( profile_name ) - 1 ] != '~' ) + { + mlt_properties profile = mlt_properties_load( filename ); + if ( profile ) + { + mlt_properties_set_data( properties, profile_name, profile, 0, + (mlt_destructor) mlt_properties_close, NULL ); + } + } + } + mlt_properties_close( dir ); + if ( filename ) + free( filename ); + + return properties; +} + +/** Update the profile using the attributes of a producer. + * + * Use this to make an "auto-profile." Typically, you need to re-open the producer + * after you use this because some producers (e.g. avformat) adjust their framerate + * to that of the profile used when you created it. + * \public \memberof mlt_profile_s + * \param profile the profile to update + * \param producer the producer to inspect + */ + +void mlt_profile_from_producer( mlt_profile profile, mlt_producer producer ) +{ + mlt_frame fr = NULL; + uint8_t *buffer = NULL; + mlt_image_format fmt = mlt_image_none; + mlt_properties p; + int w = profile->width; + int h = profile->height; + + if ( ! mlt_service_get_frame( MLT_PRODUCER_SERVICE(producer), &fr, 0 ) && fr ) + { + if ( ! mlt_frame_get_image( fr, &buffer, &fmt, &w, &h, 0 ) ) + { + // Some source properties are not exposed until after the first get_image call. + mlt_frame_close( fr ); + mlt_service_get_frame( MLT_PRODUCER_SERVICE(producer), &fr, 0 ); + p = MLT_FRAME_PROPERTIES( fr ); +// mlt_properties_dump(p, stderr); + if ( mlt_properties_get_int( p, "meta.media.frame_rate_den" ) && + mlt_properties_get_int( p, "meta.media.sample_aspect_den" ) ) + { + profile->width = mlt_properties_get_int( p, "meta.media.width" ); + profile->height = mlt_properties_get_int( p, "meta.media.height" ); + profile->progressive = mlt_properties_get_int( p, "meta.media.progressive" ); + if ( 1000 > mlt_properties_get_double( p, "meta.media.frame_rate_num" ) + / mlt_properties_get_double( p, "meta.media.frame_rate_den" ) ) + { + profile->frame_rate_num = mlt_properties_get_int( p, "meta.media.frame_rate_num" ); + profile->frame_rate_den = mlt_properties_get_int( p, "meta.media.frame_rate_den" ); + } else { + profile->frame_rate_num = 60; + profile->frame_rate_den = 1; + } + // AVCHD is mis-reported as double frame rate. + if ( profile->progressive == 0 && ( + profile->frame_rate_num / profile->frame_rate_den == 50 || + profile->frame_rate_num / profile->frame_rate_den == 59 ) ) + profile->frame_rate_num /= 2; + profile->sample_aspect_num = mlt_properties_get_int( p, "meta.media.sample_aspect_num" ); + profile->sample_aspect_den = mlt_properties_get_int( p, "meta.media.sample_aspect_den" ); + profile->colorspace = mlt_properties_get_int( p, "meta.media.colorspace" ); + profile->display_aspect_num = lrint( (double) profile->sample_aspect_num * profile->width + / profile->sample_aspect_den ); + profile->display_aspect_den = profile->height; + free( profile->description ); + profile->description = strdup( "automatic" ); + profile->is_explicit = 0; + } + } + } + mlt_frame_close( fr ); + mlt_producer_seek( producer, 0 ); +}