Search in sources :

Example 1 with Representation

use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.

the class OfflineLicenseHelper method download.

/**
   * Downloads an offline license.
   *
   * @param dataSource The {@link HttpDataSource} to be used for download.
   * @param dashManifest The {@link DashManifest} of the DASH content.
   * @return The downloaded offline license key set id.
   * @throws IOException If an error occurs reading data from the stream.
   * @throws InterruptedException If the thread has been interrupted.
   * @throws DrmSessionException Thrown when there is an error during DRM session.
   */
public byte[] download(HttpDataSource dataSource, DashManifest dashManifest) throws IOException, InterruptedException, DrmSessionException {
    // as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
    if (dashManifest.getPeriodCount() < 1) {
        return null;
    }
    Period period = dashManifest.getPeriod(0);
    int adaptationSetIndex = period.getAdaptationSetIndex(C.TRACK_TYPE_VIDEO);
    if (adaptationSetIndex == C.INDEX_UNSET) {
        adaptationSetIndex = period.getAdaptationSetIndex(C.TRACK_TYPE_AUDIO);
        if (adaptationSetIndex == C.INDEX_UNSET) {
            return null;
        }
    }
    AdaptationSet adaptationSet = period.adaptationSets.get(adaptationSetIndex);
    if (adaptationSet.representations.isEmpty()) {
        return null;
    }
    Representation representation = adaptationSet.representations.get(0);
    DrmInitData drmInitData = representation.format.drmInitData;
    if (drmInitData == null) {
        Format sampleFormat = DashUtil.loadSampleFormat(dataSource, representation);
        if (sampleFormat != null) {
            drmInitData = sampleFormat.drmInitData;
        }
        if (drmInitData == null) {
            return null;
        }
    }
    blockingKeyRequest(DefaultDrmSessionManager.MODE_DOWNLOAD, null, drmInitData);
    return drmSessionManager.getOfflineLicenseKeySetId();
}
Also used : Format(com.google.android.exoplayer2.Format) Period(com.google.android.exoplayer2.source.dash.manifest.Period) AdaptationSet(com.google.android.exoplayer2.source.dash.manifest.AdaptationSet) Representation(com.google.android.exoplayer2.source.dash.manifest.Representation)

Example 2 with Representation

use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.

the class RepresentationTest method testGetCacheKey.

public void testGetCacheKey() {
    String uri = "http://www.google.com";
    SegmentBase base = new SingleSegmentBase(new RangedUri(null, 0, 1), 1, 0, 1, 1);
    Format format = Format.createVideoContainerFormat("0", MimeTypes.APPLICATION_MP4, null, MimeTypes.VIDEO_H264, 2500000, 1920, 1080, Format.NO_VALUE, null, 0);
    Representation representation = Representation.newInstance("test_stream_1", 3, format, uri, base);
    assertEquals("test_stream_1.0.3", representation.getCacheKey());
    format = Format.createVideoContainerFormat("150", MimeTypes.APPLICATION_MP4, null, MimeTypes.VIDEO_H264, 2500000, 1920, 1080, Format.NO_VALUE, null, 0);
    representation = Representation.newInstance("test_stream_1", Representation.REVISION_ID_DEFAULT, format, uri, base);
    assertEquals("test_stream_1.150.-1", representation.getCacheKey());
}
Also used : SingleSegmentBase(com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase) SingleSegmentBase(com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase) Format(com.google.android.exoplayer2.Format)

Example 3 with Representation

use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.

the class HevcConfig method parse.

/**
   * Parses HEVC configuration data.
   *
   * @param data A {@link ParsableByteArray}, whose position is set to the start of the HEVC
   *     configuration data to parse.
   * @return A parsed representation of the HEVC configuration data.
   * @throws ParserException If an error occurred parsing the data.
   */
