Search in sources :

Example 6 with Cue

use of com.google.android.exoplayer2.text.Cue in project ExoPlayer by google.

the class DefaultAnalyticsCollector method onCues.

@Override
public void onCues(List<Cue> cues) {
    EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
    sendEvent(eventTime, AnalyticsListener.EVENT_CUES, listener -> listener.onCues(eventTime, cues));
}
Also used : EventTime(com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime)

Example 7 with Cue

use of com.google.android.exoplayer2.text.Cue in project ExoPlayer by google.

the class ImaAdsLoaderTest method loadAd_withLargeAdCuePoint_updatesAdPlaybackStateWithLoadedAd.

@Test
public void loadAd_withLargeAdCuePoint_updatesAdPlaybackStateWithLoadedAd() {
    // Use a large enough value to test correct truncating of large cue points.
    float midrollTimeSecs = Float.MAX_VALUE;
    List<Float> cuePoints = ImmutableList.of(midrollTimeSecs);
    when(mockAdsManager.getAdCuePoints()).thenReturn(cuePoints);
    imaAdsLoader.start(adsMediaSource, TEST_DATA_SPEC, TEST_ADS_ID, adViewProvider, adsLoaderListener);
    videoAdPlayer.loadAd(TEST_AD_MEDIA_INFO, new AdPodInfo() {

        @Override
        public int getTotalAds() {
            return 1;
        }

        @Override
        public int getAdPosition() {
            return 1;
        }

        @Override
        public boolean isBumper() {
            return false;
        }

        @Override
        public double getMaxDuration() {
            return 0;
        }

        @Override
        public int getPodIndex() {
            return 0;
        }

        @Override
        public double getTimeOffset() {
            return midrollTimeSecs;
        }
    });
    assertThat(getAdPlaybackState(/* periodIndex= */
    0)).isEqualTo(new AdPlaybackState(TEST_ADS_ID, getAdGroupTimesUsForCuePoints(cuePoints)).withContentDurationUs(CONTENT_PERIOD_DURATION_US).withAdCount(/* adGroupIndex= */
    0, /* adCount= */
    1).withAdUri(/* adGroupIndex= */
    0, /* adIndexInAdGroup= */
    0, TEST_URI).withAdDurationsUs(new long[][] { { TEST_AD_DURATION_US } }));
}
Also used : AdPlaybackState(com.google.android.exoplayer2.source.ads.AdPlaybackState) AdPodInfo(com.google.ads.interactivemedia.v3.api.AdPodInfo) Test(org.junit.Test)

Example 8 with Cue

use of com.google.android.exoplayer2.text.Cue in project ExoPlayer by google.

the class Cea608Decoder method getDisplayCues.

private List<Cue> getDisplayCues() {
    // CEA-608 does not define middle and end alignment, however content providers artificially
    // introduce them using whitespace. When each cue is built, we try and infer the alignment based
    // on the amount of whitespace either side of the text. To avoid consecutive cues being aligned
    // differently, we force all cues to have the same alignment, with start alignment given
    // preference, then middle alignment, then end alignment.
    @Cue.AnchorType int positionAnchor = Cue.ANCHOR_TYPE_END;
    int cueBuilderCount = cueBuilders.size();
    List<@NullableType Cue> cueBuilderCues = new ArrayList<>(cueBuilderCount);
    for (int i = 0; i < cueBuilderCount; i++) {
        @Nullable Cue cue = cueBuilders.get(i).build(/* forcedPositionAnchor= */
        Cue.TYPE_UNSET);
        cueBuilderCues.add(cue);
        if (cue != null) {
            positionAnchor = min(positionAnchor, cue.positionAnchor);
        }
    }
    // Skip null cues and rebuild any that don't have the preferred alignment.
    List<Cue> displayCues = new ArrayList<>(cueBuilderCount);
    for (int i = 0; i < cueBuilderCount; i++) {
        @Nullable Cue cue = cueBuilderCues.get(i);
        if (cue != null) {
            if (cue.positionAnchor != positionAnchor) {
                // The last time we built this cue it was non-null, it will be non-null this time too.
                cue = Assertions.checkNotNull(cueBuilders.get(i).build(positionAnchor));
            }
            displayCues.add(cue);
        }
    }
    return displayCues;
}
Also used : Cue(com.google.android.exoplayer2.text.Cue) ArrayList(java.util.ArrayList) Nullable(androidx.annotation.Nullable)

