Skip to content

Commit 580f994

Browse files
Merge pull request #1346 from DolbyLaboratories:dlb/ddp-gapless
PiperOrigin-RevId: 794961682
2 parents da6de51 + 9b1f1b1 commit 580f994

File tree

3 files changed

+154
-3
lines changed

3 files changed

+154
-3
lines changed

RELEASENOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
* Avoid potential delays caused by handling routing change callbacks at
8383
the beginning of playback
8484
([#2646]()https://github.com/androidx/media/issues/2646).
85+
* Allow codec reuse for EAC3, EAC3-JOC and AC-4 formats
86+
([#1346](https://github.com/androidx/media/pull/1346)).
8587
* Video:
8688
* Text:
8789
* Metadata:

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,9 +498,9 @@ public DecoderReuseEvaluation canReuseCodec(Format oldFormat, Format newFormat)
498498
discardReasons |= DISCARD_REASON_AUDIO_ENCODING_CHANGED;
499499
}
500500

501-
// Check whether we're adapting between two xHE-AAC formats, for which adaptation is possible
502-
// without reconfiguration or flushing.
503-
if (discardReasons == 0 && MimeTypes.AUDIO_AAC.equals(mimeType)) {
501+
// Some audio formats allow adaptation without reconfiguration or flushing.
502+
if (discardReasons == 0
503+
&& (mimeType.equals(MimeTypes.AUDIO_AAC) || mimeType.equals(MimeTypes.AUDIO_AC4))) {
504504
@Nullable
505505
Pair<Integer, Integer> oldCodecProfileLevel =
506506
MediaCodecUtil.getCodecProfileAndLevel(oldFormat);
@@ -510,6 +510,8 @@ public DecoderReuseEvaluation canReuseCodec(Format oldFormat, Format newFormat)
510510
if (oldCodecProfileLevel != null && newCodecProfileLevel != null) {
511511
int oldProfile = oldCodecProfileLevel.first;
512512
int newProfile = newCodecProfileLevel.first;
513+
// Check whether we're adapting between two xHE-AAC formats, for which adaptation is
514+
// possible without reconfiguration or flushing.
513515
if (oldProfile == CodecProfileLevel.AACObjectXHE
514516
&& newProfile == CodecProfileLevel.AACObjectXHE) {
515517
return new DecoderReuseEvaluation(
@@ -519,9 +521,32 @@ public DecoderReuseEvaluation canReuseCodec(Format oldFormat, Format newFormat)
519521
REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
520522
/* discardReasons= */ 0);
521523
}
524+
// For ac4 with the same profile and level, adaptation is possible without reconfiguration
525+
// or flushing.
526+
if (mimeType.equals(MimeTypes.AUDIO_AC4)
527+
&& oldCodecProfileLevel.equals(newCodecProfileLevel)) {
528+
return new DecoderReuseEvaluation(
529+
name,
530+
oldFormat,
531+
newFormat,
532+
REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
533+
/* discardReasons= */ 0);
534+
}
522535
}
523536
}
524537

538+
// For eac3 and eac3-joc, adaptation is possible without reconfiguration or flushing.
539+
if (discardReasons == 0
540+
&& (mimeType.equals(MimeTypes.AUDIO_E_AC3_JOC)
541+
|| mimeType.equals(MimeTypes.AUDIO_E_AC3))) {
542+
return new DecoderReuseEvaluation(
543+
name,
544+
oldFormat,
545+
newFormat,
546+
REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
547+
/* discardReasons= */ 0);
548+
}
549+
525550
if (!oldFormat.initializationDataEquals(newFormat)) {
526551
discardReasons |= DISCARD_REASON_INITIALIZATION_DATA_CHANGED;
527552
}

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

Lines changed: 124 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,31 @@ 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+
.setCodecs("ac-4.02.01.01")
100+
.setChannelCount(21)
101+
.setSampleRate(48000)
102+
.setAverageBitrate(5000)
103+
.build();
104+
77105
@Test
78106
public void canReuseCodec_withDifferentMimeType_returnsNo() {
79107
MediaCodecInfo codecInfo = buildH264CodecInfo(/* adaptive= */ true);
@@ -318,6 +346,87 @@ public void canReuseCodec_differentVideoCrop_returnsNo() {
318346
DISCARD_REASON_WORKAROUND));
319347
}
320348

349+
@Test
350+
public void canReuseCodec_eac3_returnsYesWithoutReconfiguration() {
351+
MediaCodecInfo codecInfo =
352+
new MediaCodecInfo(
353+
"eac3joc",
354+
AUDIO_E_AC3,
355+
AUDIO_E_AC3,
356+
/* capabilities= */ null,
357+
/* hardwareAccelerated= */ false,
358+
/* softwareOnly= */ true,
359+
/* vendor= */ true,
360+
/* adaptive= */ false,
361+
/* tunneling= */ false,
362+
/* secure= */ false,
363+
/* detachedSurfaceSupported= */ false);
364+
365+
assertThat(codecInfo.canReuseCodec(FORMAT_EAC3, FORMAT_EAC3))
366+
.isEqualTo(
367+
new DecoderReuseEvaluation(
368+
codecInfo.name,
369+
FORMAT_EAC3,
370+
FORMAT_EAC3,
371+
DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
372+
/* discardReasons= */ 0));
373+
}
374+
375+
@Test
376+
public void canReuseCodec_eac3joc_returnsYesWithoutReconfiguration() {
377+
MediaCodecInfo codecInfo =
378+
new MediaCodecInfo(
379+
"eac3joc",
380+
AUDIO_E_AC3_JOC,
381+
AUDIO_E_AC3_JOC,
382+
/* capabilities= */ null,
383+
/* hardwareAccelerated= */ false,
384+
/* softwareOnly= */ true,
385+
/* vendor= */ true,
386+
/* adaptive= */ false,
387+
/* tunneling= */ false,
388+
/* secure= */ false,
389+
/* detachedSurfaceSupported= */ false);
390+
391+
assertThat(codecInfo.canReuseCodec(FORMAT_EAC3JOC, FORMAT_EAC3JOC))
392+
.isEqualTo(
393+
new DecoderReuseEvaluation(
394+
codecInfo.name,
395+
FORMAT_EAC3JOC,
396+
FORMAT_EAC3JOC,
397+
DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
398+
/* discardReasons= */ 0));
399+
}
400+
401+
@Test
402+
public void canReuseCodec_ac4_returnsYesWithoutReconfiguration() {
403+
MediaCodecInfo codecInfo = buildAc4CodecInfo();
404+
405+
assertThat(codecInfo.canReuseCodec(FORMAT_AC4, FORMAT_AC4))
406+
.isEqualTo(
407+
new DecoderReuseEvaluation(
408+
codecInfo.name,
409+
FORMAT_AC4,
410+
FORMAT_AC4,
411+
DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION,
412+
/* discardReasons= */ 0));
413+
}
414+
415+
@Test
416+
public void canReuseCodec_ac4WithDifferentCodecs_returnsYesWithFlush() {
417+
MediaCodecInfo codecInfo = buildAc4CodecInfo();
418+
419+
Format ac4VariantFormat = FORMAT_AC4.buildUpon().setCodecs("ac-4.02.01.03").build();
420+
assertThat(codecInfo.canReuseCodec(FORMAT_AC4, ac4VariantFormat))
421+
.isEqualTo(
422+
new DecoderReuseEvaluation(
423+
codecInfo.name,
424+
FORMAT_AC4,
425+
ac4VariantFormat,
426+
REUSE_RESULT_YES_WITH_FLUSH,
427+
/* discardReasons= */ 0));
428+
}
429+
321430
private static MediaCodecInfo buildH264CodecInfo(boolean adaptive) {
322431
return new MediaCodecInfo(
323432
"h264",
@@ -348,6 +457,21 @@ private static MediaCodecInfo buildAacCodecInfo() {
348457
/* detachedSurfaceSupported= */ false);
349458
}
350459

460+
private static MediaCodecInfo buildAc4CodecInfo() {
461+
return new MediaCodecInfo(
462+
"ac4",
463+
AUDIO_AC4,
464+
AUDIO_AC4,
465+
/* capabilities= */ null,
466+
/* hardwareAccelerated= */ false,
467+
/* softwareOnly= */ true,
468+
/* vendor= */ true,
469+
/* adaptive= */ false,
470+
/* tunneling= */ false,
471+
/* secure= */ false,
472+
/* detachedSurfaceSupported= */ false);
473+
}
474+
351475
private static ColorInfo buildHdrColorInfo(@C.ColorSpace int colorSpace) {
352476
return new ColorInfo.Builder()
353477
.setColorSpace(colorSpace)

0 commit comments

Comments
 (0)