/*****************************************************************************
|
* LibVLC.java
|
*****************************************************************************
|
* Copyright © 2010-2013 VLC authors and VideoLAN
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms of the GNU Lesser General Public License as published by
|
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
*
|
* You should have received a copy of the GNU Lesser 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.
|
*****************************************************************************/
|
|
package org.videolan.libvlc;
|
|
import java.util.ArrayList;
|
import java.util.Map;
|
|
import android.content.Context;
|
import android.os.Build;
|
import android.util.Log;
|
import android.view.Surface;
|
|
public class LibVLC {
|
private static final String TAG = "VLC/LibVLC";
|
public static final int AOUT_AUDIOTRACK_JAVA = 0;
|
public static final int AOUT_AUDIOTRACK = 1;
|
public static final int AOUT_OPENSLES = 2;
|
|
public static final int VOUT_ANDROID_SURFACE = 0;
|
public static final int VOUT_OPEGLES2 = 1;
|
|
private static LibVLC sInstance;
|
|
/** libVLC instance C pointer */
|
private long mLibVlcInstance = 0; // Read-only, reserved for JNI
|
/** libvlc_media_player pointer and index */
|
private int mInternalMediaPlayerIndex = 0; // Read-only, reserved for JNI
|
private long mInternalMediaPlayerInstance = 0; // Read-only, reserved for JNI
|
|
private MediaList mMediaList; // Pointer to media list being followed
|
private MediaList mPrimaryList; // Primary/default media list; see getPrimaryMediaList()
|
|
/** Buffer for VLC messages */
|
private StringBuffer mDebugLogBuffer;
|
private boolean mIsBufferingLog = false;
|
|
private Aout mAout;
|
|
/** Keep screen bright */
|
//private WakeLock mWakeLock;
|
|
/** Settings */
|
private int hardwareAcceleration = -1;
|
private String subtitlesEncoding = "";
|
private int aout = LibVlcUtil.isGingerbreadOrLater() ? AOUT_OPENSLES : AOUT_AUDIOTRACK_JAVA;
|
private int vout = VOUT_ANDROID_SURFACE;
|
private boolean timeStretching = false;
|
private int deblocking = -1;
|
private String chroma = "";
|
private boolean verboseMode = true;
|
private float[] equalizer = null;
|
private boolean frameSkip = false;
|
private int networkCaching = 0;
|
|
/** Check in libVLC already initialized otherwise crash */
|
private boolean mIsInitialized = false;
|
public native void attachSurface(Surface surface, IVideoPlayer player);
|
|
public native void detachSurface();
|
|
public native void attachSubtitlesSurface(Surface surface);
|
public native void detachSubtitlesSurface();
|
|
/* Load library before object instantiation */
|
static {
|
try {
|
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
|
System.loadLibrary("iomx-gingerbread");
|
else if (Build.VERSION.SDK_INT <= 13)//Build.VERSION_CODES.HONEYCOMB_MR2
|
System.loadLibrary("iomx-hc");
|
else if (Build.VERSION.SDK_INT <= 18)//Build.VERSION_CODES.JELLY_BEAN_MR2
|
System.loadLibrary("iomx-ics");
|
} catch (Throwable t) {
|
Log.w(TAG, "Unable to load the iomx library: " + t);
|
}
|
try {
|
System.loadLibrary("vlcjni");
|
} catch (UnsatisfiedLinkError ule) {
|
Log.e(TAG, "Can't load vlcjni library: " + ule);
|
/// FIXME Alert user
|
System.exit(1);
|
} catch (SecurityException se) {
|
Log.e(TAG, "Encountered a security issue when loading vlcjni library: " + se);
|
/// FIXME Alert user
|
System.exit(1);
|
}
|
}
|
|
/**
|
* Singleton constructor of libVLC Without surface and vout to create the
|
* thumbnail and get information e.g. on the MediaLibraryActivity
|
*
|
* @return libVLC instance
|
* @throws LibVlcException
|
*/
|
public static LibVLC getInstance() throws LibVlcException {
|
synchronized (LibVLC.class) {
|
if (sInstance == null) {
|
/* First call */
|
sInstance = new LibVLC();
|
}
|
}
|
|
return sInstance;
|
}
|
|
/**
|
* Return an existing instance of libVLC Call it when it is NOT important
|
* that this fails
|
*
|
* @return libVLC instance OR null
|
*/
|
public static LibVLC getExistingInstance() {
|
synchronized (LibVLC.class) {
|
return sInstance;
|
}
|
}
|
|
/**
|
* Constructor
|
* It is private because this class is a singleton.
|
*/
|
private LibVLC() {
|
mAout = new Aout();
|
}
|
|
/**
|
* Destructor:
|
* It is bad practice to rely on them, so please don't forget to call
|
* destroy() before exiting.
|
*/
|
@Override
|
public void finalize() {
|
if (mLibVlcInstance != 0) {
|
Log.d(TAG, "LibVLC is was destroyed yet before finalize()");
|
destroy();
|
}
|
}
|
|
/**
|
* Get the media list that LibVLC is following right now.
|
*
|
* @return The media list object being followed
|
*/
|
public MediaList getMediaList() {
|
return mMediaList;
|
}
|
|
/**
|
* Set the media list for LibVLC to follow.
|
*
|
* @param mediaList The media list object to follow
|
*/
|
public void setMediaList(MediaList mediaList) {
|
mMediaList = mediaList;
|
}
|
|
/**
|
* Sets LibVLC to follow the default media list (see below)
|
*/
|
public void setMediaList() {
|
mMediaList = mPrimaryList;
|
}
|
|
/**
|
* Gets the primary media list, or the "currently playing" list.
|
* Not to be confused with the media list pointer from above, which
|
* refers the the MediaList object that libVLC is currently following.
|
* This list is just one out of many lists that it can be pointed towards.
|
*
|
* This list will be used for lists of songs that are not user-defined.
|
* For example: selecting a song from the Songs list, or from the list
|
* displayed after selecting an album.
|
*
|
* It is loaded as the default list.
|
*
|
* @return The primary media list
|
*/
|
public MediaList getPrimaryMediaList() {
|
return mPrimaryList;
|
}
|
|
/**
|
* Give to LibVLC the surface to draw the video.
|
* @param f the surface to draw
|
*/
|
public native void setSurface(Surface f);
|
|
public static synchronized void restart(Context context) {
|
if (sInstance != null) {
|
try {
|
sInstance.destroy();
|
sInstance.init(context);
|
} catch (LibVlcException lve) {
|
Log.e(TAG, "Unable to reinit libvlc: " + lve);
|
}
|
}
|
}
|
|
/**
|
* those get/is* are called from native code to get settings values.
|
*/
|
|
public int getHardwareAcceleration() {
|
return this.hardwareAcceleration;
|
}
|
|
public void setHardwareAcceleration(int hardwareAcceleration) {
|
if (hardwareAcceleration < 0) {
|
// Automatic mode: activate MediaCodec opaque direct rendering for 4.3 and above.
|
if (LibVlcUtil.isJellyBeanMR2OrLater())
|
this.hardwareAcceleration = 2;
|
else
|
this.hardwareAcceleration = 0;
|
}
|
else
|
this.hardwareAcceleration = hardwareAcceleration;
|
}
|
|
public String getSubtitlesEncoding() {
|
return subtitlesEncoding;
|
}
|
|
public void setSubtitlesEncoding(String subtitlesEncoding) {
|
this.subtitlesEncoding = subtitlesEncoding;
|
}
|
|
public int getAout() {
|
return aout;
|
}
|
|
public void setAout(int aout) {
|
if (aout < 0)
|
this.aout = LibVlcUtil.isGingerbreadOrLater() ? AOUT_OPENSLES : AOUT_AUDIOTRACK_JAVA;
|
else
|
this.aout = aout;
|
}
|
|
public int getVout() {
|
return vout;
|
}
|
|
public void setVout(int vout) {
|
if (vout < 0)
|
this.vout = VOUT_ANDROID_SURFACE;
|
else
|
this.vout = vout;
|
}
|
|
public boolean timeStretchingEnabled() {
|
return timeStretching;
|
}
|
|
public void setTimeStretching(boolean timeStretching) {
|
this.timeStretching = timeStretching;
|
}
|
|
public int getDeblocking() {
|
int ret = deblocking;
|
if(deblocking < 0) {
|
/**
|
* Set some reasonable deblocking defaults:
|
*
|
* Skip all (4) for armv6 and MIPS by default
|
* Skip non-ref (1) for all armv7 more than 1.2 Ghz and more than 2 cores
|
* Skip non-key (3) for all devices that don't meet anything above
|
*/
|
LibVlcUtil.MachineSpecs m = LibVlcUtil.getMachineSpecs();
|
if( (m.hasArmV6 && !(m.hasArmV7)) || m.hasMips )
|
ret = 4;
|
else if(m.bogoMIPS > 1200 && m.processors > 2)
|
ret = 1;
|
else
|
ret = 3;
|
} else if(deblocking > 4) { // sanity check
|
ret = 3;
|
}
|
return ret;
|
}
|
|
public void setDeblocking(int deblocking) {
|
this.deblocking = deblocking;
|
}
|
|
public String getChroma() {
|
return chroma;
|
}
|
|
public void setChroma(String chroma) {
|
this.chroma = chroma.equals("YV12") && !LibVlcUtil.isGingerbreadOrLater() ? "" : chroma;
|
}
|
|
public boolean isVerboseMode() {
|
return verboseMode;
|
}
|
|
public void setVerboseMode(boolean verboseMode) {
|
this.verboseMode = verboseMode;
|
}
|
|
public float[] getEqualizer()
|
{
|
return equalizer;
|
}
|
|
public void setEqualizer(float[] equalizer)
|
{
|
this.equalizer = equalizer;
|
applyEqualizer();
|
}
|
|
private void applyEqualizer()
|
{
|
setNativeEqualizer(mInternalMediaPlayerInstance, this.equalizer);
|
}
|
private native int setNativeEqualizer(long mediaPlayer, float[] bands);
|
|
public boolean frameSkipEnabled() {
|
return frameSkip;
|
}
|
|
public void setFrameSkip(boolean frameskip) {
|
this.frameSkip = frameskip;
|
}
|
|
public int getNetworkCaching() {
|
return this.networkCaching;
|
}
|
|
public void setNetworkCaching(int networkcaching) {
|
this.networkCaching = networkcaching;
|
}
|
|
/**
|
* Initialize the libVLC class.
|
*
|
* This function must be called before using any libVLC functions.
|
*
|
* @throws LibVlcException
|
*/
|
public void init(Context context) throws LibVlcException {
|
Log.v(TAG, "Initializing LibVLC");
|
mDebugLogBuffer = new StringBuffer();
|
if (!mIsInitialized) {
|
if(!LibVlcUtil.hasCompatibleCPU(context)) {
|
Log.e(TAG, LibVlcUtil.getErrorMsg());
|
throw new LibVlcException();
|
}
|
nativeInit();
|
mMediaList = mPrimaryList = new MediaList(this);
|
setEventHandler(EventHandler.getInstance());
|
mIsInitialized = true;
|
}
|
}
|
|
/**
|
* Destroy this libVLC instance
|
* @note You must call it before exiting
|
*/
|
public void destroy() {
|
Log.v(TAG, "Destroying LibVLC instance");
|
nativeDestroy();
|
detachEventHandler();
|
mIsInitialized = false;
|
}
|
|
/**
|
* Open the Java audio output.
|
* This function is called by the native code
|
*/
|
public void initAout(int sampleRateInHz, int channels, int samples) {
|
Log.d(TAG, "Opening the java audio output");
|
mAout.init(sampleRateInHz, channels, samples);
|
}
|
|
/**
|
* Play an audio buffer taken from the native code
|
* This function is called by the native code
|
*/
|
public void playAudio(byte[] audioData, int bufferSize) {
|
mAout.playBuffer(audioData, bufferSize);
|
}
|
|
/**
|
* Pause the Java audio output
|
* This function is called by the native code
|
*/
|
public void pauseAout() {
|
Log.d(TAG, "Pausing the java audio output");
|
mAout.pause();
|
}
|
|
/**
|
* Close the Java audio output
|
* This function is called by the native code
|
*/
|
public void closeAout() {
|
Log.d(TAG, "Closing the java audio output");
|
mAout.release();
|
}
|
|
/**
|
* Play a media from the media list (playlist)
|
*
|
* @param position The index of the media
|
*/
|
public void playIndex(int position) {
|
String mrl = mMediaList.getMRL(position);
|
if (mrl == null)
|
return;
|
String[] options = mMediaList.getMediaOptions(position);
|
mInternalMediaPlayerIndex = position;
|
playMRL(mLibVlcInstance, mrl, options);
|
}
|
|
/**
|
* Play an MRL directly.
|
*
|
* @param mrl MRL of the media to play.
|
*/
|
public void playMRL(String mrl) {
|
// index=-1 will return options from libvlc instance without relying on MediaList
|
String[] options = mMediaList.getMediaOptions(-1);
|
mInternalMediaPlayerIndex = 0;
|
playMRL(mLibVlcInstance, mrl, options);
|
}
|
|
public TrackInfo[] readTracksInfo(String mrl) {
|
return readTracksInfo(mLibVlcInstance, mrl);
|
}
|
|
/**
|
* Get a media thumbnail.
|
*/
|
public byte[] getThumbnail(String mrl, int i_width, int i_height) {
|
return getThumbnail(mLibVlcInstance, mrl, i_width, i_height);
|
}
|
|
/**
|
* Return true if there is a video track in the file
|
*/
|
public boolean hasVideoTrack(String mrl) throws java.io.IOException {
|
return hasVideoTrack(mLibVlcInstance, mrl);
|
}
|
|
/**
|
* Sets the speed of playback (1 being normal speed, 2 being twice as fast)
|
*
|
* @param rate
|
*/
|
public native void setRate(float rate);
|
|
/**
|
* Get the current playback speed
|
*/
|
public native float getRate();
|
|
/**
|
* Initialize the libvlc C library
|
* @return a pointer to the libvlc instance
|
*/
|
private native void nativeInit() throws LibVlcException;
|
|
/**
|
* Close the libvlc C library
|
* @note mLibVlcInstance should be 0 after a call to destroy()
|
*/
|
private native void nativeDestroy();
|
|
/**
|
* Start buffering to the mDebugLogBuffer.
|
*/
|
public native void startDebugBuffer();
|
public native void stopDebugBuffer();
|
public String getBufferContent() {
|
return mDebugLogBuffer.toString();
|
}
|
|
public void clearBuffer() {
|
mDebugLogBuffer.setLength(0);
|
}
|
|
public boolean isDebugBuffering() {
|
return mIsBufferingLog;
|
}
|
|
/**
|
* Play an mrl
|
*/
|
private native void playMRL(long instance, String mrl, String[] mediaOptions);
|
|
/**
|
* Returns true if any media is playing
|
*/
|
public native boolean isPlaying();
|
|
/**
|
* Returns true if any media is seekable
|
*/
|
public native boolean isSeekable();
|
|
/**
|
* Plays any loaded media
|
*/
|
public native void play();
|
|
/**
|
* Pauses any playing media
|
*/
|
public native void pause();
|
|
/**
|
* Stops any playing media
|
*/
|
public native void stop();
|
|
/**
|
* Gets volume as integer
|
*/
|
public native int getVolume();
|
|
/**
|
* Sets volume as integer
|
* @param volume: Volume level passed as integer
|
*/
|
public native int setVolume(int volume);
|
|
/**
|
* Gets the current movie time (in ms).
|
* @return the movie time (in ms), or -1 if there is no media.
|
*/
|
public native long getTime();
|
|
/**
|
* Sets the movie time (in ms), if any media is being played.
|
* @param time: Time in ms.
|
* @return the movie time (in ms), or -1 if there is no media.
|
*/
|
public native long setTime(long time);
|
|
/**
|
* Gets the movie position.
|
* @return the movie position, or -1 for any error.
|
*/
|
public native float getPosition();
|
|
/**
|
* Sets the movie position.
|
* @param pos: movie position.
|
*/
|
public native void setPosition(float pos);
|
|
/**
|
* Gets current movie's length in ms.
|
* @return the movie length (in ms), or -1 if there is no media.
|
*/
|
public native long getLength();
|
|
/**
|
* Get the libVLC version
|
* @return the libVLC version string
|
*/
|
public native String version();
|
|
/**
|
* Get the libVLC compiler
|
* @return the libVLC compiler string
|
*/
|
public native String compiler();
|
|
/**
|
* Get the libVLC changeset
|
* @return the libVLC changeset string
|
*/
|
public native String changeset();
|
|
/**
|
* Get a media thumbnail.
|
* @return a bytearray with the RGBA thumbnail data inside.
|
*/
|
private native byte[] getThumbnail(long instance, String mrl, int i_width, int i_height);
|
|
/**
|
* Return true if there is a video track in the file
|
*/
|
private native boolean hasVideoTrack(long instance, String mrl);
|
|
private native TrackInfo[] readTracksInfo(long instance, String mrl);
|
|
public native TrackInfo[] readTracksInfoInternal();
|
|
public native int getAudioTracksCount();
|
|
public native Map<Integer,String> getAudioTrackDescription();
|
|
public native int getAudioTrack();
|
|
public native int setAudioTrack(int index);
|
|
public native int getVideoTracksCount();
|
|
public native int addSubtitleTrack(String path);
|
|
public native Map<Integer,String> getSpuTrackDescription();
|
|
public native int getSpuTrack();
|
|
public native int setSpuTrack(int index);
|
|
public native int getSpuTracksCount();
|
|
public static native String nativeToURI(String path);
|
|
/**
|
* Quickly converts path to URIs, which are mandatory in libVLC.
|
*
|
* @param path
|
* The path to be converted.
|
* @return A URI representation of path
|
*/
|
public static String PathToURI(String path) {
|
if(path == null) {
|
throw new NullPointerException("Cannot convert null path!");
|
}
|
return LibVLC.nativeToURI(path);
|
}
|
|
public static native void nativeReadDirectory(String path, ArrayList<String> res);
|
|
public native static boolean nativeIsPathDirectory(String path);
|
|
/**
|
* Expand and continue playing the current media.
|
*
|
* @return the index of the media was expanded, and -1 if no media was expanded
|
*/
|
public int expandAndPlay() {
|
int r = mMediaList.expandMedia(mInternalMediaPlayerIndex);
|
if(r == 0)
|
this.playIndex(mInternalMediaPlayerIndex);
|
return r;
|
}
|
|
/**
|
* Expand the current media.
|
* @return the index of the media was expanded, and -1 if no media was expanded
|
*/
|
public int expand() {
|
return mMediaList.expandMedia(mInternalMediaPlayerIndex);
|
}
|
|
private native void setEventHandler(EventHandler eventHandler);
|
|
private native void detachEventHandler();
|
|
public native float[] getBands();
|
|
public native String[] getPresets();
|
|
public native float[] getPreset(int index);
|
}
|