Commit ae2e8589 by olly Committed by Oliver Woodman

Fix incorrect playback speed of mono audio on MTK/JB devices.

Issue #801
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=117225377
parent 8447781a
...@@ -214,7 +214,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -214,7 +214,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
private boolean codecNeedsFlushWorkaround; private boolean codecNeedsFlushWorkaround;
private boolean codecNeedsEosPropagationWorkaround; private boolean codecNeedsEosPropagationWorkaround;
private boolean codecNeedsEosFlushWorkaround; private boolean codecNeedsEosFlushWorkaround;
private boolean codecReceivedEos; private boolean codecNeedsMonoChannelCountWorkaround;
private ByteBuffer[] inputBuffers; private ByteBuffer[] inputBuffers;
private ByteBuffer[] outputBuffers; private ByteBuffer[] outputBuffers;
private long codecHotswapTimeMs; private long codecHotswapTimeMs;
...@@ -224,7 +224,8 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -224,7 +224,8 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
private boolean codecReconfigured; private boolean codecReconfigured;
private int codecReconfigurationState; private int codecReconfigurationState;
private int codecReinitializationState; private int codecReinitializationState;
private boolean codecHasQueuedBuffers; private boolean codecReceivedBuffers;
private boolean codecReceivedEos;
private int sourceState; private int sourceState;
private boolean inputStreamEnded; private boolean inputStreamEnded;
...@@ -362,6 +363,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -362,6 +363,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName); codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
codecNeedsEosPropagationWorkaround = codecNeedsEosPropagationWorkaround(codecName); codecNeedsEosPropagationWorkaround = codecNeedsEosPropagationWorkaround(codecName);
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName); codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
codecNeedsMonoChannelCountWorkaround = codecNeedsMonoChannelCountWorkaround(codecName, format);
try { try {
long codecInitializingTimestamp = SystemClock.elapsedRealtime(); long codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createByCodecName(" + codecName + ")"); TraceUtil.beginSection("createByCodecName(" + codecName + ")");
...@@ -435,12 +437,13 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -435,12 +437,13 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
inputBuffers = null; inputBuffers = null;
outputBuffers = null; outputBuffers = null;
codecReconfigured = false; codecReconfigured = false;
codecHasQueuedBuffers = false; codecReceivedBuffers = false;
codecIsAdaptive = false; codecIsAdaptive = false;
codecNeedsDiscardToSpsWorkaround = false; codecNeedsDiscardToSpsWorkaround = false;
codecNeedsFlushWorkaround = false; codecNeedsFlushWorkaround = false;
codecNeedsEosPropagationWorkaround = false; codecNeedsEosPropagationWorkaround = false;
codecNeedsEosFlushWorkaround = false; codecNeedsEosFlushWorkaround = false;
codecNeedsMonoChannelCountWorkaround = false;
codecReceivedEos = false; codecReceivedEos = false;
codecReconfigurationState = RECONFIGURATION_STATE_NONE; codecReconfigurationState = RECONFIGURATION_STATE_NONE;
codecReinitializationState = REINITIALIZATION_STATE_NONE; codecReinitializationState = REINITIALIZATION_STATE_NONE;
...@@ -523,7 +526,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -523,7 +526,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
} else { } else {
// We can flush and re-use the existing decoder. // We can flush and re-use the existing decoder.
codec.flush(); codec.flush();
codecHasQueuedBuffers = false; codecReceivedBuffers = false;
} }
if (codecReconfigured && format != null) { if (codecReconfigured && format != null) {
// Any reconfiguration data that we send shortly before the flush may be discarded. We // Any reconfiguration data that we send shortly before the flush may be discarded. We
...@@ -611,7 +614,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -611,7 +614,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
} }
inputStreamEnded = true; inputStreamEnded = true;
if (!codecHasQueuedBuffers) { if (!codecReceivedBuffers) {
processEndOfStream(); processEndOfStream();
return false; return false;
} }
...@@ -656,7 +659,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -656,7 +659,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
codec.queueInputBuffer(inputIndex, 0, bufferSize, presentationTimeUs, 0); codec.queueInputBuffer(inputIndex, 0, bufferSize, presentationTimeUs, 0);
} }
inputIndex = -1; inputIndex = -1;
codecHasQueuedBuffers = true; codecReceivedBuffers = true;
codecReconfigurationState = RECONFIGURATION_STATE_NONE; codecReconfigurationState = RECONFIGURATION_STATE_NONE;
onQueuedInputBuffer(presentationTimeUs); onQueuedInputBuffer(presentationTimeUs);
} catch (CryptoException e) { } catch (CryptoException e) {
...@@ -711,7 +714,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -711,7 +714,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
codecReconfigured = true; codecReconfigured = true;
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
} else { } else {
if (codecHasQueuedBuffers) { if (codecReceivedBuffers) {
// Signal end of stream and wait for any final output buffers before re-initialization. // Signal end of stream and wait for any final output buffers before re-initialization.
codecReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM; codecReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM;
} else { } else {
...@@ -837,8 +840,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -837,8 +840,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
} }
if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
onOutputFormatChanged(codec.getOutputFormat()); processOutputFormat();
codecCounters.outputFormatChangedCount++;
return true; return true;
} else if (outputIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { } else if (outputIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = codec.getOutputBuffers(); outputBuffers = codec.getOutputBuffers();
...@@ -873,6 +875,20 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -873,6 +875,20 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
} }
/** /**
* Processes a new output format.
*
* @throws ExoPlaybackException If an error occurs processing the output format.
*/
private void processOutputFormat() throws ExoPlaybackException {
android.media.MediaFormat format = codec.getOutputFormat();
if (codecNeedsMonoChannelCountWorkaround) {
format.setInteger(android.media.MediaFormat.KEY_CHANNEL_COUNT, 1);
}
onOutputFormatChanged(format);
codecCounters.outputFormatChangedCount++;
}
/**
* Processes the provided output buffer. * Processes the provided output buffer.
* *
* @return True if the output buffer was processed (e.g. rendered or discarded) and hence is no * @return True if the output buffer was processed (e.g. rendered or discarded) and hence is no
...@@ -1007,4 +1023,22 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -1007,4 +1023,22 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
return Util.SDK_INT <= 23 && "OMX.google.vorbis.decoder".equals(name); return Util.SDK_INT <= 23 && "OMX.google.vorbis.decoder".equals(name);
} }
/**
* Returns whether the decoder is known to set the number of audio channels in the output format
* to 2 for the given input format, whilst only actually outputting a single channel.
* <p>
* If true is returned then we explicitly override the number of channels in the output format,
* setting it to 1.
*
* @param name The decoder name.
* @param format The input format.
* @return True if the device is known to set the number of audio channels in the output format
* to 2 for the given input format, whilst only actually outputting a single channel. False
* otherwise.
*/
private static boolean codecNeedsMonoChannelCountWorkaround(String name, Format format) {
return Util.SDK_INT <= 18 && format.channelCount == 1
&& "OMX.MTK.AUDIO.DECODER.MP3".equals(name);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment