Skip to content

Commit 65a198d

Browse files
committed
Refactor based on code conventio ns
1 parent 2ecf8b3 commit 65a198d

File tree

2 files changed

+75
-43
lines changed

2 files changed

+75
-43
lines changed

RELEASENOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
* Smooth Streaming extension:
3939
* RTSP extension:
4040
* Decoder extensions (FFmpeg, VP9, AV1, etc.):
41+
* FFmpeg extension: Fix an issue that prevented some FLAC files from
42+
playing by ensuring the `STREAMINFO` block is correctly parsed and
43+
passed to the decoder
44+
([#2887](https://github.com/androidx/media/issues/2887)).
4145
* MIDI extension:
4246
* Leanback extension:
4347
* Cast extension:

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

Lines changed: 71 additions & 43 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;
@@ -198,49 +204,6 @@ private static byte[] getExtraData(String mimeType, List<byte[]> initializationD
198204
}
199205
}
200206

201-
@Nullable
202-
private static byte[] getFlacExtraData(List<byte[]> initializationData) {
203-
for (int i = 0; i < initializationData.size(); i++) {
204-
byte[] out = extractFlacStreamInfo(initializationData.get(i));
205-
if (out != null) {
206-
return out;
207-
}
208-
}
209-
return null;
210-
}
211-
212-
@Nullable
213-
private static byte[] extractFlacStreamInfo(byte[] data) {
214-
final int STREAMINFO_LEN = 34;
215-
int off = 0;
216-
217-
if (data.length >= 4
218-
&& data[0] == (byte) 'f'
219-
&& data[1] == (byte) 'L'
220-
&& data[2] == (byte) 'a'
221-
&& data[3] == (byte) 'C') {
222-
off = 4;
223-
}
224-
225-
if (data.length - off == STREAMINFO_LEN) {
226-
byte[] out = new byte[STREAMINFO_LEN];
227-
System.arraycopy(data, off, out, 0, STREAMINFO_LEN);
228-
return out;
229-
}
230-
231-
if (data.length >= off + 4) {
232-
int type = data[off] & 0x7F;
233-
int len = ((data[off + 1] & 0xFF) << 16) | ((data[off + 2] & 0xFF) << 8) | (data[off + 3] & 0xFF);
234-
if (type == 0 && len == STREAMINFO_LEN && data.length >= off + 4 + STREAMINFO_LEN) {
235-
byte[] out = new byte[STREAMINFO_LEN];
236-
System.arraycopy(data, off + 4, out, 0, STREAMINFO_LEN);
237-
return out;
238-
}
239-
}
240-
241-
return null;
242-
}
243-
244207
private static byte[] getAlacExtraData(List<byte[]> initializationData) {
245208
// FFmpeg's ALAC decoder expects an ALAC atom, which contains the ALAC "magic cookie", as extra
246209
// data. initializationData[0] contains only the magic cookie, and so we need to package it into
@@ -272,6 +235,71 @@ private static byte[] getVorbisExtraData(List<byte[]> initializationData) {
272235
return extraData;
273236
}
274237

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+
257+
if (data.length - offset == FLAC_STREAM_INFO_DATA_SIZE) {
258+
byte[] streamInfo = new byte[FLAC_STREAM_INFO_DATA_SIZE];
259+
System.arraycopy(data, offset, streamInfo, 0, FLAC_STREAM_INFO_DATA_SIZE);
260+
return streamInfo;
261+
}
262+
263+
if (data.length >= offset + FLAC_METADATA_BLOCK_HEADER_SIZE) {
264+
int type = data[offset] & 0x7F;
265+
int length =
266+
((data[offset + 1] & 0xFF) << 16)
267+
| ((data[offset + 2] & 0xFF) << 8)
268+
| (data[offset + 3] & 0xFF);
269+
270+
if (type == FLAC_METADATA_TYPE_STREAM_INFO
271+
&& length == FLAC_STREAM_INFO_DATA_SIZE
272+
&& data.length
273+
>= offset
274+
+ FLAC_METADATA_BLOCK_HEADER_SIZE
275+
+ FLAC_STREAM_INFO_DATA_SIZE) {
276+
byte[] streamInfo = new byte[FLAC_STREAM_INFO_DATA_SIZE];
277+
System.arraycopy(
278+
data,
279+
offset + FLAC_METADATA_BLOCK_HEADER_SIZE,
280+
streamInfo,
281+
0,
282+
FLAC_STREAM_INFO_DATA_SIZE);
283+
return streamInfo;
284+
}
285+
}
286+
287+
return null;
288+
}
289+
290+
private static boolean arrayStartsWith(byte[] data, byte[] prefix) {
291+
if (data.length < prefix.length) {
292+
return false;
293+
}
294+
for (int i = 0; i < prefix.length; i++) {
295+
if (data[i] != prefix[i]) {
296+
return false;
297+
}
298+
}
299+
return true;
300+
}
301+
302+
275303
private native long ffmpegInitialize(
276304
String codecName,
277305
@Nullable byte[] extraData,

0 commit comments

Comments
 (0)