public static HevcConfig parse(ParsableByteArray data) throws ParserException {
    try {
        // Skip to the NAL unit length size field.
        data.skipBytes(21);
        int lengthSizeMinusOne = data.readUnsignedByte() & 0x03;
        // Calculate the combined size of all VPS/SPS/PPS bitstreams.
        int numberOfArrays = data.readUnsignedByte();
        int csdLength = 0;
        int csdStartPosition = data.getPosition();
        for (int i = 0; i < numberOfArrays; i++) {
            // completeness (1), nal_unit_type (7)
            data.skipBytes(1);
            int numberOfNalUnits = data.readUnsignedShort();
            for (int j = 0; j < numberOfNalUnits; j++) {
                int nalUnitLength = data.readUnsignedShort();
                // Start code and NAL unit.
                csdLength += 4 + nalUnitLength;
                data.skipBytes(nalUnitLength);
            }
        }
        // Concatenate the codec-specific data into a single buffer.
        data.setPosition(csdStartPosition);
        byte[] buffer = new byte[csdLength];
        int bufferPosition = 0;
        for (int i = 0; i < numberOfArrays; i++) {
            // completeness (1), nal_unit_type (7)
            data.skipBytes(1);
            int numberOfNalUnits = data.readUnsignedShort();
            for (int j = 0; j < numberOfNalUnits; j++) {
                int nalUnitLength = data.readUnsignedShort();
                System.arraycopy(NalUnitUtil.NAL_START_CODE, 0, buffer, bufferPosition, NalUnitUtil.NAL_START_CODE.length);
                bufferPosition += NalUnitUtil.NAL_START_CODE.length;
                System.arraycopy(data.data, data.getPosition(), buffer, bufferPosition, nalUnitLength);
                bufferPosition += nalUnitLength;
                data.skipBytes(nalUnitLength);
            }
        }
        List<byte[]> initializationData = csdLength == 0 ? null : Collections.singletonList(buffer);
        return new HevcConfig(initializationData, lengthSizeMinusOne + 1);
    } catch (ArrayIndexOutOfBoundsException e) {
        throw new ParserException("Error parsing HEVC config", e);
    }
}
Also used : ParserException(com.google.android.exoplayer2.ParserException)

Example 4 with Representation

use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.

the class DefaultDashChunkSource method getNextChunk.

@Override
public final void getNextChunk(MediaChunk previous, long playbackPositionUs, ChunkHolder out) {
    if (fatalError != null) {
        return;
    }
    long bufferedDurationUs = previous != null ? (previous.endTimeUs - playbackPositionUs) : 0;
    trackSelection.updateSelectedTrack(bufferedDurationUs);
    RepresentationHolder representationHolder = representationHolders[trackSelection.getSelectedIndex()];
    Representation selectedRepresentation = representationHolder.representation;
    DashSegmentIndex segmentIndex = representationHolder.segmentIndex;
    RangedUri pendingInitializationUri = null;
    RangedUri pendingIndexUri = null;
    if (representationHolder.extractorWrapper.getSampleFormats() == null) {
        pendingInitializationUri = selectedRepresentation.getInitializationUri();
    }
    if (segmentIndex == null) {
        pendingIndexUri = selectedRepresentation.getIndexUri();
    }
    if (pendingInitializationUri != null || pendingIndexUri != null) {
        // We have initialization and/or index requests to make.
        out.chunk = newInitializationChunk(representationHolder, dataSource, trackSelection.getSelectedFormat(), trackSelection.getSelectionReason(), trackSelection.getSelectionData(), pendingInitializationUri, pendingIndexUri);
        return;
    }
    long nowUs = getNowUnixTimeUs();
    int availableSegmentCount = representationHolder.getSegmentCount();
    if (availableSegmentCount == 0) {
        // The index doesn't define any segments.
        out.endOfStream = !manifest.dynamic || (periodIndex < manifest.getPeriodCount() - 1);
        return;
    }
    int firstAvailableSegmentNum = representationHolder.getFirstSegmentNum();
    int lastAvailableSegmentNum;
    if (availableSegmentCount == DashSegmentIndex.INDEX_UNBOUNDED) {
        // The index is itself unbounded. We need to use the current time to calculate the range of
        // available segments.
        long liveEdgeTimeUs = nowUs - manifest.availabilityStartTime * 1000;
        long periodStartUs = manifest.getPeriod(periodIndex).startMs * 1000;
        long liveEdgeTimeInPeriodUs = liveEdgeTimeUs - periodStartUs;
        if (manifest.timeShiftBufferDepth != C.TIME_UNSET) {
            long bufferDepthUs = manifest.timeShiftBufferDepth * 1000;
            firstAvailableSegmentNum = Math.max(firstAvailableSegmentNum, representationHolder.getSegmentNum(liveEdgeTimeInPeriodUs - bufferDepthUs));
        }
        // getSegmentNum(liveEdgeTimestampUs) will not be completed yet, so subtract one to get the
        // index of the last completed segment.
        lastAvailableSegmentNum = representationHolder.getSegmentNum(liveEdgeTimeInPeriodUs) - 1;
    } else {
        lastAvailableSegmentNum = firstAvailableSegmentNum + availableSegmentCount - 1;
    }
    int segmentNum;
    if (previous == null) {
        segmentNum = Util.constrainValue(representationHolder.getSegmentNum(playbackPositionUs), firstAvailableSegmentNum, lastAvailableSegmentNum);
    } else {
        segmentNum = previous.getNextChunkIndex();
        if (segmentNum < firstAvailableSegmentNum) {
            // This is before the first chunk in the current manifest.
            fatalError = new BehindLiveWindowException();
            return;
        }
    }
    if (segmentNum > lastAvailableSegmentNum || (missingLastSegment && segmentNum >= lastAvailableSegmentNum)) {
        // This is beyond the last chunk in the current manifest.
        out.endOfStream = !manifest.dynamic || (periodIndex < manifest.getPeriodCount() - 1);
        return;
    }
    int maxSegmentCount = Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1);
    out.chunk = newMediaChunk(representationHolder, dataSource, trackSelection.getSelectedFormat(), trackSelection.getSelectionReason(), trackSelection.getSelectionData(), segmentNum, maxSegmentCount);
}
Also used : BehindLiveWindowException(com.google.android.exoplayer2.source.BehindLiveWindowException) RangedUri(com.google.android.exoplayer2.source.dash.manifest.RangedUri) Representation(com.google.android.exoplayer2.source.dash.manifest.Representation)

