Integrate AudioMixer for audio export.

Adds support for compositions with multiple audio sequences.

PiperOrigin-RevId: 550880626
This commit is contained in:
samrobinson 2023-07-25 15:31:00 +01:00 committed by Rohit Singh
parent 357c458028
commit 54093a152e
29 changed files with 1388 additions and 1263 deletions

View file

@ -325,16 +325,16 @@ sample:
presentationTimeUs = 464399
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1728208641
size = 2184
isKeyFrame = true
presentationTimeUs = 487619
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 620404993
size = 6008
isKeyFrame = true
presentationTimeUs = 510839
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -403,16 +403,10 @@ sample:
presentationTimeUs = 766258
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 789478
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 812698
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -457,14 +451,14 @@ sample:
presentationTimeUs = 975238
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1097317889
size = 272
isKeyFrame = true
presentationTimeUs = 998458
sample:
trackIndex = 1
dataHashCode = -587391743
size = 408
dataHashCode = -873373951
size = 4232
isKeyFrame = true
presentationTimeUs = 1021678
presentationTimeUs = 1000000
released = true

View file

@ -325,16 +325,16 @@ sample:
presentationTimeUs = 464395
sample:
trackIndex = 1
dataHashCode = -266855807
size = 4460
dataHashCode = -907321727
size = 2380
isKeyFrame = true
presentationTimeUs = 487604
sample:
trackIndex = 1
dataHashCode = 864256769
size = 4456
dataHashCode = -813809919
size = 6536
isKeyFrame = true
presentationTimeUs = 510833
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = -266855807
@ -403,16 +403,10 @@ sample:
presentationTimeUs = 766250
sample:
trackIndex = 1
dataHashCode = -266855807
size = 4460
dataHashCode = -2002051711
size = 8916
isKeyFrame = true
presentationTimeUs = 789458
sample:
trackIndex = 1
dataHashCode = 864256769
size = 4456
isKeyFrame = true
presentationTimeUs = 812687
sample:
trackIndex = 1
dataHashCode = -266855807
@ -457,16 +451,16 @@ sample:
presentationTimeUs = 975229
sample:
trackIndex = 1
dataHashCode = -266855807
size = 4460
dataHashCode = 634299009
size = 300
isKeyFrame = true
presentationTimeUs = 998437
sample:
trackIndex = 1
dataHashCode = -115707775
size = 444
dataHashCode = -1577850751
size = 4604
isKeyFrame = true
presentationTimeUs = 1021666
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = 923521

View file

@ -330,16 +330,16 @@ sample:
presentationTimeUs = 464399
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1728208641
size = 2184
isKeyFrame = true
presentationTimeUs = 487619
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 620404993
size = 6008
isKeyFrame = true
presentationTimeUs = 510839
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -408,16 +408,10 @@ sample:
presentationTimeUs = 766258
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 789478
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 812698
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -462,8 +456,14 @@ sample:
presentationTimeUs = 975238
sample:
trackIndex = 1
dataHashCode = 226248705
size = 448
dataHashCode = 1097317889
size = 272
isKeyFrame = true
presentationTimeUs = 998458
sample:
trackIndex = 1
dataHashCode = 799574529
size = 176
isKeyFrame = true
presentationTimeUs = 1000000
released = true

View file

@ -1364,16 +1364,16 @@ sample:
presentationTimeUs = 469333
sample:
trackIndex = 1
dataHashCode = -2030181452
size = 4096
dataHashCode = 339365731
size = 3840
isKeyFrame = true
presentationTimeUs = 480000
sample:
trackIndex = 1
dataHashCode = -1131911551
size = 4096
dataHashCode = 1278884562
size = 4352
isKeyFrame = true
presentationTimeUs = 501333
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 1174956589
@ -1508,16 +1508,16 @@ sample:
presentationTimeUs = 960000
sample:
trackIndex = 1
dataHashCode = 196164772
size = 4096
dataHashCode = 43993965
size = 3584
isKeyFrame = true
presentationTimeUs = 981333
sample:
trackIndex = 1
dataHashCode = -1100787564
size = 4096
dataHashCode = 984760779
size = 4608
isKeyFrame = true
presentationTimeUs = 1002666
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = -1345957974
@ -1652,16 +1652,16 @@ sample:
presentationTimeUs = 1461333
sample:
trackIndex = 1
dataHashCode = -1972687910
size = 4096
dataHashCode = 674218658
size = 3328
isKeyFrame = true
presentationTimeUs = 1482666
sample:
trackIndex = 1
dataHashCode = -1063379599
size = 4096
dataHashCode = -324278615
size = 4864
isKeyFrame = true
presentationTimeUs = 1504000
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = 496920829
@ -1934,16 +1934,16 @@ sample:
presentationTimeUs = 2469333
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 795942913
size = 1792
isKeyFrame = true
presentationTimeUs = 2490666
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1682628609
size = 6400
isKeyFrame = true
presentationTimeUs = 2512000
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2000,16 +2000,10 @@ sample:
presentationTimeUs = 2704000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 2725333
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 2746666
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2072,16 +2066,16 @@ sample:
presentationTimeUs = 2960000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -1562230783
size = 3584
isKeyFrame = true
presentationTimeUs = 2981333
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1020903425
size = 4608
isKeyFrame = true
presentationTimeUs = 3002666
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2138,16 +2132,10 @@ sample:
presentationTimeUs = 3194666
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3216000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3237333
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2216,28 +2204,22 @@ sample:
presentationTimeUs = 3472000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -1300930559
size = 1280
isKeyFrame = true
presentationTimeUs = 3493333
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -2126077951
size = 6912
isKeyFrame = true
presentationTimeUs = 3514666
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3536000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3557333
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2300,16 +2282,10 @@ sample:
presentationTimeUs = 3770666
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3792000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3813333
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2342,16 +2318,10 @@ sample:
presentationTimeUs = 3920000
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3941333
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3962666
sample:
trackIndex = 1
dataHashCode = -303661055

View file

@ -1370,16 +1370,16 @@ sample:
presentationTimeUs = 473041
sample:
trackIndex = 1
dataHashCode = 1826317146
size = 5496
dataHashCode = -1675350578
size = 1072
isKeyFrame = true
presentationTimeUs = 494416
sample:
trackIndex = 1
dataHashCode = -531342616
size = 2244
dataHashCode = 1988292468
size = 6668
isKeyFrame = true
presentationTimeUs = 523041
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = -1851185779
@ -1514,10 +1514,16 @@ sample:
presentationTimeUs = 973687
sample:
trackIndex = 1
dataHashCode = 722898605
size = 3948
dataHashCode = -548794611
size = 916
isKeyFrame = true
presentationTimeUs = 995229
sample:
trackIndex = 1
dataHashCode = 1540981665
size = 3032
isKeyFrame = true
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = 2079609877
@ -1658,16 +1664,16 @@ sample:
presentationTimeUs = 1475208
sample:
trackIndex = 1
dataHashCode = -1378914891
size = 4212
dataHashCode = -1399651613
size = 1000
isKeyFrame = true
presentationTimeUs = 1494791
sample:
trackIndex = 1
dataHashCode = 1064131864
size = 3968
dataHashCode = -534820118
size = 7180
isKeyFrame = true
presentationTimeUs = 1516729
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = -586081352
@ -1790,10 +1796,16 @@ sample:
presentationTimeUs = 1958354
sample:
trackIndex = 1
dataHashCode = -1694434488
size = 5444
dataHashCode = -1218889090
size = 5440
isKeyFrame = true
presentationTimeUs = 1971666
sample:
trackIndex = 1
dataHashCode = -833717
size = 4
isKeyFrame = true
presentationTimeUs = 2000000
sample:
trackIndex = 1
dataHashCode = 698618881
@ -1934,16 +1946,16 @@ sample:
presentationTimeUs = 2460020
sample:
trackIndex = 1
dataHashCode = 202646529
size = 4320
dataHashCode = 1734624385
size = 3356
isKeyFrame = true
presentationTimeUs = 2482520
sample:
trackIndex = 1
dataHashCode = -1017110527
size = 3840
dataHashCode = -57524351
size = 4804
isKeyFrame = true
presentationTimeUs = 2505020
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = 202646529
@ -1994,16 +2006,10 @@ sample:
presentationTimeUs = 2675020
sample:
trackIndex = 1
dataHashCode = 202646529
size = 4320
dataHashCode = -738966527
size = 8160
isKeyFrame = true
presentationTimeUs = 2695020
sample:
trackIndex = 1
dataHashCode = -1017110527
size = 3840
isKeyFrame = true
presentationTimeUs = 2717520
sample:
trackIndex = 1
dataHashCode = 202646529
@ -2078,16 +2084,16 @@ sample:
presentationTimeUs = 2972520
sample:
trackIndex = 1
dataHashCode = -1017110527
size = 3840
dataHashCode = 1878405249
size = 956
isKeyFrame = true
presentationTimeUs = 2995020
sample:
trackIndex = 1
dataHashCode = 202646529
size = 4320
dataHashCode = -1054059647
size = 7204
isKeyFrame = true
presentationTimeUs = 3015020
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = -1017110527
@ -2132,16 +2138,10 @@ sample:
presentationTimeUs = 3165020
sample:
trackIndex = 1
dataHashCode = -1017110527
size = 3840
dataHashCode = -738966527
size = 8160
isKeyFrame = true
presentationTimeUs = 3187520
sample:
trackIndex = 1
dataHashCode = 202646529
size = 4320
isKeyFrame = true
presentationTimeUs = 3207520
sample:
trackIndex = 1
dataHashCode = -1017110527
@ -2216,28 +2216,22 @@ sample:
presentationTimeUs = 3465020
sample:
trackIndex = 1
dataHashCode = 202646529
size = 4320
dataHashCode = 1278099585
size = 2876
isKeyFrame = true
presentationTimeUs = 3485020
sample:
trackIndex = 1
dataHashCode = -1017110527
size = 3840
dataHashCode = 1942242177
size = 5284
isKeyFrame = true
presentationTimeUs = 3507520
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 202646529
size = 4320
dataHashCode = -738966527
size = 8160
isKeyFrame = true
presentationTimeUs = 3527520
sample:
trackIndex = 1
dataHashCode = -1017110527
size = 3840
isKeyFrame = true
presentationTimeUs = 3550020
sample:
trackIndex = 1
dataHashCode = 202646529
@ -2300,16 +2294,10 @@ sample:
presentationTimeUs = 3762520
sample:
trackIndex = 1
dataHashCode = -1017110527
size = 3840
dataHashCode = -738966527
size = 8160
isKeyFrame = true
presentationTimeUs = 3785020
sample:
trackIndex = 1
dataHashCode = 202646529
size = 4320
isKeyFrame = true
presentationTimeUs = 3805020
sample:
trackIndex = 1
dataHashCode = -1017110527
@ -2354,8 +2342,14 @@ sample:
presentationTimeUs = 3955020
sample:
trackIndex = 1
dataHashCode = -2096740479
size = 5764
dataHashCode = -933078911
size = 5756
isKeyFrame = true
presentationTimeUs = 3970020
sample:
trackIndex = 1
dataHashCode = -1807454463
size = 8
isKeyFrame = true
presentationTimeUs = 4000000
released = true

View file

@ -1350,16 +1350,16 @@ sample:
presentationTimeUs = 458911
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 836580609
size = 3288
isKeyFrame = true
presentationTimeUs = 481360
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -1141905919
size = 5072
isKeyFrame = true
presentationTimeUs = 503809
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1428,16 +1428,10 @@ sample:
presentationTimeUs = 760702
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 783151
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 805600
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1482,16 +1476,16 @@ sample:
presentationTimeUs = 967709
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 744439297
size = 1296
isKeyFrame = true
presentationTimeUs = 992653
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -1744763903
size = 6624
isKeyFrame = true
presentationTimeUs = 1015102
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -1530,16 +1524,10 @@ sample:
presentationTimeUs = 1154761
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1177210
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1202154
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1590,16 +1578,10 @@ sample:
presentationTimeUs = 1386712
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1409160
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1434104
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1608,16 +1590,16 @@ sample:
presentationTimeUs = 1456553
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -206716671
size = 3704
isKeyFrame = true
presentationTimeUs = 1479002
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -102540799
size = 4656
isKeyFrame = true
presentationTimeUs = 1503945
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1632,16 +1614,10 @@ sample:
presentationTimeUs = 1548843
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1573786
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1596235
sample:
trackIndex = 1
dataHashCode = -448902783
@ -1692,16 +1668,10 @@ sample:
presentationTimeUs = 1780793
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1805736
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1828185
sample:
trackIndex = 1
dataHashCode = -122903935
@ -1746,16 +1716,16 @@ sample:
presentationTimeUs = 1970340
sample:
trackIndex = 1
dataHashCode = 1940582145
size = 3080
dataHashCode = 693101697
size = 28
isKeyFrame = true
presentationTimeUs = 1999841
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 243395457
size = 7012
isKeyFrame = true
presentationTimeUs = 2017301
presentationTimeUs = 2000000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1872,16 +1842,16 @@ sample:
presentationTimeUs = 2458752
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -1476683391
size = 3316
isKeyFrame = true
presentationTimeUs = 2481201
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -1993784959
size = 5044
isKeyFrame = true
presentationTimeUs = 2503650
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1938,16 +1908,10 @@ sample:
presentationTimeUs = 2713151
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 2735600
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 2760544
sample:
trackIndex = 1
dataHashCode = 571187457
@ -2004,16 +1968,16 @@ sample:
presentationTimeUs = 2967551
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2055611009
size = 1324
isKeyFrame = true
presentationTimeUs = 2992494
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -76324991
size = 6596
isKeyFrame = true
presentationTimeUs = 3014943
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2040,16 +2004,10 @@ sample:
presentationTimeUs = 3107233
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3132154
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3154603
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2088,16 +2046,10 @@ sample:
presentationTimeUs = 3294285
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 3316734
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 3339183
sample:
trackIndex = 1
dataHashCode = -448902783
@ -2130,16 +2082,16 @@ sample:
presentationTimeUs = 3456394
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 1120019841
size = 3732
isKeyFrame = true
presentationTimeUs = 3478843
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 454210945
size = 4628
isKeyFrame = true
presentationTimeUs = 3503786
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -2154,16 +2106,10 @@ sample:
presentationTimeUs = 3548684
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3573628
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3596077
sample:
trackIndex = 1
dataHashCode = -448902783
@ -2196,16 +2142,10 @@ sample:
presentationTimeUs = 3710793
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3735736
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3758185
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2244,16 +2184,10 @@ sample:
presentationTimeUs = 3897845
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 3920294
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 3942743
sample:
trackIndex = 1
dataHashCode = -1759454975

View file

@ -1350,16 +1350,16 @@ sample:
presentationTimeUs = 464399
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1728208641
size = 2184
isKeyFrame = true
presentationTimeUs = 487619
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 620404993
size = 6008
isKeyFrame = true
presentationTimeUs = 510839
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1428,16 +1428,10 @@ sample:
presentationTimeUs = 766258
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 789478
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 812698
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1482,16 +1476,16 @@ sample:
presentationTimeUs = 975238
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1097317889
size = 272
isKeyFrame = true
presentationTimeUs = 998458
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1021678
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1530,16 +1524,10 @@ sample:
presentationTimeUs = 1160997
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1184217
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1207437
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1590,16 +1578,10 @@ sample:
presentationTimeUs = 1393197
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1416417
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1439637
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1608,16 +1590,16 @@ sample:
presentationTimeUs = 1462857
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -1544807167
size = 2456
isKeyFrame = true
presentationTimeUs = 1486077
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 370729729
size = 5736
isKeyFrame = true
presentationTimeUs = 1509297
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1632,16 +1614,10 @@ sample:
presentationTimeUs = 1555736
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1578956
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1602176
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1692,16 +1668,10 @@ sample:
presentationTimeUs = 1787936
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1811156
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1834376
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1734,16 +1704,10 @@ sample:
presentationTimeUs = 1950476
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -474907647
size = 4640
isKeyFrame = true
presentationTimeUs = 1973696
sample:
trackIndex = 1
dataHashCode = -204243967
size = 544
isKeyFrame = true
presentationTimeUs = 1996916
sample:
trackIndex = 1
dataHashCode = 838148193
@ -1884,16 +1848,16 @@ sample:
presentationTimeUs = 2469319
sample:
trackIndex = 1
dataHashCode = -356476264
size = 3760
dataHashCode = 1775616337
size = 3528
isKeyFrame = true
presentationTimeUs = 2480000
sample:
trackIndex = 1
dataHashCode = 809912661
size = 3764
dataHashCode = 931216668
size = 3996
isKeyFrame = true
presentationTimeUs = 2501315
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = 16108289
@ -2028,16 +1992,16 @@ sample:
presentationTimeUs = 2960000
sample:
trackIndex = 1
dataHashCode = -1130552658
size = 3764
dataHashCode = 1297632614
size = 3296
isKeyFrame = true
presentationTimeUs = 2981315
sample:
trackIndex = 1
dataHashCode = -81801022
size = 3764
dataHashCode = -1698066806
size = 4232
isKeyFrame = true
presentationTimeUs = 3002653
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = 1930678601
@ -2172,16 +2136,16 @@ sample:
presentationTimeUs = 3461315
sample:
trackIndex = 1
dataHashCode = -884616159
size = 3764
dataHashCode = 624992026
size = 3060
isKeyFrame = true
presentationTimeUs = 3482653
sample:
trackIndex = 1
dataHashCode = 355349249
size = 3764
dataHashCode = -1816384888
size = 4468
isKeyFrame = true
presentationTimeUs = 3503990
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 1234475840

View file

@ -1350,16 +1350,16 @@ sample:
presentationTimeUs = 458911
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 836580609
size = 3288
isKeyFrame = true
presentationTimeUs = 481360
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -1141905919
size = 5072
isKeyFrame = true
presentationTimeUs = 503809
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1428,16 +1428,10 @@ sample:
presentationTimeUs = 760702
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 783151
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 805600
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1482,16 +1476,16 @@ sample:
presentationTimeUs = 967709
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 744439297
size = 1296
isKeyFrame = true
presentationTimeUs = 992653
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -1744763903
size = 6624
isKeyFrame = true
presentationTimeUs = 1015102
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -1530,16 +1524,10 @@ sample:
presentationTimeUs = 1154761
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1177210
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1202154
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1590,16 +1578,10 @@ sample:
presentationTimeUs = 1386712
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1409160
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1434104
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1608,16 +1590,16 @@ sample:
presentationTimeUs = 1456553
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -206716671
size = 3704
isKeyFrame = true
presentationTimeUs = 1479002
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -102540799
size = 4656
isKeyFrame = true
presentationTimeUs = 1503945
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1632,16 +1614,10 @@ sample:
presentationTimeUs = 1548843
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1573786
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1596235
sample:
trackIndex = 1
dataHashCode = -448902783
@ -1692,16 +1668,10 @@ sample:
presentationTimeUs = 1780793
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1805736
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1828185
sample:
trackIndex = 1
dataHashCode = -122903935
@ -1746,16 +1716,16 @@ sample:
presentationTimeUs = 1970340
sample:
trackIndex = 1
dataHashCode = -1729993902
size = 2592
dataHashCode = -752508258
size = 28
isKeyFrame = true
presentationTimeUs = 1999841
sample:
trackIndex = 1
dataHashCode = -1258890392
size = 3412
dataHashCode = -327634788
size = 5976
isKeyFrame = true
presentationTimeUs = 2014535
presentationTimeUs = 2000000
sample:
trackIndex = 1
dataHashCode = 207476260
@ -1890,16 +1860,16 @@ sample:
presentationTimeUs = 2472879
sample:
trackIndex = 1
dataHashCode = 471755676
size = 5052
dataHashCode = -607505416
size = 1016
isKeyFrame = true
presentationTimeUs = 2494240
sample:
trackIndex = 1
dataHashCode = 1234125105
size = 2060
dataHashCode = 1452244565
size = 6096
isKeyFrame = true
presentationTimeUs = 2522879
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = -1604998992
@ -2034,10 +2004,16 @@ sample:
presentationTimeUs = 2973514
sample:
trackIndex = 1
dataHashCode = 1265834707
size = 3628
dataHashCode = 1336560411
size = 872
isKeyFrame = true
presentationTimeUs = 2995056
sample:
trackIndex = 1
dataHashCode = -107356999
size = 2756
isKeyFrame = true
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = 1435145598
@ -2178,16 +2154,16 @@ sample:
presentationTimeUs = 3475034
sample:
trackIndex = 1
dataHashCode = 1365512037
size = 3868
dataHashCode = -474273643
size = 948
isKeyFrame = true
presentationTimeUs = 3494625
sample:
trackIndex = 1
dataHashCode = 1204502935
size = 3648
dataHashCode = 1428876391
size = 6568
isKeyFrame = true
presentationTimeUs = 3516553
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 829064633

View file

@ -1350,16 +1350,16 @@ sample:
presentationTimeUs = 458911
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 836580609
size = 3288
isKeyFrame = true
presentationTimeUs = 481360
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -1141905919
size = 5072
isKeyFrame = true
presentationTimeUs = 503809
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1428,16 +1428,10 @@ sample:
presentationTimeUs = 760702
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 783151
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 805600
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1482,16 +1476,16 @@ sample:
presentationTimeUs = 967709
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 744439297
size = 1296
isKeyFrame = true
presentationTimeUs = 992653
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -1744763903
size = 6624
isKeyFrame = true
presentationTimeUs = 1015102
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -1530,16 +1524,10 @@ sample:
presentationTimeUs = 1154761
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1177210
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1202154
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1590,16 +1578,10 @@ sample:
presentationTimeUs = 1386712
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1409160
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1434104
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1608,16 +1590,16 @@ sample:
presentationTimeUs = 1456553
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -206716671
size = 3704
isKeyFrame = true
presentationTimeUs = 1479002
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -102540799
size = 4656
isKeyFrame = true
presentationTimeUs = 1503945
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1632,16 +1614,10 @@ sample:
presentationTimeUs = 1548843
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1573786
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1596235
sample:
trackIndex = 1
dataHashCode = -448902783
@ -1692,16 +1668,10 @@ sample:
presentationTimeUs = 1780793
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1805736
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1828185
sample:
trackIndex = 1
dataHashCode = -122903935
@ -1746,16 +1716,16 @@ sample:
presentationTimeUs = 1970340
sample:
trackIndex = 1
dataHashCode = 1940582145
size = 3080
dataHashCode = 693101697
size = 28
isKeyFrame = true
presentationTimeUs = 1999841
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 243395457
size = 7012
isKeyFrame = true
presentationTimeUs = 2017301
presentationTimeUs = 2000000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1872,16 +1842,16 @@ sample:
presentationTimeUs = 2458752
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -1476683391
size = 3316
isKeyFrame = true
presentationTimeUs = 2481201
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -1993784959
size = 5044
isKeyFrame = true
presentationTimeUs = 2503650
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1938,16 +1908,10 @@ sample:
presentationTimeUs = 2713151
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 2735600
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 2760544
sample:
trackIndex = 1
dataHashCode = 571187457
@ -2004,16 +1968,16 @@ sample:
presentationTimeUs = 2967551
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2055611009
size = 1324
isKeyFrame = true
presentationTimeUs = 2992494
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -76324991
size = 6596
isKeyFrame = true
presentationTimeUs = 3014943
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2040,16 +2004,10 @@ sample:
presentationTimeUs = 3107233
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3132154
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3154603
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2088,16 +2046,10 @@ sample:
presentationTimeUs = 3294285
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 3316734
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 3339183
sample:
trackIndex = 1
dataHashCode = -448902783
@ -2130,16 +2082,16 @@ sample:
presentationTimeUs = 3456394
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 1120019841
size = 3732
isKeyFrame = true
presentationTimeUs = 3478843
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 454210945
size = 4628
isKeyFrame = true
presentationTimeUs = 3503786
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -2154,16 +2106,10 @@ sample:
presentationTimeUs = 3548684
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3573628
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3596077
sample:
trackIndex = 1
dataHashCode = -448902783
@ -2196,16 +2142,10 @@ sample:
presentationTimeUs = 3710793
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3735736
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3758185
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2244,16 +2184,10 @@ sample:
presentationTimeUs = 3897845
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 3920294
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 3942743
sample:
trackIndex = 1
dataHashCode = -1759454975

