diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5b32e1bb581..4b754f30378 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -97,6 +97,9 @@ * Fix bug where `MediaMetadata` was only populated from Vorbis comments with upper-case keys ([#876](https://github.com/androidx/media/issues/876)). + * Catch `OutOfMemoryError` when parsing very large ID3 frames, meaning + playback can continue without the tag info instead of playback failing + completely. * DRM: * Extend workaround for spurious ClearKey `https://default.url` license URL to API 33+ (previously the workaround only applied on API 33 diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/metadata/id3/Id3Decoder.java b/libraries/extractor/src/main/java/androidx/media3/extractor/metadata/id3/Id3Decoder.java index b05717e9471..2b7bf3c8230 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/metadata/id3/Id3Decoder.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/metadata/id3/Id3Decoder.java @@ -372,8 +372,9 @@ private static Id3Frame decodeFrame( frameSize = removeUnsynchronization(id3Data, frameSize); } + Id3Frame frame = null; + Throwable error = null; try { - Id3Frame frame; if (frameId0 == 'T' && frameId1 == 'X' && frameId2 == 'X' @@ -430,18 +431,21 @@ private static Id3Frame decodeFrame( String id = getFrameId(majorVersion, frameId0, frameId1, frameId2, frameId3); frame = decodeBinaryFrame(id3Data, frameSize, id); } - if (frame == null) { - Log.w( - TAG, - "Failed to decode frame: id=" - + getFrameId(majorVersion, frameId0, frameId1, frameId2, frameId3) - + ", frameSize=" - + frameSize); - } - return frame; + } catch (OutOfMemoryError | Exception e) { + error = e; } finally { id3Data.setPosition(nextFramePosition); } + if (frame == null) { + Log.w( + TAG, + "Failed to decode frame: id=" + + getFrameId(majorVersion, frameId0, frameId1, frameId2, frameId3) + + ", frameSize=" + + frameSize, + error); + } + return frame; } @Nullable