Commit fafcd79e by Oliver Woodman

Move AC-3 bitrate calculation into Ac3Util.

This is in preparation for removing bitrate from MediaFormat.
parent 6bf62770
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer.audio; package com.google.android.exoplayer.audio;
import com.google.android.exoplayer.C; import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Ac3Util;
import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Util; import com.google.android.exoplayer.util.Util;
...@@ -433,11 +434,7 @@ public final class AudioTrack { ...@@ -433,11 +434,7 @@ public final class AudioTrack {
int result = 0; int result = 0;
if (temporaryBufferSize == 0) { if (temporaryBufferSize == 0) {
if (isAc3 && ac3Bitrate == UNKNOWN_AC3_BITRATE) { if (isAc3 && ac3Bitrate == UNKNOWN_AC3_BITRATE) {
// Each AC-3 buffer contains 1536 frames of audio, so the AudioTrack playback position ac3Bitrate = Ac3Util.getBitrate(size, sampleRate);
// advances by 1536 per buffer (32 ms at 48 kHz). Calculate the bitrate in kbit/s.
int unscaledAc3Bitrate = size * 8 * sampleRate;
int divisor = 1000 * 1536;
ac3Bitrate = (unscaledAc3Bitrate + divisor / 2) / divisor;
} }
// This is the first time we've seen this {@code buffer}. // This is the first time we've seen this {@code buffer}.
......
...@@ -46,6 +46,7 @@ import com.google.android.exoplayer.util.ParsableByteArray; ...@@ -46,6 +46,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
private long frameDurationUs; private long frameDurationUs;
private MediaFormat mediaFormat; private MediaFormat mediaFormat;
private int sampleSize; private int sampleSize;
private int bitrate;
// Used when reading the samples. // Used when reading the samples.
private long timeUs; private long timeUs;
...@@ -149,14 +150,15 @@ import com.google.android.exoplayer.util.ParsableByteArray; ...@@ -149,14 +150,15 @@ import com.google.android.exoplayer.util.ParsableByteArray;
* Parses the sample header. * Parses the sample header.
*/ */
private void parseHeader() { private void parseHeader() {
headerScratchBits.setPosition(0);
sampleSize = Ac3Util.parseFrameSize(headerScratchBits);
if (mediaFormat == null) { if (mediaFormat == null) {
headerScratchBits.setPosition(0); headerScratchBits.setPosition(0);
mediaFormat = Ac3Util.parseFrameAc3Format(headerScratchBits); mediaFormat = Ac3Util.parseFrameAc3Format(headerScratchBits);
output.format(mediaFormat); output.format(mediaFormat);
bitrate = Ac3Util.getBitrate(sampleSize, mediaFormat.sampleRate);
} }
headerScratchBits.setPosition(0); frameDurationUs = (int) (1000L * 8 * sampleSize / bitrate);
sampleSize = Ac3Util.parseFrameSize(headerScratchBits);
frameDurationUs = (int) (1000000L * 8 * sampleSize / mediaFormat.bitrate);
} }
} }
...@@ -50,10 +50,8 @@ public final class Ac3Util { ...@@ -50,10 +50,8 @@ public final class Ac3Util {
if ((nextByte & 0x04) != 0) { if ((nextByte & 0x04) != 0) {
channelCount++; channelCount++;
} }
// Map bit_rate_code onto a bitrate in bit/s.
int bitrate = BITRATES[((nextByte & 0x03) << 3) + (data.readUnsignedByte() >> 5)] * 1000;
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE, return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
MediaFormat.NO_VALUE, channelCount, sampleRate, bitrate, Collections.<byte[]>emptyList()); MediaFormat.NO_VALUE, channelCount, sampleRate, Collections.<byte[]>emptyList());
} }
/** /**
...@@ -91,8 +89,7 @@ public final class Ac3Util { ...@@ -91,8 +89,7 @@ public final class Ac3Util {
data.skipBits(4 * 8); data.skipBits(4 * 8);
int fscod = data.readBits(2); int fscod = data.readBits(2);
int frmsizecod = data.readBits(6); data.skipBits(14); // frmsizecod(6) + bsid (5 bits) + bsmod (3 bits)
data.skipBits(8); // bsid (5 bits) + bsmod (3 bits)
int acmod = data.readBits(3); int acmod = data.readBits(3);
if ((acmod & 0x01) != 0 && acmod != 1) { if ((acmod & 0x01) != 0 && acmod != 1) {
data.skipBits(2); // cmixlev data.skipBits(2); // cmixlev
...@@ -106,7 +103,7 @@ public final class Ac3Util { ...@@ -106,7 +103,7 @@ public final class Ac3Util {
boolean lfeon = data.readBit(); boolean lfeon = data.readBit();
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE, return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
MediaFormat.NO_VALUE, CHANNEL_COUNTS[acmod] + (lfeon ? 1 : 0), SAMPLE_RATES[fscod], MediaFormat.NO_VALUE, CHANNEL_COUNTS[acmod] + (lfeon ? 1 : 0), SAMPLE_RATES[fscod],
BITRATES[frmsizecod / 2] * 1000, Collections.<byte[]>emptyList()); Collections.<byte[]>emptyList());
} }
/** /**
...@@ -133,6 +130,21 @@ public final class Ac3Util { ...@@ -133,6 +130,21 @@ public final class Ac3Util {
} }
} }
/**
* Returns the bitrate of AC-3 audio given the size of a buffer and the sample rate.
*
* @param bufferSize Size in bytes of a full buffer of samples.
* @param sampleRate Sample rate in hz.
* @return Bitrate of the audio stream in kbit/s.
*/
public static int getBitrate(int bufferSize, int sampleRate) {
// Each AC-3 buffer contains 1536 frames of audio, so the AudioTrack playback position
// advances by 1536 per buffer (32 ms at 48 kHz).
int unscaledBitrate = bufferSize * 8 * sampleRate;
int divisor = 1000 * 1536;
return (unscaledBitrate + divisor / 2) / divisor;
}
private Ac3Util() { private Ac3Util() {
// Prevent instantiation. // Prevent instantiation.
} }
......
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