Repository: over140/vlc-android-demo
Branch: master
Commit: 9adcbf8687bf
Files: 27
Total size: 93.5 KB
Directory structure:
gitextract_zhjhf_95/
├── .gitignore
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── nmbb/
│ │ └── vlc/
│ │ └── ApplicationTest.java
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ ├── com/
│ │ │ └── nmbb/
│ │ │ └── vlc/
│ │ │ ├── VLCApplication.java
│ │ │ └── ui/
│ │ │ └── VlcVideoActivity.java
│ │ └── org/
│ │ └── videolan/
│ │ ├── libvlc/
│ │ │ ├── AudioOutput.java
│ │ │ ├── EventHandler.java
│ │ │ ├── IVideoPlayer.java
│ │ │ ├── LibVLC.java
│ │ │ ├── LibVlcException.java
│ │ │ ├── LibVlcUtil.java
│ │ │ ├── Media.java
│ │ │ ├── MediaList.java
│ │ │ └── TrackInfo.java
│ │ └── vlc/
│ │ └── util/
│ │ ├── Preferences.java
│ │ └── VLCInstance.java
│ └── res/
│ ├── layout/
│ │ └── activity_video_vlc.xml
│ ├── values/
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── values-w820dp/
│ └── dimens.xml
├── build.gradle
├── gradle.properties
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/.idea
*.iml
/gradle
gradlew
gradlew.bat
proguard-rules.pro
================================================
FILE: README.md
================================================
vlc-android-demo
================
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'android'
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
defaultConfig {
applicationId "com.nmbb.vlc"
minSdkVersion 9
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:19.1.0'
}
================================================
FILE: app/src/androidTest/java/com/nmbb/vlc/ApplicationTest.java
================================================
package com.nmbb.vlc;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* Testing Fundamentals
*/
public class ApplicationTest extends ApplicationTestCase {
public ApplicationTest() {
super(Application.class);
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
================================================
FILE: app/src/main/java/com/nmbb/vlc/VLCApplication.java
================================================
package com.nmbb.vlc;
import android.app.Application;
import android.content.Context;
/**
* Created by tangjun on 14-8-24.
*/
public class VLCApplication extends Application {
private static VLCApplication sInstance;
@Override
public void onCreate() {
super.onCreate();
sInstance = this;
}
public static Context getAppContext() {
return sInstance;
}
}
================================================
FILE: app/src/main/java/com/nmbb/vlc/ui/VlcVideoActivity.java
================================================
package com.nmbb.vlc.ui;
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import com.nmbb.vlc.R;
import org.videolan.libvlc.EventHandler;
import org.videolan.libvlc.IVideoPlayer;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.LibVlcException;
import org.videolan.vlc.util.VLCInstance;
public class VlcVideoActivity extends Activity implements SurfaceHolder.Callback, IVideoPlayer {
private final static String TAG = "[VlcVideoActivity]";
private SurfaceView mSurfaceView;
private LibVLC mMediaPlayer;
private SurfaceHolder mSurfaceHolder;
private View mLoadingView;
private int mVideoHeight;
private int mVideoWidth;
private int mVideoVisibleHeight;
private int mVideoVisibleWidth;
private int mSarNum;
private int mSarDen;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_vlc);
mSurfaceView = (SurfaceView) findViewById(R.id.video);
mLoadingView = findViewById(R.id.video_loading);
try {
mMediaPlayer = VLCInstance.getLibVlcInstance();
} catch (LibVlcException e) {
e.printStackTrace();
}
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setFormat(PixelFormat.RGBX_8888);
mSurfaceHolder.addCallback(this);
mMediaPlayer.eventVideoPlayerActivityCreated(true);
EventHandler em = EventHandler.getInstance();
em.addHandler(mVlcHandler);
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
mSurfaceView.setKeepScreenOn(true);
// mMediaPlayer.setMediaList();
// mMediaPlayer.getMediaList().add(new Media(mMediaPlayer, "http://live.3gv.ifeng.com/zixun.m3u8"), false);
// mMediaPlayer.playIndex(0);
mMediaPlayer.playMRL("http://live.3gv.ifeng.com/zixun.m3u8");
}
@Override
public void onPause() {
super.onPause();
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mSurfaceView.setKeepScreenOn(false);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null) {
mMediaPlayer.eventVideoPlayerActivityCreated(false);
EventHandler em = EventHandler.getInstance();
em.removeHandler(mVlcHandler);
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
setSurfaceSize(mVideoWidth, mVideoHeight, mVideoVisibleWidth, mVideoVisibleHeight, mSarNum, mSarDen);
super.onConfigurationChanged(newConfig);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (mMediaPlayer != null) {
mSurfaceHolder = holder;
mMediaPlayer.attachSurface(holder.getSurface(), this);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mSurfaceHolder = holder;
if (mMediaPlayer != null) {
mMediaPlayer.attachSurface(holder.getSurface(), this);//, width, height
}
if (width > 0) {
mVideoHeight = height;
mVideoWidth = width;
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mMediaPlayer != null) {
mMediaPlayer.detachSurface();
}
}
@Override
public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) {
mVideoHeight = height;
mVideoWidth = width;
mVideoVisibleHeight = visible_height;
mVideoVisibleWidth = visible_width;
mSarNum = sar_num;
mSarDen = sar_den;
mHandler.removeMessages(HANDLER_SURFACE_SIZE);
mHandler.sendEmptyMessage(HANDLER_SURFACE_SIZE);
}
private static final int HANDLER_BUFFER_START = 1;
private static final int HANDLER_BUFFER_END = 2;
private static final int HANDLER_SURFACE_SIZE = 3;
private static final int SURFACE_BEST_FIT = 0;
private static final int SURFACE_FIT_HORIZONTAL = 1;
private static final int SURFACE_FIT_VERTICAL = 2;
private static final int SURFACE_FILL = 3;
private static final int SURFACE_16_9 = 4;
private static final int SURFACE_4_3 = 5;
private static final int SURFACE_ORIGINAL = 6;
private int mCurrentSize = SURFACE_BEST_FIT;
private Handler mVlcHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg == null || msg.getData() == null)
return;
switch (msg.getData().getInt("event")) {
case EventHandler.MediaPlayerTimeChanged:
break;
case EventHandler.MediaPlayerPositionChanged:
break;
case EventHandler.MediaPlayerPlaying:
mHandler.removeMessages(HANDLER_BUFFER_END);
mHandler.sendEmptyMessage(HANDLER_BUFFER_END);
break;
case EventHandler.MediaPlayerBuffering:
break;
case EventHandler.MediaPlayerLengthChanged:
break;
case EventHandler.MediaPlayerEndReached:
//播放完成
break;
}
}
};
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case HANDLER_BUFFER_START:
showLoading();
break;
case HANDLER_BUFFER_END:
hideLoading();
break;
case HANDLER_SURFACE_SIZE:
changeSurfaceSize();
break;
}
}
};
private void showLoading() {
mLoadingView.setVisibility(View.VISIBLE);
}
private void hideLoading() {
mLoadingView.setVisibility(View.GONE);
}
private void changeSurfaceSize() {
// get screen size
int dw = getWindowManager().getDefaultDisplay().getWidth();
int dh = getWindowManager().getDefaultDisplay().getHeight();
// calculate aspect ratio
double ar = (double) mVideoWidth / (double) mVideoHeight;
// calculate display aspect ratio
double dar = (double) dw / (double) dh;
switch (mCurrentSize) {
case SURFACE_BEST_FIT:
if (dar < ar)
dh = (int) (dw / ar);
else
dw = (int) (dh * ar);
break;
case SURFACE_FIT_HORIZONTAL:
dh = (int) (dw / ar);
break;
case SURFACE_FIT_VERTICAL:
dw = (int) (dh * ar);
break;
case SURFACE_FILL:
break;
case SURFACE_16_9:
ar = 16.0 / 9.0;
if (dar < ar)
dh = (int) (dw / ar);
else
dw = (int) (dh * ar);
break;
case SURFACE_4_3:
ar = 4.0 / 3.0;
if (dar < ar)
dh = (int) (dw / ar);
else
dw = (int) (dh * ar);
break;
case SURFACE_ORIGINAL:
dh = mVideoHeight;
dw = mVideoWidth;
break;
}
mSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);
ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
lp.width = dw;
lp.height = dh;
mSurfaceView.setLayoutParams(lp);
mSurfaceView.invalidate();
}
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/AudioOutput.java
================================================
/*****************************************************************************
* Aout.java
*****************************************************************************
* Copyright © 2011-2012 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 android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;
public class AudioOutput {
/**
* Java side of the audio output module for Android.
* Uses an AudioTrack to play decoded audio buffers.
*
* TODO Use MODE_STATIC instead of MODE_STREAM with a MemoryFile (ashmem)
*/
public AudioOutput() {
}
private AudioTrack mAudioTrack;
private static final String TAG = "LibVLC/aout";
public void init(int sampleRateInHz, int channels, int samples) {
Log.d(TAG, sampleRateInHz + ", " + channels + ", " + samples + "=>" + channels * samples);
int minBufferSize = AudioTrack.getMinBufferSize(sampleRateInHz,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRateInHz,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
Math.max(minBufferSize, channels * samples * 2),
AudioTrack.MODE_STREAM);
}
public void release() {
if (mAudioTrack != null) {
mAudioTrack.release();
}
mAudioTrack = null;
}
public void playBuffer(byte[] audioData, int bufferSize) {
if (mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED)
return;
if (mAudioTrack.write(audioData, 0, bufferSize) != bufferSize) {
Log.w(TAG, "Could not write all the samples to the audio device");
}
mAudioTrack.play();
}
public void pause() {
mAudioTrack.pause();
}
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/EventHandler.java
================================================
/*****************************************************************************
* EventHandler.java
*****************************************************************************
* Copyright © 2011-2014 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 android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import java.util.ArrayList;
public class EventHandler {
/*
* Be sure to subscribe to events you need in the JNI too.
*/
//public static final int MediaMetaChanged = 0;
//public static final int MediaSubItemAdded = 1;
//public static final int MediaDurationChanged = 2;
public static final int MediaParsedChanged = 3;
//public static final int MediaFreed = 4;
//public static final int MediaStateChanged = 5;
//public static final int MediaPlayerMediaChanged = 0x100;
//public static final int MediaPlayerNothingSpecial = 0x101;
//public static final int MediaPlayerOpening = 0x102;
public static final int MediaPlayerBuffering = 0x103;
public static final int MediaPlayerPlaying = 0x104;
public static final int MediaPlayerPaused = 0x105;
public static final int MediaPlayerStopped = 0x106;
//public static final int MediaPlayerForward = 0x107;
//public static final int MediaPlayerBackward = 0x108;
public static final int MediaPlayerEndReached = 0x109;
public static final int MediaPlayerEncounteredError = 0x10a;
public static final int MediaPlayerTimeChanged = 0x10b;
public static final int MediaPlayerPositionChanged = 0x10c;
//public static final int MediaPlayerSeekableChanged = 0x10d;
//public static final int MediaPlayerPausableChanged = 0x10e;
//public static final int MediaPlayerTitleChanged = 0x10f;
//public static final int MediaPlayerSnapshotTaken = 0x110;
public static final int MediaPlayerLengthChanged = 0x111;
public static final int MediaPlayerVout = 0x112;
//public static final int MediaListItemAdded = 0x200;
//public static final int MediaListWillAddItem = 0x201;
//public static final int MediaListItemDeleted = 0x202;
//public static final int MediaListWillDeleteItem = 0x203;
//public static final int MediaListViewItemAdded = 0x300;
//public static final int MediaListViewWillAddItem = 0x301;
//public static final int MediaListViewItemDeleted = 0x302;
//public static final int MediaListViewWillDeleteItem = 0x303;
//public static final int MediaListPlayerPlayed = 0x400;
//public static final int MediaListPlayerNextItemSet = 0x401;
//public static final int MediaListPlayerStopped = 0x402;
//public static final int MediaDiscovererStarted = 0x500;
//public static final int MediaDiscovererEnded = 0x501;
//public static final int VlmMediaAdded = 0x600;
//public static final int VlmMediaRemoved = 0x601;
//public static final int VlmMediaChanged = 0x602;
//public static final int VlmMediaInstanceStarted = 0x603;
//public static final int VlmMediaInstanceStopped = 0x604;
//public static final int VlmMediaInstanceStatusInit = 0x605;
//public static final int VlmMediaInstanceStatusOpening = 0x606;
//public static final int VlmMediaInstanceStatusPlaying = 0x607;
//public static final int VlmMediaInstanceStatusPause = 0x608;
//public static final int VlmMediaInstanceStatusEnd = 0x609;
//public static final int VlmMediaInstanceStatusError = 0x60a;
public static final int CustomMediaListExpanding = 0x2000;
public static final int CustomMediaListExpandingEnd = 0x2001;
public static final int CustomMediaListItemAdded = 0x2002;
public static final int CustomMediaListItemDeleted = 0x2003;
public static final int CustomMediaListItemMoved = 0x2004;
public static final int HardwareAccelerationError = 0x3000;
private ArrayList mEventHandler;
private static EventHandler mInstance;
EventHandler() {
mEventHandler = new ArrayList();
}
public static EventHandler getInstance() {
if (mInstance == null) {
mInstance = new EventHandler();
}
return mInstance;
}
public void addHandler(Handler handler) {
if (!mEventHandler.contains(handler))
mEventHandler.add(handler);
}
public void removeHandler(Handler handler) {
mEventHandler.remove(handler);
}
/** This method is called by a native thread **/
public void callback(int event, Bundle b) {
b.putInt("event", event);
for (int i = 0; i < mEventHandler.size(); i++) {
Message msg = Message.obtain();
msg.setData(b);
mEventHandler.get(i).sendMessage(msg);
}
}
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/IVideoPlayer.java
================================================
/*****************************************************************************
* IVideoPlayer.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;
public interface IVideoPlayer {
/**
* This method is called by native vout to request a surface resize when frame size doesn't match surface size.
* @param width Frame width
* @param height Frame height
* @param visible_width Visible frame width
* @param visible_height Visible frame height
* @param sar_num Surface aspect ratio numerator
* @param sar_den Surface aspect ratio denominator
*/
void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/LibVLC.java
================================================
/*****************************************************************************
* 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 android.content.Context;
import android.os.Build;
import android.util.Log;
import android.view.Surface;
import java.io.File;
import java.util.ArrayList;
import java.util.Map;
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;
public static final int HW_ACCELERATION_AUTOMATIC = -1;
public static final int HW_ACCELERATION_DISABLED = 0;
public static final int HW_ACCELERATION_DECODING = 1;
public static final int HW_ACCELERATION_FULL = 2;
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 AudioOutput mAout;
/** Keep screen bright */
//private WakeLock mWakeLock;
/** Settings */
private int hardwareAcceleration = HW_ACCELERATION_AUTOMATIC;
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;
/** Path of application-specific cache */
private String mCachePath = "";
/** Native crash handler */
private OnNativeCrashListener mOnNativeCrashListener;
/** 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();
public native void eventVideoPlayerActivityCreated(boolean created);
/* 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 <= Build.VERSION_CODES.HONEYCOMB_MR2)
System.loadLibrary("iomx-hc");
else
System.loadLibrary("iomx-ics");
} catch (Throwable t) {
// No need to warn if it isn't found, when we intentionally don't build these except for debug
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
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 org.videolan.libvlc.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 AudioOutput();
}
/**
* Destructor:
* It is bad practice to rely on them, so please don't forget to call
* destroy() before exiting.
*/
@Override
protected 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 = HW_ACCELERATION_FULL;
else
this.hardwareAcceleration = HW_ACCELERATION_DISABLED;
}
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.isICSOrLater() ? 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.frequency >= 1200 && m.processors > 2)
ret = 1;
else if(m.bogoMIPS >= 1200 && m.processors > 2) {
ret = 1;
Log.d(TAG, "Used bogoMIPS due to lack of frequency info");
} 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 org.videolan.libvlc.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();
}
File cacheDir = context.getCacheDir();
mCachePath = (cacheDir != null) ? cacheDir.getAbsolutePath() : null;
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();
/**
* Get player state.
*/
public native int getPlayerState();
/**
* 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 getAudioTrackDescription();
public native Map getStats();
public native int getAudioTrack();
public native int setAudioTrack(int index);
public native int getVideoTracksCount();
public native int addSubtitleTrack(String path);
public native Map getSpuTrackDescription();
public native int getSpuTrack();
public native int setSpuTrack(int index);
public native int getSpuTracksCount();
public static native String nativeToURI(String path);
public native static void sendMouseEvent( int action, int button, int x, int y);
/**
* 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 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);
public static interface OnNativeCrashListener {
public void onNativeCrash();
}
public void setOnNativeCrashListener(OnNativeCrashListener l) {
mOnNativeCrashListener = l;
}
private void onNativeCrash() {
if (mOnNativeCrashListener != null)
mOnNativeCrashListener.onNativeCrash();
}
public String getCachePath() {
return mCachePath;
}
public native int getTitle();
public native void setTitle(int title);
public native int getChapterCountForTitle(int title);
public native int getTitleCount();
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/LibVlcException.java
================================================
/*****************************************************************************
* LibVlcException.java
*****************************************************************************
* Copyright © 2011-2012 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.
*****************************************************************************/
/**
* LibVlcException: exceptions thrown by the native LibVLC interface
*/
package org.videolan.libvlc;
/**
* @author jpeg
*
*/
public class LibVlcException extends Exception {
private static final long serialVersionUID = -1909522348226924189L;
/**
* Create an empty error
*/
public LibVlcException() {
super();
}
/**
* @param detailMessage
*/
public LibVlcException(String detailMessage) {
super(detailMessage);
}
/**
* @param throwable
*/
public LibVlcException(Throwable throwable) {
super(throwable);
}
/**
* @param detailMessage
* @param throwable
*/
public LibVlcException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/LibVlcUtil.java
================================================
/*****************************************************************************
* LibVlcUtil.java
*****************************************************************************
* Copyright © 2011-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.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Locale;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
public class LibVlcUtil {
public final static String TAG = "VLC/LibVLC/Util";
public static boolean isFroyoOrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
}
public static boolean isGingerbreadOrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
}
public static boolean isHoneycombOrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
}
public static boolean isICSOrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
}
public static boolean isJellyBeanOrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
}
public static boolean isJellyBeanMR1OrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
}
public static boolean isJellyBeanMR2OrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
}
public static boolean isKitKatOrLater()
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
}
private static String errorMsg = null;
private static boolean isCompatible = false;
public static String getErrorMsg() {
return errorMsg;
}
public static File URItoFile(String URI) {
if(URI == null) return null;
return new File(Uri.decode(URI).replace("file://",""));
}
public static String URItoFileName(String URI) {
if(URI == null) return null;
return URItoFile(URI).getName();
}
public static boolean hasCompatibleCPU(Context context)
{
// If already checked return cached result
if(errorMsg != null || isCompatible) return isCompatible;
ElfData elf = readLib(context.getApplicationInfo().dataDir + "/lib/libvlcjni.so");
if(elf == null) {
Log.e(TAG, "WARNING: Unable to read libvlcjni.so; cannot check device ABI!");
Log.e(TAG, "WARNING: Cannot guarantee correct ABI for this build (may crash)!");
return true;
}
String CPU_ABI = Build.CPU_ABI;
String CPU_ABI2 = "none";
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { // CPU_ABI2 since 2.2
try {
CPU_ABI2 = (String)Build.class.getDeclaredField("CPU_ABI2").get(null);
} catch (Exception e) { }
}
Log.i(TAG, "machine = " + (elf.e_machine == EM_ARM ? "arm" : elf.e_machine == EM_386 ? "x86" : "mips"));
Log.i(TAG, "arch = " + elf.att_arch);
Log.i(TAG, "fpu = " + elf.att_fpu);
boolean hasNeon = false, hasFpu = false, hasArmV6 = false,
hasArmV7 = false, hasMips = false, hasX86 = false;
float bogoMIPS = -1;
int processors = 0;
if(CPU_ABI.equals("x86") ||
CPU_ABI2.equals("x86")) {
hasX86 = true;
} else if(CPU_ABI.equals("armeabi-v7a") ||
CPU_ABI2.equals("armeabi-v7a")) {
hasArmV7 = true;
hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */
} else if(CPU_ABI.equals("armeabi") ||
CPU_ABI2.equals("armeabi")) {
hasArmV6 = true;
}
try {
FileReader fileReader = new FileReader("/proc/cpuinfo");
BufferedReader br = new BufferedReader(fileReader);
String line;
while((line = br.readLine()) != null) {
if(!hasArmV7 && line.contains("ARMv7")) {
hasArmV7 = true;
hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */
}
if(!hasArmV7 && !hasArmV6 && line.contains("ARMv6"))
hasArmV6 = true;
// "clflush size" is a x86-specific cpuinfo tag.
// (see kernel sources arch/x86/kernel/cpu/proc.c)
if(line.contains("clflush size"))
hasX86 = true;
if(line.contains("GenuineIntel"))
hasX86 = true;
// "microsecond timers" is specific to MIPS.
// see arch/mips/kernel/proc.c
if(line.contains("microsecond timers"))
hasMips = true;
if(!hasNeon && line.contains("neon"))
hasNeon = true;
if(!hasFpu && line.contains("vfp"))
hasFpu = true;
if(line.startsWith("processor"))
processors++;
if(bogoMIPS < 0 && line.toLowerCase(Locale.ENGLISH).contains("bogomips")) {
String[] bogo_parts = line.split(":");
try {
bogoMIPS = Float.parseFloat(bogo_parts[1].trim());
} catch(NumberFormatException e) {
bogoMIPS = -1; // invalid bogomips
}
}
}
fileReader.close();
} catch(IOException ex){
ex.printStackTrace();
errorMsg = "IOException whilst reading cpuinfo flags";
isCompatible = false;
return false;
}
if(processors == 0)
processors = 1; // possibly borked cpuinfo?
// Enforce proper architecture to prevent problems
if(elf.e_machine == EM_386 && !hasX86) {
errorMsg = "x86 build on non-x86 device";
isCompatible = false;
return false;
} else if(elf.e_machine == EM_ARM && hasX86) {
errorMsg = "ARM build on x86 device";
isCompatible = false;
return false;
}
if(elf.e_machine == EM_MIPS && !hasMips) {
errorMsg = "MIPS build on non-MIPS device";
isCompatible = false;
return false;
} else if(elf.e_machine == EM_ARM && hasMips) {
errorMsg = "ARM build on MIPS device";
isCompatible = false;
return false;
}
if(elf.e_machine == EM_ARM && elf.att_arch.startsWith("v7") && !hasArmV7) {
errorMsg = "ARMv7 build on non-ARMv7 device";
isCompatible = false;
return false;
}
if(elf.e_machine == EM_ARM) {
if(elf.att_arch.startsWith("v6") && !hasArmV6) {
errorMsg = "ARMv6 build on non-ARMv6 device";
isCompatible = false;
return false;
} else if(elf.att_fpu && !hasFpu) {
errorMsg = "FPU-enabled build on non-FPU device";
isCompatible = false;
return false;
}
}
float frequency = -1;
try {
FileReader fileReader = new FileReader("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq");
BufferedReader br = new BufferedReader(fileReader);
String line = "";
try {
line = br.readLine();
frequency = Float.parseFloat(line) / 1000.f; /* Convert to MHz */
} catch(NumberFormatException e) {
Log.w(TAG, "Could not parse maximum CPU frequency!");
Log.w(TAG, "Failed to parse: " + line);
}
fileReader.close();
} catch(IOException ex) {
Log.w(TAG, "Could not find maximum CPU frequency!");
}
errorMsg = null;
isCompatible = true;
// Store into MachineSpecs
machineSpecs = new MachineSpecs();
machineSpecs.hasArmV6 = hasArmV6;
machineSpecs.hasArmV7 = hasArmV7;
machineSpecs.hasFpu = hasFpu;
machineSpecs.hasMips = hasMips;
machineSpecs.hasNeon = hasNeon;
machineSpecs.hasX86 = hasX86;
machineSpecs.bogoMIPS = bogoMIPS;
machineSpecs.processors = processors;
machineSpecs.frequency = frequency;
return true;
}
public static MachineSpecs getMachineSpecs() {
return machineSpecs;
}
private static MachineSpecs machineSpecs = null;
public static class MachineSpecs {
public boolean hasNeon;
public boolean hasFpu;
public boolean hasArmV6;
public boolean hasArmV7;
public boolean hasMips;
public boolean hasX86;
public float bogoMIPS;
public int processors;
public float frequency; /* in MHz */
}
private static final int EM_386 = 3;
private static final int EM_MIPS = 8;
private static final int EM_ARM = 40;
private static final int ELF_HEADER_SIZE = 52;
private static final int SECTION_HEADER_SIZE = 40;
private static final int SHT_ARM_ATTRIBUTES = 0x70000003;
private static class ElfData {
ByteOrder order;
int e_machine;
int e_shoff;
int e_shnum;
int sh_offset;
int sh_size;
String att_arch;
boolean att_fpu;
}
/** '*' prefix means it's unsupported */
private static String[] CPU_archs = {"*Pre-v4", "*v4", "*v4T",
"v5T", "v5TE", "v5TEJ",
"v6", "v6KZ", "v6T2", "v6K", "v7",
"*v6-M", "*v6S-M", "*v7E-M", "*v8"};
private static ElfData readLib(String path) {
File file = new File(path);
if (!file.exists() || !file.canRead())
return null;
RandomAccessFile in = null;
try {
in = new RandomAccessFile(file, "r");
ElfData elf = new ElfData();
if (!readHeader(in, elf))
return null;
switch (elf.e_machine) {
case EM_386:
case EM_MIPS:
return elf;
case EM_ARM:
in.close();
in = new RandomAccessFile(file, "r");
if (!readSection(in, elf))
return null;
in.close();
in = new RandomAccessFile(file, "r");
if (!readArmAttributes(in, elf))
return null;
break;
default:
return null;
}
return elf;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
return null;
}
private static boolean readHeader(RandomAccessFile in, ElfData elf) throws IOException {
// http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html
byte[] bytes = new byte[ELF_HEADER_SIZE];
in.readFully(bytes);
if (bytes[0] != 127 ||
bytes[1] != 'E' ||
bytes[2] != 'L' ||
bytes[3] != 'F' ||
bytes[4] != 1) { // ELFCLASS32, Only 32bit header is supported
return false;
}
elf.order = bytes[5] == 1
? ByteOrder.LITTLE_ENDIAN // ELFDATA2LSB
: ByteOrder.BIG_ENDIAN; // ELFDATA2MSB
// wrap bytes in a ByteBuffer to force endianess
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.order(elf.order);
elf.e_machine = buffer.getShort(18); /* Architecture */
elf.e_shoff = buffer.getInt(32); /* Section header table file offset */
elf.e_shnum = buffer.getShort(48); /* Section header table entry count */
return true;
}
private static boolean readSection(RandomAccessFile in, ElfData elf) throws IOException {
byte[] bytes = new byte[SECTION_HEADER_SIZE];
in.seek(elf.e_shoff);
for (int i = 0; i < elf.e_shnum; ++i) {
in.readFully(bytes);
// wrap bytes in a ByteBuffer to force endianess
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.order(elf.order);
int sh_type = buffer.getInt(4); /* Section type */
if (sh_type != SHT_ARM_ATTRIBUTES)
continue;
elf.sh_offset = buffer.getInt(16); /* Section file offset */
elf.sh_size = buffer.getInt(20); /* Section size in bytes */
return true;
}
return false;
}
private static boolean readArmAttributes(RandomAccessFile in, ElfData elf) throws IOException {
byte[] bytes = new byte[elf.sh_size];
in.seek(elf.sh_offset);
in.readFully(bytes);
// wrap bytes in a ByteBuffer to force endianess
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.order(elf.order);
//http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf
//http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf
if (buffer.get() != 'A') // format-version
return false;
// sub-sections loop
while (buffer.remaining() > 0) {
int start_section = buffer.position();
int length = buffer.getInt();
String vendor = getString(buffer);
if (vendor.equals("aeabi")) {
// tags loop
while (buffer.position() < start_section + length) {
int start = buffer.position();
int tag = buffer.get();
int size = buffer.getInt();
// skip if not Tag_File, we don't care about others
if (tag != 1) {
buffer.position(start + size);
continue;
}
// attributes loop
while (buffer.position() < start + size) {
tag = getUleb128(buffer);
if (tag == 6) { // CPU_arch
int arch = getUleb128(buffer);
elf.att_arch = CPU_archs[arch];
}
else if (tag == 27) { // ABI_HardFP_use
getUleb128(buffer);
elf.att_fpu = true;
}
else {
// string for 4=CPU_raw_name / 5=CPU_name / 32=compatibility
// string for >32 && odd tags
// uleb128 for other
tag %= 128;
if (tag == 4 || tag == 5 || tag == 32 || (tag > 32 && (tag & 1) != 0))
getString(buffer);
else
getUleb128(buffer);
}
}
}
break;
}
}
return true;
}
private static String getString(ByteBuffer buffer) {
StringBuilder sb = new StringBuilder(buffer.limit());
while (buffer.remaining() > 0) {
char c = (char) buffer.get();
if (c == 0)
break;
sb.append(c);
}
return sb.toString();
}
private static int getUleb128(ByteBuffer buffer) {
int ret = 0;
int c;
do {
ret <<= 7;
c = buffer.get();
ret |= c & 0x7f;
} while((c & 0x80) > 0);
return ret;
}
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/Media.java
================================================
/*****************************************************************************
* Media.java
*****************************************************************************
* Copyright © 2011-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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Locale;
import android.graphics.Bitmap;
import android.util.Log;
public class Media implements Comparable {
public final static String TAG = "VLC/LibVLC/Media";
public final static HashSet VIDEO_EXTENSIONS;
public final static HashSet AUDIO_EXTENSIONS;
public final static String EXTENSIONS_REGEX;
public final static HashSet FOLDER_BLACKLIST;
static {
String[] video_extensions = {
".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".avi", ".divx", ".drc", ".dv",
".f4v", ".flv", ".gvi", ".gxf", ".ismv", ".iso", ".m1v", ".m2v", ".m2t", ".m2ts",
".m4v", ".mkv", ".mov", ".mp2", ".mp2v", ".mp4", ".mp4v", ".mpe", ".mpeg",
".mpeg1", ".mpeg2", ".mpeg4", ".mpg", ".mpv2", ".mts", ".mtv", ".mxf", ".mxg",
".nsv", ".nut", ".nuv", ".ogm", ".ogv", ".ogx", ".ps", ".rec", ".rm", ".rmvb",
".tod", ".ts", ".tts", ".vob", ".vro", ".webm", ".wm", ".wmv", ".wtv", ".xesc" };
String[] audio_extensions = {
".3ga", ".a52", ".aac", ".ac3", ".adt", ".adts", ".aif", ".aifc", ".aiff", ".amr",
".aob", ".ape", ".awb", ".caf", ".dts", ".flac", ".it", ".m4a", ".m4b", ".m4p",
".mid", ".mka", ".mlp", ".mod", ".mpa", ".mp1", ".mp2", ".mp3", ".mpc", ".mpga",
".oga", ".ogg", ".oma", ".opus", ".ra", ".ram", ".rmi", ".s3m", ".spx", ".tta",
".voc", ".vqf", ".w64", ".wav", ".wma", ".wv", ".xa", ".xm" };
String[] folder_blacklist = {
"/alarms",
"/notifications",
"/ringtones",
"/media/alarms",
"/media/notifications",
"/media/ringtones",
"/media/audio/alarms",
"/media/audio/notifications",
"/media/audio/ringtones",
"/Android/data/" };
VIDEO_EXTENSIONS = new HashSet();
for (String item : video_extensions)
VIDEO_EXTENSIONS.add(item);
AUDIO_EXTENSIONS = new HashSet();
for (String item : audio_extensions)
AUDIO_EXTENSIONS.add(item);
StringBuilder sb = new StringBuilder(115);
sb.append(".+(\\.)((?i)(");
sb.append(video_extensions[0].substring(1));
for(int i = 1; i < video_extensions.length; i++) {
sb.append('|');
sb.append(video_extensions[i].substring(1));
}
for(int i = 0; i < audio_extensions.length; i++) {
sb.append('|');
sb.append(audio_extensions[i].substring(1));
}
sb.append("))");
EXTENSIONS_REGEX = sb.toString();
FOLDER_BLACKLIST = new HashSet();
for (String item : folder_blacklist)
FOLDER_BLACKLIST.add(android.os.Environment.getExternalStorageDirectory().getPath() + item);
}
public final static int TYPE_ALL = -1;
public final static int TYPE_VIDEO = 0;
public final static int TYPE_AUDIO = 1;
public final static int TYPE_GROUP = 2;
/** Metadata from libvlc_media */
protected String mTitle;
private String mArtist;
private String mGenre;
private String mCopyright;
private String mAlbum;
private String mTrackNumber;
private String mDescription;
private String mRating;
private String mDate;
private String mSettings;
private String mNowPlaying;
private String mPublisher;
private String mEncodedBy;
private String mTrackID;
private String mArtworkURL;
private final String mLocation;
private String mFilename;
private long mTime = 0;
private int mAudioTrack = -1;
private int mSpuTrack = -2;
private long mLength = 0;
private int mType;
private int mWidth = 0;
private int mHeight = 0;
private Bitmap mPicture;
private boolean mIsPictureParsed;
/**
* Create a new Media
* @param libVLC A pointer to the libVLC instance. Should not be NULL
* @param URI The URI of the media.
*/
public Media(LibVLC libVLC, String URI) {
if(libVLC == null)
throw new NullPointerException("libVLC was null");
mLocation = URI;
mType = TYPE_ALL;
TrackInfo[] tracks = libVLC.readTracksInfo(mLocation);
extractTrackInfo(tracks);
}
private void extractTrackInfo(TrackInfo[] tracks) {
if (tracks == null)
return;
for (TrackInfo track : tracks) {
if (track.Type == TrackInfo.TYPE_VIDEO) {
mType = TYPE_VIDEO;
mWidth = track.Width;
mHeight = track.Height;
} else if (mType == TYPE_ALL && track.Type == TrackInfo.TYPE_AUDIO){
mType = TYPE_AUDIO;
} else if (track.Type == TrackInfo.TYPE_META) {
mLength = track.Length;
mTitle = track.Title;
mArtist = getValueWrapper(track.Artist, UnknownStringType.Artist);
mAlbum = getValueWrapper(track.Album, UnknownStringType.Album);
mGenre = getValueWrapper(track.Genre, UnknownStringType.Genre);
mArtworkURL = track.ArtworkURL;
Log.d(TAG, "Title " + mTitle);
Log.d(TAG, "Artist " + mArtist);
Log.d(TAG, "Genre " + mGenre);
Log.d(TAG, "Album " + mAlbum);
}
}
/* No useful ES found */
if (mType == TYPE_ALL) {
int dotIndex = mLocation.lastIndexOf(".");
if (dotIndex != -1) {
String fileExt = mLocation.substring(dotIndex).toLowerCase(Locale.ENGLISH);
if( Media.VIDEO_EXTENSIONS.contains(fileExt) ) {
mType = TYPE_VIDEO;
} else if (Media.AUDIO_EXTENSIONS.contains(fileExt)) {
mType = TYPE_AUDIO;
}
}
}
}
public Media(String location, long time, long length, int type,
Bitmap picture, String title, String artist, String genre, String album,
int width, int height, String artworkURL, int audio, int spu) {
mLocation = location;
mFilename = null;
mTime = time;
mAudioTrack = audio;
mSpuTrack = spu;
mLength = length;
mType = type;
mPicture = picture;
mWidth = width;
mHeight = height;
mTitle = title;
mArtist = getValueWrapper(artist, UnknownStringType.Artist);
mGenre = getValueWrapper(genre, UnknownStringType.Genre);
mAlbum = getValueWrapper(album, UnknownStringType.Album);
mArtworkURL = artworkURL;
}
private enum UnknownStringType { Artist , Genre, Album };
/**
* Uses introspection to read VLC l10n databases, so that we can sever the
* hard-coded dependency gracefully for 3rd party libvlc apps while still
* maintaining good l10n in VLC for Android.
*
* @see org.videolan.vlc.util.Util#getValue(String, int)
*
* @param string The default string
* @param type Alias for R.string.xxx
* @return The default string if not empty or string from introspection
*/
private static String getValueWrapper(String string, UnknownStringType type) {
if(string != null && string.length() > 0) return string;
try {
Class> stringClass = Class.forName("org.videolan.vlc.R$string");
Class> utilClass = Class.forName("org.videolan.vlc.Util");
Integer value;
switch(type) {
case Album:
value = (Integer)stringClass.getField("unknown_album").get(null);
break;
case Genre:
value = (Integer)stringClass.getField("unknown_genre").get(null);
break;
case Artist:
default:
value = (Integer)stringClass.getField("unknown_artist").get(null);
break;
}
Method getValueMethod = utilClass.getDeclaredMethod("getValue", String.class, Integer.TYPE);
// Util.getValue(string, R.string.xxx);
return (String) getValueMethod.invoke(null, string, value);
} catch (ClassNotFoundException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (NoSuchFieldException e) {
} catch (NoSuchMethodException e) {
} catch (InvocationTargetException e) {
}
// VLC for Android translations not available (custom app perhaps)
// Use hardcoded English phrases.
switch(type) {
case Album:
return "Unknown Album";
case Genre:
return "Unknown Genre";
case Artist:
default:
return "Unknown Artist";
}
}
/**
* Compare the filenames to sort items
*/
@Override
public int compareTo(Media another) {
return mTitle.toUpperCase(Locale.getDefault()).compareTo(
another.getTitle().toUpperCase(Locale.getDefault()));
}
public String getLocation() {
return mLocation;
}
public void updateMeta() {
}
public String getFileName() {
if (mFilename == null) {
mFilename = LibVlcUtil.URItoFileName(mLocation);
}
return mFilename;
}
public long getTime() {
return mTime;
}
public void setTime(long time) {
mTime = time;
}
public int getAudioTrack() {
return mAudioTrack;
}
public void setAudioTrack(int track) {
mAudioTrack = track;
}
public int getSpuTrack() {
return mSpuTrack;
}
public void setSpuTrack(int track) {
mSpuTrack = track;
}
public long getLength() {
return mLength;
}
public int getType() {
return mType;
}
public int getWidth() {
return mWidth;
}
public int getHeight() {
return mHeight;
}
/**
* Returns the raw picture object. Likely to be NULL in VLC for Android
* due to lazy-loading.
*
* Use {@link org.videolan.vlc.util.Bitmap#getPictureFromCache(org.videolan.libvlc.Media)} instead.
*
* @return The raw picture or NULL
*/
public Bitmap getPicture() {
return mPicture;
}
/**
* Sets the raw picture object.
*
* In VLC for Android, use {@link org.videolan.vlc.MediaDatabase#setPicture(org.videolan.libvlc.Media, android.graphics.Bitmap)} instead.
*
* @param p
*/
public void setPicture(Bitmap p) {
mPicture = p;
}
public boolean isPictureParsed() {
return mIsPictureParsed;
}
public void setPictureParsed(boolean isParsed) {
mIsPictureParsed = isParsed;
}
public String getTitle() {
if (mTitle != null && mType != TYPE_VIDEO)
return mTitle;
else {
String fileName = getFileName();
if (fileName == null)
return "";
int end = fileName.lastIndexOf(".");
if (end <= 0)
return fileName;
return fileName.substring(0, end);
}
}
public String getSubtitle() {
return mType != TYPE_VIDEO ? mArtist + " - " + mAlbum : "";
}
public String getArtist() {
return mArtist;
}
public String getGenre() {
if(getValueWrapper(null, UnknownStringType.Genre).equals(mGenre))
return mGenre;
else if( mGenre.length() > 1)/* Make genres case insensitive via normalisation */
return Character.toUpperCase(mGenre.charAt(0)) + mGenre.substring(1).toLowerCase(Locale.getDefault());
else
return mGenre;
}
public String getCopyright() {
return mCopyright;
}
public String getAlbum() {
return mAlbum;
}
public String getTrackNumber() {
return mTrackNumber;
}
public String getDescription() {
return mDescription;
}
public String getRating() {
return mRating;
}
public String getDate() {
return mDate;
}
public String getSettings() {
return mSettings;
}
public String getNowPlaying() {
return mNowPlaying;
}
public String getPublisher() {
return mPublisher;
}
public String getEncodedBy() {
return mEncodedBy;
}
public String getTrackID() {
return mTrackID;
}
public String getArtworkURL() {
return mArtworkURL;
}
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/MediaList.java
================================================
/*****************************************************************************
* MediaList.java
*****************************************************************************
* Copyright © 2013 VLC authors and VideoLAN
* Copyright © 2013 Edward Wang
*
* 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 android.os.Bundle;
/**
* Java/JNI wrapper for the libvlc_media_list_t structure.
*/
public class MediaList {
private static final String TAG = "VLC/LibVLC/MediaList";
/* Since the libvlc_media_t is not created until the media plays, we have
* to cache them here. */
private static class MediaHolder {
Media m;
boolean noVideo; // default false
boolean noHardwareAcceleration; // default false
public MediaHolder(Media media) {
m = media; noVideo = false; noHardwareAcceleration = false;
}
public MediaHolder(Media m_, boolean noVideo_, boolean noHardwareAcceleration_) {
m = m_; noVideo = noVideo_; noHardwareAcceleration = noHardwareAcceleration_;
}
}
/* TODO: add locking */
private ArrayList mInternalList;
private LibVLC mLibVLC; // Used to create new objects that require a libvlc instance
private EventHandler mEventHandler;
public MediaList(LibVLC libVLC) {
mEventHandler = new EventHandler(); // used in init() below to fire events at the correct targets
mInternalList = new ArrayList();
mLibVLC = libVLC;
}
/**
* Adds a media URI to the media list.
*
* @param mrl
* The MRL to add. Must be a location and not a path.
* {@link LibVLC#PathToURI(String)} can be used to convert a path
* to a MRL.
*/
public void add(String mrl) {
add(new Media(mLibVLC, mrl));
}
public void add(Media media) {
add(media, false, false);
}
public void add(Media media, boolean noVideo) {
add(media, noVideo, false);
}
public void add(Media media, boolean noVideo, boolean noHardwareAcceleration) {
mInternalList.add(new MediaHolder(media, noVideo, noHardwareAcceleration));
signal_list_event(EventHandler.CustomMediaListItemAdded, mInternalList.size() - 1, media.getLocation());
}
/**
* Clear the media list. (remove all media)
*/
public void clear() {
// Signal to observers of media being deleted.
for(int i = 0; i < mInternalList.size(); i++) {
signal_list_event(EventHandler.CustomMediaListItemDeleted, i, mInternalList.get(i).m.getLocation());
}
mInternalList.clear();
}
private boolean isValid(int position) {
return position >= 0 && position < mInternalList.size();
}
/**
* This function checks the currently playing media for subitems at the given
* position, and if any exist, it will expand them at the same position
* and replace the current media.
*
* @param position The position to expand
* @return -1 if no subitems were found, 0 if subitems were expanded
*/
public int expandMedia(int position) {
ArrayList children = new ArrayList();
int ret = expandMedia(mLibVLC, position, children);
if(ret == 0) {
mEventHandler.callback(EventHandler.CustomMediaListExpanding, new Bundle());
this.remove(position);
for(String mrl : children) {
this.insert(position, mrl);
}
mEventHandler.callback(EventHandler.CustomMediaListExpandingEnd, new Bundle());
}
return ret;
}
private native int expandMedia(LibVLC libvlc_instance, int position, ArrayList children);
public void loadPlaylist(String mrl) {
ArrayList items = new ArrayList();
loadPlaylist(mLibVLC, mrl, items);
this.clear();
for(String item : items) {
this.add(item);
}
}
private native void loadPlaylist(LibVLC libvlc_instance, String mrl, ArrayList items);
public void insert(int position, String mrl) {
insert(position, new Media(mLibVLC, mrl));
}
public void insert(int position, Media media) {
mInternalList.add(position, new MediaHolder(media));
signal_list_event(EventHandler.CustomMediaListItemAdded, position, media.getLocation());
}
/**
* Move a media from one position to another
*
* @param startPosition start position
* @param endPosition end position
* @throws IndexOutOfBoundsException
*/
public void move(int startPosition, int endPosition) {
if (!(isValid(startPosition)
&& endPosition >= 0 && endPosition <= mInternalList.size()))
throw new IndexOutOfBoundsException("Indexes out of range");
MediaHolder toMove = mInternalList.get(startPosition);
mInternalList.remove(startPosition);
if (startPosition >= endPosition)
mInternalList.add(endPosition, toMove);
else
mInternalList.add(endPosition - 1, toMove);
Bundle b = new Bundle();
b.putInt("index_before", startPosition);
b.putInt("index_after", endPosition);
mEventHandler.callback(EventHandler.CustomMediaListItemMoved, b);
}
public void remove(int position) {
if (!isValid(position))
return;
String uri = mInternalList.get(position).m.getLocation();
mInternalList.remove(position);
signal_list_event(EventHandler.CustomMediaListItemDeleted, position, uri);
}
public void remove(String location) {
for (int i = 0; i < mInternalList.size(); ++i) {
String uri = mInternalList.get(i).m.getLocation();
if (uri.equals(location)) {
mInternalList.remove(i);
signal_list_event(EventHandler.CustomMediaListItemDeleted, i, uri);
i--;
}
}
}
public int size() {
return mInternalList.size();
}
public Media getMedia(int position) {
if (!isValid(position))
return null;
return mInternalList.get(position).m;
}
/**
* @param position The index of the media in the list
* @return null if not found
*/
public String getMRL(int position) {
if (!isValid(position))
return null;
return mInternalList.get(position).m.getLocation();
}
public String[] getMediaOptions(int position) {
boolean noHardwareAcceleration = mLibVLC.getHardwareAcceleration() == 0;
boolean noVideo = false;
if (isValid(position))
{
if (!noHardwareAcceleration)
noHardwareAcceleration = mInternalList.get(position).noHardwareAcceleration;
noVideo = mInternalList.get(position).noVideo;
}
ArrayList options = new ArrayList();
if (!noHardwareAcceleration) {
/*
* Set higher caching values if using iomx decoding, since some omx
* decoders have a very high latency, and if the preroll data isn't
* enough to make the decoder output a frame, the playback timing gets
* started too soon, and every decoded frame appears to be too late.
* On Nexus One, the decoder latency seems to be 25 input packets
* for 320x170 H.264, a few packets less on higher resolutions.
* On Nexus S, the decoder latency seems to be about 7 packets.
*/
options.add(":file-caching=1500");
options.add(":network-caching=1500");
options.add(":codec=mediacodec,iomx,all");
}
if (noVideo)
options.add(":no-video");
return options.toArray(new String[options.size()]);
}
public EventHandler getEventHandler() {
return mEventHandler;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("LibVLC Media List: {");
for(int i = 0; i < size(); i++) {
sb.append(((Integer)i).toString());
sb.append(": ");
sb.append(getMRL(i));
sb.append(", ");
}
sb.append("}");
return sb.toString();
}
private void signal_list_event(int event, int position, String uri) {
Bundle b = new Bundle();
b.putString("item_uri", uri);
b.putInt("item_index", position);
mEventHandler.callback(event, b);
}
}
================================================
FILE: app/src/main/java/org/videolan/libvlc/TrackInfo.java
================================================
/*****************************************************************************
* TrackInfo.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;
public class TrackInfo {
public static final int TYPE_UNKNOWN = -1;
public static final int TYPE_AUDIO = 0;
public static final int TYPE_VIDEO = 1;
public static final int TYPE_TEXT = 2;
public static final int TYPE_META = 3;
public int Type;
public int Id;
public String Codec;
public String Language;
public int Bitrate;
/* Video */
public int Height;
public int Width;
public float Framerate;
/* Audio */
public int Channels;
public int Samplerate;
/* MetaData */
public long Length;
public String Title;
public String Artist;
public String Album;
public String Genre;
public String ArtworkURL;
}
================================================
FILE: app/src/main/java/org/videolan/vlc/util/Preferences.java
================================================
/*****************************************************************************
* Preferences.java
*****************************************************************************
* Copyright © 2011-2014 VLC authors and VideoLAN
*
* 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.
*****************************************************************************/
package org.videolan.vlc.util;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import org.json.JSONArray;
import org.json.JSONException;
public class Preferences {
public final static String TAG = "VLC/Util/Preferences";
public static float[] getFloatArray(SharedPreferences pref, String key) {
float[] array = null;
String s = pref.getString(key, null);
if (s != null) {
try {
JSONArray json = new JSONArray(s);
array = new float[json.length()];
for (int i = 0; i < array.length; i++)
array[i] = (float) json.getDouble(i);
} catch (JSONException e) {
e.printStackTrace();
}
}
return array;
}
public static void putFloatArray(Editor editor, String key, float[] array) {
try {
JSONArray json = new JSONArray();
for (float f : array)
json.put(f);
editor.putString("equalizer_values", json.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
================================================
FILE: app/src/main/java/org/videolan/vlc/util/VLCInstance.java
================================================
/*****************************************************************************
* VLCInstance.java
*****************************************************************************
* Copyright © 2011-2014 VLC authors and VideoLAN
*
* 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.
*****************************************************************************/
package org.videolan.vlc.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.nmbb.vlc.VLCApplication;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.LibVlcException;
public class VLCInstance {
public final static String TAG = "VLC/Util/VLCInstance";
/** A set of utility functions for the VLC application */
public static LibVLC getLibVlcInstance() throws LibVlcException {
LibVLC instance = LibVLC.getExistingInstance();
if (instance == null) {
//Thread.setDefaultUncaughtExceptionHandler(new VLCCrashHandler());
instance = LibVLC.getInstance();
final Context context = VLCApplication.getAppContext();
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
VLCInstance.updateLibVlcSettings(pref);
instance.init(context);
instance.setOnNativeCrashListener(new LibVLC.OnNativeCrashListener() {
@Override
public void onNativeCrash() {
// Intent i = new Intent(context, NativeCrashActivity.class);
// i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// i.putExtra("PID", android.os.Process.myPid());
// context.startActivity(i);
// Logger.e("[VLCInstance]onNativeCrash...");
}
});
}
return instance;
}
public static void updateLibVlcSettings(SharedPreferences pref) {
LibVLC instance = LibVLC.getExistingInstance();
if (instance == null)
return;
instance.setSubtitlesEncoding(pref.getString("subtitle_text_encoding", ""));
instance.setTimeStretching(pref.getBoolean("enable_time_stretching_audio", false));
instance.setFrameSkip(pref.getBoolean("enable_frame_skip", false));
instance.setChroma(pref.getString("chroma_format", ""));
instance.setVerboseMode(pref.getBoolean("enable_verbose_mode", true));
if (pref.getBoolean("equalizer_enabled", false))
instance.setEqualizer(Preferences.getFloatArray(pref, "equalizer_values"));
int aout;
try {
aout = Integer.parseInt(pref.getString("aout", "-1"));
}
catch (NumberFormatException nfe) {
aout = -1;
}
int vout;
try {
vout = Integer.parseInt(pref.getString("vout", "-1"));
}
catch (NumberFormatException nfe) {
vout = -1;
}
int deblocking;
try {
deblocking = Integer.parseInt(pref.getString("deblocking", "-1"));
}
catch(NumberFormatException nfe) {
deblocking = -1;
}
int hardwareAcceleration;
try {
hardwareAcceleration = Integer.parseInt(pref.getString("hardware_acceleration", "-1"));
}
catch(NumberFormatException nfe) {
hardwareAcceleration = -1;
}
int networkCaching = pref.getInt("network_caching_value", 0);
if(networkCaching > 60000)
networkCaching = 60000;
else if(networkCaching < 0)
networkCaching = 0;
instance.setAout(aout);
instance.setVout(vout);
instance.setDeblocking(deblocking);
instance.setNetworkCaching(networkCaching);
instance.setHardwareAcceleration(hardwareAcceleration);
}
}
================================================
FILE: app/src/main/res/layout/activity_video_vlc.xml
================================================
================================================
FILE: app/src/main/res/values/dimens.xml
================================================
16dp
16dp
================================================
FILE: app/src/main/res/values/strings.xml
================================================
VLC-Demo
Hello world!
Settings
Loading...
================================================
FILE: app/src/main/res/values/styles.xml
================================================
================================================
FILE: app/src/main/res/values-w820dp/dimens.xml
================================================
64dp
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
================================================
FILE: settings.gradle
================================================
include ':app'