Search in sources :

Example 1 with Subtitle

use of androidx.media3.extractor.text.Subtitle in project media by androidx.

the class HlsMediaPeriod method buildAndPrepareSampleStreamWrappers.

// Internal methods.
private void buildAndPrepareSampleStreamWrappers(long positionUs) {
    HlsMultivariantPlaylist multivariantPlaylist = Assertions.checkNotNull(playlistTracker.getMultivariantPlaylist());
    Map<String, DrmInitData> overridingDrmInitData = useSessionKeys ? deriveOverridingDrmInitData(multivariantPlaylist.sessionKeyDrmInitData) : Collections.emptyMap();
    boolean hasVariants = !multivariantPlaylist.variants.isEmpty();
    List<Rendition> audioRenditions = multivariantPlaylist.audios;
    List<Rendition> subtitleRenditions = multivariantPlaylist.subtitles;
    pendingPrepareCount = 0;
    ArrayList<HlsSampleStreamWrapper> sampleStreamWrappers = new ArrayList<>();
    ArrayList<int[]> manifestUrlIndicesPerWrapper = new ArrayList<>();
    if (hasVariants) {
        buildAndPrepareMainSampleStreamWrapper(multivariantPlaylist, positionUs, sampleStreamWrappers, manifestUrlIndicesPerWrapper, overridingDrmInitData);
    }
    // TODO: Build video stream wrappers here.
    buildAndPrepareAudioSampleStreamWrappers(positionUs, audioRenditions, sampleStreamWrappers, manifestUrlIndicesPerWrapper, overridingDrmInitData);
    audioVideoSampleStreamWrapperCount = sampleStreamWrappers.size();
    // these.
    for (int i = 0; i < subtitleRenditions.size(); i++) {
        Rendition subtitleRendition = subtitleRenditions.get(i);
        String sampleStreamWrapperUid = "subtitle:" + i + ":" + subtitleRendition.name;
        HlsSampleStreamWrapper sampleStreamWrapper = buildSampleStreamWrapper(sampleStreamWrapperUid, C.TRACK_TYPE_TEXT, new Uri[] { subtitleRendition.url }, new Format[] { subtitleRendition.format }, null, Collections.emptyList(), overridingDrmInitData, positionUs);
        manifestUrlIndicesPerWrapper.add(new int[] { i });
        sampleStreamWrappers.add(sampleStreamWrapper);
        sampleStreamWrapper.prepareWithMultivariantPlaylistInfo(new TrackGroup[] { new TrackGroup(sampleStreamWrapperUid, subtitleRendition.format) }, /* primaryTrackGroupIndex= */
        0);
    }
    this.sampleStreamWrappers = sampleStreamWrappers.toArray(new HlsSampleStreamWrapper[0]);
    this.manifestUrlIndicesPerWrapper = manifestUrlIndicesPerWrapper.toArray(new int[0][]);
    pendingPrepareCount = this.sampleStreamWrappers.length;
    // Set timestamp master and trigger preparation (if not already prepared)
    this.sampleStreamWrappers[0].setIsTimestampMaster(true);
    for (HlsSampleStreamWrapper sampleStreamWrapper : this.sampleStreamWrappers) {
        sampleStreamWrapper.continuePreparing();
    }
    // All wrappers are enabled during preparation.
    enabledSampleStreamWrappers = this.sampleStreamWrappers;
}
Also used : Rendition(androidx.media3.exoplayer.hls.playlist.HlsMultivariantPlaylist.Rendition) ArrayList(java.util.ArrayList) DrmInitData(androidx.media3.common.DrmInitData) TrackGroup(androidx.media3.common.TrackGroup) HlsMultivariantPlaylist(androidx.media3.exoplayer.hls.playlist.HlsMultivariantPlaylist)

Example 2 with Subtitle

use of androidx.media3.extractor.text.Subtitle in project media by androidx.

the class Tx3gDecoder method decode.

@Override
protected Subtitle decode(byte[] bytes, int length, boolean reset) throws SubtitleDecoderException {
    parsableByteArray.reset(bytes, length);
    String cueTextString = readSubtitleText(parsableByteArray);
    if (cueTextString.isEmpty()) {
        return Tx3gSubtitle.EMPTY;
    }
    // Attach default styles.
    SpannableStringBuilder cueText = new SpannableStringBuilder(cueTextString);
    attachFontFace(cueText, defaultFontFace, DEFAULT_FONT_FACE, 0, cueText.length(), SPAN_PRIORITY_LOW);
    attachColor(cueText, defaultColorRgba, DEFAULT_COLOR, 0, cueText.length(), SPAN_PRIORITY_LOW);
    attachFontFamily(cueText, defaultFontFamily, 0, cueText.length());
    float verticalPlacement = defaultVerticalPlacement;
    // Find and attach additional styles.
    while (parsableByteArray.bytesLeft() >= SIZE_ATOM_HEADER) {
        int position = parsableByteArray.getPosition();
        int atomSize = parsableByteArray.readInt();
        int atomType = parsableByteArray.readInt();
        if (atomType == TYPE_STYL) {
            assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
            int styleRecordCount = parsableByteArray.readUnsignedShort();
            for (int i = 0; i < styleRecordCount; i++) {
                applyStyleRecord(parsableByteArray, cueText);
            }
        } else if (atomType == TYPE_TBOX && customVerticalPlacement) {
            assertTrue(parsableByteArray.bytesLeft() >= SIZE_SHORT);
            int requestedVerticalPlacement = parsableByteArray.readUnsignedShort();
            verticalPlacement = (float) requestedVerticalPlacement / calculatedVideoTrackHeight;
            verticalPlacement = Util.constrainValue(verticalPlacement, 0.0f, 0.95f);
        }
        parsableByteArray.setPosition(position + atomSize);
    }
    return new Tx3gSubtitle(new Cue.Builder().setText(cueText).setLine(verticalPlacement, LINE_TYPE_FRACTION).setLineAnchor(ANCHOR_TYPE_START).build());
}
Also used : Cue(androidx.media3.common.text.Cue) SpannableStringBuilder(android.text.SpannableStringBuilder)

