mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Merge branch 'dev-v2-dvbsubs' of git://github.com/tresvecesseis/ExoPlayer into tresvecesseis-dev-v2-dvbsubs
This commit is contained in:
commit
538e71c090
@ -5,3 +5,6 @@
|
||||
-keepclassmembers class com.google.android.exoplayer2.text.cea.Cea708Decoder {
|
||||
public <init>(int);
|
||||
}
|
||||
-keepclassmembers class com.google.android.exoplayer2.text.dvb.DvbDecoder {
|
||||
public <init>(java.util.List);
|
||||
}
|
@ -99,6 +99,7 @@ public final class MatroskaExtractor implements Extractor {
|
||||
private static final String CODEC_ID_SUBRIP = "S_TEXT/UTF8";
|
||||
private static final String CODEC_ID_VOBSUB = "S_VOBSUB";
|
||||
private static final String CODEC_ID_PGS = "S_HDMV/PGS";
|
||||
private static final String CODEC_ID_DVBSUB = "S_DVBSUB";
|
||||
|
||||
private static final int VORBIS_MAX_INPUT_SIZE = 8192;
|
||||
private static final int OPUS_MAX_INPUT_SIZE = 5760;
|
||||
@ -1233,7 +1234,8 @@ public final class MatroskaExtractor implements Extractor {
|
||||
|| CODEC_ID_PCM_INT_LIT.equals(codecId)
|
||||
|| CODEC_ID_SUBRIP.equals(codecId)
|
||||
|| CODEC_ID_VOBSUB.equals(codecId)
|
||||
|| CODEC_ID_PGS.equals(codecId);
|
||||
|| CODEC_ID_PGS.equals(codecId)
|
||||
|| CODEC_ID_DVBSUB.equals(codecId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1461,6 +1463,11 @@ public final class MatroskaExtractor implements Extractor {
|
||||
case CODEC_ID_PGS:
|
||||
mimeType = MimeTypes.APPLICATION_PGS;
|
||||
break;
|
||||
case CODEC_ID_DVBSUB:
|
||||
mimeType = MimeTypes.APPLICATION_DVBSUBS;
|
||||
initializationData = Collections.singletonList(new byte[] {
|
||||
(byte) 0x01, codecPrivate[0], codecPrivate[1], codecPrivate[2], codecPrivate[3]});
|
||||
break;
|
||||
default:
|
||||
throw new ParserException("Unrecognized codec identifier.");
|
||||
}
|
||||
@ -1495,7 +1502,8 @@ public final class MatroskaExtractor implements Extractor {
|
||||
format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null,
|
||||
Format.NO_VALUE, selectionFlags, language, drmInitData);
|
||||
} else if (MimeTypes.APPLICATION_VOBSUB.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_PGS.equals(mimeType)) {
|
||||
|| MimeTypes.APPLICATION_PGS.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_DVBSUBS.equals(mimeType)) {
|
||||
type = C.TRACK_TYPE_TEXT;
|
||||
format = Format.createImageSampleFormat(Integer.toString(trackId), mimeType, null,
|
||||
Format.NO_VALUE, initializationData, language, drmInitData);
|
||||
|
@ -109,6 +109,8 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
|
||||
? null : new SectionReader(new SpliceInfoSectionReader());
|
||||
case TsExtractor.TS_STREAM_TYPE_ID3:
|
||||
return new PesReader(new Id3Reader());
|
||||
case TsExtractor.TS_STREAM_TYPE_DVBSUBS:
|
||||
return new PesReader(new DvbSubtitlesReader(esInfo));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.extractor.ts;
|
||||
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorOutput;
|
||||
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||
import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Output PES packets to a {@link TrackOutput}.
|
||||
*/
|
||||
public final class DvbSubtitlesReader implements ElementaryStreamReader {
|
||||
|
||||
private class SubtitleTrack {
|
||||
private String language;
|
||||
private List<byte[]> initializationData;
|
||||
}
|
||||
|
||||
private List<SubtitleTrack> subtitles = new ArrayList<>();
|
||||
|
||||
private long sampleTimeUs;
|
||||
private int sampleBytesWritten;
|
||||
private boolean writingSample;
|
||||
|
||||
private List<TrackOutput> outputTracks = new ArrayList<>();
|
||||
|
||||
public DvbSubtitlesReader(TsPayloadReader.EsInfo esInfo) {
|
||||
int pos = 2;
|
||||
|
||||
while (pos < esInfo.descriptorBytes.length) {
|
||||
SubtitleTrack subtitle = new SubtitleTrack();
|
||||
subtitle.language = new String(new byte[] {
|
||||
esInfo.descriptorBytes[pos],
|
||||
esInfo.descriptorBytes[pos + 1],
|
||||
esInfo.descriptorBytes[pos + 2]});
|
||||
|
||||
if (((esInfo.descriptorBytes[pos + 3] & 0xF0 ) >> 4 ) == 2 ) {
|
||||
subtitle.language += " for hard of hearing";
|
||||
}
|
||||
|
||||
subtitle.initializationData = Collections.singletonList(new byte[] {(byte) 0x00,
|
||||
esInfo.descriptorBytes[pos + 4], esInfo.descriptorBytes[pos + 5],
|
||||
esInfo.descriptorBytes[pos + 6], esInfo.descriptorBytes[pos + 7]});
|
||||
|
||||
subtitles.add(subtitle);
|
||||
pos += 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void seek() {
|
||||
writingSample = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) {
|
||||
TrackOutput output;
|
||||
SubtitleTrack subtitle;
|
||||
|
||||
for (int i = 0; i < subtitles.size(); i++) {
|
||||
subtitle = subtitles.get(i);
|
||||
idGenerator.generateNewId();
|
||||
output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_TEXT);
|
||||
output.format(Format.createImageSampleFormat(idGenerator.getFormatId(),
|
||||
MimeTypes.APPLICATION_DVBSUBS, null, Format.NO_VALUE,
|
||||
subtitle.initializationData, subtitle.language, null));
|
||||
outputTracks.add(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void packetStarted(long pesTimeUs, boolean dataAlignmentIndicator) {
|
||||
if (!dataAlignmentIndicator) {
|
||||
return;
|
||||
}
|
||||
writingSample = true;
|
||||
sampleTimeUs = pesTimeUs;
|
||||
sampleBytesWritten = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetFinished() {
|
||||
TrackOutput output;
|
||||
|
||||
for (int i = 0; i < outputTracks.size(); i++) {
|
||||
output = outputTracks.get(i);
|
||||
output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytesWritten, 0, null);
|
||||
}
|
||||
writingSample = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume(ParsableByteArray data) {
|
||||
if (writingSample) {
|
||||
int bytesAvailable = data.bytesLeft();
|
||||
TrackOutput output;
|
||||
int dataPosition = data.getPosition();
|
||||
|
||||
for (int i = 0; i < outputTracks.size(); i++) {
|
||||
data.setPosition(dataPosition);
|
||||
output = outputTracks.get(i);
|
||||
output.sampleData(data, bytesAvailable);
|
||||
}
|
||||
|
||||
sampleBytesWritten += bytesAvailable;
|
||||
}
|
||||
}
|
||||
}
|
@ -92,6 +92,7 @@ public final class TsExtractor implements Extractor {
|
||||
public static final int TS_STREAM_TYPE_H265 = 0x24;
|
||||
public static final int TS_STREAM_TYPE_ID3 = 0x15;
|
||||
public static final int TS_STREAM_TYPE_SPLICE_INFO = 0x86;
|
||||
public static final int TS_STREAM_TYPE_DVBSUBS = 0x59;
|
||||
|
||||
private static final int TS_PACKET_SIZE = 188;
|
||||
private static final int TS_SYNC_BYTE = 0x47; // First byte of each TS packet.
|
||||
@ -356,6 +357,7 @@ public final class TsExtractor implements Extractor {
|
||||
private static final int TS_PMT_DESC_AC3 = 0x6A;
|
||||
private static final int TS_PMT_DESC_EAC3 = 0x7A;
|
||||
private static final int TS_PMT_DESC_DTS = 0x7B;
|
||||
private static final int TS_PMT_DESC_DVBSUBS = 0x59;
|
||||
|
||||
private final ParsableBitArray pmtScratch;
|
||||
private final int pid;
|
||||
@ -498,6 +500,9 @@ public final class TsExtractor implements Extractor {
|
||||
} else if (descriptorTag == TS_PMT_DESC_ISO639_LANG) {
|
||||
language = new String(data.data, data.getPosition(), 3).trim();
|
||||
// Audio type is ignored.
|
||||
} else if (descriptorTag == TS_PMT_DESC_DVBSUBS) {
|
||||
streamType = TS_STREAM_TYPE_DVBSUBS;
|
||||
language = new String(data.data, data.getPosition(), 3).trim();
|
||||
}
|
||||
// Skip unused bytes of current descriptor.
|
||||
data.skipBytes(positionOfNextDescriptor - data.getPosition());
|
||||
|
@ -167,6 +167,12 @@ public class Cue {
|
||||
*/
|
||||
public final float size;
|
||||
|
||||
/**
|
||||
* The bitmap height as a fraction of the of the viewport size, or -1 if the bitmap should be
|
||||
* displayed at its natural height given for its specified {@link #size}.
|
||||
*/
|
||||
public final float bitmapHeight;
|
||||
|
||||
/**
|
||||
* Specifies whether or not the {@link #windowColor} property is set.
|
||||
*/
|
||||
@ -190,11 +196,13 @@ public class Cue {
|
||||
* @param verticalPositionAnchor The vertical anchor. One of {@link #ANCHOR_TYPE_START},
|
||||
* {@link #ANCHOR_TYPE_MIDDLE}, {@link #ANCHOR_TYPE_END} and {@link #TYPE_UNSET}.
|
||||
* @param width The width of the cue, expressed as a fraction of the viewport width.
|
||||
* @param height The width of the cue, expressed as a fraction of the viewport width.
|
||||
*/
|
||||
public Cue(Bitmap bitmap, float horizontalPosition, @AnchorType int horizontalPositionAnchor,
|
||||
float verticalPosition, @AnchorType int verticalPositionAnchor, float width) {
|
||||
float verticalPosition, @AnchorType int verticalPositionAnchor, float width, float
|
||||
height) {
|
||||
this(null, null, bitmap, verticalPosition, LINE_TYPE_FRACTION, verticalPositionAnchor,
|
||||
horizontalPosition, horizontalPositionAnchor, width, false, Color.BLACK);
|
||||
horizontalPosition, horizontalPositionAnchor, width, height, false, Color.BLACK);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,15 +248,16 @@ public class Cue {
|
||||
* @param windowColor See {@link #windowColor}.
|
||||
*/
|
||||
public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType,
|
||||
@AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size,
|
||||
boolean windowColorSet, int windowColor) {
|
||||
@AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size,
|
||||
boolean windowColorSet, int windowColor) {
|
||||
this(text, textAlignment, null, line, lineType, lineAnchor, position, positionAnchor, size,
|
||||
windowColorSet, windowColor);
|
||||
-1, windowColorSet, windowColor);
|
||||
}
|
||||
|
||||
private Cue(CharSequence text, Alignment textAlignment, Bitmap bitmap, float line,
|
||||
@LineType int lineType, @AnchorType int lineAnchor, float position,
|
||||
@AnchorType int positionAnchor, float size, boolean windowColorSet, int windowColor) {
|
||||
@AnchorType int positionAnchor, float size, float bitmapHeight, boolean windowColorSet,
|
||||
int windowColor) {
|
||||
this.text = text;
|
||||
this.textAlignment = textAlignment;
|
||||
this.bitmap = bitmap;
|
||||
@ -258,6 +267,7 @@ public class Cue {
|
||||
this.position = position;
|
||||
this.positionAnchor = positionAnchor;
|
||||
this.size = size;
|
||||
this.bitmapHeight = bitmapHeight;
|
||||
this.windowColorSet = windowColorSet;
|
||||
this.windowColor = windowColor;
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import com.google.android.exoplayer2.text.webvtt.Mp4WebvttDecoder;
|
||||
import com.google.android.exoplayer2.text.webvtt.WebvttDecoder;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A factory for {@link SubtitleDecoder} instances.
|
||||
*/
|
||||
@ -83,6 +85,8 @@ public interface SubtitleDecoderFactory {
|
||||
} else if (format.sampleMimeType.equals(MimeTypes.APPLICATION_CEA708)) {
|
||||
return clazz.asSubclass(SubtitleDecoder.class).getConstructor(Integer.TYPE)
|
||||
.newInstance(format.accessibilityChannel);
|
||||
} else if (format.sampleMimeType.equals(MimeTypes.APPLICATION_DVBSUBS)) {
|
||||
return clazz.asSubclass(SubtitleDecoder.class).getConstructor(List.class).newInstance(format.initializationData);
|
||||
} else {
|
||||
return clazz.asSubclass(SubtitleDecoder.class).getConstructor().newInstance();
|
||||
}
|
||||
@ -112,6 +116,8 @@ public interface SubtitleDecoderFactory {
|
||||
return Class.forName("com.google.android.exoplayer2.text.cea.Cea608Decoder");
|
||||
case MimeTypes.APPLICATION_CEA708:
|
||||
return Class.forName("com.google.android.exoplayer2.text.cea.Cea708Decoder");
|
||||
case MimeTypes.APPLICATION_DVBSUBS:
|
||||
return Class.forName("com.google.android.exoplayer2.text.dvb.DvbDecoder");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.text.dvb;
|
||||
|
||||
import com.google.android.exoplayer2.text.SimpleSubtitleDecoder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link SimpleSubtitleDecoder} for DVB Subtitles.
|
||||
*/
|
||||
public final class DvbDecoder extends SimpleSubtitleDecoder {
|
||||
|
||||
private final DvbParser parser;
|
||||
|
||||
public DvbDecoder(List<byte[]> initializationData) {
|
||||
super("DvbDecoder");
|
||||
|
||||
int subtitleCompositionPage = 1;
|
||||
int subtitleAncillaryPage = 1;
|
||||
int flags = 0;
|
||||
byte[] tempByteArray;
|
||||
|
||||
if ((tempByteArray = initializationData.get(0)) != null && tempByteArray.length == 5) {
|
||||
if (tempByteArray[0] == 0x01) {
|
||||
flags |= DvbParser.FLAG_PES_STRIPPED_DVBSUB;
|
||||
}
|
||||
subtitleCompositionPage = ((tempByteArray[1] & 0xFF) << 8) | (tempByteArray[2] & 0xFF);
|
||||
subtitleAncillaryPage = ((tempByteArray[3] & 0xFF) << 8) | (tempByteArray[4] & 0xFF);
|
||||
}
|
||||
|
||||
parser = new DvbParser(subtitleCompositionPage, subtitleAncillaryPage, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DvbSubtitle decode(byte[] data, int length) {
|
||||
return new DvbSubtitle(parser.dvbSubsDecode(data, length));
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.text.dvb;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.text.Cue;
|
||||
import com.google.android.exoplayer2.text.Subtitle;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A representation of a DVB subtitle.
|
||||
*/
|
||||
/* package */ final class DvbSubtitle implements Subtitle {
|
||||
private final List<Cue> cues;
|
||||
|
||||
public DvbSubtitle(List<Cue> cues) {
|
||||
if (cues == null) {
|
||||
this.cues = Collections.emptyList();
|
||||
} else {
|
||||
this.cues = cues;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNextEventTimeIndex(long timeUs) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEventTimeCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEventTime(int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cue> getCues(long timeUs) {
|
||||
return cues;
|
||||
}
|
||||
}
|
@ -81,6 +81,7 @@ public final class MimeTypes {
|
||||
public static final String APPLICATION_SCTE35 = BASE_TYPE_APPLICATION + "/x-scte35";
|
||||
public static final String APPLICATION_CAMERA_MOTION = BASE_TYPE_APPLICATION + "/x-camera-motion";
|
||||
public static final String APPLICATION_EMSG = BASE_TYPE_APPLICATION + "/x-emsg";
|
||||
public static final String APPLICATION_DVBSUBS = BASE_TYPE_APPLICATION + "/dvbsubs";
|
||||
|
||||
private MimeTypes() {}
|
||||
|
||||
@ -222,7 +223,7 @@ public final class MimeTypes {
|
||||
|| APPLICATION_SUBRIP.equals(mimeType) || APPLICATION_TTML.equals(mimeType)
|
||||
|| APPLICATION_TX3G.equals(mimeType) || APPLICATION_MP4VTT.equals(mimeType)
|
||||
|| APPLICATION_RAWCC.equals(mimeType) || APPLICATION_VOBSUB.equals(mimeType)
|
||||
|| APPLICATION_PGS.equals(mimeType)) {
|
||||
|| APPLICATION_PGS.equals(mimeType) || APPLICATION_DVBSUBS.equals(mimeType)) {
|
||||
return C.TRACK_TYPE_TEXT;
|
||||
} else if (APPLICATION_ID3.equals(mimeType)
|
||||
|| APPLICATION_EMSG.equals(mimeType)
|
||||
|
@ -77,6 +77,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
@Cue.AnchorType
|
||||
private int cuePositionAnchor;
|
||||
private float cueSize;
|
||||
private float cueBitmapHeight;
|
||||
private boolean applyEmbeddedStyles;
|
||||
private int foregroundColor;
|
||||
private int backgroundColor;
|
||||
@ -173,6 +174,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
&& this.cuePosition == cue.position
|
||||
&& Util.areEqual(this.cuePositionAnchor, cue.positionAnchor)
|
||||
&& this.cueSize == cue.size
|
||||
&& this.cueBitmapHeight == cue.bitmapHeight
|
||||
&& this.applyEmbeddedStyles == applyEmbeddedStyles
|
||||
&& this.foregroundColor == style.foregroundColor
|
||||
&& this.backgroundColor == style.backgroundColor
|
||||
@ -200,6 +202,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
this.cuePosition = cue.position;
|
||||
this.cuePositionAnchor = cue.positionAnchor;
|
||||
this.cueSize = cue.size;
|
||||
this.cueBitmapHeight = cue.bitmapHeight;
|
||||
this.applyEmbeddedStyles = applyEmbeddedStyles;
|
||||
this.foregroundColor = style.foregroundColor;
|
||||
this.backgroundColor = style.backgroundColor;
|
||||
@ -312,7 +315,8 @@ import com.google.android.exoplayer2.util.Util;
|
||||
float anchorX = parentLeft + (parentWidth * cuePosition);
|
||||
float anchorY = parentTop + (parentHeight * cueLine);
|
||||
int width = Math.round(parentWidth * cueSize);
|
||||
int height = Math.round(width * ((float) cueBitmap.getHeight() / cueBitmap.getWidth()));
|
||||
int height = cueBitmapHeight != -1 ? Math.round(parentHeight * cueBitmapHeight)
|
||||
: Math.round(width * ((float) cueBitmap.getHeight() / cueBitmap.getWidth()));
|
||||
int x = Math.round(cueLineAnchor == Cue.ANCHOR_TYPE_END ? (anchorX - width)
|
||||
: cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorX - (width / 2)) : anchorX);
|
||||
int y = Math.round(cuePositionAnchor == Cue.ANCHOR_TYPE_END ? (anchorY - height)
|
||||
|
Loading…
x
Reference in New Issue
Block a user