[Android] [PATCH] Dynamically respond to video ES changes

Rafaël Carré funman at videolan.org
Mon Jul 2 16:46:03 CEST 2012


It looks very nice, do you have a sample with changing ES so we can test?
Le 2 juil. 2012 14:29, "Edward Wang" <edward.c.wang at compdigitec.com> a
écrit :

> This will allow us to support dynamically ES-changing streams, more
> streaming formats (TS) and more video formats (such as OGG video).
> ---
>  vlc-android/jni/libvlcjni.c                        |   12 ++++-
>  vlc-android/src/org/videolan/vlc/AudioService.java |   49
> +++++++++++++++++++-
>  .../org/videolan/vlc/AudioServiceController.java   |   12 +++++
>  vlc-android/src/org/videolan/vlc/EventManager.java |    4 +-
>  vlc-android/src/org/videolan/vlc/LibVLC.java       |    4 ++
>  .../src/org/videolan/vlc/gui/MainActivity.java     |   28 ++++--------
>  .../vlc/gui/video/VideoPlayerActivity.java         |   46
> ++++++++++++++++++-
>  .../org/videolan/vlc/interfaces/IAudioService.aidl |    1 +
>  8 files changed, 130 insertions(+), 26 deletions(-)
>
> diff --git a/vlc-android/jni/libvlcjni.c b/vlc-android/jni/libvlcjni.c
> index 1d07a82..18867ff 100644
> --- a/vlc-android/jni/libvlcjni.c
> +++ b/vlc-android/jni/libvlcjni.c
> @@ -164,6 +164,11 @@ static void vlc_event_callback(const libvlc_event_t
> *ev, void *data)
>      JNIEnv *env;
>      JavaVM *myVm = data;
>
> +    int ev_opt_data = 0;
> +    if(ev->type == libvlc_MediaPlayerVout) {
> +        /* For determining the vout/ES track change */
> +        ev_opt_data = ev->u.media_player_vout.new_count;
> +    }
>      bool isAttached = false;
>
>      if (eventManagerInstance == NULL)
> @@ -187,9 +192,9 @@ static void vlc_event_callback(const libvlc_event_t
> *ev, void *data)
>      }
>
>      /* Find the callback ID */
> -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> "(I)V");
> +    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> "(II)V");
>      if (methodID) {
> -        (*env)->CallVoidMethod(env, eventManagerInstance, methodID,
> ev->type);
> +        (*env)->CallVoidMethod(env, eventManagerInstance, methodID,
> ev->type, ev_opt_data);
>      } else {
>          LOGE("EventManager: failed to get the callback method");
>      }
> @@ -365,7 +370,7 @@ void
> Java_org_videolan_vlc_LibVLC_setEventManager(JNIEnv *env, jobject thiz, job
>          return;
>      }
>
> -    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> "(I)V");
> +    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback",
> "(II)V");
>      if (!methodID) {
>          LOGE("setEventManager: failed to get the callback method");
>          return;
> @@ -526,6 +531,7 @@ void Java_org_videolan_vlc_LibVLC_readMedia(JNIEnv
> *env, jobject thiz,
>          libvlc_MediaPlayerPaused,
>          libvlc_MediaPlayerEndReached,
>          libvlc_MediaPlayerStopped,
> +        libvlc_MediaPlayerVout,
>      };
>      int i;
>      for (i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); ++i)
> diff --git a/vlc-android/src/org/videolan/vlc/AudioService.java
> b/vlc-android/src/org/videolan/vlc/AudioService.java
> index a1f4226..c59e1d6 100644
> --- a/vlc-android/src/org/videolan/vlc/AudioService.java
> +++ b/vlc-android/src/org/videolan/vlc/AudioService.java
> @@ -30,6 +30,7 @@ import java.util.Stack;
>
>  import org.videolan.vlc.gui.MainActivity;
>  import org.videolan.vlc.gui.audio.AudioPlayerActivity;
> +import org.videolan.vlc.gui.video.VideoPlayerActivity;
>  import org.videolan.vlc.interfaces.IAudioService;
>  import org.videolan.vlc.interfaces.IAudioServiceCallback;
>  import org.videolan.vlc.widget.VLCAppWidgetProvider;
> @@ -277,6 +278,21 @@ public class AudioService extends Service {
>                      executeUpdate();
>                      next();
>                      break;
> +                case EventManager.MediaPlayerVout:
> +                    if(msg.getData().getInt("data") > 0) {
> +                        Log.i(TAG, "Obtained video track");
> +                        mMediaList.clear();
> +                        hideNotification();
> +
> +                        // Got video, switch to the video player
> +                        Intent intent = new
> Intent(VLCApplication.getAppContext(), VideoPlayerActivity.class);
> +                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
> Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
> +                        intent.putExtra("itemLocation",
> mCurrentMedia.getLocation());
> +                        // Don't lose the currently playing stream
> +                        intent.putExtra("dontParse", true);
> +                        startActivity(intent);
> +                    }
> +                    break;
>                  default:
>                      Log.e(TAG, "Event not handled");
>                      break;
> @@ -611,8 +627,39 @@ public class AudioService extends Service {
>              }
>
>              if (mCurrentMedia != null)
> -                mLibVLC.readMedia(mCurrentMedia.getLocation(), true);
> +                mLibVLC.readMedia(mCurrentMedia.getLocation());
> +            showNotification();
> +        }
> +
> +        @Override
> +        public void showWithoutParse(String URI) throws RemoteException {
> +            Log.v(TAG, "Showing playing URI " + URI);
> +            // Show an URI without interrupting/losing the current stream
> +
> +            mEventManager.addHandler(mEventHandler);
> +            mMediaList.clear();
> +            mPrevious.clear();
> +            // Prevent re-parsing the media, which would mean losing the
> connection
> +            mCurrentMedia = new Media(
> +                    getApplicationContext(),
> +                    URI,
> +                    0,
> +                    0,
> +                    Media.TYPE_AUDIO,
> +                    null,
> +                    URI,
> +
>  VLCApplication.getAppContext().getString(R.string.unknown_artist),
> +
>  VLCApplication.getAppContext().getString(R.string.unknown_genre),
> +
>  VLCApplication.getAppContext().getString(R.string.unknown_album),
> +                    0,
> +                    0,
> +                    "");
> +            mMediaList.add(mCurrentMedia);
> +
> +            // Notify everyone
> +            mHandler.sendEmptyMessage(SHOW_PROGRESS);
>              showNotification();
> +            executeUpdate();
>          }
>
>          @Override
> diff --git a/vlc-android/src/org/videolan/vlc/AudioServiceController.java
> b/vlc-android/src/org/videolan/vlc/AudioServiceController.java
> index 5f6ef61..98627e4 100644
> --- a/vlc-android/src/org/videolan/vlc/AudioServiceController.java
> +++ b/vlc-android/src/org/videolan/vlc/AudioServiceController.java
> @@ -212,6 +212,18 @@ public class AudioServiceController implements
> IAudioPlayerControl {
>          updateAudioPlayer();
>      }
>
> +    public void showWithoutParse(String u) {
> +        if (mAudioServiceBinder == null) {
> +            return;
> +        }
> +        try {
> +            mAudioServiceBinder.showWithoutParse(u);
> +        } catch (RemoteException e) {
> +            Log.e(TAG, "remote procedure call failed:
> showWithoutParse()");
> +        }
> +        updateAudioPlayer();
> +    }
> +
>      @Override
>      public String getAlbum() {
>          String album = null;
> diff --git a/vlc-android/src/org/videolan/vlc/EventManager.java
> b/vlc-android/src/org/videolan/vlc/EventManager.java
> index 6dcb44c..19e88a1 100644
> --- a/vlc-android/src/org/videolan/vlc/EventManager.java
> +++ b/vlc-android/src/org/videolan/vlc/EventManager.java
> @@ -57,6 +57,7 @@ public class EventManager {
>      //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;
> @@ -111,9 +112,10 @@ public class EventManager {
>      }
>
>      /** This method is called by a native thread **/
> -    public void callback(int event) {
> +    public void callback(int event, int optional_data) {
>          Bundle b = new Bundle();
>          b.putInt("event", event);
> +        b.putInt("data", optional_data);
>          for (int i = 0; i < mEventHandler.size(); i++) {
>              Message msg = Message.obtain();
>              msg.setData(b);
> diff --git a/vlc-android/src/org/videolan/vlc/LibVLC.java
> b/vlc-android/src/org/videolan/vlc/LibVLC.java
> index cd9444f..211c255 100644
> --- a/vlc-android/src/org/videolan/vlc/LibVLC.java
> +++ b/vlc-android/src/org/videolan/vlc/LibVLC.java
> @@ -229,6 +229,10 @@ public class LibVLC {
>          mAout.release();
>      }
>
> +    public void readMedia(String mrl) {
> +        readMedia(mLibVlcInstance, mrl, false);
> +    }
> +
>      /**
>       * Read a media.
>       */
> diff --git a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
> b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
> index f9720b0..2179cba 100644
> --- a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
> +++ b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
> @@ -20,7 +20,6 @@
>
>  package org.videolan.vlc.gui;
>
> -import java.io.IOException;
>  import java.util.ArrayList;
>
>  import org.videolan.vlc.AudioService;
> @@ -34,7 +33,6 @@ import org.videolan.vlc.VLCCallbackTask;
>  import org.videolan.vlc.gui.audio.AudioBrowserFragment;
>  import org.videolan.vlc.gui.video.VideoListAdapter;
>  import org.videolan.vlc.gui.video.VideoListFragment;
> -import org.videolan.vlc.gui.video.VideoPlayerActivity;
>  import org.videolan.vlc.interfaces.ISortable;
>  import org.videolan.vlc.widget.AudioMiniPlayer;
>
> @@ -479,23 +477,15 @@ public class MainActivity extends
> SherlockFragmentActivity {
>                              AudioServiceController c =
> AudioServiceController.getInstance();
>                              String s = input.getText().toString();
>
> -                            try {
> -
>  if(!LibVLC.getExistingInstance().hasVideoTrack(s)) {
> -                                    Log.d(TAG, "Auto-detected audio for "
> + s);
> -                                    ArrayList<String> media = new
> ArrayList<String>();
> -                                    media.add(input.getText().toString());
> -                                    c.append(media);
> -                                } else {
> -                                    Log.d(TAG, "Auto-detected Video for "
> + s);
> -                                    Intent intent = new
> Intent(getApplicationContext(),
> -
> VideoPlayerActivity.class);
> -                                    intent.putExtra("itemLocation", s);
> -                                    startActivity(intent);
> -                                }
> -                            } catch(IOException e) {
> -                                /* VLC is unable to open the MRL */
> -                                return;
> -                            }
> +                            /* Use the audio player by default. If a
> video track is
> +                             * detected, then it will automatically
> switch to the video
> +                             * player. This allows us to support more
> types of streams
> +                             * (for example, RTSP and TS streaming) where
> ES can be
> +                             * dynamically adapted rather than a simple
> scan.
> +                             */
> +                            ArrayList<String> media = new
> ArrayList<String>();
> +                            media.add(s);
> +                            c.append(media);
>                          }
>
>                          @Override
> diff --git
> a/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> b/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> index 3612444..104c6ad 100644
> --- a/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> +++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoPlayerActivity.java
> @@ -25,12 +25,14 @@ import java.io.UnsupportedEncodingException;
>  import java.lang.reflect.Method;
>  import java.net.URLDecoder;
>
> +import org.videolan.vlc.AudioServiceController;
>  import org.videolan.vlc.EventManager;
>  import org.videolan.vlc.LibVLC;
>  import org.videolan.vlc.LibVlcException;
>  import org.videolan.vlc.R;
>  import org.videolan.vlc.Util;
>  import org.videolan.vlc.gui.PreferencesActivity;
> +import org.videolan.vlc.gui.audio.AudioPlayerActivity;
>  import org.videolan.vlc.interfaces.IPlayerControl;
>  import org.videolan.vlc.interfaces.OnPlayerControlListener;
>  import org.videolan.vlc.widget.PlayerControlClassic;
> @@ -114,6 +116,13 @@ public class VideoPlayerActivity extends Activity {
>      private ImageButton mLock;
>      private ImageButton mSize;
>
> +    // what video?
> +    private String mLocation;
> +    /**
> +     * For uninterrupted switching between audio and video mode
> +     */
> +    private boolean mSwitchingView;
> +
>      // size of the video
>      private int mVideoHeight;
>      private int mVideoWidth;
> @@ -200,10 +209,15 @@ public class VideoPlayerActivity extends Activity {
>      protected void onStart() {
>          super.onStart();
>          dimStatusBar(true);
> +        mSwitchingView = false;
>      }
>
>      @Override
>      protected void onPause() {
> +        if(mSwitchingView) {
> +            super.onPause();
> +            return;
> +        }
>          long time = 0;
>          if (mLibVLC.isPlaying()) {
>              time = mLibVLC.getTime() - 5000;
> @@ -222,7 +236,7 @@ public class VideoPlayerActivity extends Activity {
>      @Override
>      protected void onDestroy() {
>          unregisterReceiver(mBatteryReceiver);
> -        if (mLibVLC != null) {
> +        if (mLibVLC != null && !mSwitchingView) {
>              mLibVLC.stop();
>          }
>
> @@ -231,9 +245,23 @@ public class VideoPlayerActivity extends Activity {
>
>          mAudioManager = null;
>
> +        if(mSwitchingView) {
> +            Log.d(TAG, "mLocation = \"" + mLocation + "\"");
> +
>  AudioServiceController.getInstance().showWithoutParse(mLocation);
> +            Intent i = new Intent(this, AudioPlayerActivity.class);
> +            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
> Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
> +            startActivity(i);
> +        }
> +        //AudioServiceController.getInstance().unbindAudioService(this);
>          super.onDestroy();
>      }
>
> +    @Override
> +    protected void onResume() {
> +        AudioServiceController.getInstance().bindAudioService(this);
> +        super.onResume();
> +    }
> +
>      private final BroadcastReceiver mBatteryReceiver = new
> BroadcastReceiver()
>      {
>          @Override
> @@ -372,6 +400,14 @@ public class VideoPlayerActivity extends Activity {
>                      /* Exit player when reach the end */
>                      VideoPlayerActivity.this.finish();
>                      break;
> +                case EventManager.MediaPlayerVout:
> +                    if(msg.getData().getInt("data") == 0) {
> +                        /* Video track lost, open in audio mode */
> +                        Log.i(TAG, "Video track lost, switching to
> audio");
> +                        VideoPlayerActivity.this.mSwitchingView = true;
> +                        VideoPlayerActivity.this.finish();
> +                    }
> +                    break;
>                  default:
>                      Log.e(TAG, "Event not handled");
>                      break;
> @@ -830,6 +866,7 @@ public class VideoPlayerActivity extends Activity {
>          String location = null;
>          String title = null;
>          String lastLocation = null;
> +        mSwitchingView = false;
>          long lastTime = 0;
>          SharedPreferences preferences =
> getSharedPreferences(PreferencesActivity.NAME, MODE_PRIVATE);
>
> @@ -842,10 +879,15 @@ public class VideoPlayerActivity extends Activity {
>              location = getIntent().getExtras().getString("itemLocation");
>          }
>
> -        if (location != null && location.length() > 0) {
> +        boolean dontParse =
> getIntent().getExtras().getBoolean("dontParse");
> +        if(dontParse)
> +            mLocation = location;
> +        if (location != null && location.length() > 0 && !dontParse) {
>              mLibVLC.readMedia(location, false);
>              mSurface.setKeepScreenOn(true);
>
> +            mLocation = location;
> +
>              // Save media for next time, and restore position if it's the
> same one as before
>              lastLocation =
> preferences.getString(PreferencesActivity.LAST_MEDIA, null);
>              lastTime = preferences.getLong(PreferencesActivity.LAST_TIME,
> 0);
> diff --git
> a/vlc-android/src/org/videolan/vlc/interfaces/IAudioService.aidl
> b/vlc-android/src/org/videolan/vlc/interfaces/IAudioService.aidl
> index 4525d94..600dc42 100644
> --- a/vlc-android/src/org/videolan/vlc/interfaces/IAudioService.aidl
> +++ b/vlc-android/src/org/videolan/vlc/interfaces/IAudioService.aidl
> @@ -50,4 +50,5 @@ interface IAudioService {
>      void addAudioCallback(IAudioServiceCallback cb);
>      void removeAudioCallback(IAudioServiceCallback cb);
>      void detectHeadset(boolean enable);
> +    void showWithoutParse(String URI);
>  }
> --
> 1.7.5.4
>
> _______________________________________________
> Android mailing list
> Android at videolan.org
> http://mailman.videolan.org/listinfo/android
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/android/attachments/20120702/04fa7e88/attachment-0001.html>


More information about the Android mailing list