Apply gapless playback metadata for MP3/MP4 playback using MediaCodec.
Issue: #497 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=117219944
This commit is contained in:
parent
ba88091c7b
commit
a1a48abe92
@ -126,6 +126,14 @@ public final class Format {
|
|||||||
* The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable.
|
* The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable.
|
||||||
*/
|
*/
|
||||||
public final int sampleRate;
|
public final int sampleRate;
|
||||||
|
/**
|
||||||
|
* The number of samples to trim from the start of the decoded audio stream.
|
||||||
|
*/
|
||||||
|
public final int encoderDelay;
|
||||||
|
/**
|
||||||
|
* The number of samples to trim from the end of the decoded audio stream.
|
||||||
|
*/
|
||||||
|
public final int encoderPadding;
|
||||||
|
|
||||||
// Text specific.
|
// Text specific.
|
||||||
|
|
||||||
@ -154,8 +162,8 @@ public final class Format {
|
|||||||
String sampleMimeType, int bitrate, int width, int height, float frameRate,
|
String sampleMimeType, int bitrate, int width, int height, float frameRate,
|
||||||
List<byte[]> initializationData) {
|
List<byte[]> initializationData) {
|
||||||
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, width, height,
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, width, height,
|
||||||
frameRate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE,
|
frameRate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null,
|
||||||
initializationData, false);
|
OFFSET_SAMPLE_RELATIVE, initializationData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createVideoSampleFormat(String id, String sampleMimeType, int bitrate,
|
public static Format createVideoSampleFormat(String id, String sampleMimeType, int bitrate,
|
||||||
@ -168,8 +176,8 @@ public final class Format {
|
|||||||
int maxInputSize, int width, int height, float frameRate, List<byte[]> initializationData,
|
int maxInputSize, int width, int height, float frameRate, List<byte[]> initializationData,
|
||||||
int rotationDegrees, float pixelWidthHeightRatio) {
|
int rotationDegrees, float pixelWidthHeightRatio) {
|
||||||
return new Format(id, null, sampleMimeType, bitrate, maxInputSize, width, height, frameRate,
|
return new Format(id, null, sampleMimeType, bitrate, maxInputSize, width, height, frameRate,
|
||||||
rotationDegrees, pixelWidthHeightRatio, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE,
|
rotationDegrees, pixelWidthHeightRatio, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null,
|
||||||
initializationData, false);
|
OFFSET_SAMPLE_RELATIVE, initializationData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio.
|
// Audio.
|
||||||
@ -178,16 +186,23 @@ public final class Format {
|
|||||||
String sampleMimeType, int bitrate, int channelCount, int sampleRate,
|
String sampleMimeType, int bitrate, int channelCount, int sampleRate,
|
||||||
List<byte[]> initializationData, String language) {
|
List<byte[]> initializationData, String language) {
|
||||||
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, channelCount, sampleRate, language, OFFSET_SAMPLE_RELATIVE,
|
NO_VALUE, NO_VALUE, NO_VALUE, channelCount, sampleRate, NO_VALUE, NO_VALUE, language,
|
||||||
initializationData, false);
|
OFFSET_SAMPLE_RELATIVE, initializationData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createAudioSampleFormat(String id, String sampleMimeType, int bitrate,
|
public static Format createAudioSampleFormat(String id, String sampleMimeType, int bitrate,
|
||||||
int maxInputSize, int channelCount, int sampleRate, List<byte[]> initializationData,
|
int maxInputSize, int channelCount, int sampleRate, List<byte[]> initializationData,
|
||||||
String language) {
|
String language) {
|
||||||
|
return createAudioSampleFormat(id, sampleMimeType, bitrate, maxInputSize, channelCount,
|
||||||
|
sampleRate, NO_VALUE, NO_VALUE, initializationData, language);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Format createAudioSampleFormat(String id, String sampleMimeType, int bitrate,
|
||||||
|
int maxInputSize, int channelCount, int sampleRate, int encoderDelay, int encoderPadding,
|
||||||
|
List<byte[]> initializationData, String language) {
|
||||||
return new Format(id, null, sampleMimeType, bitrate, maxInputSize, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new Format(id, null, sampleMimeType, bitrate, maxInputSize, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, channelCount, sampleRate, language, OFFSET_SAMPLE_RELATIVE,
|
NO_VALUE, NO_VALUE, channelCount, sampleRate, encoderDelay, encoderPadding, language,
|
||||||
initializationData, false);
|
OFFSET_SAMPLE_RELATIVE, initializationData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text.
|
// Text.
|
||||||
@ -195,8 +210,8 @@ public final class Format {
|
|||||||
public static Format createTextContainerFormat(String id, String containerMimeType,
|
public static Format createTextContainerFormat(String id, String containerMimeType,
|
||||||
String sampleMimeType, int bitrate, String language) {
|
String sampleMimeType, int bitrate, String language) {
|
||||||
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, language, OFFSET_SAMPLE_RELATIVE, null,
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, language,
|
||||||
false);
|
OFFSET_SAMPLE_RELATIVE, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createTextSampleFormat(String id, String sampleMimeType, int bitrate,
|
public static Format createTextSampleFormat(String id, String sampleMimeType, int bitrate,
|
||||||
@ -207,7 +222,8 @@ public final class Format {
|
|||||||
public static Format createTextSampleFormat(String id, String sampleMimeType, int bitrate,
|
public static Format createTextSampleFormat(String id, String sampleMimeType, int bitrate,
|
||||||
String language, long subsampleOffsetUs) {
|
String language, long subsampleOffsetUs) {
|
||||||
return new Format(id, null, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new Format(id, null, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, language, subsampleOffsetUs, null, false);
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, language,
|
||||||
|
subsampleOffsetUs, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic.
|
// Generic.
|
||||||
@ -215,19 +231,21 @@ public final class Format {
|
|||||||
public static Format createContainerFormat(String id, String containerMimeType,
|
public static Format createContainerFormat(String id, String containerMimeType,
|
||||||
String sampleMimeType, int bitrate) {
|
String sampleMimeType, int bitrate) {
|
||||||
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE, null,
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null,
|
||||||
false);
|
OFFSET_SAMPLE_RELATIVE, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createSampleFormat(String id, String sampleMimeType, int bitrate) {
|
public static Format createSampleFormat(String id, String sampleMimeType, int bitrate) {
|
||||||
return new Format(id, null, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new Format(id, null, sampleMimeType, bitrate, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE, null, false);
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE,
|
||||||
|
null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ Format(String id, String containerMimeType, String sampleMimeType,
|
/* package */ Format(String id, String containerMimeType, String sampleMimeType,
|
||||||
int bitrate, int maxInputSize, int width, int height, float frameRate, int rotationDegrees,
|
int bitrate, int maxInputSize, int width, int height, float frameRate, int rotationDegrees,
|
||||||
float pixelWidthHeightRatio, int channelCount, int sampleRate, String language,
|
float pixelWidthHeightRatio, int channelCount, int sampleRate, int encoderDelay,
|
||||||
long subsampleOffsetUs, List<byte[]> initializationData, boolean requiresSecureDecryption) {
|
int encoderPadding, String language, long subsampleOffsetUs, List<byte[]> initializationData,
|
||||||
|
boolean requiresSecureDecryption) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.containerMimeType = containerMimeType;
|
this.containerMimeType = containerMimeType;
|
||||||
this.sampleMimeType = sampleMimeType;
|
this.sampleMimeType = sampleMimeType;
|
||||||
@ -240,6 +258,8 @@ public final class Format {
|
|||||||
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
||||||
this.channelCount = channelCount;
|
this.channelCount = channelCount;
|
||||||
this.sampleRate = sampleRate;
|
this.sampleRate = sampleRate;
|
||||||
|
this.encoderDelay = encoderDelay;
|
||||||
|
this.encoderPadding = encoderPadding;
|
||||||
this.language = language;
|
this.language = language;
|
||||||
this.subsampleOffsetUs = subsampleOffsetUs;
|
this.subsampleOffsetUs = subsampleOffsetUs;
|
||||||
this.initializationData = initializationData == null ? Collections.<byte[]>emptyList()
|
this.initializationData = initializationData == null ? Collections.<byte[]>emptyList()
|
||||||
@ -250,22 +270,32 @@ public final class Format {
|
|||||||
public Format copyWithMaxInputSize(int maxInputSize) {
|
public Format copyWithMaxInputSize(int maxInputSize) {
|
||||||
return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width,
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width,
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate,
|
||||||
language, subsampleOffsetUs, initializationData, requiresSecureDecryption);
|
encoderDelay, encoderPadding, language, subsampleOffsetUs, initializationData,
|
||||||
|
requiresSecureDecryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
||||||
return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width,
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width,
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate,
|
||||||
language, subsampleOffsetUs, initializationData, requiresSecureDecryption);
|
encoderDelay, encoderPadding, language, subsampleOffsetUs, initializationData,
|
||||||
|
requiresSecureDecryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithContainerInfo(String id, int bitrate, int width, int height,
|
public Format copyWithContainerInfo(String id, int bitrate, int width, int height,
|
||||||
String language) {
|
String language) {
|
||||||
return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width,
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width,
|
||||||
height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate,
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate,
|
||||||
language, subsampleOffsetUs, initializationData, requiresSecureDecryption);
|
encoderDelay, encoderPadding, language, subsampleOffsetUs, initializationData,
|
||||||
|
requiresSecureDecryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
|
||||||
|
return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width,
|
||||||
|
height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate,
|
||||||
|
encoderDelay, encoderPadding, language, subsampleOffsetUs, initializationData,
|
||||||
|
requiresSecureDecryption);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A {@link MediaFormat} representation of this format.
|
* @return A {@link MediaFormat} representation of this format.
|
||||||
*/
|
*/
|
||||||
@ -283,6 +313,8 @@ public final class Format {
|
|||||||
maybeSetIntegerV16(format, "rotation-degrees", rotationDegrees);
|
maybeSetIntegerV16(format, "rotation-degrees", rotationDegrees);
|
||||||
maybeSetIntegerV16(format, MediaFormat.KEY_CHANNEL_COUNT, channelCount);
|
maybeSetIntegerV16(format, MediaFormat.KEY_CHANNEL_COUNT, channelCount);
|
||||||
maybeSetIntegerV16(format, MediaFormat.KEY_SAMPLE_RATE, sampleRate);
|
maybeSetIntegerV16(format, MediaFormat.KEY_SAMPLE_RATE, sampleRate);
|
||||||
|
maybeSetIntegerV16(format, "encoder-delay", encoderDelay);
|
||||||
|
maybeSetIntegerV16(format, "encoder-padding", encoderPadding);
|
||||||
for (int i = 0; i < initializationData.size(); i++) {
|
for (int i = 0; i < initializationData.size(); i++) {
|
||||||
format.setByteBuffer("csd-" + i, ByteBuffer.wrap(initializationData.get(i)));
|
format.setByteBuffer("csd-" + i, ByteBuffer.wrap(initializationData.get(i)));
|
||||||
}
|
}
|
||||||
@ -322,6 +354,8 @@ public final class Format {
|
|||||||
result = 31 * result + height;
|
result = 31 * result + height;
|
||||||
result = 31 * result + channelCount;
|
result = 31 * result + channelCount;
|
||||||
result = 31 * result + sampleRate;
|
result = 31 * result + sampleRate;
|
||||||
|
result = 31 * result + encoderDelay;
|
||||||
|
result = 31 * result + encoderPadding;
|
||||||
result = 31 * result + (language == null ? 0 : language.hashCode());
|
result = 31 * result + (language == null ? 0 : language.hashCode());
|
||||||
hashCode = result;
|
hashCode = result;
|
||||||
}
|
}
|
||||||
@ -343,6 +377,7 @@ public final class Format {
|
|||||||
|| rotationDegrees != other.rotationDegrees
|
|| rotationDegrees != other.rotationDegrees
|
||||||
|| pixelWidthHeightRatio != other.pixelWidthHeightRatio
|
|| pixelWidthHeightRatio != other.pixelWidthHeightRatio
|
||||||
|| channelCount != other.channelCount || sampleRate != other.sampleRate
|
|| channelCount != other.channelCount || sampleRate != other.sampleRate
|
||||||
|
|| encoderDelay != other.encoderDelay || encoderPadding != other.encoderPadding
|
||||||
|| subsampleOffsetUs != other.subsampleOffsetUs
|
|| subsampleOffsetUs != other.subsampleOffsetUs
|
||||||
|| !Util.areEqual(id, other.id) || !Util.areEqual(language, other.language)
|
|| !Util.areEqual(id, other.id) || !Util.areEqual(language, other.language)
|
||||||
|| !Util.areEqual(containerMimeType, other.containerMimeType)
|
|| !Util.areEqual(containerMimeType, other.containerMimeType)
|
||||||
|
@ -312,6 +312,8 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||||||
int rotationDegrees = getOptionalIntegerV16(mediaFormat, "rotation-degrees");
|
int rotationDegrees = getOptionalIntegerV16(mediaFormat, "rotation-degrees");
|
||||||
int channelCount = getOptionalIntegerV16(mediaFormat, MediaFormat.KEY_CHANNEL_COUNT);
|
int channelCount = getOptionalIntegerV16(mediaFormat, MediaFormat.KEY_CHANNEL_COUNT);
|
||||||
int sampleRate = getOptionalIntegerV16(mediaFormat, MediaFormat.KEY_SAMPLE_RATE);
|
int sampleRate = getOptionalIntegerV16(mediaFormat, MediaFormat.KEY_SAMPLE_RATE);
|
||||||
|
int encoderDelay = getOptionalIntegerV16(mediaFormat, "encoder-delay");
|
||||||
|
int encoderPadding = getOptionalIntegerV16(mediaFormat, "encoder-padding");
|
||||||
ArrayList<byte[]> initializationData = new ArrayList<>();
|
ArrayList<byte[]> initializationData = new ArrayList<>();
|
||||||
for (int i = 0; mediaFormat.containsKey("csd-" + i); i++) {
|
for (int i = 0; mediaFormat.containsKey("csd-" + i); i++) {
|
||||||
ByteBuffer buffer = mediaFormat.getByteBuffer("csd-" + i);
|
ByteBuffer buffer = mediaFormat.getByteBuffer("csd-" + i);
|
||||||
@ -322,7 +324,8 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||||||
}
|
}
|
||||||
Format format = new Format(Integer.toString(index), null, mimeType, Format.NO_VALUE,
|
Format format = new Format(Integer.toString(index), null, mimeType, Format.NO_VALUE,
|
||||||
maxInputSize, width, height, frameRate, rotationDegrees, Format.NO_VALUE, channelCount,
|
maxInputSize, width, height, frameRate, rotationDegrees, Format.NO_VALUE, channelCount,
|
||||||
sampleRate, language, Format.OFFSET_SAMPLE_RELATIVE, initializationData, false);
|
sampleRate, encoderDelay, encoderPadding, language, Format.OFFSET_SAMPLE_RELATIVE,
|
||||||
|
initializationData, false);
|
||||||
format.setFrameworkMediaFormatV16(mediaFormat);
|
format.setFrameworkMediaFormatV16(mediaFormat);
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
@ -119,9 +119,11 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
if (seeker == null) {
|
if (seeker == null) {
|
||||||
setupSeeker(input);
|
setupSeeker(input);
|
||||||
extractorOutput.seekMap(seeker);
|
extractorOutput.seekMap(seeker);
|
||||||
|
int encoderDelay = gaplessInfo != null ? gaplessInfo.encoderDelay : Format.NO_VALUE;
|
||||||
|
int encoderPadding = gaplessInfo != null ? gaplessInfo.encoderPadding : Format.NO_VALUE;
|
||||||
trackOutput.format(Format.createAudioSampleFormat(null, synchronizedHeader.mimeType,
|
trackOutput.format(Format.createAudioSampleFormat(null, synchronizedHeader.mimeType,
|
||||||
Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, synchronizedHeader.channels,
|
Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, synchronizedHeader.channels,
|
||||||
synchronizedHeader.sampleRate, null, null));
|
synchronizedHeader.sampleRate, encoderDelay, encoderPadding, null, null));
|
||||||
}
|
}
|
||||||
return readSample(input);
|
return readSample(input);
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,11 @@
|
|||||||
package com.google.android.exoplayer.extractor.mp4;
|
package com.google.android.exoplayer.extractor.mp4;
|
||||||
|
|
||||||
import com.google.android.exoplayer.C;
|
import com.google.android.exoplayer.C;
|
||||||
|
import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.extractor.Extractor;
|
import com.google.android.exoplayer.extractor.Extractor;
|
||||||
import com.google.android.exoplayer.extractor.ExtractorInput;
|
import com.google.android.exoplayer.extractor.ExtractorInput;
|
||||||
import com.google.android.exoplayer.extractor.ExtractorOutput;
|
import com.google.android.exoplayer.extractor.ExtractorOutput;
|
||||||
|
import com.google.android.exoplayer.extractor.GaplessInfo;
|
||||||
import com.google.android.exoplayer.extractor.PositionHolder;
|
import com.google.android.exoplayer.extractor.PositionHolder;
|
||||||
import com.google.android.exoplayer.extractor.SeekMap;
|
import com.google.android.exoplayer.extractor.SeekMap;
|
||||||
import com.google.android.exoplayer.extractor.TrackOutput;
|
import com.google.android.exoplayer.extractor.TrackOutput;
|
||||||
@ -282,12 +284,12 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
long durationUs = C.UNKNOWN_TIME_US;
|
long durationUs = C.UNKNOWN_TIME_US;
|
||||||
List<Mp4Track> tracks = new ArrayList<>();
|
List<Mp4Track> tracks = new ArrayList<>();
|
||||||
long earliestSampleOffset = Long.MAX_VALUE;
|
long earliestSampleOffset = Long.MAX_VALUE;
|
||||||
// TODO: Apply gapless information.
|
GaplessInfo gaplessInfo = null;
|
||||||
// GaplessInfo gaplessInfo = null;
|
Atom.ContainerAtom udta = moov.getContainerAtomOfType(Atom.TYPE_udta);
|
||||||
// Atom.ContainerAtom udta = moov.getContainerAtomOfType(Atom.TYPE_udta);
|
if (udta != null) {
|
||||||
// if (udta != null) {
|
gaplessInfo = AtomParsers.parseUdta(udta);
|
||||||
// gaplessInfo = AtomParsers.parseUdta(udta);
|
}
|
||||||
// }
|
|
||||||
for (int i = 0; i < moov.containerChildren.size(); i++) {
|
for (int i = 0; i < moov.containerChildren.size(); i++) {
|
||||||
Atom.ContainerAtom atom = moov.containerChildren.get(i);
|
Atom.ContainerAtom atom = moov.containerChildren.get(i);
|
||||||
if (atom.type != Atom.TYPE_trak) {
|
if (atom.type != Atom.TYPE_trak) {
|
||||||
@ -311,7 +313,11 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
// Each sample has up to three bytes of overhead for the start code that replaces its length.
|
// Each sample has up to three bytes of overhead for the start code that replaces its length.
|
||||||
// Allow ten source samples per output sample, like the platform extractor.
|
// Allow ten source samples per output sample, like the platform extractor.
|
||||||
int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
|
int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
|
||||||
mp4Track.trackOutput.format(track.format.copyWithMaxInputSize(maxInputSize));
|
Format format = track.format.copyWithMaxInputSize(maxInputSize);
|
||||||
|
if (gaplessInfo != null) {
|
||||||
|
format = format.copyWithGaplessInfo(gaplessInfo.encoderDelay, gaplessInfo.encoderPadding);
|
||||||
|
}
|
||||||
|
mp4Track.trackOutput.format(format);
|
||||||
|
|
||||||
durationUs = Math.max(durationUs, track.durationUs);
|
durationUs = Math.max(durationUs, track.durationUs);
|
||||||
tracks.add(mp4Track);
|
tracks.add(mp4Track);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user