Commit 040fe3b1 by cdrolle Committed by Oliver Woodman

Refactored the text.eia608 package to text.cea.

All of the classes in the text.eia608 package have been moved to
text.cea, and renamed with the "cea" prefix instead of "eia". All of
the buffering logic has been extracted from Cea608Decoder (formerly
Eia608Decoder) into the abstract CeaDecoder, which Cea608Decoder
extends. Cea608Decoder also now expects a 3-byte sample (i.e. the
entire cc_data_pkt instead of just the cc_data_1 and cc_data_2 bytes).
Classes like RawCcExtractor and SeiReader, responsible for creating
these samples, have also been updated accordingly.

This change is a necessary precursor to adding support for multi
-channel CEA-608 and CEA-708 captions.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=134537482
parent 825ec70d
Showing with 694 additions and 314 deletions
...@@ -8,7 +8,7 @@ track 0: ...@@ -8,7 +8,7 @@ track 0:
bitrate = -1 bitrate = -1
id = null id = null
containerMimeType = null containerMimeType = null
sampleMimeType = application/eia-608 sampleMimeType = application/cea-608
maxInputSize = -1 maxInputSize = -1
width = -1 width = -1
height = -1 height = -1
...@@ -25,305 +25,605 @@ track 0: ...@@ -25,305 +25,605 @@ track 0:
language = null language = null
drmInitData = - drmInitData = -
initializationData: initializationData:
sample count = 75 sample count = 150
sample 0: sample 0:
time = 37657512133 time = 37657512133
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7363
sample 1: sample 1:
time = 37657545511 time = 37657528822
flags = 1 flags = 1
data = length 2, hash FFFFF6CD data = length 3, hash 7724
sample 2: sample 2:
time = 37657578866 time = 37657545511
flags = 1 flags = 1
data = length 2, hash FFFFF6DC data = length 3, hash 766F
sample 3: sample 3:
time = 37657612244 time = 37657562177
flags = 1 flags = 1
data = length 2, hash FFFFF65B data = length 3, hash 7724
sample 4: sample 4:
time = 37657645600 time = 37657578866
flags = 1 flags = 1
data = length 2, hash FFFFF6CD data = length 3, hash 767E
sample 5: sample 5:
time = 37657678977 time = 37657595555
flags = 1 flags = 1
data = length 2, hash FFFFF67B data = length 3, hash 7724
sample 6: sample 6:
time = 37657712333 time = 37657612244
flags = 1 flags = 1
data = length 2, hash 2B5 data = length 15, hash E4359178
sample 7: sample 7:
time = 37657745711 time = 37657628911
flags = 1 flags = 1
data = length 2, hash F5 data = length 3, hash 7724
sample 8: sample 8:
time = 37657779066 time = 37657645600
flags = 1 flags = 1
data = length 2, hash FFFFF87A data = length 12, hash 15EBEB66
sample 9: sample 9:
time = 37657812444 time = 37657662288
flags = 1 flags = 1
data = length 2, hash FFFFF698 data = length 3, hash 7724
sample 10: sample 10:
time = 37657845800 time = 37657678977
flags = 1 flags = 1
data = length 2, hash 1F4 data = length 3, hash 761D
sample 11: sample 11:
time = 37657879177 time = 37657695644
flags = 1 flags = 1
data = length 2, hash 803 data = length 3, hash 7724
sample 12: sample 12:
time = 37657912533 time = 37657712333
flags = 1 flags = 1
data = length 2, hash 1F8 data = length 30, hash E181418F
sample 13: sample 13:
time = 37657945911 time = 37657729022
flags = 1 flags = 1
data = length 2, hash 117A data = length 6, hash 36289CE2
sample 14: sample 14:
time = 37657979266 time = 37657745711
flags = 1 flags = 1
data = length 2, hash 166 data = length 12, hash 3C304F5B
sample 15: sample 15:
time = 37658012644 time = 37657762377
flags = 1 flags = 1
data = length 2, hash 105A data = length 3, hash 7724
sample 16: sample 16:
time = 37658046000 time = 37657779066
flags = 1 flags = 1
data = length 2, hash FCF data = length 12, hash 88DD8EF6
sample 17: sample 17:
time = 37658079377 time = 37657795755
flags = 1 flags = 1
data = length 2, hash 1253 data = length 3, hash 7724
sample 18: sample 18:
time = 37658112733 time = 37657812444
flags = 1 flags = 1
data = length 2, hash 11DA data = length 12, hash 8B411833
sample 19: sample 19:
time = 37658146111 time = 37657829111
flags = 1 flags = 1
data = length 2, hash 795 data = length 3, hash 7724
sample 20: sample 20:
time = 37658179466 time = 37657845800
flags = 1 flags = 1
data = length 2, hash 103E data = length 12, hash 742A2DF1
sample 21: sample 21:
time = 37658212844 time = 37657862488
flags = 1 flags = 1
data = length 2, hash 120F data = length 3, hash 7724
sample 22: sample 22:
time = 37658246200 time = 37657879177
flags = 1 flags = 1
data = length 2, hash FFFFF698 data = length 12, hash 9A2ECBEE
sample 23: sample 23:
time = 37658279577 time = 37657895844
flags = 1 flags = 1
data = length 2, hash 1F4 data = length 3, hash 7724
sample 24: sample 24:
time = 37658312933 time = 37657912533
flags = 1 flags = 1
data = length 2, hash FFFFF71B data = length 12, hash 562688EA
sample 25: sample 25:
time = 37658346311 time = 37657929222
flags = 1 flags = 1
data = length 2, hash F91 data = length 3, hash 7724
sample 26: sample 26:
time = 37658379666 time = 37657945911
flags = 1 flags = 1
data = length 2, hash 166 data = length 12, hash ADE4B953
sample 27: sample 27:
time = 37658413044 time = 37657962577
flags = 1 flags = 1
data = length 2, hash 1023 data = length 3, hash 7724
sample 28: sample 28:
time = 37658446400 time = 37657979266
flags = 1 flags = 1
data = length 2, hash 117A data = length 12, hash F927E3E5
sample 29: sample 29:
time = 37658479777 time = 37657995955
flags = 1 flags = 1
data = length 2, hash 784 data = length 3, hash 7724
sample 30: sample 30:
time = 37658513133 time = 37658012644
flags = 1 flags = 1
data = length 2, hash 1F8 data = length 12, hash EA327945
sample 31: sample 31:
time = 37658546511 time = 37658029311
flags = 1 flags = 1
data = length 2, hash 10D9 data = length 3, hash 7724
sample 32: sample 32:
time = 37658579866 time = 37658046000
flags = 1 flags = 1
data = length 2, hash 935 data = length 12, hash 3E5DA13C
sample 33: sample 33:
time = 37658613244 time = 37658062688
flags = 1 flags = 1
data = length 2, hash 2B5 data = length 3, hash 7724
sample 34: sample 34:
time = 37658646600 time = 37658079377
flags = 1 flags = 1
data = length 2, hash F5 data = length 12, hash BF646AE3
sample 35: sample 35:
time = 37658679977 time = 37658096044
flags = 1 flags = 1
data = length 2, hash FFFFF87A data = length 3, hash 7724
sample 36: sample 36:
time = 37658713333 time = 37658112733
flags = 1 flags = 1
data = length 2, hash FFFFF698 data = length 12, hash 41E3BA78
sample 37: sample 37:
time = 37658746711 time = 37658129422
flags = 1 flags = 1
data = length 2, hash 1F4 data = length 3, hash 7724
sample 38: sample 38:
time = 37658780066 time = 37658146111
flags = 1 flags = 1
data = length 2, hash 793 data = length 12, hash A2945EF6
sample 39: sample 39:
time = 37658813444 time = 37658162777
flags = 1 flags = 1
data = length 2, hash FF0 data = length 3, hash 7724
sample 40: sample 40:
time = 37658846800 time = 37658179466
flags = 1 flags = 1
data = length 2, hash 16B data = length 12, hash 26735812
sample 41: sample 41:
time = 37658880177 time = 37658196155
flags = 1 flags = 1
data = length 2, hash 2C0 data = length 3, hash 7724
sample 42: sample 42:
time = 37658913533 time = 37658212844
flags = 1 flags = 1
data = length 2, hash FFFFF953 data = length 12, hash DC14D3D8
sample 43: sample 43:
time = 37658946911 time = 37658229511
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 44: sample 44:
time = 37658980266 time = 37658246200
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash 882191BE
sample 45: sample 45:
time = 37659013644 time = 37658262888
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 46: sample 46:
time = 37659047000 time = 37658279577
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash 8B4886B1
sample 47: sample 47:
time = 37659080377 time = 37658296244
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 48: sample 48:
time = 37659113733 time = 37658312933
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash 98D98F96
sample 49: sample 49:
time = 37659147111 time = 37658329622
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 50: sample 50:
time = 37659180466 time = 37658346311
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 30, hash CF8E53E3
sample 51: sample 51:
time = 37659213844 time = 37658362977
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 6, hash 36289CE2
sample 52: sample 52:
time = 37659247200 time = 37658379666
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash F883C9EE
sample 53: sample 53:
time = 37659280577 time = 37658396355
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 54: sample 54:
time = 37659313933 time = 37658413044
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash 6E6B2B9C
sample 55: sample 55:
time = 37659347311 time = 37658429711
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 56: sample 56:
time = 37659380666 time = 37658446400
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash B4FE7F08
sample 57: sample 57:
time = 37659414044 time = 37658463088
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 58: sample 58:
time = 37659447400 time = 37658479777
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash 5A1EA7C7
sample 59: sample 59:
time = 37659480777 time = 37658496444
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 60: sample 60:
time = 37659514133 time = 37658513133
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash 46BD6CC9
sample 61: sample 61:
time = 37659547511 time = 37658529822
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 3, hash 7724
sample 62: sample 62:
time = 37659580866 time = 37658546511
flags = 1 flags = 1
data = length 2, hash FFFFF3C1 data = length 12, hash 1B1E2554
sample 63: sample 63:
time = 37659614244 time = 37658563177
flags = 1 flags = 1
data = length 2, hash FFFFF6CD data = length 3, hash 7724
sample 64: sample 64:
time = 37659647600 time = 37658579866
flags = 1 flags = 1
data = length 2, hash FFFFF6DC data = length 12, hash 91FCC537
sample 65: sample 65:
time = 37659680977 time = 37658596555
flags = 1 flags = 1
data = length 2, hash FFFFF65B data = length 3, hash 7724
sample 66: sample 66:
time = 37659714333 time = 37658613244
flags = 1 flags = 1
data = length 2, hash FFFFF6CD data = length 12, hash A9355E1B
sample 67: sample 67:
time = 37659747711 time = 37658629911
flags = 1 flags = 1
data = length 2, hash FFFFF6FF data = length 3, hash 7724
sample 68: sample 68:
time = 37659781066 time = 37658646600
flags = 1 flags = 1
data = length 2, hash FFFFF6AC data = length 12, hash 2511F69B
sample 69: sample 69:
time = 37659814444 time = 37658663288
flags = 1 flags = 1
data = length 2, hash FFFFF5FE data = length 3, hash 7724
sample 70: sample 70:
time = 37659847800 time = 37658679977
flags = 1 flags = 1
data = length 2, hash FFFFFEF7 data = length 12, hash 90925736
sample 71: sample 71:
time = 37659881177 time = 37658696644
flags = 1 flags = 1
data = length 2, hash 120C data = length 3, hash 7724
sample 72: sample 72:
time = 37659914533 time = 37658713333
flags = 1 flags = 1
data = length 2, hash 1124 data = length 21, hash 431EEE30
sample 73: sample 73:
time = 37659947911 time = 37658730022
flags = 1 flags = 1
data = length 2, hash 1A9 data = length 3, hash 7724
sample 74: sample 74:
time = 37658746711
flags = 1
data = length 12, hash 7BDEF631
sample 75:
time = 37658763377
flags = 1
data = length 3, hash 7724
sample 76:
time = 37658780066
flags = 1
data = length 12, hash A2EEF59E
sample 77:
time = 37658796755
flags = 1
data = length 3, hash 7724
sample 78:
time = 37658813444
flags = 1
data = length 12, hash BFC6C022
sample 79:
time = 37658830111
flags = 1
data = length 3, hash 7724
sample 80:
time = 37658846800
flags = 1
data = length 12, hash CD4D8FCA
sample 81:
time = 37658863488
flags = 1
data = length 3, hash 7724
sample 82:
time = 37658880177
flags = 1
data = length 12, hash 2BDE8EFA
sample 83:
time = 37658896844
flags = 1
data = length 3, hash 7724
sample 84:
time = 37658913533
flags = 1
data = length 12, hash 8C858812
sample 85:
time = 37658930222
flags = 1
data = length 3, hash 7724
sample 86:
time = 37658946911
flags = 1
data = length 12, hash DE7D0E31
sample 87:
time = 37658963577
flags = 1
data = length 3, hash 7724
sample 88:
time = 37658980266
flags = 1
data = length 3, hash 7363
sample 89:
time = 37658996955
flags = 1
data = length 3, hash 7724
sample 90:
time = 37659013644
flags = 1
data = length 3, hash 7363
sample 91:
time = 37659030311
flags = 1
data = length 3, hash 7724
sample 92:
time = 37659047000
flags = 1
data = length 3, hash 7363
sample 93:
time = 37659063688
flags = 1
data = length 3, hash 7724
sample 94:
time = 37659080377
flags = 1
data = length 3, hash 7363
sample 95:
time = 37659097044
flags = 1
data = length 3, hash 7724
sample 96:
time = 37659113733
flags = 1
data = length 3, hash 7363
sample 97:
time = 37659130422
flags = 1
data = length 3, hash 7724
sample 98:
time = 37659147111
flags = 1
data = length 3, hash 7363
sample 99:
time = 37659163777
flags = 1
data = length 3, hash 7724
sample 100:
time = 37659180466
flags = 1
data = length 3, hash 7363
sample 101:
time = 37659197155
flags = 1
data = length 3, hash 7724
sample 102:
time = 37659213844
flags = 1
data = length 3, hash 7363
sample 103:
time = 37659230511
flags = 1
data = length 3, hash 7724
sample 104:
time = 37659247200
flags = 1
data = length 3, hash 7363
sample 105:
time = 37659263888
flags = 1
data = length 3, hash 7724
sample 106:
time = 37659280577
flags = 1
data = length 3, hash 7363
sample 107:
time = 37659297244
flags = 1
data = length 3, hash 7724
sample 108:
time = 37659313933
flags = 1
data = length 3, hash 7363
sample 109:
time = 37659330622
flags = 1
data = length 3, hash 7724
sample 110:
time = 37659347311
flags = 1
data = length 3, hash 7363
sample 111:
time = 37659363977
flags = 1
data = length 3, hash 7724
sample 112:
time = 37659380666
flags = 1
data = length 3, hash 7363
sample 113:
time = 37659397355
flags = 1
data = length 3, hash 7724
sample 114:
time = 37659414044
flags = 1
data = length 3, hash 7363
sample 115:
time = 37659430711
flags = 1
data = length 3, hash 7724
sample 116:
time = 37659447400
flags = 1
data = length 3, hash 7363
sample 117:
time = 37659464088
flags = 1
data = length 3, hash 7724
sample 118:
time = 37659480777
flags = 1
data = length 3, hash 7363
sample 119:
time = 37659497444
flags = 1
data = length 3, hash 7724
sample 120:
time = 37659514133
flags = 1
data = length 3, hash 7363
sample 121:
time = 37659530822
flags = 1
data = length 3, hash 7724
sample 122:
time = 37659547511
flags = 1
data = length 3, hash 7363
sample 123:
time = 37659564177
flags = 1
data = length 3, hash 7724
sample 124:
time = 37659580866
flags = 1
data = length 3, hash 7363
sample 125:
time = 37659597555
flags = 1
data = length 3, hash 7724
sample 126:
time = 37659614244
flags = 1
data = length 3, hash 766F
sample 127:
time = 37659630911
flags = 1
data = length 3, hash 7724
sample 128:
time = 37659647600
flags = 1
data = length 3, hash 767E
sample 129:
time = 37659664288
flags = 1
data = length 3, hash 7724
sample 130:
time = 37659680977
flags = 1
data = length 15, hash 191B585A
sample 131:
time = 37659697644
flags = 1
data = length 3, hash 7724
sample 132:
time = 37659714333
flags = 1
data = length 12, hash 15EC5FC5
sample 133:
time = 37659731022
flags = 1
data = length 3, hash 7724
sample 134:
time = 37659747711
flags = 1
data = length 3, hash 76A1
sample 135:
time = 37659764377
flags = 1
data = length 3, hash 7724
sample 136:
time = 37659781066
flags = 1
data = length 30, hash E8012479
sample 137:
time = 37659797755
flags = 1
data = length 6, hash 36289D5E
sample 138:
time = 37659814444
flags = 1
data = length 12, hash D32F29F3
sample 139:
time = 37659831111
flags = 1
data = length 3, hash 7724
sample 140:
time = 37659847800
flags = 1
data = length 21, hash 6258623
sample 141:
time = 37659864488
flags = 1
data = length 3, hash 7724
sample 142:
time = 37659881177
flags = 1
data = length 12, hash FE69ABA2
sample 143:
time = 37659897844
flags = 1
data = length 3, hash 7724
sample 144:
time = 37659914533
flags = 1
data = length 12, hash 958D0815
sample 145:
time = 37659931222
flags = 1
data = length 3, hash 7724
sample 146:
time = 37659947911
flags = 1
data = length 12, hash FF57BFD8
sample 147:
time = 37659964577
flags = 1
data = length 3, hash 7724
sample 148:
time = 37659981266 time = 37659981266
flags = 1 flags = 1
data = length 2, hash 935 data = length 12, hash 922122E7
sample 149:
time = 37659997955
flags = 1
data = length 3, hash 7724
tracksEnded = true tracksEnded = true
...@@ -644,7 +644,7 @@ import java.util.List; ...@@ -644,7 +644,7 @@ import java.util.List;
0 /* subsample timing is absolute */); 0 /* subsample timing is absolute */);
} else if (childAtomType == Atom.TYPE_c608) { } else if (childAtomType == Atom.TYPE_c608) {
out.format = Format.createTextSampleFormat(Integer.toString(trackId), out.format = Format.createTextSampleFormat(Integer.toString(trackId),
MimeTypes.APPLICATION_EIA608, null, Format.NO_VALUE, 0, language, drmInitData); MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE, 0, language, drmInitData);
out.requiredSampleTransformation = Track.TRANSFORMATION_CEA608_CDAT; out.requiredSampleTransformation = Track.TRANSFORMATION_CEA608_CDAT;
} }
stsd.setPosition(childStartPosition + childAtomSize); stsd.setPosition(childStartPosition + childAtomSize);
......
...@@ -30,7 +30,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -30,7 +30,7 @@ import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
/** /**
* Extracts EIA-608 data from a RawCC file * Extracts CEA data from a RawCC file.
*/ */
public final class RawCcExtractor implements Extractor { public final class RawCcExtractor implements Extractor {
...@@ -68,7 +68,7 @@ public final class RawCcExtractor implements Extractor { ...@@ -68,7 +68,7 @@ public final class RawCcExtractor implements Extractor {
trackOutput = extractorOutput.track(0); trackOutput = extractorOutput.track(0);
extractorOutput.endTracks(); extractorOutput.endTracks();
trackOutput.format(Format.createTextSampleFormat(null, MimeTypes.APPLICATION_EIA608, trackOutput.format(Format.createTextSampleFormat(null, MimeTypes.APPLICATION_CEA608,
null, Format.NO_VALUE, 0, null, null)); null, Format.NO_VALUE, 0, null, null));
} }
...@@ -154,13 +154,8 @@ public final class RawCcExtractor implements Extractor { ...@@ -154,13 +154,8 @@ public final class RawCcExtractor implements Extractor {
dataScratch.reset(); dataScratch.reset();
input.readFully(dataScratch.data, 0, 3); input.readFully(dataScratch.data, 0, 3);
// only accept EIA-608 packets which have validity (6th bit) == 1 and trackOutput.sampleData(dataScratch, 3);
// type (7-8th bits) == 0; i.e. ccDataPkt[0] == 0bXXXXX100 sampleBytesWritten += 3;
int ccValidityAndType = dataScratch.readUnsignedByte() & 0x07;
if (ccValidityAndType == 0x04) {
trackOutput.sampleData(dataScratch, 2);
sampleBytesWritten += 2;
}
} }
if (sampleBytesWritten > 0) { if (sampleBytesWritten > 0) {
......
...@@ -57,7 +57,7 @@ import java.util.List; ...@@ -57,7 +57,7 @@ import java.util.List;
/** /**
* @param output A {@link TrackOutput} to which H.264 samples should be written. * @param output A {@link TrackOutput} to which H.264 samples should be written.
* @param seiReader A reader for EIA-608 samples in SEI NAL units. * @param seiReader A reader for CEA-608 samples in SEI NAL units.
* @param allowNonIdrKeyframes Whether to treat samples consisting of non-IDR I slices as * @param allowNonIdrKeyframes Whether to treat samples consisting of non-IDR I slices as
* synchronization samples (key-frames). * synchronization samples (key-frames).
* @param detectAccessUnits Whether to split the input stream into access units (samples) based on * @param detectAccessUnits Whether to split the input stream into access units (samples) based on
......
...@@ -64,7 +64,7 @@ import java.util.Collections; ...@@ -64,7 +64,7 @@ import java.util.Collections;
/** /**
* @param output A {@link TrackOutput} to which H.265 samples should be written. * @param output A {@link TrackOutput} to which H.265 samples should be written.
* @param seiReader A reader for EIA-608 samples in SEI NAL units. * @param seiReader A reader for CEA-608 samples in SEI NAL units.
*/ */
public H265Reader(TrackOutput output, SeiReader seiReader) { public H265Reader(TrackOutput output, SeiReader seiReader) {
super(output); super(output);
......
...@@ -18,12 +18,12 @@ package com.google.android.exoplayer2.extractor.ts; ...@@ -18,12 +18,12 @@ package com.google.android.exoplayer2.extractor.ts;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.text.eia608.Eia608Decoder; import com.google.android.exoplayer2.text.cea.Cea608Decoder;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
/** /**
* Consumes SEI buffers, outputting contained EIA608 messages to a {@link TrackOutput}. * Consumes SEI buffers, outputting contained CEA-608 messages to a {@link TrackOutput}.
*/ */
/* package */ final class SeiReader { /* package */ final class SeiReader {
...@@ -31,7 +31,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray; ...@@ -31,7 +31,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
public SeiReader(TrackOutput output) { public SeiReader(TrackOutput output) {
this.output = output; this.output = output;
output.format(Format.createTextSampleFormat(null, MimeTypes.APPLICATION_EIA608, null, output.format(Format.createTextSampleFormat(null, MimeTypes.APPLICATION_CEA608, null,
Format.NO_VALUE, 0, null, null)); Format.NO_VALUE, 0, null, null));
} }
...@@ -51,7 +51,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray; ...@@ -51,7 +51,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
payloadSize += b; payloadSize += b;
} while (b == 0xFF); } while (b == 0xFF);
// Process the payload. // Process the payload.
if (Eia608Decoder.isSeiMessageEia608(payloadType, payloadSize, seiBuffer)) { if (Cea608Decoder.isSeiMessageCea608(payloadType, payloadSize, seiBuffer)) {
// Ignore country_code (1) + provider_code (2) + user_identifier (4) // Ignore country_code (1) + provider_code (2) + user_identifier (4)
// + user_data_type_code (1). // + user_data_type_code (1).
seiBuffer.skipBytes(8); seiBuffer.skipBytes(8);
...@@ -60,13 +60,13 @@ import com.google.android.exoplayer2.util.ParsableByteArray; ...@@ -60,13 +60,13 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
seiBuffer.skipBytes(1); seiBuffer.skipBytes(1);
int sampleBytes = 0; int sampleBytes = 0;
for (int i = 0; i < ccCount; i++) { for (int i = 0; i < ccCount; i++) {
int ccValidityAndType = seiBuffer.readUnsignedByte() & 0x07; int ccValidityAndType = seiBuffer.peekUnsignedByte() & 0x07;
// Check that validity == 1 and type == 0. // Check that validity == 1 and type == 0 (i.e. NTSC_CC_FIELD_1).
if (ccValidityAndType != 0x04) { if (ccValidityAndType != 0x04) {
seiBuffer.skipBytes(2); seiBuffer.skipBytes(3);
} else { } else {
sampleBytes += 2; sampleBytes += 3;
output.sampleData(seiBuffer, 2); output.sampleData(seiBuffer, 3);
} }
} }
output.sampleMetadata(pesTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytes, 0, null); output.sampleMetadata(pesTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytes, 0, null);
......
...@@ -654,9 +654,10 @@ public class DashManifestParser extends DefaultHandler ...@@ -654,9 +654,10 @@ public class DashManifestParser extends DefaultHandler
} else if (MimeTypes.isVideo(containerMimeType)) { } else if (MimeTypes.isVideo(containerMimeType)) {
return MimeTypes.getVideoMediaMimeType(codecs); return MimeTypes.getVideoMediaMimeType(codecs);
} else if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) { } else if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
// We currently only support EIA-608 through RawCC // We currently only support CEA-608 through RawCC
if (codecs != null && codecs.contains("eia608")) { if (codecs != null
return MimeTypes.APPLICATION_EIA608; && (codecs.contains("eia608") || codecs.contains("cea608"))) {
return MimeTypes.APPLICATION_CEA608;
} }
return null; return null;
} else if (mimeTypeIsRawText(containerMimeType)) { } else if (mimeTypeIsRawText(containerMimeType)) {
......
...@@ -589,7 +589,7 @@ import java.util.LinkedList; ...@@ -589,7 +589,7 @@ import java.util.LinkedList;
if (primaryExtractorTrackType == PRIMARY_TYPE_VIDEO) { if (primaryExtractorTrackType == PRIMARY_TYPE_VIDEO) {
if (MimeTypes.isAudio(sampleFormat.sampleMimeType)) { if (MimeTypes.isAudio(sampleFormat.sampleMimeType)) {
trackFormat = muxedAudioFormat; trackFormat = muxedAudioFormat;
} else if (MimeTypes.APPLICATION_EIA608.equals(sampleFormat.sampleMimeType)) { } else if (MimeTypes.APPLICATION_CEA608.equals(sampleFormat.sampleMimeType)) {
trackFormat = muxedCaptionFormat; trackFormat = muxedCaptionFormat;
} }
} }
......
...@@ -161,7 +161,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli ...@@ -161,7 +161,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
case TYPE_CLOSED_CAPTIONS: case TYPE_CLOSED_CAPTIONS:
if ("CC1".equals(parseOptionalStringAttr(line, REGEX_INSTREAM_ID))) { if ("CC1".equals(parseOptionalStringAttr(line, REGEX_INSTREAM_ID))) {
muxedCaptionFormat = Format.createTextContainerFormat(name, muxedCaptionFormat = Format.createTextContainerFormat(name,
MimeTypes.APPLICATION_M3U8, MimeTypes.APPLICATION_EIA608, null, Format.NO_VALUE, MimeTypes.APPLICATION_M3U8, MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE,
selectionFlags, language); selectionFlags, language);
} }
break; break;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
package com.google.android.exoplayer2.text; package com.google.android.exoplayer2.text;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.text.eia608.Eia608Decoder; import com.google.android.exoplayer2.text.cea.Cea608Decoder;
import com.google.android.exoplayer2.text.subrip.SubripDecoder; import com.google.android.exoplayer2.text.subrip.SubripDecoder;
import com.google.android.exoplayer2.text.ttml.TtmlDecoder; import com.google.android.exoplayer2.text.ttml.TtmlDecoder;
import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder; import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder;
...@@ -57,7 +57,7 @@ public interface SubtitleDecoderFactory { ...@@ -57,7 +57,7 @@ public interface SubtitleDecoderFactory {
* <li>TTML ({@link TtmlDecoder})</li> * <li>TTML ({@link TtmlDecoder})</li>
* <li>SubRip ({@link SubripDecoder})</li> * <li>SubRip ({@link SubripDecoder})</li>
* <li>TX3G ({@link Tx3gDecoder})</li> * <li>TX3G ({@link Tx3gDecoder})</li>
* <li>Eia608 ({@link Eia608Decoder})</li> * <li>Cea608 ({@link Cea608Decoder})</li>
* </ul> * </ul>
*/ */
SubtitleDecoderFactory DEFAULT = new SubtitleDecoderFactory() { SubtitleDecoderFactory DEFAULT = new SubtitleDecoderFactory() {
...@@ -93,8 +93,8 @@ public interface SubtitleDecoderFactory { ...@@ -93,8 +93,8 @@ public interface SubtitleDecoderFactory {
return Class.forName("com.google.android.exoplayer2.text.subrip.SubripDecoder"); return Class.forName("com.google.android.exoplayer2.text.subrip.SubripDecoder");
case MimeTypes.APPLICATION_TX3G: case MimeTypes.APPLICATION_TX3G:
return Class.forName("com.google.android.exoplayer2.text.tx3g.Tx3gDecoder"); return Class.forName("com.google.android.exoplayer2.text.tx3g.Tx3gDecoder");
case MimeTypes.APPLICATION_EIA608: case MimeTypes.APPLICATION_CEA608:
return Class.forName("com.google.android.exoplayer2.text.eia608.Eia608Decoder"); return Class.forName("com.google.android.exoplayer2.text.cea.Cea608Decoder");
default: default:
return null; return null;
} }
......
...@@ -13,28 +13,23 @@ ...@@ -13,28 +13,23 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.text.eia608; package com.google.android.exoplayer2.text.cea;
import android.text.Layout.Alignment; import android.text.Layout.Alignment;
import android.text.TextUtils; import android.text.TextUtils;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.Subtitle;
import com.google.android.exoplayer2.text.SubtitleDecoder; import com.google.android.exoplayer2.text.SubtitleDecoder;
import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.text.SubtitleInputBuffer; import com.google.android.exoplayer2.text.SubtitleInputBuffer;
import com.google.android.exoplayer2.text.SubtitleOutputBuffer;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import java.util.LinkedList;
import java.util.TreeSet;
/** /**
* A {@link SubtitleDecoder} for EIA-608 (also known as "line 21 captions" and "CEA-608"). * A {@link SubtitleDecoder} for CEA-608 (also known as "line 21 captions" and "EIA-608").
*/ */
public final class Eia608Decoder implements SubtitleDecoder { public final class Cea608Decoder extends CeaDecoder {
private static final int NUM_INPUT_BUFFERS = 10; private static final int NTSC_CC_FIELD_1 = 0x00;
private static final int NUM_OUTPUT_BUFFERS = 2; private static final int CC_VALID_FLAG = 0x04;
private static final int PAYLOAD_TYPE_CC = 4; private static final int PAYLOAD_TYPE_CC = 4;
private static final int COUNTRY_CODE = 0xB5; private static final int COUNTRY_CODE = 0xB5;
...@@ -169,18 +164,10 @@ public final class Eia608Decoder implements SubtitleDecoder { ...@@ -169,18 +164,10 @@ public final class Eia608Decoder implements SubtitleDecoder {
private static final int CUE_POSITION_ANCHOR = Cue.TYPE_UNSET; private static final int CUE_POSITION_ANCHOR = Cue.TYPE_UNSET;
private static final float CUE_SIZE = 0.8f; private static final float CUE_SIZE = 0.8f;
private final LinkedList<SubtitleInputBuffer> availableInputBuffers;
private final LinkedList<SubtitleOutputBuffer> availableOutputBuffers;
private final TreeSet<SubtitleInputBuffer> queuedInputBuffers;
private final ParsableByteArray ccData; private final ParsableByteArray ccData;
private final StringBuilder captionStringBuilder; private final StringBuilder captionStringBuilder;
private long playbackPositionUs;
private SubtitleInputBuffer dequeuedInputBuffer;
private int captionMode; private int captionMode;
private int captionRowCount; private int captionRowCount;
private String captionString; private String captionString;
...@@ -191,17 +178,7 @@ public final class Eia608Decoder implements SubtitleDecoder { ...@@ -191,17 +178,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
private byte repeatableControlCc1; private byte repeatableControlCc1;
private byte repeatableControlCc2; private byte repeatableControlCc2;
public Eia608Decoder() { public Cea608Decoder() {
availableInputBuffers = new LinkedList<>();
for (int i = 0; i < NUM_INPUT_BUFFERS; i++) {
availableInputBuffers.add(new SubtitleInputBuffer());
}
availableOutputBuffers = new LinkedList<>();
for (int i = 0; i < NUM_OUTPUT_BUFFERS; i++) {
availableOutputBuffers.add(new Eia608SubtitleOutputBuffer(this));
}
queuedInputBuffers = new TreeSet<>();
ccData = new ParsableByteArray(); ccData = new ParsableByteArray();
captionStringBuilder = new StringBuilder(); captionStringBuilder = new StringBuilder();
...@@ -212,106 +189,20 @@ public final class Eia608Decoder implements SubtitleDecoder { ...@@ -212,106 +189,20 @@ public final class Eia608Decoder implements SubtitleDecoder {
@Override @Override
public String getName() { public String getName() {
return "Eia608Decoder"; return "Cea608Decoder";
}
@Override
public void setPositionUs(long positionUs) {
playbackPositionUs = positionUs;
}
@Override
public SubtitleInputBuffer dequeueInputBuffer() throws SubtitleDecoderException {
Assertions.checkState(dequeuedInputBuffer == null);
if (availableInputBuffers.isEmpty()) {
return null;
}
dequeuedInputBuffer = availableInputBuffers.pollFirst();
return dequeuedInputBuffer;
}
@Override
public void queueInputBuffer(SubtitleInputBuffer inputBuffer) throws SubtitleDecoderException {
Assertions.checkArgument(inputBuffer != null);
Assertions.checkArgument(inputBuffer == dequeuedInputBuffer);
queuedInputBuffers.add(inputBuffer);
dequeuedInputBuffer = null;
}
@Override
public SubtitleOutputBuffer dequeueOutputBuffer() throws SubtitleDecoderException {
if (availableOutputBuffers.isEmpty()) {
return null;
}
// iterate through all available input buffers whose timestamps are less than or equal
// to the current playback position; processing input buffers for future content should
// be deferred until they would be applicable
while (!queuedInputBuffers.isEmpty()
&& queuedInputBuffers.first().timeUs <= playbackPositionUs) {
SubtitleInputBuffer inputBuffer = queuedInputBuffers.pollFirst();
// If the input buffer indicates we've reached the end of the stream, we can
// return immediately with an output buffer propagating that
if (inputBuffer.isEndOfStream()) {
SubtitleOutputBuffer outputBuffer = availableOutputBuffers.pollFirst();
outputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
releaseInputBuffer(inputBuffer);
return outputBuffer;
}
decode(inputBuffer);
// check if we have any caption updates to report
if (!TextUtils.equals(captionString, lastCaptionString)) {
lastCaptionString = captionString;
if (!inputBuffer.isDecodeOnly()) {
Cue cue = null;
if (!TextUtils.isEmpty(captionString)) {
cue = new Cue(captionString, CUE_TEXT_ALIGNMENT, CUE_LINE, CUE_LINE_TYPE,
CUE_LINE_ANCHOR, CUE_POSITION, CUE_POSITION_ANCHOR, CUE_SIZE);
}
SubtitleOutputBuffer outputBuffer = availableOutputBuffers.pollFirst();
outputBuffer.setContent(inputBuffer.timeUs, new Eia608Subtitle(cue), 0);
releaseInputBuffer(inputBuffer);
return outputBuffer;
}
}
releaseInputBuffer(inputBuffer);
}
return null;
}
private void releaseInputBuffer(SubtitleInputBuffer inputBuffer) {
inputBuffer.clear();
availableInputBuffers.add(inputBuffer);
}
protected void releaseOutputBuffer(SubtitleOutputBuffer outputBuffer) {
outputBuffer.clear();
availableOutputBuffers.add(outputBuffer);
} }
@Override @Override
public void flush() { public void flush() {
super.flush();
setCaptionMode(CC_MODE_UNKNOWN); setCaptionMode(CC_MODE_UNKNOWN);
captionRowCount = DEFAULT_CAPTIONS_ROW_COUNT; captionRowCount = DEFAULT_CAPTIONS_ROW_COUNT;
playbackPositionUs = 0;
captionStringBuilder.setLength(0); captionStringBuilder.setLength(0);
captionString = null; captionString = null;
lastCaptionString = null; lastCaptionString = null;
repeatableControlSet = false; repeatableControlSet = false;
repeatableControlCc1 = 0; repeatableControlCc1 = 0;
repeatableControlCc2 = 0; repeatableControlCc2 = 0;
while (!queuedInputBuffers.isEmpty()) {
releaseInputBuffer(queuedInputBuffers.pollFirst());
}
if (dequeuedInputBuffer != null) {
releaseInputBuffer(dequeuedInputBuffer);
dequeuedInputBuffer = null;
}
} }
@Override @Override
...@@ -319,14 +210,34 @@ public final class Eia608Decoder implements SubtitleDecoder { ...@@ -319,14 +210,34 @@ public final class Eia608Decoder implements SubtitleDecoder {
// Do nothing // Do nothing
} }
private void decode(SubtitleInputBuffer inputBuffer) { @Override
protected boolean isNewSubtitleDataAvailable() {
return !TextUtils.equals(captionString, lastCaptionString);
}
@Override
protected Subtitle createSubtitle() {
lastCaptionString = captionString;
return new CeaSubtitle(new Cue(captionString, CUE_TEXT_ALIGNMENT, CUE_LINE, CUE_LINE_TYPE,
CUE_LINE_ANCHOR, CUE_POSITION, CUE_POSITION_ANCHOR, CUE_SIZE));
}
@Override
protected void decode(SubtitleInputBuffer inputBuffer) {
ccData.reset(inputBuffer.data.array(), inputBuffer.data.limit()); ccData.reset(inputBuffer.data.array(), inputBuffer.data.limit());
boolean captionDataProcessed = false; boolean captionDataProcessed = false;
boolean isRepeatableControl = false; boolean isRepeatableControl = false;
while (ccData.bytesLeft() > 0) { while (ccData.bytesLeft() > 0) {
byte ccTypeAndValid = (byte) (ccData.readUnsignedByte() & 0x07);
byte ccData1 = (byte) (ccData.readUnsignedByte() & 0x7F); byte ccData1 = (byte) (ccData.readUnsignedByte() & 0x7F);
byte ccData2 = (byte) (ccData.readUnsignedByte() & 0x7F); byte ccData2 = (byte) (ccData.readUnsignedByte() & 0x7F);
// Only examine valid NTSC_CC_FIELD_1 packets
if (ccTypeAndValid != (CC_VALID_FLAG | NTSC_CC_FIELD_1)) {
// TODO: Add support for NTSC_CC_FIELD_2 packets
continue;
}
// Ignore empty captions. // Ignore empty captions.
if (ccData1 == 0 && ccData2 == 0) { if (ccData1 == 0 && ccData2 == 0) {
continue; continue;
...@@ -550,16 +461,16 @@ public final class Eia608Decoder implements SubtitleDecoder { ...@@ -550,16 +461,16 @@ public final class Eia608Decoder implements SubtitleDecoder {
} }
/** /**
* Inspects an sei message to determine whether it contains EIA-608. * Inspects an sei message to determine whether it contains CEA-608.
* <p> * <p>
* The position of {@code payload} is left unchanged. * The position of {@code payload} is left unchanged.
* *
* @param payloadType The payload type of the message. * @param payloadType The payload type of the message.
* @param payloadLength The length of the payload. * @param payloadLength The length of the payload.
* @param payload A {@link ParsableByteArray} containing the payload. * @param payload A {@link ParsableByteArray} containing the payload.
* @return Whether the sei message contains EIA-608. * @return Whether the sei message contains CEA-608.
*/ */
public static boolean isSeiMessageEia608(int payloadType, int payloadLength, public static boolean isSeiMessageCea608(int payloadType, int payloadLength,
ParsableByteArray payload) { ParsableByteArray payload) {
if (payloadType != PAYLOAD_TYPE_CC || payloadLength < 8) { if (payloadType != PAYLOAD_TYPE_CC || payloadLength < 8) {
return false; return false;
......
/*
* Copyright (C) 2016 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.cea;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.text.Subtitle;
import com.google.android.exoplayer2.text.SubtitleDecoder;
import com.google.android.exoplayer2.text.SubtitleDecoderException;
import com.google.android.exoplayer2.text.SubtitleInputBuffer;
import com.google.android.exoplayer2.text.SubtitleOutputBuffer;
import com.google.android.exoplayer2.util.Assertions;
import java.util.LinkedList;
import java.util.TreeSet;
/**
* Base class for subtitle parsers for CEA captions.
*/
/* package */ abstract class CeaDecoder implements SubtitleDecoder {
private static final int NUM_INPUT_BUFFERS = 10;
private static final int NUM_OUTPUT_BUFFERS = 2;
private final LinkedList<SubtitleInputBuffer> availableInputBuffers;
private final LinkedList<SubtitleOutputBuffer> availableOutputBuffers;
private final TreeSet<SubtitleInputBuffer> queuedInputBuffers;
private SubtitleInputBuffer dequeuedInputBuffer;
private long playbackPositionUs;
public CeaDecoder() {
availableInputBuffers = new LinkedList<>();
for (int i = 0; i < NUM_INPUT_BUFFERS; i++) {
availableInputBuffers.add(new SubtitleInputBuffer());
}
availableOutputBuffers = new LinkedList<>();
for (int i = 0; i < NUM_OUTPUT_BUFFERS; i++) {
availableOutputBuffers.add(new CeaOutputBuffer(this));
}
queuedInputBuffers = new TreeSet<>();
}
@Override
public abstract String getName();
@Override
public void setPositionUs(long positionUs) {
playbackPositionUs = positionUs;
}
@Override
public SubtitleInputBuffer dequeueInputBuffer() throws SubtitleDecoderException {
Assertions.checkState(dequeuedInputBuffer == null);
if (availableInputBuffers.isEmpty()) {
return null;
}
dequeuedInputBuffer = availableInputBuffers.pollFirst();
return dequeuedInputBuffer;
}
@Override
public void queueInputBuffer(SubtitleInputBuffer inputBuffer) throws SubtitleDecoderException {
Assertions.checkArgument(inputBuffer != null);
Assertions.checkArgument(inputBuffer == dequeuedInputBuffer);
queuedInputBuffers.add(inputBuffer);
dequeuedInputBuffer = null;
}
@Override
public SubtitleOutputBuffer dequeueOutputBuffer() throws SubtitleDecoderException {
if (availableOutputBuffers.isEmpty()) {
return null;
}
// iterate through all available input buffers whose timestamps are less than or equal
// to the current playback position; processing input buffers for future content should
// be deferred until they would be applicable
while (!queuedInputBuffers.isEmpty()
&& queuedInputBuffers.first().timeUs <= playbackPositionUs) {
SubtitleInputBuffer inputBuffer = queuedInputBuffers.pollFirst();
// If the input buffer indicates we've reached the end of the stream, we can
// return immediately with an output buffer propagating that
if (inputBuffer.isEndOfStream()) {
SubtitleOutputBuffer outputBuffer = availableOutputBuffers.pollFirst();
outputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
releaseInputBuffer(inputBuffer);
return outputBuffer;
}
decode(inputBuffer);
// check if we have any caption updates to report
if (isNewSubtitleDataAvailable()) {
// Even if the subtitle is decode-only; we need to generate it to consume the data so it
// isn't accidentally prepended to the next subtitle
Subtitle subtitle = createSubtitle();
if (!inputBuffer.isDecodeOnly()) {
SubtitleOutputBuffer outputBuffer = availableOutputBuffers.pollFirst();
outputBuffer.setContent(inputBuffer.timeUs, subtitle, 0);
releaseInputBuffer(inputBuffer);
return outputBuffer;
}
}
releaseInputBuffer(inputBuffer);
}
return null;
}
private void releaseInputBuffer(SubtitleInputBuffer inputBuffer) {
inputBuffer.clear();
availableInputBuffers.add(inputBuffer);
}
protected void releaseOutputBuffer(SubtitleOutputBuffer outputBuffer) {
outputBuffer.clear();
availableOutputBuffers.add(outputBuffer);
}
@Override
public void flush() {
playbackPositionUs = 0;
while (!queuedInputBuffers.isEmpty()) {
releaseInputBuffer(queuedInputBuffers.pollFirst());
}
if (dequeuedInputBuffer != null) {
releaseInputBuffer(dequeuedInputBuffer);
dequeuedInputBuffer = null;
}
}
@Override
public void release() {
// Do nothing
}
/**
* Returns whether there is data available to create a new {@link Subtitle}.
*/
protected abstract boolean isNewSubtitleDataAvailable();
/**
* Creates a {@link Subtitle} from the available data.
*/
protected abstract Subtitle createSubtitle();
/**
* Filters and processes the raw data, providing {@link Subtitle}s via {@link #createSubtitle()}
* when sufficient data has been processed.
*/
protected abstract void decode(SubtitleInputBuffer inputBuffer);
}
...@@ -13,22 +13,21 @@ ...@@ -13,22 +13,21 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.text.eia608; package com.google.android.exoplayer2.text.cea;
import com.google.android.exoplayer2.text.Subtitle;
import com.google.android.exoplayer2.text.SubtitleOutputBuffer; import com.google.android.exoplayer2.text.SubtitleOutputBuffer;
/** /**
* A {@link Subtitle} output from an {@link Eia608Decoder}. * A {@link SubtitleOutputBuffer} for {@link CeaDecoder}s.
*/ */
/* package */ final class Eia608SubtitleOutputBuffer extends SubtitleOutputBuffer { public final class CeaOutputBuffer extends SubtitleOutputBuffer {
private Eia608Decoder owner; private final CeaDecoder owner;
/** /**
* @param owner The decoder that owns this buffer. * @param owner The decoder that owns this buffer.
*/ */
public Eia608SubtitleOutputBuffer(Eia608Decoder owner) { public CeaOutputBuffer(CeaDecoder owner) {
super(); super();
this.owner = owner; this.owner = owner;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.text.eia608; package com.google.android.exoplayer2.text.cea;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.Subtitle; import com.google.android.exoplayer2.text.Subtitle;
...@@ -21,16 +21,16 @@ import java.util.Collections; ...@@ -21,16 +21,16 @@ import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* A representation of an EIA-608 subtitle. * A representation of a CEA subtitle.
*/ */
/* package */ final class Eia608Subtitle implements Subtitle { /* package */ final class CeaSubtitle implements Subtitle {
private final List<Cue> cues; private final List<Cue> cues;
/** /**
* @param cue The subtitle cue. * @param cue The subtitle cue.
*/ */
public Eia608Subtitle(Cue cue) { public CeaSubtitle(Cue cue) {
if (cue == null) { if (cue == null) {
cues = Collections.emptyList(); cues = Collections.emptyList();
} else { } else {
......
...@@ -64,7 +64,7 @@ public final class MimeTypes { ...@@ -64,7 +64,7 @@ public final class MimeTypes {
public static final String APPLICATION_MP4 = BASE_TYPE_APPLICATION + "/mp4"; public static final String APPLICATION_MP4 = BASE_TYPE_APPLICATION + "/mp4";
public static final String APPLICATION_WEBM = BASE_TYPE_APPLICATION + "/webm"; public static final String APPLICATION_WEBM = BASE_TYPE_APPLICATION + "/webm";
public static final String APPLICATION_ID3 = BASE_TYPE_APPLICATION + "/id3"; public static final String APPLICATION_ID3 = BASE_TYPE_APPLICATION + "/id3";
public static final String APPLICATION_EIA608 = BASE_TYPE_APPLICATION + "/eia-608"; public static final String APPLICATION_CEA608 = BASE_TYPE_APPLICATION + "/cea-608";
public static final String APPLICATION_SUBRIP = BASE_TYPE_APPLICATION + "/x-subrip"; public static final String APPLICATION_SUBRIP = BASE_TYPE_APPLICATION + "/x-subrip";
public static final String APPLICATION_TTML = BASE_TYPE_APPLICATION + "/ttml+xml"; public static final String APPLICATION_TTML = BASE_TYPE_APPLICATION + "/ttml+xml";
public static final String APPLICATION_M3U8 = BASE_TYPE_APPLICATION + "/x-mpegURL"; public static final String APPLICATION_M3U8 = BASE_TYPE_APPLICATION + "/x-mpegURL";
...@@ -209,7 +209,7 @@ public final class MimeTypes { ...@@ -209,7 +209,7 @@ public final class MimeTypes {
return C.TRACK_TYPE_AUDIO; return C.TRACK_TYPE_AUDIO;
} else if (isVideo(mimeType)) { } else if (isVideo(mimeType)) {
return C.TRACK_TYPE_VIDEO; return C.TRACK_TYPE_VIDEO;
} else if (isText(mimeType) || APPLICATION_EIA608.equals(mimeType) } else if (isText(mimeType) || APPLICATION_CEA608.equals(mimeType)
|| APPLICATION_SUBRIP.equals(mimeType) || APPLICATION_TTML.equals(mimeType) || APPLICATION_SUBRIP.equals(mimeType) || APPLICATION_TTML.equals(mimeType)
|| APPLICATION_TX3G.equals(mimeType) || APPLICATION_MP4VTT.equals(mimeType) || APPLICATION_TX3G.equals(mimeType) || APPLICATION_MP4VTT.equals(mimeType)
|| APPLICATION_RAWCC.equals(mimeType) || APPLICATION_VOBSUB.equals(mimeType) || APPLICATION_RAWCC.equals(mimeType) || APPLICATION_VOBSUB.equals(mimeType)
......
...@@ -195,6 +195,13 @@ public final class ParsableByteArray { ...@@ -195,6 +195,13 @@ public final class ParsableByteArray {
} }
/** /**
* Peeks at the next byte as an unsigned value.
*/
public int peekUnsignedByte() {
return (data[position] & 0xFF);
}
/**
* Reads the next byte as an unsigned value. * Reads the next byte as an unsigned value.
*/ */
public int readUnsignedByte() { public int readUnsignedByte() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment