Use the true bitrate for CBR MP3 seeking
PiperOrigin-RevId: 225989898
This commit is contained in:
parent
ee2e89e0cd
commit
0e8e9621c0
@ -7,6 +7,7 @@
|
|||||||
* Support for playing spherical videos on Daydream.
|
* Support for playing spherical videos on Daydream.
|
||||||
* Improve decoder re-use between playbacks. TODO: Write and link a blog post
|
* Improve decoder re-use between playbacks. TODO: Write and link a blog post
|
||||||
here ([#2826](https://github.com/google/ExoPlayer/issues/2826)).
|
here ([#2826](https://github.com/google/ExoPlayer/issues/2826)).
|
||||||
|
* Use the true bitrate for constant-bitrate MP3 seeking.
|
||||||
* Track selection:
|
* Track selection:
|
||||||
* Add options for controlling audio track selections to `DefaultTrackSelector`
|
* Add options for controlling audio track selections to `DefaultTrackSelector`
|
||||||
([#3314](https://github.com/google/ExoPlayer/issues/3314)).
|
([#3314](https://github.com/google/ExoPlayer/issues/3314)).
|
||||||
|
@ -34,16 +34,26 @@ public final class MpegAudioHeader {
|
|||||||
private static final String[] MIME_TYPE_BY_LAYER =
|
private static final String[] MIME_TYPE_BY_LAYER =
|
||||||
new String[] {MimeTypes.AUDIO_MPEG_L1, MimeTypes.AUDIO_MPEG_L2, MimeTypes.AUDIO_MPEG};
|
new String[] {MimeTypes.AUDIO_MPEG_L1, MimeTypes.AUDIO_MPEG_L2, MimeTypes.AUDIO_MPEG};
|
||||||
private static final int[] SAMPLING_RATE_V1 = {44100, 48000, 32000};
|
private static final int[] SAMPLING_RATE_V1 = {44100, 48000, 32000};
|
||||||
private static final int[] BITRATE_V1_L1 =
|
private static final int[] BITRATE_V1_L1 = {
|
||||||
{32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448};
|
32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000,
|
||||||
private static final int[] BITRATE_V2_L1 =
|
416000, 448000
|
||||||
{32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256};
|
};
|
||||||
private static final int[] BITRATE_V1_L2 =
|
private static final int[] BITRATE_V2_L1 = {
|
||||||
{32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384};
|
32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000,
|
||||||
private static final int[] BITRATE_V1_L3 =
|
224000, 256000
|
||||||
{32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320};
|
};
|
||||||
private static final int[] BITRATE_V2 =
|
private static final int[] BITRATE_V1_L2 = {
|
||||||
{8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160};
|
32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000,
|
||||||
|
320000, 384000
|
||||||
|
};
|
||||||
|
private static final int[] BITRATE_V1_L3 = {
|
||||||
|
32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000,
|
||||||
|
320000
|
||||||
|
};
|
||||||
|
private static final int[] BITRATE_V2 = {
|
||||||
|
8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000,
|
||||||
|
160000
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of the frame associated with {@code header}, or {@link C#LENGTH_UNSET} if it
|
* Returns the size of the frame associated with {@code header}, or {@link C#LENGTH_UNSET} if it
|
||||||
@ -89,7 +99,7 @@ public final class MpegAudioHeader {
|
|||||||
if (layer == 3) {
|
if (layer == 3) {
|
||||||
// Layer I (layer == 3)
|
// Layer I (layer == 3)
|
||||||
bitrate = version == 3 ? BITRATE_V1_L1[bitrateIndex - 1] : BITRATE_V2_L1[bitrateIndex - 1];
|
bitrate = version == 3 ? BITRATE_V1_L1[bitrateIndex - 1] : BITRATE_V2_L1[bitrateIndex - 1];
|
||||||
return (12000 * bitrate / samplingRate + padding) * 4;
|
return (12 * bitrate / samplingRate + padding) * 4;
|
||||||
} else {
|
} else {
|
||||||
// Layer II (layer == 2) or III (layer == 1)
|
// Layer II (layer == 2) or III (layer == 1)
|
||||||
if (version == 3) {
|
if (version == 3) {
|
||||||
@ -102,10 +112,10 @@ public final class MpegAudioHeader {
|
|||||||
|
|
||||||
if (version == 3) {
|
if (version == 3) {
|
||||||
// Version 1
|
// Version 1
|
||||||
return 144000 * bitrate / samplingRate + padding;
|
return 144 * bitrate / samplingRate + padding;
|
||||||
} else {
|
} else {
|
||||||
// Version 2 or 2.5
|
// Version 2 or 2.5
|
||||||
return (layer == 1 ? 72000 : 144000) * bitrate / samplingRate + padding;
|
return (layer == 1 ? 72 : 144) * bitrate / samplingRate + padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +169,7 @@ public final class MpegAudioHeader {
|
|||||||
if (layer == 3) {
|
if (layer == 3) {
|
||||||
// Layer I (layer == 3)
|
// Layer I (layer == 3)
|
||||||
bitrate = version == 3 ? BITRATE_V1_L1[bitrateIndex - 1] : BITRATE_V2_L1[bitrateIndex - 1];
|
bitrate = version == 3 ? BITRATE_V1_L1[bitrateIndex - 1] : BITRATE_V2_L1[bitrateIndex - 1];
|
||||||
frameSize = (12000 * bitrate / sampleRate + padding) * 4;
|
frameSize = (12 * bitrate / sampleRate + padding) * 4;
|
||||||
samplesPerFrame = 384;
|
samplesPerFrame = 384;
|
||||||
} else {
|
} else {
|
||||||
// Layer II (layer == 2) or III (layer == 1)
|
// Layer II (layer == 2) or III (layer == 1)
|
||||||
@ -167,19 +177,22 @@ public final class MpegAudioHeader {
|
|||||||
// Version 1
|
// Version 1
|
||||||
bitrate = layer == 2 ? BITRATE_V1_L2[bitrateIndex - 1] : BITRATE_V1_L3[bitrateIndex - 1];
|
bitrate = layer == 2 ? BITRATE_V1_L2[bitrateIndex - 1] : BITRATE_V1_L3[bitrateIndex - 1];
|
||||||
samplesPerFrame = 1152;
|
samplesPerFrame = 1152;
|
||||||
frameSize = 144000 * bitrate / sampleRate + padding;
|
frameSize = 144 * bitrate / sampleRate + padding;
|
||||||
} else {
|
} else {
|
||||||
// Version 2 or 2.5.
|
// Version 2 or 2.5.
|
||||||
bitrate = BITRATE_V2[bitrateIndex - 1];
|
bitrate = BITRATE_V2[bitrateIndex - 1];
|
||||||
samplesPerFrame = layer == 1 ? 576 : 1152;
|
samplesPerFrame = layer == 1 ? 576 : 1152;
|
||||||
frameSize = (layer == 1 ? 72000 : 144000) * bitrate / sampleRate + padding;
|
frameSize = (layer == 1 ? 72 : 144) * bitrate / sampleRate + padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate the bitrate in the same way Mp3Extractor calculates sample timestamps so that
|
||||||
|
// seeking to a given timestamp and playing from the start up to that timestamp give the same
|
||||||
|
// results for CBR streams. See also [internal: b/120390268].
|
||||||
|
bitrate = 8 * frameSize * sampleRate / samplesPerFrame;
|
||||||
String mimeType = MIME_TYPE_BY_LAYER[3 - layer];
|
String mimeType = MIME_TYPE_BY_LAYER[3 - layer];
|
||||||
int channels = ((headerData >> 6) & 3) == 3 ? 1 : 2;
|
int channels = ((headerData >> 6) & 3) == 3 ? 1 : 2;
|
||||||
header.setValues(version, mimeType, frameSize, sampleRate, channels, bitrate * 1000,
|
header.setValues(version, mimeType, frameSize, sampleRate, channels, bitrate, samplesPerFrame);
|
||||||
samplesPerFrame);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,8 +211,14 @@ public final class MpegAudioHeader {
|
|||||||
/** Number of samples stored in the frame. */
|
/** Number of samples stored in the frame. */
|
||||||
public int samplesPerFrame;
|
public int samplesPerFrame;
|
||||||
|
|
||||||
private void setValues(int version, String mimeType, int frameSize, int sampleRate, int channels,
|
private void setValues(
|
||||||
int bitrate, int samplesPerFrame) {
|
int version,
|
||||||
|
String mimeType,
|
||||||
|
int frameSize,
|
||||||
|
int sampleRate,
|
||||||
|
int channels,
|
||||||
|
int bitrate,
|
||||||
|
int samplesPerFrame) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.frameSize = frameSize;
|
this.frameSize = frameSize;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
seekMap:
|
seekMap:
|
||||||
isSeekable = true
|
isSeekable = true
|
||||||
duration = 26125
|
duration = 26122
|
||||||
getPosition(0) = [[timeUs=0, position=0]]
|
getPosition(0) = [[timeUs=0, position=0]]
|
||||||
numberOfTracks = 1
|
numberOfTracks = 1
|
||||||
track 0:
|
track 0:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
seekMap:
|
seekMap:
|
||||||
isSeekable = true
|
isSeekable = true
|
||||||
duration = 26125
|
duration = 26122
|
||||||
getPosition(0) = [[timeUs=0, position=0]]
|
getPosition(0) = [[timeUs=0, position=0]]
|
||||||
numberOfTracks = 1
|
numberOfTracks = 1
|
||||||
track 0:
|
track 0:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
seekMap:
|
seekMap:
|
||||||
isSeekable = true
|
isSeekable = true
|
||||||
duration = 26125
|
duration = 26122
|
||||||
getPosition(0) = [[timeUs=0, position=0]]
|
getPosition(0) = [[timeUs=0, position=0]]
|
||||||
numberOfTracks = 1
|
numberOfTracks = 1
|
||||||
track 0:
|
track 0:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
seekMap:
|
seekMap:
|
||||||
isSeekable = true
|
isSeekable = true
|
||||||
duration = 26125
|
duration = 26122
|
||||||
getPosition(0) = [[timeUs=0, position=0]]
|
getPosition(0) = [[timeUs=0, position=0]]
|
||||||
numberOfTracks = 1
|
numberOfTracks = 1
|
||||||
track 0:
|
track 0:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user