Support anamorphic video content.
This commit is contained in:
parent
6c3ae7f175
commit
ec90eac301
@ -73,8 +73,8 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoSizeChanged(int width, int height) {
|
public void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio) {
|
||||||
Log.d(TAG, "videoSizeChanged [" + width + ", " + height + "]");
|
Log.d(TAG, "videoSizeChanged [" + width + ", " + height + ", " + pixelWidthHeightRatio + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
// DemoPlayer.InfoListener
|
// DemoPlayer.InfoListener
|
||||||
|
@ -260,9 +260,10 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoSizeChanged(int width, int height) {
|
public void onVideoSizeChanged(int width, int height, float pixelWidthAspectRatio) {
|
||||||
shutterView.setVisibility(View.GONE);
|
shutterView.setVisibility(View.GONE);
|
||||||
surfaceView.setVideoWidthHeightRatio(height == 0 ? 1 : (float) width / height);
|
surfaceView.setVideoWidthHeightRatio(
|
||||||
|
height == 0 ? 1 : (width * pixelWidthAspectRatio) / height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// User controls
|
// User controls
|
||||||
|
@ -93,7 +93,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
|||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onStateChanged(boolean playWhenReady, int playbackState);
|
void onStateChanged(boolean playWhenReady, int playbackState);
|
||||||
void onError(Exception e);
|
void onError(Exception e);
|
||||||
void onVideoSizeChanged(int width, int height);
|
void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -377,9 +377,9 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoSizeChanged(int width, int height) {
|
public void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio) {
|
||||||
for (Listener listener : listeners) {
|
for (Listener listener : listeners) {
|
||||||
listener.onVideoSizeChanged(width, height);
|
listener.onVideoSizeChanged(width, height, pixelWidthHeightRatio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,8 +231,9 @@ public class SimplePlayerActivity extends Activity implements SurfaceHolder.Call
|
|||||||
// MediaCodecVideoTrackRenderer.Listener
|
// MediaCodecVideoTrackRenderer.Listener
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoSizeChanged(int width, int height) {
|
public void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio) {
|
||||||
surfaceView.setVideoWidthHeightRatio(height == 0 ? 1 : (float) width / height);
|
surfaceView.setVideoWidthHeightRatio(
|
||||||
|
height == 0 ? 1 : (pixelWidthHeightRatio * width) / height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,18 +79,19 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value of {@link #sourceState} when the source is not ready.
|
* Value returned by {@link #getSourceState()} when the source is not ready.
|
||||||
*/
|
*/
|
||||||
protected static final int SOURCE_STATE_NOT_READY = 0;
|
protected static final int SOURCE_STATE_NOT_READY = 0;
|
||||||
/**
|
/**
|
||||||
* Value of {@link #sourceState} when the source is ready and we're able to read from it.
|
* Value returned by {@link #getSourceState()} when the source is ready and we're able to read
|
||||||
|
* from it.
|
||||||
*/
|
*/
|
||||||
protected static final int SOURCE_STATE_READY = 1;
|
protected static final int SOURCE_STATE_READY = 1;
|
||||||
/**
|
/**
|
||||||
* Value of {@link #sourceState} when the source is ready but we might not be able to read from
|
* Value returned by {@link #getSourceState()} when the source is ready but we might not be able
|
||||||
* it. We transition to this state when an attempt to read a sample fails despite the source
|
* to read from it. We transition to this state when an attempt to read a sample fails despite the
|
||||||
* reporting that samples are available. This can occur when the next sample to be provided by
|
* source reporting that samples are available. This can occur when the next sample to be provided
|
||||||
* the source is for another renderer.
|
* by the source is for another renderer.
|
||||||
*/
|
*/
|
||||||
protected static final int SOURCE_STATE_READY_READ_MAY_FAIL = 2;
|
protected static final int SOURCE_STATE_READY_READ_MAY_FAIL = 2;
|
||||||
|
|
||||||
@ -620,7 +621,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||||||
* @param formatHolder Holds the new format.
|
* @param formatHolder Holds the new format.
|
||||||
* @throws ExoPlaybackException If an error occurs reinitializing the {@link MediaCodec}.
|
* @throws ExoPlaybackException If an error occurs reinitializing the {@link MediaCodec}.
|
||||||
*/
|
*/
|
||||||
private void onInputFormatChanged(MediaFormatHolder formatHolder) throws ExoPlaybackException {
|
protected void onInputFormatChanged(MediaFormatHolder formatHolder) throws ExoPlaybackException {
|
||||||
MediaFormat oldFormat = format;
|
MediaFormat oldFormat = format;
|
||||||
format = formatHolder.format;
|
format = formatHolder.format;
|
||||||
drmInitData = formatHolder.drmInitData;
|
drmInitData = formatHolder.drmInitData;
|
||||||
|
@ -58,8 +58,11 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
*
|
*
|
||||||
* @param width The video width in pixels.
|
* @param width The video width in pixels.
|
||||||
* @param height The video height in pixels.
|
* @param height The video height in pixels.
|
||||||
|
* @param pixelWidthHeightRatio The width to height ratio of each pixel. For the normal case
|
||||||
|
* of square pixels this will be equal to 1.0. Different values are indicative of anamorphic
|
||||||
|
* content.
|
||||||
*/
|
*/
|
||||||
void onVideoSizeChanged(int width, int height);
|
void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when a frame is rendered to a surface for the first time following that surface
|
* Invoked when a frame is rendered to a surface for the first time following that surface
|
||||||
@ -98,8 +101,10 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
|
|
||||||
private int currentWidth;
|
private int currentWidth;
|
||||||
private int currentHeight;
|
private int currentHeight;
|
||||||
|
private float currentPixelWidthHeightRatio;
|
||||||
private int lastReportedWidth;
|
private int lastReportedWidth;
|
||||||
private int lastReportedHeight;
|
private int lastReportedHeight;
|
||||||
|
private float lastReportedPixelWidthHeightRatio;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param source The upstream source from which the renderer obtains samples.
|
* @param source The upstream source from which the renderer obtains samples.
|
||||||
@ -208,8 +213,10 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
joiningDeadlineUs = -1;
|
joiningDeadlineUs = -1;
|
||||||
currentWidth = -1;
|
currentWidth = -1;
|
||||||
currentHeight = -1;
|
currentHeight = -1;
|
||||||
|
currentPixelWidthHeightRatio = -1;
|
||||||
lastReportedWidth = -1;
|
lastReportedWidth = -1;
|
||||||
lastReportedHeight = -1;
|
lastReportedHeight = -1;
|
||||||
|
lastReportedPixelWidthHeightRatio = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -272,8 +279,10 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
super.onDisabled();
|
super.onDisabled();
|
||||||
currentWidth = -1;
|
currentWidth = -1;
|
||||||
currentHeight = -1;
|
currentHeight = -1;
|
||||||
|
currentPixelWidthHeightRatio = -1;
|
||||||
lastReportedWidth = -1;
|
lastReportedWidth = -1;
|
||||||
lastReportedHeight = -1;
|
lastReportedHeight = -1;
|
||||||
|
lastReportedPixelWidthHeightRatio = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -315,6 +324,14 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
codec.setVideoScalingMode(videoScalingMode);
|
codec.setVideoScalingMode(videoScalingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onInputFormatChanged(MediaFormatHolder holder) throws ExoPlaybackException {
|
||||||
|
super.onInputFormatChanged(holder);
|
||||||
|
// TODO: Ideally this would be read in onOutputFormatChanged, but there doesn't seem
|
||||||
|
// to be a way to pass a custom key/value pair value through to the output format.
|
||||||
|
currentPixelWidthHeightRatio = holder.format.pixelWidthHeightRatio;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onOutputFormatChanged(android.media.MediaFormat format) {
|
protected void onOutputFormatChanged(android.media.MediaFormat format) {
|
||||||
boolean hasCrop = format.containsKey(KEY_CROP_RIGHT) && format.containsKey(KEY_CROP_LEFT)
|
boolean hasCrop = format.containsKey(KEY_CROP_RIGHT) && format.containsKey(KEY_CROP_LEFT)
|
||||||
@ -394,10 +411,12 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void renderOutputBuffer(MediaCodec codec, int bufferIndex) {
|
private void renderOutputBuffer(MediaCodec codec, int bufferIndex) {
|
||||||
if (lastReportedWidth != currentWidth || lastReportedHeight != currentHeight) {
|
if (lastReportedWidth != currentWidth || lastReportedHeight != currentHeight
|
||||||
|
|| lastReportedPixelWidthHeightRatio != currentPixelWidthHeightRatio) {
|
||||||
lastReportedWidth = currentWidth;
|
lastReportedWidth = currentWidth;
|
||||||
lastReportedHeight = currentHeight;
|
lastReportedHeight = currentHeight;
|
||||||
notifyVideoSizeChanged(currentWidth, currentHeight);
|
lastReportedPixelWidthHeightRatio = currentPixelWidthHeightRatio;
|
||||||
|
notifyVideoSizeChanged(currentWidth, currentHeight, currentPixelWidthHeightRatio);
|
||||||
}
|
}
|
||||||
TraceUtil.beginSection("renderVideoBuffer");
|
TraceUtil.beginSection("renderVideoBuffer");
|
||||||
codec.releaseOutputBuffer(bufferIndex, true);
|
codec.releaseOutputBuffer(bufferIndex, true);
|
||||||
@ -409,12 +428,13 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyVideoSizeChanged(final int width, final int height) {
|
private void notifyVideoSizeChanged(final int width, final int height,
|
||||||
|
final float pixelWidthHeightRatio) {
|
||||||
if (eventHandler != null && eventListener != null) {
|
if (eventHandler != null && eventListener != null) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
eventListener.onVideoSizeChanged(width, height);
|
eventListener.onVideoSizeChanged(width, height, pixelWidthHeightRatio);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class MediaFormat {
|
public class MediaFormat {
|
||||||
|
|
||||||
|
private static final String KEY_PIXEL_WIDTH_HEIGHT_RATIO =
|
||||||
|
"com.google.android.videos.pixelWidthHeightRatio";
|
||||||
|
|
||||||
public static final int NO_VALUE = -1;
|
public static final int NO_VALUE = -1;
|
||||||
|
|
||||||
public final String mimeType;
|
public final String mimeType;
|
||||||
@ -38,6 +41,7 @@ public class MediaFormat {
|
|||||||
|
|
||||||
public final int width;
|
public final int width;
|
||||||
public final int height;
|
public final int height;
|
||||||
|
public final float pixelWidthHeightRatio;
|
||||||
|
|
||||||
public final int channelCount;
|
public final int channelCount;
|
||||||
public final int sampleRate;
|
public final int sampleRate;
|
||||||
@ -59,14 +63,19 @@ public class MediaFormat {
|
|||||||
|
|
||||||
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, int width,
|
public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, int width,
|
||||||
int height, List<byte[]> initializationData) {
|
int height, List<byte[]> initializationData) {
|
||||||
return new MediaFormat(mimeType, maxInputSize, width, height, NO_VALUE, NO_VALUE,
|
return createVideoFormat(mimeType, maxInputSize, width, height, 1, initializationData);
|
||||||
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, initializationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, int channelCount,
|
public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, int channelCount,
|
||||||
int sampleRate, List<byte[]> initializationData) {
|
int sampleRate, List<byte[]> initializationData) {
|
||||||
return new MediaFormat(mimeType, maxInputSize, NO_VALUE, NO_VALUE, channelCount, sampleRate,
|
return new MediaFormat(mimeType, maxInputSize, NO_VALUE, NO_VALUE, NO_VALUE, channelCount,
|
||||||
initializationData);
|
sampleRate, initializationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(16)
|
@TargetApi(16)
|
||||||
@ -78,6 +87,7 @@ public class MediaFormat {
|
|||||||
height = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_HEIGHT);
|
height = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_HEIGHT);
|
||||||
channelCount = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_CHANNEL_COUNT);
|
channelCount = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_CHANNEL_COUNT);
|
||||||
sampleRate = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_SAMPLE_RATE);
|
sampleRate = getOptionalIntegerV16(format, android.media.MediaFormat.KEY_SAMPLE_RATE);
|
||||||
|
pixelWidthHeightRatio = getOptionalFloatV16(format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
|
||||||
initializationData = new ArrayList<byte[]>();
|
initializationData = new ArrayList<byte[]>();
|
||||||
for (int i = 0; format.containsKey("csd-" + i); i++) {
|
for (int i = 0; format.containsKey("csd-" + i); i++) {
|
||||||
ByteBuffer buffer = format.getByteBuffer("csd-" + i);
|
ByteBuffer buffer = format.getByteBuffer("csd-" + i);
|
||||||
@ -90,12 +100,14 @@ public class MediaFormat {
|
|||||||
maxHeight = NO_VALUE;
|
maxHeight = NO_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaFormat(String mimeType, int maxInputSize, int width, int height, int channelCount,
|
private MediaFormat(String mimeType, int maxInputSize, int width, int height,
|
||||||
int sampleRate, List<byte[]> initializationData) {
|
float pixelWidthHeightRatio, int channelCount, int sampleRate,
|
||||||
|
List<byte[]> initializationData) {
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.maxInputSize = maxInputSize;
|
this.maxInputSize = maxInputSize;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
||||||
this.channelCount = channelCount;
|
this.channelCount = channelCount;
|
||||||
this.sampleRate = sampleRate;
|
this.sampleRate = sampleRate;
|
||||||
this.initializationData = initializationData == null ? Collections.<byte[]>emptyList()
|
this.initializationData = initializationData == null ? Collections.<byte[]>emptyList()
|
||||||
@ -128,6 +140,7 @@ public class MediaFormat {
|
|||||||
result = 31 * result + maxInputSize;
|
result = 31 * result + maxInputSize;
|
||||||
result = 31 * result + width;
|
result = 31 * result + width;
|
||||||
result = 31 * result + height;
|
result = 31 * result + height;
|
||||||
|
result = 31 * result + Float.floatToRawIntBits(pixelWidthHeightRatio);
|
||||||
result = 31 * result + maxWidth;
|
result = 31 * result + maxWidth;
|
||||||
result = 31 * result + maxHeight;
|
result = 31 * result + maxHeight;
|
||||||
result = 31 * result + channelCount;
|
result = 31 * result + channelCount;
|
||||||
@ -163,6 +176,7 @@ public class MediaFormat {
|
|||||||
|
|
||||||
private boolean equalsInternal(MediaFormat other, boolean ignoreMaxDimensions) {
|
private boolean equalsInternal(MediaFormat other, boolean ignoreMaxDimensions) {
|
||||||
if (maxInputSize != other.maxInputSize || width != other.width || height != other.height
|
if (maxInputSize != other.maxInputSize || width != other.width || height != other.height
|
||||||
|
|| pixelWidthHeightRatio != other.pixelWidthHeightRatio
|
||||||
|| (!ignoreMaxDimensions && (maxWidth != other.maxWidth || maxHeight != other.maxHeight))
|
|| (!ignoreMaxDimensions && (maxWidth != other.maxWidth || maxHeight != other.maxHeight))
|
||||||
|| channelCount != other.channelCount || sampleRate != other.sampleRate
|
|| channelCount != other.channelCount || sampleRate != other.sampleRate
|
||||||
|| !Util.areEqual(mimeType, other.mimeType)
|
|| !Util.areEqual(mimeType, other.mimeType)
|
||||||
@ -179,8 +193,9 @@ public class MediaFormat {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "MediaFormat(" + mimeType + ", " + maxInputSize + ", " + width + ", " + height + ", " +
|
return "MediaFormat(" + mimeType + ", " + maxInputSize + ", " + width + ", " + height + ", "
|
||||||
channelCount + ", " + sampleRate + ", " + maxWidth + ", " + maxHeight + ")";
|
+ pixelWidthHeightRatio + ", " + channelCount + ", " + sampleRate + ", " + maxWidth + ", "
|
||||||
|
+ maxHeight + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,6 +211,7 @@ public class MediaFormat {
|
|||||||
maybeSetIntegerV16(format, android.media.MediaFormat.KEY_HEIGHT, height);
|
maybeSetIntegerV16(format, android.media.MediaFormat.KEY_HEIGHT, height);
|
||||||
maybeSetIntegerV16(format, android.media.MediaFormat.KEY_CHANNEL_COUNT, channelCount);
|
maybeSetIntegerV16(format, android.media.MediaFormat.KEY_CHANNEL_COUNT, channelCount);
|
||||||
maybeSetIntegerV16(format, android.media.MediaFormat.KEY_SAMPLE_RATE, sampleRate);
|
maybeSetIntegerV16(format, android.media.MediaFormat.KEY_SAMPLE_RATE, sampleRate);
|
||||||
|
maybeSetFloatV16(format, KEY_PIXEL_WIDTH_HEIGHT_RATIO, pixelWidthHeightRatio);
|
||||||
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)));
|
||||||
}
|
}
|
||||||
@ -221,9 +237,21 @@ public class MediaFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(16)
|
@TargetApi(16)
|
||||||
private static final int getOptionalIntegerV16(android.media.MediaFormat format,
|
private static final void maybeSetFloatV16(android.media.MediaFormat format, String key,
|
||||||
String key) {
|
float value) {
|
||||||
|
if (value != NO_VALUE) {
|
||||||
|
format.setFloat(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(16)
|
||||||
|
private static final int getOptionalIntegerV16(android.media.MediaFormat format, String key) {
|
||||||
return format.containsKey(key) ? format.getInteger(key) : NO_VALUE;
|
return format.containsKey(key) ? format.getInteger(key) : NO_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(16)
|
||||||
|
private static final float getOptionalFloatV16(android.media.MediaFormat format, String key) {
|
||||||
|
return format.containsKey(key) ? format.getFloat(key) : NO_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ import java.util.ArrayList;
|
|||||||
public static final int TYPE_saiz = 0x7361697A;
|
public static final int TYPE_saiz = 0x7361697A;
|
||||||
public static final int TYPE_uuid = 0x75756964;
|
public static final int TYPE_uuid = 0x75756964;
|
||||||
public static final int TYPE_senc = 0x73656E63;
|
public static final int TYPE_senc = 0x73656E63;
|
||||||
|
public static final int TYPE_pasp = 0x70617370;
|
||||||
|
|
||||||
public final int type;
|
public final int type;
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ public final class FragmentedMp4Extractor implements Extractor {
|
|||||||
parsedAtoms.add(Atom.TYPE_saiz);
|
parsedAtoms.add(Atom.TYPE_saiz);
|
||||||
parsedAtoms.add(Atom.TYPE_uuid);
|
parsedAtoms.add(Atom.TYPE_uuid);
|
||||||
parsedAtoms.add(Atom.TYPE_senc);
|
parsedAtoms.add(Atom.TYPE_senc);
|
||||||
|
parsedAtoms.add(Atom.TYPE_pasp);
|
||||||
PARSED_ATOMS = Collections.unmodifiableSet(parsedAtoms);
|
PARSED_ATOMS = Collections.unmodifiableSet(parsedAtoms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,6 +530,7 @@ public final class FragmentedMp4Extractor implements Extractor {
|
|||||||
parent.skip(24);
|
parent.skip(24);
|
||||||
int width = parent.readUnsignedShort();
|
int width = parent.readUnsignedShort();
|
||||||
int height = parent.readUnsignedShort();
|
int height = parent.readUnsignedShort();
|
||||||
|
float pixelWidthHeightRatio = 1;
|
||||||
parent.skip(50);
|
parent.skip(50);
|
||||||
|
|
||||||
List<byte[]> initializationData = null;
|
List<byte[]> initializationData = null;
|
||||||
@ -543,12 +545,14 @@ public final class FragmentedMp4Extractor implements Extractor {
|
|||||||
initializationData = parseAvcCFromParent(parent, childStartPosition);
|
initializationData = parseAvcCFromParent(parent, childStartPosition);
|
||||||
} else if (childAtomType == Atom.TYPE_sinf) {
|
} else if (childAtomType == Atom.TYPE_sinf) {
|
||||||
trackEncryptionBox = parseSinfFromParent(parent, childStartPosition, childAtomSize);
|
trackEncryptionBox = parseSinfFromParent(parent, childStartPosition, childAtomSize);
|
||||||
|
} else if (childAtomType == Atom.TYPE_pasp) {
|
||||||
|
pixelWidthHeightRatio = parsePaspFromParent(parent, childStartPosition);
|
||||||
}
|
}
|
||||||
childPosition += childAtomSize;
|
childPosition += childAtomSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaFormat format = MediaFormat.createVideoFormat(MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE,
|
MediaFormat format = MediaFormat.createVideoFormat(MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE,
|
||||||
width, height, initializationData);
|
width, height, pixelWidthHeightRatio, initializationData);
|
||||||
return Pair.create(format, trackEncryptionBox);
|
return Pair.create(format, trackEncryptionBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,6 +647,13 @@ public final class FragmentedMp4Extractor implements Extractor {
|
|||||||
return trackEncryptionBox;
|
return trackEncryptionBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static float parsePaspFromParent(ParsableByteArray parent, int position) {
|
||||||
|
parent.setPosition(position + ATOM_HEADER_SIZE);
|
||||||
|
int hSpacing = parent.readUnsignedIntToInt();
|
||||||
|
int vSpacing = parent.readUnsignedIntToInt();
|
||||||
|
return (float) hSpacing / vSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
private static TrackEncryptionBox parseSchiFromParent(ParsableByteArray parent, int position,
|
private static TrackEncryptionBox parseSchiFromParent(ParsableByteArray parent, int position,
|
||||||
int size) {
|
int size) {
|
||||||
int childPosition = position + ATOM_HEADER_SIZE;
|
int childPosition = position + ATOM_HEADER_SIZE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user