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}. */
|
/** Returns the track {@link MediaFormat} at the specified {@code trackIndex}. */
|
||||||
public MediaFormat getTrackFormat(int 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 {
|
private final class MediaExtractorSampleQueue extends SampleQueue {
|
||||||
|
|
||||||
public final int trackId;
|
public final int trackId;
|
||||||
|
public long trackDurationUs;
|
||||||
private int mainTrackIndex;
|
private int mainTrackIndex;
|
||||||
private int compatibilityTrackIndex;
|
private int compatibilityTrackIndex;
|
||||||
|
|
||||||
@ -873,6 +882,7 @@ public final class MediaExtractorCompat {
|
|||||||
// values for DRM-related arguments.
|
// values for DRM-related arguments.
|
||||||
super(allocator, /* drmSessionManager= */ null, /* drmEventDispatcher= */ null);
|
super(allocator, /* drmSessionManager= */ null, /* drmEventDispatcher= */ null);
|
||||||
this.trackId = trackId;
|
this.trackId = trackId;
|
||||||
|
trackDurationUs = C.TIME_UNSET;
|
||||||
mainTrackIndex = C.INDEX_UNSET;
|
mainTrackIndex = C.INDEX_UNSET;
|
||||||
compatibilityTrackIndex = C.INDEX_UNSET;
|
compatibilityTrackIndex = C.INDEX_UNSET;
|
||||||
}
|
}
|
||||||
@ -887,6 +897,12 @@ public final class MediaExtractorCompat {
|
|||||||
|
|
||||||
// SampleQueue implementation.
|
// SampleQueue implementation.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void durationUs(long durationUs) {
|
||||||
|
this.trackDurationUs = durationUs;
|
||||||
|
super.durationUs(durationUs);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Format getAdjustedUpstreamFormat(Format format) {
|
public Format getAdjustedUpstreamFormat(Format format) {
|
||||||
if (getUpstreamFormat() == null) {
|
if (getUpstreamFormat() == null) {
|
||||||
|
@ -616,6 +616,76 @@ public class MediaExtractorCompatTest {
|
|||||||
.isEqualTo(-1);
|
.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.
|
// Internal methods.
|
||||||
|
|
||||||
private void assertReadSample(int trackIndex, long timeUs, int size, byte... sampleData) {
|
private void assertReadSample(int trackIndex, long timeUs, int size, byte... sampleData) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user