Skip to content

Commit a797ad3

Browse files
committed
Do not flush eac3(joc) and ac4 decoders on reuse
eac3(joc) and ac4 decoders do not need to be flushed to be reused for the next compatible track or across adapative bitrate transitions. This change allows for gapless playback on devices with Dolby decoders that require internal re-initialization on flush.
1 parent a80f551 commit a797ad3

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfo.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,18 @@ public DecoderReuseEvaluation canReuseCodec(Format oldFormat, Format newFormat)
516516
}
517517
}
518518

519+
// For eac3, eac3-joc and ac4 formats, adaptation is possible without reconfiguration or
520+
// flushing.
521+
if (discardReasons == 0 && (MimeTypes.AUDIO_E_AC3_JOC.equals(mimeType)
522+
|| MimeTypes.AUDIO_E_AC3.equals(mimeType) || MimeTypes.AUDIO_AC4.equals(mimeType))) {
523+
return new DecoderReuseEvaluation(
524+
name,
525+
oldFormat,
526+
newFormat,
527+
REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
528+
/* discardReasons= */ 0);
529+
}
530+
519531
if (!oldFormat.initializationDataEquals(newFormat)) {
520532
discardReasons |= DISCARD_REASON_INITIALIZATION_DATA_CHANGED;
521533
}

libraries/exoplayer/src/test/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfoTest.java

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
package androidx.media3.exoplayer.mediacodec;
1717

1818
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
19+
import static androidx.media3.common.MimeTypes.AUDIO_AC4;
20+
import static androidx.media3.common.MimeTypes.AUDIO_E_AC3;
21+
import static androidx.media3.common.MimeTypes.AUDIO_E_AC3_JOC;
1922
import static androidx.media3.common.MimeTypes.VIDEO_AV1;
2023
import static androidx.media3.common.MimeTypes.VIDEO_H264;
2124
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_AUDIO_CHANNEL_COUNT_CHANGED;
@@ -74,6 +77,30 @@ public final class MediaCodecInfoTest {
7477
.setInitializationData(ImmutableList.of(new byte[] {4, 4, 1, 0, 0}))
7578
.build();
7679

80+
private static final Format FORMAT_EAC3 =
81+
new Format.Builder()
82+
.setSampleMimeType(AUDIO_E_AC3)
83+
.setChannelCount(6)
84+
.setSampleRate(48000)
85+
.setAverageBitrate(5000)
86+
.build();
87+
88+
private static final Format FORMAT_EAC3JOC =
89+
new Format.Builder()
90+
.setSampleMimeType(AUDIO_E_AC3_JOC)
91+
.setChannelCount(12)
92+
.setSampleRate(48000)
93+
.setAverageBitrate(5000)
94+
.build();
95+
96+
private static final Format FORMAT_AC4 =
97+
new Format.Builder()
98+
.setSampleMimeType(AUDIO_AC4)
99+
.setChannelCount(21)
100+
.setSampleRate(48000)
101+
.setAverageBitrate(5000)
102+
.build();
103+
77104
@Test
78105
public void canReuseCodec_withDifferentMimeType_returnsNo() {
79106
MediaCodecInfo codecInfo = buildH264CodecInfo(/* adaptive= */ true);
@@ -318,6 +345,63 @@ public void canReuseCodec_differentVideoCrop_returnsNo() {
318345
DISCARD_REASON_WORKAROUND));
319346
}
320347

