Merge branch 'dev-v2' into release-v2

This commit is contained in:
Oliver Woodman 2017-04-26 16:23:48 +01:00
commit d979469659
784 changed files with 9047 additions and 2419 deletions

View File

@ -30,17 +30,39 @@ repositories {
}
```
Next, include the following in your module's `build.gradle` file:
Next add a gradle compile dependency to the `build.gradle` file of your app
module. The following will add a dependency to the full ExoPlayer library:
```gradle
compile 'com.google.android.exoplayer:exoplayer:rX.X.X'
compile 'com.google.android.exoplayer:exoplayer:r2.X.X'
```
where `rX.X.X` is the your preferred version. For the latest version, see the
project's [Releases][]. For more details, see the project on [Bintray][].
where `r2.X.X` is your preferred version. Alternatively, you can depend on only
the library modules that you actually need. For example the following will add
dependencies on the Core, DASH and UI library modules, as might be required for
an app that plays DASH content:
[Releases]: https://github.com/google/ExoPlayer/releases
[Bintray]: https://bintray.com/google/exoplayer/exoplayer/view
```gradle
compile 'com.google.android.exoplayer:exoplayer-core:r2.X.X'
compile 'com.google.android.exoplayer:exoplayer-dash:r2.X.X'
compile 'com.google.android.exoplayer:exoplayer-ui:r2.X.X'
```
The available modules are listed below. Adding a dependency to the full
ExoPlayer library is equivalent to adding dependencies on all of the modules
individually.
* `exoplayer-core`: Core functionality (required).
* `exoplayer-dash`: Support for DASH content.
* `exoplayer-hls`: Support for HLS content.
* `exoplayer-smoothstreaming`: Support for SmoothStreaming content.
* `exoplayer-ui`: UI components and resources for use with ExoPlayer.
For more details, see the project on [Bintray][]. For information about the
latest versions, see the [Release notes][].
[Bintray]: https://bintray.com/google/exoplayer
[Release notes]: https://github.com/google/ExoPlayer/blob/release-v2/RELEASENOTES.md
## Developing ExoPlayer ##

View File

@ -1,5 +1,38 @@
# Release notes #
### r2.4.0 ###
* New modular library structure. You can read more about depending on individual
library modules
[here](https://medium.com/google-exoplayer/exoplayers-new-modular-structure-a916c0874907).
* Variable speed playback support on API level 16+. You can read more about
changing the playback speed
[here](https://medium.com/google-exoplayer/variable-speed-playback-with-exoplayer-e6e6a71e0343)
([#26](https://github.com/google/ExoPlayer/issues/26)).
* New time bar view, including support for displaying ad break markers.
* Support DVB subtitles in MPEG-TS and MKV.
* Support adaptive playback for audio only DASH, HLS and SmoothStreaming
([#1975](https://github.com/google/ExoPlayer/issues/1975)).
* Support for setting extractor flags on DefaultExtractorsFactory
([#2657](https://github.com/google/ExoPlayer/issues/2657)).
* Support injecting custom renderers into SimpleExoPlayer using a new
RenderersFactory interface.
* Correctly set ExoPlayer's internal thread priority to `THREAD_PRIORITY_AUDIO`.
* TX3G: Support styling and positioning.
* FLV:
* Support MP3 in FLV.
* Skip unhandled metadata rather than failing
([#2634](https://github.com/google/ExoPlayer/issues/2634)).
* Fix potential OutOfMemory errors.
* ID3: Better handle malformed ID3 data
([#2604](https://github.com/google/ExoPlayer/issues/2604),
[#2663](https://github.com/google/ExoPlayer/issues/2663)).
* FFmpeg extension: Fixed build instructions
([#2561](https://github.com/google/ExoPlayer/issues/2561)).
* VP9 extension: Reduced binary size.
* FLAC extension: Enabled 64 bit targets.
* Misc bugfixes.
### r2.3.1 ###
* Fix NPE enabling WebVTT subtitles in DASH streams
@ -15,32 +48,31 @@
rendering. You can read more about the GVR extension
[here](https://medium.com/google-exoplayer/spatial-audio-with-exoplayer-and-gvr-cecb00e9da5f#.xdjebjd7g).
* DASH improvements:
* Support embedded CEA-608 closed captions
([#2362](https://github.com/google/ExoPlayer/issues/2362)).
* Support embedded EMSG events
([#2176](https://github.com/google/ExoPlayer/issues/2176)).
* Support mspr:pro manifest element
([#2386](https://github.com/google/ExoPlayer/issues/2386)).
* Correct handling of empty segment indices at the start of live events
([#1865](https://github.com/google/ExoPlayer/issues/1865)).
* Support embedded CEA-608 closed captions
([#2362](https://github.com/google/ExoPlayer/issues/2362)).
* Support embedded EMSG events
([#2176](https://github.com/google/ExoPlayer/issues/2176)).
* Support mspr:pro manifest element
([#2386](https://github.com/google/ExoPlayer/issues/2386)).
* Correct handling of empty segment indices at the start of live events
([#1865](https://github.com/google/ExoPlayer/issues/1865)).
* HLS improvements:
* Respect initial track selection
([#2353](https://github.com/google/ExoPlayer/issues/2353)).
* Reduced frequency of media playlist requests when playback position is
close to the live edge
([#2548](https://github.com/google/ExoPlayer/issues/2548)).
* Exposed the master playlist through ExoPlayer.getCurrentManifest()
([#2537](https://github.com/google/ExoPlayer/issues/2537)).
* Support CLOSED-CAPTIONS #EXT-X-MEDIA type
([#341](https://github.com/google/ExoPlayer/issues/341)).
* Fixed handling of negative values in #EXT-X-SUPPORT
([#2495](https://github.com/google/ExoPlayer/issues/2495)).
* Fixed potential endless buffering state for streams with WebVTT subtitles
([#2424](https://github.com/google/ExoPlayer/issues/2424)).
* Respect initial track selection
([#2353](https://github.com/google/ExoPlayer/issues/2353)).
* Reduced frequency of media playlist requests when playback position is close
to the live edge ([#2548](https://github.com/google/ExoPlayer/issues/2548)).
* Exposed the master playlist through ExoPlayer.getCurrentManifest()
([#2537](https://github.com/google/ExoPlayer/issues/2537)).
* Support CLOSED-CAPTIONS #EXT-X-MEDIA type
([#341](https://github.com/google/ExoPlayer/issues/341)).
* Fixed handling of negative values in #EXT-X-SUPPORT
([#2495](https://github.com/google/ExoPlayer/issues/2495)).
* Fixed potential endless buffering state for streams with WebVTT subtitles
([#2424](https://github.com/google/ExoPlayer/issues/2424)).
* MPEG-TS improvements:
* Support for multiple programs.
* Support for multiple closed captions and caption service descriptors
([#2161](https://github.com/google/ExoPlayer/issues/2161)).
* Support for multiple programs.
* Support for multiple closed captions and caption service descriptors
([#2161](https://github.com/google/ExoPlayer/issues/2161)).
* MP3: Add `FLAG_ENABLE_CONSTANT_BITRATE_SEEKING` extractor option to enable
constant bitrate seeking in MP3 files that would otherwise be unseekable
([#2445](https://github.com/google/ExoPlayer/issues/2445)).
@ -135,15 +167,15 @@
* HLS: Support for seeking in live streams
([#87](https://github.com/google/ExoPlayer/issues/87)).
* HLS: Improved support:
* Support for EXT-X-PROGRAM-DATE-TIME
([#747](https://github.com/google/ExoPlayer/issues/747)).
* Improved handling of sample timestamps and their alignment across variants
and renditions.
* Fix issue that could cause playbacks to get stuck in an endless initial
buffering state.
* Correctly propagate BehindLiveWindowException instead of
IndexOutOfBoundsException exception
([#1695](https://github.com/google/ExoPlayer/issues/1695)).
* Support for EXT-X-PROGRAM-DATE-TIME
([#747](https://github.com/google/ExoPlayer/issues/747)).
* Improved handling of sample timestamps and their alignment across variants
and renditions.
* Fix issue that could cause playbacks to get stuck in an endless initial
buffering state.
* Correctly propagate BehindLiveWindowException instead of
IndexOutOfBoundsException exception
([#1695](https://github.com/google/ExoPlayer/issues/1695)).
* MP3/MP4: Support for ID3 metadata, including embedded album art
([#979](https://github.com/google/ExoPlayer/issues/979)).
* Improved customization of UI components. You can read about customization of
@ -153,19 +185,19 @@
MediaPeriod transitions.
* EIA608: Support for caption styling and positioning.
* MPEG-TS: Improved support:
* Support injection of custom TS payload readers.
* Support injection of custom section payload readers.
* Support SCTE-35 splice information messages.
* Support multiple table sections in a single PSI section.
* Fix NullPointerException when an unsupported stream type is encountered
([#2149](https://github.com/google/ExoPlayer/issues/2149)).
* Avoid failure when expected ID3 header not found
([#1966](https://github.com/google/ExoPlayer/issues/1966)).
* Support injection of custom TS payload readers.
* Support injection of custom section payload readers.
* Support SCTE-35 splice information messages.
* Support multiple table sections in a single PSI section.
* Fix NullPointerException when an unsupported stream type is encountered
([#2149](https://github.com/google/ExoPlayer/issues/2149)).
* Avoid failure when expected ID3 header not found
([#1966](https://github.com/google/ExoPlayer/issues/1966)).
* Improvements to the upstream cache package.
* Support caching of media segments for DASH, HLS and SmoothStreaming. Note
that caching of manifest and playlist files is still not supported in the
(normal) case where the corresponding responses are compressed.
* Support caching for ExtractorMediaSource based playbacks.
* Support caching of media segments for DASH, HLS and SmoothStreaming. Note
that caching of manifest and playlist files is still not supported in the
(normal) case where the corresponding responses are compressed.
* Support caching for ExtractorMediaSource based playbacks.
* Improved flexibility of SimpleExoPlayer
([#2102](https://github.com/google/ExoPlayer/issues/2102)).
* Fix issue where only the audio of a video would play due to capability
@ -237,63 +269,62 @@ some of the motivations behind ExoPlayer 2.x
structure and class names have also been sanitized. Read more
[here](https://medium.com/google-exoplayer/exoplayer-2-x-new-package-and-class-names-ef8e1d9ba96f#.lv8sd4nez).
* Key architectural changes:
* Late binding between rendering and media source components. Allows the
same rendering components to be re-used from one playback to another.
Enables features such as gapless playback through playlists and DASH
multi-period support.
* Improved track selection design. More details can be found
[here](https://medium.com/google-exoplayer/exoplayer-2-x-track-selection-2b62ff712cc9#.n00zo76b6).
* LoadControl now used to control buffering and loading across all playback
types.
* Media source components given additional structure. A new MediaSource
class has been introduced. MediaSources expose Timelines that describe the
media they expose, and can consist of multiple MediaPeriods. This enables
features such as seeking in live playbacks and DASH multi-period support.
* Responsibility for loading the initial DASH/SmoothStreaming/HLS manifest
is promoted to the corresponding MediaSource components and is no longer
the application's responsibility.
* Higher level abstractions such as SimpleExoPlayer have been added to the
library. These make the library easier to use for common use cases. The
demo app is halved in size as a result, whilst at the same time gaining
more functionality. Read more
[here](https://medium.com/google-exoplayer/exoplayer-2-x-improved-demo-app-d97171aaaaa1).
* Enhanced library support for implementing audio extensions. Read more
[here](https://medium.com/google-exoplayer/exoplayer-2-x-new-audio-features-cfb26c2883a#.ua75vu4s3).
* Format and MediaFormat are replaced by a single Format class.
* Late binding between rendering and media source components. Allows the same
rendering components to be re-used from one playback to another. Enables
features such as gapless playback through playlists and DASH multi-period
support.
* Improved track selection design. More details can be found
[here](https://medium.com/google-exoplayer/exoplayer-2-x-track-selection-2b62ff712cc9#.n00zo76b6).
* LoadControl now used to control buffering and loading across all playback
types.
* Media source components given additional structure. A new MediaSource class
has been introduced. MediaSources expose Timelines that describe the media
they expose, and can consist of multiple MediaPeriods. This enables features
such as seeking in live playbacks and DASH multi-period support.
* Responsibility for loading the initial DASH/SmoothStreaming/HLS manifest is
promoted to the corresponding MediaSource components and is no longer the
application's responsibility.
* Higher level abstractions such as SimpleExoPlayer have been added to the
library. These make the library easier to use for common use cases. The demo
app is halved in size as a result, whilst at the same time gaining more
functionality. Read more
[here](https://medium.com/google-exoplayer/exoplayer-2-x-improved-demo-app-d97171aaaaa1).
* Enhanced library support for implementing audio extensions. Read more
[here](https://medium.com/google-exoplayer/exoplayer-2-x-new-audio-features-cfb26c2883a#.ua75vu4s3).
* Format and MediaFormat are replaced by a single Format class.
* Key new features:
* Playlist support. Includes support for gapless playback between playlist
items and consistent application of LoadControl and TrackSelector policies
when transitioning between items
([#1270](https://github.com/google/ExoPlayer/issues/1270)).
* Seeking in live playbacks for DASH and SmoothStreaming
([#291](https://github.com/google/ExoPlayer/issues/291)).
* DASH multi-period support
([#557](https://github.com/google/ExoPlayer/issues/557)).
* MediaSource composition allows MediaSources to be concatenated into a
playlist, merged and looped. Read more
[here](https://medium.com/google-exoplayer/exoplayer-2-x-mediasource-composition-6c285fcbca1f#.zfha8qupz).
* Looping support (see above)
([#490](https://github.com/google/ExoPlayer/issues/490)).
* Ability to query information about all tracks in a piece of media
(including those not supported by the device)
([#1121](https://github.com/google/ExoPlayer/issues/1121)).
* Improved player controls.
* Support for PSSH in fMP4 moof atoms
([#1143](https://github.com/google/ExoPlayer/issues/1143)).
* Support for Opus in Ogg
([#1447](https://github.com/google/ExoPlayer/issues/1447)).
* CacheDataSource support for standalone media file playbacks (mp3, mp4
etc).
* FFMPEG extension (for audio only).
* Playlist support. Includes support for gapless playback between playlist
items and consistent application of LoadControl and TrackSelector policies
when transitioning between items
([#1270](https://github.com/google/ExoPlayer/issues/1270)).
* Seeking in live playbacks for DASH and SmoothStreaming
([#291](https://github.com/google/ExoPlayer/issues/291)).
* DASH multi-period support
([#557](https://github.com/google/ExoPlayer/issues/557)).
* MediaSource composition allows MediaSources to be concatenated into a
playlist, merged and looped. Read more
[here](https://medium.com/google-exoplayer/exoplayer-2-x-mediasource-composition-6c285fcbca1f#.zfha8qupz).
* Looping support (see above)
([#490](https://github.com/google/ExoPlayer/issues/490)).
* Ability to query information about all tracks in a piece of media (including
those not supported by the device)
([#1121](https://github.com/google/ExoPlayer/issues/1121)).
* Improved player controls.
* Support for PSSH in fMP4 moof atoms
([#1143](https://github.com/google/ExoPlayer/issues/1143)).
* Support for Opus in Ogg
([#1447](https://github.com/google/ExoPlayer/issues/1447)).
* CacheDataSource support for standalone media file playbacks (mp3, mp4 etc).
* FFMPEG extension (for audio only).
* Key bug fixes:
* Removed unnecessary secondary requests when playing standalone media
files ([#1041](https://github.com/google/ExoPlayer/issues/1041)).
* Fixed playback of video only (i.e. no audio) live streams
([#758](https://github.com/google/ExoPlayer/issues/758)).
* Fixed silent failure when media buffer is too small
([#583](https://github.com/google/ExoPlayer/issues/583)).
* Suppressed "Sending message to a Handler on a dead thread" warnings
([#426](https://github.com/google/ExoPlayer/issues/426)).
* Removed unnecessary secondary requests when playing standalone media files
([#1041](https://github.com/google/ExoPlayer/issues/1041)).
* Fixed playback of video only (i.e. no audio) live streams
([#758](https://github.com/google/ExoPlayer/issues/758)).
* Fixed silent failure when media buffer is too small
([#583](https://github.com/google/ExoPlayer/issues/583)).
* Suppressed "Sending message to a Handler on a dead thread" warnings
([#426](https://github.com/google/ExoPlayer/issues/426)).
# Legacy release notes #
@ -304,6 +335,12 @@ in all V2 releases. This cannot be assumed for changes in r1.5.12 and later,
however it can be assumed that all such changes are included in the most recent
V2 release.
### r1.5.16 ###
* VP9 extension: Reduced binary size.
* FLAC extension: Enabled 64 bit targets and fixed proguard config.
* Misc bugfixes.
### r1.5.15 ###
* SmoothStreaming: Fixed handling of start_time placeholder

View File

@ -19,8 +19,15 @@ buildscript {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'com.novoda:bintray-release:0.4.0'
}
// Workaround for the following test coverage issue. Remove when fixed:
// https://code.google.com/p/android/issues/detail?id=226070
configurations.all {
resolutionStrategy {
force 'org.jacoco:org.jacoco.report:0.7.4.201502262128'
force 'org.jacoco:org.jacoco.core:0.7.4.201502262128'
}
}
}
allprojects {
repositories {
jcenter()
@ -30,16 +37,26 @@ allprojects {
// components provided by the library may be of use on older devices.
// However, please note that the core media playback functionality
// provided by the library requires API level 16 or greater.
minSdkVersion=9
compileSdkVersion=25
targetSdkVersion=25
buildToolsVersion='25'
minSdkVersion = 9
compileSdkVersion = 25
targetSdkVersion = 25
buildToolsVersion = '25'
testSupportLibraryVersion = '0.5'
supportLibraryVersion = '25.3.1'
dexmakerVersion = '1.2'
mockitoVersion = '1.9.5'
releaseRepoName = getBintrayRepo()
releaseUserOrg = 'google'
releaseGroupId = 'com.google.android.exoplayer'
releaseVersion = 'r2.3.1'
releaseVersion = 'r2.4.0'
releaseWebsite = 'https://github.com/google/ExoPlayer'
}
if (it.hasProperty('externalBuildDir')) {
if (!new File(externalBuildDir).isAbsolute()) {
externalBuildDir = new File(rootDir, externalBuildDir)
}
buildDir = "${externalBuildDir}/${project.name}"
}
}
def getBintrayRepo() {
@ -47,3 +64,5 @@ def getBintrayRepo() {
property('publicRepo').toBoolean()
return publicRepo ? 'exoplayer' : 'exoplayer-test'
}
apply from: 'javadoc_combined.gradle'

View File

@ -45,7 +45,11 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
compile project(':library-dash')
compile project(':library-hls')
compile project(':library-smoothstreaming')
compile project(':library-ui')
withExtensionsCompile project(path: ':extension-ffmpeg')
withExtensionsCompile project(path: ':extension-flac')
withExtensionsCompile project(path: ':extension-opus')

View File

@ -16,8 +16,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.exoplayer2.demo"
android:versionCode="2301"
android:versionName="2.3.1">
android:versionCode="2400"
android:versionName="2.4.0">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

View File

@ -416,13 +416,16 @@
]
},
{
"name": "Audio -> Video",
"name": "Audio -> Video -> Audio",
"playlist": [
{
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/audio-141.mp4"
},
{
"uri": "http://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv"
},
{
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/audio-141.mp4"
}
]
},

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 com.google.android.exoplayer2.demo;
import android.text.TextUtils;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.Locale;
/**
* Utility methods for demo application.
*/
/*package*/ final class DemoUtil {
/**
* Builds a track name for display.
*
* @param format {@link Format} of the track.
* @return a generated name specific to the track.
*/
public static String buildTrackName(Format format) {
String trackName;
if (MimeTypes.isVideo(format.sampleMimeType)) {
trackName = joinWithSeparator(joinWithSeparator(joinWithSeparator(
buildResolutionString(format), buildBitrateString(format)), buildTrackIdString(format)),
buildSampleMimeTypeString(format));
} else if (MimeTypes.isAudio(format.sampleMimeType)) {
trackName = joinWithSeparator(joinWithSeparator(joinWithSeparator(joinWithSeparator(
buildLanguageString(format), buildAudioPropertyString(format)),
buildBitrateString(format)), buildTrackIdString(format)),
buildSampleMimeTypeString(format));
} else {
trackName = joinWithSeparator(joinWithSeparator(joinWithSeparator(buildLanguageString(format),
buildBitrateString(format)), buildTrackIdString(format)),
buildSampleMimeTypeString(format));
}
return trackName.length() == 0 ? "unknown" : trackName;
}
private static String buildResolutionString(Format format) {
return format.width == Format.NO_VALUE || format.height == Format.NO_VALUE
? "" : format.width + "x" + format.height;
}
private static String buildAudioPropertyString(Format format) {
return format.channelCount == Format.NO_VALUE || format.sampleRate == Format.NO_VALUE
? "" : format.channelCount + "ch, " + format.sampleRate + "Hz";
}
private static String buildLanguageString(Format format) {
return TextUtils.isEmpty(format.language) || "und".equals(format.language) ? ""
: format.language;
}
private static String buildBitrateString(Format format) {
return format.bitrate == Format.NO_VALUE ? ""
: String.format(Locale.US, "%.2fMbit", format.bitrate / 1000000f);
}
private static String joinWithSeparator(String first, String second) {
return first.length() == 0 ? second : (second.length() == 0 ? first : first + ", " + second);
}
private static String buildTrackIdString(Format format) {
return format.id == null ? "" : ("id:" + format.id);
}
private static String buildSampleMimeTypeString(Format format) {
return format.sampleMimeType == null ? "" : format.sampleMimeType;
}
private DemoUtil() {}
}

View File

@ -22,6 +22,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
@ -99,6 +100,12 @@ import java.util.Locale;
Log.d(TAG, "positionDiscontinuity");
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
Log.d(TAG, "playbackParameters " + String.format(
"[speed=%.2f, pitch=%.2f]", playbackParameters.speed, playbackParameters.pitch));
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
int periodCount = timeline.getPeriodCount();
@ -274,7 +281,7 @@ import java.util.Locale;
@Override
public void onRenderedFirstFrame(Surface surface) {
// Do nothing.
Log.d(TAG, "renderedFirstFrame [" + surface + "]");
}
// DefaultDrmSessionManager.EventListener

View File

@ -21,6 +21,7 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
@ -30,10 +31,11 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
@ -111,6 +113,7 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
private TrackSelectionHelper trackSelectionHelper;
private DebugTextViewHelper debugViewHelper;
private boolean needRetrySource;
private TrackGroupArray lastSeenTrackGroupArray;
private boolean shouldAutoPlay;
private int resumeWindow;
@ -183,8 +186,8 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initializePlayer();
} else {
@ -250,17 +253,21 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}
}
@SimpleExoPlayer.ExtensionRendererMode int extensionRendererMode =
@DefaultRenderersFactory.ExtensionRendererMode int extensionRendererMode =
((DemoApplication) getApplication()).useExtensionRenderers()
? (preferExtensionDecoders ? SimpleExoPlayer.EXTENSION_RENDERER_MODE_PREFER
: SimpleExoPlayer.EXTENSION_RENDERER_MODE_ON)
: SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF;
? (preferExtensionDecoders ? DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER
: DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON)
: DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF;
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(this,
drmSessionManager, extensionRendererMode);
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
trackSelectionHelper = new TrackSelectionHelper(trackSelector, videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, new DefaultLoadControl(),
drmSessionManager, extensionRendererMode);
lastSeenTrackGroupArray = null;
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector);
player.addListener(this);
eventLogger = new EventLogger(trackSelector);
@ -427,6 +434,11 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
// Do nothing.
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// Do nothing.
@ -472,18 +484,22 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}
@Override
@SuppressWarnings("ReferenceEquality")
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
updateButtonVisibilities();
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_video);
}
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_AUDIO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_audio);
if (trackGroups != lastSeenTrackGroupArray) {
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_video);
}
if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_AUDIO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_audio);
}
}
lastSeenTrackGroupArray = trackGroups;
}
}

View File

@ -21,13 +21,11 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckedTextView;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -37,9 +35,7 @@ import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedT
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.RandomTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.Arrays;
import java.util.Locale;
/**
* Helper class for displaying track selection dialogs.
@ -157,7 +153,7 @@ import java.util.Locale;
CheckedTextView trackView = (CheckedTextView) inflater.inflate(
trackViewLayoutId, root, false);
trackView.setBackgroundResource(selectableItemBackgroundResourceId);
trackView.setText(buildTrackName(group.getFormat(trackIndex)));
trackView.setText(DemoUtil.buildTrackName(group.getFormat(trackIndex)));
if (trackInfo.getTrackFormatSupport(rendererIndex, groupIndex, trackIndex)
== RendererCapabilities.FORMAT_HANDLED) {
trackView.setFocusable(true);
@ -296,57 +292,4 @@ import java.util.Locale;
return tracks;
}
// Track name construction.
private static String buildTrackName(Format format) {
String trackName;
if (MimeTypes.isVideo(format.sampleMimeType)) {
trackName = joinWithSeparator(joinWithSeparator(joinWithSeparator(
buildResolutionString(format), buildBitrateString(format)), buildTrackIdString(format)),
buildSampleMimeTypeString(format));
} else if (MimeTypes.isAudio(format.sampleMimeType)) {
trackName = joinWithSeparator(joinWithSeparator(joinWithSeparator(joinWithSeparator(
buildLanguageString(format), buildAudioPropertyString(format)),
buildBitrateString(format)), buildTrackIdString(format)),
buildSampleMimeTypeString(format));
} else {
trackName = joinWithSeparator(joinWithSeparator(joinWithSeparator(buildLanguageString(format),
buildBitrateString(format)), buildTrackIdString(format)),
buildSampleMimeTypeString(format));
}
return trackName.length() == 0 ? "unknown" : trackName;
}
private static String buildResolutionString(Format format) {
return format.width == Format.NO_VALUE || format.height == Format.NO_VALUE
? "" : format.width + "x" + format.height;
}
private static String buildAudioPropertyString(Format format) {
return format.channelCount == Format.NO_VALUE || format.sampleRate == Format.NO_VALUE
? "" : format.channelCount + "ch, " + format.sampleRate + "Hz";
}
private static String buildLanguageString(Format format) {
return TextUtils.isEmpty(format.language) || "und".equals(format.language) ? ""
: format.language;
}
private static String buildBitrateString(Format format) {
return format.bitrate == Format.NO_VALUE ? ""
: String.format(Locale.US, "%.2fMbit", format.bitrate / 1000000f);
}
private static String joinWithSeparator(String first, String second) {
return first.length() == 0 ? second : (second.length() == 0 ? first : first + ", " + second);
}
private static String buildTrackIdString(Format format) {
return format.id == null ? "" : ("id:" + format.id);
}
private static String buildSampleMimeTypeString(Format format) {
return format.sampleMimeType == null ? "" : format.sampleMimeType;
}
}

View File

@ -29,13 +29,18 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
compile files('libs/cronet_api.jar')
compile files('libs/cronet_impl_common_java.jar')
compile files('libs/cronet_impl_native_java.jar')
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
androidTestCompile 'org.mockito:mockito-core:1.9.5'
androidTestCompile project(':library')
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.google.dexmaker:dexmaker:' + dexmakerVersion
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:' + dexmakerVersion
androidTestCompile 'org.mockito:mockito-core:' + mockitoVersion
androidTestCompile 'com.android.support.test:runner:' + testSupportLibraryVersion
}
ext {
javadocTitle = 'Cronet extension'
}
apply from: '../../javadoc_library.gradle'

View File

@ -72,7 +72,7 @@ public final class CronetDataSourceFactory extends BaseFactory {
protected CronetDataSource createDataSourceInternal(HttpDataSource.RequestProperties
defaultRequestProperties) {
return new CronetDataSource(cronetEngine, executor, contentTypePredicate, transferListener,
connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects, null, defaultRequestProperties);
connectTimeoutMs, readTimeoutMs, resetTimeoutOnRedirects, defaultRequestProperties);
}
}

View File

@ -31,21 +31,18 @@ FFMPEG_EXT_PATH="${EXOPLAYER_ROOT}/extensions/ffmpeg/src/main"
NDK_PATH="<path to Android NDK>"
```
* Fetch and build FFmpeg. For example, to fetch and build for armv7a:
* Set up host platform ("darwin-x86_64" for Mac OS X):
```
cd "${FFMPEG_EXT_PATH}/jni" && \
git clone git://source.ffmpeg.org/ffmpeg ffmpeg && cd ffmpeg && \
./configure \
--libdir=android-libs/armeabi-v7a \
--arch=arm \
--cpu=armv7-a \
--cross-prefix="${NDK_PATH}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-" \
HOST_PLATFORM="linux-x86_64"
```
* Fetch and build FFmpeg. For example, to fetch and build for armeabi-v7a,
arm64-v8a and x86 on Linux x86_64:
```
COMMON_OPTIONS="\
--target-os=android \
--sysroot="${NDK_PATH}/platforms/android-9/arch-arm/" \
--extra-cflags="-march=armv7-a -mfloat-abi=softfp" \
--extra-ldflags="-Wl,--fix-cortex-a8" \
--extra-ldexeflags=-pie \
--disable-static \
--enable-shared \
--disable-doc \
@ -57,22 +54,56 @@ git clone git://source.ffmpeg.org/ffmpeg ffmpeg && cd ffmpeg && \
--disable-postproc \
--disable-avfilter \
--disable-symver \
--disable-swresample \
--enable-avresample \
--enable-decoder=vorbis \
--enable-decoder=opus \
--enable-decoder=flac \
--enable-decoder=alac \
" && \
cd "${FFMPEG_EXT_PATH}/jni" && \
git clone git://source.ffmpeg.org/ffmpeg ffmpeg && cd ffmpeg && \
./configure \
--libdir=android-libs/armeabi-v7a \
--arch=arm \
--cpu=armv7-a \
--cross-prefix="${NDK_PATH}/toolchains/arm-linux-androideabi-4.9/prebuilt/${HOST_PLATFORM}/bin/arm-linux-androideabi-" \
--sysroot="${NDK_PATH}/platforms/android-9/arch-arm/" \
--extra-cflags="-march=armv7-a -mfloat-abi=softfp" \
--extra-ldflags="-Wl,--fix-cortex-a8" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS} \
&& \
make -j4 && \
make install-libs
make -j4 && make install-libs && \
make clean && ./configure \
--libdir=android-libs/arm64-v8a \
--arch=aarch64 \
--cpu=armv8-a \
--cross-prefix="${NDK_PATH}/toolchains/aarch64-linux-android-4.9/prebuilt/${HOST_PLATFORM}/bin/aarch64-linux-android-" \
--sysroot="${NDK_PATH}/platforms/android-21/arch-arm64/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS} \
&& \
make -j4 && make install-libs && \
make clean && ./configure \
--libdir=android-libs/x86 \
--arch=x86 \
--cpu=i686 \
--cross-prefix="${NDK_PATH}/toolchains/x86-4.9/prebuilt/${HOST_PLATFORM}/bin/i686-linux-android-" \
--sysroot="${NDK_PATH}/platforms/android-9/arch-x86/" \
--extra-ldexeflags=-pie \
--disable-asm \
${COMMON_OPTIONS} \
&& \
make -j4 && make install-libs && \
make clean
```
* Build the JNI native libraries. Repeat this step for any other architectures
you need to support.
* Build the JNI native libraries, setting `APP_ABI` to include the architectures
built in the previous step. For example:
```
cd "${FFMPEG_EXT_PATH}"/jni && \
${NDK_PATH}/ndk-build APP_ABI=armeabi-v7a -j4
${NDK_PATH}/ndk-build APP_ABI="armeabi-v7a arm64-v8a x86" -j4
```
* In your project, you can add a dependency on the extension by using a rule