Example 3 with Subtitle

use of androidx.media3.extractor.text.Subtitle in project media by androidx.

the class SubtitleExtractor method decode.

/**
 * Decodes the subtitle data and stores the samples in the memory of the extractor.
 */
private void decode() throws IOException {
    try {
        @Nullable SubtitleInputBuffer inputBuffer = subtitleDecoder.dequeueInputBuffer();
        while (inputBuffer == null) {
            Thread.sleep(5);
            inputBuffer = subtitleDecoder.dequeueInputBuffer();
        }
        inputBuffer.ensureSpaceForWrite(bytesRead);
        inputBuffer.data.put(subtitleData.getData(), /* offset= */
        0, bytesRead);
        inputBuffer.data.limit(bytesRead);
        subtitleDecoder.queueInputBuffer(inputBuffer);
        @Nullable SubtitleOutputBuffer outputBuffer = subtitleDecoder.dequeueOutputBuffer();
        while (outputBuffer == null) {
            Thread.sleep(5);
            outputBuffer = subtitleDecoder.dequeueOutputBuffer();
        }
        for (int i = 0; i < outputBuffer.getEventTimeCount(); i++) {
            List<Cue> cues = outputBuffer.getCues(outputBuffer.getEventTime(i));
            byte[] cuesSample = cueEncoder.encode(cues);
            timestamps.add(outputBuffer.getEventTime(i));
            samples.add(new ParsableByteArray(cuesSample));
        }
        outputBuffer.release();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new InterruptedIOException();
    } catch (SubtitleDecoderException e) {
        throw ParserException.createForMalformedContainer("SubtitleDecoder failed.", e);
    }
}
Also used : ParsableByteArray(androidx.media3.common.util.ParsableByteArray) InterruptedIOException(java.io.InterruptedIOException) Cue(androidx.media3.common.text.Cue) Nullable(androidx.annotation.Nullable)

Example 4 with Subtitle

use of androidx.media3.extractor.text.Subtitle in project media by androidx.

the class Cea608Decoder method dequeueOutputBuffer.

@Nullable
@Override
public SubtitleOutputBuffer dequeueOutputBuffer() throws SubtitleDecoderException {
    SubtitleOutputBuffer outputBuffer = super.dequeueOutputBuffer();
    if (outputBuffer != null) {
        return outputBuffer;
    }
    if (shouldClearStuckCaptions()) {
        outputBuffer = getAvailableOutputBuffer();
        if (outputBuffer != null) {
            cues = Collections.emptyList();
            lastCueUpdateUs = C.TIME_UNSET;
            Subtitle subtitle = createSubtitle();
            outputBuffer.setContent(getPositionUs(), subtitle, Format.OFFSET_SAMPLE_RELATIVE);
            return outputBuffer;
        }
    }
    return null;
}
Also used : Subtitle(androidx.media3.extractor.text.Subtitle) SubtitleOutputBuffer(androidx.media3.extractor.text.SubtitleOutputBuffer) Nullable(androidx.annotation.Nullable)

Example 5 with Subtitle

use of androidx.media3.extractor.text.Subtitle in project media by androidx.

the class SsaDecoder method decode.

@Override
protected Subtitle decode(byte[] bytes, int length, boolean reset) {
    List<List<Cue>> cues = new ArrayList<>();
    List<Long> cueTimesUs = new ArrayList<>();
    ParsableByteArray data = new ParsableByteArray(bytes, length);
    if (!haveInitializationData) {
        parseHeader(data);
    }
    parseEventBody(data, cues, cueTimesUs);
    return new SsaSubtitle(cues, cueTimesUs);
}
Also used : ParsableByteArray(androidx.media3.common.util.ParsableByteArray) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Test (org.junit.Test)68 Subtitle (androidx.media3.extractor.text.Subtitle)42 Cue (androidx.media3.common.text.Cue)38 SpannedString (android.text.SpannedString)12 Spanned (android.text.Spanned)9 Nullable (androidx.annotation.Nullable)8 ArrayList (java.util.ArrayList)8 Format (androidx.media3.common.Format)5 SubtitleOutputBuffer (androidx.media3.extractor.text.SubtitleOutputBuffer)4 ParsableByteArray (androidx.media3.common.util.ParsableByteArray)3 SubtitleDecoderException (androidx.media3.extractor.text.SubtitleDecoderException)3 WebvttDecoder (androidx.media3.extractor.text.webvtt.WebvttDecoder)3 FakeExtractorInput (androidx.media3.test.utils.FakeExtractorInput)3 FakeExtractorOutput (androidx.media3.test.utils.FakeExtractorOutput)3 FakeTrackOutput (androidx.media3.test.utils.FakeTrackOutput)3 Context (android.content.Context)2 SurfaceTexture (android.graphics.SurfaceTexture)2 Bundle (android.os.Bundle)2 Surface (android.view.Surface)2 TrackGroup (androidx.media3.common.TrackGroup)2