From bb2323a125bf799b4c51daaa7130689d726d6f73 Mon Sep 17 00:00:00 2001 From: bbcallen Date: Tue, 13 Aug 2013 18:55:09 +0800 Subject: [PATCH] IjkMediaListPlayer: support multiple segment video play --- .../ijk/media/player/AbstractMediaPlayer.java | 125 ++------ .../ijk/media/player/AndroidMediaPlayer.java | 2 +- .../ijk/media/player/DummyMediaPlayer.java | 122 ++++++++ .../ijk/media/player/IjkMediaPlayer.java | 2 +- .../ijk/media/player/SimpleMediaPlayer.java | 120 ++++++++ .../player/list/AbstractMediaListPlayer.java | 243 ++++++++++++++++ .../media/player/list/IjkMediaListPlayer.java | 17 ++ .../ijk/media/player/list/MediaList.java | 101 +++++++ .../ijk/media/player/list/MediaSegment.java | 33 +++ .../media/player/list/ResolveException.java | 17 ++ .../player/list/SimpleMediaSegmentPlayer.java | 269 ++++++++++++++++++ 11 files changed, 941 insertions(+), 110 deletions(-) create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/DummyMediaPlayer.java create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/SimpleMediaPlayer.java create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/AbstractMediaListPlayer.java create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/IjkMediaListPlayer.java create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaList.java create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaSegment.java create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/ResolveException.java create mode 100644 android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/SimpleMediaSegmentPlayer.java diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java index 9be86fcf..70d1d233 100644 --- a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java @@ -1,20 +1,3 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * Copyright (C) 2013 Zhang Rui - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package tv.danmaku.ijk.media.player; import java.io.IOException; @@ -95,6 +78,23 @@ public abstract class AbstractMediaPlayer { public abstract void setAudioStreamType(int streamtype); + public abstract void setOnPreparedListener(OnPreparedListener listener); + + public abstract void setOnCompletionListener(OnCompletionListener listener); + + public abstract void setOnBufferingUpdateListener( + OnBufferingUpdateListener listener); + + public abstract void setOnSeekCompleteListener( + OnSeekCompleteListener listener); + + public abstract void setOnVideoSizeChangedListener( + OnVideoSizeChangedListener listener); + + public abstract void setOnErrorListener(OnErrorListener listener); + + public abstract void setOnInfoListener(OnInfoListener listener); + /*-------------------- * Listeners */ @@ -126,95 +126,4 @@ public abstract class AbstractMediaPlayer { public interface OnInfoListener { boolean onInfo(AbstractMediaPlayer mp, int what, int extra); } - - private OnPreparedListener mOnPreparedListener; - private OnCompletionListener mOnCompletionListener; - private OnBufferingUpdateListener mOnBufferingUpdateListener; - private OnSeekCompleteListener mOnSeekCompleteListener; - private OnVideoSizeChangedListener mOnVideoSizeChangedListener; - private OnErrorListener mOnErrorListener; - private OnInfoListener mOnInfoListener; - - public final void setOnPreparedListener(OnPreparedListener listener) { - mOnPreparedListener = listener; - } - - public final void setOnCompletionListener(OnCompletionListener listener) { - mOnCompletionListener = listener; - } - - public final void setOnBufferingUpdateListener( - OnBufferingUpdateListener listener) { - mOnBufferingUpdateListener = listener; - } - - public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) { - mOnSeekCompleteListener = listener; - } - - public final void setOnVideoSizeChangedListener( - OnVideoSizeChangedListener listener) { - mOnVideoSizeChangedListener = listener; - } - - public final void setOnErrorListener(OnErrorListener listener) { - mOnErrorListener = listener; - } - - public final void setOnInfoListener(OnInfoListener listener) { - mOnInfoListener = listener; - } - - public final void resetListeners() { - mOnPreparedListener = null; - mOnBufferingUpdateListener = null; - mOnCompletionListener = null; - mOnSeekCompleteListener = null; - mOnVideoSizeChangedListener = null; - mOnErrorListener = null; - mOnInfoListener = null; - } - - protected static final void notifyOnPrepared(AbstractMediaPlayer mp) { - if (mp != null && mp.mOnPreparedListener != null) - mp.mOnPreparedListener.onPrepared(mp); - } - - protected static final void notifyOnCompletion(AbstractMediaPlayer mp) { - if (mp != null && mp.mOnCompletionListener != null) - mp.mOnCompletionListener.onCompletion(mp); - } - - protected static final void notifyOnBufferingUpdate(AbstractMediaPlayer mp, - int percent) { - if (mp != null && mp.mOnBufferingUpdateListener != null) - mp.mOnBufferingUpdateListener.onBufferingUpdate(mp, percent); - } - - protected static final void notifyOnSeekComplete(AbstractMediaPlayer mp) { - if (mp != null && mp.mOnSeekCompleteListener != null) - mp.mOnSeekCompleteListener.onSeekComplete(mp); - } - - protected static final void notifyOnVideoSizeChanged( - AbstractMediaPlayer mp, int width, int height, int sarNum, - int sarDen) { - if (mp != null && mp.mOnVideoSizeChangedListener != null) - mp.mOnVideoSizeChangedListener.onVideoSizeChanged(mp, width, - height, sarNum, sarDen); - } - - protected static final boolean notifyOnError(AbstractMediaPlayer mp, - int what, int extra) { - if (mp != null && mp.mOnErrorListener != null) - return mp.mOnErrorListener.onError(mp, what, extra); - return false; - } - - protected static final boolean notifyOnInfo(AbstractMediaPlayer mp, - int what, int extra) { - if (mp != null && mp.mOnInfoListener != null) - return mp.mOnInfoListener.onInfo(mp, what, extra); - return false; - } } diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java index fb35b076..a5d73d2c 100644 --- a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java @@ -25,7 +25,7 @@ import android.media.MediaPlayer; import android.view.Surface; import android.view.SurfaceHolder; -public final class AndroidMediaPlayer extends AbstractMediaPlayer { +public final class AndroidMediaPlayer extends SimpleMediaPlayer { private MediaPlayer mInternalMediaPlayer; private MediaPlayerListenerAdapter mInternalListenerAdapter; diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/DummyMediaPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/DummyMediaPlayer.java new file mode 100644 index 00000000..169fa282 --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/DummyMediaPlayer.java @@ -0,0 +1,122 @@ +package tv.danmaku.ijk.media.player; + +import java.io.IOException; + +import android.content.Context; +import android.view.Surface; +import android.view.SurfaceHolder; + +public class DummyMediaPlayer extends AbstractMediaPlayer { + public int mVideoWidth; + public int mVideoHeight; + public long mCurrentPosition; + public long mDuration; + public boolean mIsPlaying; + + @Override + public void setDisplay(SurfaceHolder sh) { + } + + @Override + public void setSurface(Surface surface) { + } + + @Override + public void setDataSource(String path) throws IOException, + IllegalArgumentException, SecurityException, IllegalStateException { + } + + @Override + public void prepareAsync() throws IllegalStateException { + } + + @Override + public void start() throws IllegalStateException { + } + + @Override + public void stop() throws IllegalStateException { + } + + @Override + public void pause() throws IllegalStateException { + } + + @Override + public void setWakeMode(Context context, int mode) { + } + + @Override + public void setScreenOnWhilePlaying(boolean screenOn) { + } + + @Override + public int getVideoWidth() { + return mVideoWidth; + } + + @Override + public int getVideoHeight() { + return mVideoHeight; + } + + @Override + public boolean isPlaying() { + return mIsPlaying; + } + + @Override + public void seekTo(long msec) throws IllegalStateException { + } + + @Override + public long getCurrentPosition() { + return mCurrentPosition; + } + + @Override + public long getDuration() { + return mDuration; + } + + @Override + public void release() { + } + + @Override + public void reset() { + } + + @Override + public void setAudioStreamType(int streamtype) { + } + + @Override + public void setOnPreparedListener(OnPreparedListener listener) { + } + + @Override + public void setOnCompletionListener(OnCompletionListener listener) { + } + + @Override + public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) { + } + + @Override + public void setOnSeekCompleteListener(OnSeekCompleteListener listener) { + } + + @Override + public void setOnVideoSizeChangedListener( + OnVideoSizeChangedListener listener) { + } + + @Override + public void setOnErrorListener(OnErrorListener listener) { + } + + @Override + public void setOnInfoListener(OnInfoListener listener) { + } +} diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/IjkMediaPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/IjkMediaPlayer.java index 0922ce6c..06037be0 100644 --- a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/IjkMediaPlayer.java +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/IjkMediaPlayer.java @@ -33,7 +33,7 @@ import android.os.PowerManager; import android.view.Surface; import android.view.SurfaceHolder; -public final class IjkMediaPlayer extends AbstractMediaPlayer { +public final class IjkMediaPlayer extends SimpleMediaPlayer { private final static String TAG = IjkMediaPlayer.class.getName(); static { diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/SimpleMediaPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/SimpleMediaPlayer.java new file mode 100644 index 00000000..f97c3428 --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/SimpleMediaPlayer.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2013 Zhang Rui + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tv.danmaku.ijk.media.player; + +public abstract class SimpleMediaPlayer extends AbstractMediaPlayer { + private OnPreparedListener mOnPreparedListener; + private OnCompletionListener mOnCompletionListener; + private OnBufferingUpdateListener mOnBufferingUpdateListener; + private OnSeekCompleteListener mOnSeekCompleteListener; + private OnVideoSizeChangedListener mOnVideoSizeChangedListener; + private OnErrorListener mOnErrorListener; + private OnInfoListener mOnInfoListener; + + public final void setOnPreparedListener(OnPreparedListener listener) { + mOnPreparedListener = listener; + } + + public final void setOnCompletionListener(OnCompletionListener listener) { + mOnCompletionListener = listener; + } + + public final void setOnBufferingUpdateListener( + OnBufferingUpdateListener listener) { + mOnBufferingUpdateListener = listener; + } + + public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) { + mOnSeekCompleteListener = listener; + } + + public final void setOnVideoSizeChangedListener( + OnVideoSizeChangedListener listener) { + mOnVideoSizeChangedListener = listener; + } + + public final void setOnErrorListener(OnErrorListener listener) { + mOnErrorListener = listener; + } + + public final void setOnInfoListener(OnInfoListener listener) { + mOnInfoListener = listener; + } + + public final void resetListeners() { + mOnPreparedListener = null; + mOnBufferingUpdateListener = null; + mOnCompletionListener = null; + mOnSeekCompleteListener = null; + mOnVideoSizeChangedListener = null; + mOnErrorListener = null; + mOnInfoListener = null; + } + + public void attachListeners(AbstractMediaPlayer mp) { + mp.setOnPreparedListener(mOnPreparedListener); + mp.setOnBufferingUpdateListener(mOnBufferingUpdateListener); + mp.setOnCompletionListener(mOnCompletionListener); + mp.setOnSeekCompleteListener(mOnSeekCompleteListener); + mp.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener); + mp.setOnErrorListener(mOnErrorListener); + mp.setOnInfoListener(mOnInfoListener); + } + + protected static final void notifyOnPrepared(SimpleMediaPlayer mp) { + if (mp != null && mp.mOnPreparedListener != null) + mp.mOnPreparedListener.onPrepared(mp); + } + + protected static final void notifyOnCompletion(SimpleMediaPlayer mp) { + if (mp != null && mp.mOnCompletionListener != null) + mp.mOnCompletionListener.onCompletion(mp); + } + + protected static final void notifyOnBufferingUpdate(SimpleMediaPlayer mp, + int percent) { + if (mp != null && mp.mOnBufferingUpdateListener != null) + mp.mOnBufferingUpdateListener.onBufferingUpdate(mp, percent); + } + + protected static final void notifyOnSeekComplete(SimpleMediaPlayer mp) { + if (mp != null && mp.mOnSeekCompleteListener != null) + mp.mOnSeekCompleteListener.onSeekComplete(mp); + } + + protected static final void notifyOnVideoSizeChanged(SimpleMediaPlayer mp, + int width, int height, int sarNum, int sarDen) { + if (mp != null && mp.mOnVideoSizeChangedListener != null) + mp.mOnVideoSizeChangedListener.onVideoSizeChanged(mp, width, + height, sarNum, sarDen); + } + + protected static final boolean notifyOnError(SimpleMediaPlayer mp, + int what, int extra) { + if (mp != null && mp.mOnErrorListener != null) + return mp.mOnErrorListener.onError(mp, what, extra); + return false; + } + + protected static final boolean notifyOnInfo(SimpleMediaPlayer mp, int what, + int extra) { + if (mp != null && mp.mOnInfoListener != null) + return mp.mOnInfoListener.onInfo(mp, what, extra); + return false; + } +} diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/AbstractMediaListPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/AbstractMediaListPlayer.java new file mode 100644 index 00000000..0490cfbe --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/AbstractMediaListPlayer.java @@ -0,0 +1,243 @@ +package tv.danmaku.ijk.media.player.list; + +import java.io.IOException; + +import tv.danmaku.ijk.media.player.AbstractMediaPlayer; +import tv.danmaku.ijk.media.player.DebugLog; +import tv.danmaku.ijk.media.player.DummyMediaPlayer; +import tv.danmaku.ijk.media.player.SimpleMediaPlayer; +import android.content.Context; +import android.view.Surface; +import android.view.SurfaceHolder; + +public abstract class AbstractMediaListPlayer extends SimpleMediaPlayer { + private static final String TAG = AbstractMediaListPlayer.class + .getSimpleName(); + private Context mContext; + + private SimpleMediaSegmentPlayer mItemPlayer; + private SimpleMediaSegmentPlayer mNextPlayer; + + private SurfaceHolder mSurfaceHolder; + private Surface mSurface; + private Integer mWakeMode; + private Boolean mScreenOnWhilePlaying; + private Integer mAudioStreamType; + private int mVideoWidth; + private int mVideoHeight; + + private MediaList mMediaList; + private boolean mPrepared; + + public AbstractMediaListPlayer(Context context, MediaList.Resolver resolver) { + mContext = context.getApplicationContext(); + mItemPlayer = new SimpleMediaSegmentPlayer(0, new DummyMediaPlayer()); + try { + mMediaList = resolver.getMediaList(); + } catch (ResolveException e) { + DebugLog.printStackTrace(e); + } + } + + protected abstract AbstractMediaPlayer onCreateMediaPlayer(); + + @Override + public void setDisplay(SurfaceHolder sh) { + mSurfaceHolder = sh; + mSurface = null; + + mItemPlayer.setDisplay(sh); + } + + @Override + public void setSurface(Surface surface) { + mSurfaceHolder = null; + mSurface = surface; + + mItemPlayer.setSurface(surface); + } + + @Override + public void setDataSource(String path) throws IOException, + IllegalArgumentException, SecurityException, IllegalStateException { + DebugLog.wfmt(TAG, "setDataSource has no effect %s", path); + } + + @Override + public void prepareAsync() throws IllegalStateException { + openPlayer(0); + } + + @Override + public void start() throws IllegalStateException { + mItemPlayer.start(); + } + + @Override + public void stop() throws IllegalStateException { + mItemPlayer.stop(); + } + + @Override + public void pause() throws IllegalStateException { + mItemPlayer.pause(); + } + + @Override + public void setWakeMode(Context context, int mode) { + mWakeMode = mode; + } + + @Override + public void setScreenOnWhilePlaying(boolean screenOn) { + mScreenOnWhilePlaying = screenOn; + } + + @Override + public int getVideoWidth() { + int newWidth = mItemPlayer.getVideoWidth(); + if (newWidth > 0) + mVideoWidth = newWidth; + + return mVideoWidth; + } + + @Override + public int getVideoHeight() { + int newHeight = mItemPlayer.getVideoHeight(); + if (newHeight > 0) + mVideoHeight = newHeight; + + return mVideoHeight; + } + + @Override + public boolean isPlaying() { + return mItemPlayer.isPlaying(); + } + + @Override + public void seekTo(long msec) throws IllegalStateException { + if (mMediaList == null) + return; + + MediaSegment item = mMediaList.getItemByTime(msec); + long relativePosition = item.getRelativeTime(msec); + if (mItemPlayer.isSameMediaItem(item)) { + mItemPlayer.seekTo(relativePosition); + } else if (mNextPlayer != null) { + mNextPlayer.setSeekOnPrepared(msec); + } else { + mItemPlayer.releaseToDummyPlayer(true, relativePosition); + openPlayer(item.mOrder, relativePosition); + } + } + + @Override + public long getCurrentPosition() { + return mItemPlayer.getAbsolutePosition(); + } + + @Override + public long getDuration() { + if (mMediaList == null) + return 0; + + return mMediaList.getTotalDuration(); + } + + @Override + public void release() { + mItemPlayer.release(); + mNextPlayer.release(); + } + + @Override + public void reset() { + mItemPlayer.reset(); + mNextPlayer.reset(); + } + + @Override + public void setAudioStreamType(int streamType) { + mAudioStreamType = streamType; + } + + private OnPreparedListener mOnItemPreparedListener = new AbstractMediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(AbstractMediaPlayer mp) { + onItemPrepared(); + } + }; + + private OnCompletionListener mOnItemCompletionListener = new AbstractMediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(AbstractMediaPlayer mp) { + onItemComplete(); + } + }; + + private void onItemPrepared() { + SimpleMediaSegmentPlayer prevPlayer = mItemPlayer; + mItemPlayer = mNextPlayer; + prevPlayer.release(); + mNextPlayer = null; + + if (!mPrepared) { + mPrepared = true; + notifyOnPrepared(this); + } else { + mItemPlayer.startOnPrepared(); + } + } + + private void onItemComplete() { + int order = mItemPlayer.getOrder(); + if (order >= mMediaList.size()) { + notifyOnCompletion(this); + } else { + mItemPlayer.releaseToDummyPlayer(true); + openPlayer(order + 1); + } + } + + private void openPlayer(int order) { + openPlayer(order, 0); + } + + private void openPlayer(int order, long seekOnPrepared) { + MediaSegment mediaItem = mMediaList.get(order); + openPlayer(mediaItem, seekOnPrepared); + } + + private void openPlayer(MediaSegment mediaItem, long seekOnPrepared) { + if (mNextPlayer != null) { + mNextPlayer.release(); + mNextPlayer = null; + } + mNextPlayer = new SimpleMediaSegmentPlayer(mediaItem.mOrder, + onCreateMediaPlayer()); + + if (mSurfaceHolder != null) + mNextPlayer.setDisplay(mSurfaceHolder); + else if (mSurface != null) + mNextPlayer.setSurface(mSurface); + + if (mWakeMode != null) + mNextPlayer.setWakeMode(mContext, mWakeMode); + + if (mScreenOnWhilePlaying != null) + mNextPlayer.setScreenOnWhilePlaying(mScreenOnWhilePlaying); + + if (mAudioStreamType != null) + mNextPlayer.setAudioStreamType(mAudioStreamType); + + super.attachListeners(mItemPlayer); + mNextPlayer.setOnPreparedListener(mOnItemPreparedListener); + mNextPlayer.setOnCompletionListener(mOnItemCompletionListener); + + mNextPlayer.setMediaSegment(mediaItem); + mNextPlayer.setSeekOnPrepared(seekOnPrepared); + mNextPlayer.prepareAsync(); + } +} diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/IjkMediaListPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/IjkMediaListPlayer.java new file mode 100644 index 00000000..d3603242 --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/IjkMediaListPlayer.java @@ -0,0 +1,17 @@ +package tv.danmaku.ijk.media.player.list; + +import tv.danmaku.ijk.media.player.AbstractMediaPlayer; +import tv.danmaku.ijk.media.player.IjkMediaPlayer; +import tv.danmaku.ijk.media.player.list.MediaList.Resolver; +import android.content.Context; + +public class IjkMediaListPlayer extends AbstractMediaListPlayer { + public IjkMediaListPlayer(Context context, Resolver resolver) { + super(context, resolver); + } + + @Override + protected AbstractMediaPlayer onCreateMediaPlayer() { + return new IjkMediaPlayer(); + } +} diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaList.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaList.java new file mode 100644 index 00000000..2bed9c96 --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaList.java @@ -0,0 +1,101 @@ +package tv.danmaku.ijk.media.player.list; + +import java.util.ArrayList; + +import android.content.Context; + +public final class MediaList { + private ArrayList mSegmentList = new ArrayList(); + + private long mDuration; + + public MediaList() { + } + + public MediaList(MediaSegment mediaSegment) { + add(mediaSegment); + } + + public void add(MediaSegment mediaSegment) { + mediaSegment.mOrder = mSegmentList.size(); + mediaSegment.mStartTime = mDuration; + mDuration += mediaSegment.mDuration; + mSegmentList.add(mediaSegment); + } + + public long getTotalDuration() { + return mDuration; + } + + public MediaSegment get(int index) { + return mSegmentList.get(index); + } + + public int size() { + return mSegmentList.size(); + } + + public void clear() { + mSegmentList.clear(); + mDuration = 0; + } + + public MediaSegment getItemByTime(long position) { + MediaSegment lowerItem = null; + for (MediaSegment item : mSegmentList) { + if (item.mStartTime > position) + break; + + lowerItem = item; + } + + return lowerItem; + } + + public static interface Resolver { + public abstract void clearCache(); + + public abstract void resolve(Context context); + + public abstract void resolveAsync(Context context); + + public abstract MediaList getMediaList() throws ResolveException; + + public abstract MediaSegment getMediaSegment(int segmentId) + throws ResolveException; + } + + public static class SimpleResolver implements Resolver { + private MediaList mMediaList; + + public SimpleResolver(MediaList mediaList) { + mMediaList = mediaList; + } + + @Override + public void clearCache() { + // do nothing + } + + @Override + public void resolve(Context context) { + // do nothing + } + + @Override + public void resolveAsync(Context context) { + // do nothing + } + + @Override + public MediaList getMediaList() throws ResolveException { + return mMediaList; + } + + @Override + public MediaSegment getMediaSegment(int segmentId) + throws ResolveException { + return mMediaList.mSegmentList.get(segmentId); + } + } +} diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaSegment.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaSegment.java new file mode 100644 index 00000000..5a09f732 --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/MediaSegment.java @@ -0,0 +1,33 @@ +package tv.danmaku.ijk.media.player.list; + +public final class MediaSegment { + public String mUrl; + public long mDuration; + public long mSize; + + public int mOrder; + public long mStartTime; + + public MediaSegment() { + } + + public MediaSegment(String simpleUrl) { + this(); + mUrl = simpleUrl; + } + + public MediaSegment(String simpleUrl, long duration) { + this(simpleUrl); + mDuration = duration; + } + + public long getEndTime() { + return mStartTime + mDuration; + } + + public long getRelativeTime(long absoluteTime) { + long relativeTime = absoluteTime - mStartTime; + relativeTime = Math.max(0, relativeTime); + return relativeTime; + } +} diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/ResolveException.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/ResolveException.java new file mode 100644 index 00000000..f4ce134c --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/ResolveException.java @@ -0,0 +1,17 @@ +package tv.danmaku.ijk.media.player.list; + +public class ResolveException extends Exception { + private static final long serialVersionUID = 3248193422630584719L; + + public ResolveException() { + super(); + } + + public ResolveException(String msg) { + super(msg); + } + + public ResolveException(Throwable cause) { + super(cause); + } +} diff --git a/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/SimpleMediaSegmentPlayer.java b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/SimpleMediaSegmentPlayer.java new file mode 100644 index 00000000..8539a140 --- /dev/null +++ b/android/ijkmediaplayer/src/tv/danmaku/ijk/media/player/list/SimpleMediaSegmentPlayer.java @@ -0,0 +1,269 @@ +package tv.danmaku.ijk.media.player.list; + +import java.io.IOException; + +import tv.danmaku.ijk.media.player.AbstractMediaPlayer; +import tv.danmaku.ijk.media.player.DummyMediaPlayer; +import android.content.Context; +import android.text.TextUtils; +import android.view.Surface; +import android.view.SurfaceHolder; + +public final class SimpleMediaSegmentPlayer extends AbstractMediaPlayer { + private int mOrder; + + private MediaSegment mMediaSegment = new MediaSegment(); + private AbstractMediaPlayer mMediaPlayer; + private DummyMediaPlayer mDummyPlayer = new DummyMediaPlayer(); + + private boolean mIsReleased; + private Long mSeekOnPrepared; + + public SimpleMediaSegmentPlayer(int order, AbstractMediaPlayer mediaPlayer) { + mOrder = order; + mMediaPlayer = mediaPlayer; + } + + public int getOrder() { + return mOrder; + } + + public void setSeekOnPrepared(long seekOnPrepared) { + mSeekOnPrepared = seekOnPrepared; + } + + public boolean hasDataSource() { + if (mMediaSegment == null || TextUtils.isEmpty(mMediaSegment.mUrl)) + return false; + + return true; + } + + public boolean isSameMediaItem(MediaSegment mediaItem) { + if (!hasDataSource()) + return false; + + if (mMediaSegment.mOrder != mediaItem.mOrder) + return false; + + return true; + } + + public void setMediaSegment(MediaSegment mediaSegment) { + mOrder = mediaSegment.mOrder; + mMediaSegment = mediaSegment; + mDummyPlayer.mDuration = mediaSegment.mDuration; + } + + public void setDisplay(SurfaceHolder sh) { + mMediaPlayer.setDisplay(sh); + } + + public void setSurface(Surface surface) { + mMediaPlayer.setSurface(surface); + } + + public void seekToAbsoluteTime(long msec) throws IllegalStateException { + long relativeTime = msec - mMediaSegment.mStartTime; + relativeTime = Math.max(0, relativeTime); + + mMediaPlayer.seekTo(relativeTime); + } + + public long getAbsolutePosition() { + long absolutePosition = mMediaSegment.mStartTime + + mMediaPlayer.getCurrentPosition(); + return absolutePosition; + } + + public boolean isReleased() { + return mIsReleased; + } + + public void releaseToDummyPlayer(boolean pretendPlaying, long fakePosition) { + mDummyPlayer.mCurrentPosition = fakePosition; + mDummyPlayer.mIsPlaying = pretendPlaying; + + AbstractMediaPlayer prevMediaPlayer = mMediaPlayer; + mMediaPlayer = mDummyPlayer; + prevMediaPlayer.release(); + } + + public void releaseToDummyPlayer(boolean pretendPlaying) { + releaseToDummyPlayer(pretendPlaying, getDuration()); + } + + public void startOnPrepared() { + retrieveMedioInfo(); + mDummyPlayer.mIsPlaying = true; + + start(); + if (mSeekOnPrepared != null) { + mDummyPlayer.mCurrentPosition = mSeekOnPrepared; + seekTo(mSeekOnPrepared); + mSeekOnPrepared = null; + } else { + mDummyPlayer.mCurrentPosition = 0; + } + } + + private void retrieveMedioInfo() { + int videoWidth = mMediaPlayer.getVideoWidth(); + if (videoWidth > 0) + mDummyPlayer.mVideoWidth = videoWidth; + + int videoHeight = mMediaPlayer.getVideoHeight(); + if (videoHeight > 0) + mDummyPlayer.mVideoHeight = videoHeight; + + long duration = mMediaPlayer.getDuration(); + if (duration > 0) + mDummyPlayer.mDuration = duration; + } + + @Override + public void setDataSource(String path) throws IOException, + IllegalArgumentException, SecurityException, IllegalStateException { + mMediaSegment = new MediaSegment(path); + } + + @Override + public void prepareAsync() throws IllegalStateException { + try { + if (hasDataSource()) { + mMediaPlayer.setDataSource(mMediaSegment.mUrl); + mMediaPlayer.prepareAsync(); + } else + throw new IllegalStateException("null data source"); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e); + } catch (SecurityException e) { + throw new IllegalStateException(e); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public void start() throws IllegalStateException { + mMediaPlayer.start(); + } + + @Override + public void stop() throws IllegalStateException { + mMediaPlayer.stop(); + } + + @Override + public void pause() throws IllegalStateException { + mMediaPlayer.pause(); + } + + @Override + public void setWakeMode(Context context, int mode) { + mMediaPlayer.setWakeMode(context, mode); + } + + @Override + public void setScreenOnWhilePlaying(boolean screenOn) { + mMediaPlayer.setScreenOnWhilePlaying(screenOn); + } + + @Override + public int getVideoWidth() { + int videoWidth = mMediaPlayer.getVideoWidth(); + if (videoWidth > 0) + mDummyPlayer.mVideoWidth = videoWidth; + return videoWidth; + } + + @Override + public int getVideoHeight() { + int videoHeight = mMediaPlayer.getVideoHeight(); + if (videoHeight > 0) + mDummyPlayer.mVideoHeight = videoHeight; + return mMediaPlayer.getVideoHeight(); + } + + @Override + public boolean isPlaying() { + return mMediaPlayer.isPlaying(); + } + + @Override + public void seekTo(long msec) throws IllegalStateException { + mMediaPlayer.seekTo(msec); + } + + @Override + public long getCurrentPosition() { + return mMediaPlayer.getCurrentPosition(); + } + + @Override + public long getDuration() { + if (mMediaSegment.mDuration > 0) { + return mMediaSegment.mDuration; + } + + long duration = mMediaPlayer.getDuration(); + if (duration > 0) + mDummyPlayer.mDuration = duration; + + return duration; + } + + @Override + public void release() { + mIsReleased = true; + mMediaPlayer.release(); + } + + @Override + public void reset() { + mOrder = -1; + mMediaSegment = null; + mMediaPlayer.reset(); + } + + @Override + public void setAudioStreamType(int streamtype) { + mMediaPlayer.setAudioStreamType(streamtype); + } + + @Override + public void setOnPreparedListener(OnPreparedListener listener) { + mMediaPlayer.setOnPreparedListener(listener); + } + + @Override + public void setOnCompletionListener(OnCompletionListener listener) { + mMediaPlayer.setOnCompletionListener(listener); + } + + @Override + public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) { + mMediaPlayer.setOnBufferingUpdateListener(listener); + } + + @Override + public void setOnSeekCompleteListener(OnSeekCompleteListener listener) { + mMediaPlayer.setOnSeekCompleteListener(listener); + } + + @Override + public void setOnVideoSizeChangedListener( + OnVideoSizeChangedListener listener) { + mMediaPlayer.setOnVideoSizeChangedListener(listener); + } + + @Override + public void setOnErrorListener(OnErrorListener listener) { + mMediaPlayer.setOnErrorListener(listener); + } + + @Override + public void setOnInfoListener(OnInfoListener listener) { + mMediaPlayer.setOnInfoListener(listener); + } +} -- GitLab