Skip to content

Commit e237b46

Browse files
copybara-githubmarcbaechinger
authored andcommitted
Merge pull request #2886 from Tolriq:flac_fix
PiperOrigin-RevId: 833259723 (cherry picked from commit b0c438d)
1 parent 801e082 commit e237b46

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

RELEASENOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@
5757
* Smooth Streaming extension:
5858
* RTSP extension:
5959
* Decoder extensions (FFmpeg, VP9, AV1, etc.):
60+
* FFmpeg extension: Fix an issue that prevented some FLAC files from
61+
playing by ensuring the `STREAMINFO` block is correctly parsed and
62+
passed to the decoder
63+
([#2887](https://github.com/androidx/media/issues/2887)).
6064
* MIDI extension:
6165
* Leanback extension:
6266
* Cast extension:

libraries/decoder_ffmpeg/src/main/java/androidx/media3/decoder/ffmpeg/FfmpegAudioDecoder.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
private static final int AUDIO_DECODER_ERROR_INVALID_DATA = -1;
4040
private static final int AUDIO_DECODER_ERROR_OTHER = -2;
4141

42+
// FLAC parsing constants
43+
private static final byte[] flacStreamMarker = {'f', 'L', 'a', 'C'};
44+
private static final int FLAC_METADATA_TYPE_STREAM_INFO = 0;
45+
private static final int FLAC_METADATA_BLOCK_HEADER_SIZE = 4;
46+
private static final int FLAC_STREAM_INFO_DATA_SIZE = 34;
47+
4248
private final String codecName;
4349
@Nullable private final byte[] extraData;
4450
private final @C.PcmEncoding int encoding;
@@ -190,6 +196,8 @@ private static byte[] getExtraData(String mimeType, List<byte[]> initializationD
190196
return getAlacExtraData(initializationData);
191197
case MimeTypes.AUDIO_VORBIS:
192198
return getVorbisExtraData(initializationData);
199+
case MimeTypes.AUDIO_FLAC:
200+
return getFlacExtraData(initializationData);
193201
default:
194202
// Other codecs do not require extra data.
195203
return null;
@@ -227,6 +235,66 @@ private static byte[] getVorbisExtraData(List<byte[]> initializationData) {
227235
return extraData;
228236
}
229237

238+
@Nullable
239+
private static byte[] getFlacExtraData(List<byte[]> initializationData) {
240+
for (int i = 0; i < initializationData.size(); i++) {
241+
byte[] out = extractFlacStreamInfo(initializationData.get(i));
242+
if (out != null) {
243+
return out;
244+
}
245+
}
246+
return null;
247+
}
248+
249+
@Nullable
250+
private static byte[] extractFlacStreamInfo(byte[] data) {
251+
int offset = 0;
252+
if (arrayStartsWith(data, flacStreamMarker)) {
253+
offset = flacStreamMarker.length;
254+
}
255+
256+
if (data.length - offset == FLAC_STREAM_INFO_DATA_SIZE) {
257+
byte[] streamInfo = new byte[FLAC_STREAM_INFO_DATA_SIZE];
258+
System.arraycopy(data, offset, streamInfo, 0, FLAC_STREAM_INFO_DATA_SIZE);
259+
return streamInfo;
260+
}
261+
262+
if (data.length >= offset + FLAC_METADATA_BLOCK_HEADER_SIZE) {
263+
int type = data[offset] & 0x7F;
264+
int length =
265+
((data[offset + 1] & 0xFF) << 16)
266+
| ((data[offset + 2] & 0xFF) << 8)
267+
| (data[offset + 3] & 0xFF);
268+
269+
if (type == FLAC_METADATA_TYPE_STREAM_INFO
270+
&& length == FLAC_STREAM_INFO_DATA_SIZE
271+
&& data.length >= offset + FLAC_METADATA_BLOCK_HEADER_SIZE + FLAC_STREAM_INFO_DATA_SIZE) {
272+
byte[] streamInfo = new byte[FLAC_STREAM_INFO_DATA_SIZE];
273+
System.arraycopy(
274+
data,
275+
offset + FLAC_METADATA_BLOCK_HEADER_SIZE,
276+
streamInfo,
277+
0,
278+
FLAC_STREAM_INFO_DATA_SIZE);
279+
return streamInfo;
280+
}
281+
}
282+
283+
return null;
284+
}
285+
286+
private static boolean arrayStartsWith(byte[] data, byte[] prefix) {
287+
if (data.length < prefix.length) {
288+
return false;
289+
}
290+
for (int i = 0; i < prefix.length; i++) {
291+
if (data[i] != prefix[i]) {
292+
return false;
293+
}
294+
}
295+
return true;
296+
}
297+
230298
private native long ffmpegInitialize(
231299
String codecName,
232300
@Nullable byte[] extraData,

0 commit comments

Comments
 (0)