View file

@ -1350,16 +1350,16 @@ sample:
presentationTimeUs = 464399
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1728208641
size = 2184
isKeyFrame = true
presentationTimeUs = 487619
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 620404993
size = 6008
isKeyFrame = true
presentationTimeUs = 510839
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1428,16 +1428,10 @@ sample:
presentationTimeUs = 766258
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 789478
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 812698
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1482,16 +1476,16 @@ sample:
presentationTimeUs = 975238
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1097317889
size = 272
isKeyFrame = true
presentationTimeUs = 998458
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1021678
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1530,16 +1524,10 @@ sample:
presentationTimeUs = 1160997
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1184217
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1207437
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1590,16 +1578,10 @@ sample:
presentationTimeUs = 1393197
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1416417
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1439637
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1608,16 +1590,16 @@ sample:
presentationTimeUs = 1462857
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -1544807167
size = 2456
isKeyFrame = true
presentationTimeUs = 1486077
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 370729729
size = 5736
isKeyFrame = true
presentationTimeUs = 1509297
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1632,16 +1614,10 @@ sample:
presentationTimeUs = 1555736
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1578956
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1602176
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1692,16 +1668,10 @@ sample:
presentationTimeUs = 1787936
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 1811156
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 1834376
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1734,16 +1704,10 @@ sample:
presentationTimeUs = 1950476
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -474907647
size = 4640
isKeyFrame = true
presentationTimeUs = 1973696
sample:
trackIndex = 1
dataHashCode = -204243967
size = 544
isKeyFrame = true
presentationTimeUs = 1996916
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1872,16 +1836,16 @@ sample:
presentationTimeUs = 2464399
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1728208641
size = 2184
isKeyFrame = true
presentationTimeUs = 2487619
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 620404993
size = 6008
isKeyFrame = true
presentationTimeUs = 2510839
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -1938,16 +1902,10 @@ sample:
presentationTimeUs = 2719818
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 2743038
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 2766258
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2004,16 +1962,16 @@ sample:
presentationTimeUs = 2975238
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 1097317889
size = 272
isKeyFrame = true
presentationTimeUs = 2998458
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3021678
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2040,16 +1998,10 @@ sample:
presentationTimeUs = 3114557
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3137777
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3160997
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2088,16 +2040,10 @@ sample:
presentationTimeUs = 3300317
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3323537
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3346757
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2130,16 +2076,16 @@ sample:
presentationTimeUs = 3462857
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -1544807167
size = 2456
isKeyFrame = true
presentationTimeUs = 3486077
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = 370729729
size = 5736
isKeyFrame = true
presentationTimeUs = 3509297
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2154,16 +2100,10 @@ sample:
presentationTimeUs = 3555736
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3578956
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3602176
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2196,16 +2136,10 @@ sample:
presentationTimeUs = 3718276
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3741496
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3764716
sample:
trackIndex = 1
dataHashCode = 1742602241
@ -2238,16 +2172,10 @@ sample:
presentationTimeUs = 3880816
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
dataHashCode = -809762815
size = 8192
isKeyFrame = true
presentationTimeUs = 3904036
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 3927256
sample:
trackIndex = 1
dataHashCode = 1742602241

View file

@ -1350,16 +1350,16 @@ sample:
presentationTimeUs = 458911
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 836580609
size = 3288
isKeyFrame = true
presentationTimeUs = 481360
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -1141905919
size = 5072
isKeyFrame = true
presentationTimeUs = 503809
presentationTimeUs = 500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1428,16 +1428,10 @@ sample:
presentationTimeUs = 760702
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 783151
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 805600
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1482,16 +1476,16 @@ sample:
presentationTimeUs = 967709
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 744439297
size = 1296
isKeyFrame = true
presentationTimeUs = 992653
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -1744763903
size = 6624
isKeyFrame = true
presentationTimeUs = 1015102
presentationTimeUs = 1000000
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -1530,16 +1524,10 @@ sample:
presentationTimeUs = 1154761
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1177210
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1202154
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1590,16 +1578,10 @@ sample:
presentationTimeUs = 1386712
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 1409160
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1434104
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1608,16 +1590,16 @@ sample:
presentationTimeUs = 1456553
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -206716671
size = 3704
isKeyFrame = true
presentationTimeUs = 1479002
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -102540799
size = 4656
isKeyFrame = true
presentationTimeUs = 1503945
presentationTimeUs = 1500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1632,16 +1614,10 @@ sample:
presentationTimeUs = 1548843
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1573786
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1596235
sample:
trackIndex = 1
dataHashCode = -448902783
@ -1692,16 +1668,10 @@ sample:
presentationTimeUs = 1780793
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 1805736
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 1828185
sample:
trackIndex = 1
dataHashCode = -122903935
@ -1746,16 +1716,16 @@ sample:
presentationTimeUs = 1970340
sample:
trackIndex = 1
dataHashCode = 1940582145
size = 3080
dataHashCode = 693101697
size = 28
isKeyFrame = true
presentationTimeUs = 1999841
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 243395457
size = 7012
isKeyFrame = true
presentationTimeUs = 2017301
presentationTimeUs = 2000000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1872,16 +1842,16 @@ sample:
presentationTimeUs = 2458752
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -1476683391
size = 3316
isKeyFrame = true
presentationTimeUs = 2481201
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = -1993784959
size = 5044
isKeyFrame = true
presentationTimeUs = 2503650
presentationTimeUs = 2500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -1938,16 +1908,10 @@ sample:
presentationTimeUs = 2713151
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 2735600
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 2760544
sample:
trackIndex = 1
dataHashCode = 571187457
@ -2004,16 +1968,16 @@ sample:
presentationTimeUs = 2967551
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2055611009
size = 1324
isKeyFrame = true
presentationTimeUs = 2992494
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = -76324991
size = 6596
isKeyFrame = true
presentationTimeUs = 3014943
presentationTimeUs = 3000000
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2040,16 +2004,10 @@ sample:
presentationTimeUs = 3107233
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3132154
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3154603
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2088,16 +2046,10 @@ sample:
presentationTimeUs = 3294285
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 3316734
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 3339183
sample:
trackIndex = 1
dataHashCode = -448902783
@ -2130,16 +2082,16 @@ sample:
presentationTimeUs = 3456394
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
dataHashCode = 1120019841
size = 3732
isKeyFrame = true
presentationTimeUs = 3478843
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 454210945
size = 4628
isKeyFrame = true
presentationTimeUs = 3503786
presentationTimeUs = 3500000
sample:
trackIndex = 1
dataHashCode = 571187457
@ -2154,16 +2106,10 @@ sample:
presentationTimeUs = 3548684
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3573628
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3596077
sample:
trackIndex = 1
dataHashCode = -448902783
@ -2196,16 +2142,10 @@ sample:
presentationTimeUs = 3710793
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 2136490497
size = 7920
isKeyFrame = true
presentationTimeUs = 3735736
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
isKeyFrame = true
presentationTimeUs = 3758185
sample:
trackIndex = 1
dataHashCode = -1264223743
@ -2244,16 +2184,10 @@ sample:
presentationTimeUs = 3897845
sample:
trackIndex = 1
dataHashCode = 571187457
size = 3960
dataHashCode = 644553473
size = 8360
isKeyFrame = true
presentationTimeUs = 3920294
sample:
trackIndex = 1
dataHashCode = -1264223743
size = 4400
isKeyFrame = true
presentationTimeUs = 3942743
sample:
trackIndex = 1
dataHashCode = -1759454975

View file

@ -36,16 +36,16 @@ sample:
presentationTimeUs = 370748
sample:
trackIndex = 0
dataHashCode = 13583718
size = 8968
dataHashCode = -1241547797
size = 2192
isKeyFrame = true
presentationTimeUs = 475147
sample:
trackIndex = 0
dataHashCode = -1444602526
size = 8588
dataHashCode = -1607988131
size = 15364
isKeyFrame = true
presentationTimeUs = 576825
presentationTimeUs = 500000
sample:
trackIndex = 0
dataHashCode = -1693065958
@ -72,16 +72,16 @@ sample:
presentationTimeUs = 970680
sample:
trackIndex = 0
dataHashCode = 2042155098
size = 6482
dataHashCode = 887503681
size = 6
isKeyFrame = true
presentationTimeUs = 999931
sample:
trackIndex = 0
dataHashCode = 1417355469
size = 8556
dataHashCode = -1294750618
size = 15032
isKeyFrame = true
presentationTimeUs = 1073424
presentationTimeUs = 1000000
sample:
trackIndex = 0
dataHashCode = -2107697498
@ -102,16 +102,16 @@ sample:
presentationTimeUs = 1370680
sample:
trackIndex = 0
dataHashCode = 13583718
size = 8968
dataHashCode = 1453487712
size = 2198
isKeyFrame = true
presentationTimeUs = 1475079
sample:
trackIndex = 0
dataHashCode = -1444602526
size = 8588
dataHashCode = 209617192
size = 15358
isKeyFrame = true
presentationTimeUs = 1576757
presentationTimeUs = 1500000
sample:
trackIndex = 0
dataHashCode = -1693065958

View file

@ -0,0 +1,67 @@
format 0:
averageBitrate = 131072
sampleMimeType = audio/mp4a-latm
channelCount = 1
sampleRate = 44100
pcmEncoding = 2
sample:
trackIndex = 0
dataHashCode = 1365664853
size = 8820
isKeyFrame = true
presentationTimeUs = 0
sample:
trackIndex = 0
dataHashCode = -1466730976
size = 8820
isKeyFrame = true
presentationTimeUs = 100000
sample:
trackIndex = 0
dataHashCode = 1178728837
size = 8820
isKeyFrame = true
presentationTimeUs = 200000
sample:
trackIndex = 0
dataHashCode = -216459624
size = 8820
isKeyFrame = true
presentationTimeUs = 300000
sample:
trackIndex = 0
dataHashCode = 1990341112
size = 8820
isKeyFrame = true
presentationTimeUs = 400000
sample:
trackIndex = 0
dataHashCode = 1561236782
size = 8820
isKeyFrame = true
presentationTimeUs = 500000
sample:
trackIndex = 0
dataHashCode = 1146352887
size = 8820
isKeyFrame = true
presentationTimeUs = 600000
sample:
trackIndex = 0
dataHashCode = 1061204212
size = 8820
isKeyFrame = true
presentationTimeUs = 700000
sample:
trackIndex = 0
dataHashCode = 840187559
size = 8820
isKeyFrame = true
presentationTimeUs = 800000
sample:
trackIndex = 0
dataHashCode = -29240395
size = 8820
isKeyFrame = true
presentationTimeUs = 900000
released = true

View file

