Fallback to generate profile-level-id using H264 SPS if it's missing

Related to: Issue: #9010

Profile-level-id (Format.codecs) can be generated from SPS if SDP does not
include it.

#minor-release

PiperOrigin-RevId: 377251211
This commit is contained in:
claincly 2021-06-03 11:14:08 +01:00 committed by bachinger
parent 0edb7873e0
commit 016983ca9a
2 changed files with 27 additions and 22 deletions

View File

@ -31,6 +31,7 @@ import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.audio.AacUtil; import com.google.android.exoplayer2.audio.AacUtil;
import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.NalUnitUtil; import com.google.android.exoplayer2.util.NalUnitUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
@ -171,10 +172,6 @@ import com.google.common.collect.ImmutableMap;
private static void processH264FmtpAttribute( private static void processH264FmtpAttribute(
Format.Builder formatBuilder, ImmutableMap<String, String> fmtpAttributes) { Format.Builder formatBuilder, ImmutableMap<String, String> fmtpAttributes) {
checkArgument(fmtpAttributes.containsKey(PARAMETER_PROFILE_LEVEL_ID));
String profileLevel = checkNotNull(fmtpAttributes.get(PARAMETER_PROFILE_LEVEL_ID));
formatBuilder.setCodecs(H264_CODECS_PREFIX + profileLevel);
checkArgument(fmtpAttributes.containsKey(PARAMETER_SPROP_PARAMS)); checkArgument(fmtpAttributes.containsKey(PARAMETER_SPROP_PARAMS));
String spropParameterSets = checkNotNull(fmtpAttributes.get(PARAMETER_SPROP_PARAMS)); String spropParameterSets = checkNotNull(fmtpAttributes.get(PARAMETER_SPROP_PARAMS));
String[] parameterSets = Util.split(spropParameterSets, ","); String[] parameterSets = Util.split(spropParameterSets, ",");
@ -193,6 +190,15 @@ import com.google.common.collect.ImmutableMap;
formatBuilder.setPixelWidthHeightRatio(spsData.pixelWidthAspectRatio); formatBuilder.setPixelWidthHeightRatio(spsData.pixelWidthAspectRatio);
formatBuilder.setHeight(spsData.height); formatBuilder.setHeight(spsData.height);
formatBuilder.setWidth(spsData.width); formatBuilder.setWidth(spsData.width);
@Nullable String profileLevel = fmtpAttributes.get(PARAMETER_PROFILE_LEVEL_ID);
if (profileLevel != null) {
formatBuilder.setCodecs(H264_CODECS_PREFIX + profileLevel);
} else {
formatBuilder.setCodecs(
CodecSpecificDataUtil.buildAvcCodecString(
spsData.profileIdc, spsData.constraintsFlagsAndReservedZero2Bits, spsData.levelIdc));
}
} }
private static byte[] getH264InitializationDataFromParameterSet(String parameterSet) { private static byte[] getH264InitializationDataFromParameterSet(String parameterSet) {

View File

@ -176,6 +176,23 @@ public class RtspMediaTrackTest {
assertThat(format).isEqualTo(expectedFormat); assertThat(format).isEqualTo(expectedFormat);
} }
@Test
public void
generatePayloadFormat_withH264MediaDescriptionMissingProfileLevel_generatesCorrectProfileLevel() {
MediaDescription mediaDescription =
new MediaDescription.Builder(MEDIA_TYPE_VIDEO, 0, RTP_AVP_PROFILE, 96)
.setConnection("IN IP4 0.0.0.0")
.setBitrate(500_000)
.addAttribute(ATTR_RTPMAP, "96 H264/90000")
.addAttribute(
ATTR_FMTP,
"96 packetization-mode=1;sprop-parameter-sets=Z2QAH6zZQPARabIAAAMACAAAAwGcHjBjLA==,aOvjyyLA")
.addAttribute(ATTR_CONTROL, "track1")
.build();
RtpPayloadFormat rtpPayloadFormat = RtspMediaTrack.generatePayloadFormat(mediaDescription);
assertThat(rtpPayloadFormat.format.codecs).isEqualTo("avc1.64001F");
}
@Test @Test
public void public void
generatePayloadFormat_withAacMediaDescriptionMissingFmtpAttribute_throwsIllegalArgumentException() { generatePayloadFormat_withAacMediaDescriptionMissingFmtpAttribute_throwsIllegalArgumentException() {
@ -224,24 +241,6 @@ public class RtspMediaTrackTest {
() -> RtspMediaTrack.generatePayloadFormat(mediaDescription)); () -> RtspMediaTrack.generatePayloadFormat(mediaDescription));
} }
@Test
public void
generatePayloadFormat_withH264MediaDescriptionMissingProfileLevel_throwsIllegalArgumentException() {
MediaDescription mediaDescription =
new MediaDescription.Builder(MEDIA_TYPE_VIDEO, 0, RTP_AVP_PROFILE, 96)
.setConnection("IN IP4 0.0.0.0")
.setBitrate(500_000)
.addAttribute(ATTR_RTPMAP, "96 H264/90000")
.addAttribute(
ATTR_FMTP,
"96 packetization-mode=1;sprop-parameter-sets=Z2QAH6zZQPARabIAAAMACAAAAwGcHjBjLA==,aOvjyyLA")
.addAttribute(ATTR_CONTROL, "track1")
.build();
assertThrows(
IllegalArgumentException.class,
() -> RtspMediaTrack.generatePayloadFormat(mediaDescription));
}
@Test @Test
public void public void
generatePayloadFormat_withH264MediaDescriptionMissingSpropParameter_throwsIllegalArgumentException() { generatePayloadFormat_withH264MediaDescriptionMissingSpropParameter_throwsIllegalArgumentException() {