mirror of
https://github.com/samsonjs/media.git
synced 2026-04-09 11:55:46 +00:00
Refactored Eia608Parser so that it manipulates the caption string builder directly, avoiding unnecessary object allocation.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=120926283
This commit is contained in:
parent
ab3489efc1
commit
3d14c7242d
5 changed files with 140 additions and 294 deletions
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.text.eia608;
|
||||
|
||||
/**
|
||||
* A Closed Caption that contains textual data associated with time indices.
|
||||
*/
|
||||
/* package */ abstract class ClosedCaption {
|
||||
|
||||
/**
|
||||
* Identifies closed captions with control characters.
|
||||
*/
|
||||
public static final int TYPE_CTRL = 0;
|
||||
/**
|
||||
* Identifies closed captions with textual information.
|
||||
*/
|
||||
public static final int TYPE_TEXT = 1;
|
||||
|
||||
/**
|
||||
* The type of the closed caption data.
|
||||
*/
|
||||
public final int type;
|
||||
|
||||
protected ClosedCaption(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.text.eia608;
|
||||
|
||||
/* package */ final class ClosedCaptionCtrl extends ClosedCaption {
|
||||
|
||||
/**
|
||||
* Command initiating pop-on style captioning. Subsequent data should be loaded into a
|
||||
* non-displayed memory and held there until the {@link #END_OF_CAPTION} command is received, at
|
||||
* which point the non-displayed memory becomes the displayed memory (and vice versa).
|
||||
*/
|
||||
public static final byte RESUME_CAPTION_LOADING = 0x20;
|
||||
/**
|
||||
* Command initiating roll-up style captioning, with the maximum of 2 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
public static final byte ROLL_UP_CAPTIONS_2_ROWS = 0x25;
|
||||
/**
|
||||
* Command initiating roll-up style captioning, with the maximum of 3 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
public static final byte ROLL_UP_CAPTIONS_3_ROWS = 0x26;
|
||||
/**
|
||||
* Command initiating roll-up style captioning, with the maximum of 4 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
public static final byte ROLL_UP_CAPTIONS_4_ROWS = 0x27;
|
||||
/**
|
||||
* Command initiating paint-on style captioning. Subsequent data should be addressed immediately
|
||||
* to displayed memory without need for the {@link #RESUME_CAPTION_LOADING} command.
|
||||
*/
|
||||
public static final byte RESUME_DIRECT_CAPTIONING = 0x29;
|
||||
/**
|
||||
* Command indicating the end of a pop-on style caption. At this point the caption loaded in
|
||||
* non-displayed memory should be swapped with the one in displayed memory. If no
|
||||
* {@link #RESUME_CAPTION_LOADING} command has been received, this command forces the receiver
|
||||
* into pop-on style.
|
||||
*/
|
||||
public static final byte END_OF_CAPTION = 0x2F;
|
||||
|
||||
public static final byte ERASE_DISPLAYED_MEMORY = 0x2C;
|
||||
public static final byte CARRIAGE_RETURN = 0x2D;
|
||||
public static final byte ERASE_NON_DISPLAYED_MEMORY = 0x2E;
|
||||
|
||||
public static final byte BACKSPACE = 0x21;
|
||||
|
||||
|
||||
public static final byte MID_ROW_CHAN_1 = 0x11;
|
||||
public static final byte MID_ROW_CHAN_2 = 0x19;
|
||||
|
||||
public static final byte MISC_CHAN_1 = 0x14;
|
||||
public static final byte MISC_CHAN_2 = 0x1C;
|
||||
|
||||
public static final byte TAB_OFFSET_CHAN_1 = 0x17;
|
||||
public static final byte TAB_OFFSET_CHAN_2 = 0x1F;
|
||||
|
||||
public final byte cc1;
|
||||
public final byte cc2;
|
||||
|
||||
protected ClosedCaptionCtrl(byte cc1, byte cc2) {
|
||||
super(ClosedCaption.TYPE_CTRL);
|
||||
this.cc1 = cc1;
|
||||
this.cc2 = cc2;
|
||||
}
|
||||
|
||||
public boolean isMidRowCode() {
|
||||
return (cc1 == MID_ROW_CHAN_1 || cc1 == MID_ROW_CHAN_2) && (cc2 >= 0x20 && cc2 <= 0x2F);
|
||||
}
|
||||
|
||||
public boolean isMiscCode() {
|
||||
return (cc1 == MISC_CHAN_1 || cc1 == MISC_CHAN_2) && (cc2 >= 0x20 && cc2 <= 0x2F);
|
||||
}
|
||||
|
||||
public boolean isTabOffsetCode() {
|
||||
return (cc1 == TAB_OFFSET_CHAN_1 || cc1 == TAB_OFFSET_CHAN_2) && (cc2 >= 0x21 && cc2 <= 0x23);
|
||||
}
|
||||
|
||||
public boolean isPreambleAddressCode() {
|
||||
return (cc1 >= 0x10 && cc1 <= 0x1F) && (cc2 >= 0x40 && cc2 <= 0x7F);
|
||||
}
|
||||
|
||||
public boolean isRepeatable() {
|
||||
return cc1 >= 0x10 && cc1 <= 0x1F;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.text.eia608;
|
||||
|
||||
/* package */ final class ClosedCaptionList {
|
||||
|
||||
public final long timeUs;
|
||||
public final ClosedCaption[] captions;
|
||||
|
||||
public ClosedCaptionList(long timeUs, ClosedCaption[] captions) {
|
||||
this.timeUs = timeUs;
|
||||
this.captions = captions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.text.eia608;
|
||||
|
||||
/* package */ final class ClosedCaptionText extends ClosedCaption {
|
||||
|
||||
public final String text;
|
||||
|
||||
public ClosedCaptionText(String text) {
|
||||
super(ClosedCaption.TYPE_TEXT);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@ import com.google.android.exoplayer.util.ParsableBitArray;
|
|||
import com.google.android.exoplayer.util.ParsableByteArray;
|
||||
import com.google.android.exoplayer.util.extensions.Decoder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
|
@ -52,6 +51,55 @@ public final class Eia608Parser implements
|
|||
// The default number of rows to display in roll-up captions mode.
|
||||
private static final int DEFAULT_CAPTIONS_ROW_COUNT = 4;
|
||||
|
||||
/**
|
||||
* Command initiating pop-on style captioning. Subsequent data should be loaded into a
|
||||
* non-displayed memory and held there until the {@link #CTRL_END_OF_CAPTION} command is received,
|
||||
* at which point the non-displayed memory becomes the displayed memory (and vice versa).
|
||||
*/
|
||||
private static final byte CTRL_RESUME_CAPTION_LOADING = 0x20;
|
||||
/**
|
||||
* Command initiating roll-up style captioning, with the maximum of 2 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
private static final byte CTRL_ROLL_UP_CAPTIONS_2_ROWS = 0x25;
|
||||
/**
|
||||
* Command initiating roll-up style captioning, with the maximum of 3 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
private static final byte CTRL_ROLL_UP_CAPTIONS_3_ROWS = 0x26;
|
||||
/**
|
||||
* Command initiating roll-up style captioning, with the maximum of 4 rows displayed
|
||||
* simultaneously.
|
||||
*/
|
||||
private static final byte CTRL_ROLL_UP_CAPTIONS_4_ROWS = 0x27;
|
||||
/**
|
||||
* Command initiating paint-on style captioning. Subsequent data should be addressed immediately
|
||||
* to displayed memory without need for the {@link #CTRL_RESUME_CAPTION_LOADING} command.
|
||||
*/
|
||||
private static final byte CTRL_RESUME_DIRECT_CAPTIONING = 0x29;
|
||||
/**
|
||||
* Command indicating the end of a pop-on style caption. At this point the caption loaded in
|
||||
* non-displayed memory should be swapped with the one in displayed memory. If no
|
||||
* {@link #CTRL_RESUME_CAPTION_LOADING} command has been received, this command forces the
|
||||
* receiver into pop-on style.
|
||||
*/
|
||||
private static final byte CTRL_END_OF_CAPTION = 0x2F;
|
||||
|
||||
private static final byte CTRL_ERASE_DISPLAYED_MEMORY = 0x2C;
|
||||
private static final byte CTRL_CARRIAGE_RETURN = 0x2D;
|
||||
private static final byte CTRL_ERASE_NON_DISPLAYED_MEMORY = 0x2E;
|
||||
|
||||
private static final byte CTRL_BACKSPACE = 0x21;
|
||||
|
||||
private static final byte CTRL_MID_ROW_CHAN_1 = 0x11;
|
||||
private static final byte CTRL_MID_ROW_CHAN_2 = 0x19;
|
||||
|
||||
private static final byte CTRL_MISC_CHAN_1 = 0x14;
|
||||
private static final byte CTRL_MISC_CHAN_2 = 0x1C;
|
||||
|
||||
private static final byte CTRL_TAB_OFFSET_CHAN_1 = 0x17;
|
||||
private static final byte CTRL_TAB_OFFSET_CHAN_2 = 0x1F;
|
||||
|
||||
// Basic North American 608 CC char set, mostly ASCII. Indexed by (char-0x20).
|
||||
private static final int[] BASIC_CHARACTER_SET = new int[] {
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // ! " # $ % & '
|
||||
|
|
@ -125,8 +173,6 @@ public final class Eia608Parser implements
|
|||
private final TreeSet<SubtitleInputBuffer> queuedInputBuffers;
|
||||
|
||||
private final ParsableBitArray seiBuffer;
|
||||
private final StringBuilder textStringBuilder;
|
||||
private final ArrayList<ClosedCaption> captions;
|
||||
|
||||
private final StringBuilder captionStringBuilder;
|
||||
|
||||
|
|
@ -135,7 +181,12 @@ public final class Eia608Parser implements
|
|||
private int captionMode;
|
||||
private int captionRowCount;
|
||||
private String captionString;
|
||||
private ClosedCaptionCtrl repeatableControl;
|
||||
|
||||
private String lastCaptionString;
|
||||
|
||||
private boolean repeatableControlSet;
|
||||
private byte repeatableControlCc1;
|
||||
private byte repeatableControlCc2;
|
||||
|
||||
public Eia608Parser() {
|
||||
availableInputBuffers = new LinkedList<>();
|
||||
|
|
@ -149,8 +200,6 @@ public final class Eia608Parser implements
|
|||
queuedInputBuffers = new TreeSet<>();
|
||||
|
||||
seiBuffer = new ParsableBitArray();
|
||||
textStringBuilder = new StringBuilder();
|
||||
captions = new ArrayList<>();
|
||||
|
||||
captionStringBuilder = new StringBuilder();
|
||||
|
||||
|
|
@ -182,21 +231,28 @@ public final class Eia608Parser implements
|
|||
return null;
|
||||
}
|
||||
|
||||
SubtitleOutputBuffer outputBuffer = availableOutputBuffers.pollFirst();
|
||||
SubtitleOutputBuffer outputBuffer = null;
|
||||
SubtitleInputBuffer inputBuffer = queuedInputBuffers.pollFirst();
|
||||
|
||||
// TODO: investigate ways of batching multiple SubtitleInputBuffers into a single
|
||||
// SubtitleOutputBuffer
|
||||
// SubtitleOutputBuffer; it isn't as simple as just iterating through all of the queued input
|
||||
// buffers until there is a change because for pop-on captions this will result in the input
|
||||
// buffers being processed almost sequentially as they are queued, eliminating the re-ordering,
|
||||
// resulting in the content having characters out of order
|
||||
if (inputBuffer.isEndOfStream()) {
|
||||
outputBuffer = availableOutputBuffers.pollFirst();
|
||||
outputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
|
||||
return outputBuffer;
|
||||
}
|
||||
ClosedCaptionList captionList = decode(inputBuffer);
|
||||
Eia608Subtitle subtitle = generateSubtitle(captionList);
|
||||
outputBuffer.setOutput(inputBuffer.timeUs, subtitle, 0);
|
||||
if (inputBuffer.isDecodeOnly()) {
|
||||
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
||||
} else if (decode(inputBuffer)
|
||||
&& ((captionString == null && lastCaptionString != null)
|
||||
|| (captionString != null && !captionString.equals((lastCaptionString))))) {
|
||||
lastCaptionString = captionString;
|
||||
outputBuffer = availableOutputBuffers.pollFirst();
|
||||
outputBuffer.setOutput(inputBuffer.timeUs, new Eia608Subtitle(captionString), 0);
|
||||
if (inputBuffer.isDecodeOnly()) {
|
||||
outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
releaseInputBuffer(inputBuffer);
|
||||
return outputBuffer;
|
||||
}
|
||||
|
|
@ -217,7 +273,10 @@ public final class Eia608Parser implements
|
|||
captionRowCount = DEFAULT_CAPTIONS_ROW_COUNT;
|
||||
captionStringBuilder.setLength(0);
|
||||
captionString = null;
|
||||
repeatableControl = null;
|
||||
lastCaptionString = null;
|
||||
repeatableControlSet = false;
|
||||
repeatableControlCc1 = 0;
|
||||
repeatableControlCc2 = 0;
|
||||
while (!queuedInputBuffers.isEmpty()) {
|
||||
releaseInputBuffer(queuedInputBuffers.pollFirst());
|
||||
}
|
||||
|
|
@ -232,13 +291,10 @@ public final class Eia608Parser implements
|
|||
// Do nothing
|
||||
}
|
||||
|
||||
private ClosedCaptionList decode(SubtitleInputBuffer inputBuffer) {
|
||||
private boolean decode(SubtitleInputBuffer inputBuffer) {
|
||||
if (inputBuffer.size < 10) {
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
captions.clear();
|
||||
textStringBuilder.setLength(0);
|
||||
seiBuffer.reset(inputBuffer.data.array());
|
||||
|
||||
// country_code (8) + provider_code (16) + user_identifier (32) + user_data_type_code (8) +
|
||||
|
|
@ -247,6 +303,8 @@ public final class Eia608Parser implements
|
|||
int ccCount = seiBuffer.readBits(5);
|
||||
seiBuffer.skipBits(8);
|
||||
|
||||
boolean captionDataProcessed = false;
|
||||
boolean isRepeatableControl = false;
|
||||
for (int i = 0; i < ccCount; i++) {
|
||||
seiBuffer.skipBits(5); // one_bit + reserved
|
||||
boolean ccValid = seiBuffer.readBit();
|
||||
|
|
@ -269,11 +327,14 @@ public final class Eia608Parser implements
|
|||
continue;
|
||||
}
|
||||
|
||||
// If we've reached this point then there is data to process; flag that work has been done.
|
||||
captionDataProcessed = true;
|
||||
|
||||
// Special North American character set.
|
||||
// ccData2 - P|0|1|1|X|X|X|X
|
||||
if ((ccData1 == 0x11 || ccData1 == 0x19)
|
||||
&& ((ccData2 & 0x70) == 0x30)) {
|
||||
textStringBuilder.append(getSpecialChar(ccData2));
|
||||
captionStringBuilder.append(getSpecialChar(ccData2));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -282,7 +343,7 @@ public final class Eia608Parser implements
|
|||
if ((ccData1 == 0x12 || ccData1 == 0x1A)
|
||||
&& ((ccData2 & 0x60) == 0x20)) {
|
||||
backspace(); // Remove standard equivalent of the special extended char.
|
||||
textStringBuilder.append(getExtendedEsFrChar(ccData2));
|
||||
captionStringBuilder.append(getExtendedEsFrChar(ccData2));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -291,89 +352,76 @@ public final class Eia608Parser implements
|
|||
if ((ccData1 == 0x13 || ccData1 == 0x1B)
|
||||
&& ((ccData2 & 0x60) == 0x20)) {
|
||||
backspace(); // Remove standard equivalent of the special extended char.
|
||||
textStringBuilder.append(getExtendedPtDeChar(ccData2));
|
||||
captionStringBuilder.append(getExtendedPtDeChar(ccData2));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Control character.
|
||||
if (ccData1 < 0x20) {
|
||||
addCtrl(ccData1, ccData2);
|
||||
isRepeatableControl = handleCtrl(ccData1, ccData2);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Basic North American character set.
|
||||
textStringBuilder.append(getChar(ccData1));
|
||||
captionStringBuilder.append(getChar(ccData1));
|
||||
if (ccData2 >= 0x20) {
|
||||
textStringBuilder.append(getChar(ccData2));
|
||||
captionStringBuilder.append(getChar(ccData2));
|
||||
}
|
||||
}
|
||||
|
||||
addBufferedText();
|
||||
|
||||
if (captions.isEmpty()) {
|
||||
return null;
|
||||
if (!captionDataProcessed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClosedCaption[] captionArray = new ClosedCaption[captions.size()];
|
||||
captions.toArray(captionArray);
|
||||
return new ClosedCaptionList(inputBuffer.timeUs, captionArray);
|
||||
if (!isRepeatableControl) {
|
||||
repeatableControlSet = false;
|
||||
}
|
||||
if (captionMode == CC_MODE_ROLL_UP || captionMode == CC_MODE_PAINT_ON) {
|
||||
captionString = getDisplayCaption();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Eia608Subtitle generateSubtitle(ClosedCaptionList captionList) {
|
||||
int captionBufferSize = (captionList == null) ? 0 : captionList.captions.length;
|
||||
if (captionBufferSize != 0) {
|
||||
boolean isRepeatableControl = false;
|
||||
for (ClosedCaption caption : captionList.captions) {
|
||||
if (caption.type == ClosedCaption.TYPE_CTRL) {
|
||||
ClosedCaptionCtrl captionCtrl = (ClosedCaptionCtrl) caption;
|
||||
isRepeatableControl = captionBufferSize == 1 && captionCtrl.isRepeatable();
|
||||
if (isRepeatableControl && repeatableControl != null
|
||||
&& repeatableControl.cc1 == captionCtrl.cc1
|
||||
&& repeatableControl.cc2 == captionCtrl.cc2) {
|
||||
repeatableControl = null;
|
||||
continue;
|
||||
} else if (isRepeatableControl) {
|
||||
repeatableControl = captionCtrl;
|
||||
}
|
||||
if (captionCtrl.isMiscCode()) {
|
||||
handleMiscCode(captionCtrl);
|
||||
} else if (captionCtrl.isPreambleAddressCode()) {
|
||||
handlePreambleAddressCode();
|
||||
}
|
||||
} else {
|
||||
handleText((ClosedCaptionText) caption);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRepeatableControl) {
|
||||
repeatableControl = null;
|
||||
}
|
||||
if (captionMode == CC_MODE_ROLL_UP || captionMode == CC_MODE_PAINT_ON) {
|
||||
captionString = getDisplayCaption();
|
||||
}
|
||||
private boolean handleCtrl(byte cc1, byte cc2) {
|
||||
boolean isRepeatableControl = isRepeatable(cc1, cc2);
|
||||
if (isRepeatableControl && repeatableControlSet
|
||||
&& repeatableControlCc1 == cc1
|
||||
&& repeatableControlCc2 == cc2) {
|
||||
repeatableControlSet = false;
|
||||
return true;
|
||||
} else if (isRepeatableControl) {
|
||||
repeatableControlSet = true;
|
||||
repeatableControlCc1 = cc1;
|
||||
repeatableControlCc2 = cc2;
|
||||
}
|
||||
|
||||
return new Eia608Subtitle(captionString);
|
||||
if (isMiscCode(cc1, cc2)) {
|
||||
handleMiscCode(cc2);
|
||||
} else if (isPreambleAddressCode(cc1, cc2)) {
|
||||
// TODO: Add better handling of this with specific positioning.
|
||||
maybeAppendNewline();
|
||||
}
|
||||
return isRepeatableControl;
|
||||
}
|
||||
|
||||
private void handleMiscCode(ClosedCaptionCtrl caption) {
|
||||
switch (caption.cc2) {
|
||||
case ClosedCaptionCtrl.ROLL_UP_CAPTIONS_2_ROWS:
|
||||
private void handleMiscCode(byte cc2) {
|
||||
switch (cc2) {
|
||||
case CTRL_ROLL_UP_CAPTIONS_2_ROWS:
|
||||
captionRowCount = 2;
|
||||
setCaptionMode(CC_MODE_ROLL_UP);
|
||||
return;
|
||||
case ClosedCaptionCtrl.ROLL_UP_CAPTIONS_3_ROWS:
|
||||
case CTRL_ROLL_UP_CAPTIONS_3_ROWS:
|
||||
captionRowCount = 3;
|
||||
setCaptionMode(CC_MODE_ROLL_UP);
|
||||
return;
|
||||
case ClosedCaptionCtrl.ROLL_UP_CAPTIONS_4_ROWS:
|
||||
case CTRL_ROLL_UP_CAPTIONS_4_ROWS:
|
||||
captionRowCount = 4;
|
||||
setCaptionMode(CC_MODE_ROLL_UP);
|
||||
return;
|
||||
case ClosedCaptionCtrl.RESUME_CAPTION_LOADING:
|
||||
case CTRL_RESUME_CAPTION_LOADING:
|
||||
setCaptionMode(CC_MODE_POP_ON);
|
||||
return;
|
||||
case ClosedCaptionCtrl.RESUME_DIRECT_CAPTIONING:
|
||||
case CTRL_RESUME_DIRECT_CAPTIONING:
|
||||
setCaptionMode(CC_MODE_PAINT_ON);
|
||||
return;
|
||||
}
|
||||
|
|
@ -382,24 +430,24 @@ public final class Eia608Parser implements
|
|||
return;
|
||||
}
|
||||
|
||||
switch (caption.cc2) {
|
||||
case ClosedCaptionCtrl.ERASE_DISPLAYED_MEMORY:
|
||||
switch (cc2) {
|
||||
case CTRL_ERASE_DISPLAYED_MEMORY:
|
||||
captionString = null;
|
||||
if (captionMode == CC_MODE_ROLL_UP || captionMode == CC_MODE_PAINT_ON) {
|
||||
captionStringBuilder.setLength(0);
|
||||
}
|
||||
return;
|
||||
case ClosedCaptionCtrl.ERASE_NON_DISPLAYED_MEMORY:
|
||||
case CTRL_ERASE_NON_DISPLAYED_MEMORY:
|
||||
captionStringBuilder.setLength(0);
|
||||
return;
|
||||
case ClosedCaptionCtrl.END_OF_CAPTION:
|
||||
case CTRL_END_OF_CAPTION:
|
||||
captionString = getDisplayCaption();
|
||||
captionStringBuilder.setLength(0);
|
||||
return;
|
||||
case ClosedCaptionCtrl.CARRIAGE_RETURN:
|
||||
case CTRL_CARRIAGE_RETURN:
|
||||
maybeAppendNewline();
|
||||
return;
|
||||
case ClosedCaptionCtrl.BACKSPACE:
|
||||
case CTRL_BACKSPACE:
|
||||
if (captionStringBuilder.length() > 0) {
|
||||
captionStringBuilder.setLength(captionStringBuilder.length() - 1);
|
||||
}
|
||||
|
|
@ -407,13 +455,10 @@ public final class Eia608Parser implements
|
|||
}
|
||||
}
|
||||
|
||||
private void handlePreambleAddressCode() {
|
||||
// TODO: Add better handling of this with specific positioning.
|
||||
maybeAppendNewline();
|
||||
}
|
||||
|
||||
private void handleText(ClosedCaptionText caption) {
|
||||
captionStringBuilder.append(caption.text);
|
||||
private void backspace() {
|
||||
if (captionStringBuilder.length() > 0) {
|
||||
captionStringBuilder.setLength(captionStringBuilder.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeAppendNewline() {
|
||||
|
|
@ -485,21 +530,17 @@ public final class Eia608Parser implements
|
|||
return (char) SPECIAL_PT_DE_CHARACTER_SET[index];
|
||||
}
|
||||
|
||||
private void addBufferedText() {
|
||||
if (textStringBuilder.length() > 0) {
|
||||
String textSnippet = textStringBuilder.toString();
|
||||
captions.add(new ClosedCaptionText(textSnippet));
|
||||
textStringBuilder.setLength(0);
|
||||
}
|
||||
private static boolean isMiscCode(byte cc1, byte cc2) {
|
||||
return (cc1 == CTRL_MISC_CHAN_1 || cc1 == CTRL_MISC_CHAN_2)
|
||||
&& (cc2 >= 0x20 && cc2 <= 0x2F);
|
||||
}
|
||||
|
||||
private void addCtrl(byte ccData1, byte ccData2) {
|
||||
addBufferedText();
|
||||
captions.add(new ClosedCaptionCtrl(ccData1, ccData2));
|
||||
private static boolean isPreambleAddressCode(byte cc1, byte cc2) {
|
||||
return (cc1 >= 0x10 && cc1 <= 0x1F) && (cc2 >= 0x40 && cc2 <= 0x7F);
|
||||
}
|
||||
|
||||
private void backspace() {
|
||||
addCtrl((byte) 0x14, ClosedCaptionCtrl.BACKSPACE);
|
||||
private static boolean isRepeatable(byte cc1, byte cc2) {
|
||||
return cc1 >= 0x10 && cc1 <= 0x1F;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue