Search in sources :

Example 21 with DrmInitData

use of com.google.android.exoplayer2.drm.DrmInitData in project ExoPlayer by google.

the class DumpableFormat method dump.

@Override
public void dump(Dumper dumper) {
    dumper.startBlock("format " + index);
    addIfNonDefault(dumper, "averageBitrate", format -> format.averageBitrate);
    addIfNonDefault(dumper, "peakBitrate", format -> format.peakBitrate);
    addIfNonDefault(dumper, "id", format -> format.id);
    addIfNonDefault(dumper, "containerMimeType", format -> format.containerMimeType);
    addIfNonDefault(dumper, "sampleMimeType", format -> format.sampleMimeType);
    addIfNonDefault(dumper, "codecs", format -> format.codecs);
    addIfNonDefault(dumper, "maxInputSize", format -> format.maxInputSize);
    addIfNonDefault(dumper, "width", format -> format.width);
    addIfNonDefault(dumper, "height", format -> format.height);
    addIfNonDefault(dumper, "frameRate", format -> format.frameRate);
    addIfNonDefault(dumper, "rotationDegrees", format -> format.rotationDegrees);
    addIfNonDefault(dumper, "pixelWidthHeightRatio", format -> format.pixelWidthHeightRatio);
    @Nullable ColorInfo colorInfo = format.colorInfo;
    if (colorInfo != null) {
        dumper.startBlock("colorInfo");
        dumper.add("colorSpace", colorInfo.colorSpace);
        dumper.add("colorRange", colorInfo.colorRange);
        dumper.add("colorTransfer", colorInfo.colorTransfer);
        dumper.add("hdrStaticInfo", colorInfo.hdrStaticInfo);
        dumper.endBlock();
    }
    addIfNonDefault(dumper, "channelCount", format -> format.channelCount);
    addIfNonDefault(dumper, "sampleRate", format -> format.sampleRate);
    addIfNonDefault(dumper, "pcmEncoding", format -> format.pcmEncoding);
    addIfNonDefault(dumper, "encoderDelay", format -> format.encoderDelay);
    addIfNonDefault(dumper, "encoderPadding", format -> format.encoderPadding);
    addIfNonDefault(dumper, "subsampleOffsetUs", format -> format.subsampleOffsetUs);
    addIfNonDefault(dumper, "selectionFlags", format -> format.selectionFlags);
    addIfNonDefault(dumper, "language", format -> format.language);
    addIfNonDefault(dumper, "label", format -> format.label);
    if (format.drmInitData != null) {
        dumper.add("drmInitData", format.drmInitData.hashCode());
    }
    addIfNonDefault(dumper, "metadata", format -> format.metadata);
    if (!format.initializationData.isEmpty()) {
        dumper.startBlock("initializationData");
        for (int i = 0; i < format.initializationData.size(); i++) {
            dumper.add("data", format.initializationData.get(i));
        }
        dumper.endBlock();
    }
    dumper.endBlock();
}
Also used : Nullable(androidx.annotation.Nullable) ColorInfo(com.google.android.exoplayer2.video.ColorInfo)

Example 22 with DrmInitData

use of com.google.android.exoplayer2.drm.DrmInitData in project ExoPlayer by google.

the class DefaultDrmSessionManager method getSchemeDatas.

/**
 * Extracts {@link SchemeData} instances suitable for the given DRM scheme {@link UUID}.
 *
 * @param drmInitData The {@link DrmInitData} from which to extract the {@link SchemeData}.
 * @param uuid The UUID.
 * @param allowMissingData Whether a {@link SchemeData} with null {@link SchemeData#data} may be
 *     returned.
 * @return The extracted {@link SchemeData} instances, or an empty list if no suitable data is
 *     present.
 */
private static List<SchemeData> getSchemeDatas(DrmInitData drmInitData, UUID uuid, boolean allowMissingData) {
    // Look for matching scheme data (matching the Common PSSH box for ClearKey).
    List<SchemeData> matchingSchemeDatas = new ArrayList<>(drmInitData.schemeDataCount);
    for (int i = 0; i < drmInitData.schemeDataCount; i++) {
        SchemeData schemeData = drmInitData.get(i);
        boolean uuidMatches = schemeData.matches(uuid) || (C.CLEARKEY_UUID.equals(uuid) && schemeData.matches(C.COMMON_PSSH_UUID));
        if (uuidMatches && (schemeData.data != null || allowMissingData)) {
            matchingSchemeDatas.add(schemeData);
        }
    }
    return matchingSchemeDatas;
}
Also used : ArrayList(java.util.ArrayList) SchemeData(com.google.android.exoplayer2.drm.DrmInitData.SchemeData) SuppressLint(android.annotation.SuppressLint)

Example 23 with DrmInitData

use of com.google.android.exoplayer2.drm.DrmInitData in project ExoPlayer by google.

the class HlsMediaChunk method prepareExtraction.

@RequiresNonNull("output")
@EnsuresNonNull("extractor")
private DefaultExtractorInput prepareExtraction(DataSource dataSource, DataSpec dataSpec, boolean initializeTimestampAdjuster) throws IOException {
    long bytesToRead = dataSource.open(dataSpec);
    if (initializeTimestampAdjuster) {
        try {
            timestampAdjuster.sharedInitializeOrWait(isMasterTimestampSource, startTimeUs);
        } catch (InterruptedException e) {
            throw new InterruptedIOException();
        }
    }
    DefaultExtractorInput extractorInput = new DefaultExtractorInput(dataSource, dataSpec.position, bytesToRead);
    if (extractor == null) {
        long id3Timestamp = peekId3PrivTimestamp(extractorInput);
        extractorInput.resetPeekPosition();
        extractor = previousExtractor != null ? previousExtractor.recreate() : extractorFactory.createExtractor(dataSpec.uri, trackFormat, muxedCaptionFormats, timestampAdjuster, dataSource.getResponseHeaders(), extractorInput, playerId);
        if (extractor.isPackedAudioExtractor()) {
            output.setSampleOffsetUs(id3Timestamp != C.TIME_UNSET ? timestampAdjuster.adjustTsTimestamp(id3Timestamp) : startTimeUs);
        } else {
            // In case the container format changes mid-stream to non-packed-audio, we need to reset
            // the timestamp offset.
            output.setSampleOffsetUs(/* sampleOffsetUs= */
            0L);
        }
        output.onNewExtractor();
        extractor.init(output);
    }
    output.setDrmInitData(drmInitData);
    return extractorInput;
}
Also used : InterruptedIOException(java.io.InterruptedIOException) DefaultExtractorInput(com.google.android.exoplayer2.extractor.DefaultExtractorInput) EnsuresNonNull(org.checkerframework.checker.nullness.qual.EnsuresNonNull) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 24 with DrmInitData

use of com.google.android.exoplayer2.drm.DrmInitData in project ExoPlayer by google.

the class HlsMediaPeriod method buildAndPrepareMainSampleStreamWrapper.

/**
 * This method creates and starts preparation of the main {@link HlsSampleStreamWrapper}.
 *
 * <p>The main sample stream wrapper is the first element of {@link #sampleStreamWrappers}. It
 * provides {@link SampleStream}s for the variant urls in the multivariant playlist. It may be
 * adaptive and may contain multiple muxed tracks.
 *
 * <p>If chunkless preparation is allowed, the media period will try preparation without segment
 * downloads. This is only possible if variants contain the CODECS attribute. If not, traditional
 * preparation with segment downloads will take place. The following points apply to chunkless
 * preparation:
 *
 * <ul>
 *   <li>A muxed audio track will be exposed if the codecs list contain an audio entry and the
 *       multivariant playlist either contains an EXT-X-MEDIA tag without the URI attribute or
 *       does not contain any EXT-X-MEDIA tag.
 *   <li>Closed captions will only be exposed if they are declared by the multivariant playlist.
 *   <li>An ID3 track is exposed preemptively, in case the segments contain an ID3 track.
 * </ul>
 *
 * @param multivariantPlaylist The HLS multivariant playlist.
 * @param positionUs If preparation requires any chunk downloads, the position in microseconds at
 *     which downloading should start. Ignored otherwise.
 * @param sampleStreamWrappers List to which the built main sample stream wrapper should be added.
 * @param manifestUrlIndicesPerWrapper List to which the selected variant indices should be added.
 * @param overridingDrmInitData Overriding {@link DrmInitData}, keyed by protection scheme type
 *     (i.e. {@link DrmInitData#schemeType}).
 */
private void buildAndPrepareMainSampleStreamWrapper(HlsMultivariantPlaylist multivariantPlaylist, long positionUs, List<HlsSampleStreamWrapper> sampleStreamWrappers, List<int[]> manifestUrlIndicesPerWrapper, Map<String, DrmInitData> overridingDrmInitData) {
    int[] variantTypes = new int[multivariantPlaylist.variants.size()];
    int videoVariantCount = 0;
    int audioVariantCount = 0;
    for (int i = 0; i < multivariantPlaylist.variants.size(); i++) {
        Variant variant = multivariantPlaylist.variants.get(i);
        Format format = variant.format;
        if (format.height > 0 || Util.getCodecsOfType(format.codecs, C.TRACK_TYPE_VIDEO) != null) {
            variantTypes[i] = C.TRACK_TYPE_VIDEO;
            videoVariantCount++;
        } else if (Util.getCodecsOfType(format.codecs, C.TRACK_TYPE_AUDIO) != null) {
            variantTypes[i] = C.TRACK_TYPE_AUDIO;
            audioVariantCount++;
        } else {
            variantTypes[i] = C.TRACK_TYPE_UNKNOWN;
        }
    }
    boolean useVideoVariantsOnly = false;
    boolean useNonAudioVariantsOnly = false;
    int selectedVariantsCount = variantTypes.length;
    if (videoVariantCount > 0) {
        // We've identified some variants as definitely containing video. Assume variants within the
        // multivariant playlist are marked consistently, and hence that we have the full set. Filter
        // out any other variants, which are likely to be audio only.
        useVideoVariantsOnly = true;
        selectedVariantsCount = videoVariantCount;
    } else if (audioVariantCount < variantTypes.length) {
        // We've identified some variants, but not all, as being audio only. Filter them out to leave
        // the remaining variants, which are likely to contain video.
        useNonAudioVariantsOnly = true;
        selectedVariantsCount = variantTypes.length - audioVariantCount;
    }
    Uri[] selectedPlaylistUrls = new Uri[selectedVariantsCount];
    Format[] selectedPlaylistFormats = new Format[selectedVariantsCount];
    int[] selectedVariantIndices = new int[selectedVariantsCount];
    int outIndex = 0;
    for (int i = 0; i < multivariantPlaylist.variants.size(); i++) {
        if ((!useVideoVariantsOnly || variantTypes[i] == C.TRACK_TYPE_VIDEO) && (!useNonAudioVariantsOnly || variantTypes[i] != C.TRACK_TYPE_AUDIO)) {
            Variant variant = multivariantPlaylist.variants.get(i);
            selectedPlaylistUrls[outIndex] = variant.url;
            selectedPlaylistFormats[outIndex] = variant.format;
            selectedVariantIndices[outIndex++] = i;
        }
    }
    String codecs = selectedPlaylistFormats[0].codecs;
    int numberOfVideoCodecs = Util.getCodecCountOfType(codecs, C.TRACK_TYPE_VIDEO);
    int numberOfAudioCodecs = Util.getCodecCountOfType(codecs, C.TRACK_TYPE_AUDIO);
    boolean codecsStringAllowsChunklessPreparation = numberOfAudioCodecs <= 1 && numberOfVideoCodecs <= 1 && numberOfAudioCodecs + numberOfVideoCodecs > 0;
    @C.TrackType int trackType = !useVideoVariantsOnly && numberOfAudioCodecs > 0 ? C.TRACK_TYPE_AUDIO : C.TRACK_TYPE_DEFAULT;
    String sampleStreamWrapperUid = "main";
    HlsSampleStreamWrapper sampleStreamWrapper = buildSampleStreamWrapper(sampleStreamWrapperUid, trackType, selectedPlaylistUrls, selectedPlaylistFormats, multivariantPlaylist.muxedAudioFormat, multivariantPlaylist.muxedCaptionFormats, overridingDrmInitData, positionUs);
    sampleStreamWrappers.add(sampleStreamWrapper);
    manifestUrlIndicesPerWrapper.add(selectedVariantIndices);
    if (allowChunklessPreparation && codecsStringAllowsChunklessPreparation) {
        List<TrackGroup> muxedTrackGroups = new ArrayList<>();
        if (numberOfVideoCodecs > 0) {
            Format[] videoFormats = new Format[selectedVariantsCount];
            for (int i = 0; i < videoFormats.length; i++) {
                videoFormats[i] = deriveVideoFormat(selectedPlaylistFormats[i]);
            }
            muxedTrackGroups.add(new TrackGroup(sampleStreamWrapperUid, videoFormats));
            if (numberOfAudioCodecs > 0 && (multivariantPlaylist.muxedAudioFormat != null || multivariantPlaylist.audios.isEmpty())) {
                muxedTrackGroups.add(new TrackGroup(/* id= */
                sampleStreamWrapperUid + ":audio", deriveAudioFormat(selectedPlaylistFormats[0], multivariantPlaylist.muxedAudioFormat, /* isPrimaryTrackInVariant= */
                false)));
            }
            List<Format> ccFormats = multivariantPlaylist.muxedCaptionFormats;
            if (ccFormats != null) {
                for (int i = 0; i < ccFormats.size(); i++) {
                    String ccId = sampleStreamWrapperUid + ":cc:" + i;
                    muxedTrackGroups.add(new TrackGroup(ccId, ccFormats.get(i)));
                }
            }
        } else /* numberOfAudioCodecs > 0 */
        {
            // Variants only contain audio.
            Format[] audioFormats = new Format[selectedVariantsCount];
            for (int i = 0; i < audioFormats.length; i++) {
                audioFormats[i] = deriveAudioFormat(/* variantFormat= */
                selectedPlaylistFormats[i], multivariantPlaylist.muxedAudioFormat, /* isPrimaryTrackInVariant= */
                true);
            }
            muxedTrackGroups.add(new TrackGroup(sampleStreamWrapperUid, audioFormats));
        }
        TrackGroup id3TrackGroup = new TrackGroup(/* id= */
        sampleStreamWrapperUid + ":id3", new Format.Builder().setId("ID3").setSampleMimeType(MimeTypes.APPLICATION_ID3).build());
        muxedTrackGroups.add(id3TrackGroup);
        sampleStreamWrapper.prepareWithMultivariantPlaylistInfo(muxedTrackGroups.toArray(new TrackGroup[0]), /* primaryTrackGroupIndex= */
        0, /* optionalTrackGroupsIndices...= */
        muxedTrackGroups.indexOf(id3TrackGroup));
    }
}
Also used : ArrayList(java.util.ArrayList) Uri(android.net.Uri) Variant(com.google.android.exoplayer2.source.hls.playlist.HlsMultivariantPlaylist.Variant) Format(com.google.android.exoplayer2.Format) TrackGroup(com.google.android.exoplayer2.source.TrackGroup)

Example 25 with DrmInitData

use of com.google.android.exoplayer2.drm.DrmInitData in project ExoPlayer by google.

the class HlsMediaPeriod method deriveOverridingDrmInitData.

private static Map<String, DrmInitData> deriveOverridingDrmInitData(List<DrmInitData> sessionKeyDrmInitData) {
    ArrayList<DrmInitData> mutableSessionKeyDrmInitData = new ArrayList<>(sessionKeyDrmInitData);
    HashMap<String, DrmInitData> drmInitDataBySchemeType = new HashMap<>();
    for (int i = 0; i < mutableSessionKeyDrmInitData.size(); i++) {
        DrmInitData drmInitData = sessionKeyDrmInitData.get(i);
        String scheme = drmInitData.schemeType;
        // Merge any subsequent drmInitData instances that have the same scheme type. This is valid
        // due to the assumptions documented on HlsMediaSource.Builder.setUseSessionKeys, and is
        // necessary to get data for different CDNs (e.g. Widevine and PlayReady) into a single
        // drmInitData.
        int j = i + 1;
        while (j < mutableSessionKeyDrmInitData.size()) {
            DrmInitData nextDrmInitData = mutableSessionKeyDrmInitData.get(j);
            if (TextUtils.equals(nextDrmInitData.schemeType, scheme)) {
                drmInitData = drmInitData.merge(nextDrmInitData);
                mutableSessionKeyDrmInitData.remove(j);
            } else {
                j++;
            }
        }
        drmInitDataBySchemeType.put(scheme, drmInitData);
    }
    return drmInitDataBySchemeType;
}
Also used : DrmInitData(com.google.android.exoplayer2.drm.DrmInitData) HashMap(java.util.HashMap) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList)

Aggregations

DrmInitData (com.google.android.exoplayer2.drm.DrmInitData)17 Nullable (androidx.annotation.Nullable)16 Format (com.google.android.exoplayer2.Format)10 SchemeData (com.google.android.exoplayer2.drm.DrmInitData.SchemeData)10 ArrayList (java.util.ArrayList)10 Metadata (com.google.android.exoplayer2.metadata.Metadata)5 SuppressLint (android.annotation.SuppressLint)4 Uri (android.net.Uri)4 TrackGroup (com.google.android.exoplayer2.source.TrackGroup)3 ColorInfo (com.google.android.exoplayer2.video.ColorInfo)3 MediaFormat (android.media.MediaFormat)2 Looper (android.os.Looper)2 AndroidJUnit4 (androidx.test.ext.junit.runners.AndroidJUnit4)2 C (com.google.android.exoplayer2.C)2 PlayerId (com.google.android.exoplayer2.analytics.PlayerId)2 DrmSessionReference (com.google.android.exoplayer2.drm.DrmSessionManager.DrmSessionReference)2 AppManagedProvider (com.google.android.exoplayer2.drm.ExoMediaDrm.AppManagedProvider)2 GaplessInfoHolder (com.google.android.exoplayer2.extractor.GaplessInfoHolder)2 SeekPoint (com.google.android.exoplayer2.extractor.SeekPoint)2 ContainerAtom (com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom)2