348+
@Test
349+
public void canReuseCodec_eac3_returnsYesWithoutReconfiguration() {
350+
MediaCodecInfo codecInfo = buildEac3CodecInfo();
351+
352+
Format variantFormat =
353+
FORMAT_EAC3
354+
.buildUpon()
355+
.setInitializationData(ImmutableList.of(new byte[] {0}))
356+
.build();
357+
assertThat(codecInfo.canReuseCodec(FORMAT_EAC3, variantFormat))
358+
.isEqualTo(
359+
new DecoderReuseEvaluation(
360+
codecInfo.name,
361+
FORMAT_EAC3,
362+
variantFormat,
363+
DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
364+
/* discardReasons= */ 0));
365+
}
366+
367+
@Test
368+
public void canReuseCodec_eac3joc_returnsYesWithoutReconfiguration() {
369+
MediaCodecInfo codecInfo = buildEac3JocCodecInfo();
370+
371+
Format variantFormat =
372+
FORMAT_EAC3JOC
373+
.buildUpon()
374+
.setInitializationData(ImmutableList.of(new byte[] {0}))
375+
.build();
376+
assertThat(codecInfo.canReuseCodec(FORMAT_EAC3JOC, variantFormat))
377+
.isEqualTo(
378+
new DecoderReuseEvaluation(
379+
codecInfo.name,
380+
FORMAT_EAC3JOC,
381+
variantFormat,
382+
DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
383+
/* discardReasons= */ 0));
384+
}
385+
386+
@Test
387+
public void canReuseCodec_ac4_returnsYesWithoutReconfiguration() {
388+
MediaCodecInfo codecInfo = buildAc4CodecInfo();
389+
390+
Format variantFormat =
391+
FORMAT_AC4
392+
.buildUpon()
393+
.setInitializationData(ImmutableList.of(new byte[] {0}))
394+
.build();
395+
assertThat(codecInfo.canReuseCodec(FORMAT_AC4, variantFormat))
396+
.isEqualTo(
397+
new DecoderReuseEvaluation(
398+
codecInfo.name,
399+
FORMAT_AC4,
400+
variantFormat,
401+
DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
402+
/* discardReasons= */ 0));
403+
}
404+
321405
private static MediaCodecInfo buildH264CodecInfo(boolean adaptive) {
322406
return new MediaCodecInfo(
323407
"h264",
@@ -348,6 +432,51 @@ private static MediaCodecInfo buildAacCodecInfo() {
348432
/* detachedSurfaceSupported= */ false);
349433
}
350434

435+
private static MediaCodecInfo buildEac3CodecInfo() {
436+
return new MediaCodecInfo(
437+
"eac3joc",
438+
AUDIO_E_AC3,
439+
AUDIO_E_AC3,
440+
/* capabilities= */ null,
441+
/* hardwareAccelerated= */ false,
442+
/* softwareOnly= */ true,
443+
/* vendor= */ true,
444+
/* adaptive= */ false,
445+
/* tunneling= */ false,
446+
/* secure= */ false,
447+
/* detachedSurfaceSupported= */ false);
448+
}
449+
450+
private static MediaCodecInfo buildEac3JocCodecInfo() {
451+
return new MediaCodecInfo(
452+
"eac3joc",
453+
AUDIO_E_AC3_JOC,
454+
AUDIO_E_AC3_JOC,
455+
/* capabilities= */ null,
456+
/* hardwareAccelerated= */ false,
457+
/* softwareOnly= */ true,
458+
/* vendor= */ true,
459+
/* adaptive= */ false,
460+
/* tunneling= */ false,
461+
/* secure= */ false,
462+
/* detachedSurfaceSupported= */ false);
463+
}
464+
465+
private static MediaCodecInfo buildAc4CodecInfo() {
466+
return new MediaCodecInfo(
467+
"ac4",
468+
AUDIO_AC4,
469+
AUDIO_AC4,
470+
/* capabilities= */ null,
471+
/* hardwareAccelerated= */ false,
472+
/* softwareOnly= */ true,
473+
/* vendor= */ true,
474+
/* adaptive= */ false,
475+
/* tunneling= */ false,
476+
/* secure= */ false,
477+
/* detachedSurfaceSupported= */ false);
478+
}
479+
351480
private static ColorInfo buildHdrColorInfo(@C.ColorSpace int colorSpace) {
352481
return new ColorInfo.Builder()
353482
.setColorSpace(colorSpace)

0 commit comments

Comments
 (0)