├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.gradle ├── demo ├── build.gradle └── src │ └── main │ ├── .classpath │ ├── .project │ ├── .settings │ └── org.eclipse.jdt.core.prefs │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── google │ │ └── android │ │ └── exoplayer │ │ └── demo │ │ ├── DemoUtil.java │ │ ├── SampleChooserActivity.java │ │ ├── Samples.java │ │ ├── full │ │ ├── EventLogger.java │ │ ├── FullPlayerActivity.java │ │ ├── SmoothStreamingTestMediaDrmCallback.java │ │ ├── WidevineTestMediaDrmCallback.java │ │ └── player │ │ │ ├── DashVodRendererBuilder.java │ │ │ ├── DebugTrackRenderer.java │ │ │ ├── DefaultRendererBuilder.java │ │ │ ├── DemoPlayer.java │ │ │ └── SmoothStreamingRendererBuilder.java │ │ └── simple │ │ ├── DashVodRendererBuilder.java │ │ ├── DefaultRendererBuilder.java │ │ ├── SimplePlayerActivity.java │ │ └── SmoothStreamingRendererBuilder.java │ ├── project.properties │ └── res │ ├── layout │ ├── player_activity_full.xml │ ├── player_activity_simple.xml │ ├── sample_chooser_activity.xml │ └── sample_chooser_inline_header.xml │ └── values │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .project~ ├── build.gradle ├── doc_src │ └── images │ │ ├── exoplayer_playbackstate.png │ │ ├── exoplayer_state.png │ │ ├── exoplayer_threading_model.png │ │ └── trackrenderer_state.png └── src │ └── main │ ├── .classpath │ ├── .project │ ├── .settings │ └── org.eclipse.jdt.core.prefs │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── google │ │ └── android │ │ └── exoplayer │ │ ├── C.java │ │ ├── CodecCounters.java │ │ ├── CryptoInfo.java │ │ ├── DecoderInfo.java │ │ ├── DefaultLoadControl.java │ │ ├── DummyTrackRenderer.java │ │ ├── ExoPlaybackException.java │ │ ├── ExoPlayer.java │ │ ├── ExoPlayerImpl.java │ │ ├── ExoPlayerImplInternal.java │ │ ├── ExoPlayerLibraryInfo.java │ │ ├── FrameworkSampleSource.java │ │ ├── LoadControl.java │ │ ├── MediaClock.java │ │ ├── MediaCodecAudioTrackRenderer.java │ │ ├── MediaCodecTrackRenderer.java │ │ ├── MediaCodecUtil.java │ │ ├── MediaCodecVideoTrackRenderer.java │ │ ├── MediaFormat.java │ │ ├── MediaFormatHolder.java │ │ ├── ParserException.java │ │ ├── SampleHolder.java │ │ ├── SampleSource.java │ │ ├── TrackInfo.java │ │ ├── TrackRenderer.java │ │ ├── VideoSurfaceView.java │ │ ├── chunk │ │ ├── Chunk.java │ │ ├── ChunkOperationHolder.java │ │ ├── ChunkSampleSource.java │ │ ├── ChunkSource.java │ │ ├── Format.java │ │ ├── FormatEvaluator.java │ │ ├── MediaChunk.java │ │ ├── Mp4MediaChunk.java │ │ ├── MultiTrackChunkSource.java │ │ └── SingleSampleMediaChunk.java │ │ ├── dash │ │ ├── DashChunkSource.java │ │ ├── DashSegmentIndex.java │ │ ├── DashWrappingSegmentIndex.java │ │ └── mpd │ │ │ ├── AdaptationSet.java │ │ │ ├── ContentProtection.java │ │ │ ├── MediaPresentationDescription.java │ │ │ ├── MediaPresentationDescriptionFetcher.java │ │ │ ├── MediaPresentationDescriptionParser.java │ │ │ ├── Period.java │ │ │ ├── RangedUri.java │ │ │ ├── Representation.java │ │ │ ├── SegmentBase.java │ │ │ ├── UrlTemplate.java │ │ │ └── UtcTimingElement.java │ │ ├── drm │ │ ├── DrmSessionManager.java │ │ ├── MediaDrmCallback.java │ │ └── StreamingDrmSessionManager.java │ │ ├── parser │ │ ├── Extractor.java │ │ ├── SegmentIndex.java │ │ ├── mp4 │ │ │ ├── Atom.java │ │ │ ├── DefaultSampleValues.java │ │ │ ├── FragmentedMp4Extractor.java │ │ │ ├── ParsableByteArray.java │ │ │ ├── Track.java │ │ │ ├── TrackEncryptionBox.java │ │ │ └── TrackFragment.java │ │ └── webm │ │ │ ├── DefaultEbmlReader.java │ │ │ ├── EbmlEventHandler.java │ │ │ ├── EbmlReader.java │ │ │ └── WebmExtractor.java │ │ ├── smoothstreaming │ │ ├── SmoothStreamingChunkSource.java │ │ ├── SmoothStreamingManifest.java │ │ ├── SmoothStreamingManifestFetcher.java │ │ └── SmoothStreamingManifestParser.java │ │ ├── text │ │ ├── Subtitle.java │ │ ├── SubtitleParser.java │ │ ├── TextTrackRenderer.java │ │ └── ttml │ │ │ ├── TtmlNode.java │ │ │ ├── TtmlParser.java │ │ │ └── TtmlSubtitle.java │ │ ├── upstream │ │ ├── Allocation.java │ │ ├── Allocator.java │ │ ├── BandwidthMeter.java │ │ ├── BufferPool.java │ │ ├── ByteArrayDataSink.java │ │ ├── ByteArrayDataSource.java │ │ ├── ByteArrayNonBlockingInputStream.java │ │ ├── DataSink.java │ │ ├── DataSource.java │ │ ├── DataSourceInputStream.java │ │ ├── DataSourceStream.java │ │ ├── DataSpec.java │ │ ├── DefaultBandwidthMeter.java │ │ ├── FileDataSource.java │ │ ├── HttpDataSource.java │ │ ├── Loader.java │ │ ├── NetworkLock.java │ │ ├── NonBlockingInputStream.java │ │ ├── PriorityDataSource.java │ │ ├── TeeDataSource.java │ │ ├── TransferListener.java │ │ ├── UnexpectedLengthException.java │ │ └── cache │ │ │ ├── Cache.java │ │ │ ├── CacheDataSink.java │ │ │ ├── CacheDataSource.java │ │ │ ├── CacheEvictor.java │ │ │ ├── CacheSpan.java │ │ │ ├── LeastRecentlyUsedCacheEvictor.java │ │ │ ├── NoOpCacheEvictor.java │ │ │ └── SimpleCache.java │ │ └── util │ │ ├── Assertions.java │ │ ├── Clock.java │ │ ├── CodecSpecificDataUtil.java │ │ ├── LongArray.java │ │ ├── ManifestFetcher.java │ │ ├── MimeTypes.java │ │ ├── PlayerControl.java │ │ ├── Predicate.java │ │ ├── SlidingPercentile.java │ │ ├── SystemClock.java │ │ ├── TraceUtil.java │ │ ├── Util.java │ │ └── VerboseLogUtil.java │ ├── project.properties │ └── res │ └── .README.txt └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Android generated 2 | bin 3 | gen 4 | lint.xml 5 | 6 | # IntelliJ IDEA 7 | .idea 8 | *.iml 9 | *.ipr 10 | *.iws 11 | classes 12 | gen-external-apklibs 13 | 14 | # Eclipse 15 | .project 16 | .classpath 17 | .settings 18 | .checkstyle 19 | 20 | # Gradle 21 | .gradle 22 | build 23 | out 24 | 25 | # Maven 26 | target 27 | release.properties 28 | pom.xml.* 29 | 30 | # Ant 31 | ant.properties 32 | local.properties 33 | proguard.cfg 34 | proguard-project.txt 35 | 36 | # Other 37 | .DS_Store 38 | dist 39 | tmp 40 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute # 2 | 3 | We'd love to hear your feedback. Please open new issues describing any bugs, 4 | feature requests or suggestions that you have. 5 | 6 | We are not actively looking to accept patches to this project at the current 7 | time, however in some cases we may do so. For such cases, please see the 8 | agreement below. 9 | 10 | 11 | ## Contributor License Agreement ## 12 | 13 | Contributions to any Google project must be accompanied by a Contributor 14 | License Agreement. This is not a copyright **assignment**, it simply gives 15 | Google permission to use and redistribute your contributions as part of the 16 | project. 17 | 18 | * If you are an individual writing original source code and you're sure you 19 | own the intellectual property, then you'll need to sign an [individual 20 | CLA][]. 21 | 22 | * If you work for a company that wants to allow you to contribute your work, 23 | then you'll need to sign a [corporate CLA][]. 24 | 25 | You generally only need to submit a CLA once, so if you've already submitted 26 | one (even if it was for a different project), you probably don't need to do it 27 | again. 28 | 29 | [individual CLA]: https://developers.google.com/open-source/cla/individual 30 | [corporate CLA]: https://developers.google.com/open-source/cla/corporate 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExoPlayer Readme # 2 | 3 | ## Description ## 4 | 5 | ExoPlayer is an application level media player for Android. It provides an 6 | alternative to Android’s MediaPlayer API for playing audio and video both 7 | locally and over the internet. ExoPlayer supports features not currently 8 | supported by Android’s MediaPlayer API (as of KitKat), including DASH and 9 | SmoothStreaming adaptive playbacks, persistent caching and custom renderers. 10 | Unlike the MediaPlayer API, ExoPlayer is easy to customize and extend, and 11 | can be updated through Play Store application updates. 12 | 13 | 14 | ## Developer guide ## 15 | 16 | The [ExoPlayer developer guide][] provides a wealth of information to help you 17 | get started. 18 | 19 | [ExoPlayer developer guide]: http://developer.android.com/guide/topics/media/exoplayer.html 20 | 21 | 22 | ## Reference documentation ## 23 | 24 | [Class reference][] (Documents the ExoPlayer library classes). 25 | 26 | [Class reference]: http://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer/package-summary.html 27 | 28 | 29 | ## Project branches ## 30 | 31 | * The [master][] branch holds the most recent minor release. 32 | * Most development work happens on the [dev][] branch. 33 | * Additional development branches may be established for major features. 34 | 35 | [master]: https://github.com/google/ExoPlayer/tree/master 36 | [dev]: https://github.com/google/ExoPlayer/tree/dev 37 | 38 | 39 | ## Using Eclipse ## 40 | 41 | The repository includes Eclipse projects for both the ExoPlayer library and its 42 | accompanying demo application. To get started: 43 | 44 | 1. Install Eclipse and setup the [Android SDK][]. 45 | 46 | 1. Open Eclipse and navigate to File->Import->General->Existing Projects into 47 | Workspace. 48 | 49 | 1. Select the root directory of the repository. 50 | 51 | 1. Import the ExoPlayerDemo and ExoPlayerLib projects. 52 | 53 | [Android SDK]: http://developer.android.com/sdk/index.html 54 | 55 | 56 | ## Using Gradle ## 57 | 58 | ExoPlayer can also be built using Gradle. You can include it as a dependent project and build from source. e.g. 59 | 60 | ``` 61 | // setting.gradle 62 | include ':app', ':..:ExoPlayer:library' 63 | 64 | // app/build.gradle 65 | dependencies { 66 | compile project(':..:ExoPlayer:library') 67 | } 68 | ``` 69 | 70 | If you want to use ExoPlayer as a jar, run: 71 | 72 | ``` 73 | ./gradlew jarRelease 74 | ``` 75 | 76 | and copy library.jar to the libs-folder of your new project. 77 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 16 | 17 | buildscript { 18 | repositories { 19 | mavenCentral() 20 | } 21 | dependencies { 22 | classpath 'com.android.tools.build:gradle:0.12.+' 23 | } 24 | } 25 | 26 | allprojects { 27 | repositories { 28 | mavenCentral() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 The Android Open Source Project 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | apply plugin: 'android' 15 | 16 | android { 17 | compileSdkVersion 19 18 | buildToolsVersion "19.1" 19 | 20 | defaultConfig { 21 | minSdkVersion 16 22 | targetSdkVersion 19 23 | } 24 | buildTypes { 25 | release { 26 | runProguard false 27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 28 | } 29 | } 30 | 31 | lintOptions { 32 | abortOnError false 33 | } 34 | } 35 | 36 | dependencies { 37 | compile project(':library') 38 | } 39 | -------------------------------------------------------------------------------- /demo/src/main/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demo/src/main/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | ExoPlayerDemo 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | 35 | 1363908154650 36 | 37 | 22 38 | 39 | org.eclipse.ui.ide.multiFilter 40 | 1.0-name-matches-false-false-BUILD 41 | 42 | 43 | 44 | 1363908154652 45 | 46 | 10 47 | 48 | org.eclipse.ui.ide.multiFilter 49 | 1.0-name-matches-true-false-build 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /demo/src/main/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 47 | 48 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /demo/src/main/java/com/google/android/exoplayer/demo/DemoUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.android.exoplayer.demo; 17 | 18 | import com.google.android.exoplayer.ExoPlayerLibraryInfo; 19 | 20 | import android.content.Context; 21 | import android.content.pm.PackageInfo; 22 | import android.content.pm.PackageManager.NameNotFoundException; 23 | import android.os.Build; 24 | 25 | import java.io.BufferedInputStream; 26 | import java.io.BufferedOutputStream; 27 | import java.io.ByteArrayOutputStream; 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.io.OutputStream; 31 | import java.net.HttpURLConnection; 32 | import java.net.MalformedURLException; 33 | import java.net.URL; 34 | import java.util.Map; 35 | import java.util.UUID; 36 | 37 | /** 38 | * Utility methods for the demo application. 39 | */ 40 | public class DemoUtil { 41 | 42 | public static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); 43 | 44 | public static final String CONTENT_TYPE_EXTRA = "content_type"; 45 | public static final String CONTENT_ID_EXTRA = "content_id"; 46 | 47 | public static final int TYPE_DASH_VOD = 0; 48 | public static final int TYPE_SS_VOD = 1; 49 | public static final int TYPE_OTHER = 2; 50 | 51 | public static final boolean EXPOSE_EXPERIMENTAL_FEATURES = false; 52 | 53 | public static String getUserAgent(Context context) { 54 | String versionName; 55 | try { 56 | String packageName = context.getPackageName(); 57 | PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); 58 | versionName = info.versionName; 59 | } catch (NameNotFoundException e) { 60 | versionName = "?"; 61 | } 62 | return "ExoPlayerDemo/" + versionName + " (Linux;Android " + Build.VERSION.RELEASE + 63 | ") " + "ExoPlayerLib/" + ExoPlayerLibraryInfo.VERSION; 64 | } 65 | 66 | public static byte[] executePost(String url, byte[] data, Map requestProperties) 67 | throws MalformedURLException, IOException { 68 | HttpURLConnection urlConnection = null; 69 | try { 70 | urlConnection = (HttpURLConnection) new URL(url).openConnection(); 71 | urlConnection.setRequestMethod("POST"); 72 | urlConnection.setDoOutput(data != null); 73 | urlConnection.setDoInput(true); 74 | if (requestProperties != null) { 75 | for (Map.Entry requestProperty : requestProperties.entrySet()) { 76 | urlConnection.setRequestProperty(requestProperty.getKey(), requestProperty.getValue()); 77 | } 78 | } 79 | if (data != null) { 80 | OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); 81 | out.write(data); 82 | out.close(); 83 | } 84 | InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 85 | return convertInputStreamToByteArray(in); 86 | } finally { 87 | if (urlConnection != null) { 88 | urlConnection.disconnect(); 89 | } 90 | } 91 | } 92 | 93 | private static byte[] convertInputStreamToByteArray(InputStream inputStream) throws IOException { 94 | byte[] bytes = null; 95 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 96 | byte data[] = new byte[1024]; 97 | int count; 98 | while ((count = inputStream.read(data)) != -1) { 99 | bos.write(data, 0, count); 100 | } 101 | bos.flush(); 102 | bos.close(); 103 | inputStream.close(); 104 | bytes = bos.toByteArray(); 105 | return bytes; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /demo/src/main/java/com/google/android/exoplayer/demo/full/SmoothStreamingTestMediaDrmCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.android.exoplayer.demo.full; 17 | 18 | import com.google.android.exoplayer.demo.DemoUtil; 19 | import com.google.android.exoplayer.drm.MediaDrmCallback; 20 | import com.google.android.exoplayer.drm.StreamingDrmSessionManager; 21 | 22 | import android.annotation.TargetApi; 23 | import android.media.MediaDrm.KeyRequest; 24 | import android.media.MediaDrm.ProvisionRequest; 25 | import android.text.TextUtils; 26 | 27 | import java.io.IOException; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | import java.util.UUID; 31 | 32 | /** 33 | * Demo {@link StreamingDrmSessionManager} for smooth streaming test content. 34 | */ 35 | @TargetApi(18) 36 | public class SmoothStreamingTestMediaDrmCallback implements MediaDrmCallback { 37 | 38 | private static final String PLAYREADY_TEST_DEFAULT_URI = 39 | "http://playready.directtaps.net/pr/svc/rightsmanager.asmx"; 40 | private static final Map KEY_REQUEST_PROPERTIES; 41 | static { 42 | HashMap keyRequestProperties = new HashMap(); 43 | keyRequestProperties.put("Content-Type", "text/xml"); 44 | keyRequestProperties.put("SOAPAction", 45 | "http://schemas.microsoft.com/DRM/2007/03/protocols/AcquireLicense"); 46 | KEY_REQUEST_PROPERTIES = keyRequestProperties; 47 | } 48 | 49 | @Override 50 | public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws IOException { 51 | String url = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData()); 52 | return DemoUtil.executePost(url, null, null); 53 | } 54 | 55 | @Override 56 | public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws Exception { 57 | String url = request.getDefaultUrl(); 58 | if (TextUtils.isEmpty(url)) { 59 | url = PLAYREADY_TEST_DEFAULT_URI; 60 | } 61 | return DemoUtil.executePost(url, request.getData(), KEY_REQUEST_PROPERTIES); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /demo/src/main/java/com/google/android/exoplayer/demo/full/WidevineTestMediaDrmCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.android.exoplayer.demo.full; 17 | 18 | import com.google.android.exoplayer.demo.DemoUtil; 19 | import com.google.android.exoplayer.drm.MediaDrmCallback; 20 | 21 | import android.annotation.TargetApi; 22 | import android.media.MediaDrm.KeyRequest; 23 | import android.media.MediaDrm.ProvisionRequest; 24 | import android.text.TextUtils; 25 | 26 | import org.apache.http.client.ClientProtocolException; 27 | 28 | import java.io.IOException; 29 | import java.util.UUID; 30 | 31 | /** 32 | * A {@link MediaDrmCallback} for Widevine test content. 33 | */ 34 | @TargetApi(18) 35 | public class WidevineTestMediaDrmCallback implements MediaDrmCallback { 36 | 37 | private static final String WIDEVINE_GTS_DEFAULT_BASE_URI = 38 | "http://wv-staging-proxy.appspot.com/proxy?provider=YouTube&video_id="; 39 | 40 | private final String defaultUri; 41 | 42 | public WidevineTestMediaDrmCallback(String videoId) { 43 | defaultUri = WIDEVINE_GTS_DEFAULT_BASE_URI + videoId; 44 | } 45 | 46 | @Override 47 | public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) 48 | throws ClientProtocolException, IOException { 49 | String url = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData()); 50 | return DemoUtil.executePost(url, null, null); 51 | } 52 | 53 | @Override 54 | public byte[] executeKeyRequest(UUID uuid, KeyRequest request) throws IOException { 55 | String url = request.getDefaultUrl(); 56 | if (TextUtils.isEmpty(url)) { 57 | url = defaultUri; 58 | } 59 | return DemoUtil.executePost(url, request.getData(), null); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /demo/src/main/java/com/google/android/exoplayer/demo/full/player/DebugTrackRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.android.exoplayer.demo.full.player; 17 | 18 | import com.google.android.exoplayer.ExoPlaybackException; 19 | import com.google.android.exoplayer.MediaCodecTrackRenderer; 20 | import com.google.android.exoplayer.TrackRenderer; 21 | import com.google.android.exoplayer.chunk.ChunkSampleSource; 22 | import com.google.android.exoplayer.chunk.Format; 23 | 24 | import android.widget.TextView; 25 | 26 | /** 27 | * A {@link TrackRenderer} that periodically updates debugging information displayed by a 28 | * {@link TextView}. 29 | */ 30 | /* package */ class DebugTrackRenderer extends TrackRenderer implements Runnable { 31 | 32 | private final TextView textView; 33 | private final MediaCodecTrackRenderer renderer; 34 | private final ChunkSampleSource videoSampleSource; 35 | 36 | private volatile boolean pendingFailure; 37 | private volatile long currentPositionUs; 38 | 39 | public DebugTrackRenderer(TextView textView, MediaCodecTrackRenderer renderer) { 40 | this(textView, renderer, null); 41 | } 42 | 43 | public DebugTrackRenderer(TextView textView, MediaCodecTrackRenderer renderer, 44 | ChunkSampleSource videoSampleSource) { 45 | this.textView = textView; 46 | this.renderer = renderer; 47 | this.videoSampleSource = videoSampleSource; 48 | } 49 | 50 | public void injectFailure() { 51 | pendingFailure = true; 52 | } 53 | 54 | @Override 55 | protected boolean isEnded() { 56 | return true; 57 | } 58 | 59 | @Override 60 | protected boolean isReady() { 61 | return true; 62 | } 63 | 64 | @Override 65 | protected int doPrepare() throws ExoPlaybackException { 66 | maybeFail(); 67 | return STATE_PREPARED; 68 | } 69 | 70 | @Override 71 | protected void doSomeWork(long timeUs) throws ExoPlaybackException { 72 | maybeFail(); 73 | if (timeUs < currentPositionUs || timeUs > currentPositionUs + 1000000) { 74 | currentPositionUs = timeUs; 75 | textView.post(this); 76 | } 77 | } 78 | 79 | @Override 80 | public void run() { 81 | textView.setText(getRenderString()); 82 | } 83 | 84 | private String getRenderString() { 85 | return "ms(" + (currentPositionUs / 1000) + "), " + getQualityString() + 86 | ", " + renderer.codecCounters.getDebugString(); 87 | } 88 | 89 | private String getQualityString() { 90 | Format format = videoSampleSource == null ? null : videoSampleSource.getFormat(); 91 | return format == null ? "null" : "height(" + format.height + "), itag(" + format.id + ")"; 92 | } 93 | 94 | @Override 95 | protected long getCurrentPositionUs() { 96 | return currentPositionUs; 97 | } 98 | 99 | @Override 100 | protected long getDurationUs() { 101 | return TrackRenderer.MATCH_LONGEST_US; 102 | } 103 | 104 | @Override 105 | protected long getBufferedPositionUs() { 106 | return TrackRenderer.END_OF_TRACK_US; 107 | } 108 | 109 | @Override 110 | protected void seekTo(long timeUs) { 111 | currentPositionUs = timeUs; 112 | } 113 | 114 | private void maybeFail() throws ExoPlaybackException { 115 | if (pendingFailure) { 116 | pendingFailure = false; 117 | throw new ExoPlaybackException("fail() was called on DebugTrackRenderer"); 118 | } 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /demo/src/main/java/com/google/android/exoplayer/demo/full/player/DefaultRendererBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.android.exoplayer.demo.full.player; 17 | 18 | import com.google.android.exoplayer.FrameworkSampleSource; 19 | import com.google.android.exoplayer.MediaCodecAudioTrackRenderer; 20 | import com.google.android.exoplayer.MediaCodecVideoTrackRenderer; 21 | import com.google.android.exoplayer.TrackRenderer; 22 | import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilder; 23 | import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilderCallback; 24 | 25 | import android.content.Context; 26 | import android.media.MediaCodec; 27 | import android.net.Uri; 28 | import android.widget.TextView; 29 | 30 | /** 31 | * A {@link RendererBuilder} for streams that can be read using 32 | * {@link android.media.MediaExtractor}. 33 | */ 34 | public class DefaultRendererBuilder implements RendererBuilder { 35 | 36 | private final Context context; 37 | private final Uri uri; 38 | private final TextView debugTextView; 39 | 40 | public DefaultRendererBuilder(Context context, Uri uri, TextView debugTextView) { 41 | this.context = context; 42 | this.uri = uri; 43 | this.debugTextView = debugTextView; 44 | } 45 | 46 | @Override 47 | public void buildRenderers(DemoPlayer player, RendererBuilderCallback callback) { 48 | // Build the video and audio renderers. 49 | FrameworkSampleSource sampleSource = new FrameworkSampleSource(context, uri, null, 2); 50 | MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource, 51 | null, true, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000, 52 | player.getMainHandler(), player, 50); 53 | MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource, 54 | null, true, player.getMainHandler(), player); 55 | 56 | // Build the debug renderer. 57 | TrackRenderer debugRenderer = debugTextView != null 58 | ? new DebugTrackRenderer(debugTextView, videoRenderer) 59 | : null; 60 | 61 | // Invoke the callback. 62 | TrackRenderer[] renderers = new TrackRenderer[DemoPlayer.RENDERER_COUNT]; 63 | renderers[DemoPlayer.TYPE_VIDEO] = videoRenderer; 64 | renderers[DemoPlayer.TYPE_AUDIO] = audioRenderer; 65 | renderers[DemoPlayer.TYPE_DEBUG] = debugRenderer; 66 | callback.onRenderers(null, null, renderers); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /demo/src/main/java/com/google/android/exoplayer/demo/simple/DefaultRendererBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.android.exoplayer.demo.simple; 17 | 18 | import com.google.android.exoplayer.FrameworkSampleSource; 19 | import com.google.android.exoplayer.MediaCodecAudioTrackRenderer; 20 | import com.google.android.exoplayer.MediaCodecVideoTrackRenderer; 21 | import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilder; 22 | import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilderCallback; 23 | 24 | import android.media.MediaCodec; 25 | import android.net.Uri; 26 | 27 | /** 28 | * A {@link RendererBuilder} for streams that can be read using 29 | * {@link android.media.MediaExtractor}. 30 | */ 31 | /* package */ class DefaultRendererBuilder implements RendererBuilder { 32 | 33 | private final SimplePlayerActivity playerActivity; 34 | private final Uri uri; 35 | 36 | public DefaultRendererBuilder(SimplePlayerActivity playerActivity, Uri uri) { 37 | this.playerActivity = playerActivity; 38 | this.uri = uri; 39 | } 40 | 41 | @Override 42 | public void buildRenderers(RendererBuilderCallback callback) { 43 | // Build the video and audio renderers. 44 | FrameworkSampleSource sampleSource = new FrameworkSampleSource(playerActivity, uri, null, 2); 45 | MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource, 46 | MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, playerActivity.getMainHandler(), 47 | playerActivity, 50); 48 | MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource); 49 | 50 | // Invoke the callback. 51 | callback.onRenderers(videoRenderer, audioRenderer); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /demo/src/main/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-19 12 | android.library=false 13 | android.library.reference.1=../../../library/src/main 14 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/player_activity_full.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 26 | 27 | 37 | 38 | 42 | 43 | 48 | 49 | 55 | 56 | 62 | 63 | 68 | 69 |