Search in sources :

Example 31 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class RepeatedTranscodeTransformationTest method repeatedTranscodeNoAudio_givesConsistentLengthOutput.

@Test
public void repeatedTranscodeNoAudio_givesConsistentLengthOutput() throws Exception {
    Context context = ApplicationProvider.getApplicationContext();
    Matrix transformationMatrix = new Matrix();
    transformationMatrix.postTranslate((float) 0.1, (float) 0.1);
    Transformer transformer = new Transformer.Builder(context).setRemoveAudio(true).setTransformationRequest(new TransformationRequest.Builder().setVideoMimeType(MimeTypes.VIDEO_H265).setTransformationMatrix(transformationMatrix).build()).build();
    Set<Long> differentOutputSizesBytes = new HashSet<>();
    for (int i = 0; i < TRANSCODE_COUNT; i++) {
        // Use a long video in case an error occurs a while after the start of the video.
        AndroidTestUtil.TransformationResult result = runTransformer(context, /* testId= */
        "repeatedTranscodeNoAudio_givesConsistentLengthOutput_" + i, transformer, AndroidTestUtil.REMOTE_MP4_10_SECONDS_URI_STRING, /* timeoutSeconds= */
        120);
        differentOutputSizesBytes.add(Assertions.checkNotNull(result.fileSizeBytes));
    }
    assertWithMessage("Different transcoding output sizes detected. Sizes: " + differentOutputSizesBytes).that(differentOutputSizesBytes.size()).isEqualTo(1);
}
Also used : Context(android.content.Context) AndroidTestUtil(com.google.android.exoplayer2.transformer.AndroidTestUtil) Matrix(android.graphics.Matrix) Transformer(com.google.android.exoplayer2.transformer.Transformer) AndroidTestUtil.runTransformer(com.google.android.exoplayer2.transformer.AndroidTestUtil.runTransformer) TransformationRequest(com.google.android.exoplayer2.transformer.TransformationRequest) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 32 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class TtmlDecoder method parseFontSize.

private static void parseFontSize(String expression, TtmlStyle out) throws SubtitleDecoderException {
    String[] expressions = Util.split(expression, "\\s+");
    Matcher matcher;
    if (expressions.length == 1) {
        matcher = FONT_SIZE.matcher(expression);
    } else if (expressions.length == 2) {
        matcher = FONT_SIZE.matcher(expressions[1]);
        Log.w(TAG, "Multiple values in fontSize attribute. Picking the second value for vertical font" + " size and ignoring the first.");
    } else {
        throw new SubtitleDecoderException("Invalid number of entries for fontSize: " + expressions.length + ".");
    }
    if (matcher.matches()) {
        String unit = Assertions.checkNotNull(matcher.group(3));
        switch(unit) {
            case "px":
                out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_PIXEL);
                break;
            case "em":
                out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_EM);
                break;
            case "%":
                out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_PERCENT);
                break;
            default:
                throw new SubtitleDecoderException("Invalid unit for fontSize: '" + unit + "'.");
        }
        out.setFontSize(Float.parseFloat(Assertions.checkNotNull(matcher.group(1))));
    } else {
        throw new SubtitleDecoderException("Invalid expression for fontSize: '" + expression + "'.");
    }
}
Also used : Matcher(java.util.regex.Matcher) SubtitleDecoderException(com.google.android.exoplayer2.text.SubtitleDecoderException)

Example 33 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class TtmlDecoder method decode.

@Override
protected Subtitle decode(byte[] bytes, int length, boolean reset) throws SubtitleDecoderException {
    try {
        XmlPullParser xmlParser = xmlParserFactory.newPullParser();
        Map<String, TtmlStyle> globalStyles = new HashMap<>();
        Map<String, TtmlRegion> regionMap = new HashMap<>();
        Map<String, String> imageMap = new HashMap<>();
        regionMap.put(TtmlNode.ANONYMOUS_REGION_ID, new TtmlRegion(TtmlNode.ANONYMOUS_REGION_ID));
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes, 0, length);
        xmlParser.setInput(inputStream, null);
        @Nullable TtmlSubtitle ttmlSubtitle = null;
        ArrayDeque<TtmlNode> nodeStack = new ArrayDeque<>();
        int unsupportedNodeDepth = 0;
        int eventType = xmlParser.getEventType();
        FrameAndTickRate frameAndTickRate = DEFAULT_FRAME_AND_TICK_RATE;
        CellResolution cellResolution = DEFAULT_CELL_RESOLUTION;
        @Nullable TtsExtent ttsExtent = null;
        while (eventType != XmlPullParser.END_DOCUMENT) {
            @Nullable TtmlNode parent = nodeStack.peek();
            if (unsupportedNodeDepth == 0) {
                String name = xmlParser.getName();
                if (eventType == XmlPullParser.START_TAG) {
                    if (TtmlNode.TAG_TT.equals(name)) {
                        frameAndTickRate = parseFrameAndTickRates(xmlParser);
                        cellResolution = parseCellResolution(xmlParser, DEFAULT_CELL_RESOLUTION);
                        ttsExtent = parseTtsExtent(xmlParser);
                    }
                    if (!isSupportedTag(name)) {
                        Log.i(TAG, "Ignoring unsupported tag: " + xmlParser.getName());
                        unsupportedNodeDepth++;
                    } else if (TtmlNode.TAG_HEAD.equals(name)) {
                        parseHeader(xmlParser, globalStyles, cellResolution, ttsExtent, regionMap, imageMap);
                    } else {
                        try {
                            TtmlNode node = parseNode(xmlParser, parent, regionMap, frameAndTickRate);
                            nodeStack.push(node);
                            if (parent != null) {
                                parent.addChild(node);
                            }
                        } catch (SubtitleDecoderException e) {
                            Log.w(TAG, "Suppressing parser error", e);
                            // Treat the node (and by extension, all of its children) as unsupported.
                            unsupportedNodeDepth++;
                        }
                    }
                } else if (eventType == XmlPullParser.TEXT) {
                    Assertions.checkNotNull(parent).addChild(TtmlNode.buildTextNode(xmlParser.getText()));
                } else if (eventType == XmlPullParser.END_TAG) {
                    if (xmlParser.getName().equals(TtmlNode.TAG_TT)) {
                        ttmlSubtitle = new TtmlSubtitle(Assertions.checkNotNull(nodeStack.peek()), globalStyles, regionMap, imageMap);
                    }
                    nodeStack.pop();
                }
            } else {
                if (eventType == XmlPullParser.START_TAG) {
                    unsupportedNodeDepth++;
                } else if (eventType == XmlPullParser.END_TAG) {
                    unsupportedNodeDepth--;
                }
            }
            xmlParser.next();
            eventType = xmlParser.getEventType();
        }
        if (ttmlSubtitle != null) {
            return ttmlSubtitle;
        } else {
            throw new SubtitleDecoderException("No TTML subtitles found");
        }
    } catch (XmlPullParserException xppe) {
        throw new SubtitleDecoderException("Unable to decode source", xppe);
    } catch (IOException e) {
        throw new IllegalStateException("Unexpected error when reading input.", e);
    }
}
Also used : HashMap(java.util.HashMap) XmlPullParser(org.xmlpull.v1.XmlPullParser) IOException(java.io.IOException) ArrayDeque(java.util.ArrayDeque) SubtitleDecoderException(com.google.android.exoplayer2.text.SubtitleDecoderException) ByteArrayInputStream(java.io.ByteArrayInputStream) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) Nullable(androidx.annotation.Nullable)

Example 34 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class TtmlDecoder method parseTimeExpression.

/**
 * Parses a time expression, returning the parsed timestamp.
 *
 * <p>For the format of a time expression, see: <a
 * href="http://www.w3.org/TR/ttaf1-dfxp/#timing-value-timeExpression">timeExpression</a>
 *
 * @param time A string that includes the time expression.
 * @param frameAndTickRate The effective frame and tick rates of the stream.
 * @return The parsed timestamp in microseconds.
 * @throws SubtitleDecoderException If the given string does not contain a valid time expression.
 */
