mirror of
https://github.com/samsonjs/media.git
synced 2026-04-14 12:45:47 +00:00
Add 360 video samples to the demo app
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=206747144
This commit is contained in:
parent
9ec14d1ada
commit
02e9972630
7 changed files with 89 additions and 24 deletions
|
|
@ -589,5 +589,20 @@
|
|||
"abr_algorithm": "random"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "360",
|
||||
"samples": [
|
||||
{
|
||||
"name": "Congo (360 top-bottom stereo)",
|
||||
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/360/congo.mp4",
|
||||
"spherical_stereo_mode": "top_bottom"
|
||||
},
|
||||
{
|
||||
"name": "Iceland (360 top-bottom stereo ts)",
|
||||
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/360/iceland0.ts",
|
||||
"spherical_stereo_mode": "top_bottom"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ import com.google.android.exoplayer2.ui.DebugTextViewHelper;
|
|||
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||
import com.google.android.exoplayer2.ui.PlayerView;
|
||||
import com.google.android.exoplayer2.ui.TrackSelectionView;
|
||||
import com.google.android.exoplayer2.ui.spherical.SphericalSurfaceView;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
||||
|
|
@ -109,6 +110,11 @@ public class PlayerActivity extends Activity
|
|||
private static final String ABR_ALGORITHM_DEFAULT = "default";
|
||||
private static final String ABR_ALGORITHM_RANDOM = "random";
|
||||
|
||||
public static final String SPHERICAL_STEREO_MODE_EXTRA = "spherical_stereo_mode";
|
||||
public static final String SPHERICAL_STEREO_MODE_MONO = "mono";
|
||||
public static final String SPHERICAL_STEREO_MODE_TOP_BOTTOM = "top_bottom";
|
||||
public static final String SPHERICAL_STEREO_MODE_LEFT_RIGHT = "left_right";
|
||||
|
||||
// For backwards compatibility only.
|
||||
private static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
|
||||
|
||||
|
|
@ -151,6 +157,10 @@ public class PlayerActivity extends Activity
|
|||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
String sphericalStereoMode = getIntent().getStringExtra(SPHERICAL_STEREO_MODE_EXTRA);
|
||||
if (sphericalStereoMode != null) {
|
||||
setTheme(R.style.PlayerTheme_Spherical);
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
dataSourceFactory = buildDataSourceFactory();
|
||||
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
|
||||
|
|
@ -167,6 +177,21 @@ public class PlayerActivity extends Activity
|
|||
playerView.setControllerVisibilityListener(this);
|
||||
playerView.setErrorMessageProvider(new PlayerErrorMessageProvider());
|
||||
playerView.requestFocus();
|
||||
if (sphericalStereoMode != null) {
|
||||
int stereoMode;
|
||||
if (SPHERICAL_STEREO_MODE_MONO.equals(sphericalStereoMode)) {
|
||||
stereoMode = C.STEREO_MODE_MONO;
|
||||
} else if (SPHERICAL_STEREO_MODE_TOP_BOTTOM.equals(sphericalStereoMode)) {
|
||||
stereoMode = C.STEREO_MODE_TOP_BOTTOM;
|
||||
} else if (SPHERICAL_STEREO_MODE_LEFT_RIGHT.equals(sphericalStereoMode)) {
|
||||
stereoMode = C.STEREO_MODE_LEFT_RIGHT;
|
||||
} else {
|
||||
showToast(R.string.error_unrecognized_stereo_mode);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
((SphericalSurfaceView) playerView.getVideoSurfaceView()).setStereoMode(stereoMode);
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
trackSelectorParameters = savedInstanceState.getParcelable(KEY_TRACK_SELECTOR_PARAMETERS);
|
||||
|
|
|
|||
|
|
@ -249,6 +249,7 @@ public class SampleChooserActivity extends Activity
|
|||
ArrayList<UriSample> playlistSamples = null;
|
||||
String adTagUri = null;
|
||||
String abrAlgorithm = null;
|
||||
String sphericalStereoMode = null;
|
||||
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
|
|
@ -309,6 +310,11 @@ public class SampleChooserActivity extends Activity
|
|||
!insidePlaylist, "Invalid attribute on nested item: abr_algorithm");
|
||||
abrAlgorithm = reader.nextString();
|
||||
break;
|
||||
case "spherical_stereo_mode":
|
||||
Assertions.checkState(
|
||||
!insidePlaylist, "Invalid attribute on nested item: spherical_stereo_mode");
|
||||
sphericalStereoMode = reader.nextString();
|
||||
break;
|
||||
default:
|
||||
throw new ParserException("Unsupported attribute name: " + name);
|
||||
}
|
||||
|
|
@ -325,7 +331,14 @@ public class SampleChooserActivity extends Activity
|
|||
sampleName, preferExtensionDecoders, abrAlgorithm, drmInfo, playlistSamplesArray);
|
||||
} else {
|
||||
return new UriSample(
|
||||
sampleName, preferExtensionDecoders, abrAlgorithm, drmInfo, uri, extension, adTagUri);
|
||||
sampleName,
|
||||
preferExtensionDecoders,
|
||||
abrAlgorithm,
|
||||
drmInfo,
|
||||
uri,
|
||||
extension,
|
||||
adTagUri,
|
||||
sphericalStereoMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -512,6 +525,7 @@ public class SampleChooserActivity extends Activity
|
|||
public final Uri uri;
|
||||
public final String extension;
|
||||
public final String adTagUri;
|
||||
public final String sphericalStereoMode;
|
||||
|
||||
public UriSample(
|
||||
String name,
|
||||
|
|
@ -520,11 +534,13 @@ public class SampleChooserActivity extends Activity
|
|||
DrmInfo drmInfo,
|
||||
Uri uri,
|
||||
String extension,
|
||||
String adTagUri) {
|
||||
String adTagUri,
|
||||
String sphericalStereoMode) {
|
||||
super(name, preferExtensionDecoders, abrAlgorithm, drmInfo);
|
||||
this.uri = uri;
|
||||
this.extension = extension;
|
||||
this.adTagUri = adTagUri;
|
||||
this.sphericalStereoMode = sphericalStereoMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -533,6 +549,7 @@ public class SampleChooserActivity extends Activity
|
|||
.setData(uri)
|
||||
.putExtra(PlayerActivity.EXTENSION_EXTRA, extension)
|
||||
.putExtra(PlayerActivity.AD_TAG_URI_EXTRA, adTagUri)
|
||||
.putExtra(PlayerActivity.SPHERICAL_STEREO_MODE_EXTRA, sphericalStereoMode)
|
||||
.setAction(PlayerActivity.ACTION_VIEW);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
<string name="error_unrecognized_abr_algorithm">Unrecognized ABR algorithm</string>
|
||||
|
||||
<string name="error_unrecognized_stereo_mode">Unrecognized stereo mode</string>
|
||||
|
||||
<string name="error_drm_not_supported">Protected content not supported on API levels below 18</string>
|
||||
|
||||
<string name="error_drm_unsupported_scheme">This device does not support the required DRM scheme</string>
|
||||
|
|
|
|||
|
|
@ -20,4 +20,8 @@
|
|||
<item name="android:windowBackground">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="PlayerTheme.Spherical">
|
||||
<item name="surface_type">spherical_view</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import java.nio.FloatBuffer;
|
|||
/*package*/ final class Mesh {
|
||||
|
||||
/** Defines the constants identifying the current eye type. */
|
||||
public interface EyeType {
|
||||
/*package*/ interface EyeType {
|
||||
/** Single eye in monocular rendering. */
|
||||
int MONOCULAR = 0;
|
||||
|
||||
|
|
@ -43,19 +43,6 @@ import java.nio.FloatBuffer;
|
|||
int RIGHT = 2;
|
||||
}
|
||||
|
||||
/** Standard media where a single camera frame takes up the entire media frame. */
|
||||
public static final int MEDIA_MONOSCOPIC = 0;
|
||||
/**
|
||||
* Stereo media where the left & right halves of the frame are rendered for the left & right eyes,
|
||||
* respectively. If the stereo media is rendered in a non-VR display, only the left half is used.
|
||||
*/
|
||||
public static final int MEDIA_STEREO_LEFT_RIGHT = 1;
|
||||
/**
|
||||
* Stereo media where the top & bottom halves of the frame are rendered for the left & right eyes,
|
||||
* respectively. If the stereo media is rendered in a non-VR display, only the top half is used.
|
||||
*/
|
||||
public static final int MEDIA_STEREO_TOP_BOTTOM = 2;
|
||||
|
||||
// Basic vertex & fragment shaders to render a mesh with 3D position & 2D texture data.
|
||||
private static final String[] VERTEX_SHADER_CODE =
|
||||
new String[] {
|
||||
|
|
@ -121,7 +108,7 @@ import java.nio.FloatBuffer;
|
|||
* (0, 180].
|
||||
* @param horizontalFovDegrees Total longitudinal degrees that are covered by the sphere.Must be
|
||||
* in (0, 360].
|
||||
* @param mediaFormat A MEDIA_* value.
|
||||
* @param stereoMode A {@link C.StereoMode} value.
|
||||
* @return Unintialized Mesh.
|
||||
*/
|
||||
public static Mesh createUvSphere(
|
||||
|
|
@ -130,10 +117,10 @@ import java.nio.FloatBuffer;
|
|||
int longitudes,
|
||||
float verticalFovDegrees,
|
||||
float horizontalFovDegrees,
|
||||
int mediaFormat) {
|
||||
@C.StereoMode int stereoMode) {
|
||||
return new Mesh(
|
||||
createUvSphereVertexData(
|
||||
radius, latitudes, longitudes, verticalFovDegrees, horizontalFovDegrees, mediaFormat));
|
||||
radius, latitudes, longitudes, verticalFovDegrees, horizontalFovDegrees, stereoMode));
|
||||
}
|
||||
|
||||
/** Used by static constructors. */
|
||||
|
|
@ -219,7 +206,7 @@ import java.nio.FloatBuffer;
|
|||
int longitudes,
|
||||
float verticalFovDegrees,
|
||||
float horizontalFovDegrees,
|
||||
int mediaFormat) {
|
||||
@C.StereoMode int stereoMode) {
|
||||
if (radius <= 0
|
||||
|| latitudes < 1
|
||||
|| longitudes < 1
|
||||
|
|
@ -258,12 +245,12 @@ import java.nio.FloatBuffer;
|
|||
float theta = quadWidthRads * i + (float) Math.PI - horizontalFovRads / 2;
|
||||
|
||||
// Set vertex position data as Cartesian coordinates.
|
||||
vertexData[offset + 0] = -(float) (radius * Math.sin(theta) * Math.cos(phi));
|
||||
vertexData[offset] = -(float) (radius * Math.sin(theta) * Math.cos(phi));
|
||||
vertexData[offset + 1] = (float) (radius * Math.sin(phi));
|
||||
vertexData[offset + 2] = (float) (radius * Math.cos(theta) * Math.cos(phi));
|
||||
|
||||
// Set vertex texture.x data.
|
||||
if (mediaFormat == MEDIA_STEREO_LEFT_RIGHT) {
|
||||
if (stereoMode == C.STEREO_MODE_LEFT_RIGHT) {
|
||||
// For left-right media, each eye's x coordinate points to the left or right half of the
|
||||
// texture.
|
||||
vertexData[offset + 3] = (i * quadWidthRads / horizontalFovRads) / 2;
|
||||
|
|
@ -275,7 +262,7 @@ import java.nio.FloatBuffer;
|
|||
}
|
||||
|
||||
// Set vertex texture.y data. The "1 - ..." is due to Canvas vs GL coords.
|
||||
if (mediaFormat == MEDIA_STEREO_TOP_BOTTOM) {
|
||||
if (stereoMode == C.STEREO_MODE_TOP_BOTTOM) {
|
||||
// For top-bottom media, each eye's y coordinate points to the top or bottom half of the
|
||||
// texture.
|
||||
vertexData[offset + 4] = 1 - (((j + k) * quadHeightRads / verticalFovRads) / 2 + .5f);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import android.util.AttributeSet;
|
|||
import android.view.Display;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowManager;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ui.spherical.Mesh.EyeType;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
|
@ -129,6 +130,20 @@ public final class SphericalSurfaceView extends GLSurfaceView {
|
|||
setRenderer(renderer);
|
||||
setOnTouchListener(touchTracker);
|
||||
|
||||
setStereoMode(C.STEREO_MODE_MONO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets stereo mode of the media to be played.
|
||||
*
|
||||
* @param stereoMode One of {@link C#STEREO_MODE_MONO}, {@link C#STEREO_MODE_TOP_BOTTOM}, {@link
|
||||
* C#STEREO_MODE_LEFT_RIGHT}.
|
||||
*/
|
||||
public void setStereoMode(@C.StereoMode int stereoMode) {
|
||||
Assertions.checkState(
|
||||
stereoMode == C.STEREO_MODE_MONO
|
||||
|| stereoMode == C.STEREO_MODE_TOP_BOTTOM
|
||||
|| stereoMode == C.STEREO_MODE_LEFT_RIGHT);
|
||||
Mesh mesh =
|
||||
Mesh.createUvSphere(
|
||||
SPHERE_RADIUS_METERS,
|
||||
|
|
@ -136,7 +151,7 @@ public final class SphericalSurfaceView extends GLSurfaceView {
|
|||
DEFAULT_SPHERE_COLUMNS,
|
||||
DEFAULT_SPHERE_VERTICAL_DEGREES,
|
||||
DEFAULT_SPHERE_HORIZONTAL_DEGREES,
|
||||
Mesh.MEDIA_MONOSCOPIC);
|
||||
stereoMode);
|
||||
queueEvent(() -> renderer.scene.setMesh(mesh));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue