mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Remove impossible UnsupportedEncodingException
from Id3Decoder
The list of charsets is already hard-coded, and using `Charset` types ensures they will all be present at run-time, hence we will never encounter an 'unsupported' charset. PiperOrigin-RevId: 491324466 (cherry picked from commit 5292e408a6fd000c1a125519e22a7c18460eed59)
This commit is contained in:
parent
26f5e9b83c
commit
289f0cf00b
@ -26,9 +26,10 @@ import androidx.media3.common.util.Util;
|
|||||||
import androidx.media3.extractor.metadata.MetadataInputBuffer;
|
import androidx.media3.extractor.metadata.MetadataInputBuffer;
|
||||||
import androidx.media3.extractor.metadata.SimpleMetadataDecoder;
|
import androidx.media3.extractor.metadata.SimpleMetadataDecoder;
|
||||||
import com.google.common.base.Ascii;
|
import com.google.common.base.Ascii;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -436,30 +437,25 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
+ frameSize);
|
+ frameSize);
|
||||||
}
|
}
|
||||||
return frame;
|
return frame;
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
Log.w(TAG, "Unsupported character encoding");
|
|
||||||
return null;
|
|
||||||
} finally {
|
} finally {
|
||||||
id3Data.setPosition(nextFramePosition);
|
id3Data.setPosition(nextFramePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static TextInformationFrame decodeTxxxFrame(ParsableByteArray id3Data, int frameSize)
|
private static TextInformationFrame decodeTxxxFrame(ParsableByteArray id3Data, int frameSize) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
if (frameSize < 1) {
|
if (frameSize < 1) {
|
||||||
// Frame is malformed.
|
// Frame is malformed.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int encoding = id3Data.readUnsignedByte();
|
int encoding = id3Data.readUnsignedByte();
|
||||||
String charset = getCharsetName(encoding);
|
|
||||||
|
|
||||||
byte[] data = new byte[frameSize - 1];
|
byte[] data = new byte[frameSize - 1];
|
||||||
id3Data.readBytes(data, 0, frameSize - 1);
|
id3Data.readBytes(data, 0, frameSize - 1);
|
||||||
|
|
||||||
int descriptionEndIndex = indexOfTerminator(data, 0, encoding);
|
int descriptionEndIndex = indexOfTerminator(data, 0, encoding);
|
||||||
String description = new String(data, 0, descriptionEndIndex, charset);
|
String description = new String(data, 0, descriptionEndIndex, getCharset(encoding));
|
||||||
|
|
||||||
ImmutableList<String> values =
|
ImmutableList<String> values =
|
||||||
decodeTextInformationFrameValues(
|
decodeTextInformationFrameValues(
|
||||||
@ -469,7 +465,7 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static TextInformationFrame decodeTextInformationFrame(
|
private static TextInformationFrame decodeTextInformationFrame(
|
||||||
ParsableByteArray id3Data, int frameSize, String id) throws UnsupportedEncodingException {
|
ParsableByteArray id3Data, int frameSize, String id) {
|
||||||
if (frameSize < 1) {
|
if (frameSize < 1) {
|
||||||
// Frame is malformed.
|
// Frame is malformed.
|
||||||
return null;
|
return null;
|
||||||
@ -485,17 +481,17 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ImmutableList<String> decodeTextInformationFrameValues(
|
private static ImmutableList<String> decodeTextInformationFrameValues(
|
||||||
byte[] data, final int encoding, final int index) throws UnsupportedEncodingException {
|
byte[] data, final int encoding, final int index) {
|
||||||
if (index >= data.length) {
|
if (index >= data.length) {
|
||||||
return ImmutableList.of("");
|
return ImmutableList.of("");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmutableList.Builder<String> values = ImmutableList.builder();
|
ImmutableList.Builder<String> values = ImmutableList.builder();
|
||||||
String charset = getCharsetName(encoding);
|
|
||||||
int valueStartIndex = index;
|
int valueStartIndex = index;
|
||||||
int valueEndIndex = indexOfTerminator(data, valueStartIndex, encoding);
|
int valueEndIndex = indexOfTerminator(data, valueStartIndex, encoding);
|
||||||
while (valueStartIndex < valueEndIndex) {
|
while (valueStartIndex < valueEndIndex) {
|
||||||
String value = new String(data, valueStartIndex, valueEndIndex - valueStartIndex, charset);
|
String value =
|
||||||
|
new String(data, valueStartIndex, valueEndIndex - valueStartIndex, getCharset(encoding));
|
||||||
values.add(value);
|
values.add(value);
|
||||||
|
|
||||||
valueStartIndex = valueEndIndex + delimiterLength(encoding);
|
valueStartIndex = valueEndIndex + delimiterLength(encoding);
|
||||||
@ -507,47 +503,44 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frameSize)
|
private static UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frameSize) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
if (frameSize < 1) {
|
if (frameSize < 1) {
|
||||||
// Frame is malformed.
|
// Frame is malformed.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int encoding = id3Data.readUnsignedByte();
|
int encoding = id3Data.readUnsignedByte();
|
||||||
String charset = getCharsetName(encoding);
|
|
||||||
|
|
||||||
byte[] data = new byte[frameSize - 1];
|
byte[] data = new byte[frameSize - 1];
|
||||||
id3Data.readBytes(data, 0, frameSize - 1);
|
id3Data.readBytes(data, 0, frameSize - 1);
|
||||||
|
|
||||||
int descriptionEndIndex = indexOfTerminator(data, 0, encoding);
|
int descriptionEndIndex = indexOfTerminator(data, 0, encoding);
|
||||||
String description = new String(data, 0, descriptionEndIndex, charset);
|
String description = new String(data, 0, descriptionEndIndex, getCharset(encoding));
|
||||||
|
|
||||||
int urlStartIndex = descriptionEndIndex + delimiterLength(encoding);
|
int urlStartIndex = descriptionEndIndex + delimiterLength(encoding);
|
||||||
int urlEndIndex = indexOfZeroByte(data, urlStartIndex);
|
int urlEndIndex = indexOfZeroByte(data, urlStartIndex);
|
||||||
String url = decodeStringIfValid(data, urlStartIndex, urlEndIndex, "ISO-8859-1");
|
String url = decodeStringIfValid(data, urlStartIndex, urlEndIndex, Charsets.ISO_8859_1);
|
||||||
|
|
||||||
return new UrlLinkFrame("WXXX", description, url);
|
return new UrlLinkFrame("WXXX", description, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UrlLinkFrame decodeUrlLinkFrame(
|
private static UrlLinkFrame decodeUrlLinkFrame(
|
||||||
ParsableByteArray id3Data, int frameSize, String id) throws UnsupportedEncodingException {
|
ParsableByteArray id3Data, int frameSize, String id) {
|
||||||
byte[] data = new byte[frameSize];
|
byte[] data = new byte[frameSize];
|
||||||
id3Data.readBytes(data, 0, frameSize);
|
id3Data.readBytes(data, 0, frameSize);
|
||||||
|
|
||||||
int urlEndIndex = indexOfZeroByte(data, 0);
|
int urlEndIndex = indexOfZeroByte(data, 0);
|
||||||
String url = new String(data, 0, urlEndIndex, "ISO-8859-1");
|
String url = new String(data, 0, urlEndIndex, Charsets.ISO_8859_1);
|
||||||
|
|
||||||
return new UrlLinkFrame(id, null, url);
|
return new UrlLinkFrame(id, null, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PrivFrame decodePrivFrame(ParsableByteArray id3Data, int frameSize)
|
private static PrivFrame decodePrivFrame(ParsableByteArray id3Data, int frameSize) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
byte[] data = new byte[frameSize];
|
byte[] data = new byte[frameSize];
|
||||||
id3Data.readBytes(data, 0, frameSize);
|
id3Data.readBytes(data, 0, frameSize);
|
||||||
|
|
||||||
int ownerEndIndex = indexOfZeroByte(data, 0);
|
int ownerEndIndex = indexOfZeroByte(data, 0);
|
||||||
String owner = new String(data, 0, ownerEndIndex, "ISO-8859-1");
|
String owner = new String(data, 0, ownerEndIndex, Charsets.ISO_8859_1);
|
||||||
|
|
||||||
int privateDataStartIndex = ownerEndIndex + 1;
|
int privateDataStartIndex = ownerEndIndex + 1;
|
||||||
byte[] privateData = copyOfRangeIfValid(data, privateDataStartIndex, data.length);
|
byte[] privateData = copyOfRangeIfValid(data, privateDataStartIndex, data.length);
|
||||||
@ -555,16 +548,15 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
return new PrivFrame(owner, privateData);
|
return new PrivFrame(owner, privateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GeobFrame decodeGeobFrame(ParsableByteArray id3Data, int frameSize)
|
private static GeobFrame decodeGeobFrame(ParsableByteArray id3Data, int frameSize) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
int encoding = id3Data.readUnsignedByte();
|
int encoding = id3Data.readUnsignedByte();
|
||||||
String charset = getCharsetName(encoding);
|
Charset charset = getCharset(encoding);
|
||||||
|
|
||||||
byte[] data = new byte[frameSize - 1];
|
byte[] data = new byte[frameSize - 1];
|
||||||
id3Data.readBytes(data, 0, frameSize - 1);
|
id3Data.readBytes(data, 0, frameSize - 1);
|
||||||
|
|
||||||
int mimeTypeEndIndex = indexOfZeroByte(data, 0);
|
int mimeTypeEndIndex = indexOfZeroByte(data, 0);
|
||||||
String mimeType = new String(data, 0, mimeTypeEndIndex, "ISO-8859-1");
|
String mimeType = new String(data, 0, mimeTypeEndIndex, Charsets.ISO_8859_1);
|
||||||
|
|
||||||
int filenameStartIndex = mimeTypeEndIndex + 1;
|
int filenameStartIndex = mimeTypeEndIndex + 1;
|
||||||
int filenameEndIndex = indexOfTerminator(data, filenameStartIndex, encoding);
|
int filenameEndIndex = indexOfTerminator(data, filenameStartIndex, encoding);
|
||||||
@ -582,10 +574,9 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ApicFrame decodeApicFrame(
|
private static ApicFrame decodeApicFrame(
|
||||||
ParsableByteArray id3Data, int frameSize, int majorVersion)
|
ParsableByteArray id3Data, int frameSize, int majorVersion) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
int encoding = id3Data.readUnsignedByte();
|
int encoding = id3Data.readUnsignedByte();
|
||||||
String charset = getCharsetName(encoding);
|
Charset charset = getCharset(encoding);
|
||||||
|
|
||||||
byte[] data = new byte[frameSize - 1];
|
byte[] data = new byte[frameSize - 1];
|
||||||
id3Data.readBytes(data, 0, frameSize - 1);
|
id3Data.readBytes(data, 0, frameSize - 1);
|
||||||
@ -594,13 +585,13 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
int mimeTypeEndIndex;
|
int mimeTypeEndIndex;
|
||||||
if (majorVersion == 2) {
|
if (majorVersion == 2) {
|
||||||
mimeTypeEndIndex = 2;
|
mimeTypeEndIndex = 2;
|
||||||
mimeType = "image/" + Ascii.toLowerCase(new String(data, 0, 3, "ISO-8859-1"));
|
mimeType = "image/" + Ascii.toLowerCase(new String(data, 0, 3, Charsets.ISO_8859_1));
|
||||||
if ("image/jpg".equals(mimeType)) {
|
if ("image/jpg".equals(mimeType)) {
|
||||||
mimeType = "image/jpeg";
|
mimeType = "image/jpeg";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mimeTypeEndIndex = indexOfZeroByte(data, 0);
|
mimeTypeEndIndex = indexOfZeroByte(data, 0);
|
||||||
mimeType = Ascii.toLowerCase(new String(data, 0, mimeTypeEndIndex, "ISO-8859-1"));
|
mimeType = Ascii.toLowerCase(new String(data, 0, mimeTypeEndIndex, Charsets.ISO_8859_1));
|
||||||
if (mimeType.indexOf('/') == -1) {
|
if (mimeType.indexOf('/') == -1) {
|
||||||
mimeType = "image/" + mimeType;
|
mimeType = "image/" + mimeType;
|
||||||
}
|
}
|
||||||
@ -621,15 +612,14 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static CommentFrame decodeCommentFrame(ParsableByteArray id3Data, int frameSize)
|
private static CommentFrame decodeCommentFrame(ParsableByteArray id3Data, int frameSize) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
if (frameSize < 4) {
|
if (frameSize < 4) {
|
||||||
// Frame is malformed.
|
// Frame is malformed.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int encoding = id3Data.readUnsignedByte();
|
int encoding = id3Data.readUnsignedByte();
|
||||||
String charset = getCharsetName(encoding);
|
Charset charset = getCharset(encoding);
|
||||||
|
|
||||||
byte[] data = new byte[3];
|
byte[] data = new byte[3];
|
||||||
id3Data.readBytes(data, 0, 3);
|
id3Data.readBytes(data, 0, 3);
|
||||||
@ -654,13 +644,15 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
int majorVersion,
|
int majorVersion,
|
||||||
boolean unsignedIntFrameSizeHack,
|
boolean unsignedIntFrameSizeHack,
|
||||||
int frameHeaderSize,
|
int frameHeaderSize,
|
||||||
@Nullable FramePredicate framePredicate)
|
@Nullable FramePredicate framePredicate) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
int framePosition = id3Data.getPosition();
|
int framePosition = id3Data.getPosition();
|
||||||
int chapterIdEndIndex = indexOfZeroByte(id3Data.getData(), framePosition);
|
int chapterIdEndIndex = indexOfZeroByte(id3Data.getData(), framePosition);
|
||||||
String chapterId =
|
String chapterId =
|
||||||
new String(
|
new String(
|
||||||
id3Data.getData(), framePosition, chapterIdEndIndex - framePosition, "ISO-8859-1");
|
id3Data.getData(),
|
||||||
|
framePosition,
|
||||||
|
chapterIdEndIndex - framePosition,
|
||||||
|
Charsets.ISO_8859_1);
|
||||||
id3Data.setPosition(chapterIdEndIndex + 1);
|
id3Data.setPosition(chapterIdEndIndex + 1);
|
||||||
|
|
||||||
int startTime = id3Data.readInt();
|
int startTime = id3Data.readInt();
|
||||||
@ -695,13 +687,15 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
int majorVersion,
|
int majorVersion,
|
||||||
boolean unsignedIntFrameSizeHack,
|
boolean unsignedIntFrameSizeHack,
|
||||||
int frameHeaderSize,
|
int frameHeaderSize,
|
||||||
@Nullable FramePredicate framePredicate)
|
@Nullable FramePredicate framePredicate) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
int framePosition = id3Data.getPosition();
|
int framePosition = id3Data.getPosition();
|
||||||
int elementIdEndIndex = indexOfZeroByte(id3Data.getData(), framePosition);
|
int elementIdEndIndex = indexOfZeroByte(id3Data.getData(), framePosition);
|
||||||
String elementId =
|
String elementId =
|
||||||
new String(
|
new String(
|
||||||
id3Data.getData(), framePosition, elementIdEndIndex - framePosition, "ISO-8859-1");
|
id3Data.getData(),
|
||||||
|
framePosition,
|
||||||
|
elementIdEndIndex - framePosition,
|
||||||
|
Charsets.ISO_8859_1);
|
||||||
id3Data.setPosition(elementIdEndIndex + 1);
|
id3Data.setPosition(elementIdEndIndex + 1);
|
||||||
|
|
||||||
int ctocFlags = id3Data.readUnsignedByte();
|
int ctocFlags = id3Data.readUnsignedByte();
|
||||||
@ -713,7 +707,8 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
int startIndex = id3Data.getPosition();
|
int startIndex = id3Data.getPosition();
|
||||||
int endIndex = indexOfZeroByte(id3Data.getData(), startIndex);
|
int endIndex = indexOfZeroByte(id3Data.getData(), startIndex);
|
||||||
children[i] = new String(id3Data.getData(), startIndex, endIndex - startIndex, "ISO-8859-1");
|
children[i] =
|
||||||
|
new String(id3Data.getData(), startIndex, endIndex - startIndex, Charsets.ISO_8859_1);
|
||||||
id3Data.setPosition(endIndex + 1);
|
id3Data.setPosition(endIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -792,23 +787,18 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Maps encoding byte from ID3v2 frame to a {@link Charset}. */
|
||||||
* Maps encoding byte from ID3v2 frame to a Charset.
|
private static Charset getCharset(int encodingByte) {
|
||||||
*
|
|
||||||
* @param encodingByte The value of encoding byte from ID3v2 frame.
|
|
||||||
* @return Charset name.
|
|
||||||
*/
|
|
||||||
private static String getCharsetName(int encodingByte) {
|
|
||||||
switch (encodingByte) {
|
switch (encodingByte) {
|
||||||
case ID3_TEXT_ENCODING_UTF_16:
|
case ID3_TEXT_ENCODING_UTF_16:
|
||||||
return "UTF-16";
|
return Charsets.UTF_16;
|
||||||
case ID3_TEXT_ENCODING_UTF_16BE:
|
case ID3_TEXT_ENCODING_UTF_16BE:
|
||||||
return "UTF-16BE";
|
return Charsets.UTF_16BE;
|
||||||
case ID3_TEXT_ENCODING_UTF_8:
|
case ID3_TEXT_ENCODING_UTF_8:
|
||||||
return "UTF-8";
|
return Charsets.UTF_8;
|
||||||
case ID3_TEXT_ENCODING_ISO_8859_1:
|
case ID3_TEXT_ENCODING_ISO_8859_1:
|
||||||
default:
|
default:
|
||||||
return "ISO-8859-1";
|
return Charsets.ISO_8859_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,21 +861,19 @@ public final class Id3Decoder extends SimpleMetadataDecoder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string obtained by decoding the specified range of {@code data} using the specified
|
* Returns a string obtained by decoding the specified range of {@code data} using the specified
|
||||||
* {@code charsetName}. An empty string is returned if the range is invalid.
|
* {@code charset}. An empty string is returned if the range is invalid.
|
||||||
*
|
*
|
||||||
* @param data The array from which to decode the string.
|
* @param data The array from which to decode the string.
|
||||||
* @param from The start of the range.
|
* @param from The start of the range.
|
||||||
* @param to The end of the range (exclusive).
|
* @param to The end of the range (exclusive).
|
||||||
* @param charsetName The name of the Charset to use.
|
* @param charset The {@link Charset} to use.
|
||||||
* @return The decoded string, or an empty string if the range is invalid.
|
* @return The decoded string, or an empty string if the range is invalid.
|
||||||
* @throws UnsupportedEncodingException If the Charset is not supported.
|
|
||||||
*/
|
*/
|
||||||
private static String decodeStringIfValid(byte[] data, int from, int to, String charsetName)
|
private static String decodeStringIfValid(byte[] data, int from, int to, Charset charset) {
|
||||||
throws UnsupportedEncodingException {
|
|
||||||
if (to <= from || to > data.length) {
|
if (to <= from || to > data.length) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return new String(data, from, to - from, charsetName);
|
return new String(data, from, to - from, charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Id3Header {
|
private static final class Id3Header {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user