vlc-android 非常的强大,目前我们主要是使用vlc来播送组播UDP TS流。类似地址:udp://@239.1.1.0:2860这样的地址。在此之前发现声音会卡顿,效果不太好。今天发现是底层驱动的问题。
但是在进行vlc stop时候不能进行资源释放,很是奇怪。明天解决这个问题。文章后续会继续整理!!!
---------------------------------------------------------------------------
针对此前遇到vlc stop时候不能进行资源释放,后来是参考了VLC-android的源码,
具体类文件目录是:
类的代码:看一下VLC是如何释放的,这样处理逻辑比较好。
- /*****************************************************************************
- * VideoPlayerActivity.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.gui.video;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.OutputStream;
- import java.io.StreamCorruptedException;
- import java.io.UnsupportedEncodingException;
- import java.lang.reflect.Method;
- import java.net.URLDecoder;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.Locale;
- import java.util.Map;
- import org.videolan.libvlc.EventHandler;
- import org.videolan.libvlc.IVideoPlayer;
- import org.videolan.libvlc.LibVLC;
- import org.videolan.libvlc.LibVlcException;
- import org.videolan.libvlc.LibVlcUtil;
- import org.videolan.libvlc.Media;
- import org.videolan.vlc.MediaDatabase;
- import org.videolan.vlc.R;
- import org.videolan.vlc.VLCApplication;
- import org.videolan.vlc.audio.AudioServiceController;
- import org.videolan.vlc.gui.CommonDialogs;
- import org.videolan.vlc.gui.CommonDialogs.MenuType;
- import org.videolan.vlc.gui.MainActivity;
- import org.videolan.vlc.gui.PreferencesActivity;
- import org.videolan.vlc.util.AndroidDevices;
- import org.videolan.vlc.util.Strings;
- import org.videolan.vlc.util.VLCInstance;
- import org.videolan.vlc.util.WeakHandler;
- import android.annotation.TargetApi;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.KeyguardManager;
- import android.app.Presentation;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.Editor;
- import android.content.pm.ActivityInfo;
- import android.content.res.Configuration;
- import android.database.Cursor;
- import android.graphics.Color;
- import android.graphics.ImageFormat;
- import android.graphics.PixelFormat;
- import android.media.AudioManager;
- import android.media.AudioManager.OnAudioFocusChangeListener;
- import android.media.MediaRouter;
- import android.os.Build;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.preference.PreferenceManager;
- import android.provider.MediaStore;
- import android.provider.Settings.SettingNotFoundException;
- import android.text.format.DateFormat;
- import android.util.DisplayMetrics;
- import android.util.Log;
- import android.view.Display;
- import android.view.MotionEvent;
- import android.view.Surface;
- import android.view.SurfaceHolder;
- import android.view.SurfaceHolder.Callback;
- import android.view.SurfaceView;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.View.OnSystemUiVisibilityChangeListener;
- import android.view.ViewGroup.LayoutParams;
- import android.view.WindowManager;
- import android.view.animation.Animation;
- import android.view.animation.AnimationSet;
- import android.view.animation.AnimationUtils;
- import android.view.animation.DecelerateInterpolator;
- import android.view.animation.RotateAnimation;
- import android.widget.FrameLayout;
- import android.widget.ImageButton;
- import android.widget.ImageView;
- import android.widget.SeekBar;
- import android.widget.SeekBar.OnSeekBarChangeListener;
- import android.widget.TextView;
- public class VideoPlayerActivity extends Activity implements IVideoPlayer {
- public final static String TAG = "VLC/VideoPlayerActivity";
- // Internal intent identifier to distinguish between internal launch and
- // external intent.
- private final static String PLAY_FROM_VIDEOGRID = "org.videolan.vlc.gui.video.PLAY_FROM_VIDEOGRID";
- private SurfaceView mSurface;
- private SurfaceView mSubtitlesSurface;
- private SurfaceHolder mSurfaceHolder;
- private SurfaceHolder mSubtitlesSurfaceHolder;
- private FrameLayout mSurfaceFrame;
- private MediaRouter mMediaRouter;
- private MediaRouter.SimpleCallback mMediaRouterCallback;
- private SecondaryDisplay mPresentation;
- private LibVLC mLibVLC;
- private String mLocation;
- 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 SharedPreferences mSettings;
- /** Overlay */
- private View mOverlayHeader;
- private View mOverlayOption;
- private View mOverlayProgress;
- private View mOverlayBackground;
- private static final int OVERLAY_TIMEOUT = 4000;
- private static final int OVERLAY_INFINITE = 3600000;
- private static final int FADE_OUT = 1;
- private static final int SHOW_PROGRESS = 2;
- private static final int SURFACE_SIZE = 3;
- private static final int AUDIO_SERVICE_CONNECTION_SUCCESS = 5;
- private static final int AUDIO_SERVICE_CONNECTION_FAILED = 6;
- private static final int FADE_OUT_INFO = 4;
- private boolean mDragging;
- private boolean mShowing;
- private int mUiVisibility = -1;
- private SeekBar mSeekbar;
- private TextView mTitle;
- private TextView mSysTime;
- private TextView mBattery;
- private TextView mTime;
- private TextView mLength;
- private TextView mInfo;
- private ImageView mLoading;
- private TextView mLoadingText;
- private ImageButton mPlayPause;
- private ImageButton mBackward;
- private ImageButton mForward;
- private boolean mEnableJumpButtons;
- private boolean mEnableBrightnessGesture;
- private boolean mEnableCloneMode;
- private boolean mDisplayRemainingTime = false;
- private int mScreenOrientation;
- private ImageButton mAudioTrack;
- private ImageButton mSubtitle;
- private ImageButton mLock;
- private ImageButton mSize;
- private ImageButton mMenu;
- private boolean mIsLocked = false;
- private int mLastAudioTrack = -1;
- private int mLastSpuTrack = -2;
- /**
- * For uninterrupted switching between audio and video mode
- */
- private boolean mSwitchingView;
- private boolean mEndReached;
- private boolean mCanSeek;
- // Playlist
- private int savedIndexPosition = -1;
- // size of the video
- private int mVideoHeight;
- private int mVideoWidth;
- private int mVideoVisibleHeight;
- private int mVideoVisibleWidth;
- private int mSarNum;
- private int mSarDen;
- //Volume
- private AudioManager mAudioManager;
- private int mAudioMax;
- private OnAudioFocusChangeListener mAudioFocusListener;
- //Touch Events
- private static final int TOUCH_NONE = 0;
- private static final int TOUCH_VOLUME = 1;
- private static final int TOUCH_BRIGHTNESS = 2;
- private static final int TOUCH_SEEK = 3;
- private int mTouchAction;
- private int mSurfaceYDisplayRange;
- private float mTouchY, mTouchX, mVol;
- // Brightness
- private boolean mIsFirstBrightnessGesture = true;
- // Tracks & Subtitles
- private Map<Integer,String> mAudioTracksList;
- private Map<Integer,String> mSubtitleTracksList;
- /**
- * Used to store a selected subtitle; see onActivityResult.
- * It is possible to have multiple custom subs in one session
- * (just like desktop VLC allows you as well.)
- */
- private final ArrayList<String> mSubtitleSelectedFiles = new ArrayList<String>();
- // Whether fallback from HW acceleration to SW decoding was done.
- private boolean mDisabledHardwareAcceleration = false;
- private int mPreviousHardwareAccelerationMode;
- // Tips
- private View mOverlayTips;
- private static final String PREF_TIPS_SHOWN = "video_player_tips_shown";
- // Navigation handling (DVD, Blu-Ray...)
- private ImageButton mNavMenu;
- private boolean mHasMenu = false;
- private boolean mIsNavMenu = false;
- @Override
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.i(TAG, "onCreate.");
- if (LibVlcUtil.isJellyBeanMR1OrLater()) {
- // Get the media router service (Miracast)
- mMediaRouter = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE);
- mMediaRouterCallback = new MediaRouter.SimpleCallback() {
- @Override
- public void onRoutePresentationDisplayChanged(
- MediaRouter router, MediaRouter.RouteInfo info) {
- Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
- removePresentation();
- }
- };
- Log.d(TAG, "MediaRouter information : " + mMediaRouter .toString());
- }
- mSettings = PreferenceManager.getDefaultSharedPreferences(this);
- /* Services and miscellaneous */
- mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
- mAudioMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
- mEnableCloneMode = mSettings.getBoolean("enable_clone_mode", false);
- createPresentation();
- setContentView(mPresentation == null ? R.layout.player : R.layout.player_remote_control);
- if (LibVlcUtil.isICSOrLater())
- getWindow().getDecorView().findViewById(android.R.id.content).setOnSystemUiVisibilityChangeListener(
- new OnSystemUiVisibilityChangeListener() {
- @Override
- public void onSystemUiVisibilityChange(int visibility) {
- if (visibility == mUiVisibility)
- return;
- setSurfaceSize(mVideoWidth, mVideoHeight, mVideoVisibleWidth, mVideoVisibleHeight, mSarNum, mSarDen);
- if (visibility == View.SYSTEM_UI_FLAG_VISIBLE && !mShowing && !isFinishing()) {
- showOverlay();
- }
- mUiVisibility = visibility;
- }
- }
- );
- /** initialize Views an their Events */
- mOverlayHeader = findViewById(R.id.player_overlay_header);
- mOverlayOption = findViewById(R.id.option_overlay);
- mOverlayProgress = findViewById(R.id.progress_overlay);
- mOverlayBackground = findViewById(R.id.player_overlay_background);
- /* header */
- mTitle = (TextView) findViewById(R.id.player_overlay_title);
- mSysTime = (TextView) findViewById(R.id.player_overlay_systime);
- mBattery = (TextView) findViewById(R.id.player_overlay_battery);
- // Position and remaining time
- mTime = (TextView) findViewById(R.id.player_overlay_time);
- mTime.setOnClickListener(mRemainingTimeListener);
- mLength = (TextView) findViewById(R.id.player_overlay_length);
- mLength.setOnClickListener(mRemainingTimeListener);
- // the info textView is not on the overlay
- mInfo = (TextView) findViewById(R.id.player_overlay_info);
- mEnableBrightnessGesture = mSettings.getBoolean("enable_brightness_gesture", true);
- mScreenOrientation = Integer.valueOf(
- mSettings.getString("screen_orientation_value", "4" /*SCREEN_ORIENTATION_SENSOR*/));
- mEnableJumpButtons = mSettings.getBoolean("enable_jump_buttons", false);
- mPlayPause = (ImageButton) findViewById(R.id.player_overlay_play);
- mPlayPause.setOnClickListener(mPlayPauseListener);
- mBackward = (ImageButton) findViewById(R.id.player_overlay_backward);
- mBackward.setOnClickListener(mBackwardListener);
- mForward = (ImageButton) findViewById(R.id.player_overlay_forward);
- mForward.setOnClickListener(mForwardListener);
- mAudioTrack = (ImageButton) findViewById(R.id.player_overlay_audio);
- mAudioTrack.setVisibility(View.GONE);
- mSubtitle = (ImageButton) findViewById(R.id.player_overlay_subtitle);
- mSubtitle.setVisibility(View.GONE);
- mNavMenu = (ImageButton) findViewById(R.id.player_overlay_navmenu);
- mNavMenu.setVisibility(View.GONE);
- mLock = (ImageButton) findViewById(R.id.lock_overlay_button);
- mLock.setOnClickListener(mLockListener);
- mSize = (ImageButton) findViewById(R.id.player_overlay_size);
- mSize.setOnClickListener(mSizeListener);
- mMenu = (ImageButton) findViewById(R.id.player_overlay_adv_function);
- try {
- mLibVLC = VLCInstance.getLibVlcInstance();
- } catch (LibVlcException e) {
- Log.d(TAG, "LibVLC initialisation failed");
- return;
- }
- mSurface = (SurfaceView) findViewById(R.id.player_surface);
- mSurfaceHolder = mSurface.getHolder();
- mSurfaceFrame = (FrameLayout) findViewById(R.id.player_surface_frame);
- String chroma = mSettings.getString("chroma_format", "");
- if(LibVlcUtil.isGingerbreadOrLater() && chroma.equals("YV12")) {
- mSurfaceHolder.setFormat(ImageFormat.YV12);
- } else if (chroma.equals("RV16")) {
- mSurfaceHolder.setFormat(PixelFormat.RGB_565);
- } else {
- mSurfaceHolder.setFormat(PixelFormat.RGBX_8888);
- }
- mSubtitlesSurface = (SurfaceView) findViewById(R.id.subtitles_surface);
- mSubtitlesSurfaceHolder = mSubtitlesSurface.getHolder();
- mSubtitlesSurfaceHolder.setFormat(PixelFormat.RGBA_8888);
- mSubtitlesSurface.setZOrderMediaOverlay(true);
- if (mPresentation == null) {
- mSurfaceHolder.addCallback(mSurfaceCallback);
- mSubtitlesSurfaceHolder.addCallback(mSubtitlesSurfaceCallback);
- }
- mSeekbar = (SeekBar) findViewById(R.id.player_overlay_seekbar);
- mSeekbar.setOnSeekBarChangeListener(mSeekListener);
- /* Loading view */
- mLoading = (ImageView) findViewById(R.id.player_overlay_loading);
- mLoadingText = (TextView) findViewById(R.id.player_overlay_loading_text);
- startLoadingAnimation();
- mSwitchingView = false;
- mEndReached = false;
- // Clear the resume time, since it is only used for resumes in external
- // videos.
- SharedPreferences.Editor editor = mSettings.edit();
- editor.putLong(PreferencesActivity.VIDEO_RESUME_TIME, -1);
- // Also clear the subs list, because it is supposed to be per session
- // only (like desktop VLC). We don't want the customs subtitle file
- // to persist forever with this video.
- editor.putString(PreferencesActivity.VIDEO_SUBTITLE_FILES, null);
- editor.commit();
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(VLCApplication.SLEEP_INTENT);
- registerReceiver(mReceiver, filter);
- Log.d(TAG,
- "Hardware acceleration mode: "
- + Integer.toString(mLibVLC.getHardwareAcceleration()));
- /* Only show the subtitles surface when using "Full Acceleration" mode */
- if (mLibVLC.getHardwareAcceleration() == LibVLC.HW_ACCELERATION_FULL)
- mSubtitlesSurface.setVisibility(View.VISIBLE);
- // Signal to LibVLC that the videoPlayerActivity was created, thus the
- // SurfaceView is now available for MediaCodec direct rendering.
- mLibVLC.eventVideoPlayerActivityCreated(true);
- //mLibVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_FULL);
- EventHandler em = EventHandler.getInstance();
- em.addHandler(eventHandler);
- this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
- // Extra initialization when no secondary display is detected
- if (mPresentation == null) {
- // Orientation
- // 100 is the value for screen_orientation_start_lock
- setRequestedOrientation(mScreenOrientation != 100
- ? mScreenOrientation
- : getScreenOrientation());
- // Tips
- mOverlayTips = findViewById(R.id.player_overlay_tips);
- if(mSettings.getBoolean(PREF_TIPS_SHOWN, false))
- mOverlayTips.setVisibility(View.GONE);
- else {
- mOverlayTips.bringToFront();
- mOverlayTips.invalidate();
- }
- } else
- setRequestedOrientation(getScreenOrientation());
- updateNavStatus();
- }
- @Override
- protected void onPause() {
- super.onPause();
- Log.i(TAG, "onPause. mSwitchingView="+mSwitchingView);
- if (mMediaRouter != null) {
- // Stop listening for changes to media routes.
- mediaRouterAddCallback(false);
- }
- if(mSwitchingView) {
- Log.d(TAG, "mLocation = \"" + mLocation + "\"");
- AudioServiceController.getInstance().showWithoutParse(savedIndexPosition);
- AudioServiceController.getInstance().unbindAudioService(this);
- return;
- }
- long time = mLibVLC.getTime();
- long length = mLibVLC.getLength();
- //remove saved position if in the last 5 seconds
- if (length - time < 5000)
- time = 0;
- else
- time -= 5000; // go back 5 seconds, to compensate loading time
- /*
- * Pausing here generates errors because the vout is constantly
- * trying to refresh itself every 80ms while the surface is not
- * accessible anymore.
- * To workaround that, we keep the last known position in the playlist
- * in savedIndexPosition to be able to restore it during onResume().
- */
- mLibVLC.stop();
- mSurface.setKeepScreenOn(false);
- SharedPreferences.Editor editor = mSettings.edit();
- // Save position
- if (time >= 0 && mCanSeek) {
- if(MediaDatabase.getInstance().mediaItemExists(mLocation)) {
- MediaDatabase.getInstance().updateMedia(
- mLocation,
- MediaDatabase.mediaColumn.MEDIA_TIME,
- time);
- } else {
- // Video file not in media library, store time just for onResume()
- editor.putLong(PreferencesActivity.VIDEO_RESUME_TIME, time);
- }
- }
- // Save selected subtitles
- String subtitleList_serialized = null;
- if(mSubtitleSelectedFiles.size() > 0) {
- Log.d(TAG, "Saving selected subtitle files");
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try {
- ObjectOutputStream oos = new ObjectOutputStream(bos);
- oos.writeObject(mSubtitleSelectedFiles);
- subtitleList_serialized = bos.toString();
- } catch(IOException e) {}
- }
- editor.putString(PreferencesActivity.VIDEO_SUBTITLE_FILES, subtitleList_serialized);
- editor.commit();
- AudioServiceController.getInstance().unbindAudioService(this);
- }
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- @Override
- protected void onStop() {
- super.onStop();
- Log.i(TAG, "onStop.");
- // Dismiss the presentation when the activity is not visible.
- if (mPresentation != null) {
- Log.i(TAG, "Dismissing presentation because the activity is no longer visible.");
- mPresentation.dismiss();
- mPresentation = null;
- }
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- Log.i(TAG, "onDestroy.");
- unregisterReceiver(mReceiver);
- EventHandler em = EventHandler.getInstance();
- em.removeHandler(eventHandler);
- // MediaCodec opaque direct rendering should not be used anymore since there is no surface to attach.
- mLibVLC.eventVideoPlayerActivityCreated(false);
- // HW acceleration was temporarily disabled because of an error, restore the previous value.
- if (mDisabledHardwareAcceleration)
- mLibVLC.setHardwareAcceleration(mPreviousHardwareAccelerationMode);
- mAudioManager = null;
- }
- @Override
- protected void onResume() {
- super.onResume();
- Log.i(TAG, "onResume.");
- mSwitchingView = false;
- AudioServiceController.getInstance().bindAudioService(this,
- new AudioServiceController.AudioServiceConnectionListener() {
- @Override
- public void onConnectionSuccess() {
- mHandler.sendEmptyMessage(AUDIO_SERVICE_CONNECTION_SUCCESS);
- }
- @Override
- public void onConnectionFailed() {
- mHandler.sendEmptyMessage(AUDIO_SERVICE_CONNECTION_FAILED);
- }
- });
- if (mMediaRouter != null) {
- // Listen for changes to media routes.
- mediaRouterAddCallback(true);
- }
- }
- /**
- * Add or remove MediaRouter callbacks. This is provided for version targeting.
- *
- * @param add true to add, false to remove
- */
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- private void mediaRouterAddCallback(boolean add) {
- if(!LibVlcUtil.isJellyBeanMR1OrLater() || mMediaRouter == null) return;
- if(add)
- mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback);
- else
- mMediaRouter.removeCallback(mMediaRouterCallback);
- }
- private void startPlayback() {
- Log.i(TAG, "startPlayback.");
- loadMedia();
- /*
- * if the activity has been paused by pressing the power button,
- * pressing it again will show the lock screen.
- * But onResume will also be called, even if vlc-android is still in the background.
- * To workaround that, pause playback if the lockscreen is displayed
- */
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mLibVLC != null && mLibVLC.isPlaying()) {
- KeyguardManager km = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
- if (km.inKeyguardRestrictedInputMode())
- mLibVLC.pause();
- }
- }}, 500);
- // Add any selected subtitle file from the file picker
- if(mSubtitleSelectedFiles.size() > 0) {
- for(String file : mSubtitleSelectedFiles) {
- Log.i(TAG, "Adding user-selected subtitle " + file);
- mLibVLC.addSubtitleTrack(file);
- }
- }
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if(data == null) return;
- if(data.getDataString() == null) {
- Log.d(TAG, "Subtitle selection dialog was cancelled");
- }
- if(data.getData() == null) return;
- String subtitlePath = data.getData().getPath();
- if(requestCode == CommonDialogs.INTENT_SPECIFIC) {
- Log.d(TAG, "Specific subtitle file: " + subtitlePath);
- } else if(requestCode == CommonDialogs.INTENT_GENERIC) {
- Log.d(TAG, "Generic subtitle file: " + subtitlePath);
- }
- mSubtitleSelectedFiles.add(subtitlePath);
- }
- public static void start(Context context, String location) {
- start(context, location, null, -1, false, false);
- }
- public static void start(Context context, String location, Boolean fromStart) {
- start(context, location, null, -1, false, fromStart);
- }
- public static void start(Context context, String location, String title, Boolean dontParse) {
- start(context, location, title, -1, dontParse, false);
- }
- public static void start(Context context, String location, String title, int position, Boolean dontParse) {
- start(context, location, title, position, dontParse, false);
- }
- public static void start(Context context, String location, String title, int position, Boolean dontParse, Boolean fromStart) {
- Intent intent = new Intent(context, VideoPlayerActivity.class);
- intent.setAction(VideoPlayerActivity.PLAY_FROM_VIDEOGRID);
- intent.putExtra("itemLocation", location);
- intent.putExtra("itemTitle", title);
- intent.putExtra("dontParse", dontParse);
- intent.putExtra("fromStart", fromStart);
- intent.putExtra("itemPosition", position);
- if (dontParse)
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- context.startActivity(intent);
- }
- private final BroadcastReceiver mReceiver = new BroadcastReceiver()
- {
- @Override
- public void onReceive(Context context, Intent intent)
- {
- String action = intent.getAction();
- if (action.equalsIgnoreCase(Intent.ACTION_BATTERY_CHANGED)) {
- int batteryLevel = intent.getIntExtra("level", 0);
- if (batteryLevel >= 50)
- mBattery.setTextColor(Color.GREEN);
- else if (batteryLevel >= 30)
- mBattery.setTextColor(Color.YELLOW);
- else
- mBattery.setTextColor(Color.RED);
- mBattery.setText(String.format("%d%%", batteryLevel));
- }
- else if (action.equalsIgnoreCase(VLCApplication.SLEEP_INTENT)) {
- finish();
- }
- }
- };
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- showOverlay();
- return true;
- }
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- setSurfaceSize(mVideoWidth, mVideoHeight, mVideoVisibleWidth, mVideoVisibleHeight, mSarNum, mSarDen);
- super.onConfigurationChanged(newConfig);
- }
- @Override
- public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) {
- if (width * height == 0)
- return;
- // store video size
- mVideoHeight = height;
- mVideoWidth = width;
- mVideoVisibleHeight = visible_height;
- mVideoVisibleWidth = visible_width;
- mSarNum = sar_num;
- mSarDen = sar_den;
- Message msg = mHandler.obtainMessage(SURFACE_SIZE);
- mHandler.sendMessage(msg);
- }
- /**
- * Lock screen rotation
- */
- private void lockScreen() {
- if(mScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
- setRequestedOrientation(14 /* SCREEN_ORIENTATION_LOCKED */);
- else
- setRequestedOrientation(getScreenOrientation());
- }
- showInfo(R.string.locked, 1000);
- mLock.setBackgroundResource(R.drawable.ic_locked);
- mTime.setEnabled(false);
- mSeekbar.setEnabled(false);
- mLength.setEnabled(false);
- hideOverlay(true);
- }
- /**
- * Remove screen lock
- */
- private void unlockScreen() {
- if(mScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR)
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
- showInfo(R.string.unlocked, 1000);
- mLock.setBackgroundResource(R.drawable.ic_lock);
- mTime.setEnabled(true);
- mSeekbar.setEnabled(true);
- mLength.setEnabled(true);
- mShowing = false;
- showOverlay();
- }
- /**
- * Show text in the info view for "duration" milliseconds
- * @param text
- * @param duration
- */
- private void showInfo(String text, int duration) {
- mInfo.setVisibility(View.VISIBLE);
- mInfo.setText(text);
- mHandler.removeMessages(FADE_OUT_INFO);
- mHandler.sendEmptyMessageDelayed(FADE_OUT_INFO, duration);
- }
- private void showInfo(int textid, int duration) {
- mInfo.setVisibility(View.VISIBLE);
- mInfo.setText(textid);
- mHandler.removeMessages(FADE_OUT_INFO);
- mHandler.sendEmptyMessageDelayed(FADE_OUT_INFO, duration);
- }
- /**
- * Show text in the info view
- * @param text
- */
- private void showInfo(String text) {
- mInfo.setVisibility(View.VISIBLE);
- mInfo.setText(text);
- mHandler.removeMessages(FADE_OUT_INFO);
- }
- /**
- * hide the info view with "delay" milliseconds delay
- * @param delay
- */
- private void hideInfo(int delay) {
- mHandler.sendEmptyMessageDelayed(FADE_OUT_INFO, delay);
- }
- /**
- * hide the info view
- */
- private void hideInfo() {
- hideInfo(0);
- }
- private void fadeOutInfo() {
- if (mInfo.getVisibility() == View.VISIBLE)
- mInfo.startAnimation(AnimationUtils.loadAnimation(
- VideoPlayerActivity.this, android.R.anim.fade_out));
- mInfo.setVisibility(View.INVISIBLE);
- }
- @TargetApi(Build.VERSION_CODES.FROYO)
- private int changeAudioFocus(boolean acquire) {
- if(!LibVlcUtil.isFroyoOrLater()) // NOP if not supported
- return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
- if (mAudioFocusListener == null) {
- mAudioFocusListener = new OnAudioFocusChangeListener() {
- @Override
- public void onAudioFocusChange(int focusChange) {
- /*
- * Pause playback during alerts and notifications
- */
- switch (focusChange)
- {
- case AudioManager.AUDIOFOCUS_LOSS:
- case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
- case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
- if (mLibVLC.isPlaying())
- mLibVLC.pause();
- break;
- case AudioManager.AUDIOFOCUS_GAIN:
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
- case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
- if (!mLibVLC.isPlaying())
- mLibVLC.play();
- break;
- }
- }
- };
- }
- int result;
- if(acquire) {
- result = mAudioManager.requestAudioFocus(mAudioFocusListener,
- AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
- mAudioManager.setParameters("bgm_state=true");
- }
- else {
- if (mAudioManager != null) {
- result = mAudioManager.abandonAudioFocus(mAudioFocusListener);
- mAudioManager.setParameters("bgm_state=false");
- }
- else
- result = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
- }
- return result;
- }
- /**
- * Handle libvlc asynchronous events
- */
- private final Handler eventHandler = new VideoPlayerEventHandler(this);
- private static class VideoPlayerEventHandler extends WeakHandler<VideoPlayerActivity> {
- public VideoPlayerEventHandler(VideoPlayerActivity owner) {
- super(owner);
- }
- @Override
- public void handleMessage(Message msg) {
- VideoPlayerActivity activity = getOwner();
- if(activity == null) return;
- // Do not handle events if we are leaving the VideoPlayerActivity
- if (activity.mSwitchingView) return;
- switch (msg.getData().getInt("event")) {
- case EventHandler.MediaParsedChanged:
- Log.i(TAG, "MediaParsedChanged");
- activity.updateNavStatus();
- if (!activity.mHasMenu && activity.mLibVLC.getVideoTracksCount() < 1) {
- Log.i(TAG, "No video track, open in audio mode");
- activity.switchToAudioMode();
- }
- break;
- case EventHandler.MediaPlayerPlaying:
- Log.i(TAG, "MediaPlayerPlaying");
- activity.stopLoadingAnimation();
- activity.showOverlay();
- /** FIXME: update the track list when it changes during the
- * playback. (#7540) */
- activity.setESTrackLists(true);
- activity.setESTracks();
- activity.changeAudioFocus(true);
- activity.updateNavStatus();
- break;
- case EventHandler.MediaPlayerPaused:
- Log.i(TAG, "MediaPlayerPaused");
- break;
- case EventHandler.MediaPlayerStopped:
- Log.i(TAG, "MediaPlayerStopped");
- activity.changeAudioFocus(false);
- break;
- case EventHandler.MediaPlayerEndReached:
- Log.i(TAG, "MediaPlayerEndReached");
- activity.changeAudioFocus(false);
- activity.endReached();
- break;
- case EventHandler.MediaPlayerVout:
- activity.updateNavStatus();
- if (!activity.mHasMenu)
- activity.handleVout(msg);
- break;
- case EventHandler.MediaPlayerPositionChanged:
- if (!activity.mCanSeek)
- activity.mCanSeek = true;
- //don't spam the logs
- break;
- case EventHandler.MediaPlayerEncounteredError:
- Log.i(TAG, "MediaPlayerEncounteredError");
- activity.encounteredError();
- break;
- case EventHandler.HardwareAccelerationError:
- Log.i(TAG, "HardwareAccelerationError");
- activity.handleHardwareAccelerationError();
- break;
- case EventHandler.MediaPlayerTimeChanged:
- // avoid useless error logs
- break;
- default:
- Log.e(TAG, String.format("Event not handled (0x%x)", msg.getData().getInt("event")));
- break;
- }
- activity.updateOverlayPausePlay();
- }
- };
- /**
- * Handle resize of the surface and the overlay
- */
- private final Handler mHandler = new VideoPlayerHandler(this);
- private static class VideoPlayerHandler extends WeakHandler<VideoPlayerActivity> {
- public VideoPlayerHandler(VideoPlayerActivity owner) {
- super(owner);
- }
- @Override
- public void handleMessage(Message msg) {
- VideoPlayerActivity activity = getOwner();
- if(activity == null) // WeakReference could be GC'ed early
- return;
- switch (msg.what) {
- case FADE_OUT:
- activity.hideOverlay(false);
- break;
- case SHOW_PROGRESS:
- int pos = activity.setOverlayProgress();
- if (activity.canShowProgress()) {
- msg = obtainMessage(SHOW_PROGRESS);
- sendMessageDelayed(msg, 1000 - (pos % 1000));
- }
- break;
- case SURFACE_SIZE:
- activity.changeSurfaceSize();
- break;
- case FADE_OUT_INFO:
- activity.fadeOutInfo();
- break;
- case AUDIO_SERVICE_CONNECTION_SUCCESS:
- activity.startPlayback();
- break;
- case AUDIO_SERVICE_CONNECTION_FAILED:
- activity.finish();
- break;
- }
- }
- };
- private boolean canShowProgress() {
- return !mDragging && mShowing && mLibVLC.isPlaying();
- }
- private void endReached() {
- if(mLibVLC.getMediaList().expandMedia(savedIndexPosition) == 0) {
- Log.d(TAG, "Found a video playlist, expanding it");
- eventHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- loadMedia();
- }
- }, 1000);
- } else {
- /* Exit player when reaching the end */
- mEndReached = true;
- finish();
- }
- }
- private void encounteredError() {
- /* Encountered Error, exit player with a message */
- AlertDialog dialog = new AlertDialog.Builder(VideoPlayerActivity.this)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- finish();
- }
- })
- .setTitle(R.string.encountered_error_title)
- .setMessage(R.string.encountered_error_message)
- .create();
- dialog.show();
- }
- public void eventHardwareAccelerationError() {
- EventHandler em = EventHandler.getInstance();
- em.callback(EventHandler.HardwareAccelerationError, new Bundle());
- }
- private void handleHardwareAccelerationError() {
- mLibVLC.stop();
- AlertDialog dialog = new AlertDialog.Builder(VideoPlayerActivity.this)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- mDisabledHardwareAcceleration = true;
- mPreviousHardwareAccelerationMode = mLibVLC.getHardwareAcceleration();
- mLibVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_DISABLED);
- mSubtitlesSurface.setVisibility(View.INVISIBLE);
- loadMedia();
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- finish();
- }
- })
- .setTitle(R.string.hardware_acceleration_error_title)
- .setMessage(R.string.hardware_acceleration_error_message)
- .create();
- if(!isFinishing())
- dialog.show();
- }
- private void handleVout(Message msg) {
- if (msg.getData().getInt("data") == 0 && !mEndReached) {
- /* Video track lost, open in audio mode */
- Log.i(TAG, "Video track lost, switching to audio");
- mSwitchingView = true;
- finish();
- }
- }
- private void switchToAudioMode() {
- mSwitchingView = true;
- // Show the MainActivity if it is not in background.
- if (getIntent().getAction() != null
- && getIntent().getAction().equals(Intent.ACTION_VIEW)) {
- Intent i = new Intent(this, MainActivity.class);
- startActivity(i);
- }
- finish();
- }
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- private void changeSurfaceSize() {
- int sw;
- int sh;
- // get screen size
- if (mPresentation == null) {
- sw = getWindow().getDecorView().getWidth();
- sh = getWindow().getDecorView().getHeight();
- } else {
- sw = mPresentation.getWindow().getDecorView().getWidth();
- sh = mPresentation.getWindow().getDecorView().getHeight();
- }
- double dw = sw, dh = sh;
- boolean isPortrait;
- if (mPresentation == null) {
- // getWindow().getDecorView() doesn't always take orientation into account, we have to correct the values
- isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
- } else {
- isPortrait = false;
- }
- if (sw > sh && isPortrait || sw < sh && !isPortrait) {
- dw = sh;
- dh = sw;
- }
- // sanity check
- if (dw * dh == 0 || mVideoWidth * mVideoHeight == 0) {
- Log.e(TAG, "Invalid surface size");
- return;
- }
- // compute the aspect ratio
- double ar, vw;
- if (mSarDen == mSarNum) {
- /* No indication about the density, assuming 1:1 */
- vw = mVideoVisibleWidth;
- ar = (double)mVideoVisibleWidth / (double)mVideoVisibleHeight;
- } else {
- /* Use the specified aspect ratio */
- vw = mVideoVisibleWidth * (double)mSarNum / mSarDen;
- ar = vw / mVideoVisibleHeight;
- }
- // compute the display aspect ratio
- double dar = dw / dh;
- switch (mCurrentSize) {
- case SURFACE_BEST_FIT:
- if (dar < ar)
- dh = dw / ar;
- else
- dw = dh * ar;
- break;
- case SURFACE_FIT_HORIZONTAL:
- dh = dw / ar;
- break;
- case SURFACE_FIT_VERTICAL:
- dw = dh * ar;
- break;
- case SURFACE_FILL:
- break;
- case SURFACE_16_9:
- ar = 16.0 / 9.0;
- if (dar < ar)
- dh = dw / ar;
- else
- dw = dh * ar;
- break;
- case SURFACE_4_3:
- ar = 4.0 / 3.0;
- if (dar < ar)
- dh = dw / ar;
- else
- dw = dh * ar;
- break;
- case SURFACE_ORIGINAL:
- dh = mVideoVisibleHeight;
- dw = vw;
- break;
- }
- SurfaceView surface;
- SurfaceView subtitlesSurface;
- SurfaceHolder surfaceHolder;
- SurfaceHolder subtitlesSurfaceHolder;
- FrameLayout surfaceFrame;
- if (mPresentation == null) {
- surface = mSurface;
- subtitlesSurface = mSubtitlesSurface;
- surfaceHolder = mSurfaceHolder;
- subtitlesSurfaceHolder = mSubtitlesSurfaceHolder;
- surfaceFrame = mSurfaceFrame;
- } else {
- surface = mPresentation.mSurface;
- subtitlesSurface = mPresentation.mSubtitlesSurface;
- surfaceHolder = mPresentation.mSurfaceHolder;
- subtitlesSurfaceHolder = mPresentation.mSubtitlesSurfaceHolder;
- surfaceFrame = mPresentation.mSurfaceFrame;
- }
- // force surface buffer size
- surfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);
- subtitlesSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);
- // set display size
- LayoutParams lp = surface.getLayoutParams();
- lp.width = (int) Math.ceil(dw * mVideoWidth / mVideoVisibleWidth);
- lp.height = (int) Math.ceil(dh * mVideoHeight / mVideoVisibleHeight);
- surface.setLayoutParams(lp);
- subtitlesSurface.setLayoutParams(lp);
- // set frame size (crop if necessary)
- lp = surfaceFrame.getLayoutParams();
- lp.width = (int) Math.floor(dw);
- lp.height = (int) Math.floor(dh);
- surfaceFrame.setLayoutParams(lp);
- surface.invalidate();
- subtitlesSurface.invalidate();
- }
- /**
- * show/hide the overlay
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (mIsLocked) {
- // locked, only handle show/hide & ignore all actions
- if (event.getAction() == MotionEvent.ACTION_UP) {
- if (!mShowing) {
- showOverlay();
- } else {
- hideOverlay(true);
- }
- }
- return false;
- }
- DisplayMetrics screen = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(screen);
- if (mSurfaceYDisplayRange == 0)
- mSurfaceYDisplayRange = Math.min(screen.widthPixels, screen.heightPixels);
- float y_changed = event.getRawY() - mTouchY;
- float x_changed = event.getRawX() - mTouchX;
- // coef is the gradient's move to determine a neutral zone
- float coef = Math.abs (y_changed / x_changed);
- float xgesturesize = ((x_changed / screen.xdpi) * 2.54f);
- /* Offset for Mouse Events */
- int[] offset = new int[2];
- mSurface.getLocationOnScreen(offset);
- int xTouch = Math.round((event.getRawX() - offset[0]) * mVideoWidth / mSurface.getWidth());
- int yTouch = Math.round((event.getRawY() - offset[1]) * mVideoHeight / mSurface.getHeight());
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- // Audio
- mTouchY = event.getRawY();
- mVol = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
- mTouchAction = TOUCH_NONE;
- // Seek
- mTouchX = event.getRawX();
- // Mouse events for the core
- LibVLC.sendMouseEvent(MotionEvent.ACTION_DOWN, 0, xTouch, yTouch);
- break;
- case MotionEvent.ACTION_MOVE:
- // Mouse events for the core
- LibVLC.sendMouseEvent(MotionEvent.ACTION_MOVE, 0, xTouch, yTouch);
- // No volume/brightness action if coef < 2 or a secondary display is connected
- //TODO : Volume action when a secondary display is connected
- if (coef > 2 && mPresentation == null) {
- // Volume (Up or Down - Right side)
- if (!mEnableBrightnessGesture || (int)mTouchX > (screen.widthPixels / 2)){
- doVolumeTouch(y_changed);
- }
- // Brightness (Up or Down - Left side)
- if (mEnableBrightnessGesture && (int)mTouchX < (screen.widthPixels / 2)){
- doBrightnessTouch(y_changed);
- }
- // Extend the overlay for a little while, so that it doesn't
- // disappear on the user if more adjustment is needed. This
- // is because on devices with soft navigation (e.g. Galaxy
- // Nexus), gestures can't be made without activating the UI.
- if(AndroidDevices.hasNavBar())
- showOverlay();
- }
- // Seek (Right or Left move)
- doSeekTouch(coef, xgesturesize, false);
- break;
- case MotionEvent.ACTION_UP:
- // Mouse events for the core
- LibVLC.sendMouseEvent(MotionEvent.ACTION_UP, 0, xTouch, yTouch);
- // Audio or Brightness
- if ( mTouchAction == TOUCH_NONE) {
- if (!mShowing) {
- showOverlay();
- } else {
- hideOverlay(true);
- }
- }
- // Seek
- doSeekTouch(coef, xgesturesize, true);
- break;
- }
- return mTouchAction != TOUCH_NONE;
- }
- private void doSeekTouch(float coef, float gesturesize, boolean seek) {
- // No seek action if coef > 0.5 and gesturesize < 1cm
- if (coef > 0.5 || Math.abs(gesturesize) < 1 || !mCanSeek)
- return;
- if (mTouchAction != TOUCH_NONE && mTouchAction != TOUCH_SEEK)
- return;
- mTouchAction = TOUCH_SEEK;
- // Always show seekbar when searching
- if (!mShowing) showOverlay();
- long length = mLibVLC.getLength();
- long time = mLibVLC.getTime();
- // Size of the jump, 10 minutes max (600000), with a bi-cubic progression, for a 8cm gesture
- int jump = (int) (Math.signum(gesturesize) * ((600000 * Math.pow((gesturesize / 8), 4)) + 3000));
- // Adjust the jump
- if ((jump > 0) && ((time + jump) > length))
- jump = (int) (length - time);
- if ((jump < 0) && ((time + jump) < 0))
- jump = (int) -time;
- //Jump !
- if (seek && length > 0)
- mLibVLC.setTime(time + jump);
- if (length > 0)
- //Show the jump's size
- showInfo(String.format("%s%s (%s)",
- jump >= 0 ? "+" : "",
- Strings.millisToString(jump),
- Strings.millisToString(time + jump)), 1000);
- else
- showInfo(R.string.unseekable_stream, 1000);
- }
- private void doVolumeTouch(float y_changed) {
- if (mTouchAction != TOUCH_NONE && mTouchAction != TOUCH_VOLUME)
- return;
- int delta = -(int) ((y_changed / mSurfaceYDisplayRange) * mAudioMax);
- int vol = (int) Math.min(Math.max(mVol + delta, 0), mAudioMax);
- if (delta != 0) {
- mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, vol, 0);
- mTouchAction = TOUCH_VOLUME;
- showInfo(getString(R.string.volume) + '\u00A0' + Integer.toString(vol),1000);
- }
- }
- private void initBrightnessTouch() {
- float brightnesstemp = 0.01f;
- // Initialize the layoutParams screen brightness
- try {
- brightnesstemp = android.provider.Settings.System.getInt(getContentResolver(),
- android.provider.Settings.System.SCREEN_BRIGHTNESS) / 255.0f;
- } catch (SettingNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- WindowManager.LayoutParams lp = getWindow().getAttributes();
- lp.screenBrightness = brightnesstemp;
- getWindow().setAttributes(lp);
- mIsFirstBrightnessGesture = false;
- }
- private void doBrightnessTouch(float y_changed) {
- if (mTouchAction != TOUCH_NONE && mTouchAction != TOUCH_BRIGHTNESS)
- return;
- if (mIsFirstBrightnessGesture) initBrightnessTouch();
- mTouchAction = TOUCH_BRIGHTNESS;
- // Set delta : 0.07f is arbitrary for now, it possibly will change in the future
- float delta = - y_changed / mSurfaceYDisplayRange * 0.07f;
- // Estimate and adjust Brightness
- WindowManager.LayoutParams lp = getWindow().getAttributes();
- lp.screenBrightness = Math.min(Math.max(lp.screenBrightness + delta, 0.01f), 1);
- // Set Brightness
- getWindow().setAttributes(lp);
- showInfo(getString(R.string.brightness) + '\u00A0' + Math.round(lp.screenBrightness*15),1000);
- }
- /**
- * handle changes of the seekbar (slicer)
- */
- private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- mDragging = true;
- showOverlay(OVERLAY_INFINITE);
- }
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- mDragging = false;
- showOverlay();
- hideInfo();
- }
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (fromUser && mCanSeek) {
- mLibVLC.setTime(progress);
- setOverlayProgress();
- mTime.setText(Strings.millisToString(progress));
- showInfo(Strings.millisToString(progress));
- }
- }
- };
- /**
- *
- */
- private final OnClickListener mAudioTrackListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- final String[] arrList = new String[mAudioTracksList.size()];
- int i = 0;
- int listPosition = 0;
- for(Map.Entry<Integer,String> entry : mAudioTracksList.entrySet()) {
- arrList[i] = entry.getValue();
- // map the track position to the list position
- if(entry.getKey() == mLibVLC.getAudioTrack())
- listPosition = i;
- i++;
- }
- AlertDialog dialog = new AlertDialog.Builder(VideoPlayerActivity.this)
- .setTitle(R.string.track_audio)
- .setSingleChoiceItems(arrList, listPosition, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int listPosition) {
- int trackID = -1;
- // Reverse map search...
- for(Map.Entry<Integer, String> entry : mAudioTracksList.entrySet()) {
- if(arrList[listPosition].equals(entry.getValue())) {
- trackID = entry.getKey();
- break;
- }
- }
- if(trackID < 0) return;
- MediaDatabase.getInstance().updateMedia(
- mLocation,
- MediaDatabase.mediaColumn.MEDIA_AUDIOTRACK,
- trackID);
- mLibVLC.setAudioTrack(trackID);
- dialog.dismiss();
- }
- })
- .create();
- dialog.setCanceledOnTouchOutside(true);
- dialog.setOwnerActivity(VideoPlayerActivity.this);
- dialog.show();
- }
- };
- /**
- *
- */
- private final OnClickListener mSubtitlesListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- final String[] arrList = new String[mSubtitleTracksList.size()];
- int i = 0;
- int listPosition = 0;
- for(Map.Entry<Integer,String> entry : mSubtitleTracksList.entrySet()) {
- arrList[i] = entry.getValue();
- // map the track position to the list position
- if(entry.getKey() == mLibVLC.getSpuTrack())
- listPosition = i;
- i++;
- }
- AlertDialog dialog = new AlertDialog.Builder(VideoPlayerActivity.this)
- .setTitle(R.string.track_text)
- .setSingleChoiceItems(arrList, listPosition, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int listPosition) {
- int trackID = -2;
- // Reverse map search...
- for(Map.Entry<Integer, String> entry : mSubtitleTracksList.entrySet()) {
- if(arrList[listPosition].equals(entry.getValue())) {
- trackID = entry.getKey();
- break;
- }
- }
- if(trackID < -1) return;
- MediaDatabase.getInstance().updateMedia(
- mLocation,
- MediaDatabase.mediaColumn.MEDIA_SPUTRACK,
- trackID);
- mLibVLC.setSpuTrack(trackID);
- dialog.dismiss();
- }
- })
- .create();
- dialog.setCanceledOnTouchOutside(true);
- dialog.setOwnerActivity(VideoPlayerActivity.this);
- dialog.show();
- }
- };
- private final OnClickListener mNavMenuListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- /* Try to return to the menu. */
- /* FIXME: not working correctly in all cases */
- mLibVLC.setTitle(0);
- }
- };
- /**
- *
- */
- private final OnClickListener mPlayPauseListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mLibVLC.isPlaying())
- pause();
- else
- play();
- showOverlay();
- }
- };
- /**
- *
- */
- private final OnClickListener mBackwardListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- seek(-10000);
- }
- };
- /**
- *
- */
- private final OnClickListener mForwardListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- seek(10000);
- }
- };
- public void seek(int delta) {
- // unseekable stream
- if(mLibVLC.getLength() <= 0 || !mCanSeek) return;
- long position = mLibVLC.getTime() + delta;
- if (position < 0) position = 0;
- mLibVLC.setTime(position);
- showOverlay();
- }
- /**
- *
- */
- private final OnClickListener mLockListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mIsLocked) {
- mIsLocked = false;
- unlockScreen();
- } else {
- mIsLocked = true;
- lockScreen();
- }
- }
- };
- /**
- *
- */
- private final OnClickListener mSizeListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mCurrentSize < SURFACE_ORIGINAL) {
- mCurrentSize++;
- } else {
- mCurrentSize = 0;
- }
- changeSurfaceSize();
- switch (mCurrentSize) {
- case SURFACE_BEST_FIT:
- showInfo(R.string.surface_best_fit, 1000);
- break;
- case SURFACE_FIT_HORIZONTAL:
- showInfo(R.string.surface_fit_horizontal, 1000);
- break;
- case SURFACE_FIT_VERTICAL:
- showInfo(R.string.surface_fit_vertical, 1000);
- break;
- case SURFACE_FILL:
- showInfo(R.string.surface_fill, 1000);
- break;
- case SURFACE_16_9:
- showInfo("16:9", 1000);
- break;
- case SURFACE_4_3:
- showInfo("4:3", 1000);
- break;
- case SURFACE_ORIGINAL:
- showInfo(R.string.surface_original, 1000);
- break;
- }
- showOverlay();
- }
- };
- private final OnClickListener mRemainingTimeListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- mDisplayRemainingTime = !mDisplayRemainingTime;
- showOverlay();
- }
- };
- /**
- * attach and disattach surface to the lib
- */
- private final SurfaceHolder.Callback mSurfaceCallback = new Callback() {
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- if(format == PixelFormat.RGBX_8888)
- Log.d(TAG, "Pixel format is RGBX_8888");
- else if(format == PixelFormat.RGB_565)
- Log.d(TAG, "Pixel format is RGB_565");
- else if(format == ImageFormat.YV12)
- Log.d(TAG, "Pixel format is YV12");
- else
- Log.d(TAG, "Pixel format is other/unknown");
- if(mLibVLC != null)
- mLibVLC.attachSurface(holder.getSurface(), VideoPlayerActivity.this);
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- if(mLibVLC != null)
- mLibVLC.detachSurface();
- }
- };
- private final SurfaceHolder.Callback mSubtitlesSurfaceCallback = new Callback() {
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- if(mLibVLC != null)
- mLibVLC.attachSubtitlesSurface(holder.getSurface());
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- if(mLibVLC != null)
- mLibVLC.detachSubtitlesSurface();
- }
- };
- /**
- * show overlay the the default timeout
- */
- private void showOverlay() {
- showOverlay(OVERLAY_TIMEOUT);
- }
- /**
- * show overlay
- */
- private void showOverlay(int timeout) {
- if (mIsNavMenu)
- return;
- mHandler.sendEmptyMessage(SHOW_PROGRESS);
- if (!mShowing) {
- mShowing = true;
- if (!mIsLocked) {
- mOverlayHeader.setVisibility(View.VISIBLE);
- mOverlayOption.setVisibility(View.VISIBLE);
- mPlayPause.setVisibility(View.VISIBLE);
- mMenu.setVisibility(View.VISIBLE);
- dimStatusBar(false);
- }
- mOverlayProgress.setVisibility(View.VISIBLE);
- if (mPresentation != null) mOverlayBackground.setVisibility(View.VISIBLE);
- }
- Message msg = mHandler.obtainMessage(FADE_OUT);
- if (timeout != 0) {
- mHandler.removeMessages(FADE_OUT);
- mHandler.sendMessageDelayed(msg, timeout);
- }
- updateOverlayPausePlay();
- }
- /**
- * hider overlay
- */
- private void hideOverlay(boolean fromUser) {
- if (mShowing) {
- mHandler.removeMessages(SHOW_PROGRESS);
- Log.i(TAG, "remove View!");
- if (mOverlayTips != null) mOverlayTips.setVisibility(View.INVISIBLE);
- if (!fromUser && !mIsLocked) {
- mOverlayHeader.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
- mOverlayOption.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
- mOverlayProgress.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
- mPlayPause.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
- mMenu.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
- }
- if (mPresentation != null) {
- mOverlayBackground.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
- mOverlayBackground.setVisibility(View.INVISIBLE);
- }
- mOverlayHeader.setVisibility(View.INVISIBLE);
- mOverlayOption.setVisibility(View.INVISIBLE);
- mOverlayProgress.setVisibility(View.INVISIBLE);
- mPlayPause.setVisibility(View.INVISIBLE);
- mMenu.setVisibility(View.INVISIBLE);
- mShowing = false;
- dimStatusBar(true);
- }
- }
- /**
- * Dim the status bar and/or navigation icons when needed on Android 3.x.
- * Hide it on Android 4.0 and later
- */
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- private void dimStatusBar(boolean dim) {
- if (!LibVlcUtil.isHoneycombOrLater() || !AndroidDevices.hasNavBar() || mIsNavMenu)
- return;
- int layout = 0;
- if (!AndroidDevices.hasCombBar() && LibVlcUtil.isJellyBeanOrLater())
- layout = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
- int visibility = (dim ? (AndroidDevices.hasCombBar()
- ? View.SYSTEM_UI_FLAG_LOW_PROFILE
- : View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
- : View.SYSTEM_UI_FLAG_VISIBLE) | layout;
- mSurface.setSystemUiVisibility(visibility);
- mSubtitlesSurface.setSystemUiVisibility(visibility);
- }
- private void updateOverlayPausePlay() {
- if (mLibVLC == null)
- return;
- if (mPresentation == null)
- mPlayPause.setBackgroundResource(mLibVLC.isPlaying() ? R.drawable.ic_pause_circle
- : R.drawable.ic_play_circle);
- else
- mPlayPause.setBackgroundResource(mLibVLC.isPlaying() ? R.drawable.ic_pause_circle_big_o
- : R.drawable.ic_play_circle_big_o);
- }
- /**
- * update the overlay
- */
- private int setOverlayProgress() {
- if (mLibVLC == null) {
- return 0;
- }
- int time = (int) mLibVLC.getTime();
- int length = (int) mLibVLC.getLength();
- if (length == 0) {
- Media media = MediaDatabase.getInstance().getMedia(mLocation);
- if (media != null)
- length = (int) media.getLength();
- }
- // Update all view elements
- boolean isSeekable = mEnableJumpButtons && length > 0;
- mBackward.setVisibility(isSeekable ? View.VISIBLE : View.GONE);
- mForward.setVisibility(isSeekable ? View.VISIBLE : View.GONE);
- mSeekbar.setMax(length);
- mSeekbar.setProgress(time);
- mSysTime.setText(DateFormat.getTimeFormat(this).format(new Date(System.currentTimeMillis())));
- if (time >= 0) mTime.setText(Strings.millisToString(time));
- if (length >= 0) mLength.setText(mDisplayRemainingTime && length > 0
- ? "- " + Strings.millisToString(length - time)
- : Strings.millisToString(length));
- return time;
- }
- private void setESTracks() {
- if (mLastAudioTrack >= 0) {
- mLibVLC.setAudioTrack(mLastAudioTrack);
- mLastAudioTrack = -1;
- }
- if (mLastSpuTrack >= -1) {
- mLibVLC.setSpuTrack(mLastSpuTrack);
- mLastSpuTrack = -2;
- }
- }
- private void setESTrackLists(boolean force) {
- if(mAudioTracksList == null || force) {
- if (mLibVLC.getAudioTracksCount() > 2) {
- mAudioTracksList = mLibVLC.getAudioTrackDescription();
- mAudioTrack.setOnClickListener(mAudioTrackListener);
- mAudioTrack.setVisibility(View.VISIBLE);
- }
- else {
- mAudioTrack.setVisibility(View.GONE);
- mAudioTrack.setOnClickListener(null);
- }
- }
- if (mSubtitleTracksList == null || force) {
- if (mLibVLC.getSpuTracksCount() > 0) {
- mSubtitleTracksList = mLibVLC.getSpuTrackDescription();
- mSubtitle.setOnClickListener(mSubtitlesListener);
- mSubtitle.setVisibility(View.VISIBLE);
- }
- else {
- mSubtitle.setVisibility(View.GONE);
- mSubtitle.setOnClickListener(null);
- }
- }
- }
- /**
- *
- */
- private void play() {
- mLibVLC.play();
- mSurface.setKeepScreenOn(true);
- }
- /**
- *
- */
- private void pause() {
- mLibVLC.pause();
- mSurface.setKeepScreenOn(false);
- }
- /**
- * External extras:
- * - position (long) - position of the video to start with (in ms)
- */
- @SuppressWarnings({ "unchecked" })
- private void loadMedia() {
- mLocation = null;
- String title = getResources().getString(R.string.title);
- boolean dontParse = false;
- boolean fromStart = false;
- String itemTitle = null;
- int itemPosition = -1; // Index in the media list as passed by AudioServer (used only for vout transition internally)
- long intentPosition = -1; // position passed in by intent (ms)
- if (getIntent().getAction() != null
- && getIntent().getAction().equals(Intent.ACTION_VIEW)) {
- /* Started from external application 'content' */
- if (getIntent().getData() != null
- && getIntent().getData().getScheme() != null
- && getIntent().getData().getScheme().equals("content")) {
- // Media or MMS URI
- if(getIntent().getData().getHost().equals("media")
- || getIntent().getData().getHost().equals("mms")) {
- try {
- Cursor cursor = getContentResolver().query(getIntent().getData(),
- new String[]{ MediaStore.Video.Media.DATA }, null, null, null);
- if (cursor != null) {
- int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
- if (cursor.moveToFirst())
- mLocation = LibVLC.PathToURI(cursor.getString(column_index));
- cursor.close();
- }
- } catch (Exception e) {
- Log.e(TAG, "Couldn't read the file from media or MMS");
- encounteredError();
- }
- }
- // Mail-based apps - download the stream to a temporary file and play it
- else if(getIntent().getData().getHost().equals("com.fsck.k9.attachmentprovider")
- || getIntent().getData().getHost().equals("gmail-ls")) {
- try {
- Cursor cursor = getContentResolver().query(getIntent().getData(),
- new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);
- if (cursor != null) {
- cursor.moveToFirst();
- String filename = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));
- cursor.close();
- Log.i(TAG, "Getting file " + filename + " from content:// URI");
- InputStream is = getContentResolver().openInputStream(getIntent().getData());
- OutputStream os = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/Download/" + filename);
- byte[] buffer = new byte[1024];
- int bytesRead = 0;
- while((bytesRead = is.read(buffer)) >= 0) {
- os.write(buffer, 0, bytesRead);
- }
- os.close();
- is.close();
- mLocation = LibVLC.PathToURI(Environment.getExternalStorageDirectory().getPath() + "/Download/" + filename);
- }
- } catch (Exception e) {
- Log.e(TAG, "Couldn't download file from mail URI");
- encounteredError();
- }
- }
- // other content-based URI (probably file pickers)
- else {
- mLocation = getIntent().getData().getPath();
- }
- } /* External application */
- else if (getIntent().getDataString() != null) {
- // Plain URI
- mLocation = getIntent().getDataString();
- // Remove VLC prefix if needed
- if (mLocation.startsWith("vlc://")) {
- mLocation = mLocation.substring(6);
- }
- // Decode URI
- if (!mLocation.contains("/")){
- try {
- mLocation = URLDecoder.decode(mLocation,"UTF-8");
- } catch (UnsupportedEncodingException e) {
- Log.w(TAG, "UnsupportedEncodingException while decoding MRL " + mLocation);
- }
- }
- } else {
- Log.e(TAG, "Couldn't understand the intent");
- encounteredError();
- }
- // Try to get the position
- if(getIntent().getExtras() != null)
- intentPosition = getIntent().getExtras().getLong("position", -1);
- } /* ACTION_VIEW */
- /* Started from VideoListActivity */
- else if(getIntent().getAction() != null
- && getIntent().getAction().equals(PLAY_FROM_VIDEOGRID)
- && getIntent().getExtras() != null) {
- mLocation = getIntent().getExtras().getString("itemLocation");
- itemTitle = getIntent().getExtras().getString("itemTitle");
- dontParse = getIntent().getExtras().getBoolean("dontParse");
- fromStart = getIntent().getExtras().getBoolean("fromStart");
- itemPosition = getIntent().getExtras().getInt("itemPosition", -1);
- }
- mSurface.setKeepScreenOn(true);
- if(mLibVLC == null)
- return;
- /* WARNING: hack to avoid a crash in mediacodec on KitKat.
- * Disable hardware acceleration if the media has a ts extension. */
- if (mLocation != null && LibVlcUtil.isKitKatOrLater()) {
- String locationLC = mLocation.toLowerCase(Locale.ENGLISH);
- if (locationLC.endsWith(".ts")
- || locationLC.endsWith(".tts")
- || locationLC.endsWith(".m2t")
- || locationLC.endsWith(".mts")
- || locationLC.endsWith(".m2ts")) {
- mDisabledHardwareAcceleration = true;
- mPreviousHardwareAccelerationMode = mLibVLC.getHardwareAcceleration();
- // mLibVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_DISABLED);
- mLibVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_FULL);
- }
- }
- mLibVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_DISABLED);
- /* Start / resume playback */
- if(dontParse && itemPosition >= 0) {
- // Provided externally from AudioService
- Log.d(TAG, "Continuing playback from AudioService at index " + itemPosition);
- savedIndexPosition = itemPosition;
- if(!mLibVLC.isPlaying()) {
- // AudioService-transitioned playback for item after sleep and resume
- mLibVLC.playIndex(savedIndexPosition);
- dontParse = false;
- }
- else {
- stopLoadingAnimation();
- showOverlay();
- }
- updateNavStatus();
- } else if (savedIndexPosition > -1) {
- AudioServiceController.getInstance().stop(); // Stop the previous playback.
- mLibVLC.setMediaList();
- mLibVLC.playIndex(savedIndexPosition);
- } else if (mLocation != null && mLocation.length() > 0 && !dontParse) {
- AudioServiceController.getInstance().stop(); // Stop the previous playback.
- mLibVLC.setMediaList();
- mLibVLC.getMediaList().add(new Media(mLibVLC, mLocation));
- savedIndexPosition = mLibVLC.getMediaList().size() - 1;
- mLibVLC.playIndex(savedIndexPosition);
- }
- mCanSeek = false;
- if (mLocation != null && mLocation.length() > 0 && !dontParse) {
- // restore last position
- Media media = MediaDatabase.getInstance().getMedia(mLocation);
- if(media != null) {
- // in media library
- if(media.getTime() > 0 && !fromStart)
- mLibVLC.setTime(media.getTime());
- // Consume fromStart option after first use to prevent
- // restarting again when playback is paused.
- getIntent().putExtra("fromStart", false);
- mLastAudioTrack = media.getAudioTrack();
- mLastSpuTrack = media.getSpuTrack();
- } else {
- // not in media library
- long rTime = mSettings.getLong(PreferencesActivity.VIDEO_RESUME_TIME, -1);
- Editor editor = mSettings.edit();
- editor.putLong(PreferencesActivity.VIDEO_RESUME_TIME, -1);
- editor.commit();
- if(rTime > 0)
- mLibVLC.setTime(rTime);
- if(intentPosition > 0)
- mLibVLC.setTime(intentPosition);
- }
- // Get possible subtitles
- String subtitleList_serialized = mSettings.getString(PreferencesActivity.VIDEO_SUBTITLE_FILES, null);
- ArrayList<String> prefsList = new ArrayList<String>();
- if(subtitleList_serialized != null) {
- ByteArrayInputStream bis = new ByteArrayInputStream(subtitleList_serialized.getBytes());
- try {
- ObjectInputStream ois = new ObjectInputStream(bis);
- prefsList = (ArrayList<String>)ois.readObject();
- } catch(ClassNotFoundException e) {}
- catch (StreamCorruptedException e) {}
- catch (IOException e) {}
- }
- for(String x : prefsList){
- if(!mSubtitleSelectedFiles.contains(x))
- mSubtitleSelectedFiles.add(x);
- }
- // Get the title
- try {
- title = URLDecoder.decode(mLocation, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- } catch (IllegalArgumentException e) {
- }
- if (title.startsWith("file:")) {
- title = new File(title).getName();
- int dotIndex = title.lastIndexOf('.');
- if (dotIndex != -1)
- title = title.substring(0, dotIndex);
- }
- } else if(itemTitle != null) {
- title = itemTitle;
- }
- mTitle.setText(title);
- }
- @SuppressWarnings("deprecation")
- private int getScreenRotation(){
- WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO /* Android 2.2 has getRotation */) {
- try {
- Method m = display.getClass().getDeclaredMethod("getRotation");
- return (Integer) m.invoke(display);
- } catch (Exception e) {
- return Surface.ROTATION_0;
- }
- } else {
- return display.getOrientation();
- }
- }
- @TargetApi(Build.VERSION_CODES.GINGERBREAD)
- private int getScreenOrientation(){
- WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- int rot = getScreenRotation();
- /*
- * Since getRotation() returns the screen's "natural" orientation,
- * which is not guaranteed to be SCREEN_ORIENTATION_PORTRAIT,
- * we have to invert the SCREEN_ORIENTATION value if it is "naturally"
- * landscape.
- */
- @SuppressWarnings("deprecation")
- boolean defaultWide = display.getWidth() > display.getHeight();
- if(rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270)
- defaultWide = !defaultWide;
- if(defaultWide) {
- switch (rot) {
- case Surface.ROTATION_0:
- return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
- case Surface.ROTATION_90:
- return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
- case Surface.ROTATION_180:
- // SCREEN_ORIENTATION_REVERSE_PORTRAIT only available since API
- // Level 9+
- return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
- : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- case Surface.ROTATION_270:
- // SCREEN_ORIENTATION_REVERSE_LANDSCAPE only available since API
- // Level 9+
- return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
- : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- default:
- return 0;
- }
- } else {
- switch (rot) {
- case Surface.ROTATION_0:
- return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
- case Surface.ROTATION_90:
- return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
- case Surface.ROTATION_180:
- // SCREEN_ORIENTATION_REVERSE_PORTRAIT only available since API
- // Level 9+
- return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
- : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- case Surface.ROTATION_270:
- // SCREEN_ORIENTATION_REVERSE_LANDSCAPE only available since API
- // Level 9+
- return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
- : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- default:
- return 0;
- }
- }
- }
- public void showAdvancedOptions(View v) {
- CommonDialogs.advancedOptions(this, v, MenuType.Video);
- }
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- private void createPresentation() {
- if (mMediaRouter == null || mEnableCloneMode)
- return;
- // Get the current route and its presentation display.
- MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
- MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
- Display presentationDisplay = route != null ? route.getPresentationDisplay() : null;
- if (presentationDisplay != null) {
- // Show a new presentation if possible.
- Log.i(TAG, "Showing presentation on display: " + presentationDisplay);
- mPresentation = new SecondaryDisplay(this, presentationDisplay);
- mPresentation.setOnDismissListener(mOnDismissListener);
- try {
- mPresentation.show();
- } catch (WindowManager.InvalidDisplayException ex) {
- Log.w(TAG, "Couldn't show presentation! Display was removed in "
- + "the meantime.", ex);
- mPresentation = null;
- }
- } else
- Log.i(TAG, "No secondary display detected");
- }
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- private void removePresentation() {
- if (mMediaRouter == null)
- return;
- // Dismiss the current presentation if the display has changed.
- Log.i(TAG, "Dismissing presentation because the current route no longer "
- + "has a presentation display.");
- mLibVLC.pause(); // Stop sending frames to avoid a crash.
- finish(); //TODO restore the video on the new display instead of closing
- if (mPresentation != null) mPresentation.dismiss();
- mPresentation = null;
- }
- /**
- * Listens for when presentations are dismissed.
- */
- private final DialogInterface.OnDismissListener mOnDismissListener = new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- if (dialog == mPresentation) {
- Log.i(TAG, "Presentation was dismissed.");
- mPresentation = null;
- }
- }
- };
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- private final class SecondaryDisplay extends Presentation {
- public final static String TAG = "VLC/SecondaryDisplay";
- private SurfaceView mSurface;
- private SurfaceView mSubtitlesSurface;
- private SurfaceHolder mSurfaceHolder;
- private SurfaceHolder mSubtitlesSurfaceHolder;
- private FrameLayout mSurfaceFrame;
- private LibVLC mLibVLC;
- public SecondaryDisplay(Context context, Display display) {
- super(context, display);
- if (context instanceof Activity) {
- setOwnerActivity((Activity) context);
- }
- try {
- mLibVLC = VLCInstance.getLibVlcInstance();
- } catch (LibVlcException e) {
- Log.d(TAG, "LibVLC initialisation failed");
- return;
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.player_remote);
- mSurface = (SurfaceView) findViewById(R.id.remote_player_surface);
- mSurfaceHolder = mSurface.getHolder();
- mSurfaceFrame = (FrameLayout) findViewById(R.id.remote_player_surface_frame);
- String chroma = mSettings.getString("chroma_format", "");
- if(LibVlcUtil.isGingerbreadOrLater() && chroma.equals("YV12")) {
- mSurfaceHolder.setFormat(ImageFormat.YV12);
- } else if (chroma.equals("RV16")) {
- mSurfaceHolder.setFormat(PixelFormat.RGB_565);
- } else {
- mSurfaceHolder.setFormat(PixelFormat.RGBX_8888);
- }
- VideoPlayerActivity activity = (VideoPlayerActivity)getOwnerActivity();
- if (activity == null) {
- Log.e(TAG, "Failed to get the VideoPlayerActivity instance, secondary display won't work");
- return;
- }
- mSurfaceHolder.addCallback(activity.mSurfaceCallback);
- mSubtitlesSurface = (SurfaceView) findViewById(R.id.remote_subtitles_surface);
- mSubtitlesSurfaceHolder = mSubtitlesSurface.getHolder();
- mSubtitlesSurfaceHolder.setFormat(PixelFormat.RGBA_8888);
- mSubtitlesSurface.setZOrderMediaOverlay(true);
- mSubtitlesSurfaceHolder.addCallback(activity.mSubtitlesSurfaceCallback);
- /* Only show the subtitles surface when using "Full Acceleration" mode */
- if (mLibVLC != null && mLibVLC.getHardwareAcceleration() == LibVLC.HW_ACCELERATION_FULL)
- mSubtitlesSurface.setVisibility(View.VISIBLE);
- Log.i(TAG, "Secondary display created");
- }
- }
- /**
- * Start the video loading animation.
- */
- private void startLoadingAnimation() {
- AnimationSet anim = new AnimationSet(true);
- RotateAnimation rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
- rotate.setDuration(800);
- rotate.setInterpolator(new DecelerateInterpolator());
- rotate.setRepeatCount(RotateAnimation.INFINITE);
- anim.addAnimation(rotate);
- mLoading.startAnimation(anim);
- mLoadingText.setVisibility(View.VISIBLE);
- }
- /**
- * Stop the video loading animation.
- */
- private void stopLoadingAnimation() {
- mLoading.setVisibility(View.INVISIBLE);
- mLoading.clearAnimation();
- mLoadingText.setVisibility(View.GONE);
- }
- public void onClickOverlayTips(View v) {
- mOverlayTips.setVisibility(View.GONE);
- }
- public void onClickDismissTips(View v) {
- mOverlayTips.setVisibility(View.GONE);
- Editor editor = mSettings.edit();
- editor.putBoolean(PREF_TIPS_SHOWN, true);
- editor.commit();
- }
- private void updateNavStatus() {
- mHasMenu = mLibVLC.getChapterCountForTitle(0) > 1 && mLibVLC.getTitleCount() > 1;
- mIsNavMenu = mHasMenu && mLibVLC.getTitle() == 0;
- /***
- * HACK ALERT: assume that any media with >1 titles = DVD with menus
- * Should be replaced with a more robust title/chapter selection popup
- */
- Log.d(TAG,
- "updateNavStatus: getChapterCountForTitle(0) = "
- + mLibVLC.getChapterCountForTitle(0)
- + ", getTitleCount() = " + mLibVLC.getTitleCount());
- if (mIsNavMenu) {
- /*
- * Keep the overlay hidden in order to have touch events directly
- * transmitted to navigation handling.
- */
- hideOverlay(false);
- }
- else if (mHasMenu) {
- setESTrackLists(true);
- setESTracks();
- /* Show the return to menu button. */
- mNavMenu.setVisibility(View.VISIBLE);
- mNavMenu.setOnClickListener(mNavMenuListener);
- }
- else
- mNavMenu.setVisibility(View.GONE);
- }
- }
http://blog.csdn.net/cuiran/article/details/40558085
相关推荐
在本文中,我们将深入探讨如何利用VLC创建UDP组播,这是一个在网络中高效传输多媒体数据的技术。 首先,了解UDP(User Datagram Protocol)和组播的概念至关重要。UDP是一种无连接的传输层协议,相比于TCP,它不...
在Android平台上,使用VLC(VideoLAN Client)来实现RTSP(Real Time Streaming Protocol)流媒体播放是一项常见的技术任务。VLC是一个开源、跨平台的多媒体框架,支持各种媒体格式和流协议,使得开发者能够方便地...
5. **第三方库依赖**:VLC可能依赖于FFmpeg、Libav等第三方库进行音频和视频处理。 **贡献与社区参与:** 1. **开源文化**:由于是开源项目,任何人都可以参与到VLC的开发中,提交bug报告、改进代码或添加新功能。 ...
使用vlc-1.0.5.tar.bz2 + live555-2010.01.tar.gz export MYDIR=/root/lf 将live555-2010.01.tar.gz和vlc-1.0.5.tar.bz2放置在$MYDIR下 cd $MYDIR (一) 编译liveMedia tar xvfz live555-2010.01.tar.gz cd live ./...
WebRTC(Web Real-Time Communication)是浏览器内置的实时通信框架,旨在实现浏览器之间的音视频通信,而无需插件或第三方软件。WebRTC支持ICE(Interactive Connectivity Establishment)、STUN(Session ...
它集成了多个第三方库和技术,如libcdio用于读取ISO文件,FFmpeg则为VLC提供了大部分的编解码能力。此外,VLC还利用了DirectShow等API接口来提升播放性能。 #### 四、应用场景 - **教育领域**:教师可以利用VLC...
通过调用`GetStreamUri`方法,可以获取到一个RTSP(Real Time Streaming Protocol)URL,然后使用Android的`MediaPlayer`或第三方库如VLC来播放视频。 5. **PTZ控制**: 如果设备支持PTZ,我们可以使用PTZ Service...
- 提供应用查询接口和资源查询接口,方便第三方开发和集成。 总的来说,云视睿博流媒体服务器是一个强大的多媒体服务平台,集成了丰富的直播、点播、转码和安全管理功能,支持多种协议和终端设备,具有高可用性和...
开发者需要熟悉Android SDK,理解如何创建服务、活动、广播接收器等组件,以及如何使用Android Media Player API或第三方库(如ExoPlayer)来处理多媒体。 4. **Apple TV的AirPlay协议**:虽然Apple TV主要与iOS...