private static long parseTimeExpression(String time, FrameAndTickRate frameAndTickRate) throws SubtitleDecoderException {
    Matcher matcher = CLOCK_TIME.matcher(time);
    if (matcher.matches()) {
        String hours = Assertions.checkNotNull(matcher.group(1));
        double durationSeconds = Long.parseLong(hours) * 3600;
        String minutes = Assertions.checkNotNull(matcher.group(2));
        durationSeconds += Long.parseLong(minutes) * 60;
        String seconds = Assertions.checkNotNull(matcher.group(3));
        durationSeconds += Long.parseLong(seconds);
        @Nullable String fraction = matcher.group(4);
        durationSeconds += (fraction != null) ? Double.parseDouble(fraction) : 0;
        @Nullable String frames = matcher.group(5);
        durationSeconds += (frames != null) ? Long.parseLong(frames) / frameAndTickRate.effectiveFrameRate : 0;
        @Nullable String subframes = matcher.group(6);
        durationSeconds += (subframes != null) ? ((double) Long.parseLong(subframes)) / frameAndTickRate.subFrameRate / frameAndTickRate.effectiveFrameRate : 0;
        return (long) (durationSeconds * C.MICROS_PER_SECOND);
    }
    matcher = OFFSET_TIME.matcher(time);
    if (matcher.matches()) {
        String timeValue = Assertions.checkNotNull(matcher.group(1));
        double offsetSeconds = Double.parseDouble(timeValue);
        String unit = Assertions.checkNotNull(matcher.group(2));
        switch(unit) {
            case "h":
                offsetSeconds *= 3600;
                break;
            case "m":
                offsetSeconds *= 60;
                break;
            case "s":
                // Do nothing.
                break;
            case "ms":
                offsetSeconds /= 1000;
                break;
            case "f":
                offsetSeconds /= frameAndTickRate.effectiveFrameRate;
                break;
            case "t":
                offsetSeconds /= frameAndTickRate.tickRate;
                break;
        }
        return (long) (offsetSeconds * C.MICROS_PER_SECOND);
    }
    throw new SubtitleDecoderException("Malformed time expression: " + time);
}
Also used : Matcher(java.util.regex.Matcher) Nullable(androidx.annotation.Nullable) SubtitleDecoderException(com.google.android.exoplayer2.text.SubtitleDecoderException)

Example 35 with Assertions.checkNotNull

use of com.google.android.exoplayer2.util.Assertions.checkNotNull in project ExoPlayer by google.

the class HlsMediaChunk method createInstance.

/**
 * Creates a new instance.
 *
 * @param extractorFactory A {@link HlsExtractorFactory} from which the {@link
 *     HlsMediaChunkExtractor} is obtained.
 * @param dataSource The source from which the data should be loaded.
 * @param format The chunk format.
 * @param startOfPlaylistInPeriodUs The position of the playlist in the period in microseconds.
 * @param mediaPlaylist The media playlist from which this chunk was obtained.
 * @param segmentBaseHolder The segment holder.
 * @param playlistUrl The url of the playlist from which this chunk was obtained.
 * @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
 *     information is available in the multivariant playlist.
 * @param trackSelectionReason See {@link #trackSelectionReason}.
 * @param trackSelectionData See {@link #trackSelectionData}.
 * @param isMasterTimestampSource True if the chunk can initialize the timestamp adjuster.
 * @param timestampAdjusterProvider The provider from which to obtain the {@link
 *     TimestampAdjuster}.
 * @param previousChunk The {@link HlsMediaChunk} that preceded this one. May be null.
 * @param mediaSegmentKey The media segment decryption key, if fully encrypted. Null otherwise.
 * @param initSegmentKey The initialization segment decryption key, if fully encrypted. Null
 *     otherwise.
 * @param shouldSpliceIn Whether samples for this chunk should be spliced into existing samples.
 */
public static HlsMediaChunk createInstance(HlsExtractorFactory extractorFactory, DataSource dataSource, Format format, long startOfPlaylistInPeriodUs, HlsMediaPlaylist mediaPlaylist, HlsChunkSource.SegmentBaseHolder segmentBaseHolder, Uri playlistUrl, @Nullable List<Format> muxedCaptionFormats, @C.SelectionReason int trackSelectionReason, @Nullable Object trackSelectionData, boolean isMasterTimestampSource, TimestampAdjusterProvider timestampAdjusterProvider, @Nullable HlsMediaChunk previousChunk, @Nullable byte[] mediaSegmentKey, @Nullable byte[] initSegmentKey, boolean shouldSpliceIn, PlayerId playerId) {
    // Media segment.
    HlsMediaPlaylist.SegmentBase mediaSegment = segmentBaseHolder.segmentBase;
    DataSpec dataSpec = new DataSpec.Builder().setUri(UriUtil.resolveToUri(mediaPlaylist.baseUri, mediaSegment.url)).setPosition(mediaSegment.byteRangeOffset).setLength(mediaSegment.byteRangeLength).setFlags(segmentBaseHolder.isPreload ? FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED : 0).build();
    boolean mediaSegmentEncrypted = mediaSegmentKey != null;
    @Nullable byte[] mediaSegmentIv = mediaSegmentEncrypted ? getEncryptionIvArray(Assertions.checkNotNull(mediaSegment.encryptionIV)) : null;
    DataSource mediaDataSource = buildDataSource(dataSource, mediaSegmentKey, mediaSegmentIv);
    // Init segment.
    HlsMediaPlaylist.Segment initSegment = mediaSegment.initializationSegment;
    DataSpec initDataSpec = null;
    boolean initSegmentEncrypted = false;
    @Nullable DataSource initDataSource = null;
    if (initSegment != null) {
        initSegmentEncrypted = initSegmentKey != null;
        @Nullable byte[] initSegmentIv = initSegmentEncrypted ? getEncryptionIvArray(Assertions.checkNotNull(initSegment.encryptionIV)) : null;
        Uri initSegmentUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, initSegment.url);
        initDataSpec = new DataSpec(initSegmentUri, initSegment.byteRangeOffset, initSegment.byteRangeLength);
        initDataSource = buildDataSource(dataSource, initSegmentKey, initSegmentIv);
    }
    long segmentStartTimeInPeriodUs = startOfPlaylistInPeriodUs + mediaSegment.relativeStartTimeUs;
    long segmentEndTimeInPeriodUs = segmentStartTimeInPeriodUs + mediaSegment.durationUs;
    int discontinuitySequenceNumber = mediaPlaylist.discontinuitySequence + mediaSegment.relativeDiscontinuitySequence;
    @Nullable HlsMediaChunkExtractor previousExtractor = null;
    Id3Decoder id3Decoder;
    ParsableByteArray scratchId3Data;
    if (previousChunk != null) {
        boolean isSameInitData = initDataSpec == previousChunk.initDataSpec || (initDataSpec != null && previousChunk.initDataSpec != null && initDataSpec.uri.equals(previousChunk.initDataSpec.uri) && initDataSpec.position == previousChunk.initDataSpec.position);
        boolean isFollowingChunk = playlistUrl.equals(previousChunk.playlistUrl) && previousChunk.loadCompleted;
        id3Decoder = previousChunk.id3Decoder;
        scratchId3Data = previousChunk.scratchId3Data;
        previousExtractor = isSameInitData && isFollowingChunk && !previousChunk.extractorInvalidated && previousChunk.discontinuitySequenceNumber == discontinuitySequenceNumber ? previousChunk.extractor : null;
    } else {
        id3Decoder = new Id3Decoder();
        scratchId3Data = new ParsableByteArray(Id3Decoder.ID3_HEADER_LENGTH);
    }
    return new HlsMediaChunk(extractorFactory, mediaDataSource, dataSpec, format, mediaSegmentEncrypted, initDataSource, initDataSpec, initSegmentEncrypted, playlistUrl, muxedCaptionFormats, trackSelectionReason, trackSelectionData, segmentStartTimeInPeriodUs, segmentEndTimeInPeriodUs, segmentBaseHolder.mediaSequence, segmentBaseHolder.partIndex, /* isPublished= */
    !segmentBaseHolder.isPreload, discontinuitySequenceNumber, mediaSegment.hasGapTag, isMasterTimestampSource, /* timestampAdjuster= */
    timestampAdjusterProvider.getAdjuster(discontinuitySequenceNumber), mediaSegment.drmInitData, previousExtractor, id3Decoder, scratchId3Data, shouldSpliceIn, playerId);
}
Also used : Uri(android.net.Uri) DataSource(com.google.android.exoplayer2.upstream.DataSource) ParsableByteArray(com.google.android.exoplayer2.util.ParsableByteArray) DataSpec(com.google.android.exoplayer2.upstream.DataSpec) HlsMediaPlaylist(com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist) Id3Decoder(com.google.android.exoplayer2.metadata.id3.Id3Decoder) Nullable(androidx.annotation.Nullable)

Aggregations

Nullable (androidx.annotation.Nullable)28 Format (com.google.android.exoplayer2.Format)10 ArrayList (java.util.ArrayList)9 MediaItem (com.google.android.exoplayer2.MediaItem)8 DataSpec (com.google.android.exoplayer2.upstream.DataSpec)5 Matcher (java.util.regex.Matcher)5 SuppressLint (android.annotation.SuppressLint)4 Context (android.content.Context)4 Uri (android.net.Uri)4 MediaSource (com.google.android.exoplayer2.source.MediaSource)4 DataSource (com.google.android.exoplayer2.upstream.DataSource)4 StatsDataSource (com.google.android.exoplayer2.upstream.StatsDataSource)4 Activity (android.app.Activity)3 Intent (android.content.Intent)3 SQLException (android.database.SQLException)3 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)3 Bundle (android.os.Bundle)3 CallbackMediaItem (androidx.media2.common.CallbackMediaItem)3 C (com.google.android.exoplayer2.C)3 ExoPlayer (com.google.android.exoplayer2.ExoPlayer)3