@ -36,16 +36,16 @@ sample:
presentationTimeUs = 370748
sample:
trackIndex = 0
dataHashCode = 13583718
size = 8968
dataHashCode = -1241547797
size = 2192
isKeyFrame = true
presentationTimeUs = 475147
sample:
trackIndex = 0
dataHashCode = -1444602526
size = 8588
dataHashCode = -1607988131
size = 15364
isKeyFrame = true
presentationTimeUs = 576825
presentationTimeUs = 500000
sample:
trackIndex = 0
dataHashCode = -1693065958
@ -72,16 +72,16 @@ sample:
presentationTimeUs = 970680
sample:
trackIndex = 0
dataHashCode = 2002762528
size = 6450
dataHashCode = 887503681
size = 6
isKeyFrame = true
presentationTimeUs = 999931
sample:
trackIndex = 0
dataHashCode = -657557348
size = 9288
dataHashCode = -1218473605
size = 15732
isKeyFrame = true
presentationTimeUs = 1073061
presentationTimeUs = 1000000
sample:
trackIndex = 0
dataHashCode = 1101737790
@ -102,16 +102,16 @@ sample:
presentationTimeUs = 1377981
sample:
trackIndex = 0
dataHashCode = -1146784158
size = 7898
dataHashCode = 403097819
size = 1586
isKeyFrame = true
presentationTimeUs = 1482018
sample:
trackIndex = 0
dataHashCode = -108739018
size = 9244
dataHashCode = 1889137981
size = 15556
isKeyFrame = true
presentationTimeUs = 1571564
presentationTimeUs = 1500000
sample:
trackIndex = 0
dataHashCode = 1527742727
@ -132,8 +132,14 @@ sample:
presentationTimeUs = 1869365
sample:
trackIndex = 0
dataHashCode = -2024887086
size = 1312
dataHashCode = -1794283843
size = 1310
isKeyFrame = true
presentationTimeUs = 1985147
sample:
trackIndex = 0
dataHashCode = 1302
size = 2
isKeyFrame = true
presentationTimeUs = 2000000
released = true

View file

@ -42,16 +42,16 @@ sample:
presentationTimeUs = 348645
sample:
trackIndex = 0
dataHashCode = 591641755
size = 18624
dataHashCode = 554484641
size = 14952
isKeyFrame = true
presentationTimeUs = 422125
sample:
trackIndex = 0
dataHashCode = -909124577
size = 19056
dataHashCode = -1596995303
size = 22728
isKeyFrame = true
presentationTimeUs = 519125
presentationTimeUs = 500000
sample:
trackIndex = 0
dataHashCode = -1644849415
@ -72,16 +72,16 @@ sample:
presentationTimeUs = 823770
sample:
trackIndex = 0
dataHashCode = -1348998373
size = 18696
dataHashCode = 1994534499
size = 14312
isKeyFrame = true
presentationTimeUs = 925458
sample:
trackIndex = 0
dataHashCode = 1191266277
size = 19108
dataHashCode = -258879331
size = 23492
isKeyFrame = true
presentationTimeUs = 1022833
presentationTimeUs = 1000000
sample:
trackIndex = 0
dataHashCode = -1278785599

View file

@ -42,16 +42,16 @@ sample:
presentationTimeUs = 348645
sample:
trackIndex = 0
dataHashCode = -555451391
size = 20216
dataHashCode = 804848209
size = 15020
isKeyFrame = true
presentationTimeUs = 421770
sample:
trackIndex = 0
dataHashCode = 1700905759
size = 17472
dataHashCode = -95210289
size = 22668
isKeyFrame = true
presentationTimeUs = 527062
presentationTimeUs = 500000
sample:
trackIndex = 0
dataHashCode = -416119019
@ -72,16 +72,16 @@ sample:
presentationTimeUs = 830729
sample:
trackIndex = 0
dataHashCode = 956501205
size = 20124
dataHashCode = 1298593295
size = 15308
isKeyFrame = true
presentationTimeUs = 920270
sample:
trackIndex = 0
dataHashCode = 299859135
size = 18748
dataHashCode = -1669619067
size = 23564
isKeyFrame = true
presentationTimeUs = 1025083
presentationTimeUs = 1000000
sample:
trackIndex = 0
dataHashCode = 636945085

View file

@ -36,16 +36,16 @@ sample:
presentationTimeUs = 348625
sample:
trackIndex = 0
dataHashCode = -877978019
size = 19200
dataHashCode = -1794464029
size = 9868
isKeyFrame = true
presentationTimeUs = 448604
sample:
trackIndex = 0
dataHashCode = 903565693
size = 19200
dataHashCode = -328768009
size = 28532
isKeyFrame = true
presentationTimeUs = 548604
presentationTimeUs = 500000
sample:
trackIndex = 0
dataHashCode = -1424006305
@ -66,16 +66,16 @@ sample:
presentationTimeUs = 848604
sample:
trackIndex = 0
dataHashCode = -510424155
size = 19200
dataHashCode = -437038979
size = 9868
isKeyFrame = true
presentationTimeUs = 948604
sample:
trackIndex = 0
dataHashCode = 13706341
size = 19200
dataHashCode = 409224589
size = 28532
isKeyFrame = true
presentationTimeUs = 1048604
presentationTimeUs = 1000000
sample:
trackIndex = 0
dataHashCode = -1421600077

View file

@ -16,6 +16,7 @@
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.transformer.AndroidTestUtil.JPG_ASSET_URI_STRING;
import static androidx.media3.transformer.AndroidTestUtil.MP3_ASSET_URI_STRING;
import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_FORMAT;
import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_URI_STRING;
@ -70,6 +71,81 @@ public class TransformerEndToEndTest {
private final Context context = ApplicationProvider.getApplicationContext();
private volatile @MonotonicNonNull TextureAssetLoader textureAssetLoader;
@Test
public void compositionEditing_withThreeSequences_completes() throws Exception {
String testId = "compositionEditing_withThreeSequences_completes";
Transformer transformer = new Transformer.Builder(context).build();
if (AndroidTestUtil.skipAndLogIfFormatsUnsupported(
context,
testId,
/* inputFormat= */ MP4_ASSET_FORMAT,
/* outputFormat= */ MP4_ASSET_FORMAT)) {
return;
}
EditedMediaItem audioVideoItem =
new EditedMediaItem.Builder(MediaItem.fromUri(MP4_ASSET_URI_STRING))
.setEffects(
new Effects(
ImmutableList.of(createSonic(/* pitch= */ 2f)),
ImmutableList.of(RgbFilter.createInvertedFilter())))
.build();
EditedMediaItem imageItem =
new EditedMediaItem.Builder(MediaItem.fromUri(JPG_ASSET_URI_STRING))
.setDurationUs(1_500_000)
.setFrameRate(30)
.build();
EditedMediaItemSequence audioVideoSequence =
new EditedMediaItemSequence(ImmutableList.of(audioVideoItem, imageItem, audioVideoItem));
EditedMediaItem.Builder audioBuilder =
new EditedMediaItem.Builder(MediaItem.fromUri(MP4_ASSET_URI_STRING)).setRemoveVideo(true);
EditedMediaItemSequence audioSequence =
new EditedMediaItemSequence(
ImmutableList.of(
audioBuilder
.setEffects(
new Effects(
ImmutableList.of(createSonic(/* pitch= */ 1.3f)),
/* videoEffects= */ ImmutableList.of()))
.build(),
audioBuilder
.setEffects(
new Effects(
ImmutableList.of(createSonic(/* pitch= */ 0.85f)),
/* videoEffects= */ ImmutableList.of()))
.build()));
EditedMediaItemSequence audioLoopingSequence =
new EditedMediaItemSequence(
ImmutableList.of(
audioBuilder
.setEffects(
new Effects(
ImmutableList.of(createSonic(/* pitch= */ 0.4f)),
/* videoEffects= */ ImmutableList.of()))
.build()),
/* isLooping= */ true);
Composition composition =
new Composition.Builder(
ImmutableList.of(audioVideoSequence, audioSequence, audioLoopingSequence))
.build();
ExportTestResult result =
new TransformerAndroidTestRunner.Builder(context, transformer)
.build()
.run(testId, composition);
// MP4_ASSET duration is ~1s.
// Image asset duration is ~1.5s.
// audioVideoSequence duration: ~3.5s (3 inputs).
// audioSequence duration: ~2s (2 inputs).
// audioLoopingSequence: Matches max other sequence (~3.5s) -> 4 inputs of ~1s audio item.
assertThat(result.exportResult.processedInputs).hasSize(9);
}
@Test
public void videoEditing_withImageInput_completesWithCorrectFrameCountAndDuration()
throws Exception {
@ -403,7 +479,7 @@ public class TransformerEndToEndTest {
/* outputFormat= */ MP4_ASSET_FORMAT)) {
return;
}
ImmutableList<AudioProcessor> audioProcessors = ImmutableList.of(new SonicAudioProcessor());
ImmutableList<AudioProcessor> audioProcessors = ImmutableList.of(createSonic(1.2f));
ImmutableList<Effect> videoEffects = ImmutableList.of(RgbFilter.createGrayscaleFilter());
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_URI_STRING));
EditedMediaItem editedMediaItem =
@ -613,4 +689,10 @@ public class TransformerEndToEndTest {
return true;
}
}
private static AudioProcessor createSonic(float pitch) {
SonicAudioProcessor sonic = new SonicAudioProcessor();
sonic.setPitch(pitch);
return sonic;
}
}

View file

