Search in sources :

Example 21 with Cue

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

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(com.google.android.exoplayer2.util.ParsableByteArray) InterruptedIOException(java.io.InterruptedIOException) Nullable(androidx.annotation.Nullable)

Example 22 with Cue

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

the class DvbParser method decode.

/**
 * Decodes a subtitling packet, returning a list of parsed {@link Cue}s.
 *
 * @param data The subtitling packet data to decode.
 * @param limit The limit in {@code data} at which to stop decoding.
 * @return The parsed {@link Cue}s.
 */
public List<Cue> decode(byte[] data, int limit) {
    // Parse the input data.
    ParsableBitArray dataBitArray = new ParsableBitArray(data, limit);
    while (// sync_byte (8) + segment header (40)
    dataBitArray.bitsLeft() >= 48 && dataBitArray.readBits(8) == 0x0F) {
        parseSubtitlingSegment(dataBitArray, subtitleService);
    }
    @Nullable PageComposition pageComposition = subtitleService.pageComposition;
    if (pageComposition == null) {
        return Collections.emptyList();
    }
    // Update the canvas bitmap if necessary.
    DisplayDefinition displayDefinition = subtitleService.displayDefinition != null ? subtitleService.displayDefinition : defaultDisplayDefinition;
    if (bitmap == null || displayDefinition.width + 1 != bitmap.getWidth() || displayDefinition.height + 1 != bitmap.getHeight()) {
        bitmap = Bitmap.createBitmap(displayDefinition.width + 1, displayDefinition.height + 1, Bitmap.Config.ARGB_8888);
        canvas.setBitmap(bitmap);
    }
    // Build the cues.
    List<Cue> cues = new ArrayList<>();
    SparseArray<PageRegion> pageRegions = pageComposition.regions;
    for (int i = 0; i < pageRegions.size(); i++) {
        // Save clean clipping state.
        canvas.save();
        PageRegion pageRegion = pageRegions.valueAt(i);
        int regionId = pageRegions.keyAt(i);
        RegionComposition regionComposition = subtitleService.regions.get(regionId);
        // Clip drawing to the current region and display definition window.
        int baseHorizontalAddress = pageRegion.horizontalAddress + displayDefinition.horizontalPositionMinimum;
        int baseVerticalAddress = pageRegion.verticalAddress + displayDefinition.verticalPositionMinimum;
        int clipRight = min(baseHorizontalAddress + regionComposition.width, displayDefinition.horizontalPositionMaximum);
        int clipBottom = min(baseVerticalAddress + regionComposition.height, displayDefinition.verticalPositionMaximum);
        canvas.clipRect(baseHorizontalAddress, baseVerticalAddress, clipRight, clipBottom);
        ClutDefinition clutDefinition = subtitleService.cluts.get(regionComposition.clutId);
        if (clutDefinition == null) {
            clutDefinition = subtitleService.ancillaryCluts.get(regionComposition.clutId);
            if (clutDefinition == null) {
                clutDefinition = defaultClutDefinition;
            }
        }
        SparseArray<RegionObject> regionObjects = regionComposition.regionObjects;
        for (int j = 0; j < regionObjects.size(); j++) {
            int objectId = regionObjects.keyAt(j);
            RegionObject regionObject = regionObjects.valueAt(j);
            ObjectData objectData = subtitleService.objects.get(objectId);
            if (objectData == null) {
                objectData = subtitleService.ancillaryObjects.get(objectId);
            }
            if (objectData != null) {
                @Nullable Paint paint = objectData.nonModifyingColorFlag ? null : defaultPaint;
                paintPixelDataSubBlocks(objectData, clutDefinition, regionComposition.depth, baseHorizontalAddress + regionObject.horizontalPosition, baseVerticalAddress + regionObject.verticalPosition, paint, canvas);
            }
        }
        if (regionComposition.fillFlag) {
            int color;
            if (regionComposition.depth == REGION_DEPTH_8_BIT) {
                color = clutDefinition.clutEntries8Bit[regionComposition.pixelCode8Bit];
            } else if (regionComposition.depth == REGION_DEPTH_4_BIT) {
                color = clutDefinition.clutEntries4Bit[regionComposition.pixelCode4Bit];
            } else {
                color = clutDefinition.clutEntries2Bit[regionComposition.pixelCode2Bit];
            }
            fillRegionPaint.setColor(color);
            canvas.drawRect(baseHorizontalAddress, baseVerticalAddress, baseHorizontalAddress + regionComposition.width, baseVerticalAddress + regionComposition.height, fillRegionPaint);
        }
        cues.add(new Cue.Builder().setBitmap(Bitmap.createBitmap(bitmap, baseHorizontalAddress, baseVerticalAddress, regionComposition.width, regionComposition.height)).setPosition((float) baseHorizontalAddress / displayDefinition.width).setPositionAnchor(Cue.ANCHOR_TYPE_START).setLine((float) baseVerticalAddress / displayDefinition.height, Cue.LINE_TYPE_FRACTION).setLineAnchor(Cue.ANCHOR_TYPE_START).setSize((float) regionComposition.width / displayDefinition.width).setBitmapHeight((float) regionComposition.height / displayDefinition.height).build());
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        // Restore clean clipping state.
        canvas.restore();
    }
    return Collections.unmodifiableList(cues);
}
Also used : ArrayList(java.util.ArrayList) Paint(android.graphics.Paint) Paint(android.graphics.Paint) Cue(com.google.android.exoplayer2.text.Cue) Nullable(androidx.annotation.Nullable) ParsableBitArray(com.google.android.exoplayer2.util.ParsableBitArray)