Example 5 with Representation

use of com.google.android.exoplayer2.source.dash.manifest.Representation in project ExoPlayer by google.

the class DefaultDashChunkSource method newMediaChunk.

private static Chunk newMediaChunk(RepresentationHolder representationHolder, DataSource dataSource, Format trackFormat, int trackSelectionReason, Object trackSelectionData, int firstSegmentNum, int maxSegmentCount) {
    Representation representation = representationHolder.representation;
    long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum);
    RangedUri segmentUri = representationHolder.getSegmentUrl(firstSegmentNum);
    String baseUrl = representation.baseUrl;
    if (representationHolder.extractorWrapper == null) {
        long endTimeUs = representationHolder.getSegmentEndTimeUs(firstSegmentNum);
        DataSpec dataSpec = new DataSpec(segmentUri.resolveUri(baseUrl), segmentUri.start, segmentUri.length, representation.getCacheKey());
        return new SingleSampleMediaChunk(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, firstSegmentNum, representationHolder.trackType, trackFormat);
    } else {
        int segmentCount = 1;
        for (int i = 1; i < maxSegmentCount; i++) {
            RangedUri nextSegmentUri = representationHolder.getSegmentUrl(firstSegmentNum + i);
            RangedUri mergedSegmentUri = segmentUri.attemptMerge(nextSegmentUri, baseUrl);
            if (mergedSegmentUri == null) {
                // Unable to merge segment fetches because the URIs do not merge.
                break;
            }
            segmentUri = mergedSegmentUri;
            segmentCount++;
        }
        long endTimeUs = representationHolder.getSegmentEndTimeUs(firstSegmentNum + segmentCount - 1);
        DataSpec dataSpec = new DataSpec(segmentUri.resolveUri(baseUrl), segmentUri.start, segmentUri.length, representation.getCacheKey());
        long sampleOffsetUs = -representation.presentationTimeOffsetUs;
        return new ContainerMediaChunk(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, firstSegmentNum, segmentCount, sampleOffsetUs, representationHolder.extractorWrapper);
    }
}
Also used : SingleSampleMediaChunk(com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk) RangedUri(com.google.android.exoplayer2.source.dash.manifest.RangedUri) DataSpec(com.google.android.exoplayer2.upstream.DataSpec) Representation(com.google.android.exoplayer2.source.dash.manifest.Representation) ContainerMediaChunk(com.google.android.exoplayer2.source.chunk.ContainerMediaChunk)

Aggregations

Representation (com.google.android.exoplayer2.source.dash.manifest.Representation)17 Nullable (androidx.annotation.Nullable)12 RangedUri (com.google.android.exoplayer2.source.dash.manifest.RangedUri)10 Format (com.google.android.exoplayer2.Format)9 AdaptationSet (com.google.android.exoplayer2.source.dash.manifest.AdaptationSet)6 ArrayList (java.util.ArrayList)6 SingleSegmentBase (com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase)5 DataSpec (com.google.android.exoplayer2.upstream.DataSpec)5 Test (org.junit.Test)5 SchemeData (com.google.android.exoplayer2.drm.DrmInitData.SchemeData)4 StreamKey (com.google.android.exoplayer2.offline.StreamKey)3 BehindLiveWindowException (com.google.android.exoplayer2.source.BehindLiveWindowException)3 ContainerMediaChunk (com.google.android.exoplayer2.source.chunk.ContainerMediaChunk)3 InitializationChunk (com.google.android.exoplayer2.source.chunk.InitializationChunk)3 SingleSampleMediaChunk (com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk)3 MultiSegmentRepresentation (com.google.android.exoplayer2.source.dash.manifest.Representation.MultiSegmentRepresentation)3 SingleSegmentRepresentation (com.google.android.exoplayer2.source.dash.manifest.Representation.SingleSegmentRepresentation)3 DrmInitData (com.google.android.exoplayer2.drm.DrmInitData)2 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)2 DashSegmentIndex (com.google.android.exoplayer2.source.dash.DashSegmentIndex)2