mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
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
This commit is contained in:
parent
825ec70d31
commit
040fe3b194
@ -8,7 +8,7 @@ track 0:
|
||||
bitrate = -1
|
||||
id = null
|
||||
containerMimeType = null
|
||||
sampleMimeType = application/eia-608
|
||||
sampleMimeType = application/cea-608
|
||||
maxInputSize = -1
|
||||
width = -1
|
||||
height = -1
|
||||
@ -25,305 +25,605 @@ track 0:
|
||||
language = null
|
||||
drmInitData = -
|
||||
initializationData:
|
||||
sample count = 75
|
||||
sample count = 150
|
||||
sample 0:
|
||||
time = 37657512133
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
data = length 3, hash 7363
|
||||
sample 1:
|
||||
time = 37657528822
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 2:
|
||||
time = 37657545511
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 2:
|
||||
data = length 3, hash 766F
|
||||
sample 3:
|
||||
time = 37657562177
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 4:
|
||||
time = 37657578866
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6DC
|
||||
sample 3:
|
||||
data = length 3, hash 767E
|
||||
sample 5:
|
||||
time = 37657595555
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 6:
|
||||
time = 37657612244
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF65B
|
||||
sample 4:
|
||||
data = length 15, hash E4359178
|
||||
sample 7:
|
||||
time = 37657628911
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 8:
|
||||
time = 37657645600
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 5:
|
||||
data = length 12, hash 15EBEB66
|
||||
sample 9:
|
||||
time = 37657662288
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 10:
|
||||
time = 37657678977
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF67B
|
||||
sample 6:
|
||||
data = length 3, hash 761D
|
||||
sample 11:
|
||||
time = 37657695644
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 12:
|
||||
time = 37657712333
|
||||
flags = 1
|
||||
data = length 2, hash 2B5
|
||||
sample 7:
|
||||
data = length 30, hash E181418F
|
||||
sample 13:
|
||||
time = 37657729022
|
||||
flags = 1
|
||||
data = length 6, hash 36289CE2
|
||||
sample 14:
|
||||
time = 37657745711
|
||||
flags = 1
|
||||
data = length 2, hash F5
|
||||
sample 8:
|
||||
data = length 12, hash 3C304F5B
|
||||
sample 15:
|
||||
time = 37657762377
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 16:
|
||||
time = 37657779066
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF87A
|
||||
sample 9:
|
||||
data = length 12, hash 88DD8EF6
|
||||
sample 17:
|
||||
time = 37657795755
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 18:
|
||||
time = 37657812444
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF698
|
||||
sample 10:
|
||||
data = length 12, hash 8B411833
|
||||
sample 19:
|
||||
time = 37657829111
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 20:
|
||||
time = 37657845800
|
||||
flags = 1
|
||||
data = length 2, hash 1F4
|
||||
sample 11:
|
||||
data = length 12, hash 742A2DF1
|
||||
sample 21:
|
||||
time = 37657862488
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 22:
|
||||
time = 37657879177
|
||||
flags = 1
|
||||
data = length 2, hash 803
|
||||
sample 12:
|
||||
data = length 12, hash 9A2ECBEE
|
||||
sample 23:
|
||||
time = 37657895844
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 24:
|
||||
time = 37657912533
|
||||
flags = 1
|
||||
data = length 2, hash 1F8
|
||||
sample 13:
|
||||
data = length 12, hash 562688EA
|
||||
sample 25:
|
||||
time = 37657929222
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 26:
|
||||
time = 37657945911
|
||||
flags = 1
|
||||
data = length 2, hash 117A
|
||||
sample 14:
|
||||
data = length 12, hash ADE4B953
|
||||
sample 27:
|
||||
time = 37657962577
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 28:
|
||||
time = 37657979266
|
||||
flags = 1
|
||||
data = length 2, hash 166
|
||||
sample 15:
|
||||
data = length 12, hash F927E3E5
|
||||
sample 29:
|
||||
time = 37657995955
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 30:
|
||||
time = 37658012644
|
||||
flags = 1
|
||||
data = length 2, hash 105A
|
||||
sample 16:
|
||||
data = length 12, hash EA327945
|
||||
sample 31:
|
||||
time = 37658029311
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 32:
|
||||
time = 37658046000
|
||||
flags = 1
|
||||
data = length 2, hash FCF
|
||||
sample 17:
|
||||
data = length 12, hash 3E5DA13C
|
||||
sample 33:
|
||||
time = 37658062688
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 34:
|
||||
time = 37658079377
|
||||
flags = 1
|
||||
data = length 2, hash 1253
|
||||
sample 18:
|
||||
data = length 12, hash BF646AE3
|
||||
sample 35:
|
||||
time = 37658096044
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 36:
|
||||
time = 37658112733
|
||||
flags = 1
|
||||
data = length 2, hash 11DA
|
||||
sample 19:
|
||||
data = length 12, hash 41E3BA78
|
||||
sample 37:
|
||||
time = 37658129422
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 38:
|
||||
time = 37658146111
|
||||
flags = 1
|
||||
data = length 2, hash 795
|
||||
sample 20:
|
||||
data = length 12, hash A2945EF6
|
||||
sample 39:
|
||||
time = 37658162777
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 40:
|
||||
time = 37658179466
|
||||
flags = 1
|
||||
data = length 2, hash 103E
|
||||
sample 21:
|
||||
data = length 12, hash 26735812
|
||||
sample 41:
|
||||
time = 37658196155
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 42:
|
||||
time = 37658212844
|
||||
flags = 1
|
||||
data = length 2, hash 120F
|
||||
sample 22:
|
||||
data = length 12, hash DC14D3D8
|
||||
sample 43:
|
||||
time = 37658229511
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 44:
|
||||
time = 37658246200
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF698
|
||||
sample 23:
|
||||
data = length 12, hash 882191BE
|
||||
sample 45:
|
||||
time = 37658262888
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 46:
|
||||
time = 37658279577
|
||||
flags = 1
|
||||
data = length 2, hash 1F4
|
||||
sample 24:
|
||||
data = length 12, hash 8B4886B1
|
||||
sample 47:
|
||||
time = 37658296244
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 48:
|
||||
time = 37658312933
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF71B
|
||||
sample 25:
|
||||
data = length 12, hash 98D98F96
|
||||
sample 49:
|
||||
time = 37658329622
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 50:
|
||||
time = 37658346311
|
||||
flags = 1
|
||||
data = length 2, hash F91
|
||||
sample 26:
|
||||
data = length 30, hash CF8E53E3
|
||||
sample 51:
|
||||
time = 37658362977
|
||||
flags = 1
|
||||
data = length 6, hash 36289CE2
|
||||
sample 52:
|
||||
time = 37658379666
|
||||
flags = 1
|
||||
data = length 2, hash 166
|
||||
sample 27:
|
||||
data = length 12, hash F883C9EE
|
||||
sample 53:
|
||||
time = 37658396355
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 54:
|
||||
time = 37658413044
|
||||
flags = 1
|
||||
data = length 2, hash 1023
|
||||
sample 28:
|
||||
data = length 12, hash 6E6B2B9C
|
||||
sample 55:
|
||||
time = 37658429711
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 56:
|
||||
time = 37658446400
|
||||
flags = 1
|
||||
data = length 2, hash 117A
|
||||
sample 29:
|
||||
data = length 12, hash B4FE7F08
|
||||
sample 57:
|
||||
time = 37658463088
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 58:
|
||||
time = 37658479777
|
||||
flags = 1
|
||||
data = length 2, hash 784
|
||||
sample 30:
|
||||
data = length 12, hash 5A1EA7C7
|
||||
sample 59:
|
||||
time = 37658496444
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 60:
|
||||
time = 37658513133
|
||||
flags = 1
|
||||
data = length 2, hash 1F8
|
||||
sample 31:
|
||||
data = length 12, hash 46BD6CC9
|
||||
sample 61:
|
||||
time = 37658529822
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 62:
|
||||
time = 37658546511
|
||||
flags = 1
|
||||
data = length 2, hash 10D9
|
||||
sample 32:
|
||||
data = length 12, hash 1B1E2554
|
||||
sample 63:
|
||||
time = 37658563177
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 64:
|
||||
time = 37658579866
|
||||
flags = 1
|
||||
data = length 2, hash 935
|
||||
sample 33:
|
||||
data = length 12, hash 91FCC537
|
||||
sample 65:
|
||||
time = 37658596555
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 66:
|
||||
time = 37658613244
|
||||
flags = 1
|
||||
data = length 2, hash 2B5
|
||||
sample 34:
|
||||
data = length 12, hash A9355E1B
|
||||
sample 67:
|
||||
time = 37658629911
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 68:
|
||||
time = 37658646600
|
||||
flags = 1
|
||||
data = length 2, hash F5
|
||||
sample 35:
|
||||
data = length 12, hash 2511F69B
|
||||
sample 69:
|
||||
time = 37658663288
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 70:
|
||||
time = 37658679977
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF87A
|
||||
sample 36:
|
||||
data = length 12, hash 90925736
|
||||
sample 71:
|
||||
time = 37658696644
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 72:
|
||||
time = 37658713333
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF698
|
||||
sample 37:
|
||||
data = length 21, hash 431EEE30
|
||||
sample 73:
|
||||
time = 37658730022
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 74:
|
||||
time = 37658746711
|
||||
flags = 1
|
||||
data = length 2, hash 1F4
|
||||
sample 38:
|
||||
data = length 12, hash 7BDEF631
|
||||
sample 75:
|
||||
time = 37658763377
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 76:
|
||||
time = 37658780066
|
||||
flags = 1
|
||||
data = length 2, hash 793
|
||||
sample 39:
|
||||
data = length 12, hash A2EEF59E
|
||||
sample 77:
|
||||
time = 37658796755
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 78:
|
||||
time = 37658813444
|
||||
flags = 1
|
||||
data = length 2, hash FF0
|
||||
sample 40:
|
||||
data = length 12, hash BFC6C022
|
||||
sample 79:
|
||||
time = 37658830111
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 80:
|
||||
time = 37658846800
|
||||
flags = 1
|
||||
data = length 2, hash 16B
|
||||
sample 41:
|
||||
data = length 12, hash CD4D8FCA
|
||||
sample 81:
|
||||
time = 37658863488
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 82:
|
||||
time = 37658880177
|
||||
flags = 1
|
||||
data = length 2, hash 2C0
|
||||
sample 42:
|
||||
data = length 12, hash 2BDE8EFA
|
||||
sample 83:
|
||||
time = 37658896844
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 84:
|
||||
time = 37658913533
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF953
|
||||
sample 43:
|
||||
data = length 12, hash 8C858812
|
||||
sample 85:
|
||||
time = 37658930222
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 86:
|
||||
time = 37658946911
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 44:
|
||||
data = length 12, hash DE7D0E31
|
||||
sample 87:
|
||||
time = 37658963577
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 88:
|
||||
time = 37658980266
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 45:
|
||||
data = length 3, hash 7363
|
||||
sample 89:
|
||||
time = 37658996955
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 90:
|
||||
time = 37659013644
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 46:
|
||||
data = length 3, hash 7363
|
||||
sample 91:
|
||||
time = 37659030311
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 92:
|
||||
time = 37659047000
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 47:
|
||||
data = length 3, hash 7363
|
||||
sample 93:
|
||||
time = 37659063688
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 94:
|
||||
time = 37659080377
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 48:
|
||||
data = length 3, hash 7363
|
||||
sample 95:
|
||||
time = 37659097044
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 96:
|
||||
time = 37659113733
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 49:
|
||||
data = length 3, hash 7363
|
||||
sample 97:
|
||||
time = 37659130422
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 98:
|
||||
time = 37659147111
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 50:
|
||||
data = length 3, hash 7363
|
||||
sample 99:
|
||||
time = 37659163777
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 100:
|
||||
time = 37659180466
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 51:
|
||||
data = length 3, hash 7363
|
||||
sample 101:
|
||||
time = 37659197155
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 102:
|
||||
time = 37659213844
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 52:
|
||||
data = length 3, hash 7363
|
||||
sample 103:
|
||||
time = 37659230511
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 104:
|
||||
time = 37659247200
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 53:
|
||||
data = length 3, hash 7363
|
||||
sample 105:
|
||||
time = 37659263888
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 106:
|
||||
time = 37659280577
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 54:
|
||||
data = length 3, hash 7363
|
||||
sample 107:
|
||||
time = 37659297244
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 108:
|
||||
time = 37659313933
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 55:
|
||||
data = length 3, hash 7363
|
||||
sample 109:
|
||||
time = 37659330622
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 110:
|
||||
time = 37659347311
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 56:
|
||||
data = length 3, hash 7363
|
||||
sample 111:
|
||||
time = 37659363977
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 112:
|
||||
time = 37659380666
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 57:
|
||||
data = length 3, hash 7363
|
||||
sample 113:
|
||||
time = 37659397355
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 114:
|
||||
time = 37659414044
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 58:
|
||||
data = length 3, hash 7363
|
||||
sample 115:
|
||||
time = 37659430711
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 116:
|
||||
time = 37659447400
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 59:
|
||||
data = length 3, hash 7363
|
||||
sample 117:
|
||||
time = 37659464088
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 118:
|
||||
time = 37659480777
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 60:
|
||||
data = length 3, hash 7363
|
||||
sample 119:
|
||||
time = 37659497444
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 120:
|
||||
time = 37659514133
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 61:
|
||||
data = length 3, hash 7363
|
||||
sample 121:
|
||||
time = 37659530822
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 122:
|
||||
time = 37659547511
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 62:
|
||||
data = length 3, hash 7363
|
||||
sample 123:
|
||||
time = 37659564177
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 124:
|
||||
time = 37659580866
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF3C1
|
||||
sample 63:
|
||||
data = length 3, hash 7363
|
||||
sample 125:
|
||||
time = 37659597555
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 126:
|
||||
time = 37659614244
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 64:
|
||||
data = length 3, hash 766F
|
||||
sample 127:
|
||||
time = 37659630911
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 128:
|
||||
time = 37659647600
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6DC
|
||||
sample 65:
|
||||
data = length 3, hash 767E
|
||||
sample 129:
|
||||
time = 37659664288
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 130:
|
||||
time = 37659680977
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF65B
|
||||
sample 66:
|
||||
data = length 15, hash 191B585A
|
||||
sample 131:
|
||||
time = 37659697644
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 132:
|
||||
time = 37659714333
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6CD
|
||||
sample 67:
|
||||
data = length 12, hash 15EC5FC5
|
||||
sample 133:
|
||||
time = 37659731022
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 134:
|
||||
time = 37659747711
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6FF
|
||||
sample 68:
|
||||
data = length 3, hash 76A1
|
||||
sample 135:
|
||||
time = 37659764377
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 136:
|
||||
time = 37659781066
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF6AC
|
||||
sample 69:
|
||||
data = length 30, hash E8012479
|
||||
sample 137:
|
||||
time = 37659797755
|
||||
flags = 1
|
||||
data = length 6, hash 36289D5E
|
||||
sample 138:
|
||||
time = 37659814444
|
||||
flags = 1
|
||||
data = length 2, hash FFFFF5FE
|
||||
sample 70:
|
||||
data = length 12, hash D32F29F3
|
||||
sample 139:
|
||||
time = 37659831111
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 140:
|
||||
time = 37659847800
|
||||
flags = 1
|
||||
data = length 2, hash FFFFFEF7
|
||||
sample 71:
|
||||
data = length 21, hash 6258623
|
||||
sample 141:
|
||||
time = 37659864488
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 142:
|
||||
time = 37659881177
|
||||
flags = 1
|
||||
data = length 2, hash 120C
|
||||
sample 72:
|
||||
data = length 12, hash FE69ABA2
|
||||
sample 143:
|
||||
time = 37659897844
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 144:
|
||||
time = 37659914533
|
||||
flags = 1
|
||||
data = length 2, hash 1124
|
||||
sample 73:
|
||||
data = length 12, hash 958D0815
|
||||
sample 145:
|
||||
time = 37659931222
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 146:
|
||||
time = 37659947911
|
||||
flags = 1
|
||||
data = length 2, hash 1A9
|
||||
sample 74:
|
||||
data = length 12, hash FF57BFD8
|
||||
sample 147:
|
||||
time = 37659964577
|
||||
flags = 1
|
||||
data = length 3, hash 7724
|
||||
sample 148:
|
||||
time = 37659981266
|
||||
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
|
||||
|
@ -644,7 +644,7 @@ import java.util.List;
|
||||
0 /* subsample timing is absolute */);
|
||||
} else if (childAtomType == Atom.TYPE_c608) {
|
||||
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;
|
||||
}
|
||||
stsd.setPosition(childStartPosition + childAtomSize);
|
||||
|
@ -30,7 +30,7 @@ import com.google.android.exoplayer2.util.Util;
|
||||
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 {
|
||||
|
||||
@ -68,7 +68,7 @@ public final class RawCcExtractor implements Extractor {
|
||||
trackOutput = extractorOutput.track(0);
|
||||
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));
|
||||
}
|
||||
|
||||
@ -154,13 +154,8 @@ public final class RawCcExtractor implements Extractor {
|
||||
dataScratch.reset();
|
||||
input.readFully(dataScratch.data, 0, 3);
|
||||
|
||||
// only accept EIA-608 packets which have validity (6th bit) == 1 and
|
||||
// type (7-8th bits) == 0; i.e. ccDataPkt[0] == 0bXXXXX100
|
||||
int ccValidityAndType = dataScratch.readUnsignedByte() & 0x07;
|
||||
if (ccValidityAndType == 0x04) {
|
||||
trackOutput.sampleData(dataScratch, 2);
|
||||
sampleBytesWritten += 2;
|
||||
}
|
||||
trackOutput.sampleData(dataScratch, 3);
|
||||
sampleBytesWritten += 3;
|
||||
}
|
||||
|
||||
if (sampleBytesWritten > 0) {
|
||||
|
@ -57,7 +57,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @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
|
||||
* synchronization samples (key-frames).
|
||||
* @param detectAccessUnits Whether to split the input stream into access units (samples) based on
|
||||
|
@ -64,7 +64,7 @@ import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
super(output);
|
||||
|
@ -18,12 +18,12 @@ 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.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.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 {
|
||||
|
||||
@ -31,7 +31,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
|
||||
public SeiReader(TrackOutput 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));
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
payloadSize += b;
|
||||
} while (b == 0xFF);
|
||||
// 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)
|
||||
// + user_data_type_code (1).
|
||||
seiBuffer.skipBytes(8);
|
||||
@ -60,13 +60,13 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||
seiBuffer.skipBytes(1);
|
||||
int sampleBytes = 0;
|
||||
for (int i = 0; i < ccCount; i++) {
|
||||
int ccValidityAndType = seiBuffer.readUnsignedByte() & 0x07;
|
||||
// Check that validity == 1 and type == 0.
|
||||
int ccValidityAndType = seiBuffer.peekUnsignedByte() & 0x07;
|
||||
// Check that validity == 1 and type == 0 (i.e. NTSC_CC_FIELD_1).
|
||||
if (ccValidityAndType != 0x04) {
|
||||
seiBuffer.skipBytes(2);
|
||||
seiBuffer.skipBytes(3);
|
||||
} else {
|
||||
sampleBytes += 2;
|
||||
output.sampleData(seiBuffer, 2);
|
||||
sampleBytes += 3;
|
||||
output.sampleData(seiBuffer, 3);
|
||||
}
|
||||
}
|
||||
output.sampleMetadata(pesTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytes, 0, null);
|
||||
|
@ -654,9 +654,10 @@ public class DashManifestParser extends DefaultHandler
|
||||
} else if (MimeTypes.isVideo(containerMimeType)) {
|
||||
return MimeTypes.getVideoMediaMimeType(codecs);
|
||||
} else if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
// We currently only support EIA-608 through RawCC
|
||||
if (codecs != null && codecs.contains("eia608")) {
|
||||
return MimeTypes.APPLICATION_EIA608;
|
||||
// We currently only support CEA-608 through RawCC
|
||||
if (codecs != null
|
||||
&& (codecs.contains("eia608") || codecs.contains("cea608"))) {
|
||||
return MimeTypes.APPLICATION_CEA608;
|
||||
}
|
||||
return null;
|
||||
} else if (mimeTypeIsRawText(containerMimeType)) {
|
||||
|
@ -589,7 +589,7 @@ import java.util.LinkedList;
|
||||
if (primaryExtractorTrackType == PRIMARY_TYPE_VIDEO) {
|
||||
if (MimeTypes.isAudio(sampleFormat.sampleMimeType)) {
|
||||
trackFormat = muxedAudioFormat;
|
||||
} else if (MimeTypes.APPLICATION_EIA608.equals(sampleFormat.sampleMimeType)) {
|
||||
} else if (MimeTypes.APPLICATION_CEA608.equals(sampleFormat.sampleMimeType)) {
|
||||
trackFormat = muxedCaptionFormat;
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
case TYPE_CLOSED_CAPTIONS:
|
||||
if ("CC1".equals(parseOptionalStringAttr(line, REGEX_INSTREAM_ID))) {
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
@ -16,7 +16,7 @@
|
||||
package com.google.android.exoplayer2.text;
|
||||
|
||||
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.ttml.TtmlDecoder;
|
||||
import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder;
|
||||
@ -57,7 +57,7 @@ public interface SubtitleDecoderFactory {
|
||||
* <li>TTML ({@link TtmlDecoder})</li>
|
||||
* <li>SubRip ({@link SubripDecoder})</li>
|
||||
* <li>TX3G ({@link Tx3gDecoder})</li>
|
||||
* <li>Eia608 ({@link Eia608Decoder})</li>
|
||||
* <li>Cea608 ({@link Cea608Decoder})</li>
|
||||
* </ul>
|
||||
*/
|
||||
SubtitleDecoderFactory DEFAULT = new SubtitleDecoderFactory() {
|
||||
@ -93,8 +93,8 @@ public interface SubtitleDecoderFactory {
|
||||
return Class.forName("com.google.android.exoplayer2.text.subrip.SubripDecoder");
|
||||
case MimeTypes.APPLICATION_TX3G:
|
||||
return Class.forName("com.google.android.exoplayer2.text.tx3g.Tx3gDecoder");
|
||||
case MimeTypes.APPLICATION_EIA608:
|
||||
return Class.forName("com.google.android.exoplayer2.text.eia608.Eia608Decoder");
|
||||
case MimeTypes.APPLICATION_CEA608:
|
||||
return Class.forName("com.google.android.exoplayer2.text.cea.Cea608Decoder");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -13,28 +13,23 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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.TextUtils;
|
||||
import com.google.android.exoplayer2.C;
|
||||
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.SubtitleDecoderException;
|
||||
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 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 NUM_OUTPUT_BUFFERS = 2;
|
||||
private static final int NTSC_CC_FIELD_1 = 0x00;
|
||||
private static final int CC_VALID_FLAG = 0x04;
|
||||
|
||||
private static final int PAYLOAD_TYPE_CC = 4;
|
||||
private static final int COUNTRY_CODE = 0xB5;
|
||||
@ -169,18 +164,10 @@ public final class Eia608Decoder implements SubtitleDecoder {
|
||||
private static final int CUE_POSITION_ANCHOR = Cue.TYPE_UNSET;
|
||||
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 StringBuilder captionStringBuilder;
|
||||
|
||||
private long playbackPositionUs;
|
||||
|
||||
private SubtitleInputBuffer dequeuedInputBuffer;
|
||||
|
||||
private int captionMode;
|
||||
private int captionRowCount;
|
||||
private String captionString;
|
||||
@ -191,17 +178,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
|
||||
private byte repeatableControlCc1;
|
||||
private byte repeatableControlCc2;
|
||||
|
||||
public Eia608Decoder() {
|
||||
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<>();
|
||||
|
||||
public Cea608Decoder() {
|
||||
ccData = new ParsableByteArray();
|
||||
|
||||
captionStringBuilder = new StringBuilder();
|
||||
@ -212,106 +189,20 @@ public final class Eia608Decoder implements SubtitleDecoder {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Eia608Decoder";
|
||||
}
|
||||
|
||||
@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);
|
||||
return "Cea608Decoder";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
super.flush();
|
||||
setCaptionMode(CC_MODE_UNKNOWN);
|
||||
captionRowCount = DEFAULT_CAPTIONS_ROW_COUNT;
|
||||
playbackPositionUs = 0;
|
||||
captionStringBuilder.setLength(0);
|
||||
captionString = null;
|
||||
lastCaptionString = null;
|
||||
repeatableControlSet = false;
|
||||
repeatableControlCc1 = 0;
|
||||
repeatableControlCc2 = 0;
|
||||
while (!queuedInputBuffers.isEmpty()) {
|
||||
releaseInputBuffer(queuedInputBuffers.pollFirst());
|
||||
}
|
||||
if (dequeuedInputBuffer != null) {
|
||||
releaseInputBuffer(dequeuedInputBuffer);
|
||||
dequeuedInputBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -319,14 +210,34 @@ public final class Eia608Decoder implements SubtitleDecoder {
|
||||
// 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());
|
||||
boolean captionDataProcessed = false;
|
||||
boolean isRepeatableControl = false;
|
||||
while (ccData.bytesLeft() > 0) {
|
||||
byte ccTypeAndValid = (byte) (ccData.readUnsignedByte() & 0x07);
|
||||
byte ccData1 = (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.
|
||||
if (ccData1 == 0 && ccData2 == 0) {
|
||||
continue;
|
||||
@ -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>
|
||||
* The position of {@code payload} is left unchanged.
|
||||
*
|
||||
* @param payloadType The payload type of the message.
|
||||
* @param payloadLength The length of 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) {
|
||||
if (payloadType != PAYLOAD_TYPE_CC || payloadLength < 8) {
|
||||
return false;
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public Eia608SubtitleOutputBuffer(Eia608Decoder owner) {
|
||||
public CeaOutputBuffer(CeaDecoder owner) {
|
||||
super();
|
||||
this.owner = owner;
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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.Subtitle;
|
||||
@ -21,16 +21,16 @@ import java.util.Collections;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @param cue The subtitle cue.
|
||||
*/
|
||||
public Eia608Subtitle(Cue cue) {
|
||||
public CeaSubtitle(Cue cue) {
|
||||
if (cue == null) {
|
||||
cues = Collections.emptyList();
|
||||
} else {
|
@ -64,7 +64,7 @@ public final class MimeTypes {
|
||||
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_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_TTML = BASE_TYPE_APPLICATION + "/ttml+xml";
|
||||
public static final String APPLICATION_M3U8 = BASE_TYPE_APPLICATION + "/x-mpegURL";
|
||||
@ -209,7 +209,7 @@ public final class MimeTypes {
|
||||
return C.TRACK_TYPE_AUDIO;
|
||||
} else if (isVideo(mimeType)) {
|
||||
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_TX3G.equals(mimeType) || APPLICATION_MP4VTT.equals(mimeType)
|
||||
|| APPLICATION_RAWCC.equals(mimeType) || APPLICATION_VOBSUB.equals(mimeType)
|
||||
|
@ -194,6 +194,13 @@ public final class ParsableByteArray {
|
||||
position += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks at the next byte as an unsigned value.
|
||||
*/
|
||||
public int peekUnsignedByte() {
|
||||
return (data[position] & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next byte as an unsigned value.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user