Commit c3d8ad24 by hoangtc Committed by Oliver Woodman

Add supports for Seeking in ADTS format using a constant bitrate seekmap.

- Use ConstantBitrateSeeker to implement seeking for ADTS format. Since most
ADTS streams are VBR, we use the average bitrate of the first 1000 frames as
the average bit rate.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=207509651
parent f3ad87d6
Showing with 2242 additions and 14 deletions
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
* Audio: * Audio:
* Support seeking for the AMR container format using constant bitrate seek * Support seeking for the AMR container format using constant bitrate seek
map. map.
* Support seeking for the ADTS container format using constant bitrate seek
map ([#4548](https://github.com/google/ExoPlayer/issues/4548)).
* Add support for mu-law and A-law PCM with the ffmpeg extension * Add support for mu-law and A-law PCM with the ffmpeg extension
([#4360](https://github.com/google/ExoPlayer/issues/4360)). ([#4360](https://github.com/google/ExoPlayer/issues/4360)).
* Increase `AudioTrack` buffer sizes to the theoretical maximum required for * Increase `AudioTrack` buffer sizes to the theoretical maximum required for
......
seekMap:
isSeekable = true
duration = 4360000
getPosition(0) = [[timeUs=0, position=6]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/3gpp
maxInputSize = 61
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 8000
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 949
sample count = 73
sample 0:
time = 2900000
flags = 1
data = length 13, hash FFFBE047
sample 1:
time = 2920000
flags = 1
data = length 13, hash BEACFCB0
sample 2:
time = 2940000
flags = 1
data = length 13, hash AEB5096C
sample 3:
time = 2960000
flags = 1
data = length 13, hash B0D381B
sample 4:
time = 2980000
flags = 1
data = length 13, hash 3D9D5122
sample 5:
time = 3000000
flags = 1
data = length 13, hash 6C1DDB95
sample 6:
time = 3020000
flags = 1
data = length 13, hash ADACADCF
sample 7:
time = 3040000
flags = 1
data = length 13, hash 159E321E
sample 8:
time = 3060000
flags = 1
data = length 13, hash B1466264
sample 9:
time = 3080000
flags = 1
data = length 13, hash 4DDF7223
sample 10:
time = 3100000
flags = 1
data = length 13, hash C9BDB82A
sample 11:
time = 3120000
flags = 1
data = length 13, hash A49B2D9D
sample 12:
time = 3140000
flags = 1
data = length 13, hash D645E7E5
sample 13:
time = 3160000
flags = 1
data = length 13, hash 1C4232DC
sample 14:
time = 3180000
flags = 1
data = length 13, hash 83078219
sample 15:
time = 3200000
flags = 1
data = length 13, hash D6D8B072
sample 16:
time = 3220000
flags = 1
data = length 13, hash 975DB40
sample 17:
time = 3240000
flags = 1
data = length 13, hash A15FDD05
sample 18:
time = 3260000
flags = 1
data = length 13, hash 4B839E41
sample 19:
time = 3280000
flags = 1
data = length 13, hash 7418F499
sample 20:
time = 3300000
flags = 1
data = length 13, hash 7A4945E4
sample 21:
time = 3320000
flags = 1
data = length 13, hash 6249558C
sample 22:
time = 3340000
flags = 1
data = length 13, hash BD4C5BE3
sample 23:
time = 3360000
flags = 1
data = length 13, hash BAB30F1D
sample 24:
time = 3380000
flags = 1
data = length 13, hash 1E1C7012
sample 25:
time = 3400000
flags = 1
data = length 13, hash 9A3F8A89
sample 26:
time = 3420000
flags = 1
data = length 13, hash 20BE6D7B
sample 27:
time = 3440000
flags = 1
data = length 13, hash CAA0591D
sample 28:
time = 3460000
flags = 1
data = length 13, hash 6D554D17
sample 29:
time = 3480000
flags = 1
data = length 13, hash D97C3B31
sample 30:
time = 3500000
flags = 1
data = length 13, hash 75BC5C3
sample 31:
time = 3520000
flags = 1
data = length 13, hash 7BA1784B
sample 32:
time = 3540000
flags = 1
data = length 13, hash 1D175D92
sample 33:
time = 3560000
flags = 1
data = length 13, hash ADCA60FD
sample 34:
time = 3580000
flags = 1
data = length 13, hash 37018693
sample 35:
time = 3600000
flags = 1
data = length 13, hash 4553606F
sample 36:
time = 3620000
flags = 1
data = length 13, hash CF434565
sample 37:
time = 3640000
flags = 1
data = length 13, hash D264D757
sample 38:
time = 3660000
flags = 1
data = length 13, hash 4FB493EF
sample 39:
time = 3680000
flags = 1
data = length 13, hash 919F53A
sample 40:
time = 3700000
flags = 1
data = length 13, hash C22B009B
sample 41:
time = 3720000
flags = 1
data = length 13, hash 5981470
sample 42:
time = 3740000
flags = 1
data = length 13, hash A5D3937C
sample 43:
time = 3760000
flags = 1
data = length 13, hash A2504429
sample 44:
time = 3780000
flags = 1
data = length 13, hash AD1B70BE
sample 45:
time = 3800000
flags = 1
data = length 13, hash 2E39ED5E
sample 46:
time = 3820000
flags = 1
data = length 13, hash 13A8BE8E
sample 47:
time = 3840000
flags = 1
data = length 13, hash 1ACD740B
sample 48:
time = 3860000
flags = 1
data = length 13, hash 80F38B3
sample 49:
time = 3880000
flags = 1
data = length 13, hash DA9DA79F
sample 50:
time = 3900000
flags = 1
data = length 13, hash 21B95B7E
sample 51:
time = 3920000
flags = 1
data = length 13, hash CD22497B
sample 52:
time = 3940000
flags = 1
data = length 13, hash 718BB35D
sample 53:
time = 3960000
flags = 1
data = length 13, hash 69ABA6AD
sample 54:
time = 3980000
flags = 1
data = length 13, hash BAE19549
sample 55:
time = 4000000
flags = 1
data = length 13, hash 2A792FB3
sample 56:
time = 4020000
flags = 1
data = length 13, hash 71FCD8
sample 57:
time = 4040000
flags = 1
data = length 13, hash 44D2B5B3
sample 58:
time = 4060000
flags = 1
data = length 13, hash 1E87B11B
sample 59:
time = 4080000
flags = 1
data = length 13, hash 78CD2C11
sample 60:
time = 4100000
flags = 1
data = length 13, hash 9F198DF0
sample 61:
time = 4120000
flags = 1
data = length 13, hash B291F16A
sample 62:
time = 4140000
flags = 1
data = length 13, hash CF820EE0
sample 63:
time = 4160000
flags = 1
data = length 13, hash 4E24F683
sample 64:
time = 4180000
flags = 1
data = length 13, hash 52BCD68F
sample 65:
time = 4200000
flags = 1
data = length 13, hash 42588CB0
sample 66:
time = 4220000
flags = 1
data = length 13, hash EBBFECA2
sample 67:
time = 4240000
flags = 1
data = length 13, hash C11050CF
sample 68:
time = 4260000
flags = 1
data = length 13, hash 6F738603
sample 69:
time = 4280000
flags = 1
data = length 13, hash DAD06E5
sample 70:
time = 4300000
flags = 1
data = length 13, hash 5B036C64
sample 71:
time = 4320000
flags = 1
data = length 13, hash A58DC12E
sample 72:
time = 4340000
flags = 1
data = length 13, hash AC59BA7C
tracksEnded = true
seekMap:
isSeekable = true
duration = 4360000
getPosition(0) = [[timeUs=0, position=6]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/3gpp
maxInputSize = 61
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 8000
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 13
sample count = 1
sample 0:
time = 4340000
flags = 1
data = length 13, hash AC59BA7C
tracksEnded = true
seekMap:
isSeekable = true
duration = 3380000
getPosition(0) = [[timeUs=0, position=9]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/amr-wb
maxInputSize = 61
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 16000
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 1368
sample count = 57
sample 0:
time = 2240000
flags = 1
data = length 24, hash 4EC5E974
sample 1:
time = 2260000
flags = 1
data = length 24, hash 1C1CD40D
sample 2:
time = 2280000
flags = 1
data = length 24, hash 76CC54BC
sample 3:
time = 2300000
flags = 1
data = length 24, hash D497ACF5
sample 4:
time = 2320000
flags = 1
data = length 24, hash A1386080
sample 5:
time = 2340000
flags = 1
data = length 24, hash 7ED36954
sample 6:
time = 2360000
flags = 1
data = length 24, hash C11A3BF9
sample 7:
time = 2380000
flags = 1
data = length 24, hash 8FB69488
sample 8:
time = 2400000
flags = 1
data = length 24, hash C6225F59
sample 9:
time = 2420000
flags = 1
data = length 24, hash 122AB6D2
sample 10:
time = 2440000
flags = 1
data = length 24, hash 1E195E7D
sample 11:
time = 2460000
flags = 1
data = length 24, hash BD3DF418
sample 12:
time = 2480000
flags = 1
data = length 24, hash D8AE4A5
sample 13:
time = 2500000
flags = 1
data = length 24, hash 977BD182
sample 14:
time = 2520000
flags = 1
data = length 24, hash F361F060
sample 15:
time = 2540000
flags = 1
data = length 24, hash 11EC8CD0
sample 16:
time = 2560000
flags = 1
data = length 24, hash 3798F3D2
sample 17:
time = 2580000
flags = 1
data = length 24, hash B2C2517C
sample 18:
time = 2600000
flags = 1
data = length 24, hash FBE0D0D8
sample 19:
time = 2620000
flags = 1
data = length 24, hash 7033172F
sample 20:
time = 2640000
flags = 1
data = length 24, hash BE760029
sample 21:
time = 2660000
flags = 1
data = length 24, hash 590AF28C
sample 22:
time = 2680000
flags = 1
data = length 24, hash AD28C48F
sample 23:
time = 2700000
flags = 1
data = length 24, hash 640AA61B
sample 24:
time = 2720000
flags = 1
data = length 24, hash ABE659B
sample 25:
time = 2740000
flags = 1
data = length 24, hash ED2691D2
sample 26:
time = 2760000
flags = 1
data = length 24, hash D998C80E
sample 27:
time = 2780000
flags = 1
data = length 24, hash 8DC0DF5C
sample 28:
time = 2800000
flags = 1
data = length 24, hash 7692247B
sample 29:
time = 2820000
flags = 1
data = length 24, hash C1D1CCB9
sample 30:
time = 2840000
flags = 1
data = length 24, hash 362CE78E
sample 31:
time = 2860000
flags = 1
data = length 24, hash 54FA84A
sample 32:
time = 2880000
flags = 1
data = length 24, hash 29E88C84
sample 33:
time = 2900000
flags = 1
data = length 24, hash 1CD848AC
sample 34:
time = 2920000
flags = 1
data = length 24, hash 5C3D4A79
sample 35:
time = 2940000
flags = 1
data = length 24, hash 1AA8E604
sample 36:
time = 2960000
flags = 1
data = length 24, hash 186A4316
sample 37:
time = 2980000
flags = 1
data = length 24, hash 61ACE481
sample 38:
time = 3000000
flags = 1
data = length 24, hash D0C42780
sample 39:
time = 3020000
flags = 1
data = length 24, hash FAD51BA1
sample 40:
time = 3040000
flags = 1
data = length 24, hash F1A9AC71
sample 41:
time = 3060000
flags = 1
data = length 24, hash 24425449
sample 42:
time = 3080000
flags = 1
data = length 24, hash 37AAC3E6
sample 43:
time = 3100000
flags = 1
data = length 24, hash 91F68CB4
sample 44:
time = 3120000
flags = 1
data = length 24, hash F8C92820
sample 45:
time = 3140000
flags = 1
data = length 24, hash ECD39C3E
sample 46:
time = 3160000
flags = 1
data = length 24, hash B27D8F78
sample 47:
time = 3180000
flags = 1
data = length 24, hash C9EB3DFB
sample 48:
time = 3200000
flags = 1
data = length 24, hash 88DC54A2
sample 49:
time = 3220000
flags = 1
data = length 24, hash 7FC4C5BE
sample 50:
time = 3240000
flags = 1
data = length 24, hash E4F684EF
sample 51:
time = 3260000
flags = 1
data = length 24, hash 55C08B56
sample 52:
time = 3280000
flags = 1
data = length 24, hash E5A0F006
sample 53:
time = 3300000
flags = 1
data = length 24, hash DE3F3AA7
sample 54:
time = 3320000
flags = 1
data = length 24, hash 3F28AE7F
sample 55:
time = 3340000
flags = 1
data = length 24, hash 3949CAFF
sample 56:
time = 3360000
flags = 1
data = length 24, hash 772665A0
tracksEnded = true
seekMap:
isSeekable = true
duration = 3380000
getPosition(0) = [[timeUs=0, position=9]]
numberOfTracks = 1
track 0:
format:
bitrate = -1
id = null
containerMimeType = null
sampleMimeType = audio/amr-wb
maxInputSize = 61
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 16000
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 24
sample count = 1
sample 0:
time = 3360000
flags = 1
data = length 24, hash 772665A0
tracksEnded = true
seekMap:
isSeekable = true
duration = 3356772
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 2
track 0:
format:
bitrate = -1
id = 0
containerMimeType = null
sampleMimeType = audio/mp4a-latm
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 44100
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
data = length 2, hash 5F7
total output bytes = 20533
sample count = 94
sample 0:
time = 1118924
flags = 1
data = length 232, hash 4B5BF5E8
sample 1:
time = 1142143
flags = 1
data = length 233, hash F3D80836
sample 2:
time = 1165362
flags = 1
data = length 237, hash 32E0A11E
sample 3:
time = 1188581
flags = 1
data = length 228, hash E1B89F13
sample 4:
time = 1211800
flags = 1
data = length 237, hash 8BDD9E38
sample 5:
time = 1235019
flags = 1
data = length 235, hash 3C84161F
sample 6:
time = 1258238
flags = 1
data = length 227, hash A47E1789
sample 7:
time = 1281457
flags = 1
data = length 228, hash 869FDFD3
sample 8:
time = 1304676
flags = 1
data = length 233, hash 272ECE2
sample 9:
time = 1327895
flags = 1
data = length 227, hash DB6B9618
sample 10:
time = 1351114
flags = 1
data = length 212, hash 63214325
sample 11:
time = 1374333
flags = 1
data = length 221, hash 9BA588A1
sample 12:
time = 1397552
flags = 1
data = length 225, hash 21EFD50C
sample 13:
time = 1420771
flags = 1
data = length 231, hash F3AD0BF
sample 14:
time = 1443990
flags = 1
data = length 224, hash 822C9210
sample 15:
time = 1467209
flags = 1
data = length 195, hash D4EF53EE
sample 16:
time = 1490428
flags = 1
data = length 195, hash A816647A
sample 17:
time = 1513647
flags = 1
data = length 184, hash 9A2B7E6
sample 18:
time = 1536866
flags = 1
data = length 210, hash 956E3600
sample 19:
time = 1560085
flags = 1
data = length 234, hash 35CFDA0A
sample 20:
time = 1583304
flags = 1
data = length 239, hash 9E15AC1E
sample 21:
time = 1606523
flags = 1
data = length 228, hash F3B70641
sample 22:
time = 1629742
flags = 1
data = length 237, hash 124E3194
sample 23:
time = 1652961
flags = 1
data = length 231, hash 950CD7C8
sample 24:
time = 1676180
flags = 1
data = length 236, hash A12E49AF
sample 25:
time = 1699399
flags = 1
data = length 242, hash 43BC9C24
sample 26:
time = 1722618
flags = 1
data = length 241, hash DCF0B17
sample 27:
time = 1745837
flags = 1
data = length 251, hash C0B99968
sample 28:
time = 1769056
flags = 1
data = length 245, hash 9B38ED1C
sample 29:
time = 1792275
flags = 1
data = length 238, hash 1BA69079
sample 30:
time = 1815494
flags = 1
data = length 233, hash 44C8C6BF
sample 31:
time = 1838713
flags = 1
data = length 231, hash EABBEE02
sample 32:
time = 1861932
flags = 1
data = length 226, hash D09C44FB
sample 33:
time = 1885151
flags = 1
data = length 235, hash BE6A6608
sample 34:
time = 1908370
flags = 1
data = length 235, hash 2735F454
sample 35:
time = 1931589
flags = 1
data = length 238, hash B160DFE7
sample 36:
time = 1954808
flags = 1
data = length 232, hash 1B217D2E
sample 37:
time = 1978027
flags = 1
data = length 251, hash D1C14CEA
sample 38:
time = 2001246
flags = 1
data = length 256, hash 97C87F08
sample 39:
time = 2024465
flags = 1
data = length 237, hash 6645DB3
sample 40:
time = 2047684
flags = 1
data = length 235, hash 727A1C82
sample 41:
time = 2070903
flags = 1
data = length 234, hash 5015F8B5
sample 42:
time = 2094122
flags = 1
data = length 241, hash 9102144B
sample 43:
time = 2117341
flags = 1
data = length 224, hash 64E0D807
sample 44:
time = 2140560
flags = 1
data = length 228, hash 1922B852
sample 45:
time = 2163779
flags = 1
data = length 224, hash 953502D8
sample 46:
time = 2186998
flags = 1
data = length 214, hash 92B87FE7
sample 47:
time = 2210217
flags = 1
data = length 213, hash BB0C8D86
sample 48:
time = 2233436
flags = 1
data = length 206, hash 9AD21017
sample 49:
time = 2256655
flags = 1
data = length 209, hash C479FE94
sample 50:
time = 2279874
flags = 1
data = length 220, hash 3033DCE1
sample 51:
time = 2303093
flags = 1
data = length 217, hash 7D589C94
sample 52:
time = 2326312
flags = 1
data = length 216, hash AAF6C183
sample 53:
time = 2349531
flags = 1
data = length 206, hash 1EE1207F
sample 54:
time = 2372750
flags = 1
data = length 204, hash 4BEB1210
sample 55:
time = 2395969
flags = 1
data = length 213, hash 21A841C9
sample 56:
time = 2419188
flags = 1
data = length 207, hash B80B0424
sample 57:
time = 2442407
flags = 1
data = length 212, hash 4785A1C3
sample 58:
time = 2465626
flags = 1
data = length 205, hash 59BF7229
sample 59:
time = 2488845
flags = 1
data = length 208, hash FA313DDE
sample 60:
time = 2512064
flags = 1
data = length 211, hash 190D85FD
sample 61:
time = 2535283
flags = 1
data = length 211, hash BA050052
sample 62:
time = 2558502
flags = 1
data = length 211, hash F3080F10
sample 63:
time = 2581721
flags = 1
data = length 210, hash F41B7BE7
sample 64:
time = 2604940
flags = 1
data = length 207, hash 2176C97E
sample 65:
time = 2628159
flags = 1
data = length 220, hash 32087455
sample 66:
time = 2651378
flags = 1
data = length 213, hash 4E5649A8
sample 67:
time = 2674597
flags = 1
data = length 213, hash 5F12FDCF
sample 68:
time = 2697816
flags = 1
data = length 204, hash 1E895C2A
sample 69:
time = 2721035
flags = 1
data = length 219, hash 45382270
sample 70:
time = 2744254
flags = 1
data = length 205, hash D66C6A1D
sample 71:
time = 2767473
flags = 1
data = length 204, hash 467AD01F
sample 72:
time = 2790692
flags = 1
data = length 211, hash F0435574
sample 73:
time = 2813911
flags = 1
data = length 206, hash 8C96B75F
sample 74:
time = 2837130
flags = 1
data = length 200, hash 82553248
sample 75:
time = 2860349
flags = 1
data = length 180, hash 1E51E6CE
sample 76:
time = 2883568
flags = 1
data = length 196, hash 33151DC4
sample 77:
time = 2906787
flags = 1
data = length 197, hash 1E62A7D6
sample 78:
time = 2930006
flags = 1
data = length 206, hash 6A6C4CC9
sample 79:
time = 2953225
flags = 1
data = length 209, hash A72FABAA
sample 80:
time = 2976444
flags = 1
data = length 217, hash BA33B985
sample 81:
time = 2999663
flags = 1
data = length 235, hash 9919CFD9
sample 82:
time = 3022882
flags = 1
data = length 236, hash A22C7267
sample 83:
time = 3046101
flags = 1
data = length 213, hash 3D57C901
sample 84:
time = 3069320
flags = 1
data = length 205, hash 47F68FDE
sample 85:
time = 3092539
flags = 1
data = length 210, hash 9A756E9C
sample 86:
time = 3115758
flags = 1
data = length 210, hash BD45C31F
sample 87:
time = 3138977
flags = 1
data = length 207, hash 8774FF7B
sample 88:
time = 3162196
flags = 1
data = length 149, hash 4678C0E5
sample 89:
time = 3185415
flags = 1
data = length 161, hash E991035D
sample 90:
time = 3208634
flags = 1
data = length 197, hash C3013689
sample 91:
time = 3231853
flags = 1
data = length 208, hash E6C0237
sample 92:
time = 3255072
flags = 1
data = length 232, hash A330F188
sample 93:
time = 3278291
flags = 1
data = length 174, hash 2B69C34E
track 1:
format:
bitrate = -1
id = 1
containerMimeType = null
sampleMimeType = application/id3
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = -1
sampleRate = -1
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 0
sample count = 0
tracksEnded = true
seekMap:
isSeekable = true
duration = 3356772
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 2
track 0:
format:
bitrate = -1
id = 0
containerMimeType = null
sampleMimeType = audio/mp4a-latm
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 44100
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
data = length 2, hash 5F7
total output bytes = 10161
sample count = 49
sample 0:
time = 2237848
flags = 1
data = length 224, hash 953502D8
sample 1:
time = 2261067
flags = 1
data = length 214, hash 92B87FE7
sample 2:
time = 2284286
flags = 1
data = length 213, hash BB0C8D86
sample 3:
time = 2307505
flags = 1
data = length 206, hash 9AD21017
sample 4:
time = 2330724
flags = 1
data = length 209, hash C479FE94
sample 5:
time = 2353943
flags = 1
data = length 220, hash 3033DCE1
sample 6:
time = 2377162
flags = 1
data = length 217, hash 7D589C94
sample 7:
time = 2400381
flags = 1
data = length 216, hash AAF6C183
sample 8:
time = 2423600
flags = 1
data = length 206, hash 1EE1207F
sample 9:
time = 2446819
flags = 1
data = length 204, hash 4BEB1210
sample 10:
time = 2470038
flags = 1
data = length 213, hash 21A841C9
sample 11:
time = 2493257
flags = 1
data = length 207, hash B80B0424
sample 12:
time = 2516476
flags = 1
data = length 212, hash 4785A1C3
sample 13:
time = 2539695
flags = 1
data = length 205, hash 59BF7229
sample 14:
time = 2562914
flags = 1
data = length 208, hash FA313DDE
sample 15:
time = 2586133
flags = 1
data = length 211, hash 190D85FD
sample 16:
time = 2609352
flags = 1
data = length 211, hash BA050052
sample 17:
time = 2632571
flags = 1
data = length 211, hash F3080F10
sample 18:
time = 2655790
flags = 1
data = length 210, hash F41B7BE7
sample 19:
time = 2679009
flags = 1
data = length 207, hash 2176C97E
sample 20:
time = 2702228
flags = 1
data = length 220, hash 32087455
sample 21:
time = 2725447
flags = 1
data = length 213, hash 4E5649A8
sample 22:
time = 2748666
flags = 1
data = length 213, hash 5F12FDCF
sample 23:
time = 2771885
flags = 1
data = length 204, hash 1E895C2A
sample 24:
time = 2795104
flags = 1
data = length 219, hash 45382270
sample 25:
time = 2818323
flags = 1
data = length 205, hash D66C6A1D
sample 26:
time = 2841542
flags = 1
data = length 204, hash 467AD01F
sample 27:
time = 2864761
flags = 1
data = length 211, hash F0435574
sample 28:
time = 2887980
flags = 1
data = length 206, hash 8C96B75F
sample 29:
time = 2911199
flags = 1
data = length 200, hash 82553248
sample 30:
time = 2934418
flags = 1
data = length 180, hash 1E51E6CE
sample 31:
time = 2957637
flags = 1
data = length 196, hash 33151DC4
sample 32:
time = 2980856
flags = 1
data = length 197, hash 1E62A7D6
sample 33:
time = 3004075
flags = 1
data = length 206, hash 6A6C4CC9
sample 34:
time = 3027294
flags = 1
data = length 209, hash A72FABAA
sample 35:
time = 3050513
flags = 1
data = length 217, hash BA33B985
sample 36:
time = 3073732
flags = 1
data = length 235, hash 9919CFD9
sample 37:
time = 3096951
flags = 1
data = length 236, hash A22C7267
sample 38:
time = 3120170
flags = 1
data = length 213, hash 3D57C901
sample 39:
time = 3143389
flags = 1
data = length 205, hash 47F68FDE
sample 40:
time = 3166608
flags = 1
data = length 210, hash 9A756E9C
sample 41:
time = 3189827
flags = 1
data = length 210, hash BD45C31F
sample 42:
time = 3213046
flags = 1
data = length 207, hash 8774FF7B
sample 43:
time = 3236265
flags = 1
data = length 149, hash 4678C0E5
sample 44:
time = 3259484
flags = 1
data = length 161, hash E991035D
sample 45:
time = 3282703
flags = 1
data = length 197, hash C3013689
sample 46:
time = 3305922
flags = 1
data = length 208, hash E6C0237
sample 47:
time = 3329141
flags = 1
data = length 232, hash A330F188
sample 48:
time = 3352360
flags = 1
data = length 174, hash 2B69C34E
track 1:
format:
bitrate = -1
id = 1
containerMimeType = null
sampleMimeType = application/id3
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = -1
sampleRate = -1
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 0
sample count = 0
tracksEnded = true
seekMap:
isSeekable = true
duration = 3356772
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 2
track 0:
format:
bitrate = -1
id = 0
containerMimeType = null
sampleMimeType = audio/mp4a-latm
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = 1
sampleRate = 44100
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
data = length 2, hash 5F7
total output bytes = 174
sample count = 1
sample 0:
time = 3356772
flags = 1
data = length 174, hash 2B69C34E
track 1:
format:
bitrate = -1
id = 1
containerMimeType = null
sampleMimeType = application/id3
maxInputSize = -1
width = -1
height = -1
frameRate = -1.0
rotationDegrees = 0
pixelWidthHeightRatio = 1.0
channelCount = -1
sampleRate = -1
pcmEncoding = -1
encoderDelay = 0
encoderPadding = 0
subsampleOffsetUs = 9223372036854775807
selectionFlags = 0
language = null
drmInitData = -
initializationData:
total output bytes = 0
sample count = 0
tracksEnded = true
...@@ -179,12 +179,26 @@ public final class AmrExtractorTest { ...@@ -179,12 +179,26 @@ public final class AmrExtractorTest {
@Test @Test
public void testExtractingNarrowBandSamples() throws Exception { public void testExtractingNarrowBandSamples() throws Exception {
ExtractorAsserts.assertBehavior(createAmrExtractorFactory(), "amr/sample_nb.amr"); ExtractorAsserts.assertBehavior(
createAmrExtractorFactory(/* withSeeking= */ false), "amr/sample_nb.amr");
} }
@Test @Test
public void testExtractingWideBandSamples() throws Exception { public void testExtractingWideBandSamples() throws Exception {
ExtractorAsserts.assertBehavior(createAmrExtractorFactory(), "amr/sample_wb.amr"); ExtractorAsserts.assertBehavior(
createAmrExtractorFactory(/* withSeeking= */ false), "amr/sample_wb.amr");
}
@Test
public void testExtractingNarrowBandSamples_withSeeking() throws Exception {
ExtractorAsserts.assertBehavior(
createAmrExtractorFactory(/* withSeeking= */ true), "amr/sample_nb_cbr.amr");
}
@Test
public void testExtractingWideBandSamples_withSeeking() throws Exception {
ExtractorAsserts.assertBehavior(
createAmrExtractorFactory(/* withSeeking= */ true), "amr/sample_wb_cbr.amr");
} }
private byte[] newWideBandAmrFrameWithType(int frameType) { private byte[] newWideBandAmrFrameWithType(int frameType) {
...@@ -235,11 +249,15 @@ public final class AmrExtractorTest { ...@@ -235,11 +249,15 @@ public final class AmrExtractorTest {
} }
@NonNull @NonNull
private static ExtractorAsserts.ExtractorFactory createAmrExtractorFactory() { private static ExtractorAsserts.ExtractorFactory createAmrExtractorFactory(boolean withSeeking) {
return new ExtractorAsserts.ExtractorFactory() { return new ExtractorAsserts.ExtractorFactory() {
@Override @Override
public Extractor create() { public Extractor create() {
if (!withSeeking) {
return new AmrExtractor(); return new AmrExtractor();
} else {
return new AmrExtractor(AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING);
}
} }
}; };
} }
......
...@@ -37,4 +37,18 @@ public final class AdtsExtractorTest { ...@@ -37,4 +37,18 @@ public final class AdtsExtractorTest {
}, },
"ts/sample.adts"); "ts/sample.adts");
} }
@Test
public void testSample_withSeeking() throws Exception {
ExtractorAsserts.assertBehavior(
new ExtractorFactory() {
@Override
public Extractor create() {
return new AdtsExtractor(
/* firstStreamSampleTimestampUs= */ 0,
/* flags= */ AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING);
}
},
"ts/sample_cbs.adts");
}
} }
...@@ -95,12 +95,24 @@ public class AdtsReaderTest { ...@@ -95,12 +95,24 @@ public class AdtsReaderTest {
TestUtil.joinByteArrays( TestUtil.joinByteArrays(
ADTS_HEADER, ADTS_HEADER,
ADTS_CONTENT, ADTS_CONTENT,
ADTS_HEADER,
ADTS_CONTENT,
// Adts sample missing the first sync byte // Adts sample missing the first sync byte
// The Reader should be able to read the next sample.
Arrays.copyOfRange(ADTS_HEADER, 1, ADTS_HEADER.length), Arrays.copyOfRange(ADTS_HEADER, 1, ADTS_HEADER.length),
ADTS_CONTENT,
ADTS_HEADER,
ADTS_CONTENT)); ADTS_CONTENT));
feed(); feed();
assertSampleCounts(0, 1); assertSampleCounts(0, 3);
adtsOutput.assertSample(0, ADTS_CONTENT, 0, C.BUFFER_FLAG_KEY_FRAME, null); for (int i = 0; i < 3; i++) {
adtsOutput.assertSample(
/* index= */ i,
/* data= */ ADTS_CONTENT,
/* timeUs= */ ADTS_SAMPLE_DURATION * i,
/* flags= */ C.BUFFER_FLAG_KEY_FRAME,
/* cryptoData= */ null);
}
} }
@Test @Test
......
...@@ -22,8 +22,13 @@ import android.content.Context; ...@@ -22,8 +22,13 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.testutil.FakeExtractorInput.SimulatedIOException; import com.google.android.exoplayer2.testutil.FakeExtractorInput.SimulatedIOException;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
...@@ -223,4 +228,150 @@ public class TestUtil { ...@@ -223,4 +228,150 @@ public class TestUtil {
mse / (255.0 * 255.0 * 3.0 * firstBitmap.getWidth() * firstBitmap.getHeight()); mse / (255.0 * 255.0 * 3.0 * firstBitmap.getWidth() * firstBitmap.getHeight());
return 10 * Math.log10(1.0 / normalizedMse); return 10 * Math.log10(1.0 / normalizedMse);
} }
/** Returns the {@link Uri} for the given asset path. */
public static Uri buildAssetUri(String assetPath) {
return Uri.parse("asset:///" + assetPath);
}
/**
* Reads from the given input using the given {@link Extractor}, until it can produce the {@link
* SeekMap} and all of the tracks have been identified, or until the extractor encounters EOF.
*
* @param extractor The {@link Extractor} to extractor from input.
* @param output The {@link FakeTrackOutput} to store the extracted {@link SeekMap} and track.
* @param dataSource The {@link DataSource} that will be used to read from the input.
* @param uri The Uri of the input.
* @return The extracted {@link SeekMap}.
* @throws IOException If an error occurred reading from the input, or if the extractor finishes
* reading from input without extracting any {@link SeekMap}.
* @throws InterruptedException If the thread was interrupted.
*/
public static SeekMap extractSeekMap(
Extractor extractor, FakeExtractorOutput output, DataSource dataSource, Uri uri)
throws IOException, InterruptedException {
ExtractorInput input = getExtractorInputFromPosition(dataSource, /* position= */ 0, uri);
extractor.init(output);
PositionHolder positionHolder = new PositionHolder();
int readResult = Extractor.RESULT_CONTINUE;
while (true) {
try {
// Keep reading until we can get the seek map
while (readResult == Extractor.RESULT_CONTINUE
&& (output.seekMap == null || !output.tracksEnded)) {
readResult = extractor.read(input, positionHolder);
}
} finally {
Util.closeQuietly(dataSource);
}
if (readResult == Extractor.RESULT_SEEK) {
input = getExtractorInputFromPosition(dataSource, positionHolder.position, uri);
readResult = Extractor.RESULT_CONTINUE;
} else if (readResult == Extractor.RESULT_END_OF_INPUT) {
throw new IOException("EOF encountered without seekmap");
}
if (output.seekMap != null) {
return output.seekMap;
}
}
}
/**
* Extracts all samples from the given file into a {@link FakeTrackOutput}.
*
* @param extractor The {@link Extractor} to extractor from input.
* @param context A {@link Context}.
* @param fileName The name of the input file.
* @return The {@link FakeTrackOutput} containing the extracted samples.
* @throws IOException If an error occurred reading from the input, or if the extractor finishes
* reading from input without extracting any {@link SeekMap}.
* @throws InterruptedException If the thread was interrupted.
*/
public static FakeExtractorOutput extractAllSamplesFromFile(
Extractor extractor, Context context, String fileName)
throws IOException, InterruptedException {
byte[] data = TestUtil.getByteArray(context, fileName);
FakeExtractorOutput expectedOutput = new FakeExtractorOutput();
extractor.init(expectedOutput);
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
PositionHolder positionHolder = new PositionHolder();
int readResult = Extractor.RESULT_CONTINUE;
while (readResult != Extractor.RESULT_END_OF_INPUT) {
while (readResult == Extractor.RESULT_CONTINUE) {
readResult = extractor.read(input, positionHolder);
}
if (readResult == Extractor.RESULT_SEEK) {
input.setPosition((int) positionHolder.position);
readResult = Extractor.RESULT_CONTINUE;
}
}
return expectedOutput;
}
/**
* Seeks to the given seek time of the stream from the given input, and keeps reading from the
* input until we can extract at least one sample following the seek position, or until
* end-of-input is reached.
*
* @param extractor The {@link Extractor} to extractor from input.
* @param seekMap The {@link SeekMap} of the stream from the given input.
* @param seekTimeUs The seek time, in micro-seconds.
* @param trackOutput The {@link FakeTrackOutput} to store the extracted samples.
* @param dataSource The {@link DataSource} that will be used to read from the input.
* @param uri The Uri of the input.
* @return The index of the first extracted sample written to the given {@code trackOutput} after
* the seek is completed, or -1 if the seek is completed without any extracted sample.
*/
public static int seekToTimeUs(
Extractor extractor,
SeekMap seekMap,
long seekTimeUs,
DataSource dataSource,
FakeTrackOutput trackOutput,
Uri uri)
throws IOException, InterruptedException {
int numSampleBeforeSeek = trackOutput.getSampleCount();
SeekMap.SeekPoints seekPoints = seekMap.getSeekPoints(seekTimeUs);
long initialSeekLoadPosition = seekPoints.first.position;
extractor.seek(initialSeekLoadPosition, seekTimeUs);
PositionHolder positionHolder = new PositionHolder();
positionHolder.position = C.POSITION_UNSET;
ExtractorInput extractorInput =
TestUtil.getExtractorInputFromPosition(dataSource, initialSeekLoadPosition, uri);
int extractorReadResult = Extractor.RESULT_CONTINUE;
while (true) {
try {
// Keep reading until we can read at least one sample after seek
while (extractorReadResult == Extractor.RESULT_CONTINUE
&& trackOutput.getSampleCount() == numSampleBeforeSeek) {
extractorReadResult = extractor.read(extractorInput, positionHolder);
}
} finally {
Util.closeQuietly(dataSource);
}
if (extractorReadResult == Extractor.RESULT_SEEK) {
extractorInput =
TestUtil.getExtractorInputFromPosition(dataSource, positionHolder.position, uri);
extractorReadResult = Extractor.RESULT_CONTINUE;
} else if (extractorReadResult == Extractor.RESULT_END_OF_INPUT) {
return -1;
} else if (trackOutput.getSampleCount() > numSampleBeforeSeek) {
// First index after seek = num sample before seek.
return numSampleBeforeSeek;
}
}
}
/** Returns an {@link ExtractorInput} to read from the given input at given position. */
private static ExtractorInput getExtractorInputFromPosition(
DataSource dataSource, long position, Uri uri) throws IOException {
DataSpec dataSpec = new DataSpec(uri, position, C.LENGTH_UNSET, /* key= */ null);
long inputLength = dataSource.open(dataSpec);
return new DefaultExtractorInput(dataSource, position, inputLength);
}
} }
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