@ -18,363 +18,112 @@ package androidx.media3.transformer;
import static androidx.media3.common.audio.AudioProcessor.EMPTY_BUFFER;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT;
import androidx.annotation.Nullable;
import android.util.SparseArray;
import androidx.media3.common.C;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.audio.AudioProcessingPipeline;
import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.audio.AudioProcessor.AudioFormat;
import androidx.media3.common.audio.AudioProcessor.UnhandledAudioFormatException;
import androidx.media3.common.audio.ChannelMixingAudioProcessor;
import androidx.media3.common.audio.ChannelMixingMatrix;
import androidx.media3.common.audio.SonicAudioProcessor;
import androidx.media3.common.audio.SpeedChangingAudioProcessor;
import androidx.media3.common.util.NullableType;
import androidx.media3.decoder.DecoderInputBuffer;
import com.google.common.collect.ImmutableList;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicReference;
/** Processes raw audio samples. */
/* package */ final class AudioGraph implements GraphInput {
private static final int MAX_INPUT_BUFFER_COUNT = 10;
private final AudioFormat outputAudioFormat;
private final SilentAudioGenerator silentAudioGenerator;
private final Queue<DecoderInputBuffer> availableInputBuffers;
private final Queue<DecoderInputBuffer> pendingInputBuffers;
private final AtomicReference<@NullableType MediaItemChange> pendingMediaItemChange;
/* package */ final class AudioGraph {
private final AudioMixerImpl mixer;
private final SparseArray<AudioGraphInput> inputs;
@Nullable private DecoderInputBuffer currentInputBufferBeingOutput;
private AudioProcessingPipeline audioProcessingPipeline;
private boolean processedFirstMediaItemChange;
private boolean receivedEndOfStreamFromInput;
private boolean queueEndOfStreamAfterSilence;
private int finishedInputs;
private ByteBuffer currentOutput;
// TODO(b/260618558): Move silent audio generation upstream of this component.
public AudioGraph(Format firstInputFormat, EditedMediaItem firstEditedMediaItem)
throws UnhandledAudioFormatException {
checkArgument(firstInputFormat.pcmEncoding != Format.NO_VALUE);
availableInputBuffers = new ConcurrentLinkedDeque<>();
ByteBuffer emptyBuffer = ByteBuffer.allocateDirect(0).order(ByteOrder.nativeOrder());
for (int i = 0; i < MAX_INPUT_BUFFER_COUNT; i++) {
DecoderInputBuffer inputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DIRECT);
inputBuffer.data = emptyBuffer;
availableInputBuffers.add(inputBuffer);
}
pendingInputBuffers = new ConcurrentLinkedDeque<>();
pendingMediaItemChange = new AtomicReference<>();
AudioFormat inputAudioFormat = new AudioFormat(firstInputFormat);
silentAudioGenerator = new SilentAudioGenerator(inputAudioFormat);
audioProcessingPipeline =
configureProcessing(
/* editedMediaItem= */ firstEditedMediaItem,
/* trackFormat= */ firstInputFormat,
/* inputAudioFormat= */ inputAudioFormat,
/* requiredOutputAudioFormat= */ AudioFormat.NOT_SET);
// APP configuration not active until flush called. getOutputAudioFormat based on active config.
audioProcessingPipeline.flush();
outputAudioFormat = audioProcessingPipeline.getOutputAudioFormat();
/** Creates an instance. */
public AudioGraph() {
mixer = new AudioMixerImpl(/* outputSilenceWithNoSources= */ false);
inputs = new SparseArray<>();
currentOutput = EMPTY_BUFFER;
}
public AudioFormat getOutputAudioFormat() {
return outputAudioFormat;
/** Returns a new {@link AudioGraphInput} instance. */
public AudioGraphInput registerInput(EditedMediaItem item, Format format) throws ExportException {
checkArgument(format.pcmEncoding != Format.NO_VALUE);
try {
AudioGraphInput audioGraphInput = new AudioGraphInput(item, format);
if (inputs.size() == 0) {
mixer.configure(
audioGraphInput.getOutputAudioFormat(),
/* bufferSizeMs= */ C.LENGTH_UNSET,
/* startTimeUs= */ 0);
}
int sourceId = mixer.addSource(audioGraphInput.getOutputAudioFormat(), /* startTimeUs= */ 0);
inputs.append(sourceId, audioGraphInput);
return audioGraphInput;
} catch (UnhandledAudioFormatException e) {
throw ExportException.createForAudioProcessing(e, "existingInputs=" + inputs.size());
}
}
/**
* Returns a {@link ByteBuffer} of output.
* Returns the {@link AudioFormat} of the {@linkplain #getOutput() output}.
*
* @throws ExportException If the configuration of underlying components fails as a result of
* upstream changes.
* <p>{@link AudioFormat#NOT_SET} is returned if no inputs have been {@linkplain #registerInput
* registered}.
*/
public AudioFormat getOutputAudioFormat() {
return mixer.getOutputAudioFormat();
}
/**
* Returns a {@link ByteBuffer} containing output data between the position and limit.
*
* <p>The same buffer is returned until it has been fully consumed ({@code position == limit}).
*/
public ByteBuffer getOutput() throws ExportException {
ByteBuffer outputBuffer = getOutputInternal();
if (outputBuffer.hasRemaining()) {
return outputBuffer;
if (!mixer.isEnded()) {
feedMixer();
}
if (!hasDataToOutput() && pendingMediaItemChange.get() != null) {
try {
configureForPendingMediaItemChange();
} catch (AudioProcessor.UnhandledAudioFormatException e) {
throw ExportException.createForAudioProcessing(e, "AudioGraph reconfiguration");
}
if (currentOutput.hasRemaining()) {
return currentOutput;
}
return EMPTY_BUFFER;
}
@Override
public void onMediaItemChanged(
EditedMediaItem editedMediaItem,
long durationUs,
@Nullable Format trackFormat,
boolean isLast) {
if (trackFormat == null) {
checkState(
durationUs != C.TIME_UNSET,
"Could not generate silent audio because duration is unknown.");
} else {
checkState(MimeTypes.isAudio(trackFormat.sampleMimeType));
checkState(trackFormat.pcmEncoding != Format.NO_VALUE);
}
pendingMediaItemChange.set(
new MediaItemChange(editedMediaItem, durationUs, trackFormat, isLast));
}
@Override
@Nullable
public DecoderInputBuffer getInputBuffer() {
if (silentAudioGenerator.hasRemaining() || pendingMediaItemChange.get() != null) {
return null;
}
return availableInputBuffers.peek();
}
@Override
public boolean queueInputBuffer() {
checkState(pendingMediaItemChange.get() == null);
DecoderInputBuffer inputBuffer = availableInputBuffers.remove();
pendingInputBuffers.add(inputBuffer);
return true;
currentOutput = mixer.getOutput();
return currentOutput;
}
/** Releases underlying resources, including clearing the inputs. */
public void release() {
audioProcessingPipeline.reset();
for (int i = 0; i < inputs.size(); i++) {
inputs.valueAt(i).release();
}
inputs.clear();
mixer.reset();
}
/** Returns whether the input has ended and all queued data has been output. */
public boolean isEnded() {
if (hasDataToOutput()) {
return false;
}
if (pendingMediaItemChange.get() != null) {
return false;
}
return receivedEndOfStreamFromInput || queueEndOfStreamAfterSilence;
return !currentOutput.hasRemaining() && finishedInputs >= inputs.size() && mixer.isEnded();
}
private ByteBuffer getOutputInternal() {
if (!processedFirstMediaItemChange) {
return EMPTY_BUFFER;
private void feedMixer() throws ExportException {
for (int i = 0; i < inputs.size(); i++) {
feedMixerFromInput(inputs.keyAt(i), inputs.valueAt(i));
}
if (!audioProcessingPipeline.isOperational()) {
return feedOutputFromInput();
}
// Ensure APP progresses as much as possible.
while (feedProcessingPipelineFromInput()) {}
return audioProcessingPipeline.getOutput();
}
private boolean feedProcessingPipelineFromInput() {
if (silentAudioGenerator.hasRemaining()) {
ByteBuffer inputData = silentAudioGenerator.getBuffer();
audioProcessingPipeline.queueInput(inputData);
if (inputData.hasRemaining()) {
return false;
}
if (!silentAudioGenerator.hasRemaining()) {
audioProcessingPipeline.queueEndOfStream();
return false;
}
return true;
private void feedMixerFromInput(int sourceId, AudioGraphInput input) throws ExportException {
if (!mixer.hasSource(sourceId)) {
return;
}
@Nullable DecoderInputBuffer pendingInputBuffer = pendingInputBuffers.peek();
if (pendingInputBuffer == null) {
if (pendingMediaItemChange.get() != null) {
audioProcessingPipeline.queueEndOfStream();
}
return false;
if (input.isEnded()) {
mixer.removeSource(sourceId);
finishedInputs++;
return;
}
if (pendingInputBuffer.isEndOfStream()) {
audioProcessingPipeline.queueEndOfStream();
receivedEndOfStreamFromInput = true;
clearAndAddToAvailableBuffers(pendingInputBuffers.remove());
return false;
}
ByteBuffer inputData = checkNotNull(pendingInputBuffer.data);
audioProcessingPipeline.queueInput(inputData);
if (inputData.hasRemaining()) {
return false;
}
clearAndAddToAvailableBuffers(pendingInputBuffers.remove());
return true;
}
private ByteBuffer feedOutputFromInput() {
if (silentAudioGenerator.hasRemaining()) {
return silentAudioGenerator.getBuffer();
}
// When output is fed directly from input, the output ByteBuffer is linked to a specific
// DecoderInputBuffer. Therefore it must be consumed by the downstream component before it can
// be used for fresh input.
@Nullable DecoderInputBuffer previousOutputBuffer = currentInputBufferBeingOutput;
if (previousOutputBuffer != null) {
ByteBuffer data = checkStateNotNull(previousOutputBuffer.data);
if (data.hasRemaining()) {
// Currently output data has not been consumed, return it.
return data;
}
clearAndAddToAvailableBuffers(previousOutputBuffer);
currentInputBufferBeingOutput = null;
}
@Nullable DecoderInputBuffer currentInputBuffer = pendingInputBuffers.poll();
if (currentInputBuffer == null) {
return EMPTY_BUFFER;
}
@Nullable ByteBuffer currentInputBufferData = currentInputBuffer.data;
receivedEndOfStreamFromInput = currentInputBuffer.isEndOfStream();
// If there is no input data, make buffer available, ensuring underlying data reference is not
// kept. Data associated with EOS buffer is ignored.
if (currentInputBufferData == null
|| !currentInputBufferData.hasRemaining()
|| receivedEndOfStreamFromInput) {
clearAndAddToAvailableBuffers(currentInputBuffer);
return EMPTY_BUFFER;
}
currentInputBufferBeingOutput = currentInputBuffer;
return currentInputBufferData;
}
private boolean hasDataToOutput() {
if (!processedFirstMediaItemChange) {
return false;
}
if (currentInputBufferBeingOutput != null
&& currentInputBufferBeingOutput.data != null
&& currentInputBufferBeingOutput.data.hasRemaining()) {
return true;
}
if (silentAudioGenerator.hasRemaining()) {
return true;
}
if (!pendingInputBuffers.isEmpty()) {
return true;
}
if (audioProcessingPipeline.isOperational() && !audioProcessingPipeline.isEnded()) {
return true;
}
return false;
}
private void clearAndAddToAvailableBuffers(DecoderInputBuffer inputBuffer) {
inputBuffer.clear();
inputBuffer.timeUs = 0;
availableInputBuffers.add(inputBuffer);
}
/**
* Configures the graph based on the pending {@linkplain #onMediaItemChanged media item change}.
*
* <p>Before configuration, all {@linkplain #hasDataToOutput() pending data} must be consumed
* through {@link #getOutput()}.
*/
private void configureForPendingMediaItemChange() throws UnhandledAudioFormatException {
MediaItemChange pendingChange = checkStateNotNull(pendingMediaItemChange.get());
AudioFormat pendingAudioFormat;
if (pendingChange.format != null) {
pendingAudioFormat = new AudioFormat(pendingChange.format);
} else { // Generating silence
pendingAudioFormat = silentAudioGenerator.audioFormat;
silentAudioGenerator.addSilence(pendingChange.durationUs);
if (pendingChange.isLast) {
queueEndOfStreamAfterSilence = true;
}
}
if (processedFirstMediaItemChange) {
// APP is configured in constructor for first media item.
audioProcessingPipeline =
configureProcessing(
/* editedMediaItem= */ pendingChange.editedMediaItem,
/* trackFormat= */ pendingChange.format,
/* inputAudioFormat= */ pendingAudioFormat,
/* requiredOutputAudioFormat= */ outputAudioFormat);
}
audioProcessingPipeline.flush();
pendingMediaItemChange.set(null);
receivedEndOfStreamFromInput = false;
processedFirstMediaItemChange = true;
}
private static AudioProcessingPipeline configureProcessing(
EditedMediaItem editedMediaItem,
@Nullable Format trackFormat,
AudioFormat inputAudioFormat,
AudioFormat requiredOutputAudioFormat)
throws UnhandledAudioFormatException {
ImmutableList.Builder<AudioProcessor> audioProcessors = new ImmutableList.Builder<>();
if (editedMediaItem.flattenForSlowMotion
&& trackFormat != null
&& trackFormat.metadata != null) {
audioProcessors.add(
new SpeedChangingAudioProcessor(new SegmentSpeedProvider(trackFormat.metadata)));
}
audioProcessors.addAll(editedMediaItem.effects.audioProcessors);
// Ensure the output from APP matches what the encoder is configured to receive.
if (!requiredOutputAudioFormat.equals(AudioFormat.NOT_SET)) {
SonicAudioProcessor sampleRateChanger = new SonicAudioProcessor();
sampleRateChanger.setOutputSampleRateHz(requiredOutputAudioFormat.sampleRate);
audioProcessors.add(sampleRateChanger);
// TODO(b/262706549): Handle channel mixing with AudioMixer.
if (requiredOutputAudioFormat.channelCount <= 2) {
// ChannelMixingMatrix.create only has defaults for mono/stereo input/output.
ChannelMixingAudioProcessor channelCountChanger = new ChannelMixingAudioProcessor();
channelCountChanger.putChannelMixingMatrix(
ChannelMixingMatrix.create(
/* inputChannelCount= */ 1, requiredOutputAudioFormat.channelCount));
channelCountChanger.putChannelMixingMatrix(
ChannelMixingMatrix.create(
/* inputChannelCount= */ 2, requiredOutputAudioFormat.channelCount));
audioProcessors.add(channelCountChanger);
}
}
AudioProcessingPipeline audioProcessingPipeline =
new AudioProcessingPipeline(audioProcessors.build());
AudioFormat outputAudioFormat = audioProcessingPipeline.configure(inputAudioFormat);
if (!requiredOutputAudioFormat.equals(AudioFormat.NOT_SET)
&& !outputAudioFormat.equals(requiredOutputAudioFormat)) {
throw new UnhandledAudioFormatException(
"Audio format can not be modified to match existing downstream format", inputAudioFormat);
}
return audioProcessingPipeline;
}
private static final class MediaItemChange {
public final EditedMediaItem editedMediaItem;
public final long durationUs;
@Nullable public final Format format;
public final boolean isLast;
public MediaItemChange(
EditedMediaItem editedMediaItem, long durationUs, @Nullable Format format, boolean isLast) {
this.editedMediaItem = editedMediaItem;
this.durationUs = durationUs;
this.format = format;
this.isLast = isLast;
try {
mixer.queueInput(sourceId, input.getOutput());
} catch (UnhandledAudioFormatException e) {
throw ExportException.createForAudioProcessing(
e, "AudioGraphInput (sourceId=" + sourceId + ") reconfiguration");
}
}
}

View file

@ -0,0 +1,382 @@
/*
* Copyright 2021 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 androidx.media3.transformer;
import static androidx.media3.common.audio.AudioProcessor.EMPTY_BUFFER;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.audio.AudioProcessingPipeline;
import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.audio.AudioProcessor.AudioFormat;
import androidx.media3.common.audio.AudioProcessor.UnhandledAudioFormatException;
import androidx.media3.common.audio.ChannelMixingAudioProcessor;
import androidx.media3.common.audio.ChannelMixingMatrix;
import androidx.media3.common.audio.SonicAudioProcessor;
import androidx.media3.common.audio.SpeedChangingAudioProcessor;
import androidx.media3.common.util.NullableType;
import androidx.media3.decoder.DecoderInputBuffer;
import com.google.common.collect.ImmutableList;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicReference;
/**
* Processes a single stream of raw audio samples.
*
* <p>Handles changes to the {@link Format} and {@link Effects} on {@linkplain #onMediaItemChanged
* item boundaries}.
*/
/* package */ final class AudioGraphInput implements GraphInput {
private static final int MAX_INPUT_BUFFER_COUNT = 10;
private final AudioFormat outputAudioFormat;
// TODO(b/260618558): Move silent audio generation upstream of this component.
private final SilentAudioGenerator silentAudioGenerator;
private final Queue<DecoderInputBuffer> availableInputBuffers;
private final Queue<DecoderInputBuffer> pendingInputBuffers;
private final AtomicReference<@NullableType MediaItemChange> pendingMediaItemChange;
@Nullable private DecoderInputBuffer currentInputBufferBeingOutput;
private AudioProcessingPipeline audioProcessingPipeline;
private boolean processedFirstMediaItemChange;
private boolean receivedEndOfStreamFromInput;
private boolean queueEndOfStreamAfterSilence;
public AudioGraphInput(EditedMediaItem item, Format inputFormat)
throws UnhandledAudioFormatException {
checkArgument(inputFormat.pcmEncoding != Format.NO_VALUE);
availableInputBuffers = new ConcurrentLinkedDeque<>();
ByteBuffer emptyBuffer = ByteBuffer.allocateDirect(0).order(ByteOrder.nativeOrder());
for (int i = 0; i < MAX_INPUT_BUFFER_COUNT; i++) {
DecoderInputBuffer inputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DIRECT);
inputBuffer.data = emptyBuffer;
availableInputBuffers.add(inputBuffer);
}
pendingInputBuffers = new ConcurrentLinkedDeque<>();
pendingMediaItemChange = new AtomicReference<>();
AudioFormat inputAudioFormat = new AudioFormat(inputFormat);
silentAudioGenerator = new SilentAudioGenerator(inputAudioFormat);
audioProcessingPipeline =
configureProcessing(
/* editedMediaItem= */ item,
/* inputFormat= */ inputFormat,
/* inputAudioFormat= */ inputAudioFormat,
/* requiredOutputAudioFormat= */ AudioFormat.NOT_SET);
// APP configuration not active until flush called. getOutputAudioFormat based on active config.
audioProcessingPipeline.flush();
outputAudioFormat = audioProcessingPipeline.getOutputAudioFormat();
}
public AudioFormat getOutputAudioFormat() {
return outputAudioFormat;
}
/**
* Returns a {@link ByteBuffer} of output.
*
* @throws UnhandledAudioFormatException If the configuration of underlying components fails as a
* result of upstream changes.
*/
public ByteBuffer getOutput() throws UnhandledAudioFormatException {
ByteBuffer outputBuffer = getOutputInternal();
if (outputBuffer.hasRemaining()) {
return outputBuffer;
}
if (!hasDataToOutput() && pendingMediaItemChange.get() != null) {
configureForPendingMediaItemChange();
}
return EMPTY_BUFFER;
}
@Override
public void onMediaItemChanged(
EditedMediaItem editedMediaItem,
long durationUs,
@Nullable Format trackFormat,
boolean isLast) {
if (trackFormat == null) {
checkState(
durationUs != C.TIME_UNSET,
"Could not generate silent audio because duration is unknown.");
} else {
checkState(MimeTypes.isAudio(trackFormat.sampleMimeType));
checkState(trackFormat.pcmEncoding != Format.NO_VALUE);
}
pendingMediaItemChange.set(
new MediaItemChange(editedMediaItem, durationUs, trackFormat, isLast));
}
@Override
@Nullable
public DecoderInputBuffer getInputBuffer() {
if (silentAudioGenerator.hasRemaining() || pendingMediaItemChange.get() != null) {
return null;
}
return availableInputBuffers.peek();
}
@Override
public boolean queueInputBuffer() {
checkState(pendingMediaItemChange.get() == null);
DecoderInputBuffer inputBuffer = availableInputBuffers.remove();
pendingInputBuffers.add(inputBuffer);
return true;
}
public void release() {
audioProcessingPipeline.reset();
}
/** Returns whether the input has ended and all queued data has been output. */
public boolean isEnded() {
if (hasDataToOutput()) {
return false;
}
if (pendingMediaItemChange.get() != null) {
return false;
}
return receivedEndOfStreamFromInput || queueEndOfStreamAfterSilence;
}
private ByteBuffer getOutputInternal() {
if (!processedFirstMediaItemChange) {
return EMPTY_BUFFER;
}
if (!audioProcessingPipeline.isOperational()) {
return feedOutputFromInput();
}
// Ensure APP progresses as much as possible.
while (feedProcessingPipelineFromInput()) {}
return audioProcessingPipeline.getOutput();
}
private boolean feedProcessingPipelineFromInput() {
if (silentAudioGenerator.hasRemaining()) {
ByteBuffer inputData = silentAudioGenerator.getBuffer();
audioProcessingPipeline.queueInput(inputData);
if (inputData.hasRemaining()) {
return false;
}
if (!silentAudioGenerator.hasRemaining()) {
audioProcessingPipeline.queueEndOfStream();
return false;
}
return true;
}
@Nullable DecoderInputBuffer pendingInputBuffer = pendingInputBuffers.peek();
if (pendingInputBuffer == null) {
if (pendingMediaItemChange.get() != null) {
audioProcessingPipeline.queueEndOfStream();
}
return false;
}
if (pendingInputBuffer.isEndOfStream()) {
audioProcessingPipeline.queueEndOfStream();
receivedEndOfStreamFromInput = true;
clearAndAddToAvailableBuffers(pendingInputBuffers.remove());
return false;
}
ByteBuffer inputData = checkNotNull(pendingInputBuffer.data);
audioProcessingPipeline.queueInput(inputData);
if (inputData.hasRemaining()) {
return false;
}
clearAndAddToAvailableBuffers(pendingInputBuffers.remove());
return true;
}
private ByteBuffer feedOutputFromInput() {
if (silentAudioGenerator.hasRemaining()) {
return silentAudioGenerator.getBuffer();
}
// When output is fed directly from input, the output ByteBuffer is linked to a specific
// DecoderInputBuffer. Therefore it must be consumed by the downstream component before it can
// be used for fresh input.
@Nullable DecoderInputBuffer previousOutputBuffer = currentInputBufferBeingOutput;
if (previousOutputBuffer != null) {
ByteBuffer data = checkStateNotNull(previousOutputBuffer.data);
if (data.hasRemaining()) {
// Currently output data has not been consumed, return it.
return data;
}
clearAndAddToAvailableBuffers(previousOutputBuffer);
currentInputBufferBeingOutput = null;
}
@Nullable DecoderInputBuffer currentInputBuffer = pendingInputBuffers.poll();
if (currentInputBuffer == null) {
return EMPTY_BUFFER;
}
@Nullable ByteBuffer currentInputBufferData = currentInputBuffer.data;
receivedEndOfStreamFromInput = currentInputBuffer.isEndOfStream();
// If there is no input data, make buffer available, ensuring underlying data reference is not
// kept. Data associated with EOS buffer is ignored.
if (currentInputBufferData == null
|| !currentInputBufferData.hasRemaining()
|| receivedEndOfStreamFromInput) {
clearAndAddToAvailableBuffers(currentInputBuffer);
return EMPTY_BUFFER;
}
currentInputBufferBeingOutput = currentInputBuffer;
return currentInputBufferData;
}
private boolean hasDataToOutput() {
if (!processedFirstMediaItemChange) {
return false;
}
if (currentInputBufferBeingOutput != null
&& currentInputBufferBeingOutput.data != null
&& currentInputBufferBeingOutput.data.hasRemaining()) {
return true;
}
if (silentAudioGenerator.hasRemaining()) {
return true;
}
if (!pendingInputBuffers.isEmpty()) {
return true;
}
if (audioProcessingPipeline.isOperational() && !audioProcessingPipeline.isEnded()) {
return true;
}
return false;
}
private void clearAndAddToAvailableBuffers(DecoderInputBuffer inputBuffer) {
inputBuffer.clear();
inputBuffer.timeUs = 0;
availableInputBuffers.add(inputBuffer);
}
/**
* Configures the graph based on the pending {@linkplain #onMediaItemChanged media item change}.
*
* <p>Before configuration, all {@linkplain #hasDataToOutput() pending data} must be consumed
* through {@link #getOutput()}.
*/
private void configureForPendingMediaItemChange() throws UnhandledAudioFormatException {
MediaItemChange pendingChange = checkStateNotNull(pendingMediaItemChange.get());
AudioFormat pendingAudioFormat;
if (pendingChange.format != null) {
pendingAudioFormat = new AudioFormat(pendingChange.format);
} else { // Generating silence
pendingAudioFormat = silentAudioGenerator.audioFormat;
silentAudioGenerator.addSilence(pendingChange.durationUs);
if (pendingChange.isLast) {
queueEndOfStreamAfterSilence = true;
}
}
if (processedFirstMediaItemChange) {
// APP is configured in constructor for first media item.
audioProcessingPipeline =
configureProcessing(
/* editedMediaItem= */ pendingChange.editedMediaItem,
/* inputFormat= */ pendingChange.format,
/* inputAudioFormat= */ pendingAudioFormat,
/* requiredOutputAudioFormat= */ outputAudioFormat);
}
audioProcessingPipeline.flush();
pendingMediaItemChange.set(null);
receivedEndOfStreamFromInput = false;
processedFirstMediaItemChange = true;
}
private static AudioProcessingPipeline configureProcessing(
EditedMediaItem editedMediaItem,
@Nullable Format inputFormat,
AudioFormat inputAudioFormat,
AudioFormat requiredOutputAudioFormat)
throws UnhandledAudioFormatException {
ImmutableList.Builder<AudioProcessor> audioProcessors = new ImmutableList.Builder<>();
if (editedMediaItem.flattenForSlowMotion
&& inputFormat != null
&& inputFormat.metadata != null) {
audioProcessors.add(
new SpeedChangingAudioProcessor(new SegmentSpeedProvider(inputFormat.metadata)));
}
audioProcessors.addAll(editedMediaItem.effects.audioProcessors);
// Ensure the output from APP matches what the encoder is configured to receive.
if (!requiredOutputAudioFormat.equals(AudioFormat.NOT_SET)) {
SonicAudioProcessor sampleRateChanger = new SonicAudioProcessor();
sampleRateChanger.setOutputSampleRateHz(requiredOutputAudioFormat.sampleRate);
audioProcessors.add(sampleRateChanger);
// TODO(b/262706549): Handle channel mixing with AudioMixer.
if (requiredOutputAudioFormat.channelCount <= 2) {
// ChannelMixingMatrix.create only has defaults for mono/stereo input/output.
ChannelMixingAudioProcessor channelCountChanger = new ChannelMixingAudioProcessor();
channelCountChanger.putChannelMixingMatrix(
ChannelMixingMatrix.create(
/* inputChannelCount= */ 1, requiredOutputAudioFormat.channelCount));
channelCountChanger.putChannelMixingMatrix(
ChannelMixingMatrix.create(
/* inputChannelCount= */ 2, requiredOutputAudioFormat.channelCount));
audioProcessors.add(channelCountChanger);
}
}
AudioProcessingPipeline audioProcessingPipeline =
new AudioProcessingPipeline(audioProcessors.build());
AudioFormat outputAudioFormat = audioProcessingPipeline.configure(inputAudioFormat);
if (!requiredOutputAudioFormat.equals(AudioFormat.NOT_SET)
&& !outputAudioFormat.equals(requiredOutputAudioFormat)) {
throw new UnhandledAudioFormatException(
"Audio can not be modified to match downstream format", inputAudioFormat);
}
return audioProcessingPipeline;
}
private static final class MediaItemChange {
public final EditedMediaItem editedMediaItem;
public final long durationUs;
@Nullable public final Format format;
public final boolean isLast;
public MediaItemChange(
EditedMediaItem editedMediaItem, long durationUs, @Nullable Format format, boolean isLast) {
this.editedMediaItem = editedMediaItem;
this.durationUs = durationUs;
this.format = format;
this.isLast = isLast;
}
}
}

View file

@ -15,6 +15,7 @@
*/
package androidx.media3.transformer;
import androidx.media3.common.C;
import androidx.media3.common.audio.AudioProcessor.AudioFormat;
import androidx.media3.common.audio.AudioProcessor.UnhandledAudioFormatException;
import androidx.media3.common.util.UnstableApi;
@ -54,7 +55,7 @@ import java.nio.ByteBuffer;
public interface AudioMixer {
/** Creates an unconfigured instance. */
public static AudioMixer create() {
return new AudioMixerImpl();
return new AudioMixerImpl(/* outputSilenceWithNoSources= */ true);
}
/**
@ -67,7 +68,7 @@ public interface AudioMixer {
* queued before {@link #getOutput()} is called.
*
* @param outputAudioFormat The audio format of buffers returned from {@link #getOutput()}.
* @param bufferSizeMs The mixing buffer size in milliseconds.
* @param bufferSizeMs The optional mixing buffer size in milliseconds, or {@link C#LENGTH_UNSET}.
* @param startTimeUs The start time of the mixer output in microseconds.
* @throws UnhandledAudioFormatException If the output audio format is not supported.
*/

View file

@ -15,9 +15,11 @@
*/
package androidx.media3.transformer;
import static androidx.media3.common.audio.AudioProcessor.EMPTY_BUFFER;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static java.lang.Math.max;
import static java.lang.Math.min;
import android.util.SparseArray;
@ -33,8 +35,8 @@ import java.nio.ByteOrder;
/** An {@link AudioMixer} that incrementally mixes source audio into a fixed size mixing buffer. */
/* package */ final class AudioMixerImpl implements AudioMixer {
private static final ByteBuffer EMPTY_BUFFER =
ByteBuffer.allocateDirect(0).order(ByteOrder.nativeOrder());
// TODO(b/290002438, b/276734854): Improve buffer management & determine best default size.
private static final int DEFAULT_BUFFER_SIZE_MS = 500;
private final SparseArray<SourceInfo> sources;
private int nextSourceId;
@ -52,7 +54,19 @@ import java.nio.ByteOrder;
/** Position (in frames) of the mixer end point, relative to the mixer start. */
private long endPosition;
public AudioMixerImpl() {
/**
* Largest position (in frames) of {@link #removeSource(int) removed} sources, relative to the
* mixer start.
*/
private long maxPositionOfRemovedSources;
/**
* Creates an instance.
*
* @param outputSilenceWithNoSources Whether {@link #getOutput()} should output buffers of silence
* when there are no {@link #addSource sources}.
*/
public AudioMixerImpl(boolean outputSilenceWithNoSources) {
sources = new SparseArray<>();
outputAudioFormat = AudioFormat.NOT_SET;
bufferSizeFrames = C.LENGTH_UNSET;
@ -60,6 +74,13 @@ import java.nio.ByteOrder;
mixerStartTimeUs = C.TIME_UNSET;
inputLimit = C.LENGTH_UNSET;
endPosition = Long.MAX_VALUE;
if (outputSilenceWithNoSources) {
maxPositionOfRemovedSources = Long.MAX_VALUE;
}
}
public AudioFormat getOutputAudioFormat() {
return outputAudioFormat;
}
@Override
@ -68,6 +89,11 @@ import java.nio.ByteOrder;
checkState(
this.outputAudioFormat.equals(AudioFormat.NOT_SET), "Audio mixer already configured.");
if (bufferSizeMs == C.LENGTH_UNSET) {
bufferSizeMs = DEFAULT_BUFFER_SIZE_MS;
}
checkArgument(bufferSizeMs > 0);
if (!AudioMixingUtil.canMix(outputAudioFormat)) {
throw new UnhandledAudioFormatException(
"Can not mix to this AudioFormat.", outputAudioFormat);
@ -75,7 +101,6 @@ import java.nio.ByteOrder;
this.outputAudioFormat = outputAudioFormat;
bufferSizeFrames = bufferSizeMs * outputAudioFormat.sampleRate / 1000;
mixerStartTimeUs = startTimeUs;
mixingBuffers =
new MixingBuffer[] {allocateMixingBuffer(0), allocateMixingBuffer(bufferSizeFrames)};
updateInputFrameLimit();
@ -106,7 +131,8 @@ import java.nio.ByteOrder;
throws UnhandledAudioFormatException {
checkStateIsConfigured();
if (!supportsSourceAudioFormat(sourceFormat)) {
throw new UnhandledAudioFormatException(sourceFormat);
throw new UnhandledAudioFormatException(
"Can not add source. MixerFormat=" + outputAudioFormat, sourceFormat);
}
long startFrameOffset =
@ -125,6 +151,11 @@ import java.nio.ByteOrder;
return sourceId;
}
public boolean hasSource(int sourceId) {
checkStateIsConfigured();
return sources.get(sourceId) != null;
}
@Override
public void setSourceVolume(int sourceId, float volume) {
checkStateIsConfigured();
@ -137,12 +168,17 @@ import java.nio.ByteOrder;
@Override
public void removeSource(int sourceId) {
checkStateIsConfigured();
maxPositionOfRemovedSources =
max(maxPositionOfRemovedSources, getSourceById(sourceId).position);
sources.delete(sourceId);
}
@Override
public void queueInput(int sourceId, ByteBuffer sourceBuffer) {
checkStateIsConfigured();
if (!sourceBuffer.hasRemaining()) {
return;
}
SourceInfo source = getSourceById(sourceId);
if (source.position >= inputLimit) {
@ -188,8 +224,12 @@ import java.nio.ByteOrder;
@Override
public ByteBuffer getOutput() {
checkStateIsConfigured();
if (isEnded()) {
return EMPTY_BUFFER;
}
long minSourcePosition = sources.size() == 0 ? maxPositionOfRemovedSources : endPosition;
long minSourcePosition = endPosition;
for (int i = 0; i < sources.size(); i++) {
minSourcePosition = min(minSourcePosition, sources.valueAt(i).position);
}
@ -221,7 +261,8 @@ import java.nio.ByteOrder;
@Override
public boolean isEnded() {
checkStateIsConfigured();
return outputPosition >= endPosition;
return outputPosition >= endPosition
|| (outputPosition >= maxPositionOfRemovedSources && sources.size() == 0);
}
@Override

View file

@ -16,7 +16,6 @@
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED;
@ -25,7 +24,6 @@ import static java.lang.Math.min;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.Format;
import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.audio.AudioProcessor.AudioFormat;
import androidx.media3.common.util.Util;
import androidx.media3.decoder.DecoderInputBuffer;
@ -43,25 +41,25 @@ import org.checkerframework.dataflow.qual.Pure;
private final DecoderInputBuffer encoderOutputBuffer;
private final AudioGraph audioGraph;
private final AudioGraphInput firstInput;
private final Format firstInputFormat;
private boolean returnedFirstInput;
private long encoderTotalInputBytes;
public AudioSampleExporter(
Format firstAssetLoaderInputFormat,
Format firstExporterInputFormat,
Format firstAssetLoaderTrackFormat,
Format firstInputFormat,
TransformationRequest transformationRequest,
EditedMediaItem firstEditedMediaItem,
Codec.EncoderFactory encoderFactory,
MuxerWrapper muxerWrapper,
FallbackListener fallbackListener)
throws ExportException {
super(firstAssetLoaderInputFormat, muxerWrapper);
checkArgument(firstExporterInputFormat.pcmEncoding != Format.NO_VALUE);
try {
audioGraph = new AudioGraph(firstExporterInputFormat, firstEditedMediaItem);
} catch (AudioProcessor.UnhandledAudioFormatException e) {
throw ExportException.createForAudioProcessing(e, "AudioGraph initialization");
}
super(firstAssetLoaderTrackFormat, muxerWrapper);
audioGraph = new AudioGraph();
this.firstInputFormat = firstInputFormat;
firstInput = audioGraph.registerInput(firstEditedMediaItem, firstInputFormat);
encoderInputAudioFormat = audioGraph.getOutputAudioFormat();
checkState(!encoderInputAudioFormat.equals(AudioFormat.NOT_SET));
@ -70,7 +68,7 @@ import org.checkerframework.dataflow.qual.Pure;
.setSampleMimeType(
transformationRequest.audioMimeType != null
? transformationRequest.audioMimeType
: checkNotNull(firstAssetLoaderInputFormat.sampleMimeType))
: checkNotNull(firstAssetLoaderTrackFormat.sampleMimeType))
.setSampleRate(encoderInputAudioFormat.sampleRate)
.setChannelCount(encoderInputAudioFormat.channelCount)
.setPcmEncoding(encoderInputAudioFormat.encoding)
@ -97,8 +95,14 @@ import org.checkerframework.dataflow.qual.Pure;
}
@Override
public GraphInput getInput() {
return audioGraph;
public AudioGraphInput getInput(EditedMediaItem item, Format format) throws ExportException {
if (!returnedFirstInput) {
// First input initialized in constructor because output AudioFormat is needed.
returnedFirstInput = true;
checkState(format.equals(this.firstInputFormat));
return firstInput;
}
return audioGraph.registerInput(item, format);
}
@Override
@ -110,7 +114,6 @@ import org.checkerframework.dataflow.qual.Pure;
@Override
protected boolean processDataUpToMuxer() throws ExportException {
// Returns same buffer until consumed. getOutput internally progresses underlying input data.
ByteBuffer audioGraphBuffer = audioGraph.getOutput();
if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) {

View file

@ -89,7 +89,7 @@ import java.util.concurrent.atomic.AtomicLong;
}
@Override
public GraphInput getInput() {
public GraphInput getInput(EditedMediaItem item, Format format) {
return this;
}

View file

@ -61,8 +61,13 @@ import java.util.List;
* from the thread used to call the other {@link GraphInput} methods. All subsequent {@link
* GraphInput} method calls must be made from the thread on which {@link
* GraphInput#onMediaItemChanged} is called.
*
* @param editedMediaItem The initial {@link EditedMediaItem} of the input.
* @param format The initial {@link Format} of the input.
* @throws ExportException If an error occurs getting the input.
*/
public abstract GraphInput getInput();
public abstract GraphInput getInput(EditedMediaItem editedMediaItem, Format format)
throws ExportException;
/**
* Processes the input data and returns whether it may be possible to process more data by calling

View file

@ -531,7 +531,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return null;
}
GraphInput sampleExporterInput = sampleExporter.getInput();
GraphInput sampleExporterInput =
sampleExporter.getInput(editedMediaItems.get(0), assetLoaderOutputFormat);
OnMediaItemChangedListener onMediaItemChangedListener =
(editedMediaItem, durationUs, trackFormat, isLast) -> {
onMediaItemChanged(trackType, durationUs, isLast);
@ -569,15 +570,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
checkState(assetLoaderInputTracker.getSampleExporter(trackType) == null);
Format firstAssetLoaderInputFormat =
assetLoaderInputTracker.getAssetLoaderInputFormat(sequenceIndex, trackType);
EditedMediaItem firstEditedMediaItem = editedMediaItems.get(0);
if (MimeTypes.isAudio(assetLoaderOutputFormat.sampleMimeType)) {
assetLoaderInputTracker.registerSampleExporter(
C.TRACK_TYPE_AUDIO,
new AudioSampleExporter(
firstAssetLoaderInputFormat,
/* firstExporterInputFormat= */ assetLoaderOutputFormat,
/* firstInputFormat= */ assetLoaderOutputFormat,
transformationRequest,
firstEditedMediaItem,
editedMediaItems.get(0),
encoderFactory,
muxerWrapper,
fallbackListener));

View file

@ -174,7 +174,7 @@ import org.checkerframework.dataflow.qual.Pure;
}
@Override
public GraphInput getInput() {
public GraphInput getInput(EditedMediaItem item, Format format) {
return singleInputVideoGraph;
}

View file

@ -18,28 +18,47 @@ package androidx.media3.transformer;
import static androidx.media3.test.utils.TestUtil.createByteBuffer;
import static androidx.media3.test.utils.TestUtil.createFloatArray;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import androidx.media3.common.C;
import androidx.media3.common.audio.AudioProcessor.AudioFormat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import java.nio.ByteBuffer;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.ParameterizedRobolectricTestRunner.Parameter;
import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
/** Unit tests for {@link AudioMixerImpl}. */
@RunWith(AndroidJUnit4.class)
@RunWith(ParameterizedRobolectricTestRunner.class)
public final class AudioMixerImplTest {
@Parameters(name = "{0}")
public static ImmutableList<Boolean> parameters() {
return ImmutableList.of(false, true);
}
private static final int SAMPLE_RATE = 1000; // 1 ms = 1 frame.
private static final AudioFormat AUDIO_FORMAT_STEREO_PCM_FLOAT =
new AudioFormat(SAMPLE_RATE, /* channelCount= */ 2, C.ENCODING_PCM_FLOAT);
private static final AudioFormat AUDIO_FORMAT_STEREO_PCM_16BIT =
new AudioFormat(SAMPLE_RATE, /* channelCount= */ 2, C.ENCODING_PCM_16BIT);
private final AudioMixer mixer = new AudioMixerImpl();
@Parameter public boolean outputSilenceWithNoSources;
private AudioMixer mixer;
@Before
public void setup() {
mixer = new AudioMixerImpl(outputSilenceWithNoSources);
}
@Test
public void output_withNoSource_isSilence() throws Exception {
public void output_withNoSource_whenOutputSilenceWithNoSources_isSilence() throws Exception {
assumeTrue(outputSilenceWithNoSources);
mixer.configure(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* bufferSizeMs= */ 3, /* startTimeUs= */ 0);
assertThat(createFloatArray(mixer.getOutput())).isEqualTo(new float[6]);
@ -47,6 +66,41 @@ public final class AudioMixerImplTest {
assertThat(createFloatArray(mixer.getOutput())).isEqualTo(new float[6]);
}
@Test
public void output_withOneEndedSource_whenOutputSilenceWithNoSources_isInputThenSilence()
throws Exception {
assumeTrue(outputSilenceWithNoSources);
mixer.configure(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* bufferSizeMs= */ 3, /* startTimeUs= */ 0);
int sourceId = mixer.addSource(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* startTimeUs= */ 0);
mixer.queueInput(sourceId, createByteBuffer(new float[] {0.1f, -0.1f}));
mixer.removeSource(sourceId);
assertThat(createFloatArray(mixer.getOutput()))
.isEqualTo(new float[] {0.1f, -0.1f, 0f, 0f, 0f, 0f});
}
@Test
public void output_withNoSource_whenNotOutputSilenceWithNoSources_isEmpty() throws Exception {
assumeFalse(outputSilenceWithNoSources);
mixer.configure(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* bufferSizeMs= */ 3, /* startTimeUs= */ 0);
assertThat(createFloatArray(mixer.getOutput())).isEqualTo(new float[0]);
}
@Test
public void output_withOneEndedSource_whenNotOutputSilenceWithNoSources_isInput()
throws Exception {
assumeFalse(outputSilenceWithNoSources);
mixer.configure(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* bufferSizeMs= */ 3, /* startTimeUs= */ 0);
int sourceId = mixer.addSource(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* startTimeUs= */ 0);
mixer.queueInput(sourceId, createByteBuffer(new float[] {0.1f, -0.1f}));
mixer.removeSource(sourceId);
assertThat(createFloatArray(mixer.getOutput())).isEqualTo(new float[] {0.1f, -0.1f});
}
@Test
public void output_withOneSource_isInput() throws Exception {
mixer.configure(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* bufferSizeMs= */ 3, /* startTimeUs= */ 0);
@ -219,18 +273,6 @@ public final class AudioMixerImplTest {
.isEqualTo(new float[] {0.125f, 0.25f, 0.125f, 0.25f, 0.125f, 0.25f});
}
@Test
public void output_withOneEndedSource_isInputThenSilence() throws Exception {
mixer.configure(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* bufferSizeMs= */ 3, /* startTimeUs= */ 0);
int sourceId = mixer.addSource(AUDIO_FORMAT_STEREO_PCM_FLOAT, /* startTimeUs= */ 0);
mixer.queueInput(sourceId, createByteBuffer(new float[] {0.1f, -0.1f}));
mixer.removeSource(sourceId);
assertThat(createFloatArray(mixer.getOutput()))
.isEqualTo(new float[] {0.1f, -0.1f, 0f, 0f, 0f, 0f});
}
@Test
public void output_withOneSourceAndEndTime_isInputUntilEndTime() throws Exception {
mixer.configure(

View file

@ -15,16 +15,24 @@
*/
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.transformer.TestUtil.ASSET_URI_PREFIX;
import static androidx.media3.transformer.TestUtil.FILE_AUDIO_ONLY;
import static androidx.media3.transformer.TestUtil.FILE_AUDIO_RAW;
import static androidx.media3.transformer.TestUtil.FILE_AUDIO_RAW_VIDEO;
import static androidx.media3.transformer.TestUtil.FILE_AUDIO_VIDEO;
import static androidx.media3.transformer.TestUtil.FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S;
import static androidx.media3.transformer.TestUtil.FILE_VIDEO_ONLY;
import static androidx.media3.transformer.TestUtil.createEncodersAndDecoders;
import static androidx.media3.transformer.TestUtil.createTransformerBuilder;
import static androidx.media3.transformer.TestUtil.getDumpFileName;
import static androidx.media3.transformer.TestUtil.removeEncodersAndDecoders;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import androidx.media3.common.MediaItem;
import androidx.media3.common.util.Util;
import androidx.media3.test.utils.DumpFileAsserts;
import androidx.media3.transformer.TestUtil.TestMuxerFactory.TestMuxerHolder;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@ -43,19 +51,22 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class CompositionExportTest {
private Context context;
private String outputPath;
private TestMuxerHolder testMuxerHolder;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
context = ApplicationProvider.getApplicationContext();
outputPath = Util.createTempFile(context, "TransformerTest").getPath();
testMuxerHolder = new TestUtil.TestMuxerFactory.TestMuxerHolder();
testMuxerHolder = new TestMuxerHolder();
createEncodersAndDecoders();
}
@After
public void tearDown() throws Exception {
Files.delete(Paths.get(outputPath));
removeEncodersAndDecoders();
}
@Test
@ -150,4 +161,118 @@ public class CompositionExportTest {
assertThat(exportResult.durationMs).isEqualTo(3108);
assertThat(exportResult.fileSizeBytes).isEqualTo(337308);
}
@Test
public void start_loopingRawAudio_producesExpectedResult() throws Exception {
Transformer transformer =
createTransformerBuilder(testMuxerHolder, /* enableFallback= */ false).build();
EditedMediaItemSequence audioSequence =
new EditedMediaItemSequence(
ImmutableList.of(
new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW))
.build()),
/* isLooping= */ true);
EditedMediaItem videoEditedMediaItem =
new EditedMediaItem.Builder(
MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S))
.setRemoveAudio(true)
.build();
EditedMediaItemSequence videoSequence =
new EditedMediaItemSequence(ImmutableList.of(videoEditedMediaItem, videoEditedMediaItem));
Composition composition =
new Composition.Builder(ImmutableList.of(audioSequence, videoSequence))
.setTransmuxVideo(true)
.build();
transformer.start(composition, outputPath);
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
assertThat(exportResult.durationMs).isEqualTo(31_053);
// FILE_AUDIO_RAW duration is 1000ms. Input 32 times to cover the 31_053ms duration.
assertThat(exportResult.processedInputs).hasSize(34);
assertThat(exportResult.channelCount).isEqualTo(1);
assertThat(exportResult.fileSizeBytes).isEqualTo(5292662);
}
@Test
public void start_compositionOfConcurrentAudio_isCorrect() throws Exception {
Transformer transformer =
createTransformerBuilder(testMuxerHolder, /* enableFallback= */ false).build();
EditedMediaItem rawAudioItem =
new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW)).build();
EditedMediaItemSequence firstSequence =
new EditedMediaItemSequence(ImmutableList.of(rawAudioItem));
EditedMediaItemSequence secondSequence =
new EditedMediaItemSequence(ImmutableList.of(rawAudioItem));
transformer.start(
new Composition.Builder(ImmutableList.of(firstSequence, secondSequence)).build(),
outputPath);
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
assertThat(exportResult.processedInputs).hasSize(2);
DumpFileAsserts.assertOutput(
context,
checkNotNull(testMuxerHolder.testMuxer),
getDumpFileName(FILE_AUDIO_RAW + ".concurrent"));
}
@Test
public void start_audioVideoCompositionWithExtraAudio_isCorrect() throws Exception {
Transformer transformer =
createTransformerBuilder(testMuxerHolder, /* enableFallback= */ false).build();
EditedMediaItem audioVideoItem =
new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW_VIDEO))
.build();
EditedMediaItemSequence audioVideoSeq =
new EditedMediaItemSequence(ImmutableList.of(audioVideoItem));
EditedMediaItem audioItem =
new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW_VIDEO))
.setRemoveVideo(true)
.build();
EditedMediaItemSequence audioSeq = new EditedMediaItemSequence(ImmutableList.of(audioItem));
transformer.start(
new Composition.Builder(ImmutableList.of(audioVideoSeq, audioSeq))
.setTransmuxVideo(true)
.build(),
outputPath);
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
assertThat(exportResult.processedInputs).hasSize(2);
assertThat(exportResult.durationMs).isEqualTo(1984);
}
@Test
public void start_audioVideoCompositionWithLoopingAudio_isCorrect() throws Exception {
Transformer transformer =
createTransformerBuilder(testMuxerHolder, /* enableFallback= */ false).build();
EditedMediaItem audioVideoItem =
new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW_VIDEO))
.build();
EditedMediaItemSequence audioVideoSeq =
new EditedMediaItemSequence(
ImmutableList.of(audioVideoItem, audioVideoItem, audioVideoItem));
EditedMediaItem audioItem =
new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW_VIDEO))
.setRemoveVideo(true)
.build();
EditedMediaItemSequence audioSeq =
new EditedMediaItemSequence(ImmutableList.of(audioItem), /* isLooping= */ true);
transformer.start(
new Composition.Builder(ImmutableList.of(audioVideoSeq, audioSeq))
.setTransmuxVideo(true)
.build(),
outputPath);
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
assertThat(exportResult.processedInputs).hasSize(7);
assertThat(exportResult.durationMs).isEqualTo(5984);
}
}