Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
180/360/3D video support (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
MortimerGoro authored Nov 10, 2018
1 parent 5eeebbe commit eaa4fc5
Show file tree
Hide file tree
Showing 74 changed files with 2,630 additions and 90 deletions.
1 change: 1 addition & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ add_library( # Sets the name of the library.
src/main/cpp/JNIUtil.cpp
src/main/cpp/SplashAnimation.cpp
src/main/cpp/VRBrowser.cpp
src/main/cpp/VRVideo.cpp
src/main/cpp/Widget.cpp
src/main/cpp/WidgetPlacement.cpp
src/main/cpp/WidgetResizer.cpp
Expand Down
25 changes: 25 additions & 0 deletions app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.mozilla.vrbrowser.ui.widgets.RootWidget;
import org.mozilla.vrbrowser.ui.widgets.TopBarWidget;
import org.mozilla.vrbrowser.ui.widgets.TrayWidget;
import org.mozilla.vrbrowser.ui.widgets.VideoProjectionMenuWidget;
import org.mozilla.vrbrowser.ui.widgets.Widget;
import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate;
import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement;
Expand Down Expand Up @@ -806,6 +807,11 @@ public void setTrayVisible(boolean visible) {
}
}

@Override
public void setControllersVisible(final boolean aVisible) {
queueRunnable(() -> setControllersVisibleNative(aVisible));
}

@Override
public void setBrowserSize(float targetWidth, float targetHeight) {
mBrowserWidget.setBrowserSize(targetWidth, targetHeight, 1.0f);
Expand Down Expand Up @@ -849,6 +855,21 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in
}
}

@Override
public void showVRVideo(final int aWindowHandle, final @VideoProjectionMenuWidget.VideoProjectionFlags int aVideoProjection) {
queueRunnable(() -> showVRVideoNative(aWindowHandle, aVideoProjection));
}

@Override
public void hideVRVideo() {
queueRunnable(this::hideVRVideoNative);
}

@Override
public void resetUIYaw() {
queueRunnable(this::resetUIYawNative);
}

private native void addWidgetNative(int aHandle, WidgetPlacement aPlacement);
private native void updateWidgetNative(int aHandle, WidgetPlacement aPlacement);
private native void removeWidgetNative(int aHandle);
Expand All @@ -860,4 +881,8 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in
private native void workaroundGeckoSigAction();
private native void updateEnvironmentNative();
private native void updatePointerColorNative();
private native void showVRVideoNative(int aWindowHandler, int aVideoProjection);
private native void hideVRVideoNative();
private native void resetUIYawNative();
private native void setControllersVisibleNative(boolean aVisible);
}
198 changes: 198 additions & 0 deletions app/src/common/shared/org/mozilla/vrbrowser/browser/Media.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package org.mozilla.vrbrowser.browser;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import org.mozilla.geckoview.MediaElement;

public class Media implements MediaElement.Delegate {
private static final String LOGTAG = "VRB";
private boolean mIsFullscreen = false;
private double mCurrentTime = 0.0f;
private MediaElement.Metadata mMetaData;
private double mPlaybackRate = 1.0f;
private int mReadyState = MediaElement.MEDIA_READY_STATE_HAVE_NOTHING;
private boolean mPlaying = false;
private boolean mEnded = false;
private double mVolume = 1.0f;
private boolean mIsMuted = false;
private boolean mIsUnloaded = false;
private org.mozilla.geckoview.MediaElement mMedia;
private MediaElement.Delegate mDelegate;

public Media(@NonNull MediaElement aMediaElement) {
mMedia = aMediaElement;
aMediaElement.setDelegate(this);
}

public void setDelegate(@Nullable MediaElement.Delegate aDelegate) {
mDelegate = aDelegate;
}

public double getDuration() {
if (mMetaData != null) {
return mMetaData.duration;
}
return -1.0f;
}

public boolean isFullscreen() {
return mIsFullscreen;
}

public double getCurrentTime() {
return mCurrentTime;
}

public MediaElement.Metadata getMetaData() {
return mMetaData;
}

public double getPlaybackRate() {
return mPlaybackRate;
}

public int getReadyState() {
return mReadyState;
}

public boolean isPlaying() {
return mPlaying;
}

public boolean isEnded() {
return mEnded;
}

public double getVolume() {
return mVolume;
}

public boolean isMuted() {
return mIsMuted;
}

public boolean isUnloaded() {
return mIsUnloaded;
}

public MediaElement getMediaElement() {
return mMedia;
}

public void seek(double aTime) {
mMedia.seek(aTime);
}

public void play() {
mMedia.play();
}

public void pause() {
mMedia.pause();
}

public void setVolume(double aVolume) {
mMedia.setVolume(aVolume);
}

public void setMuted(boolean aIsMuted) {
mMedia.setMuted(aIsMuted);
}

public void unload() {
mIsUnloaded = true;
mDelegate = null;
}

public int getWidth() {
return mMetaData != null ? (int)mMetaData.width : 0;
}

public int getHeight() {
return mMetaData != null ? (int)mMetaData.height : 0;
}

// Media Element delegate
@Override
public void onPlaybackStateChange(MediaElement mediaElement, int playbackState) {
if (playbackState == MediaElement.MEDIA_STATE_PLAY) {
mPlaying = true;
} else if (playbackState == MediaElement.MEDIA_STATE_PAUSE) {
mPlaying = false;
} else if (playbackState == MediaElement.MEDIA_STATE_ENDED) {
mEnded = true;
}
if (mDelegate != null) {
mDelegate.onPlaybackStateChange(mediaElement, playbackState);
}
}

@Override
public void onReadyStateChange(MediaElement mediaElement, int readyState) {
mReadyState = readyState;
if (mDelegate != null) {
mDelegate.onReadyStateChange(mediaElement, readyState);
}
}

@Override
public void onMetadataChange(MediaElement mediaElement, MediaElement.Metadata metaData) {
mMetaData = metaData;
if (mDelegate != null) {
mDelegate.onMetadataChange(mediaElement, metaData);
}
}

@Override
public void onLoadProgress(MediaElement mediaElement, MediaElement.LoadProgressInfo progressInfo) {
if (mDelegate != null) {
mDelegate.onLoadProgress(mediaElement, progressInfo);
}
}

@Override
public void onVolumeChange(MediaElement mediaElement, double volume, boolean muted) {
mVolume = volume;
mIsMuted = muted;
if (mDelegate != null) {
mDelegate.onVolumeChange(mediaElement, volume, muted);
}
}

@Override
public void onTimeChange(MediaElement mediaElement, double time) {
mCurrentTime = time;
double duration = getDuration();
if (duration <= 0 || mCurrentTime < getDuration()) {
mEnded = false;
}
if (mDelegate != null) {
mDelegate.onTimeChange(mediaElement, time);
}
}

@Override
public void onPlaybackRateChange(MediaElement mediaElement, double rate) {
mPlaybackRate = rate;
if (mDelegate != null) {
mDelegate.onPlaybackRateChange(mediaElement, rate);
}
}

@Override
public void onFullscreenChange(MediaElement mediaElement, boolean fullscreen) {
mIsFullscreen = fullscreen;
if (mDelegate != null) {
mDelegate.onFullscreenChange(mediaElement, fullscreen);
}
}

@Override
public void onError(MediaElement mediaElement, int code) {
if (mDelegate != null) {
mDelegate.onError(mediaElement, code);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoProfile;
import org.mozilla.geckoview.AllowOrDeny;
import org.mozilla.geckoview.MediaElement;
import org.mozilla.geckoview.GeckoResult;
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoRuntimeSettings;
Expand Down Expand Up @@ -55,7 +56,7 @@

public class SessionStore implements GeckoSession.NavigationDelegate, GeckoSession.ProgressDelegate,
GeckoSession.ContentDelegate, GeckoSession.TextInputDelegate, GeckoSession.TrackingProtectionDelegate,
GeckoSession.PromptDelegate, SharedPreferences.OnSharedPreferenceChangeListener {
GeckoSession.PromptDelegate, GeckoSession.MediaDelegate, SharedPreferences.OnSharedPreferenceChangeListener {

private static SessionStore mInstance;
private static final String LOGTAG = "VRB";
Expand Down Expand Up @@ -103,6 +104,7 @@ class State {
boolean mFullScreen;
GeckoSession mSession;
SessionSettings mSettings;
ArrayList<Media> mMediaElements = new ArrayList<>();
}

private GeckoRuntime mRuntime;
Expand Down Expand Up @@ -328,6 +330,7 @@ int createSession(SessionSettings aSettings) {
state.mSession.getTextInput().setDelegate(this);
state.mSession.setPermissionDelegate(mPermissionDelegate);
state.mSession.setTrackingProtectionDelegate(this);
state.mSession.setMediaDelegate(this);
for (SessionChangeListener listener: mSessionChangeListeners) {
listener.onNewSession(state.mSession, result);
}
Expand All @@ -345,6 +348,7 @@ public void removeSession(int aSessionId) {
session.setPromptDelegate(null);
session.setPermissionDelegate(null);
session.setTrackingProtectionDelegate(null);
session.setMediaDelegate(null);
mSessions.remove(aSessionId);
for (SessionChangeListener listener: mSessionChangeListeners) {
listener.onRemoveSession(session, aSessionId);
Expand Down Expand Up @@ -499,6 +503,26 @@ public String getPreviousUri() {
return result;
}

public Media getFullScreenVideo() {
Media result = null;
if (mCurrentSession != null) {
State state = mSessions.get(mCurrentSession.hashCode());
if (state == null) {
return result;
}
if (state.mMediaElements.size() > 0) {
return state.mMediaElements.get(state.mMediaElements.size() - 1);
}
for (Media media: state.mMediaElements) {
if (media.isFullscreen()) {
result = media;
break;
}
}
}
return result;
}

public boolean isInputActive(int aSessionId) {
SessionStore.State state = mSessions.get(aSessionId);
if (state != null) {
Expand Down Expand Up @@ -1190,8 +1214,33 @@ public GeckoResult<AllowOrDeny> onPopupRequest(final GeckoSession session, final
return GeckoResult.fromValue(AllowOrDeny.DENY);
}

// SharedPreferences.OnSharedPreferenceChangeListener
// MediaDelegate
@Override
public void onMediaAdd(GeckoSession session, MediaElement element) {
SessionStore.State state = mSessions.get(getSessionId(session));
if (state == null) {
return;
}
Media media = new Media(element);
state.mMediaElements.add(media);
}

@Override
public void onMediaRemove(GeckoSession session, MediaElement element) {
SessionStore.State state = mSessions.get(getSessionId(session));
if (state == null) {
return;
}
for (int i = 0; i < state.mMediaElements.size(); ++i) {
Media media = state.mMediaElements.get(i);
if (media.getMediaElement() == element) {
media.unload();
return;
}
}
}

// SharedPreferences.OnSharedPreferenceChangeListener
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (mContext != null) {
Expand Down
Loading

0 comments on commit eaa4fc5

Please sign in to comment.