View File

@ -30,5 +30,10 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
}
ext {
javadocTitle = 'FFmpeg extension'
}
apply from: '../../javadoc_library.gradle'

View File

@ -31,15 +31,10 @@ LOCAL_MODULE := libavresample
LOCAL_SRC_FILES := ffmpeg/android-libs/$(TARGET_ARCH_ABI)/$(LOCAL_MODULE).so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libswresample
LOCAL_SRC_FILES := ffmpeg/android-libs/$(TARGET_ARCH_ABI)/$(LOCAL_MODULE).so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := ffmpeg_jni.cc
LOCAL_C_INCLUDES := ffmpeg
LOCAL_SHARED_LIBRARIES := libavcodec libavresample libavutil libswresample
LOCAL_SHARED_LIBRARIES := libavcodec libavresample libavutil
LOCAL_LDLIBS := -Lffmpeg/android-libs/$(TARGET_ARCH_ABI) -llog
include $(BUILD_SHARED_LIBRARY)

View File

@ -30,7 +30,11 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
androidTestCompile project(':testutils')
}
ext {
javadocTitle = 'FLAC extension'
}
apply from: '../../javadoc_library.gradle'

View File

@ -22,6 +22,7 @@ import android.test.InstrumentationTestCase;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
@ -102,6 +103,11 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
// Do nothing.
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
// Do nothing.
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// Do nothing.

