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;
}
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());
}
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);
}
}
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;
}
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);
}
Aggregations