Browse Source

增加aac解析

kwl 2 weeks ago
parent
commit
d605c79c69
1 changed files with 59 additions and 1 deletions
  1. 59 1
      src/main/java/com/jttserver/codec/FlvPacketizer.java

+ 59 - 1
src/main/java/com/jttserver/codec/FlvPacketizer.java

@@ -187,7 +187,65 @@ public class FlvPacketizer {
                 codecInfo.pcmAccum = new short[1024 * codecInfo.aacChannels];
             }
 
-            // 初始化AAC编码器
+            // 如果负载类型本身就是 AAC(例如原始 AAC 帧或 ADTS),直接封装为 FLV 的 AAC 原始包
+            if (codecInfo.payloadAudio == JttConstants.PAYLOAD_TYPE_AAC
+                    || codecInfo.payloadAudio == JttConstants.PAYLOAD_TYPE_AACLC
+                    || codecInfo.payloadAudio == JttConstants.PAYLOAD_TYPE_MP4AUDIO
+                    || codecInfo.payloadAudio == JttConstants.PAYLOAD_TYPE_HEAAC) {
+
+                byte[] rawAac = audioBytes;
+                // 检测 ADTS(syncword 0xFFF)并解析 header 以获取采样率/声道以及去掉 ADTS 头
+                if (rawAac.length >= 2 && (rawAac[0] & 0xFF) == 0xFF && (rawAac[1] & 0xF0) == 0xF0) {
+                    int protectionAbsent = rawAac[1] & 0x01;
+                    int adtsHeaderLen = (protectionAbsent == 0) ? 9 : 7;
+                    if (rawAac.length >= adtsHeaderLen) {
+                        int samplingIndex = (rawAac[2] & 0x3C) >> 2;
+                        int channelConfig = ((rawAac[2] & 0x01) << 2) | ((rawAac[3] & 0xC0) >> 6);
+
+                        int[] rates = new int[] {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350};
+                        int sampleRate = 44100;
+                        if (samplingIndex >= 0 && samplingIndex < rates.length) sampleRate = rates[samplingIndex];
+
+                        codecInfo.aacSampleRate = sampleRate;
+                        codecInfo.aacChannels = Math.max(1, channelConfig);
+
+                        int payloadLen = rawAac.length - adtsHeaderLen;
+                        if (payloadLen > 0) {
+                            byte[] tmp = new byte[payloadLen];
+                            System.arraycopy(rawAac, adtsHeaderLen, tmp, 0, payloadLen);
+                            rawAac = tmp;
+                        }
+                    }
+                }
+
+                // 生成/获取 AAC 序列头(若尚未生成)
+                byte[] seq = new byte[0];
+                if (!codecInfo.aacSequenceHeaderGenerated) {
+                    seq = createAacSequenceHeader(codecInfo.aacSampleRate, codecInfo.aacChannels, timestamp);
+                    codecInfo.aacSequenceHeaderTag = seq;
+                    codecInfo.aacSequenceHeaderGenerated = true;
+                }
+
+                // 创建 AAC 原始数据的 FLV 音频 Tag (AACPacketType = 1)
+                byte[] rawTag = createAudioTag(JttConstants.AAC_SEQUENCE_DATA, rawAac, timestamp);
+
+                // 若本次刚生成序列头,则返回序列头+本帧;否则只返回本帧
+                if (seq != null && seq.length > 0) {
+                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
+                    try {
+                        bout.write(seq);
+                        bout.write(rawTag);
+                        return bout.toByteArray();
+                    } catch (IOException e) {
+                        logger.error("合并 AAC 序列头与原始帧失败", e);
+                        return new byte[0];
+                    }
+                }
+
+                return rawTag;
+            }
+
+            // 初始化AAC编码器(仅当需要把其他编码解码并编码为 AAC 时使用)
             if (codecInfo.aacHandle == 0) {
                 try {
                     codecInfo.aacHandle = AacEncoderNative.initEncoder(