Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for RTSP Mp4a-Latm #162

Closed
wants to merge 11 commits into from
Expand Up @@ -31,7 +31,9 @@
import androidx.media3.common.C;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.ParserException;
import androidx.media3.common.util.CodecSpecificDataUtil;
import androidx.media3.common.util.ParsableBitArray;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.extractor.AacUtil;
Expand Down Expand Up @@ -208,6 +210,13 @@ public int hashCode() {
case MimeTypes.AUDIO_AAC:
checkArgument(channelCount != C.INDEX_UNSET);
checkArgument(!fmtpParameters.isEmpty());
if(mediaEncoding.equals(RtpPayloadFormat.RTP_MEDIA_MPEG4_AUDIO)) {
Pair<Integer, Integer> cfgOpts = getSampleRateAndChannelCountFromAudioConfig(
rakeshnitb marked this conversation as resolved.
Show resolved Hide resolved
fmtpParameters, channelCount, clockRate);
channelCount = cfgOpts.first;
clockRate = cfgOpts.second;
formatBuilder.setSampleRate(clockRate).setChannelCount(channelCount);
}
processAacFmtpAttribute(formatBuilder, fmtpParameters, channelCount, clockRate);
break;
case MimeTypes.AUDIO_AMR_NB:
Expand Down Expand Up @@ -301,6 +310,38 @@ private static void processAacFmtpAttribute(
AacUtil.buildAacLcAudioSpecificConfig(sampleRate, channelCount)));
}

/**
* Parses an MPEG-4 Audio Stream Mux configuration, as defined in ISO/IEC14496-3. FMTP attribute
rakeshnitb marked this conversation as resolved.
Show resolved Hide resolved
* contains config which is a byte array containing the MPEG-4 Audio Stream Mux configuration to
* parse.
*/
private static Pair<Integer, Integer> getSampleRateAndChannelCountFromAudioConfig(
ImmutableMap<String, String> fmtpAttributes,
int channelCount,
rakeshnitb marked this conversation as resolved.
Show resolved Hide resolved
int sampleRate) {
@Nullable String configInput = fmtpAttributes.get(PARAMETER_MP4V_CONFIG);
if (configInput != null && configInput.length() % 2 == 0) {
byte[] configBuffer = Util.getBytesFromHexString(configInput);
ParsableBitArray scratchBits = new ParsableBitArray(configBuffer);
int audioMuxVersion = scratchBits.readBits(1);
if (audioMuxVersion == 0) {
checkArgument(scratchBits.readBits(1) == 1, "Invalid allStreamsSameTimeFraming.");
scratchBits.readBits(6);
checkArgument(scratchBits.readBits(4) == 0, "Invalid numProgram.");
checkArgument(scratchBits.readBits(3) == 0, "Invalid numLayer.");
AacUtil.Config aacConfig = null;
rakeshnitb marked this conversation as resolved.
Show resolved Hide resolved
try {
aacConfig = AacUtil.parseAudioSpecificConfig(scratchBits, false);
} catch (ParserException e) {
throw new IllegalArgumentException(e);
}
sampleRate = aacConfig.sampleRateHz;
channelCount = aacConfig.channelCount;
}
}
return Pair.create(channelCount, sampleRate);
}

private static void processMPEG4FmtpAttribute(
Format.Builder formatBuilder, ImmutableMap<String, String> fmtpAttributes) {
@Nullable String configInput = fmtpAttributes.get(PARAMETER_MP4V_CONFIG);
Expand Down