From 165f4f2fd4008d247f98b42ae7f18a0c80f544db Mon Sep 17 00:00:00 2001 From: michaelkatz Date: Thu, 13 Apr 2023 16:06:09 +0100 Subject: [PATCH] Use default profile-level-id if absent in Describe SDP for MPEG4-LATM PiperOrigin-RevId: 524003092 --- RELEASENOTES.md | 3 ++ .../media3/exoplayer/rtsp/RtspMediaTrack.java | 13 +++++-- .../exoplayer/rtsp/RtspMediaTrackTest.java | 37 ++++++++++++++++++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 631cf4cdde..21bfce104b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -98,6 +98,9 @@ * Retry with TCP if RTSP Setup with UDP fails with RTSP Error 461 UnsupportedTransport ([#11069](https://github.com/google/ExoPlayer/issues/11069)). + * For MPEG4-LATM, use default profile-level-id value if absent in Describe + Response SDP message + ([#302](https://github.com/androidx/media/issues/302)). * IMA DAI extension: * Fix a bug where a new ad group is inserted in live streams because the calculated content position in consecutive timelines varies slightly. diff --git a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaTrack.java b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaTrack.java index 60fbb483d3..d14439cc01 100644 --- a/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaTrack.java +++ b/libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaTrack.java @@ -229,7 +229,8 @@ import com.google.common.collect.ImmutableMap; .setChannelCount(aacConfig.channelCount) .setCodecs(aacConfig.codecs); } - processAacFmtpAttribute(formatBuilder, fmtpParameters, channelCount, clockRate); + processAacFmtpAttribute( + formatBuilder, fmtpParameters, mediaEncoding, channelCount, clockRate); break; case MimeTypes.AUDIO_AMR_NB: case MimeTypes.AUDIO_AMR_WB: @@ -311,11 +312,17 @@ import com.google.common.collect.ImmutableMap; private static void processAacFmtpAttribute( Format.Builder formatBuilder, ImmutableMap fmtpAttributes, + String mediaEncoding, int channelCount, int sampleRate) { + @Nullable String profileLevel = fmtpAttributes.get(PARAMETER_PROFILE_LEVEL_ID); + if (profileLevel == null && mediaEncoding.equals(RtpPayloadFormat.RTP_MEDIA_MPEG4_LATM_AUDIO)) { + // As defined in RFC3016 Section 5.3 for MPEG4-LATM, if profile-level-id is not specified, + // then a default value of 30 should be used. + profileLevel = "30"; + } checkArgument( - fmtpAttributes.containsKey(PARAMETER_PROFILE_LEVEL_ID), "missing profile-level-id param"); - String profileLevel = checkNotNull(fmtpAttributes.get(PARAMETER_PROFILE_LEVEL_ID)); + profileLevel != null && !profileLevel.isEmpty(), "missing profile-level-id param"); formatBuilder.setCodecs(AAC_CODECS_PREFIX + profileLevel); formatBuilder.setInitializationData( ImmutableList.of( diff --git a/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspMediaTrackTest.java b/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspMediaTrackTest.java index bfd2308c42..5f0eeb627e 100644 --- a/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspMediaTrackTest.java +++ b/libraries/exoplayer_rtsp/src/test/java/androidx/media3/exoplayer/rtsp/RtspMediaTrackTest.java @@ -402,6 +402,22 @@ public class RtspMediaTrackTest { assertThat(rtpPayloadFormat.format.codecs).isEqualTo("avc1.64001F"); } + @Test + public void + generatePayloadFormat_withMpeg4LatmMediaDescriptionMissingProfileLevel_generatesCorrectProfileLevel() { + MediaDescription mediaDescription = + new MediaDescription.Builder( + MEDIA_TYPE_AUDIO, /* port= */ 0, RTP_AVP_PROFILE, /* payloadType= */ 96) + .setConnection("IN IP4 0.0.0.0") + .setBitrate(96_000) + .addAttribute(ATTR_RTPMAP, "96 MP4A-LATM/44100") + .addAttribute(ATTR_FMTP, "96 config=40002410adca00; cpresent=0") + .addAttribute(ATTR_CONTROL, "track1") + .build(); + RtpPayloadFormat rtpPayloadFormat = RtspMediaTrack.generatePayloadFormat(mediaDescription); + assertThat(rtpPayloadFormat.format.codecs).isEqualTo("mp4a.40.30"); + } + @Test public void generatePayloadFormat_withAacMediaDescriptionMissingFmtpAttribute_throwsIllegalArgumentException() { @@ -420,7 +436,7 @@ public class RtspMediaTrackTest { @Test public void - generatePayloadFormat_withMediaDescriptionMissingProfileLevel_throwsIllegalArgumentException() { + generatePayloadFormat_withMpeg4GenericMediaDescriptionMissingProfileLevel_throwsIllegalArgumentException() { MediaDescription mediaDescription = new MediaDescription.Builder( MEDIA_TYPE_AUDIO, /* port= */ 0, RTP_AVP_PROFILE, /* payloadType= */ 97) @@ -437,6 +453,25 @@ public class RtspMediaTrackTest { () -> RtspMediaTrack.generatePayloadFormat(mediaDescription)); } + @Test + public void + generatePayloadFormat_withMpeg4GenericMediaDescriptionEmptyProfileLevel_throwsIllegalArgumentException() { + MediaDescription mediaDescription = + new MediaDescription.Builder( + MEDIA_TYPE_AUDIO, /* port= */ 0, RTP_AVP_PROFILE, /* payloadType= */ 97) + .setConnection("IN IP4 0.0.0.0") + .setBitrate(96_000) + .addAttribute(ATTR_RTPMAP, "97 MPEG4-GENERIC/44100") + .addAttribute( + ATTR_FMTP, + "97 streamtype=5;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1208;profile-level-id=;") + .addAttribute(ATTR_CONTROL, "track1") + .build(); + assertThrows( + IllegalArgumentException.class, + () -> RtspMediaTrack.generatePayloadFormat(mediaDescription)); + } + @Test public void generatePayloadFormat_withH264MediaDescriptionMissingFmtpAttribute_throwsIllegalArgumentException() {