package net.sourceforge.jffmpeg; import java.util.ResourceBundle; import java.util.StringTokenizer; import javax.media.format.VideoFormat; import javax.media.format.AudioFormat; import javax.media.Format; import net.sourceforge.jffmpeg.ffmpegnative.NativeDecoder; /** * Manage the available Codecs. * * These are loaded from a .properties file. */ public class CodecManager { /** * Resource bundle with configuration information */ private ResourceBundle resources; /** * Location of Jffmpeg resource file */ private static final String JFFMPEG_RESOURCE = "net.sourceforge.jffmpeg.Jffmpeg"; /** * List of supported video formats */ private static final String SUPPORTED_VIDEO_FORMATS = "SupportedVideoFormats"; /** * List of supported video formats */ private static final String SUPPORTED_AUDIO_FORMATS = "SupportedAudioFormats"; /** * Override native library name */ private static final String LIBRARY_NAME = "FFMpegNativeLibrary"; private static final String SYS_LIBRARY_NAME = "net.sourceforge.jffmpeg.FFMpegNativeLibrary"; /** * Load the CodecManager class */ public CodecManager() { resources = ResourceBundle.getBundle( JFFMPEG_RESOURCE ); } /** * Read the native library name. * This can be overriden using a system property. */ public String getNativeLibraryName() { String libraryName = null; try { libraryName = System.getProperty( SYS_LIBRARY_NAME ); } catch ( Exception e ) { /* SecurityException */ } try { if ( libraryName == null || libraryName.length() == 0 ) { libraryName = resources.getString( LIBRARY_NAME ); } } catch ( Exception e ) { /* ResourceNotFoundException */ } return libraryName; } /** * Return list of supported VideoFormats */ public VideoFormat[] getSupportedVideoFormats() { String formats = resources.getString( SUPPORTED_VIDEO_FORMATS ); StringTokenizer tokenizer = new StringTokenizer( formats, "," ); VideoFormat[] videoFormats = new VideoFormat[ tokenizer.countTokens() ]; int i = 0; while ( tokenizer.hasMoreTokens() ) { videoFormats[ i++ ] = new VideoFormat( tokenizer.nextToken() ); } return videoFormats; } /** * Return list of supported VideoFormats */ public AudioFormat[] getSupportedAudioFormats() { String formats = resources.getString( SUPPORTED_AUDIO_FORMATS ); StringTokenizer tokenizer = new StringTokenizer( formats, "," ); AudioFormat[] audioFormats = new AudioFormat[ tokenizer.countTokens() ]; int i = 0; while ( tokenizer.hasMoreTokens() ) { audioFormats[ i++ ] = new AudioFormat( tokenizer.nextToken() ); } return audioFormats; } /** * Return the Codec information for this encoding */ public JffmpegVideoFormat getVideoCodec( String encoding ) { return new JffmpegVideoFormat( encoding, resources ); } /** * Return the Codec information for this encoding */ public JffmpegAudioFormat getAudioCodec( String encoding ) { return new JffmpegAudioFormat( encoding, resources ); } /** * Store if the native codec is available */ private static volatile int isNativeLoaded = -1; public synchronized static boolean isNativeAvailable() { if ( isNativeLoaded == -1 ) { try { NativeDecoder d = new NativeDecoder(); isNativeLoaded = d.isCodecAvailable() ? 1 : 0; } catch ( Throwable e ) { isNativeLoaded = 0; } } return (isNativeLoaded > 0); } } /** * This class is used to describe an individual * Video codec. All parameters are loaded from * a resource bundle. */ class JffmpegVideoFormat extends VideoFormat { private static final String RTP_STRING = ".RTP"; private static final String NATIVE_STRING = ".Native"; private static final String CLASS_STRING = ".Class"; private static final String JAVA_CLASS_STRING = ".JavaClass"; private static final String FFMPEG_NAME = ".FFMpegName"; private static final String TRUNCATE_STRING = ".IsTruncated"; private String name; ResourceBundle configuration; /** * Construct a Video codec description */ public JffmpegVideoFormat( String name, ResourceBundle configuration ) { super( name ); this.name = name; this.configuration = configuration; } /** * Returns true if this is an RTP format */ public boolean isRtp() { return "true".equalsIgnoreCase( configuration.getString( name + RTP_STRING) ); } /** * Returns true if this Codec is managed by the JNI layer */ public boolean isNative() { return CodecManager.isNativeAvailable() && "true".equalsIgnoreCase( configuration.getString( name + NATIVE_STRING) ); } /** * Return the class set to handle this codec */ public String getCodecClass() { return configuration.getString( name + (isNative() ? CLASS_STRING : JAVA_CLASS_STRING) ); } /** * Returns the identifier used by FFMpeg for this Codec */ public String getFFMpegCodecName() { return configuration.getString( name + FFMPEG_NAME ); } public boolean isTruncated() { return "true".equalsIgnoreCase( configuration.getString( name + TRUNCATE_STRING) ); } } /** * This class is used to describe an individual * Audio codec. All parameters are loaded from * a resource bundle. */ class JffmpegAudioFormat extends AudioFormat { private static final String NATIVE_STRING = ".Native"; private static final String CLASS_STRING = ".Class"; private static final String JAVA_CLASS_STRING = ".JavaClass"; private static final String FFMPEG_NAME = ".FFMpegName"; private String name; ResourceBundle configuration; /** * Construct a Video codec description */ public JffmpegAudioFormat( String name, ResourceBundle configuration ) { super( name ); this.name = name; this.configuration = configuration; } /** * Returns true if this Codec is managed by the JNI layer */ public boolean isNative() { return CodecManager.isNativeAvailable() && "true".equalsIgnoreCase( configuration.getString( name + NATIVE_STRING) ); } /** * Return the class set to handle this codec */ public String getCodecClass() { return configuration.getString( name + (isNative() ? CLASS_STRING : JAVA_CLASS_STRING) ); } /** * Returns the identifier used by FFMpeg for this Codec */ public String getFFMpegCodecName() { return configuration.getString( name + FFMPEG_NAME ); } }