View File

@ -24,10 +24,15 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
compile 'com.google.vr:sdk-audio:1.30.0'
}
ext {
javadocTitle = 'GVR extension'
}
apply from: '../../javadoc_library.gradle'
ext {
releaseArtifact = 'extension-gvr'
releaseDescription = 'Google VR extension for ExoPlayer.'

View File

@ -152,14 +152,19 @@ public final class GvrAudioProcessor implements AudioProcessor {
@Override
public void flush() {
gvrAudioSurround.flush();
if (gvrAudioSurround != null) {
gvrAudioSurround.flush();
}
inputEnded = false;
}
@Override
public synchronized void release() {
buffer = null;
public synchronized void reset() {
maybeReleaseGvrAudioSurround();
inputEnded = false;
buffer = null;
sampleRateHz = Format.NO_VALUE;
channelCount = Format.NO_VALUE;
}
private void maybeReleaseGvrAudioSurround() {

View File

@ -29,12 +29,17 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
compile('com.squareup.okhttp3:okhttp:3.6.0') {
exclude group: 'org.json'
}
}
ext {
javadocTitle = 'OkHttp extension'
}
apply from: '../../javadoc_library.gradle'
ext {
releaseArtifact = 'extension-okhttp'
releaseDescription = 'OkHttp extension for ExoPlayer.'

View File

@ -30,5 +30,10 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
}
ext {
javadocTitle = 'Opus extension'
}
apply from: '../../javadoc_library.gradle'

View File

@ -22,6 +22,7 @@ import android.test.InstrumentationTestCase;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
@ -102,6 +103,11 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
// Do nothing.
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
// Do nothing.
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// Do nothing.

View File

@ -161,7 +161,7 @@ import java.util.List;
cryptoInfo.key, cryptoInfo.iv, cryptoInfo.numSubSamples,
cryptoInfo.numBytesOfClearData, cryptoInfo.numBytesOfEncryptedData)
: opusDecode(nativeDecoderContext, inputBuffer.timeUs, inputData, inputData.limit(),
outputBuffer, SAMPLE_RATE);
outputBuffer);
if (result < 0) {
if (result == DRM_ERROR) {
String message = "Drm error: " + opusGetErrorMessage(nativeDecoderContext);
@ -210,7 +210,7 @@ import java.util.List;
private native long opusInit(int sampleRate, int channelCount, int numStreams, int numCoupled,
int gain, byte[] streamMap);
private native int opusDecode(long decoder, long timeUs, ByteBuffer inputBuffer, int inputSize,
SimpleOutputBuffer outputBuffer, int sampleRate);
SimpleOutputBuffer outputBuffer);
private native int opusSecureDecode(long decoder, long timeUs, ByteBuffer inputBuffer,
int inputSize, SimpleOutputBuffer outputBuffer, int sampleRate,
ExoMediaCrypto mediaCrypto, int inputMode, byte[] key, byte[] iv,

View File

@ -59,6 +59,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
}
static const int kBytesPerSample = 2; // opus fixed point uses 16 bit samples.
static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
static int channelCount;
static int errorCode;
@ -92,16 +93,14 @@ DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount,
}
DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs,
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer,
jint sampleRate) {
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer) {
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
const uint8_t* inputBuffer =
reinterpret_cast<const uint8_t*>(
env->GetDirectBufferAddress(jInputBuffer));
const int32_t inputSampleCount =
opus_packet_get_nb_samples(inputBuffer, inputSize, sampleRate);
const jint outputSize = inputSampleCount * kBytesPerSample * channelCount;
const jint outputSize =
kMaxOpusOutputPacketSizeSamples * kBytesPerSample * channelCount;
env->CallObjectMethod(jOutputBuffer, outputBufferInit, jTimeUs, outputSize);
const jobject jOutputBufferData = env->CallObjectMethod(jOutputBuffer,
@ -110,7 +109,7 @@ DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs,
int16_t* outputBufferData = reinterpret_cast<int16_t*>(
env->GetDirectBufferAddress(jOutputBufferData));
int sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize,
outputBufferData, outputSize, 0);
outputBufferData, kMaxOpusOutputPacketSizeSamples, 0);
// record error code
errorCode = (sampleCount < 0) ? sampleCount : 0;
return (sampleCount < 0) ? sampleCount

View File

@ -49,7 +49,7 @@ git clone https://chromium.googlesource.com/libyuv/libyuv libyuv
cd "${VP9_EXT_PATH}/jni/libvpx" && \
git checkout tags/v1.6.1 -b v1.6.1 && \
cd "${VP9_EXT_PATH}/jni/libyuv" && \
git checkout e2611a73
git checkout 996a2bbd
```
* Run a script that generates necessary configuration files for libvpx:

View File

@ -30,6 +30,10 @@ android {
}
dependencies {
compile project(':library')
compile project(':library-core')
}
ext {
javadocTitle = 'VP9 extension'
}
apply from: '../../javadoc_library.gradle'

View File

@ -23,6 +23,7 @@ import android.util.Log;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
@ -134,6 +135,11 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
// Do nothing.
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
// Do nothing.
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
// Do nothing.

View File

@ -87,8 +87,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
private boolean inputStreamEnded;
private boolean outputStreamEnded;
private int lastReportedWidth;
private int lastReportedHeight;
private int reportedWidth;
private int reportedHeight;
private long droppedFrameAccumulationStartTimeMs;
private int droppedFrames;
@ -147,10 +147,10 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
this.drmSessionManager = drmSessionManager;
this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
joiningDeadlineMs = -1;
clearLastReportedVideoSize();
joiningDeadlineMs = C.TIME_UNSET;
clearReportedVideoSize();
formatHolder = new FormatHolder();
flagsOnlyBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance();
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
outputMode = VpxDecoder.OUTPUT_MODE_NONE;
}
@ -185,44 +185,40 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
}
}
if (isRendererAvailable()) {
drmSession = pendingDrmSession;
ExoMediaCrypto mediaCrypto = null;
if (drmSession != null) {
int drmSessionState = drmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
} else if (drmSessionState == DrmSession.STATE_OPENED
|| drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
mediaCrypto = drmSession.getMediaCrypto();
} else {
// The drm session isn't open yet.
return;
}
// We have a format.
drmSession = pendingDrmSession;
ExoMediaCrypto mediaCrypto = null;
if (drmSession != null) {
int drmSessionState = drmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
} else if (drmSessionState == DrmSession.STATE_OPENED
|| drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
mediaCrypto = drmSession.getMediaCrypto();
} else {
// The drm session isn't open yet.
return;
}
try {
if (decoder == null) {
// If we don't have a decoder yet, we need to instantiate one.
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createVpxDecoder");
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE,
mediaCrypto);
decoder.setOutputMode(outputMode);
TraceUtil.endSection();
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp,
codecInitializedTimestamp - codecInitializingTimestamp);
decoderCounters.decoderInitCount++;
}
TraceUtil.beginSection("drainAndFeed");
while (drainOutputBuffer(positionUs)) {}
while (feedInputBuffer()) {}
}
try {
if (decoder == null) {
// If we don't have a decoder yet, we need to instantiate one.
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createVpxDecoder");
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE, mediaCrypto);
decoder.setOutputMode(outputMode);
TraceUtil.endSection();
} catch (VpxDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp,
codecInitializedTimestamp - codecInitializingTimestamp);
decoderCounters.decoderInitCount++;
}
} else {
skipToKeyframeBefore(positionUs);
TraceUtil.beginSection("drainAndFeed");
while (drainOutputBuffer(positionUs)) {}
while (feedInputBuffer()) {}
TraceUtil.endSection();
} catch (VpxDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
}
decoderCounters.ensureUpdated();
}
@ -257,27 +253,26 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return false;
}
// Drop the frame if we're joining and are more than 30ms late, or if we have the next frame
// and that's also late. Else we'll render what we have.
if ((joiningDeadlineMs != -1 && outputBuffer.timeUs < positionUs - 30000)
|| (nextOutputBuffer != null && !nextOutputBuffer.isEndOfStream()
&& nextOutputBuffer.timeUs < positionUs)) {
decoderCounters.droppedOutputBufferCount++;
droppedFrames++;
consecutiveDroppedFrameCount++;
decoderCounters.maxConsecutiveDroppedOutputBufferCount = Math.max(
consecutiveDroppedFrameCount,
decoderCounters.maxConsecutiveDroppedOutputBufferCount);
if (droppedFrames == maxDroppedFramesToNotify) {
maybeNotifyDroppedFrames();
if (outputMode == VpxDecoder.OUTPUT_MODE_NONE) {
// Skip frames in sync with playback, so we'll be at the right frame if the mode changes.
if (outputBuffer.timeUs <= positionUs) {
skipBuffer();
return true;
}
outputBuffer.release();
outputBuffer = null;
return false;
}
final long nextOutputBufferTimeUs =
nextOutputBuffer != null && !nextOutputBuffer.isEndOfStream()
? nextOutputBuffer.timeUs : C.TIME_UNSET;
if (shouldDropOutputBuffer(
outputBuffer.timeUs, nextOutputBufferTimeUs, positionUs, joiningDeadlineMs)) {
dropBuffer();
return true;
}
// If we have not rendered any frame so far (either initially or immediately following a seek),
// render one frame irrespective of the state or current position.
// If we have yet to render a frame to the current output (either initially or immediately
// following a seek), render one irrespective of the state or current position.
if (!renderedFirstFrame
|| (getState() == STATE_STARTED && outputBuffer.timeUs <= positionUs + 30000)) {
renderBuffer();
@ -285,27 +280,63 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return false;
}
/**
* Returns whether the current frame should be dropped.
*
* @param outputBufferTimeUs The timestamp of the current output buffer.
* @param nextOutputBufferTimeUs The timestamp of the next output buffer or
* {@link TIME_UNSET} if the next output buffer is unavailable.
* @param positionUs The current playback position.
* @param joiningDeadlineMs The joining deadline.
* @return Returns whether to drop the current output buffer.
*/
protected boolean shouldDropOutputBuffer(long outputBufferTimeUs, long nextOutputBufferTimeUs,
long positionUs, long joiningDeadlineMs) {
// Drop the frame if we're joining and are more than 30ms late, or if we have the next frame
// and that's also late. Else we'll render what we have.
return (joiningDeadlineMs != C.TIME_UNSET && outputBufferTimeUs < positionUs - 30000)
|| (nextOutputBufferTimeUs != C.TIME_UNSET && nextOutputBufferTimeUs < positionUs);
}
private void renderBuffer() {
decoderCounters.renderedOutputBufferCount++;
consecutiveDroppedFrameCount = 0;
maybeNotifyVideoSizeChanged(outputBuffer.width, outputBuffer.height);
if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_RGB && surface != null) {
renderRgbFrame(outputBuffer, scaleToFit);
if (!renderedFirstFrame) {
renderedFirstFrame = true;
eventDispatcher.renderedFirstFrame(surface);
}
outputBuffer.release();
} else if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_YUV && outputBufferRenderer != null) {
// The renderer will release the buffer.
outputBufferRenderer.setOutputBuffer(outputBuffer);
if (!renderedFirstFrame) {
renderedFirstFrame = true;
eventDispatcher.renderedFirstFrame(null);
}
int bufferMode = outputBuffer.mode;
boolean renderRgb = bufferMode == VpxDecoder.OUTPUT_MODE_RGB && surface != null;
boolean renderYuv = bufferMode == VpxDecoder.OUTPUT_MODE_YUV && outputBufferRenderer != null;
if (!renderRgb && !renderYuv) {
dropBuffer();
} else {
outputBuffer.release();
maybeNotifyVideoSizeChanged(outputBuffer.width, outputBuffer.height);
if (renderRgb) {
renderRgbFrame(outputBuffer, scaleToFit);
outputBuffer.release();
} else /* renderYuv */ {
outputBufferRenderer.setOutputBuffer(outputBuffer);
// The renderer will release the buffer.
}
outputBuffer = null;
consecutiveDroppedFrameCount = 0;
decoderCounters.renderedOutputBufferCount++;
maybeNotifyRenderedFirstFrame();
}
}
private void dropBuffer() {
decoderCounters.droppedOutputBufferCount++;
droppedFrames++;
consecutiveDroppedFrameCount++;
decoderCounters.maxConsecutiveDroppedOutputBufferCount = Math.max(
consecutiveDroppedFrameCount, decoderCounters.maxConsecutiveDroppedOutputBufferCount);
if (droppedFrames == maxDroppedFramesToNotify) {
maybeNotifyDroppedFrames();
}
outputBuffer.release();
outputBuffer = null;
}
private void skipBuffer() {
decoderCounters.skippedOutputBufferCount++;
outputBuffer.release();
outputBuffer = null;
}
@ -406,11 +437,11 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return false;
}
if (format != null && (isSourceReady() || outputBuffer != null)
&& (renderedFirstFrame || !isRendererAvailable())) {
&& (renderedFirstFrame || outputMode == VpxDecoder.OUTPUT_MODE_NONE)) {
// Ready. If we were joining then we've now joined, so clear the joining deadline.
joiningDeadlineMs = -1;
joiningDeadlineMs = C.TIME_UNSET;
return true;
} else if (joiningDeadlineMs == -1) {
} else if (joiningDeadlineMs == C.TIME_UNSET) {
// Not joining.
return false;
} else if (SystemClock.elapsedRealtime() < joiningDeadlineMs) {
@ -418,7 +449,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return true;
} else {
// The joining deadline has been exceeded. Give up and clear the deadline.
joiningDeadlineMs = -1;
joiningDeadlineMs = C.TIME_UNSET;
return false;
}
}
@ -433,24 +464,27 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
protected void onPositionReset(long positionUs, boolean joining) {
inputStreamEnded = false;
outputStreamEnded = false;
renderedFirstFrame = false;
clearRenderedFirstFrame();
consecutiveDroppedFrameCount = 0;
if (decoder != null) {
flushDecoder();
}
joiningDeadlineMs = joining && allowedJoiningTimeMs > 0
? (SystemClock.elapsedRealtime() + allowedJoiningTimeMs) : -1;
if (joining) {
setJoiningDeadlineMs();
} else {
joiningDeadlineMs = C.TIME_UNSET;
}
}
@Override
protected void onStarted() {
droppedFrames = 0;
droppedFrameAccumulationStartTimeMs = SystemClock.elapsedRealtime();
joiningDeadlineMs = C.TIME_UNSET;
}
@Override
protected void onStopped() {
joiningDeadlineMs = -1;
maybeNotifyDroppedFrames();
}
@ -460,7 +494,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
outputBuffer = null;
format = null;
waitingForKeys = false;
clearLastReportedVideoSize();
clearReportedVideoSize();
clearRenderedFirstFrame();
try {
releaseDecoder();
} finally {
@ -537,47 +572,78 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
private void setOutput(Surface surface, VpxOutputBufferRenderer outputBufferRenderer) {
// At most one output may be non-null. Both may be null if the output is being cleared.
Assertions.checkState(surface == null || outputBufferRenderer == null);
// Clear state so that we always call the event listener with the video size and when a frame
// is rendered, even if the output hasn't changed.
renderedFirstFrame = false;
clearLastReportedVideoSize();
// We only need to update the decoder if the output has changed.
if (this.surface != surface || this.outputBufferRenderer != outputBufferRenderer) {
// The output has changed.
this.surface = surface;
this.outputBufferRenderer = outputBufferRenderer;
outputMode = outputBufferRenderer != null ? VpxDecoder.OUTPUT_MODE_YUV
: surface != null ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE;
updateDecoder();
}
}
private void updateDecoder() {
if (decoder != null) {
if (outputMode == VpxDecoder.OUTPUT_MODE_NONE) {
releaseDecoder();
if (outputMode != VpxDecoder.OUTPUT_MODE_NONE) {
if (decoder != null) {
decoder.setOutputMode(outputMode);
}
// If we know the video size, report it again immediately.
maybeRenotifyVideoSizeChanged();
// We haven't rendered to the new output yet.
clearRenderedFirstFrame();
if (getState() == STATE_STARTED) {
setJoiningDeadlineMs();
}
} else {
decoder.setOutputMode(outputMode);
// The output has been removed. We leave the outputMode of the underlying decoder unchanged
// in anticipation that a subsequent output will likely be of the same type.
clearReportedVideoSize();
clearRenderedFirstFrame();
}
} else if (outputMode != VpxDecoder.OUTPUT_MODE_NONE) {
// The output is unchanged and non-null. If we know the video size and/or have already
// rendered to the output, report these again immediately.
maybeRenotifyVideoSizeChanged();
maybeRenotifyRenderedFirstFrame();
}
}
private boolean isRendererAvailable() {
return surface != null || outputBufferRenderer != null;
private void setJoiningDeadlineMs() {
joiningDeadlineMs = allowedJoiningTimeMs > 0
? (SystemClock.elapsedRealtime() + allowedJoiningTimeMs) : C.TIME_UNSET;
}
private void clearLastReportedVideoSize() {
lastReportedWidth = Format.NO_VALUE;
lastReportedHeight = Format.NO_VALUE;
private void clearRenderedFirstFrame() {
renderedFirstFrame = false;
}
private void maybeNotifyRenderedFirstFrame() {
if (!renderedFirstFrame) {
renderedFirstFrame = true;
eventDispatcher.renderedFirstFrame(surface);
}
}
private void maybeRenotifyRenderedFirstFrame() {
if (renderedFirstFrame) {
eventDispatcher.renderedFirstFrame(surface);
}
}
private void clearReportedVideoSize() {
reportedWidth = Format.NO_VALUE;
reportedHeight = Format.NO_VALUE;
}
private void maybeNotifyVideoSizeChanged(int width, int height) {
if (lastReportedWidth != width || lastReportedHeight != height) {
lastReportedWidth = width;
lastReportedHeight = height;
if (reportedWidth != width || reportedHeight != height) {
reportedWidth = width;
reportedHeight = height;
eventDispatcher.videoSizeChanged(width, height, 0, 1);
}
}
private void maybeRenotifyVideoSizeChanged() {
if (reportedWidth != Format.NO_VALUE || reportedHeight != Format.NO_VALUE) {
eventDispatcher.videoSizeChanged(reportedWidth, reportedHeight, 0, 1);
}
}
private void maybeNotifyDroppedFrames() {
if (droppedFrames > 0) {
long now = SystemClock.elapsedRealtime();

View File

@ -21,6 +21,7 @@ LIBYUV_ROOT := $(WORKING_DIR)/libyuv
# build libyuv_static.a
LOCAL_PATH := $(WORKING_DIR)
LIBYUV_DISABLE_JPEG := "yes"
include $(LIBYUV_ROOT)/Android.mk
# build libvpx.so

View File

@ -68,7 +68,7 @@ limit=$((${#arch[@]} - 1))
# everything else will be removed.
allowed_files="libvpx_srcs.txt vpx_config.c vpx_config.h vpx_scale_rtcd.h"
allowed_files+=" vp8_rtcd.h vp9_rtcd.h vpx_version.h vpx_config.asm"
allowed_files+=" vpx_dsp_rtcd.h"
allowed_files+=" vpx_dsp_rtcd.h libvpx.ver"
remove_trailing_whitespace() {
perl -pi -e 's/\s\+$//' "$@"

View File

@ -37,9 +37,7 @@ LOCAL_SRC_FILES += $(addprefix libvpx/, $(filter-out vpx_config.c, \
# include assembly files if they exist
# "%.asm.[sS]" covers neon assembly and "%.asm" covers x86 assembly
LOCAL_SRC_FILES += $(addprefix libvpx/, \
$(filter %.asm.s %.asm, $(libvpx_codec_srcs)))
LOCAL_SRC_FILES += $(addprefix libvpx/, \
$(filter %.asm.S %.asm, $(libvpx_codec_srcs)))
$(filter %.asm.s %.asm.S %.asm, $(libvpx_codec_srcs)))
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
# append .neon to *_neon.c and *.[sS]
@ -48,10 +46,8 @@ LOCAL_SRC_FILES := $(subst .s,.s.neon,$(LOCAL_SRC_FILES))
LOCAL_SRC_FILES := $(subst .S,.S.neon,$(LOCAL_SRC_FILES))
endif
# remove duplicates
LOCAL_SRC_FILES := $(sort $(LOCAL_SRC_FILES))
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/libvpx \
$(LOCAL_PATH)/libvpx/vpx
LOCAL_LDFLAGS := -Wl,--version-script=$(CONFIG_DIR)/libvpx.ver
include $(BUILD_SHARED_LIBRARY)

View File

@ -20,8 +20,9 @@
#include <android/log.h>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <new>
#include "libyuv.h" // NOLINT

68
javadoc_combined.gradle Normal file
View File

@ -0,0 +1,68 @@
// Copyright (C) 2017 The Android Open Source Project
//
// 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.
class CombinedJavadocPlugin implements Plugin<Project> {
static final String TASK_NAME = "generateCombinedJavadoc"
@Override
void apply(Project project) {
project.gradle.projectsEvaluated {
Set<Project> libraryModules = getLibraryModules(project)
if (!libraryModules.isEmpty()) {
String sdkDirectory = getSdkDirectory(libraryModules)
project.task(TASK_NAME, type: Javadoc) {
description = "Generates combined Javadoc."
title = "ExoPlayer library"
source = libraryModules.generateJavadoc.source
classpath = project.files(libraryModules.generateJavadoc.classpath)
destinationDir = project.file("$project.buildDir/docs/javadoc")
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "https://developer.android.com/reference",
"${sdkDirectory}/docs/reference"
encoding = "UTF-8"
}
exclude "**/BuildConfig.java"
exclude "**/R.java"
destinationDir project.file("$project.buildDir/docs/javadoc")
doLast {
libraryModules.each { libraryModule ->
project.copy {
from "${libraryModule.projectDir}/src/main/javadoc"
into "${project.buildDir}/docs/javadoc"
}
}
}
}
}
}
}
// Returns Android library modules that declare a generateJavadoc task.
private Set<Project> getLibraryModules(Project project) {
project.subprojects.findAll {
it.plugins.findPlugin("com.android.library") &&
it.tasks.findByName("generateJavadoc")
}
}
// Returns the Android SDK directory given a set of Android library modules.
private String getSdkDirectory(Set<Project> libraryModules) {
// We can retrieve the Android SDK directory from any module.
return libraryModules.iterator().next().android.sdkDirectory
}
}
apply plugin: CombinedJavadocPlugin

40
javadoc_library.gradle Normal file
View File

@ -0,0 +1,40 @@
// Copyright (C) 2017 The Android Open Source Project
//
// 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.
android.libraryVariants.all { variant ->
def name = variant.buildType.name
if (!name.equals("release")) {
return; // Skip non-release builds.
}
task("generateJavadoc", type: Javadoc) {
description = "Generates Javadoc for the ${javadocTitle}."
title = "ExoPlayer ${javadocTitle}"
source = variant.javaCompile.source
classpath = files(variant.javaCompile.classpath.files,
project.android.getBootClasspath())
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "https://developer.android.com/reference",
"${android.sdkDirectory}/docs/reference"
encoding = "UTF-8"
}
exclude "**/BuildConfig.java"
exclude "**/R.java"
doLast {
copy {
from "src/main/javadoc"
into "$buildDir/docs/javadoc"
}
}
}
}

38
library/all/build.gradle Normal file
View File

@ -0,0 +1,38 @@
// Copyright (C) 2016 The Android Open Source Project
//
// 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.
apply plugin: 'com.android.library'
android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
defaultConfig {
minSdkVersion project.ext.minSdkVersion
targetSdkVersion project.ext.targetSdkVersion
}
}
dependencies {
compile project(':library-core')
compile project(':library-dash')
compile project(':library-hls')
compile project(':library-smoothstreaming')
compile project(':library-ui')
}
ext {
releaseArtifact = 'exoplayer'
releaseDescription = 'The ExoPlayer library (all modules).'
}
apply from: '../../publish.gradle'

View File

@ -1,87 +0,0 @@
// Copyright (C) 2016 The Android Open Source Project
//
// 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.
import com.android.builder.core.BuilderConstants
apply plugin: 'com.android.library'
android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
defaultConfig {
minSdkVersion project.ext.minSdkVersion
targetSdkVersion project.ext.targetSdkVersion
consumerProguardFiles 'proguard-rules.txt'
}
buildTypes {
// Re-enable test coverage when the following issue is fixed:
// https://code.google.com/p/android/issues/detail?id=226070
// debug {
// testCoverageEnabled = true
// }
}
sourceSets {
androidTest {
java.srcDirs += "../testutils/src/main/java/"
}
}
}
dependencies {
compile 'com.android.support:support-annotations:25.2.0'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
androidTestCompile 'org.mockito:mockito-core:1.9.5'
}
android.libraryVariants.all { variant ->
def name = variant.buildType.name
if (name.equals(BuilderConstants.DEBUG)) {
return; // Skip debug builds.
}
def task = project.tasks.create "jar${name.capitalize()}", Jar
task.dependsOn variant.javaCompile
task.from variant.javaCompile.destinationDir
artifacts.add('archives', task);
}
android.libraryVariants.all { variant ->
task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
title = "ExoPlayer library"
description "Generates Javadoc for $variant.name."
source = variant.javaCompile.source
classpath = files(variant.javaCompile.classpath.files, project.android.getBootClasspath())
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "https://developer.android.com/reference","${android.sdkDirectory}/docs/reference"
encoding = 'UTF-8'
}
exclude '**/BuildConfig.java'
exclude '**/R.java'
doLast {
copy {
from "src/main/javadoc"
into "$buildDir/docs/javadoc"
}
}
}
}
ext {
releaseArtifact = 'exoplayer'
releaseDescription = 'The ExoPlayer library.'
}
apply from: '../publish.gradle'

54
library/core/build.gradle Normal file
View File

@ -0,0 +1,54 @@
// Copyright (C) 2016 The Android Open Source Project
//
// 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.
apply plugin: 'com.android.library'
android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion
defaultConfig {
minSdkVersion project.ext.minSdkVersion
targetSdkVersion project.ext.targetSdkVersion
}
sourceSets {
androidTest {
java.srcDirs += "../../testutils/src/main/java/"
}
}
buildTypes {
debug {
testCoverageEnabled = true
}
}
}
dependencies {
compile 'com.android.support:support-annotations:' + supportLibraryVersion
androidTestCompile 'com.google.dexmaker:dexmaker:' + dexmakerVersion
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:' + dexmakerVersion
androidTestCompile 'org.mockito:mockito-core:' + mockitoVersion
}
ext {
javadocTitle = 'Core module'
}
apply from: '../../javadoc_library.gradle'
ext {
releaseArtifact = 'exoplayer-core'
releaseDescription = 'The ExoPlayer library core module.'
}
apply from: '../../publish.gradle'

View File

@ -16,7 +16,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.google.android.exoplayer2.test">
package="com.google.android.exoplayer2.core.test">
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="24"/>
@ -27,7 +27,7 @@
</application>
<instrumentation
android:targetPackage="com.google.android.exoplayer2.test"
android:targetPackage="com.google.android.exoplayer2.core.test"
android:name="android.test.InstrumentationTestRunner"
tools:replace="android:targetPackage"/>

Some files were not shown because too many files have changed in this diff Show More