mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Populate MediaFormat.KEY_DURATION
in MediaExtractorCompat
Previously, `getTrackFormat()` in `MediaExtractorCompat` returned a `MediaFormat` without setting `MediaFormat.KEY_DURATION`. With this change: - `MediaFormat.KEY_DURATION` is set based on the track's duration, if available. - If the track duration is unset, the duration from the seek map is used as a fallback. - When neither duration is set, `MediaFormat.KEY_DURATION` remains unset. This ensures that `MediaFormat.KEY_DURATION` is populated when possible, enhancing duration information availability. PiperOrigin-RevId: 691395114
This commit is contained in:
parent
27de9f02e0
commit
df07fa35d8
@ -417,7 +417,15 @@ public final class MediaExtractorCompat {
|
||||
|
||||
/** Returns the track {@link MediaFormat} at the specified {@code trackIndex}. */
|
||||
public MediaFormat getTrackFormat(int trackIndex) {
|
||||
return tracks.get(trackIndex).createDownstreamMediaFormat(formatHolder, noDataBuffer);
|
||||
MediaExtractorTrack track = tracks.get(trackIndex);
|
||||
MediaFormat mediaFormat = track.createDownstreamMediaFormat(formatHolder, noDataBuffer);
|
||||
long trackDurationUs = track.sampleQueue.trackDurationUs;
|
||||
if (trackDurationUs != C.TIME_UNSET) {
|
||||
mediaFormat.setLong(MediaFormat.KEY_DURATION, trackDurationUs);
|
||||
} else if (seekMap != null && seekMap.getDurationUs() != C.TIME_UNSET) {
|
||||
mediaFormat.setLong(MediaFormat.KEY_DURATION, seekMap.getDurationUs());
|
||||
}
|
||||
return mediaFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -865,6 +873,7 @@ public final class MediaExtractorCompat {
|
||||
private final class MediaExtractorSampleQueue extends SampleQueue {
|
||||
|
||||
public final int trackId;
|
||||
public long trackDurationUs;
|
||||
private int mainTrackIndex;
|
||||
private int compatibilityTrackIndex;
|
||||
|
||||
@ -873,6 +882,7 @@ public final class MediaExtractorCompat {
|
||||
// values for DRM-related arguments.
|
||||
super(allocator, /* drmSessionManager= */ null, /* drmEventDispatcher= */ null);
|
||||
this.trackId = trackId;
|
||||
trackDurationUs = C.TIME_UNSET;
|
||||
mainTrackIndex = C.INDEX_UNSET;
|
||||
compatibilityTrackIndex = C.INDEX_UNSET;
|
||||
}
|
||||
@ -887,6 +897,12 @@ public final class MediaExtractorCompat {
|
||||
|
||||
// SampleQueue implementation.
|
||||
|
||||
@Override
|
||||
public void durationUs(long durationUs) {
|
||||
this.trackDurationUs = durationUs;
|
||||
super.durationUs(durationUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Format getAdjustedUpstreamFormat(Format format) {
|
||||
if (getUpstreamFormat() == null) {
|
||||
|
@ -616,6 +616,76 @@ public class MediaExtractorCompatTest {
|
||||
.isEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTrackFormat_withBothTrackAndSeekMapDurationsSet_prioritizesTrackDuration()
|
||||
throws IOException {
|
||||
TrackOutput[] outputs = new TrackOutput[1];
|
||||
fakeExtractor.addReadAction(
|
||||
(input, seekPosition) -> {
|
||||
outputs[0] = extractorOutput.track(/* id= */ 0, C.TRACK_TYPE_VIDEO);
|
||||
extractorOutput.endTracks();
|
||||
extractorOutput.seekMap(
|
||||
new FakeSeekMap(
|
||||
/* durationUs= */ 1_000_000L, (timeUs) -> new SeekPoints(SeekPoint.START)));
|
||||
outputs[0].format(PLACEHOLDER_FORMAT_VIDEO);
|
||||
outputs[0].durationUs(2_000_000L);
|
||||
return Extractor.RESULT_CONTINUE;
|
||||
});
|
||||
mediaExtractorCompat.setDataSource(PLACEHOLDER_URI, /* offset= */ 0);
|
||||
mediaExtractorCompat.selectTrack(/* trackIndex= */ 0);
|
||||
|
||||
MediaFormat mediaFormat = mediaExtractorCompat.getTrackFormat(/* trackIndex= */ 0);
|
||||
|
||||
assertThat(mediaFormat.containsKey(MediaFormat.KEY_DURATION)).isTrue();
|
||||
assertThat(mediaFormat.getLong(MediaFormat.KEY_DURATION)).isEqualTo(2_000_000L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTrackFormat_withOnlySeekMapDurationSet_returnsSeekMapDuration()
|
||||
throws IOException {
|
||||
TrackOutput[] outputs = new TrackOutput[1];
|
||||
fakeExtractor.addReadAction(
|
||||
(input, seekPosition) -> {
|
||||
outputs[0] = extractorOutput.track(/* id= */ 0, C.TRACK_TYPE_VIDEO);
|
||||
extractorOutput.endTracks();
|
||||
extractorOutput.seekMap(
|
||||
new FakeSeekMap(
|
||||
/* durationUs= */ 1_000_000L, (timeUs) -> new SeekPoints(SeekPoint.START)));
|
||||
outputs[0].format(PLACEHOLDER_FORMAT_VIDEO);
|
||||
return Extractor.RESULT_CONTINUE;
|
||||
});
|
||||
mediaExtractorCompat.setDataSource(PLACEHOLDER_URI, /* offset= */ 0);
|
||||
mediaExtractorCompat.selectTrack(/* trackIndex= */ 0);
|
||||
|
||||
MediaFormat mediaFormat = mediaExtractorCompat.getTrackFormat(/* trackIndex= */ 0);
|
||||
|
||||
assertThat(mediaFormat.containsKey(MediaFormat.KEY_DURATION)).isTrue();
|
||||
assertThat(mediaFormat.getLong(MediaFormat.KEY_DURATION)).isEqualTo(1_000_000L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTrackFormat_withNoTrackOrSeekMapDurationSet_returnsNoDuration()
|
||||
throws IOException {
|
||||
TrackOutput[] outputs = new TrackOutput[1];
|
||||
fakeExtractor.addReadAction(
|
||||
(input, seekPosition) -> {
|
||||
outputs[0] = extractorOutput.track(/* id= */ 0, C.TRACK_TYPE_VIDEO);
|
||||
extractorOutput.endTracks();
|
||||
outputs[0].format(
|
||||
new Format.Builder()
|
||||
.setSampleMimeType(MimeTypes.VIDEO_H264)
|
||||
.setCodecs("avc.123")
|
||||
.build());
|
||||
return Extractor.RESULT_CONTINUE;
|
||||
});
|
||||
mediaExtractorCompat.setDataSource(PLACEHOLDER_URI, /* offset= */ 0);
|
||||
mediaExtractorCompat.selectTrack(/* trackIndex= */ 0);
|
||||
|
||||
MediaFormat mediaFormat = mediaExtractorCompat.getTrackFormat(/* trackIndex= */ 0);
|
||||
|
||||
assertThat(mediaFormat.containsKey(MediaFormat.KEY_DURATION)).isFalse();
|
||||
}
|
||||
|
||||
// Internal methods.
|
||||
|
||||
private void assertReadSample(int trackIndex, long timeUs, int size, byte... sampleData) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user