mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Remove getDurationUs from the SampleExtractor interface.
Set the duration on the MediaFormat instead.
This commit is contained in:
parent
f3f9c845cd
commit
489e99158f
@ -40,6 +40,8 @@ public class MediaFormat {
|
||||
public final String mimeType;
|
||||
public final int maxInputSize;
|
||||
|
||||
public final long durationUs;
|
||||
|
||||
public final int width;
|
||||
public final int height;
|
||||
public final float pixelWidthHeightRatio;
|
||||
@ -49,11 +51,11 @@ public class MediaFormat {
|
||||
|
||||
public final int bitrate;
|
||||
|
||||
public final List<byte[]> initializationData;
|
||||
|
||||
private int maxWidth;
|
||||
private int maxHeight;
|
||||
|
||||
public final List<byte[]> initializationData;
|
||||
|
||||
// Lazy-initialized hashcode.
|
||||
private int hashCode;
|
||||
// Possibly-lazy-initialized framework media format.
|
||||
@ -66,25 +68,38 @@ public class MediaFormat {
|
||||
|
||||
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, int width,
|
||||
int height, List<byte[]> initializationData) {
|
||||
return createVideoFormat(mimeType, maxInputSize, width, height, 1, initializationData);
|
||||
return createVideoFormat(
|
||||
mimeType, maxInputSize, C.UNKNOWN_TIME_US, width, height, initializationData);
|
||||
}
|
||||
|
||||
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, int width,
|
||||
int height, float pixelWidthHeightRatio, List<byte[]> initializationData) {
|
||||
return new MediaFormat(mimeType, maxInputSize, width, height, pixelWidthHeightRatio, NO_VALUE,
|
||||
NO_VALUE, NO_VALUE, initializationData);
|
||||
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, long durationUs,
|
||||
int width, int height, List<byte[]> initializationData) {
|
||||
return createVideoFormat(
|
||||
mimeType, maxInputSize, durationUs, width, height, 1, initializationData);
|
||||
}
|
||||
|
||||
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, long durationUs,
|
||||
int width, int height, float pixelWidthHeightRatio, List<byte[]> initializationData) {
|
||||
return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, pixelWidthHeightRatio,
|
||||
NO_VALUE, NO_VALUE, NO_VALUE, initializationData);
|
||||
}
|
||||
|
||||
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, int channelCount,
|
||||
int sampleRate, List<byte[]> initializationData) {
|
||||
return new MediaFormat(mimeType, maxInputSize, NO_VALUE, NO_VALUE, NO_VALUE, channelCount,
|
||||
sampleRate, NO_VALUE, initializationData);
|
||||
return createAudioFormat(
|
||||
mimeType, maxInputSize, C.UNKNOWN_TIME_US, channelCount, sampleRate, initializationData);
|
||||
}
|
||||
|
||||
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, int channelCount,
|
||||
int sampleRate, int bitrate, List<byte[]> initializationData) {
|
||||
return new MediaFormat(mimeType, maxInputSize, NO_VALUE, NO_VALUE, NO_VALUE, channelCount,
|
||||
sampleRate, bitrate, initializationData);
|
||||
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, long durationUs,
|
||||
int channelCount, int sampleRate, List<byte[]> initializationData) {
|
||||
return createAudioFormat(
|
||||
mimeType, maxInputSize, durationUs, channelCount, sampleRate, NO_VALUE, initializationData);
|
||||
}
|
||||
|
||||
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, long durationUs,
|
||||
int channelCount, int sampleRate, int bitrate, List<byte[]> initializationData) {
|
||||
return new MediaFormat(mimeType, maxInputSize, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||
channelCount, sampleRate, bitrate, initializationData);
|
||||
}
|
||||
|
||||
public static MediaFormat createId3Format() {
|
||||
@ -100,8 +115,8 @@ public class MediaFormat {
|
||||
}
|
||||
|
||||
public static MediaFormat createFormatForMimeType(String mimeType) {
|
||||
return new MediaFormat(mimeType, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||
NO_VALUE, null);
|
||||
return new MediaFormat(mimeType, NO_VALUE, C.UNKNOWN_TIME_US, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||
NO_VALUE, NO_VALUE, NO_VALUE, null);
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
@ -123,15 +138,18 @@ public class MediaFormat {
|
||||
initializationData.add(data);
|
||||
buffer.flip();
|
||||
}
|
||||
durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION)
|
||||
? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US;
|
||||
maxWidth = NO_VALUE;
|
||||
maxHeight = NO_VALUE;
|
||||
}
|
||||
|
||||
private MediaFormat(String mimeType, int maxInputSize, int width, int height,
|
||||
private MediaFormat(String mimeType, int maxInputSize, long durationUs, int width, int height,
|
||||
float pixelWidthHeightRatio, int channelCount, int sampleRate, int bitrate,
|
||||
List<byte[]> initializationData) {
|
||||
this.mimeType = mimeType;
|
||||
this.maxInputSize = maxInputSize;
|
||||
this.durationUs = durationUs;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
||||
@ -169,6 +187,7 @@ public class MediaFormat {
|
||||
result = 31 * result + width;
|
||||
result = 31 * result + height;
|
||||
result = 31 * result + Float.floatToRawIntBits(pixelWidthHeightRatio);
|
||||
result = 31 * result + (int) durationUs;
|
||||
result = 31 * result + maxWidth;
|
||||
result = 31 * result + maxHeight;
|
||||
result = 31 * result + channelCount;
|
||||
@ -225,7 +244,7 @@ public class MediaFormat {
|
||||
public String toString() {
|
||||
return "MediaFormat(" + mimeType + ", " + maxInputSize + ", " + width + ", " + height + ", "
|
||||
+ pixelWidthHeightRatio + ", " + channelCount + ", " + sampleRate + ", " + bitrate + ", "
|
||||
+ maxWidth + ", " + maxHeight + ")";
|
||||
+ durationUs + ", " + maxWidth + ", " + maxHeight + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,6 +265,9 @@ public class MediaFormat {
|
||||
for (int i = 0; i < initializationData.size(); i++) {
|
||||
format.setByteBuffer("csd-" + i, ByteBuffer.wrap(initializationData.get(i)));
|
||||
}
|
||||
if (durationUs != C.UNKNOWN_TIME_US) {
|
||||
format.setLong(android.media.MediaFormat.KEY_DURATION, durationUs);
|
||||
}
|
||||
maybeSetMaxDimensionsV16(format);
|
||||
frameworkMediaFormat = format;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.google.android.exoplayer.chunk.parser;
|
||||
|
||||
import com.google.android.exoplayer.C;
|
||||
import com.google.android.exoplayer.MediaFormat;
|
||||
import com.google.android.exoplayer.ParserException;
|
||||
import com.google.android.exoplayer.SampleHolder;
|
||||
@ -79,11 +78,6 @@ public interface Extractor {
|
||||
*/
|
||||
public MediaFormat getFormat();
|
||||
|
||||
/**
|
||||
* Returns the duration of the stream in microseconds, or {@link C#UNKNOWN_TIME_US} if unknown.
|
||||
*/
|
||||
public long getDurationUs();
|
||||
|
||||
/**
|
||||
* Returns the pssh information parsed from the stream.
|
||||
*
|
||||
|
@ -198,11 +198,6 @@ public final class FragmentedMp4Extractor implements Extractor {
|
||||
return track == null ? null : track.mediaFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDurationUs() {
|
||||
return track == null ? C.UNKNOWN_TIME_US : track.durationUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(NonBlockingInputStream inputStream, SampleHolder out)
|
||||
throws ParserException {
|
||||
|
@ -104,7 +104,7 @@ public final class WebmExtractor implements Extractor {
|
||||
private long segmentStartOffsetBytes = UNKNOWN;
|
||||
private long segmentEndOffsetBytes = UNKNOWN;
|
||||
private long timecodeScale = 1000000L;
|
||||
private long durationUs = UNKNOWN;
|
||||
private long durationUs = C.UNKNOWN_TIME_US;
|
||||
private int pixelWidth = UNKNOWN;
|
||||
private int pixelHeight = UNKNOWN;
|
||||
private int channelCount = UNKNOWN;
|
||||
@ -181,11 +181,6 @@ public final class WebmExtractor implements Extractor {
|
||||
return format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDurationUs() {
|
||||
return durationUs == UNKNOWN ? C.UNKNOWN_TIME_US : durationUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<UUID, byte[]> getPsshInfo() {
|
||||
// TODO: Parse pssh data from Webm streams.
|
||||
@ -463,8 +458,8 @@ public final class WebmExtractor implements Extractor {
|
||||
private void buildVideoFormat() throws ParserException {
|
||||
if (pixelWidth != UNKNOWN && pixelHeight != UNKNOWN
|
||||
&& (format == null || format.width != pixelWidth || format.height != pixelHeight)) {
|
||||
format = MediaFormat.createVideoFormat(
|
||||
MimeTypes.VIDEO_VP9, MediaFormat.NO_VALUE, pixelWidth, pixelHeight, null);
|
||||
format = MediaFormat.createVideoFormat(MimeTypes.VIDEO_VP9, MediaFormat.NO_VALUE, durationUs,
|
||||
pixelWidth, pixelHeight, null);
|
||||
readResults |= RESULT_READ_INIT;
|
||||
} else if (format == null) {
|
||||
throw new ParserException("Unable to build format");
|
||||
@ -485,17 +480,15 @@ public final class WebmExtractor implements Extractor {
|
||||
&& (format == null || format.channelCount != channelCount
|
||||
|| format.sampleRate != sampleRate)) {
|
||||
if (CODEC_ID_VORBIS.equals(codecId)) {
|
||||
format = MediaFormat.createAudioFormat(
|
||||
MimeTypes.AUDIO_VORBIS, VORBIS_MAX_INPUT_SIZE,
|
||||
channelCount, sampleRate, parseVorbisCodecPrivate());
|
||||
format = MediaFormat.createAudioFormat(MimeTypes.AUDIO_VORBIS, VORBIS_MAX_INPUT_SIZE,
|
||||
durationUs, channelCount, sampleRate, parseVorbisCodecPrivate());
|
||||
} else if (CODEC_ID_OPUS.equals(codecId)) {
|
||||
ArrayList<byte[]> opusInitializationData = new ArrayList<byte[]>(3);
|
||||
opusInitializationData.add(codecPrivate);
|
||||
opusInitializationData.add(ByteBuffer.allocate(Long.SIZE).putLong(codecDelayNs).array());
|
||||
opusInitializationData.add(ByteBuffer.allocate(Long.SIZE).putLong(seekPreRollNs).array());
|
||||
format = MediaFormat.createAudioFormat(
|
||||
MimeTypes.AUDIO_OPUS, OPUS_MAX_INPUT_SIZE, channelCount, sampleRate,
|
||||
opusInitializationData);
|
||||
format = MediaFormat.createAudioFormat(MimeTypes.AUDIO_OPUS, OPUS_MAX_INPUT_SIZE,
|
||||
durationUs, channelCount, sampleRate, opusInitializationData);
|
||||
}
|
||||
readResults |= RESULT_READ_INIT;
|
||||
} else if (format == null) {
|
||||
@ -512,7 +505,7 @@ public final class WebmExtractor implements Extractor {
|
||||
private void buildCues() throws ParserException {
|
||||
if (segmentStartOffsetBytes == UNKNOWN) {
|
||||
throw new ParserException("Segment start/end offsets unknown");
|
||||
} else if (durationUs == UNKNOWN) {
|
||||
} else if (durationUs == C.UNKNOWN_TIME_US) {
|
||||
throw new ParserException("Duration unknown");
|
||||
} else if (cuesSizeBytes == UNKNOWN) {
|
||||
throw new ParserException("Cues size unknown");
|
||||
|
@ -67,7 +67,7 @@ public final class CommonMp4AtomParsers {
|
||||
|
||||
long mediaTimescale = parseMdhd(mdia.getLeafAtomOfType(Atom.TYPE_mdhd).data);
|
||||
Pair<MediaFormat, TrackEncryptionBox[]> sampleDescriptions =
|
||||
parseStsd(stbl.getLeafAtomOfType(Atom.TYPE_stsd).data);
|
||||
parseStsd(stbl.getLeafAtomOfType(Atom.TYPE_stsd).data, durationUs);
|
||||
return new Track(id, trackType, mediaTimescale, durationUs, sampleDescriptions.first,
|
||||
sampleDescriptions.second);
|
||||
}
|
||||
@ -321,7 +321,8 @@ public final class CommonMp4AtomParsers {
|
||||
return mdhd.readUnsignedInt();
|
||||
}
|
||||
|
||||
private static Pair<MediaFormat, TrackEncryptionBox[]> parseStsd(ParsableByteArray stsd) {
|
||||
private static Pair<MediaFormat, TrackEncryptionBox[]> parseStsd(
|
||||
ParsableByteArray stsd, long durationUs) {
|
||||
stsd.setPosition(Mp4Util.FULL_ATOM_HEADER_SIZE);
|
||||
int numberOfEntries = stsd.readInt();
|
||||
MediaFormat mediaFormat = null;
|
||||
@ -334,19 +335,19 @@ public final class CommonMp4AtomParsers {
|
||||
if (childAtomType == Atom.TYPE_avc1 || childAtomType == Atom.TYPE_avc3
|
||||
|| childAtomType == Atom.TYPE_encv) {
|
||||
Pair<MediaFormat, TrackEncryptionBox> avc =
|
||||
parseAvcFromParent(stsd, childStartPosition, childAtomSize);
|
||||
parseAvcFromParent(stsd, childStartPosition, childAtomSize, durationUs);
|
||||
mediaFormat = avc.first;
|
||||
trackEncryptionBoxes[i] = avc.second;
|
||||
} else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca
|
||||
|| childAtomType == Atom.TYPE_ac_3) {
|
||||
Pair<MediaFormat, TrackEncryptionBox> audioSampleEntry =
|
||||
parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize);
|
||||
Pair<MediaFormat, TrackEncryptionBox> audioSampleEntry = parseAudioSampleEntry(stsd,
|
||||
childAtomType, childStartPosition, childAtomSize, durationUs);
|
||||
mediaFormat = audioSampleEntry.first;
|
||||
trackEncryptionBoxes[i] = audioSampleEntry.second;
|
||||
} else if (childAtomType == Atom.TYPE_TTML) {
|
||||
mediaFormat = MediaFormat.createTtmlFormat();
|
||||
} else if (childAtomType == Atom.TYPE_mp4v) {
|
||||
mediaFormat = parseMp4vFromParent(stsd, childStartPosition, childAtomSize);
|
||||
mediaFormat = parseMp4vFromParent(stsd, childStartPosition, childAtomSize, durationUs);
|
||||
}
|
||||
stsd.setPosition(childStartPosition + childAtomSize);
|
||||
}
|
||||
@ -355,7 +356,7 @@ public final class CommonMp4AtomParsers {
|
||||
|
||||
/** Returns the media format for an avc1 box. */
|
||||
private static Pair<MediaFormat, TrackEncryptionBox> parseAvcFromParent(ParsableByteArray parent,
|
||||
int position, int size) {
|
||||
int position, int size, long durationUs) {
|
||||
parent.setPosition(position + Mp4Util.ATOM_HEADER_SIZE);
|
||||
|
||||
parent.skip(24);
|
||||
@ -388,7 +389,7 @@ public final class CommonMp4AtomParsers {
|
||||
}
|
||||
|
||||
MediaFormat format = MediaFormat.createVideoFormat(MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE,
|
||||
width, height, pixelWidthHeightRatio, initializationData);
|
||||
durationUs, width, height, pixelWidthHeightRatio, initializationData);
|
||||
return Pair.create(format, trackEncryptionBox);
|
||||
}
|
||||
|
||||
@ -468,8 +469,8 @@ public final class CommonMp4AtomParsers {
|
||||
}
|
||||
|
||||
/** Returns the media format for an mp4v box. */
|
||||
private static MediaFormat parseMp4vFromParent(ParsableByteArray parent,
|
||||
int position, int size) {
|
||||
private static MediaFormat parseMp4vFromParent(ParsableByteArray parent, int position, int size,
|
||||
long durationUs) {
|
||||
parent.setPosition(position + Mp4Util.ATOM_HEADER_SIZE);
|
||||
|
||||
parent.skip(24);
|
||||
@ -492,11 +493,11 @@ public final class CommonMp4AtomParsers {
|
||||
}
|
||||
|
||||
return MediaFormat.createVideoFormat(
|
||||
MimeTypes.VIDEO_MP4V, MediaFormat.NO_VALUE, width, height, initializationData);
|
||||
MimeTypes.VIDEO_MP4V, MediaFormat.NO_VALUE, durationUs, width, height, initializationData);
|
||||
}
|
||||
|
||||
private static Pair<MediaFormat, TrackEncryptionBox> parseAudioSampleEntry(
|
||||
ParsableByteArray parent, int atomType, int position, int size) {
|
||||
ParsableByteArray parent, int atomType, int position, int size, long durationUs) {
|
||||
parent.setPosition(position + Mp4Util.ATOM_HEADER_SIZE);
|
||||
parent.skip(16);
|
||||
int channelCount = parent.readUnsignedShort();
|
||||
@ -555,7 +556,7 @@ public final class CommonMp4AtomParsers {
|
||||
}
|
||||
|
||||
MediaFormat format = MediaFormat.createAudioFormat(
|
||||
mimeType, sampleSize, channelCount, sampleRate, bitrate,
|
||||
mimeType, sampleSize, durationUs, channelCount, sampleRate, bitrate,
|
||||
initializationData == null ? null : Collections.singletonList(initializationData));
|
||||
return Pair.create(format, trackEncryptionBox);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package com.google.android.exoplayer.source;
|
||||
|
||||
import com.google.android.exoplayer.C;
|
||||
import com.google.android.exoplayer.MediaFormat;
|
||||
import com.google.android.exoplayer.MediaFormatHolder;
|
||||
import com.google.android.exoplayer.SampleHolder;
|
||||
import com.google.android.exoplayer.SampleSource;
|
||||
@ -67,8 +68,8 @@ public final class DefaultSampleSource implements SampleSource {
|
||||
pendingDiscontinuities = new boolean[trackCount];
|
||||
trackInfos = new TrackInfo[trackCount];
|
||||
for (int track = 0; track < trackCount; track++) {
|
||||
String mimeType = sampleExtractor.getMediaFormat(track).mimeType;
|
||||
trackInfos[track] = new TrackInfo(mimeType, sampleExtractor.getDurationUs(track));
|
||||
MediaFormat mediaFormat = sampleExtractor.getMediaFormat(track);
|
||||
trackInfos[track] = new TrackInfo(mediaFormat.mimeType, mediaFormat.durationUs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.google.android.exoplayer.source;
|
||||
|
||||
import com.google.android.exoplayer.C;
|
||||
import com.google.android.exoplayer.MediaFormat;
|
||||
import com.google.android.exoplayer.SampleHolder;
|
||||
import com.google.android.exoplayer.SampleSource;
|
||||
@ -146,13 +145,6 @@ public final class FrameworkSampleExtractor implements SampleExtractor {
|
||||
return Util.SDK_INT >= 18 ? getPsshInfoV18() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDurationUs(int track) {
|
||||
android.media.MediaFormat format = mediaExtractor.getTrackFormat(track);
|
||||
return format.containsKey(android.media.MediaFormat.KEY_DURATION)
|
||||
? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readSample(int track, SampleHolder sampleHolder) {
|
||||
int sampleTrack = mediaExtractor.getSampleTrackIndex();
|
||||
|
@ -81,9 +81,6 @@ public interface SampleExtractor {
|
||||
/** Returns the DRM initialization data for {@code track}. */
|
||||
Map<UUID, byte[]> getDrmInitData(int track);
|
||||
|
||||
/** Returns the duration of {@code track} in microseconds. */
|
||||
long getDurationUs(int track);
|
||||
|
||||
/**
|
||||
* Reads the next sample in the track at index {@code track} into {@code sampleHolder}, returning
|
||||
* {@link SampleSource#SAMPLE_READ} if it is available.
|
||||
|
@ -42,9 +42,9 @@ public class MediaFormatTest extends TestCase {
|
||||
initData.add(initData2);
|
||||
|
||||
testConversionToFrameworkFormatV16(
|
||||
MediaFormat.createVideoFormat("video/xyz", 102400, 1280, 720, 1.5f, initData));
|
||||
MediaFormat.createVideoFormat("video/xyz", 102400, 1000L, 1280, 720, 1.5f, initData));
|
||||
testConversionToFrameworkFormatV16(
|
||||
MediaFormat.createAudioFormat("audio/xyz", 102400, 5, 44100, initData));
|
||||
MediaFormat.createAudioFormat("audio/xyz", 102400, 1000L, 5, 44100, initData));
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
|
Loading…
x
Reference in New Issue
Block a user