use of androidx.media3.exoplayer.dash.manifest.Representation in project media by androidx.
the class DashDownloader method addSegmentsForAdaptationSet.
private void addSegmentsForAdaptationSet(DataSource dataSource, AdaptationSet adaptationSet, long periodStartUs, long periodDurationUs, boolean removing, ArrayList<Segment> out) throws IOException, InterruptedException {
for (int i = 0; i < adaptationSet.representations.size(); i++) {
Representation representation = adaptationSet.representations.get(i);
DashSegmentIndex index;
try {
index = getSegmentIndex(dataSource, adaptationSet.type, representation, removing);
if (index == null) {
// Loading succeeded but there was no index.
throw new DownloadException("Missing segment index");
}
} catch (IOException e) {
if (!removing) {
throw e;
}
// Generating an incomplete segment list is allowed. Advance to the next representation.
continue;
}
long segmentCount = index.getSegmentCount(periodDurationUs);
if (segmentCount == DashSegmentIndex.INDEX_UNBOUNDED) {
throw new DownloadException("Unbounded segment index");
}
String baseUrl = castNonNull(baseUrlExclusionList.selectBaseUrl(representation.baseUrls)).url;
@Nullable RangedUri initializationUri = representation.getInitializationUri();
if (initializationUri != null) {
out.add(createSegment(representation, baseUrl, periodStartUs, initializationUri));
}
@Nullable RangedUri indexUri = representation.getIndexUri();
if (indexUri != null) {
out.add(createSegment(representation, baseUrl, periodStartUs, indexUri));
}
long firstSegmentNum = index.getFirstSegmentNum();
long lastSegmentNum = firstSegmentNum + segmentCount - 1;
for (long j = firstSegmentNum; j <= lastSegmentNum; j++) {
out.add(createSegment(representation, baseUrl, periodStartUs + index.getTimeUs(j), index.getSegmentUrl(j)));
}
}
}
use of androidx.media3.exoplayer.dash.manifest.Representation in project media by androidx.
the class DashDownloadTest method downloadContent.
private DashDownloader downloadContent() throws Exception {
DashManifest dashManifest = DashUtil.loadManifest(httpDataSourceFactory.createDataSource(), MANIFEST_URI);
ArrayList<StreamKey> keys = new ArrayList<>();
for (int pIndex = 0; pIndex < dashManifest.getPeriodCount(); pIndex++) {
List<AdaptationSet> adaptationSets = dashManifest.getPeriod(pIndex).adaptationSets;
for (int aIndex = 0; aIndex < adaptationSets.size(); aIndex++) {
AdaptationSet adaptationSet = adaptationSets.get(aIndex);
List<Representation> representations = adaptationSet.representations;
for (int rIndex = 0; rIndex < representations.size(); rIndex++) {
String id = representations.get(rIndex).format.id;
if (DashTestData.AAC_AUDIO_REPRESENTATION_ID.equals(id) || DashTestData.H264_CDD_FIXED.equals(id)) {
keys.add(new StreamKey(pIndex, aIndex, rIndex));
}
}
}
}
CacheDataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory().setCache(cache).setUpstreamDataSourceFactory(httpDataSourceFactory);
return new DashDownloader(new MediaItem.Builder().setUri(MANIFEST_URI).setStreamKeys(keys).build(), cacheDataSourceFactory);
}
use of androidx.media3.exoplayer.dash.manifest.Representation in project media by androidx.
the class DashMediaPeriod method buildPrimaryAndEmbeddedTrackGroupInfos.
private static int buildPrimaryAndEmbeddedTrackGroupInfos(DrmSessionManager drmSessionManager, List<AdaptationSet> adaptationSets, int[][] groupedAdaptationSetIndices, int primaryGroupCount, boolean[] primaryGroupHasEventMessageTrackFlags, Format[][] primaryGroupClosedCaptionTrackFormats, TrackGroup[] trackGroups, TrackGroupInfo[] trackGroupInfos) {
int trackGroupCount = 0;
for (int i = 0; i < primaryGroupCount; i++) {
int[] adaptationSetIndices = groupedAdaptationSetIndices[i];
List<Representation> representations = new ArrayList<>();
for (int adaptationSetIndex : adaptationSetIndices) {
representations.addAll(adaptationSets.get(adaptationSetIndex).representations);
}
Format[] formats = new Format[representations.size()];
for (int j = 0; j < formats.length; j++) {
Format format = representations.get(j).format;
formats[j] = format.copyWithCryptoType(drmSessionManager.getCryptoType(format));
}
AdaptationSet firstAdaptationSet = adaptationSets.get(adaptationSetIndices[0]);
String trackGroupId = firstAdaptationSet.id != AdaptationSet.ID_UNSET ? Integer.toString(firstAdaptationSet.id) : ("unset:" + i);
int primaryTrackGroupIndex = trackGroupCount++;
int eventMessageTrackGroupIndex = primaryGroupHasEventMessageTrackFlags[i] ? trackGroupCount++ : C.INDEX_UNSET;
int closedCaptionTrackGroupIndex = primaryGroupClosedCaptionTrackFormats[i].length != 0 ? trackGroupCount++ : C.INDEX_UNSET;
trackGroups[primaryTrackGroupIndex] = new TrackGroup(trackGroupId, formats);
trackGroupInfos[primaryTrackGroupIndex] = TrackGroupInfo.primaryTrack(firstAdaptationSet.type, adaptationSetIndices, primaryTrackGroupIndex, eventMessageTrackGroupIndex, closedCaptionTrackGroupIndex);
if (eventMessageTrackGroupIndex != C.INDEX_UNSET) {
String eventMessageTrackGroupId = trackGroupId + ":emsg";
Format format = new Format.Builder().setId(eventMessageTrackGroupId).setSampleMimeType(MimeTypes.APPLICATION_EMSG).build();
trackGroups[eventMessageTrackGroupIndex] = new TrackGroup(eventMessageTrackGroupId, format);
trackGroupInfos[eventMessageTrackGroupIndex] = TrackGroupInfo.embeddedEmsgTrack(adaptationSetIndices, primaryTrackGroupIndex);
}
if (closedCaptionTrackGroupIndex != C.INDEX_UNSET) {
String closedCaptionTrackGroupId = trackGroupId + ":cc";
trackGroups[closedCaptionTrackGroupIndex] = new TrackGroup(closedCaptionTrackGroupId, primaryGroupClosedCaptionTrackFormats[i]);
trackGroupInfos[closedCaptionTrackGroupIndex] = TrackGroupInfo.embeddedClosedCaptionTrack(adaptationSetIndices, primaryTrackGroupIndex);
}
}
return trackGroupCount;
}
use of androidx.media3.exoplayer.dash.manifest.Representation in project media by androidx.
the class AvcConfig method parse.
/**
* Parses AVC configuration data.
*
* @param data A {@link ParsableByteArray}, whose position is set to the start of the AVC
* configuration data to parse.
* @return A parsed representation of the AVC configuration data.
* @throws ParserException If an error occurred parsing the data.
*/
public static AvcConfig parse(ParsableByteArray data) throws ParserException {
try {
// Skip to the AVCDecoderConfigurationRecord (defined in 14496-15)
data.skipBytes(4);
int nalUnitLengthFieldLength = (data.readUnsignedByte() & 0x3) + 1;
if (nalUnitLengthFieldLength == 3) {
throw new IllegalStateException();
}
List<byte[]> initializationData = new ArrayList<>();
int numSequenceParameterSets = data.readUnsignedByte() & 0x1F;
for (int j = 0; j < numSequenceParameterSets; j++) {
initializationData.add(buildNalUnitForChild(data));
}
int numPictureParameterSets = data.readUnsignedByte();
for (int j = 0; j < numPictureParameterSets; j++) {
initializationData.add(buildNalUnitForChild(data));
}
int width = Format.NO_VALUE;
int height = Format.NO_VALUE;
float pixelWidthHeightRatio = 1;
@Nullable String codecs = null;
if (numSequenceParameterSets > 0) {
byte[] sps = initializationData.get(0);
SpsData spsData = NalUnitUtil.parseSpsNalUnit(initializationData.get(0), nalUnitLengthFieldLength, sps.length);
width = spsData.width;
height = spsData.height;
pixelWidthHeightRatio = spsData.pixelWidthHeightRatio;
codecs = CodecSpecificDataUtil.buildAvcCodecString(spsData.profileIdc, spsData.constraintsFlagsAndReservedZero2Bits, spsData.levelIdc);
}
return new AvcConfig(initializationData, nalUnitLengthFieldLength, width, height, pixelWidthHeightRatio, codecs);
} catch (ArrayIndexOutOfBoundsException e) {
throw ParserException.createForMalformedContainer("Error parsing AVC config", e);
}
}
use of androidx.media3.exoplayer.dash.manifest.Representation in project media by androidx.
the class DashUtilTest method resolveCacheKey_representationCacheKeyIsNull_resolvesRangedUriWithFirstBaseUrl.
@Test
public void resolveCacheKey_representationCacheKeyIsNull_resolvesRangedUriWithFirstBaseUrl() {
ImmutableList<BaseUrl> baseUrls = ImmutableList.of(new BaseUrl("http://www.google.com"), new BaseUrl("http://www.foo.com"));
Representation.SingleSegmentRepresentation representation = new Representation.SingleSegmentRepresentation(/* revisionId= */
1L, new Format.Builder().build(), baseUrls, new SingleSegmentBase(), /* inbandEventStreams= */
null, /* essentialProperties= */
ImmutableList.of(), /* supplementalProperties= */
ImmutableList.of(), /* cacheKey= */
null, /* contentLength= */
1);
RangedUri rangedUri = new RangedUri("path/to/resource", /* start= */
0, /* length= */
1);
String cacheKey = DashUtil.resolveCacheKey(representation, rangedUri);
assertThat(cacheKey).isEqualTo("http://www.google.com/path/to/resource");
}
Aggregations