Example 23 with Cue

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

the class SsaDecoder method parseDialogueLine.

/**
 * Parses a dialogue line.
 *
 * @param dialogueLine The dialogue values (i.e. everything after {@code Dialogue:}).
 * @param format The dialogue format to use when parsing {@code dialogueLine}.
 * @param cues A list to which parsed cues will be added.
 * @param cueTimesUs A sorted list to which parsed cue timestamps will be added.
 */
private void parseDialogueLine(String dialogueLine, SsaDialogueFormat format, List<List<Cue>> cues, List<Long> cueTimesUs) {
    Assertions.checkArgument(dialogueLine.startsWith(DIALOGUE_LINE_PREFIX));
    String[] lineValues = dialogueLine.substring(DIALOGUE_LINE_PREFIX.length()).split(",", format.length);
    if (lineValues.length != format.length) {
        Log.w(TAG, "Skipping dialogue line with fewer columns than format: " + dialogueLine);
        return;
    }
    long startTimeUs = parseTimecodeUs(lineValues[format.startTimeIndex]);
    if (startTimeUs == C.TIME_UNSET) {
        Log.w(TAG, "Skipping invalid timing: " + dialogueLine);
        return;
    }
    long endTimeUs = parseTimecodeUs(lineValues[format.endTimeIndex]);
    if (endTimeUs == C.TIME_UNSET) {
        Log.w(TAG, "Skipping invalid timing: " + dialogueLine);
        return;
    }
    @Nullable SsaStyle style = styles != null && format.styleIndex != C.INDEX_UNSET ? styles.get(lineValues[format.styleIndex].trim()) : null;
    String rawText = lineValues[format.textIndex];
    SsaStyle.Overrides styleOverrides = SsaStyle.Overrides.parseFromDialogue(rawText);
    String text = SsaStyle.Overrides.stripStyleOverrides(rawText).replace("\\N", "\n").replace("\\n", "\n").replace("\\h", "\u00A0");
    Cue cue = createCue(text, style, styleOverrides, screenWidth, screenHeight);
    int startTimeIndex = addCuePlacerholderByTime(startTimeUs, cueTimesUs, cues);
    int endTimeIndex = addCuePlacerholderByTime(endTimeUs, cueTimesUs, cues);
    // Iterate on cues from startTimeIndex until endTimeIndex, adding the current cue.
    for (int i = startTimeIndex; i < endTimeIndex; i++) {
        cues.get(i).add(cue);
    }
}
Also used : Cue(com.google.android.exoplayer2.text.Cue) SpannableString(android.text.SpannableString) Nullable(androidx.annotation.Nullable)

Example 24 with Cue

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

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(com.google.android.exoplayer2.util.ParsableByteArray) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Example 25 with Cue

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

the class PgsDecoder method readNextSection.

@Nullable
private static Cue readNextSection(ParsableByteArray buffer, CueBuilder cueBuilder) {
    int limit = buffer.limit();
    int sectionType = buffer.readUnsignedByte();
    int sectionLength = buffer.readUnsignedShort();
    int nextSectionPosition = buffer.getPosition() + sectionLength;
    if (nextSectionPosition > limit) {
        buffer.setPosition(limit);
        return null;
    }
    Cue cue = null;
    switch(sectionType) {
        case SECTION_TYPE_PALETTE:
            cueBuilder.parsePaletteSection(buffer, sectionLength);
            break;
        case SECTION_TYPE_BITMAP_PICTURE:
            cueBuilder.parseBitmapSection(buffer, sectionLength);
            break;
        case SECTION_TYPE_IDENTIFIER:
            cueBuilder.parseIdentifierSection(buffer, sectionLength);
            break;
        case SECTION_TYPE_END:
            cue = cueBuilder.build();
            cueBuilder.reset();
            break;
        default:
            break;
    }
    buffer.setPosition(nextSectionPosition);
    return cue;
}
Also used : Cue(com.google.android.exoplayer2.text.Cue) Nullable(androidx.annotation.Nullable)

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