Implement MP3 ConstantBitrateSeeker.getDataEndPosition()

This is needed to correctly handle files with trailing non-MP3 data
(which is indicated by the length in the `Info` frame being shorter than
the overall length of the file).

The test file was generated by appending 150kB of `DEADBEEF` onto the
end of `test-cbr-info-header.mp3`, and the test asserts that the
extracted samples are identical.

Issue: androidx/media#1480

#cherrypick

PiperOrigin-RevId: 658727595
This commit is contained in:
ibaker 2024-08-02 02:49:28 -07:00 committed by Copybara-Service
parent 018d0488e1
commit b09cea9e3a
4 changed files with 21 additions and 1 deletions

View File

@ -35,6 +35,9 @@
* Extractors: * Extractors:
* Allow `Mp4Extractor` and `FragmentedMp4Extractor` to identify H264 * Allow `Mp4Extractor` and `FragmentedMp4Extractor` to identify H264
samples that are not used as reference by subsequent samples. samples that are not used as reference by subsequent samples.
* MP3: Fix `Searched too many bytes` error by correctly ignoring trailing
non-MP3 data based on the length field in an `Info` frame
([#1480](https://github.com/androidx/media/issues/1480)).
* DataSource: * DataSource:
* Update `HttpEngineDataSource` to allow use starting at version S * Update `HttpEngineDataSource` to allow use starting at version S
extension 7 instead of API level 34 extension 7 instead of API level 34

View File

@ -25,6 +25,7 @@ import androidx.media3.extractor.MpegAudioUtil;
/* package */ final class ConstantBitrateSeeker extends ConstantBitrateSeekMap implements Seeker { /* package */ final class ConstantBitrateSeeker extends ConstantBitrateSeekMap implements Seeker {
private final int bitrate; private final int bitrate;
private final long dataEndPosition;
/** /**
* Constructs an instance. * Constructs an instance.
@ -60,6 +61,7 @@ import androidx.media3.extractor.MpegAudioUtil;
boolean allowSeeksIfLengthUnknown) { boolean allowSeeksIfLengthUnknown) {
super(inputLength, firstFramePosition, bitrate, frameSize, allowSeeksIfLengthUnknown); super(inputLength, firstFramePosition, bitrate, frameSize, allowSeeksIfLengthUnknown);
this.bitrate = bitrate; this.bitrate = bitrate;
dataEndPosition = inputLength != C.LENGTH_UNSET ? inputLength : C.INDEX_UNSET;
} }
@Override @Override
@ -69,7 +71,7 @@ import androidx.media3.extractor.MpegAudioUtil;
@Override @Override
public long getDataEndPosition() { public long getDataEndPosition() {
return C.INDEX_UNSET; return dataEndPosition;
} }
@Override @Override

View File

@ -54,6 +54,21 @@ public final class Mp3ExtractorTest {
Mp3Extractor::new, "media/mp3/test-cbr-info-header-pcut-frame.mp3", simulationConfig); Mp3Extractor::new, "media/mp3/test-cbr-info-header-pcut-frame.mp3", simulationConfig);
} }
// https://github.com/androidx/media/issues/1480
@Test
public void mp3SampleWithInfoHeaderAndTrailingGarbage() throws Exception {
// This test file is test-cbr-info-header.mp3 with 150kB of 0xDEADBEEF garbage appended on the
// end. The test asserts that the extracted samples are the same as for
// test-cbr-info-header.mp3.
ExtractorAsserts.assertBehavior(
Mp3Extractor::new,
"media/mp3/test-cbr-info-header-trailing-garbage.mp3",
new AssertionConfig.Builder()
.setDumpFilesPrefix("extractordumps/mp3/test-cbr-info-header.mp3")
.build(),
simulationConfig);
}
@Test @Test
public void mp3SampleWithCbrSeeker() throws Exception { public void mp3SampleWithCbrSeeker() throws Exception {
ExtractorAsserts.assertBehavior( ExtractorAsserts.assertBehavior(