Test output file's metadata using MetadataRetriever

Earlier implementation compared the whole file against a golden
data. The new implementation compares only the metadata being tested.
This will avoid updating the golden data when any unrelated change
(unrelated to scenario being tested) is made.

Added a separate test to compare the whole output file against a golden data.

PiperOrigin-RevId: 604692985
This commit is contained in:
sheenachhabra 2024-02-06 10:33:56 -08:00 committed by Copybara-Service
parent 7ae3d69e00
commit 20053dcdc6
5 changed files with 197 additions and 1139 deletions

View file

@ -1,344 +0,0 @@
seekMap:
isSeekable = true
duration = 1065600
getPosition(0) = [[timeUs=0, position=44]]
getPosition(1) = [[timeUs=0, position=44]]
getPosition(532800) = [[timeUs=0, position=44]]
getPosition(1065600) = [[timeUs=0, position=44]]
numberOfTracks = 2
track 0:
total output bytes = 301392
sample count = 30
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.640034
maxInputSize = 22910
width = 1080
height = 720
frameRate = 31.004547
colorInfo:
colorSpace = 1
colorRange = 2
colorTransfer = 3
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=com.android.version, value=13, mdta: key=com.android.capture.fps, value=60.0, xyz: latitude=40.68, longitude=-74.4999, Mp4Timestamp: creation time=3785416745, modification time=3785416745, timescale=10000]
initializationData:
data = length 23, hash 33E412EE
data = length 9, hash FBAFBC0C
sample 0:
time = 0
flags = 1
data = length 7744, hash DDF91733
sample 1:
time = 33355
flags = 0
data = length 1168, hash 89E48A20
sample 2:
time = 66722
flags = 0
data = length 960, hash D4AD9EF0
sample 3:
time = 100100
flags = 0
data = length 976, hash CD49C23C
sample 4:
time = 133455
flags = 0
data = length 1360, hash 337B78A9
sample 5:
time = 166822
flags = 0
data = length 2288, hash 5D5FD1C8
sample 6:
time = 200200
flags = 0
data = length 3856, hash 3D7DCD46
sample 7:
time = 233555
flags = 0
data = length 4048, hash 47C78814
sample 8:
time = 266922
flags = 0
data = length 6144, hash 8FD9AD7D
sample 9:
time = 300300
flags = 0
data = length 7632, hash 4245F848
sample 10:
time = 333655
flags = 0
data = length 9792, hash B2B9AB4B
sample 11:
time = 367022
flags = 0
data = length 14496, hash E0F2E0BA
sample 12:
time = 400400
flags = 0
data = length 17664, hash 3E3189E
sample 13:
time = 433755
flags = 0
data = length 5712, hash CA808ECF
sample 14:
time = 467122
flags = 0
data = length 9776, hash C875D1AA
sample 15:
time = 500500
flags = 0
data = length 17712, hash 69AE17D4
sample 16:
time = 533855
flags = 0
data = length 11440, hash 7370E78C
sample 17:
time = 567222
flags = 0
data = length 8544, hash 5A581986
sample 18:
time = 600600
flags = 0
data = length 19904, hash 98AB5C44
sample 19:
time = 633955
flags = 0
data = length 14352, hash 74B754E3
sample 20:
time = 667322
flags = 0
data = length 9568, hash 369746A6
sample 21:
time = 700700
flags = 0
data = length 12192, hash E0F8A71A
sample 22:
time = 734055
flags = 0
data = length 22880, hash 75E833BA
sample 23:
time = 767422
flags = 0
data = length 16832, hash E8BFCFE3
sample 24:
time = 800800
flags = 0
data = length 5120, hash E04AEF94
sample 25:
time = 834155
flags = 0
data = length 9888, hash 1166103E
sample 26:
time = 867522
flags = 0
data = length 17024, hash F9A96740
sample 27:
time = 900900
flags = 0
data = length 20864, hash DF9E88B8
sample 28:
time = 934255
flags = 0
data = length 7216, hash BE22BE2F
sample 29:
time = 967622
flags = 536870912
data = length 14240, hash E190BF31
track 1:
total output bytes = 9529
sample count = 45
format 0:
id = 2
sampleMimeType = audio/mp4a-latm
codecs = mp4a.40.2
maxInputSize = 294
channelCount = 1
sampleRate = 44100
language = und
metadata = entries=[mdta: key=com.android.version, value=13, xyz: latitude=40.68, longitude=-74.4999, Mp4Timestamp: creation time=3785416745, modification time=3785416745, timescale=10000]
initializationData:
data = length 2, hash 5F7
sample 0:
time = 0
flags = 1
data = length 23, hash 47DE9131
sample 1:
time = 67208
flags = 1
data = length 6, hash 31EC5206
sample 2:
time = 90437
flags = 1
data = length 148, hash 894A176B
sample 3:
time = 113645
flags = 1
data = length 189, hash CEF235A1
sample 4:
time = 136875
flags = 1
data = length 205, hash BBF5F7B0
sample 5:
time = 160083
flags = 1
data = length 210, hash F278B193
sample 6:
time = 183312
flags = 1
data = length 210, hash 82DA1589
sample 7:
time = 206520
flags = 1
data = length 207, hash 5BE231DF
sample 8:
time = 229750
flags = 1
data = length 225, hash 18819EE1
sample 9:
time = 252958
flags = 1
data = length 215, hash CA7FA67B
sample 10:
time = 276187
flags = 1
data = length 211, hash 581A1C18
sample 11:
time = 299416
flags = 1
data = length 216, hash ADB88187
sample 12:
time = 322625
flags = 1
data = length 229, hash 2E8BA4DC
sample 13:
time = 345854
flags = 1
data = length 232, hash 22F0C510
sample 14:
time = 369062
flags = 1
data = length 235, hash 867AD0DC
sample 15:
time = 392291
flags = 1
data = length 231, hash 84E823A8
sample 16:
time = 415500
flags = 1
data = length 226, hash 1BEF3A95
sample 17:
time = 438729
flags = 1
data = length 216, hash EAA345AE
sample 18:
time = 461958
flags = 1
data = length 229, hash 6957411F
sample 19:
time = 485166
flags = 1
data = length 219, hash 41275022
sample 20:
time = 508395
flags = 1
data = length 241, hash 6495DF96
sample 21:
time = 531604
flags = 1
data = length 228, hash 63D95906
sample 22:
time = 554833
flags = 1
data = length 238, hash 34F676F9
sample 23:
time = 578041
flags = 1
data = length 234, hash E5CBC045
sample 24:
time = 601270
flags = 1
data = length 231, hash 5FC43661
sample 25:
time = 624479
flags = 1
data = length 217, hash 682708ED
sample 26:
time = 647708
flags = 1
data = length 239, hash D43780FC
sample 27:
time = 670937
flags = 1
data = length 243, hash C5E17980
sample 28:
time = 694145
flags = 1
data = length 231, hash AC5837BA
sample 29:
time = 717375
flags = 1
data = length 230, hash 169EE895
sample 30:
time = 740583
flags = 1
data = length 238, hash C48FF3F1
sample 31:
time = 763812
flags = 1
data = length 225, hash 531E4599
sample 32:
time = 787020
flags = 1
data = length 232, hash CB3C6B8D
sample 33:
time = 810250
flags = 1
data = length 243, hash F8C94C7
sample 34:
time = 833458
flags = 1
data = length 232, hash A646A7D0
sample 35:
time = 856687
flags = 1
data = length 237, hash E8B787A5
sample 36:
time = 879916
flags = 1
data = length 228, hash 3FA7A29F
sample 37:
time = 903125
flags = 1
data = length 235, hash B9B33B0A
sample 38:
time = 926354
flags = 1
data = length 264, hash 71A4869E
sample 39:
time = 949562
flags = 1
data = length 257, hash D049B54C
sample 40:
time = 972791
flags = 1
data = length 227, hash 66757231
sample 41:
time = 996000
flags = 1
data = length 227, hash BD374F1B
sample 42:
time = 1019229
flags = 1
data = length 235, hash 999477F6
sample 43:
time = 1042437
flags = 1
data = length 229, hash FFF98DF0
sample 44:
time = 1065666
flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true

View file

@ -1,344 +0,0 @@
seekMap:
isSeekable = true
duration = 1065600
getPosition(0) = [[timeUs=0, position=44]]
getPosition(1) = [[timeUs=0, position=44]]
getPosition(532800) = [[timeUs=0, position=44]]
getPosition(1065600) = [[timeUs=0, position=44]]
numberOfTracks = 2
track 0:
total output bytes = 301392
sample count = 30
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.640034
maxInputSize = 22910
width = 1080
height = 720
frameRate = 31.004547
colorInfo:
colorSpace = 1
colorRange = 2
colorTransfer = 3
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=com.android.version, value=13, mdta: key=StringKey, value=StringValue, mdta: key=FloatKey, value=600.0, xyz: latitude=40.68, longitude=-74.4999, Mp4Timestamp: creation time=3785416745, modification time=3785416745, timescale=10000]
initializationData:
data = length 23, hash 33E412EE
data = length 9, hash FBAFBC0C
sample 0:
time = 0
flags = 1
data = length 7744, hash DDF91733
sample 1:
time = 33355
flags = 0
data = length 1168, hash 89E48A20
sample 2:
time = 66722
flags = 0
data = length 960, hash D4AD9EF0
sample 3:
time = 100100
flags = 0
data = length 976, hash CD49C23C
sample 4:
time = 133455
flags = 0
data = length 1360, hash 337B78A9
sample 5:
time = 166822
flags = 0
data = length 2288, hash 5D5FD1C8
sample 6:
time = 200200
flags = 0
data = length 3856, hash 3D7DCD46
sample 7:
time = 233555
flags = 0
data = length 4048, hash 47C78814
sample 8:
time = 266922
flags = 0
data = length 6144, hash 8FD9AD7D
sample 9:
time = 300300
flags = 0
data = length 7632, hash 4245F848
sample 10:
time = 333655
flags = 0
data = length 9792, hash B2B9AB4B
sample 11:
time = 367022
flags = 0
data = length 14496, hash E0F2E0BA
sample 12:
time = 400400
flags = 0
data = length 17664, hash 3E3189E
sample 13:
time = 433755
flags = 0
data = length 5712, hash CA808ECF
sample 14:
time = 467122
flags = 0
data = length 9776, hash C875D1AA
sample 15:
time = 500500
flags = 0
data = length 17712, hash 69AE17D4
sample 16:
time = 533855
flags = 0
data = length 11440, hash 7370E78C
sample 17:
time = 567222
flags = 0
data = length 8544, hash 5A581986
sample 18:
time = 600600
flags = 0
data = length 19904, hash 98AB5C44
sample 19:
time = 633955
flags = 0
data = length 14352, hash 74B754E3
sample 20:
time = 667322
flags = 0
data = length 9568, hash 369746A6
sample 21:
time = 700700
flags = 0
data = length 12192, hash E0F8A71A
sample 22:
time = 734055
flags = 0
data = length 22880, hash 75E833BA
sample 23:
time = 767422
flags = 0
data = length 16832, hash E8BFCFE3
sample 24:
time = 800800
flags = 0
data = length 5120, hash E04AEF94
sample 25:
time = 834155
flags = 0
data = length 9888, hash 1166103E
sample 26:
time = 867522
flags = 0
data = length 17024, hash F9A96740
sample 27:
time = 900900
flags = 0
data = length 20864, hash DF9E88B8
sample 28:
time = 934255
flags = 0
data = length 7216, hash BE22BE2F
sample 29:
time = 967622
flags = 536870912
data = length 14240, hash E190BF31
track 1:
total output bytes = 9529
sample count = 45
format 0:
id = 2
sampleMimeType = audio/mp4a-latm
codecs = mp4a.40.2
maxInputSize = 294
channelCount = 1
sampleRate = 44100
language = und
metadata = entries=[mdta: key=com.android.version, value=13, mdta: key=StringKey, value=StringValue, mdta: key=FloatKey, value=600.0, xyz: latitude=40.68, longitude=-74.4999, Mp4Timestamp: creation time=3785416745, modification time=3785416745, timescale=10000]
initializationData:
data = length 2, hash 5F7
sample 0:
time = 0
flags = 1
data = length 23, hash 47DE9131
sample 1:
time = 67208
flags = 1
data = length 6, hash 31EC5206
sample 2:
time = 90437
flags = 1
data = length 148, hash 894A176B
sample 3:
time = 113645
flags = 1
data = length 189, hash CEF235A1
sample 4:
time = 136875
flags = 1
data = length 205, hash BBF5F7B0
sample 5:
time = 160083
flags = 1
data = length 210, hash F278B193
sample 6:
time = 183312
flags = 1
data = length 210, hash 82DA1589
sample 7:
time = 206520
flags = 1
data = length 207, hash 5BE231DF
sample 8:
time = 229750
flags = 1
data = length 225, hash 18819EE1
sample 9:
time = 252958
flags = 1
data = length 215, hash CA7FA67B
sample 10:
time = 276187
flags = 1
data = length 211, hash 581A1C18
sample 11:
time = 299416
flags = 1
data = length 216, hash ADB88187
sample 12:
time = 322625
flags = 1
data = length 229, hash 2E8BA4DC
sample 13:
time = 345854
flags = 1
data = length 232, hash 22F0C510
sample 14:
time = 369062
flags = 1
data = length 235, hash 867AD0DC
sample 15:
time = 392291
flags = 1
data = length 231, hash 84E823A8
sample 16:
time = 415500
flags = 1
data = length 226, hash 1BEF3A95
sample 17:
time = 438729
flags = 1
data = length 216, hash EAA345AE
sample 18:
time = 461958
flags = 1
data = length 229, hash 6957411F
sample 19:
time = 485166
flags = 1
data = length 219, hash 41275022
sample 20:
time = 508395
flags = 1
data = length 241, hash 6495DF96
sample 21:
time = 531604
flags = 1
data = length 228, hash 63D95906
sample 22:
time = 554833
flags = 1
data = length 238, hash 34F676F9
sample 23:
time = 578041
flags = 1
data = length 234, hash E5CBC045
sample 24:
time = 601270
flags = 1
data = length 231, hash 5FC43661
sample 25:
time = 624479
flags = 1
data = length 217, hash 682708ED
sample 26:
time = 647708
flags = 1
data = length 239, hash D43780FC
sample 27:
time = 670937
flags = 1
data = length 243, hash C5E17980
sample 28:
time = 694145
flags = 1
data = length 231, hash AC5837BA
sample 29:
time = 717375
flags = 1
data = length 230, hash 169EE895
sample 30:
time = 740583
flags = 1
data = length 238, hash C48FF3F1
sample 31:
time = 763812
flags = 1
data = length 225, hash 531E4599
sample 32:
time = 787020
flags = 1
data = length 232, hash CB3C6B8D
sample 33:
time = 810250
flags = 1
data = length 243, hash F8C94C7
sample 34:
time = 833458
flags = 1
data = length 232, hash A646A7D0
sample 35:
time = 856687
flags = 1
data = length 237, hash E8B787A5
sample 36:
time = 879916
flags = 1
data = length 228, hash 3FA7A29F
sample 37:
time = 903125
flags = 1
data = length 235, hash B9B33B0A
sample 38:
time = 926354
flags = 1
data = length 264, hash 71A4869E
sample 39:
time = 949562
flags = 1
data = length 257, hash D049B54C
sample 40:
time = 972791
flags = 1
data = length 227, hash 66757231
sample 41:
time = 996000
flags = 1
data = length 227, hash BD374F1B
sample 42:
time = 1019229
flags = 1
data = length 235, hash 999477F6
sample 43:
time = 1042437
flags = 1
data = length 229, hash FFF98DF0
sample 44:
time = 1065666
flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true

View file

@ -1,344 +0,0 @@
seekMap:
isSeekable = true
duration = 1065600
getPosition(0) = [[timeUs=0, position=44]]
getPosition(1) = [[timeUs=0, position=44]]
getPosition(532800) = [[timeUs=0, position=44]]
getPosition(1065600) = [[timeUs=0, position=44]]
numberOfTracks = 2
track 0:
total output bytes = 301392
sample count = 30
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.640034
maxInputSize = 22910
width = 1080
height = 720
frameRate = 31.004547
colorInfo:
colorSpace = 1
colorRange = 2
colorTransfer = 3
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[mdta: key=com.android.version, value=13, xyz: latitude=45.0, longitude=-90.0, Mp4Timestamp: creation time=3785416745, modification time=3785416745, timescale=10000]
initializationData:
data = length 23, hash 33E412EE
data = length 9, hash FBAFBC0C
sample 0:
time = 0
flags = 1
data = length 7744, hash DDF91733
sample 1:
time = 33355
flags = 0
data = length 1168, hash 89E48A20
sample 2:
time = 66722
flags = 0
data = length 960, hash D4AD9EF0
sample 3:
time = 100100
flags = 0
data = length 976, hash CD49C23C
sample 4:
time = 133455
flags = 0
data = length 1360, hash 337B78A9
sample 5:
time = 166822
flags = 0
data = length 2288, hash 5D5FD1C8
sample 6:
time = 200200
flags = 0
data = length 3856, hash 3D7DCD46
sample 7:
time = 233555
flags = 0
data = length 4048, hash 47C78814
sample 8:
time = 266922
flags = 0
data = length 6144, hash 8FD9AD7D
sample 9:
time = 300300
flags = 0
data = length 7632, hash 4245F848
sample 10:
time = 333655
flags = 0
data = length 9792, hash B2B9AB4B
sample 11:
time = 367022
flags = 0
data = length 14496, hash E0F2E0BA
sample 12:
time = 400400
flags = 0
data = length 17664, hash 3E3189E
sample 13:
time = 433755
flags = 0
data = length 5712, hash CA808ECF
sample 14:
time = 467122
flags = 0
data = length 9776, hash C875D1AA
sample 15:
time = 500500
flags = 0
data = length 17712, hash 69AE17D4
sample 16:
time = 533855
flags = 0
data = length 11440, hash 7370E78C
sample 17:
time = 567222
flags = 0
data = length 8544, hash 5A581986
sample 18:
time = 600600
flags = 0
data = length 19904, hash 98AB5C44
sample 19:
time = 633955
flags = 0
data = length 14352, hash 74B754E3
sample 20:
time = 667322
flags = 0
data = length 9568, hash 369746A6
sample 21:
time = 700700
flags = 0
data = length 12192, hash E0F8A71A
sample 22:
time = 734055
flags = 0
data = length 22880, hash 75E833BA
sample 23:
time = 767422
flags = 0
data = length 16832, hash E8BFCFE3
sample 24:
time = 800800
flags = 0
data = length 5120, hash E04AEF94
sample 25:
time = 834155
flags = 0
data = length 9888, hash 1166103E
sample 26:
time = 867522
flags = 0
data = length 17024, hash F9A96740
sample 27:
time = 900900
flags = 0
data = length 20864, hash DF9E88B8
sample 28:
time = 934255
flags = 0
data = length 7216, hash BE22BE2F
sample 29:
time = 967622
flags = 536870912
data = length 14240, hash E190BF31
track 1:
total output bytes = 9529
sample count = 45
format 0:
id = 2
sampleMimeType = audio/mp4a-latm
codecs = mp4a.40.2
maxInputSize = 294
channelCount = 1
sampleRate = 44100
language = und
metadata = entries=[mdta: key=com.android.version, value=13, xyz: latitude=45.0, longitude=-90.0, Mp4Timestamp: creation time=3785416745, modification time=3785416745, timescale=10000]
initializationData:
data = length 2, hash 5F7
sample 0:
time = 0
flags = 1
data = length 23, hash 47DE9131
sample 1:
time = 67208
flags = 1
data = length 6, hash 31EC5206
sample 2:
time = 90437
flags = 1
data = length 148, hash 894A176B
sample 3:
time = 113645
flags = 1
data = length 189, hash CEF235A1
sample 4:
time = 136875
flags = 1
data = length 205, hash BBF5F7B0
sample 5:
time = 160083
flags = 1
data = length 210, hash F278B193
sample 6:
time = 183312
flags = 1
data = length 210, hash 82DA1589
sample 7:
time = 206520
flags = 1
data = length 207, hash 5BE231DF
sample 8:
time = 229750
flags = 1
data = length 225, hash 18819EE1
sample 9:
time = 252958
flags = 1
data = length 215, hash CA7FA67B
sample 10:
time = 276187
flags = 1
data = length 211, hash 581A1C18
sample 11:
time = 299416
flags = 1
data = length 216, hash ADB88187
sample 12:
time = 322625
flags = 1
data = length 229, hash 2E8BA4DC
sample 13:
time = 345854
flags = 1
data = length 232, hash 22F0C510
sample 14:
time = 369062
flags = 1
data = length 235, hash 867AD0DC
sample 15:
time = 392291
flags = 1
data = length 231, hash 84E823A8
sample 16:
time = 415500
flags = 1
data = length 226, hash 1BEF3A95
sample 17:
time = 438729
flags = 1
data = length 216, hash EAA345AE
sample 18:
time = 461958
flags = 1
data = length 229, hash 6957411F
sample 19:
time = 485166
flags = 1
data = length 219, hash 41275022
sample 20:
time = 508395
flags = 1
data = length 241, hash 6495DF96
sample 21:
time = 531604
flags = 1
data = length 228, hash 63D95906
sample 22:
time = 554833
flags = 1
data = length 238, hash 34F676F9
sample 23:
time = 578041
flags = 1
data = length 234, hash E5CBC045
sample 24:
time = 601270
flags = 1
data = length 231, hash 5FC43661
sample 25:
time = 624479
flags = 1
data = length 217, hash 682708ED
sample 26:
time = 647708
flags = 1
data = length 239, hash D43780FC
sample 27:
time = 670937
flags = 1
data = length 243, hash C5E17980
sample 28:
time = 694145
flags = 1
data = length 231, hash AC5837BA
sample 29:
time = 717375
flags = 1
data = length 230, hash 169EE895
sample 30:
time = 740583
flags = 1
data = length 238, hash C48FF3F1
sample 31:
time = 763812
flags = 1
data = length 225, hash 531E4599
sample 32:
time = 787020
flags = 1
data = length 232, hash CB3C6B8D
sample 33:
time = 810250
flags = 1
data = length 243, hash F8C94C7
sample 34:
time = 833458
flags = 1
data = length 232, hash A646A7D0
sample 35:
time = 856687
flags = 1
data = length 237, hash E8B787A5
sample 36:
time = 879916
flags = 1
data = length 228, hash 3FA7A29F
sample 37:
time = 903125
flags = 1
data = length 235, hash B9B33B0A
sample 38:
time = 926354
flags = 1
data = length 264, hash 71A4869E
sample 39:
time = 949562
flags = 1
data = length 257, hash D049B54C
sample 40:
time = 972791
flags = 1
data = length 227, hash 66757231
sample 41:
time = 996000
flags = 1
data = length 227, hash BD374F1B
sample 42:
time = 1019229
flags = 1
data = length 235, hash 999477F6
sample 43:
time = 1042437
flags = 1
data = length 229, hash FFF98DF0
sample 44:
time = 1065666
flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true

View file

@ -15,12 +15,16 @@
*/
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.transformer.TestUtil.FILE_AUDIO_VIDEO;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.container.Mp4TimestampData.TIMESCALE_UNSET;
import static androidx.media3.test.utils.FileUtil.retrieveTrackFormat;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.Format;
import androidx.media3.common.MediaItem;
import androidx.media3.common.Metadata;
import androidx.media3.common.util.Util;
@ -29,11 +33,13 @@ import androidx.media3.container.Mp4LocationData;
import androidx.media3.container.Mp4TimestampData;
import androidx.media3.container.XmpData;
import androidx.media3.extractor.mp4.Mp4Extractor;
import androidx.media3.extractor.text.DefaultSubtitleParserFactory;
import androidx.media3.test.utils.DumpFileAsserts;
import androidx.media3.test.utils.FakeClock;
import androidx.media3.test.utils.FakeExtractorOutput;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.base.Predicate;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -43,7 +49,8 @@ import org.junit.runner.RunWith;
/** End-to-end test for {@link Transformer} with {@link InAppMuxer}. */
@RunWith(AndroidJUnit4.class)
public class TransformerWithInAppMuxerEndToEndTest {
private static final String MP4_FILE = "asset:///media/mp4/sample_no_bframes.mp4";
private static final String MP4_FILE_PATH = "asset:///media/mp4/sample_no_bframes.mp4";
private static final String MP4_FILE_NAME = "mp4/sample_no_bframes.mp4";
@Rule public final TemporaryFolder outputDir = new TemporaryFolder();
private final Context context = ApplicationProvider.getApplicationContext();
@ -55,15 +62,51 @@ public class TransformerWithInAppMuxerEndToEndTest {
}
@Test
public void transmux_withLocationMetadata_outputMatchesExpected() throws Exception {
public void transmux_mp4File_outputMatchesExpected() throws Exception {
Muxer.Factory inAppMuxerFactory =
new InAppMuxer.Factory.Builder()
.setMetadataProvider(
metadataEntries ->
// Add timestamp to make output file deterministic.
metadataEntries.add(
new Mp4TimestampData(
/* creationTimestampSeconds= */ 2_000_000_000L,
/* modificationTimestampSeconds= */ 2_000_000_000L,
TIMESCALE_UNSET)))
.build();
Transformer transformer =
new Transformer.Builder(context)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE_PATH));
transformer.start(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
FakeExtractorOutput fakeExtractorOutput =
androidx.media3.test.utils.TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(new DefaultSubtitleParserFactory()), outputPath);
DumpFileAsserts.assertOutput(
context,
fakeExtractorOutput,
TestUtil.getDumpFileName(
/* originalFileName= */ MP4_FILE_NAME,
/* modifications...= */ "transmuxed_with_inappmuxer"));
}
@Test
public void transmux_withLocationMetadata_writesSameLocationMetadata() throws Exception {
Mp4LocationData expectedLocationData =
new Mp4LocationData(/* latitude= */ 45f, /* longitude= */ -90f);
Muxer.Factory inAppMuxerFactory =
new InAppMuxer.Factory.Builder()
.setMetadataProvider(
metadataEntries -> {
metadataEntries.removeIf(
(Metadata.Entry entry) -> entry instanceof Mp4LocationData);
metadataEntries.add(
new Mp4LocationData(/* latitude= */ 45f, /* longitude= */ -90f));
metadataEntries.add(expectedLocationData);
})
.build();
Transformer transformer =
@ -71,21 +114,15 @@ public class TransformerWithInAppMuxerEndToEndTest {
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE));
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE_PATH));
transformer.start(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
FakeExtractorOutput fakeExtractorOutput =
androidx.media3.test.utils.TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(), checkNotNull(outputPath));
// [xyz: latitude=45.0, longitude=-90.0] in track metadata dump.
DumpFileAsserts.assertOutput(
context,
fakeExtractorOutput,
TestUtil.getDumpFileName(
/* originalFileName= */ FILE_AUDIO_VIDEO,
/* modifications...= */ "with_location_metadata"));
Mp4LocationData actualLocationData =
(Mp4LocationData)
retrieveMetadata(context, outputPath, entry -> entry instanceof Mp4LocationData);
assertThat(actualLocationData).isEqualTo(expectedLocationData);
}
@Test
@ -101,7 +138,7 @@ public class TransformerWithInAppMuxerEndToEndTest {
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE));
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE_PATH));
transformer.start(mediaItem, outputPath);
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
@ -111,18 +148,91 @@ public class TransformerWithInAppMuxerEndToEndTest {
}
@Test
public void transmux_withCaptureFps_outputMatchesExpected() throws Exception {
public void transmux_withCaptureFps_writesSameCaptureFps() throws Exception {
float captureFps = 60.0f;
MdtaMetadataEntry expectedCaptureFps =
new MdtaMetadataEntry(
MdtaMetadataEntry.KEY_ANDROID_CAPTURE_FPS,
/* value= */ Util.toByteArray(captureFps),
/* localeIndicator= */ 0,
MdtaMetadataEntry.TYPE_INDICATOR_FLOAT32);
Muxer.Factory inAppMuxerFactory =
new InAppMuxer.Factory.Builder()
.setMetadataProvider(metadataEntries -> metadataEntries.add(expectedCaptureFps))
.build();
Transformer transformer =
new Transformer.Builder(context)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE_PATH));
transformer.start(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
MdtaMetadataEntry actualCaptureFps =
(MdtaMetadataEntry)
retrieveMetadata(
context,
outputPath,
entry ->
entry instanceof MdtaMetadataEntry
&& ((MdtaMetadataEntry) entry).key.equals(expectedCaptureFps.key));
assertThat(actualCaptureFps).isEqualTo(expectedCaptureFps);
}
@Test
public void transmux_withTimestampData_writesSameTimestampData() throws Exception {
// TODO: b/285281716 - Use different value for modification timestamp.
Mp4TimestampData expectedTimestampData =
new Mp4TimestampData(
/* creationTimestampSeconds= */ 2_000_000_000L,
/* modificationTimestampSeconds= */ 2_000_000_000L,
TIMESCALE_UNSET);
Muxer.Factory inAppMuxerFactory =
new InAppMuxer.Factory.Builder()
.setMetadataProvider(metadataEntries -> metadataEntries.add(expectedTimestampData))
.build();
Transformer transformer =
new Transformer.Builder(context)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE_PATH));
transformer.start(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
Mp4TimestampData actualTimestampData =
(Mp4TimestampData)
retrieveMetadata(context, outputPath, entry -> entry instanceof Mp4TimestampData);
assertThat(actualTimestampData.creationTimestampSeconds)
.isEqualTo(expectedTimestampData.creationTimestampSeconds);
assertThat(actualTimestampData.modificationTimestampSeconds)
.isEqualTo(expectedTimestampData.modificationTimestampSeconds);
}
@Test
public void transmux_withCustomMetadata_writesSameCustomMetadata() throws Exception {
MdtaMetadataEntry expectedStringMetadata =
new MdtaMetadataEntry(
"StringKey",
Util.getUtf8Bytes("StringValue"),
/* localeIndicator= */ 0,
MdtaMetadataEntry.TYPE_INDICATOR_STRING);
MdtaMetadataEntry expectedFloatMetadata =
new MdtaMetadataEntry(
"FloatKey",
/* value= */ Util.toByteArray(600.0f),
/* localeIndicator= */ 0,
MdtaMetadataEntry.TYPE_INDICATOR_FLOAT32);
Muxer.Factory inAppMuxerFactory =
new InAppMuxer.Factory.Builder()
.setMetadataProvider(
metadataEntries -> {
float captureFps = 60.0f;
metadataEntries.add(
new MdtaMetadataEntry(
MdtaMetadataEntry.KEY_ANDROID_CAPTURE_FPS,
/* value= */ Util.toByteArray(captureFps),
/* localeIndicator= */ 0,
MdtaMetadataEntry.TYPE_INDICATOR_FLOAT32));
metadataEntries.add(expectedStringMetadata);
metadataEntries.add(expectedFloatMetadata);
})
.build();
Transformer transformer =
@ -130,98 +240,78 @@ public class TransformerWithInAppMuxerEndToEndTest {
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE));
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE_PATH));
transformer.start(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
FakeExtractorOutput fakeExtractorOutput =
androidx.media3.test.utils.TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(), checkNotNull(outputPath));
// [mdta: key=com.android.capture.fps, value=60.0] in video track metadata dump.
DumpFileAsserts.assertOutput(
context,
fakeExtractorOutput,
TestUtil.getDumpFileName(
/* originalFileName= */ FILE_AUDIO_VIDEO, /* modifications...= */ "with_capture_fps"));
MdtaMetadataEntry actualStringMetadata =
(MdtaMetadataEntry)
retrieveMetadata(
context,
outputPath,
entry ->
entry instanceof MdtaMetadataEntry
&& ((MdtaMetadataEntry) entry).key.equals(expectedStringMetadata.key));
assertThat(actualStringMetadata).isEqualTo(expectedStringMetadata);
MdtaMetadataEntry actualFloatMetadata =
(MdtaMetadataEntry)
retrieveMetadata(
context,
outputPath,
entry ->
entry instanceof MdtaMetadataEntry
&& ((MdtaMetadataEntry) entry).key.equals(expectedFloatMetadata.key));
assertThat(actualFloatMetadata).isEqualTo(expectedFloatMetadata);
}
@Test
public void transmux_withCreationTime_outputMatchesExpected() throws Exception {
Muxer.Factory inAppMuxerFactory =
new InAppMuxer.Factory.Builder()
.setMetadataProvider(
metadataEntries ->
metadataEntries.add(
new Mp4TimestampData(/* creationTimestampSeconds= */ 2_000_000_000L)))
.build();
/**
* Returns specific {@linkplain Metadata.Entry metadata} from the media file.
*
* @param context The application context.
* @param filePath The path of the media file.
* @param predicate The {@link Predicate} to be used to retrieve the {@linkplain Metadata.Entry
* metadata}.
* @return The {@linkplain Metadata.Entry metadata}.
*/
@Nullable
private static Metadata.Entry retrieveMetadata(
Context context, @Nullable String filePath, Predicate<Metadata.Entry> predicate) {
Format videoTrackFormat = retrieveTrackFormat(context, filePath, C.TRACK_TYPE_VIDEO);
@Nullable
Metadata.Entry metadataEntryFromVideoTrack = findMetadataEntry(videoTrackFormat, predicate);
Format audioTrackFormat = retrieveTrackFormat(context, filePath, C.TRACK_TYPE_AUDIO);
@Nullable
Metadata.Entry metadataEntryFromAudioTrack = findMetadataEntry(audioTrackFormat, predicate);
Transformer transformer =
new Transformer.Builder(context)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE));
ensureSameMetadataAcrossTracks(metadataEntryFromVideoTrack, metadataEntryFromAudioTrack);
transformer.start(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
FakeExtractorOutput fakeExtractorOutput =
androidx.media3.test.utils.TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(), checkNotNull(outputPath));
// [Creation time: 2_000_000_000_000] in track metadata dump.
DumpFileAsserts.assertOutput(
context,
fakeExtractorOutput,
TestUtil.getDumpFileName(
/* originalFileName= */ FILE_AUDIO_VIDEO, /* modifications...= */
"with_creation_time"));
return metadataEntryFromVideoTrack != null
? metadataEntryFromVideoTrack
: metadataEntryFromAudioTrack;
}
@Test
public void transmux_withCustomeMetadata_outputMatchesExpected() throws Exception {
Muxer.Factory inAppMuxerFactory =
new InAppMuxer.Factory.Builder()
.setMetadataProvider(
metadataEntries -> {
String stringKey = "StringKey";
String stringValue = "StringValue";
metadataEntries.add(
new MdtaMetadataEntry(
stringKey,
Util.getUtf8Bytes(stringValue),
/* localeIndicator= */ 0,
MdtaMetadataEntry.TYPE_INDICATOR_STRING));
String floatKey = "FloatKey";
float floatValue = 600.0f;
metadataEntries.add(
new MdtaMetadataEntry(
floatKey,
Util.toByteArray(floatValue),
/* localeIndicator= */ 0,
MdtaMetadataEntry.TYPE_INDICATOR_FLOAT32));
})
.build();
Transformer transformer =
new Transformer.Builder(context)
.setClock(new FakeClock(/* isAutoAdvancing= */ true))
.setMuxerFactory(inAppMuxerFactory)
.build();
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_FILE));
private static void ensureSameMetadataAcrossTracks(
@Nullable Metadata.Entry firstTrackMetadata, @Nullable Metadata.Entry secondTrackMetadata) {
// If same metadata is present in both audio and video track, then they must be same.
if (firstTrackMetadata != null && secondTrackMetadata != null) {
checkState(firstTrackMetadata.equals(secondTrackMetadata));
}
}
transformer.start(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
@Nullable
private static Metadata.Entry findMetadataEntry(
Format format, Predicate<Metadata.Entry> predicate) {
if (format.metadata == null) {
return null;
}
FakeExtractorOutput fakeExtractorOutput =
androidx.media3.test.utils.TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(), checkNotNull(outputPath));
// [mdta: key=StringKey, value=StringValue, mdta: key=FloatKey, value=600.0] in track metadata
// dump
DumpFileAsserts.assertOutput(
context,
fakeExtractorOutput,
TestUtil.getDumpFileName(
/* originalFileName= */ FILE_AUDIO_VIDEO, /* modifications...= */
"with_custom_metadata"));
for (int i = 0; i < format.metadata.length(); i++) {
Metadata.Entry metadataEntry = format.metadata.get(i);
if (predicate.apply(metadataEntry)) {
return metadataEntry;
}
}
return null;
}
}