Move utility methods to DashUtil class
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=148647040
This commit is contained in:
parent
e26723cdc7
commit
98f4fb85c2
@ -17,7 +17,6 @@
|
|||||||
package com.google.android.exoplayer2.drm;
|
package com.google.android.exoplayer2.drm;
|
||||||
|
|
||||||
import android.media.MediaDrm;
|
import android.media.MediaDrm;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
@ -27,24 +26,14 @@ import com.google.android.exoplayer2.Format;
|
|||||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.EventListener;
|
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.EventListener;
|
||||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode;
|
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode;
|
||||||
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
|
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
|
||||||
import com.google.android.exoplayer2.extractor.Extractor;
|
import com.google.android.exoplayer2.source.dash.DashUtil;
|
||||||
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
|
|
||||||
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
|
|
||||||
import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper;
|
|
||||||
import com.google.android.exoplayer2.source.chunk.InitializationChunk;
|
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
|
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
|
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.Period;
|
import com.google.android.exoplayer2.source.dash.manifest.Period;
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
|
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.Representation;
|
import com.google.android.exoplayer2.source.dash.manifest.Representation;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSourceInputStream;
|
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource.Factory;
|
import com.google.android.exoplayer2.upstream.HttpDataSource.Factory;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@ -58,28 +47,6 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
|
|||||||
private final DefaultDrmSessionManager<T> drmSessionManager;
|
private final DefaultDrmSessionManager<T> drmSessionManager;
|
||||||
private final HandlerThread handlerThread;
|
private final HandlerThread handlerThread;
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to download a DASH manifest.
|
|
||||||
*
|
|
||||||
* @param dataSource The {@link HttpDataSource} from which the manifest should be read.
|
|
||||||
* @param manifestUriString The URI of the manifest to be read.
|
|
||||||
* @return An instance of {@link DashManifest}.
|
|
||||||
* @throws IOException If an error occurs reading data from the stream.
|
|
||||||
* @see DashManifestParser
|
|
||||||
*/
|
|
||||||
public static DashManifest downloadManifest(HttpDataSource dataSource, String manifestUriString)
|
|
||||||
throws IOException {
|
|
||||||
DataSourceInputStream inputStream = new DataSourceInputStream(
|
|
||||||
dataSource, new DataSpec(Uri.parse(manifestUriString)));
|
|
||||||
try {
|
|
||||||
inputStream.open();
|
|
||||||
DashManifestParser parser = new DashManifestParser();
|
|
||||||
return parser.parse(dataSource.getUri(), inputStream);
|
|
||||||
} finally {
|
|
||||||
inputStream.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new instance which uses Widevine CDM. Call {@link #releaseResources()} when
|
* Instantiates a new instance which uses Widevine CDM. Call {@link #releaseResources()} when
|
||||||
* you're done with the helper instance.
|
* you're done with the helper instance.
|
||||||
@ -174,7 +141,7 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
|
|||||||
*/
|
*/
|
||||||
public byte[] download(HttpDataSource dataSource, String manifestUriString)
|
public byte[] download(HttpDataSource dataSource, String manifestUriString)
|
||||||
throws IOException, InterruptedException, DrmSessionException {
|
throws IOException, InterruptedException, DrmSessionException {
|
||||||
return download(dataSource, downloadManifest(dataSource, manifestUriString));
|
return download(dataSource, DashUtil.loadManifest(dataSource, manifestUriString));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,14 +177,8 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
|
|||||||
Representation representation = adaptationSet.representations.get(0);
|
Representation representation = adaptationSet.representations.get(0);
|
||||||
DrmInitData drmInitData = representation.format.drmInitData;
|
DrmInitData drmInitData = representation.format.drmInitData;
|
||||||
if (drmInitData == null) {
|
if (drmInitData == null) {
|
||||||
ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(representation.format,
|
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, representation,
|
||||||
adaptationSet.type);
|
adaptationSet.type);
|
||||||
InitializationChunk initializationChunk = loadInitializationChunk(dataSource, representation,
|
|
||||||
extractorWrapper);
|
|
||||||
if (initializationChunk == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Format sampleFormat = extractorWrapper.getSampleFormat();
|
|
||||||
if (sampleFormat != null) {
|
if (sampleFormat != null) {
|
||||||
drmInitData = sampleFormat.drmInitData;
|
drmInitData = sampleFormat.drmInitData;
|
||||||
}
|
}
|
||||||
@ -291,28 +252,4 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InitializationChunk loadInitializationChunk(DataSource dataSource,
|
|
||||||
Representation representation, ChunkExtractorWrapper extractorWrapper)
|
|
||||||
throws IOException, InterruptedException {
|
|
||||||
RangedUri rangedUri = representation.getInitializationUri();
|
|
||||||
if (rangedUri == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
DataSpec dataSpec = new DataSpec(rangedUri.resolveUri(representation.baseUrl), rangedUri.start,
|
|
||||||
rangedUri.length, representation.getCacheKey());
|
|
||||||
InitializationChunk initializationChunk = new InitializationChunk(dataSource, dataSpec,
|
|
||||||
representation.format, C.SELECTION_REASON_UNKNOWN, null /* trackSelectionData */,
|
|
||||||
extractorWrapper);
|
|
||||||
initializationChunk.load();
|
|
||||||
return initializationChunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ChunkExtractorWrapper newWrappedExtractor(Format format, int trackType) {
|
|
||||||
final String mimeType = format.containerMimeType;
|
|
||||||
final boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM)
|
|
||||||
|| mimeType.startsWith(MimeTypes.AUDIO_WEBM);
|
|
||||||
final Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor();
|
|
||||||
return new ChunkExtractorWrapper(extractor, format, trackType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* 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.source.dash;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
|
import com.google.android.exoplayer2.extractor.ChunkIndex;
|
||||||
|
import com.google.android.exoplayer2.extractor.Extractor;
|
||||||
|
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
|
||||||
|
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
|
||||||
|
import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper;
|
||||||
|
import com.google.android.exoplayer2.source.chunk.InitializationChunk;
|
||||||
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
||||||
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
|
||||||
|
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
|
||||||
|
import com.google.android.exoplayer2.source.dash.manifest.Representation;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSourceInputStream;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for DASH streams.
|
||||||
|
*/
|
||||||
|
public final class DashUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a DASH manifest.
|
||||||
|
*
|
||||||
|
* @param dataSource The {@link HttpDataSource} from which the manifest should be read.
|
||||||
|
* @param manifestUriString The URI of the manifest to be read.
|
||||||
|
* @return An instance of {@link DashManifest}.
|
||||||
|
* @throws IOException If an error occurs reading data from the stream.
|
||||||
|
* @see DashManifestParser
|
||||||
|
*/
|
||||||
|
public static DashManifest loadManifest(DataSource dataSource, String manifestUriString)
|
||||||
|
throws IOException {
|
||||||
|
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource,
|
||||||
|
new DataSpec(Uri.parse(manifestUriString), DataSpec.FLAG_ALLOW_CACHING_UNKNOWN_LENGTH));
|
||||||
|
try {
|
||||||
|
inputStream.open();
|
||||||
|
DashManifestParser parser = new DashManifestParser();
|
||||||
|
return parser.parse(dataSource.getUri(), inputStream);
|
||||||
|
} finally {
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads initialization data for the {@code representation} and returns the sample {@link
|
||||||
|
* Format}.
|
||||||
|
*
|
||||||
|
* @param dataSource The source from which the data should be loaded.
|
||||||
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @param type The type of the primary track. Typically one of the {@link C} {@code TRACK_TYPE_*}
|
||||||
|
* constants.
|
||||||
|
* @return the sample {@link Format} of the given representation.
|
||||||
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
|
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||||
|
*/
|
||||||
|
public static Format loadSampleFormat(DataSource dataSource, Representation representation,
|
||||||
|
int type) throws IOException, InterruptedException {
|
||||||
|
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, representation,
|
||||||
|
type, false);
|
||||||
|
return extractorWrapper == null ? null : extractorWrapper.getSampleFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads initialization and index data for the {@code representation} and returns the {@link
|
||||||
|
* ChunkIndex}.
|
||||||
|
*
|
||||||
|
* @param dataSource The source from which the data should be loaded.
|
||||||
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @param type The type of the primary track. Typically one of the {@link C} {@code TRACK_TYPE_*}
|
||||||
|
* constants.
|
||||||
|
* @return {@link ChunkIndex} of the given representation.
|
||||||
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
|
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||||
|
*/
|
||||||
|
public static ChunkIndex loadChunkIndex(DataSource dataSource, Representation representation,
|
||||||
|
int type) throws IOException, InterruptedException {
|
||||||
|
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, representation,
|
||||||
|
type, true);
|
||||||
|
return extractorWrapper == null ? null : (ChunkIndex) extractorWrapper.getSeekMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads initialization data for the {@code representation} and optionally index data then
|
||||||
|
* returns a {@link ChunkExtractorWrapper} which contains the output.
|
||||||
|
*
|
||||||
|
* @param dataSource The source from which the data should be loaded.
|
||||||
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @param type The type of the primary track. Typically one of the {@link C} {@code TRACK_TYPE_*}
|
||||||
|
* constants.
|
||||||
|
* @param loadIndex Whether to load index data too.
|
||||||
|
* @return A {@link ChunkExtractorWrapper} for the {@code representation}, or null if no
|
||||||
|
* initialization or (if requested) index data exists.
|
||||||
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
|
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||||
|
*/
|
||||||
|
private static ChunkExtractorWrapper loadInitializationData(DataSource dataSource,
|
||||||
|
Representation representation, int type, boolean loadIndex)
|
||||||
|
throws IOException, InterruptedException {
|
||||||
|
RangedUri initializationUri = representation.getInitializationUri();
|
||||||
|
if (initializationUri == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(representation.format, type);
|
||||||
|
RangedUri requestUri;
|
||||||
|
if (loadIndex) {
|
||||||
|
RangedUri indexUri = representation.getIndexUri();
|
||||||
|
if (indexUri == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// It's common for initialization and index data to be stored adjacently. Attempt to merge
|
||||||
|
// the two requests together to request both at once.
|
||||||
|
requestUri = initializationUri.attemptMerge(indexUri, representation.baseUrl);
|
||||||
|
if (requestUri == null) {
|
||||||
|
loadInitializationData(dataSource, representation, extractorWrapper, initializationUri);
|
||||||
|
requestUri = indexUri;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestUri = initializationUri;
|
||||||
|
}
|
||||||
|
loadInitializationData(dataSource, representation, extractorWrapper, requestUri);
|
||||||
|
return extractorWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void loadInitializationData(DataSource dataSource,
|
||||||
|
Representation representation, ChunkExtractorWrapper extractorWrapper, RangedUri requestUri)
|
||||||
|
throws IOException, InterruptedException {
|
||||||
|
DataSpec dataSpec = new DataSpec(requestUri.resolveUri(representation.baseUrl),
|
||||||
|
requestUri.start, requestUri.length, representation.getCacheKey());
|
||||||
|
InitializationChunk initializationChunk = new InitializationChunk(dataSource, dataSpec,
|
||||||
|
representation.format, C.SELECTION_REASON_UNKNOWN, null /* trackSelectionData */,
|
||||||
|
extractorWrapper);
|
||||||
|
initializationChunk.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ChunkExtractorWrapper newWrappedExtractor(Format format, int trackType) {
|
||||||
|
String mimeType = format.containerMimeType;
|
||||||
|
boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM)
|
||||||
|
|| mimeType.startsWith(MimeTypes.AUDIO_WEBM);
|
||||||
|
Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor();
|
||||||
|
return new ChunkExtractorWrapper(extractor, format, trackType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DashUtil() {}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user