mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
commit
1c6149b4d7
27 changed files with 323 additions and 91 deletions
|
|
@ -1,5 +1,19 @@
|
||||||
# Release notes #
|
# Release notes #
|
||||||
|
|
||||||
|
### 2.7.2 ###
|
||||||
|
|
||||||
|
* Gradle: Upgrade Gradle version from 4.1 to 4.4 so it can work with Android
|
||||||
|
Studio 3.1 ([#3708](https://github.com/google/ExoPlayer/issues/3708)).
|
||||||
|
* Match codecs starting with "mp4a" to different Audio MimeTypes
|
||||||
|
([#3779](https://github.com/google/ExoPlayer/issues/3779)).
|
||||||
|
* Fix ANR issue on Redmi 4X and Redmi Note 4
|
||||||
|
([#4006](https://github.com/google/ExoPlayer/issues/4006)).
|
||||||
|
* Fix handling of zero padded strings when parsing Matroska streams
|
||||||
|
([#4010](https://github.com/google/ExoPlayer/issues/4010)).
|
||||||
|
* Fix "Decoder input buffer too small" error when playing some FLAC streams.
|
||||||
|
* MediaSession extension: Omit fast forward and rewind actions when media is not
|
||||||
|
seekable ([#4001](https://github.com/google/ExoPlayer/issues/4001)).
|
||||||
|
|
||||||
### 2.7.1 ###
|
### 2.7.1 ###
|
||||||
|
|
||||||
* Gradle: Replaced 'compile' (deprecated) with 'implementation' and
|
* Gradle: Replaced 'compile' (deprecated) with 'implementation' and
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ buildscript {
|
||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
classpath 'com.android.tools.build:gradle:3.1.0'
|
||||||
classpath 'com.novoda:bintray-release:0.5.0'
|
classpath 'com.novoda:bintray-release:0.8.1'
|
||||||
}
|
}
|
||||||
// Workaround for the following test coverage issue. Remove when fixed:
|
// Workaround for the following test coverage issue. Remove when fixed:
|
||||||
// https://code.google.com/p/android/issues/detail?id=226070
|
// https://code.google.com/p/android/issues/detail?id=226070
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
project.ext {
|
project.ext {
|
||||||
// ExoPlayer version and version code.
|
// ExoPlayer version and version code.
|
||||||
releaseVersion = '2.7.1'
|
releaseVersion = '2.7.2'
|
||||||
releaseVersionCode = 2701
|
releaseVersionCode = 2702
|
||||||
// Important: ExoPlayer specifies a minSdkVersion of 14 because various
|
// Important: ExoPlayer specifies a minSdkVersion of 14 because various
|
||||||
// components provided by the library may be of use on older devices.
|
// components provided by the library may be of use on older devices.
|
||||||
// However, please note that the core media playback functionality provided
|
// However, please note that the core media playback functionality provided
|
||||||
|
|
@ -22,7 +22,7 @@ project.ext {
|
||||||
minSdkVersion = 14
|
minSdkVersion = 14
|
||||||
targetSdkVersion = 27
|
targetSdkVersion = 27
|
||||||
compileSdkVersion = 27
|
compileSdkVersion = 27
|
||||||
buildToolsVersion = '26.0.2'
|
buildToolsVersion = '27.0.3'
|
||||||
testSupportLibraryVersion = '0.5'
|
testSupportLibraryVersion = '0.5'
|
||||||
supportLibraryVersion = '27.0.0'
|
supportLibraryVersion = '27.0.0'
|
||||||
playServicesLibraryVersion = '11.4.2'
|
playServicesLibraryVersion = '11.4.2'
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@ EXOPLAYER_ROOT="$(pwd)"
|
||||||
FFMPEG_EXT_PATH="${EXOPLAYER_ROOT}/extensions/ffmpeg/src/main"
|
FFMPEG_EXT_PATH="${EXOPLAYER_ROOT}/extensions/ffmpeg/src/main"
|
||||||
```
|
```
|
||||||
|
|
||||||
* Download the [Android NDK][] and set its location in an environment variable:
|
* Download the [Android NDK][] and set its location in an environment variable.
|
||||||
|
Only versions up to NDK 15c are supported currently.
|
||||||
|
|
||||||
```
|
```
|
||||||
NDK_PATH="<path to Android NDK>"
|
NDK_PATH="<path to Android NDK>"
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ track 0:
|
||||||
id = null
|
id = null
|
||||||
containerMimeType = null
|
containerMimeType = null
|
||||||
sampleMimeType = audio/raw
|
sampleMimeType = audio/raw
|
||||||
maxInputSize = -1
|
maxInputSize = 16384
|
||||||
width = -1
|
width = -1
|
||||||
height = -1
|
height = -1
|
||||||
frameRate = -1.0
|
frameRate = -1.0
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ track 0:
|
||||||
id = null
|
id = null
|
||||||
containerMimeType = null
|
containerMimeType = null
|
||||||
sampleMimeType = audio/raw
|
sampleMimeType = audio/raw
|
||||||
maxInputSize = -1
|
maxInputSize = 16384
|
||||||
width = -1
|
width = -1
|
||||||
height = -1
|
height = -1
|
||||||
frameRate = -1.0
|
frameRate = -1.0
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ track 0:
|
||||||
id = null
|
id = null
|
||||||
containerMimeType = null
|
containerMimeType = null
|
||||||
sampleMimeType = audio/raw
|
sampleMimeType = audio/raw
|
||||||
maxInputSize = -1
|
maxInputSize = 16384
|
||||||
width = -1
|
width = -1
|
||||||
height = -1
|
height = -1
|
||||||
frameRate = -1.0
|
frameRate = -1.0
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ track 0:
|
||||||
id = null
|
id = null
|
||||||
containerMimeType = null
|
containerMimeType = null
|
||||||
sampleMimeType = audio/raw
|
sampleMimeType = audio/raw
|
||||||
maxInputSize = -1
|
maxInputSize = 16384
|
||||||
width = -1
|
width = -1
|
||||||
height = -1
|
height = -1
|
||||||
frameRate = -1.0
|
frameRate = -1.0
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ public final class FlacExtractor implements Extractor {
|
||||||
MimeTypes.AUDIO_RAW,
|
MimeTypes.AUDIO_RAW,
|
||||||
null,
|
null,
|
||||||
streamInfo.bitRate(),
|
streamInfo.bitRate(),
|
||||||
Format.NO_VALUE,
|
streamInfo.maxDecodedFrameSize(),
|
||||||
streamInfo.channels,
|
streamInfo.channels,
|
||||||
streamInfo.sampleRate,
|
streamInfo.sampleRate,
|
||||||
getPcmEncoding(streamInfo.bitsPerSample),
|
getPcmEncoding(streamInfo.bitsPerSample),
|
||||||
|
|
|
||||||
|
|
@ -77,11 +77,10 @@ public class DefaultPlaybackController implements MediaSessionConnector.Playback
|
||||||
public long getSupportedPlaybackActions(Player player) {
|
public long getSupportedPlaybackActions(Player player) {
|
||||||
if (player == null || player.getCurrentTimeline().isEmpty()) {
|
if (player == null || player.getCurrentTimeline().isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (!player.isCurrentWindowSeekable()) {
|
||||||
|
return BASE_ACTIONS;
|
||||||
}
|
}
|
||||||
long actions = BASE_ACTIONS;
|
long actions = BASE_ACTIONS | PlaybackStateCompat.ACTION_SEEK_TO;
|
||||||
if (player.isCurrentWindowSeekable()) {
|
|
||||||
actions |= PlaybackStateCompat.ACTION_SEEK_TO;
|
|
||||||
}
|
|
||||||
if (fastForwardIncrementMs > 0) {
|
if (fastForwardIncrementMs > 0) {
|
||||||
actions |= PlaybackStateCompat.ACTION_FAST_FORWARD;
|
actions |= PlaybackStateCompat.ACTION_FAST_FORWARD;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
apply from: "${rootDir}/javadoc_util.gradle"
|
||||||
|
|
||||||
class CombinedJavadocPlugin implements Plugin<Project> {
|
class CombinedJavadocPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
static final String TASK_NAME = "generateCombinedJavadoc"
|
static final String TASK_NAME = "generateCombinedJavadoc"
|
||||||
|
|
@ -20,22 +22,32 @@ class CombinedJavadocPlugin implements Plugin<Project> {
|
||||||
project.gradle.projectsEvaluated {
|
project.gradle.projectsEvaluated {
|
||||||
Set<Project> libraryModules = getLibraryModules(project)
|
Set<Project> libraryModules = getLibraryModules(project)
|
||||||
if (!libraryModules.isEmpty()) {
|
if (!libraryModules.isEmpty()) {
|
||||||
String sdkDirectory = getSdkDirectory(libraryModules)
|
|
||||||
project.task(TASK_NAME, type: Javadoc) {
|
project.task(TASK_NAME, type: Javadoc) {
|
||||||
description = "Generates combined Javadoc."
|
description = "Generates combined Javadoc."
|
||||||
title = "ExoPlayer library"
|
title = "ExoPlayer library"
|
||||||
source = libraryModules.generateJavadoc.source
|
source = libraryModules.generateJavadoc.source
|
||||||
classpath = project.files(libraryModules.generateJavadoc.classpath)
|
classpath = project.files([])
|
||||||
destinationDir = project.file("$project.buildDir/docs/javadoc")
|
destinationDir = project.file("$project.buildDir/docs/javadoc")
|
||||||
options {
|
options {
|
||||||
links "http://docs.oracle.com/javase/7/docs/api/"
|
links "https://docs.oracle.com/javase/7/docs/api/",
|
||||||
linksOffline "https://developer.android.com/reference",
|
"https://developer.android.com/reference"
|
||||||
"${sdkDirectory}/docs/reference"
|
|
||||||
encoding = "UTF-8"
|
encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
exclude "**/BuildConfig.java"
|
exclude "**/BuildConfig.java"
|
||||||
exclude "**/R.java"
|
exclude "**/R.java"
|
||||||
destinationDir project.file("$project.buildDir/docs/javadoc")
|
doFirst {
|
||||||
|
libraryModules.each { libraryModule ->
|
||||||
|
libraryModule.android.libraryVariants.all { variant ->
|
||||||
|
def name = variant.buildType.name
|
||||||
|
if (name.equals("release")) {
|
||||||
|
classpath +=
|
||||||
|
libraryModule.project.files(
|
||||||
|
variant.javaCompile.classpath.files,
|
||||||
|
libraryModule.project.android.getBootClasspath())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
doLast {
|
doLast {
|
||||||
libraryModules.each { libraryModule ->
|
libraryModules.each { libraryModule ->
|
||||||
project.copy {
|
project.copy {
|
||||||
|
|
@ -43,6 +55,7 @@ class CombinedJavadocPlugin implements Plugin<Project> {
|
||||||
into "${project.buildDir}/docs/javadoc"
|
into "${project.buildDir}/docs/javadoc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
project.fixJavadoc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,12 +70,6 @@ class CombinedJavadocPlugin implements Plugin<Project> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
apply plugin: CombinedJavadocPlugin
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
apply from: "${rootDir}/javadoc_util.gradle"
|
||||||
|
|
||||||
android.libraryVariants.all { variant ->
|
android.libraryVariants.all { variant ->
|
||||||
def name = variant.buildType.name
|
def name = variant.buildType.name
|
||||||
if (!name.equals("release")) {
|
if (!name.equals("release")) {
|
||||||
|
|
@ -20,21 +22,26 @@ android.libraryVariants.all { variant ->
|
||||||
description = "Generates Javadoc for the ${javadocTitle}."
|
description = "Generates Javadoc for the ${javadocTitle}."
|
||||||
title = "ExoPlayer ${javadocTitle}"
|
title = "ExoPlayer ${javadocTitle}"
|
||||||
source = variant.javaCompile.source
|
source = variant.javaCompile.source
|
||||||
classpath = files(variant.javaCompile.classpath.files,
|
|
||||||
project.android.getBootClasspath())
|
|
||||||
options {
|
options {
|
||||||
links "http://docs.oracle.com/javase/7/docs/api/"
|
links "http://docs.oracle.com/javase/7/docs/api/"
|
||||||
linksOffline "https://developer.android.com/reference",
|
linksOffline "https://developer.android.com/reference",
|
||||||
"${android.sdkDirectory}/docs/reference"
|
"${android.sdkDirectory}/docs/reference"
|
||||||
encoding = "UTF-8"
|
encoding = "UTF-8"
|
||||||
}
|
}
|
||||||
exclude "**/BuildConfig.java"
|
exclude "**/BuildConfig.java"
|
||||||
exclude "**/R.java"
|
exclude "**/R.java"
|
||||||
|
doFirst {
|
||||||
|
classpath =
|
||||||
|
files(
|
||||||
|
variant.javaCompile.classpath.files,
|
||||||
|
project.android.getBootClasspath())
|
||||||
|
}
|
||||||
doLast {
|
doLast {
|
||||||
copy {
|
copy {
|
||||||
from "src/main/javadoc"
|
from "src/main/javadoc"
|
||||||
into "$buildDir/docs/javadoc"
|
into "$buildDir/docs/javadoc"
|
||||||
}
|
}
|
||||||
|
project.fixJavadoc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
javadoc_util.gradle
Normal file
39
javadoc_util.gradle
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (C) 2018 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.
|
||||||
|
ext.fixJavadoc = {
|
||||||
|
def javadocPath = "${project.buildDir}/docs/javadoc"
|
||||||
|
// Fix external Android links to target the top frame.
|
||||||
|
def androidRoot = "https://developer.android.com/reference/"
|
||||||
|
def androidLink = "<a href=\"(${androidRoot}.*?)\\?is-external=true\""
|
||||||
|
def androidFixed = "<a href=\"\\1\" target=\"_top\""
|
||||||
|
ant.replaceregexp(match:androidLink, replace:androidFixed, flags:'g') {
|
||||||
|
fileset(dir: "${javadocPath}", includes: "**/*.html")
|
||||||
|
}
|
||||||
|
// Fix external Oracle links to use frames and target the top frame.
|
||||||
|
def oracleRoot = "https://docs.oracle.com/javase/7/docs/api/"
|
||||||
|
def oracleLink = "<a href=\"(${oracleRoot})(.*?)\\?is-external=true\""
|
||||||
|
def oracleFixed = "<a href=\"\\1index.html\\?\\2\" target=\"_top\""
|
||||||
|
ant.replaceregexp(match:oracleLink, replace:oracleFixed, flags:'g') {
|
||||||
|
fileset(dir: "${javadocPath}", includes: "**/*.html")
|
||||||
|
}
|
||||||
|
// Remove date metadata that changes every time Javadoc is generated.
|
||||||
|
def javadocGeneratedBy = "<!-- Generated by javadoc.*?-->\n"
|
||||||
|
ant.replaceregexp(match:javadocGeneratedBy, replace:"") {
|
||||||
|
fileset(dir: "${javadocPath}", includes: "**/*.html")
|
||||||
|
}
|
||||||
|
def dateMeta = "<meta name=\"date\".*?>\n"
|
||||||
|
ant.replaceregexp(match:dateMeta, replace:"") {
|
||||||
|
fileset(dir: "${javadocPath}", includes: "**/*.html")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,11 +29,11 @@ public final class ExoPlayerLibraryInfo {
|
||||||
|
|
||||||
/** The version of the library expressed as a string, for example "1.2.3". */
|
/** The version of the library expressed as a string, for example "1.2.3". */
|
||||||
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
|
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
|
||||||
public static final String VERSION = "2.7.1";
|
public static final String VERSION = "2.7.2";
|
||||||
|
|
||||||
/** The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}. */
|
/** The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}. */
|
||||||
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
||||||
public static final String VERSION_SLASHY = "ExoPlayerLib/2.7.1";
|
public static final String VERSION_SLASHY = "ExoPlayerLib/2.7.2";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The version of the library expressed as an integer, for example 1002003.
|
* The version of the library expressed as an integer, for example 1002003.
|
||||||
|
|
@ -43,7 +43,7 @@ public final class ExoPlayerLibraryInfo {
|
||||||
* integer version 123045006 (123-045-006).
|
* integer version 123045006 (123-045-006).
|
||||||
*/
|
*/
|
||||||
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
|
||||||
public static final int VERSION_INT = 2007001;
|
public static final int VERSION_INT = 2007002;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
|
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
|
||||||
|
|
|
||||||
|
|
@ -202,10 +202,11 @@ import java.util.Stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and returns a string of length {@code byteLength} from the {@link ExtractorInput}.
|
* Reads a string of length {@code byteLength} from the {@link ExtractorInput}. Zero padding is
|
||||||
|
* removed, so the returned string may be shorter than {@code byteLength}.
|
||||||
*
|
*
|
||||||
* @param input The {@link ExtractorInput} from which to read.
|
* @param input The {@link ExtractorInput} from which to read.
|
||||||
* @param byteLength The length of the float being read.
|
* @param byteLength The length of the string being read, including zero padding.
|
||||||
* @return The read string value.
|
* @return The read string value.
|
||||||
* @throws IOException If an error occurs reading from the input.
|
* @throws IOException If an error occurs reading from the input.
|
||||||
* @throws InterruptedException If the thread is interrupted.
|
* @throws InterruptedException If the thread is interrupted.
|
||||||
|
|
@ -217,7 +218,12 @@ import java.util.Stack;
|
||||||
}
|
}
|
||||||
byte[] stringBytes = new byte[byteLength];
|
byte[] stringBytes = new byte[byteLength];
|
||||||
input.readFully(stringBytes, 0, byteLength);
|
input.readFully(stringBytes, 0, byteLength);
|
||||||
return new String(stringBytes);
|
// Remove zero padding.
|
||||||
|
int trimmedLength = byteLength;
|
||||||
|
while (trimmedLength > 0 && stringBytes[trimmedLength - 1] == 0) {
|
||||||
|
trimmedLength--;
|
||||||
|
}
|
||||||
|
return new String(stringBytes, 0, trimmedLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.extractor.mp4;
|
package com.google.android.exoplayer2.extractor.mp4;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.MimeTypes.getMimeTypeFromMp4ObjectType;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
|
@ -1030,47 +1032,11 @@ import java.util.List;
|
||||||
|
|
||||||
// Set the MIME type based on the object type indication (14496-1 table 5).
|
// Set the MIME type based on the object type indication (14496-1 table 5).
|
||||||
int objectTypeIndication = parent.readUnsignedByte();
|
int objectTypeIndication = parent.readUnsignedByte();
|
||||||
String mimeType;
|
String mimeType = getMimeTypeFromMp4ObjectType(objectTypeIndication);
|
||||||
switch (objectTypeIndication) {
|
if (MimeTypes.AUDIO_MPEG.equals(mimeType)
|
||||||
case 0x60:
|
|| MimeTypes.AUDIO_DTS.equals(mimeType)
|
||||||
case 0x61:
|
|| MimeTypes.AUDIO_DTS_HD.equals(mimeType)) {
|
||||||
mimeType = MimeTypes.VIDEO_MPEG2;
|
return Pair.create(mimeType, null);
|
||||||
break;
|
|
||||||
case 0x20:
|
|
||||||
mimeType = MimeTypes.VIDEO_MP4V;
|
|
||||||
break;
|
|
||||||
case 0x21:
|
|
||||||
mimeType = MimeTypes.VIDEO_H264;
|
|
||||||
break;
|
|
||||||
case 0x23:
|
|
||||||
mimeType = MimeTypes.VIDEO_H265;
|
|
||||||
break;
|
|
||||||
case 0x6B:
|
|
||||||
mimeType = MimeTypes.AUDIO_MPEG;
|
|
||||||
return Pair.create(mimeType, null);
|
|
||||||
case 0x40:
|
|
||||||
case 0x66:
|
|
||||||
case 0x67:
|
|
||||||
case 0x68:
|
|
||||||
mimeType = MimeTypes.AUDIO_AAC;
|
|
||||||
break;
|
|
||||||
case 0xA5:
|
|
||||||
mimeType = MimeTypes.AUDIO_AC3;
|
|
||||||
break;
|
|
||||||
case 0xA6:
|
|
||||||
mimeType = MimeTypes.AUDIO_E_AC3;
|
|
||||||
break;
|
|
||||||
case 0xA9:
|
|
||||||
case 0xAC:
|
|
||||||
mimeType = MimeTypes.AUDIO_DTS;
|
|
||||||
return Pair.create(mimeType, null);
|
|
||||||
case 0xAA:
|
|
||||||
case 0xAB:
|
|
||||||
mimeType = MimeTypes.AUDIO_DTS_HD;
|
|
||||||
return Pair.create(mimeType, null);
|
|
||||||
default:
|
|
||||||
mimeType = null;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parent.skipBytes(12);
|
parent.skipBytes(12);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
|
||||||
|
|
@ -194,7 +195,20 @@ public final class MimeTypes {
|
||||||
} else if (codec.startsWith("vp8") || codec.startsWith("vp08")) {
|
} else if (codec.startsWith("vp8") || codec.startsWith("vp08")) {
|
||||||
return MimeTypes.VIDEO_VP8;
|
return MimeTypes.VIDEO_VP8;
|
||||||
} else if (codec.startsWith("mp4a")) {
|
} else if (codec.startsWith("mp4a")) {
|
||||||
return MimeTypes.AUDIO_AAC;
|
String mimeType = null;
|
||||||
|
if (codec.startsWith("mp4a.")) {
|
||||||
|
String objectTypeString = codec.substring(5); // remove the 'mp4a.' prefix
|
||||||
|
if (objectTypeString.length() >= 2) {
|
||||||
|
try {
|
||||||
|
String objectTypeHexString = Util.toUpperInvariant(objectTypeString.substring(0, 2));
|
||||||
|
int objectTypeInt = Integer.parseInt(objectTypeHexString, 16);
|
||||||
|
mimeType = getMimeTypeFromMp4ObjectType(objectTypeInt);
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mimeType == null ? MimeTypes.AUDIO_AAC : mimeType;
|
||||||
} else if (codec.startsWith("ac-3") || codec.startsWith("dac3")) {
|
} else if (codec.startsWith("ac-3") || codec.startsWith("dac3")) {
|
||||||
return MimeTypes.AUDIO_AC3;
|
return MimeTypes.AUDIO_AC3;
|
||||||
} else if (codec.startsWith("ec-3") || codec.startsWith("dec3")) {
|
} else if (codec.startsWith("ec-3") || codec.startsWith("dec3")) {
|
||||||
|
|
@ -213,6 +227,50 @@ public final class MimeTypes {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derives a mimeType from MP4 object type identifier, as defined in RFC 6381 and
|
||||||
|
* http://www.mp4ra.org/object.html.
|
||||||
|
*
|
||||||
|
* @param objectType The objectType identifier to derive.
|
||||||
|
* @return The mimeType, or null if it could not be derived.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static String getMimeTypeFromMp4ObjectType(int objectType) {
|
||||||
|
switch (objectType) {
|
||||||
|
case 0x60:
|
||||||
|
case 0x61:
|
||||||
|
return MimeTypes.VIDEO_MPEG2;
|
||||||
|
case 0x20:
|
||||||
|
return MimeTypes.VIDEO_MP4V;
|
||||||
|
case 0x21:
|
||||||
|
return MimeTypes.VIDEO_H264;
|
||||||
|
case 0x23:
|
||||||
|
return MimeTypes.VIDEO_H265;
|
||||||
|
case 0x69:
|
||||||
|
case 0x6B:
|
||||||
|
return MimeTypes.AUDIO_MPEG;
|
||||||
|
case 0x40:
|
||||||
|
case 0x66:
|
||||||
|
case 0x67:
|
||||||
|
case 0x68:
|
||||||
|
return MimeTypes.AUDIO_AAC;
|
||||||
|
case 0xA5:
|
||||||
|
return MimeTypes.AUDIO_AC3;
|
||||||
|
case 0xA6:
|
||||||
|
return MimeTypes.AUDIO_E_AC3;
|
||||||
|
case 0xA9:
|
||||||
|
case 0xAC:
|
||||||
|
return MimeTypes.AUDIO_DTS;
|
||||||
|
case 0xAA:
|
||||||
|
case 0xAB:
|
||||||
|
return MimeTypes.AUDIO_DTS_HD;
|
||||||
|
case 0xAD:
|
||||||
|
return MimeTypes.AUDIO_OPUS;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link C}{@code .TRACK_TYPE_*} constant that corresponds to a specified MIME type.
|
* Returns the {@link C}{@code .TRACK_TYPE_*} constant that corresponds to a specified MIME type.
|
||||||
* {@link C#TRACK_TYPE_UNKNOWN} if the MIME type is not known or the mapping cannot be
|
* {@link C#TRACK_TYPE_UNKNOWN} if the MIME type is not known or the mapping cannot be
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,16 @@ public final class Util {
|
||||||
return text == null ? null : text.toLowerCase(Locale.US);
|
return text == null ? null : text.toLowerCase(Locale.US);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts text to upper case using {@link Locale#US}.
|
||||||
|
*
|
||||||
|
* @param text The text to convert.
|
||||||
|
* @return The upper case text, or null if {@code text} is null.
|
||||||
|
*/
|
||||||
|
public static String toUpperInvariant(String text) {
|
||||||
|
return text == null ? null : text.toUpperCase(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divides a {@code numerator} by a {@code denominator}, returning the ceiled result.
|
* Divides a {@code numerator} by a {@code denominator}, returning the ceiled result.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1102,9 +1102,13 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
// Work around https://github.com/google/ExoPlayer/issues/3236,
|
// Work around https://github.com/google/ExoPlayer/issues/3236,
|
||||||
// https://github.com/google/ExoPlayer/issues/3355,
|
// https://github.com/google/ExoPlayer/issues/3355,
|
||||||
// https://github.com/google/ExoPlayer/issues/3439,
|
// https://github.com/google/ExoPlayer/issues/3439,
|
||||||
// https://github.com/google/ExoPlayer/issues/3724 and
|
// https://github.com/google/ExoPlayer/issues/3724,
|
||||||
// https://github.com/google/ExoPlayer/issues/3835.
|
// https://github.com/google/ExoPlayer/issues/3835 and
|
||||||
return (("deb".equals(Util.DEVICE) || "flo".equals(Util.DEVICE)) // Nexus 7 (2013)
|
// https://github.com/google/ExoPlayer/issues/4006.
|
||||||
|
return (("deb".equals(Util.DEVICE) // Nexus 7 (2013)
|
||||||
|
|| "flo".equals(Util.DEVICE) // Nexus 7 (2013)
|
||||||
|
|| "mido".equals(Util.DEVICE) // Redmi Note 4
|
||||||
|
|| "santoni".equals(Util.DEVICE)) // Redmi 4X
|
||||||
&& "OMX.qcom.video.decoder.avc".equals(name))
|
&& "OMX.qcom.video.decoder.avc".equals(name))
|
||||||
|| (("tcl_eu".equals(Util.DEVICE) // TCL Percee TV
|
|| (("tcl_eu".equals(Util.DEVICE) // TCL Percee TV
|
||||||
|| "SVP-DTV15".equals(Util.DEVICE) // Sony Bravia 4K 2015
|
|| "SVP-DTV15".equals(Util.DEVICE) // Sony Bravia 4K 2015
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,14 @@ public class DefaultEbmlReaderTest {
|
||||||
assertEvents(input, expected.events);
|
assertEvents(input, expected.events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStringElementWithZeroPadding() throws IOException, InterruptedException {
|
||||||
|
ExtractorInput input = createTestInput(0x42, 0x82, 0x86, 0x41, 0x62, 0x63, 0x00, 0x00, 0x00);
|
||||||
|
TestOutput expected = new TestOutput();
|
||||||
|
expected.stringElement(TestOutput.ID_DOC_TYPE, "Abc");
|
||||||
|
assertEvents(input, expected.events);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStringElementEmpty() throws IOException, InterruptedException {
|
public void testStringElementEmpty() throws IOException, InterruptedException {
|
||||||
ExtractorInput input = createTestInput(0x42, 0x82, 0x80);
|
ExtractorInput input = createTestInput(0x42, 0x82, 0x80);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.util;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
/** Unit test for {@link MimeTypes}. */
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public final class MimeTypesTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMediaMimeType_fromValidCodecs_returnsCorrectMimeType() {
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc1")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc1.42E01E")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc1.42E01F")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc1.4D401F")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc1.4D4028")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc1.640028")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc1.640029")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("avc3")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("hev1")).isEqualTo(MimeTypes.VIDEO_H265);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("hvc1")).isEqualTo(MimeTypes.VIDEO_H265);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("vp08")).isEqualTo(MimeTypes.VIDEO_VP8);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("vp8")).isEqualTo(MimeTypes.VIDEO_VP8);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("vp09")).isEqualTo(MimeTypes.VIDEO_VP9);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("vp9")).isEqualTo(MimeTypes.VIDEO_VP9);
|
||||||
|
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("ac-3")).isEqualTo(MimeTypes.AUDIO_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("dac3")).isEqualTo(MimeTypes.AUDIO_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("dec3")).isEqualTo(MimeTypes.AUDIO_E_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("ec-3")).isEqualTo(MimeTypes.AUDIO_E_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("ec+3")).isEqualTo(MimeTypes.AUDIO_E_AC3_JOC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("dtsc")).isEqualTo(MimeTypes.AUDIO_DTS);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("dtse")).isEqualTo(MimeTypes.AUDIO_DTS);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("dtsh")).isEqualTo(MimeTypes.AUDIO_DTS_HD);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("dtsl")).isEqualTo(MimeTypes.AUDIO_DTS_HD);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("opus")).isEqualTo(MimeTypes.AUDIO_OPUS);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("vorbis")).isEqualTo(MimeTypes.AUDIO_VORBIS);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.40.02")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.40.05")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.40.2")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.40.5")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.40.29")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.66")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.67")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.68")).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.69")).isEqualTo(MimeTypes.AUDIO_MPEG);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.6B")).isEqualTo(MimeTypes.AUDIO_MPEG);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.a5")).isEqualTo(MimeTypes.AUDIO_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.A5")).isEqualTo(MimeTypes.AUDIO_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.a6")).isEqualTo(MimeTypes.AUDIO_E_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.A6")).isEqualTo(MimeTypes.AUDIO_E_AC3);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.A9")).isEqualTo(MimeTypes.AUDIO_DTS);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.AC")).isEqualTo(MimeTypes.AUDIO_DTS);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.AA")).isEqualTo(MimeTypes.AUDIO_DTS_HD);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.AB")).isEqualTo(MimeTypes.AUDIO_DTS_HD);
|
||||||
|
assertThat(MimeTypes.getMediaMimeType("mp4a.AD")).isEqualTo(MimeTypes.AUDIO_OPUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMimeTypeFromMp4ObjectType_forValidObjectType_returnsCorrectMimeType() {
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x60)).isEqualTo(MimeTypes.VIDEO_MPEG2);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x61)).isEqualTo(MimeTypes.VIDEO_MPEG2);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x20)).isEqualTo(MimeTypes.VIDEO_MP4V);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x21)).isEqualTo(MimeTypes.VIDEO_H264);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x23)).isEqualTo(MimeTypes.VIDEO_H265);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x6B)).isEqualTo(MimeTypes.AUDIO_MPEG);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x40)).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x66)).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x67)).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x68)).isEqualTo(MimeTypes.AUDIO_AAC);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0xA5)).isEqualTo(MimeTypes.AUDIO_AC3);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0xA6)).isEqualTo(MimeTypes.AUDIO_E_AC3);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0xA9)).isEqualTo(MimeTypes.AUDIO_DTS);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0xAC)).isEqualTo(MimeTypes.AUDIO_DTS);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0xAA)).isEqualTo(MimeTypes.AUDIO_DTS_HD);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0xAB)).isEqualTo(MimeTypes.AUDIO_DTS_HD);
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0xAD)).isEqualTo(MimeTypes.AUDIO_OPUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMimeTypeFromMp4ObjectType_forInvalidObjectType_returnsNull() {
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0)).isNull();
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x600)).isNull();
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(0x01)).isNull();
|
||||||
|
assertThat(MimeTypes.getMimeTypeFromMp4ObjectType(-1)).isNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -117,7 +117,8 @@ public final class DashDownloader extends SegmentDownloader<DashManifest, Repres
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int segmentCount = index.getSegmentCount(C.TIME_UNSET);
|
long periodDurationUs = manifest.getPeriodDurationUs(key.periodIndex);
|
||||||
|
int segmentCount = index.getSegmentCount(periodDurationUs);
|
||||||
if (segmentCount == DashSegmentIndex.INDEX_UNBOUNDED) {
|
if (segmentCount == DashSegmentIndex.INDEX_UNBOUNDED) {
|
||||||
throw new DownloadException("Unbounded index for representation: " + key);
|
throw new DownloadException("Unbounded index for representation: " + key);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,9 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||||
Format format, List<Format> muxedCaptionFormats, DrmInitData drmInitData,
|
Format format, List<Format> muxedCaptionFormats, DrmInitData drmInitData,
|
||||||
TimestampAdjuster timestampAdjuster) {
|
TimestampAdjuster timestampAdjuster) {
|
||||||
String lastPathSegment = uri.getLastPathSegment();
|
String lastPathSegment = uri.getLastPathSegment();
|
||||||
|
if (lastPathSegment == null) {
|
||||||
|
lastPathSegment = "";
|
||||||
|
}
|
||||||
boolean isPackedAudioExtractor = false;
|
boolean isPackedAudioExtractor = false;
|
||||||
Extractor extractor;
|
Extractor extractor;
|
||||||
if (MimeTypes.TEXT_VTT.equals(format.sampleMimeType)
|
if (MimeTypes.TEXT_VTT.equals(format.sampleMimeType)
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@ import static com.google.common.truth.Truth.assertThat;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
|
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
|
||||||
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
@ -122,7 +122,7 @@ public class HlsMediaPlaylistParserTest {
|
||||||
.isEqualTo("https://priv.example.com/key.php?r=2682");
|
.isEqualTo("https://priv.example.com/key.php?r=2682");
|
||||||
// 0xA7A == 2682.
|
// 0xA7A == 2682.
|
||||||
assertThat(segment.encryptionIV).isNotNull();
|
assertThat(segment.encryptionIV).isNotNull();
|
||||||
assertThat(segment.encryptionIV.toUpperCase(Locale.getDefault())).isEqualTo("A7A");
|
assertThat(Util.toUpperInvariant(segment.encryptionIV)).isEqualTo("A7A");
|
||||||
assertThat(segment.byterangeLength).isEqualTo(51740);
|
assertThat(segment.byterangeLength).isEqualTo(51740);
|
||||||
assertThat(segment.byterangeOffset).isEqualTo(2147586650L);
|
assertThat(segment.byterangeOffset).isEqualTo(2147586650L);
|
||||||
assertThat(segment.url).isEqualTo("https://priv.example.com/fileSequence2682.ts");
|
assertThat(segment.url).isEqualTo("https://priv.example.com/fileSequence2682.ts");
|
||||||
|
|
@ -134,7 +134,7 @@ public class HlsMediaPlaylistParserTest {
|
||||||
.isEqualTo("https://priv.example.com/key.php?r=2682");
|
.isEqualTo("https://priv.example.com/key.php?r=2682");
|
||||||
// 0xA7B == 2683.
|
// 0xA7B == 2683.
|
||||||
assertThat(segment.encryptionIV).isNotNull();
|
assertThat(segment.encryptionIV).isNotNull();
|
||||||
assertThat(segment.encryptionIV.toUpperCase(Locale.getDefault())).isEqualTo("A7B");
|
assertThat(Util.toUpperInvariant(segment.encryptionIV)).isEqualTo("A7B");
|
||||||
assertThat(segment.byterangeLength).isEqualTo(C.LENGTH_UNSET);
|
assertThat(segment.byterangeLength).isEqualTo(C.LENGTH_UNSET);
|
||||||
assertThat(segment.byterangeOffset).isEqualTo(0);
|
assertThat(segment.byterangeOffset).isEqualTo(0);
|
||||||
assertThat(segment.url).isEqualTo("https://priv.example.com/fileSequence2683.ts");
|
assertThat(segment.url).isEqualTo("https://priv.example.com/fileSequence2683.ts");
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ public class DefaultTimeBar extends View implements TimeBar {
|
||||||
try {
|
try {
|
||||||
scrubberDrawable = a.getDrawable(R.styleable.DefaultTimeBar_scrubber_drawable);
|
scrubberDrawable = a.getDrawable(R.styleable.DefaultTimeBar_scrubber_drawable);
|
||||||
if (scrubberDrawable != null) {
|
if (scrubberDrawable != null) {
|
||||||
setDrawableLayoutDirection(scrubberDrawable, getLayoutDirection());
|
setDrawableLayoutDirection(scrubberDrawable);
|
||||||
defaultTouchTargetHeight =
|
defaultTouchTargetHeight =
|
||||||
Math.max(scrubberDrawable.getMinimumHeight(), defaultTouchTargetHeight);
|
Math.max(scrubberDrawable.getMinimumHeight(), defaultTouchTargetHeight);
|
||||||
}
|
}
|
||||||
|
|
@ -747,8 +747,8 @@ public class DefaultTimeBar extends View implements TimeBar {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int dpToPx(DisplayMetrics displayMetrics, int dps) {
|
private boolean setDrawableLayoutDirection(Drawable drawable) {
|
||||||
return (int) (dps * displayMetrics.density + 0.5f);
|
return Util.SDK_INT >= 23 && setDrawableLayoutDirection(drawable, getLayoutDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean setDrawableLayoutDirection(Drawable drawable, int layoutDirection) {
|
private static boolean setDrawableLayoutDirection(Drawable drawable, int layoutDirection) {
|
||||||
|
|
@ -771,4 +771,7 @@ public class DefaultTimeBar extends View implements TimeBar {
|
||||||
return 0x33000000 | (adMarkerColor & 0x00FFFFFF);
|
return 0x33000000 | (adMarkerColor & 0x00FFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int dpToPx(DisplayMetrics displayMetrics, int dps) {
|
||||||
|
return (int) (dps * displayMetrics.density + 0.5f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ if (project.ext.has("exoplayerPublishEnabled")
|
||||||
apply plugin: 'bintray-release'
|
apply plugin: 'bintray-release'
|
||||||
publish {
|
publish {
|
||||||
artifactId = releaseArtifact
|
artifactId = releaseArtifact
|
||||||
description = releaseDescription
|
desc = releaseDescription
|
||||||
version = releaseVersion
|
publishVersion = releaseVersion
|
||||||
repoName = getBintrayRepo()
|
repoName = getBintrayRepo()
|
||||||
userOrg = 'google'
|
userOrg = 'google'
|
||||||
groupId = 'com.google.android.exoplayer'
|
groupId = 'com.google.android.exoplayer'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue