Support ALL non-UTF-8 ICY metadata
- Dominant language
- Java
- Stars
- 21.9k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
### Use case description
Currently, decoding function to `String` is not implemented thoroughly. Metadata read by `IcyDecoder` supports only UTF-8 and ISO-8859-1 charsets. It should support other charsets as well. Duplicate try-catch blocks used in `decodeToString` function are not systematic (implemented as fix of issue [#6753](https://github.com/google/ExoPlayer/issues/6753)):
```
@Nullable
private String decodeToString(ByteBuffer data) {
try {
return utf8Decoder.decode(data).toString();
} catch (CharacterCodingException e) {
// Fall through to try ISO-8859-1 decoding.
} finally {
utf8Decoder.reset();
data.rewind();
}
try {
return iso88591Decoder.decode(data).toString();
} catch (CharacterCodingException e) {
return null;
} finally {
iso88591Decoder.reset();
data.rewind();
}
}
```
There should be a way to allow `IcyDecoder` to decode into other charsets.
### How to test the issue/solution
[Stream address](http://holos.fm:8000/holos ) (windows-1251 charset)
Current (wrong) output: ÁÓÐÌÀÊÀ ÌÀÐ²ß - ß Ñàìà
Correct (expected) output: БурмакаЯ Марія - Я сама
### Proposed solution - provide raw metadata out of Exoplayer through callback
Ideal solution for the programmer would be to create callback to `Exoplayer` `Listener`, that would provide raw metadata. These metadata could be decoded outside `Exoplayer` then.
```
exoPlayer.addListener(new Player.Listener() {
@Override
public void onMediaMetadataChangedRaw(ByteBuffer buffer) {
// we can decode it with correct charset here
}
});
```
### Alternative solution - Detect charset and decode accordingly
For example, [UniversalDetector](https://code.google.com/archive/p/juniversalchardet/downloads) lib detects the charset. We have tried that in decode function of `IcyDecoder`, it detects the charset properly. Similar detection (possibly without any lib) could be implemented.
```
public static String guessEncoding(byte[] bytes) {
String DEFAULT_ENCODING = "UTF-8";
UniversalDetector detector =
new org.mozilla.universalchardet.UniversalDetector(null);
detector.handleData(bytes, 0, bytes.length);
detector.dataEnd();
String encoding = detector.getDetectedCharset();
detector.reset();
if (encoding == null) {
encoding = DEFAULT_ENCODING;
}
return encoding;
}
@Override
protected Metadata decode(MetadataInputBuffer inputBuffer, ByteBuffer buffer) {
byte[] bufferArray = new byte[buffer.remaining()];
buffer.get(bufferArray);
String val = guessEncoding(bufferArray);
// in val, we have detected charset now
...
```
Contributor guide
Assessment
This issue has not been assessed yet.