Example 9 with Cue

use of com.google.android.exoplayer2.text.Cue in project ExoPlayer by google.

the class WebViewSubtitleOutput method updateWebView.

private void updateWebView() {
    StringBuilder html = new StringBuilder();
    html.append(Util.formatInvariant("<body><div style='" + "-webkit-user-select:none;" + "position:fixed;" + "top:0;" + "bottom:0;" + "left:0;" + "right:0;" + "color:%s;" + "font-size:%s;" + "line-height:%.2f;" + "text-shadow:%s;" + "'>", HtmlUtils.toCssRgba(style.foregroundColor), convertTextSizeToCss(defaultTextSizeType, defaultTextSize), CSS_LINE_HEIGHT, convertCaptionStyleToCssTextShadow(style)));
    Map<String, String> cssRuleSets = new HashMap<>();
    cssRuleSets.put(HtmlUtils.cssAllClassDescendantsSelector(DEFAULT_BACKGROUND_CSS_CLASS), Util.formatInvariant("background-color:%s;", HtmlUtils.toCssRgba(style.backgroundColor)));
    for (int i = 0; i < textCues.size(); i++) {
        Cue cue = textCues.get(i);
        float positionPercent = (cue.position != Cue.DIMEN_UNSET) ? (cue.position * 100) : 50;
        int positionAnchorTranslatePercent = anchorTypeToTranslatePercent(cue.positionAnchor);
        String lineValue;
        boolean lineMeasuredFromEnd = false;
        int lineAnchorTranslatePercent = 0;
        if (cue.line != Cue.DIMEN_UNSET) {
            switch(cue.lineType) {
                case Cue.LINE_TYPE_NUMBER:
                    if (cue.line >= 0) {
                        lineValue = Util.formatInvariant("%.2fem", cue.line * CSS_LINE_HEIGHT);
                    } else {
                        lineValue = Util.formatInvariant("%.2fem", (-cue.line - 1) * CSS_LINE_HEIGHT);
                        lineMeasuredFromEnd = true;
                    }
                    break;
                case Cue.LINE_TYPE_FRACTION:
                case Cue.TYPE_UNSET:
                default:
                    lineValue = Util.formatInvariant("%.2f%%", cue.line * 100);
                    lineAnchorTranslatePercent = cue.verticalType == Cue.VERTICAL_TYPE_RL ? -anchorTypeToTranslatePercent(cue.lineAnchor) : anchorTypeToTranslatePercent(cue.lineAnchor);
            }
        } else {
            lineValue = Util.formatInvariant("%.2f%%", (1.0f - bottomPaddingFraction) * 100);
            lineAnchorTranslatePercent = -100;
        }
        String size = cue.size != Cue.DIMEN_UNSET ? Util.formatInvariant("%.2f%%", cue.size * 100) : "fit-content";
        String textAlign = convertAlignmentToCss(cue.textAlignment);
        String writingMode = convertVerticalTypeToCss(cue.verticalType);
        String cueTextSizeCssPx = convertTextSizeToCss(cue.textSizeType, cue.textSize);
        String windowCssColor = HtmlUtils.toCssRgba(cue.windowColorSet ? cue.windowColor : style.windowColor);
        String positionProperty;
        String lineProperty;
        switch(cue.verticalType) {
            case Cue.VERTICAL_TYPE_LR:
                lineProperty = lineMeasuredFromEnd ? "right" : "left";
                positionProperty = "top";
                break;
            case Cue.VERTICAL_TYPE_RL:
                lineProperty = lineMeasuredFromEnd ? "left" : "right";
                positionProperty = "top";
                break;
            case Cue.TYPE_UNSET:
            default:
                lineProperty = lineMeasuredFromEnd ? "bottom" : "top";
                positionProperty = "left";
        }
        String sizeProperty;
        int horizontalTranslatePercent;
        int verticalTranslatePercent;
        if (cue.verticalType == Cue.VERTICAL_TYPE_LR || cue.verticalType == Cue.VERTICAL_TYPE_RL) {
            sizeProperty = "height";
            horizontalTranslatePercent = lineAnchorTranslatePercent;
            verticalTranslatePercent = positionAnchorTranslatePercent;
        } else {
            sizeProperty = "width";
            horizontalTranslatePercent = positionAnchorTranslatePercent;
            verticalTranslatePercent = lineAnchorTranslatePercent;
        }
        SpannedToHtmlConverter.HtmlAndCss htmlAndCss = SpannedToHtmlConverter.convert(cue.text, getContext().getResources().getDisplayMetrics().density);
        for (String cssSelector : cssRuleSets.keySet()) {
            @Nullable String previousCssDeclarationBlock = cssRuleSets.put(cssSelector, cssRuleSets.get(cssSelector));
            Assertions.checkState(previousCssDeclarationBlock == null || previousCssDeclarationBlock.equals(cssRuleSets.get(cssSelector)));
        }
        html.append(Util.formatInvariant("<div style='" + "position:absolute;" + "z-index:%s;" + "%s:%.2f%%;" + "%s:%s;" + "%s:%s;" + "text-align:%s;" + "writing-mode:%s;" + "font-size:%s;" + "background-color:%s;" + "transform:translate(%s%%,%s%%)" + "%s;" + "'>", /* z-index */
        i, positionProperty, positionPercent, lineProperty, lineValue, sizeProperty, size, textAlign, writingMode, cueTextSizeCssPx, windowCssColor, horizontalTranslatePercent, verticalTranslatePercent, getBlockShearTransformFunction(cue))).append(Util.formatInvariant("<span class='%s'>", DEFAULT_BACKGROUND_CSS_CLASS));
        if (cue.multiRowAlignment != null) {
            html.append(Util.formatInvariant("<span style='display:inline-block; text-align:%s;'>", convertAlignmentToCss(cue.multiRowAlignment))).append(htmlAndCss.html).append("</span>");
        } else {
            html.append(htmlAndCss.html);
        }
        html.append("</span>").append("</div>");
    }
    html.append("</div></body></html>");
    StringBuilder htmlHead = new StringBuilder();
    htmlHead.append("<html><head><style>");
    for (String cssSelector : cssRuleSets.keySet()) {
        htmlHead.append(cssSelector).append("{").append(cssRuleSets.get(cssSelector)).append("}");
    }
    htmlHead.append("</style></head>");
    html.insert(0, htmlHead.toString());
    webView.loadData(Base64.encodeToString(html.toString().getBytes(Charsets.UTF_8), Base64.NO_PADDING), "text/html", "base64");
}
Also used : Cue(com.google.android.exoplayer2.text.Cue) HashMap(java.util.HashMap) Nullable(androidx.annotation.Nullable)

Example 10 with Cue

use of com.google.android.exoplayer2.text.Cue in project ExoPlayer by google.

the class SubtitleViewUtilsTest method buildCue.

private static Cue buildCue() {
    SpannableString spanned = new SpannableString("TextEmphasis おはよ Ruby ございます 123 Underline RelativeSize AbsoluteSize");
    spanned.setSpan(new TextEmphasisSpan(TextEmphasisSpan.MARK_SHAPE_CIRCLE, TextEmphasisSpan.MARK_FILL_FILLED, TextAnnotation.POSITION_BEFORE), "Text emphasis ".length(), "Text emphasis おはよ".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    spanned.setSpan(new RubySpan("おはよ", TextAnnotation.POSITION_BEFORE), "TextEmphasis おはよ Ruby ".length(), "TextEmphasis おはよ Ruby ございます".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    spanned.setSpan(new HorizontalTextInVerticalContextSpan(), "TextEmphasis おはよ Ruby ございます ".length(), "TextEmphasis おはよ Ruby ございます 123".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    spanned.setSpan(new UnderlineSpan(), "TextEmphasis おはよ Ruby ございます 123 ".length(), "TextEmphasis おはよ Ruby ございます 123 Underline".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    spanned.setSpan(new RelativeSizeSpan(1f), "TextEmphasis おはよ Ruby ございます 123 Underline ".length(), "TextEmphasis おはよ Ruby ございます 123 Underline RelativeSize".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    spanned.setSpan(new AbsoluteSizeSpan(10), "TextEmphasis おはよ Ruby ございます 123 Underline RelativeSize ".length(), "TextEmphasis おはよ Ruby ございます 123 Underline RelativeSize AbsoluteSize".length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    return new Cue.Builder().setText(spanned).setTextAlignment(Layout.Alignment.ALIGN_CENTER).setMultiRowAlignment(Layout.Alignment.ALIGN_NORMAL).setLine(5, Cue.LINE_TYPE_NUMBER).setLineAnchor(Cue.ANCHOR_TYPE_END).setPosition(0.4f).setPositionAnchor(Cue.ANCHOR_TYPE_MIDDLE).setTextSize(0.2f, Cue.TEXT_SIZE_TYPE_FRACTIONAL).setSize(0.8f).setWindowColor(Color.CYAN).setVerticalType(Cue.VERTICAL_TYPE_RL).setShearDegrees(-15f).build();
}
Also used : SpannableString(android.text.SpannableString) RubySpan(com.google.android.exoplayer2.text.span.RubySpan) Cue(com.google.android.exoplayer2.text.Cue) HorizontalTextInVerticalContextSpan(com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan) TextEmphasisSpan(com.google.android.exoplayer2.text.span.TextEmphasisSpan) RelativeSizeSpan(android.text.style.RelativeSizeSpan) UnderlineSpan(android.text.style.UnderlineSpan) AbsoluteSizeSpan(android.text.style.AbsoluteSizeSpan)

Aggregations

Cue (com.google.android.exoplayer2.text.Cue)58 Test (org.junit.Test)40 Subtitle (com.google.android.exoplayer2.text.Subtitle)13 ArrayList (java.util.ArrayList)12 Nullable (androidx.annotation.Nullable)10 Spanned (android.text.Spanned)8 SpannableStringBuilder (android.text.SpannableStringBuilder)7 ParsableByteArray (com.google.android.exoplayer2.util.ParsableByteArray)5 FakeExtractorOutput (com.google.android.exoplayer2.testutil.FakeExtractorOutput)4 SpannableString (android.text.SpannableString)3 UnderlineSpan (android.text.style.UnderlineSpan)3 Format (com.google.android.exoplayer2.Format)3 AdPlaybackState (com.google.android.exoplayer2.source.ads.AdPlaybackState)3 FakeExtractorInput (com.google.android.exoplayer2.testutil.FakeExtractorInput)3 FakeTrackOutput (com.google.android.exoplayer2.testutil.FakeTrackOutput)3 HorizontalTextInVerticalContextSpan (com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan)3 RubySpan (com.google.android.exoplayer2.text.span.RubySpan)3 TextEmphasisSpan (com.google.android.exoplayer2.text.span.TextEmphasisSpan)3 WebvttDecoder (com.google.android.exoplayer2.text.webvtt.WebvttDecoder)3 Matcher (java.util.regex.Matcher)3