зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1382151 - Pause Exoplayer when mediaelement is paused. r=kikuo
MozReview-Commit-ID: 5MDBBP5vfpa --HG-- extra : rebase_source : 9981585791cd359296ac7fef0fe0d7e900af6c61
This commit is contained in:
Родитель
4e4645bdba
Коммит
4843d195fb
|
@ -93,4 +93,26 @@ HLSDecoder::Load(MediaResource*)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
HLSDecoder::Play()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
HLS_DEBUG("HLSDecoder", "MediaElement called Play");
|
||||||
|
auto resourceWrapper =
|
||||||
|
static_cast<HLSResource*>(GetResource())->GetResourceWrapper();
|
||||||
|
resourceWrapper->Play();
|
||||||
|
return MediaDecoder::Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HLSDecoder::Pause()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
HLS_DEBUG("HLSDecoder", "MediaElement called Pause");
|
||||||
|
auto resourceWrapper =
|
||||||
|
static_cast<HLSResource*>(GetResource())->GetResourceWrapper();
|
||||||
|
resourceWrapper->Pause();
|
||||||
|
return MediaDecoder::Pause();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -37,6 +37,10 @@ public:
|
||||||
bool aIsPrivateBrowsing,
|
bool aIsPrivateBrowsing,
|
||||||
nsIStreamListener**) override;
|
nsIStreamListener**) override;
|
||||||
nsresult Load(MediaResource*) override;
|
nsresult Load(MediaResource*) override;
|
||||||
|
|
||||||
|
nsresult Play() override;
|
||||||
|
|
||||||
|
void Pause() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -88,5 +88,9 @@ public interface BaseHlsPlayer {
|
||||||
|
|
||||||
public void resume();
|
public void resume();
|
||||||
|
|
||||||
|
public void play();
|
||||||
|
|
||||||
|
public void pause();
|
||||||
|
|
||||||
public void release();
|
public void release();
|
||||||
}
|
}
|
|
@ -79,6 +79,22 @@ public class GeckoHLSResourceWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WrapForJNI(calledFrom = "gecko")
|
||||||
|
public void play() {
|
||||||
|
if (DEBUG) Log.d(LOGTAG, "GeckoHLSResourceWrapper mediaelement played");
|
||||||
|
if (mPlayer != null) {
|
||||||
|
mPlayer.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@WrapForJNI(calledFrom = "gecko")
|
||||||
|
public void pause() {
|
||||||
|
if (DEBUG) Log.d(LOGTAG, "GeckoHLSResourceWrapper mediaelement paused");
|
||||||
|
if (mPlayer != null) {
|
||||||
|
mPlayer.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void assertTrue(boolean condition) {
|
private static void assertTrue(boolean condition) {
|
||||||
if (DEBUG && !condition) {
|
if (DEBUG && !condition) {
|
||||||
throw new AssertionError("Expected condition to be true");
|
throw new AssertionError("Expected condition to be true");
|
||||||
|
|
|
@ -60,7 +60,8 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||||
* mPlayerId is a token used for Gecko media pipeline to obtain corresponding player.
|
* mPlayerId is a token used for Gecko media pipeline to obtain corresponding player.
|
||||||
*/
|
*/
|
||||||
private final int mPlayerId;
|
private final int mPlayerId;
|
||||||
private volatile boolean mSuspended = false;
|
private boolean mExoplayerSuspended = false;
|
||||||
|
private boolean mMediaElementSuspended = false;
|
||||||
private DataSource.Factory mMediaDataSourceFactory;
|
private DataSource.Factory mMediaDataSourceFactory;
|
||||||
|
|
||||||
private Handler mMainHandler;
|
private Handler mMainHandler;
|
||||||
|
@ -312,6 +313,9 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||||
public synchronized void onLoadingChanged(boolean isLoading) {
|
public synchronized void onLoadingChanged(boolean isLoading) {
|
||||||
if (DEBUG) { Log.d(LOGTAG, "loading [" + isLoading + "]"); }
|
if (DEBUG) { Log.d(LOGTAG, "loading [" + isLoading + "]"); }
|
||||||
if (!isLoading) {
|
if (!isLoading) {
|
||||||
|
if (mMediaElementSuspended) {
|
||||||
|
suspendExoplayer();
|
||||||
|
}
|
||||||
// To update buffered position.
|
// To update buffered position.
|
||||||
mComponentEventDispatcher.onDataArrived(C.TRACK_TYPE_DEFAULT);
|
mComponentEventDispatcher.onDataArrived(C.TRACK_TYPE_DEFAULT);
|
||||||
}
|
}
|
||||||
|
@ -321,8 +325,8 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void onPlayerStateChanged(boolean playWhenReady, int state) {
|
public synchronized void onPlayerStateChanged(boolean playWhenReady, int state) {
|
||||||
if (DEBUG) { Log.d(LOGTAG, "state [" + playWhenReady + ", " + getStateString(state) + "]"); }
|
if (DEBUG) { Log.d(LOGTAG, "state [" + playWhenReady + ", " + getStateString(state) + "]"); }
|
||||||
if (state == ExoPlayer.STATE_READY && !mSuspended) {
|
if (state == ExoPlayer.STATE_READY && !mExoplayerSuspended && !mMediaElementSuspended) {
|
||||||
mPlayer.setPlayWhenReady(true);
|
resumeExoplayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,6 +683,12 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||||
// Called on HLSDemuxer's TaskQueue
|
// Called on HLSDemuxer's TaskQueue
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean seek(long positionUs) {
|
public synchronized boolean seek(long positionUs) {
|
||||||
|
// Need to temporarily resume Exoplayer to download the chunks for getting the demuxed
|
||||||
|
// keyframe sample when HTMLMediaElement is paused. Suspend Exoplayer when collecting enough
|
||||||
|
// samples in onLoadingChanged.
|
||||||
|
if (mExoplayerSuspended) {
|
||||||
|
resumeExoplayer();
|
||||||
|
}
|
||||||
// positionUs : microseconds.
|
// positionUs : microseconds.
|
||||||
// NOTE : 1) It's not possible to seek media by tracktype via ExoPlayer Interface.
|
// NOTE : 1) It's not possible to seek media by tracktype via ExoPlayer Interface.
|
||||||
// 2) positionUs is samples PTS from MFR, we need to re-adjust it
|
// 2) positionUs is samples PTS from MFR, we need to re-adjust it
|
||||||
|
@ -712,7 +722,7 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||||
|
|
||||||
// Called on HLSDemuxer's TaskQueue
|
// Called on HLSDemuxer's TaskQueue
|
||||||
@Override
|
@Override
|
||||||
public long getNextKeyFrameTime() {
|
public synchronized long getNextKeyFrameTime() {
|
||||||
long nextKeyFrameTime = mVRenderer != null
|
long nextKeyFrameTime = mVRenderer != null
|
||||||
? mVRenderer.getNextKeyFrameTime()
|
? mVRenderer.getNextKeyFrameTime()
|
||||||
: Long.MAX_VALUE;
|
: Long.MAX_VALUE;
|
||||||
|
@ -722,29 +732,68 @@ public class GeckoHlsPlayer implements BaseHlsPlayer, ExoPlayer.EventListener {
|
||||||
// Called on Gecko's main thread.
|
// Called on Gecko's main thread.
|
||||||
@Override
|
@Override
|
||||||
public synchronized void suspend() {
|
public synchronized void suspend() {
|
||||||
if (mSuspended) {
|
if (mExoplayerSuspended) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (DEBUG) { Log.d(LOGTAG, "suspend player id : " + mPlayerId); }
|
if (mMediaElementSuspended) {
|
||||||
mSuspended = true;
|
if (DEBUG) {
|
||||||
if (mPlayer != null) {
|
Log.d(LOGTAG, "suspend player id : " + mPlayerId);
|
||||||
mPlayer.setPlayWhenReady(false);
|
}
|
||||||
|
suspendExoplayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called on Gecko's main thread.
|
// Called on Gecko's main thread.
|
||||||
@Override
|
@Override
|
||||||
public synchronized void resume() {
|
public synchronized void resume() {
|
||||||
if (!mSuspended) {
|
if (!mExoplayerSuspended) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (DEBUG) { Log.d(LOGTAG, "resume player id : " + mPlayerId); }
|
if (!mMediaElementSuspended) {
|
||||||
mSuspended = false;
|
if (DEBUG) {
|
||||||
if (mPlayer != null) {
|
Log.d(LOGTAG, "resume player id : " + mPlayerId);
|
||||||
mPlayer.setPlayWhenReady(true);
|
}
|
||||||
|
resumeExoplayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called on Gecko's main thread.
|
||||||
|
@Override
|
||||||
|
public synchronized void play() {
|
||||||
|
if (!mMediaElementSuspended) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) { Log.d(LOGTAG, "mediaElement played."); }
|
||||||
|
mMediaElementSuspended = false;
|
||||||
|
resumeExoplayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called on Gecko's main thread.
|
||||||
|
@Override
|
||||||
|
public synchronized void pause() {
|
||||||
|
if (mMediaElementSuspended) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DEBUG) { Log.d(LOGTAG, "mediaElement paused."); }
|
||||||
|
mMediaElementSuspended = true;
|
||||||
|
suspendExoplayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void suspendExoplayer() {
|
||||||
|
if (mPlayer != null) {
|
||||||
|
mExoplayerSuspended = true;
|
||||||
|
if (DEBUG) { Log.d(LOGTAG, "suspend Exoplayer"); }
|
||||||
|
mPlayer.setPlayWhenReady(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void resumeExoplayer() {
|
||||||
|
if (mPlayer != null) {
|
||||||
|
mExoplayerSuspended = false;
|
||||||
|
if (DEBUG) { Log.d(LOGTAG, "resume Exoplayer"); }
|
||||||
|
mPlayer.setPlayWhenReady(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Called on Gecko's main thread, when HLSDemuxer or HLSResource destructs.
|
// Called on Gecko's main thread, when HLSDemuxer or HLSResource destructs.
|
||||||
@Override
|
@Override
|
||||||
public synchronized void release() {
|
public synchronized void release() {
|
||||||
|
|
|
@ -2050,6 +2050,22 @@ auto GeckoHLSResourceWrapper::GetPlayerId() const -> int32_t
|
||||||
return mozilla::jni::Method<GetPlayerId_t>::Call(GeckoHLSResourceWrapper::mCtx, nullptr);
|
return mozilla::jni::Method<GetPlayerId_t>::Call(GeckoHLSResourceWrapper::mCtx, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr char GeckoHLSResourceWrapper::Pause_t::name[];
|
||||||
|
constexpr char GeckoHLSResourceWrapper::Pause_t::signature[];
|
||||||
|
|
||||||
|
auto GeckoHLSResourceWrapper::Pause() const -> void
|
||||||
|
{
|
||||||
|
return mozilla::jni::Method<Pause_t>::Call(GeckoHLSResourceWrapper::mCtx, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr char GeckoHLSResourceWrapper::Play_t::name[];
|
||||||
|
constexpr char GeckoHLSResourceWrapper::Play_t::signature[];
|
||||||
|
|
||||||
|
auto GeckoHLSResourceWrapper::Play() const -> void
|
||||||
|
{
|
||||||
|
return mozilla::jni::Method<Play_t>::Call(GeckoHLSResourceWrapper::mCtx, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
constexpr char GeckoHLSResourceWrapper::Resume_t::name[];
|
constexpr char GeckoHLSResourceWrapper::Resume_t::name[];
|
||||||
constexpr char GeckoHLSResourceWrapper::Resume_t::signature[];
|
constexpr char GeckoHLSResourceWrapper::Resume_t::signature[];
|
||||||
|
|
||||||
|
|
|
@ -5879,6 +5879,44 @@ public:
|
||||||
|
|
||||||
auto GetPlayerId() const -> int32_t;
|
auto GetPlayerId() const -> int32_t;
|
||||||
|
|
||||||
|
struct Pause_t {
|
||||||
|
typedef GeckoHLSResourceWrapper Owner;
|
||||||
|
typedef void ReturnType;
|
||||||
|
typedef void SetterType;
|
||||||
|
typedef mozilla::jni::Args<> Args;
|
||||||
|
static constexpr char name[] = "pause";
|
||||||
|
static constexpr char signature[] =
|
||||||
|
"()V";
|
||||||
|
static const bool isStatic = false;
|
||||||
|
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||||
|
mozilla::jni::ExceptionMode::ABORT;
|
||||||
|
static const mozilla::jni::CallingThread callingThread =
|
||||||
|
mozilla::jni::CallingThread::GECKO;
|
||||||
|
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||||
|
mozilla::jni::DispatchTarget::CURRENT;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto Pause() const -> void;
|
||||||
|
|
||||||
|
struct Play_t {
|
||||||
|
typedef GeckoHLSResourceWrapper Owner;
|
||||||
|
typedef void ReturnType;
|
||||||
|
typedef void SetterType;
|
||||||
|
typedef mozilla::jni::Args<> Args;
|
||||||
|
static constexpr char name[] = "play";
|
||||||
|
static constexpr char signature[] =
|
||||||
|
"()V";
|
||||||
|
static const bool isStatic = false;
|
||||||
|
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||||
|
mozilla::jni::ExceptionMode::ABORT;
|
||||||
|
static const mozilla::jni::CallingThread callingThread =
|
||||||
|
mozilla::jni::CallingThread::GECKO;
|
||||||
|
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||||
|
mozilla::jni::DispatchTarget::CURRENT;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto Play() const -> void;
|
||||||
|
|
||||||
struct Resume_t {
|
struct Resume_t {
|
||||||
typedef GeckoHLSResourceWrapper Owner;
|
typedef GeckoHLSResourceWrapper Owner;
|
||||||
typedef void ReturnType;
|
typedef void ReturnType;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче