zhuizhu 6 mesi fa
parent
commit
33c780dd2f
2 ha cambiato i file con 29 aggiunte e 155 eliminazioni
  1. 12 37
      libs/Recorder/encoder_aac.cpp
  2. 17 118
      libs/Recorder/muxer_ffmpeg.cpp

+ 12 - 37
libs/Recorder/encoder_aac.cpp

@@ -90,7 +90,9 @@ int encoder_aac::init(int nb_channels, int sample_rate, AVSampleFormat fmt, int
         
         // 对于RTMP推流,确保生成ADTS头部
         // 不设置GLOBAL_HEADER,让每个包都包含ADTS头
-        _encoder_ctx->flags &= ~AV_CODEC_FLAG_GLOBAL_HEADER;
+        // _encoder_ctx->flags &= ~AV_CODEC_FLAG_GLOBAL_HEADER;
+        // 由容器/复用层决定是否需要全局头,编码器保持默认行为(输出原始AAC帧)
+        /* no manual change to GLOBAL_HEADER here */
         
         ret = avcodec_open2(_encoder_ctx, _encoder, &options);
         av_dict_free(&options);
@@ -103,11 +105,10 @@ int encoder_aac::init(int nb_channels, int sample_rate, AVSampleFormat fmt, int
         al_debug("AAC encoder initialized: frame_size=%d, extradata_size=%d, profile=%d", 
                  _encoder_ctx->frame_size, _encoder_ctx->extradata_size, _encoder_ctx->profile);
         
-        // 初始化BSF将raw AAC转换为ADTS格式
-        // 注意:我们需要手动添加ADTS头部,因为没有直接的BSF可以将raw AAC转换为ADTS
-        // 暂时跳过BSF初始化,使用手动ADTS头部添加
+        // 初始化BSF以适配必要的比特流转换
+        // 目前不使用AAC相关BSF,编码器输出原始AAC帧,由复用器/容器处理(如写入ASC/ADTS等)
         _bsf_ctx = NULL;
-        al_debug("Skipping BSF initialization, will add ADTS headers manually");
+        al_debug("No AAC BSF used; raw AAC frames will be passed to muxer for container-specific framing");
         
         /*
         const AVBitStreamFilter *bsf = av_bsf_get_by_name("aac_adtstoasc");
@@ -334,42 +335,16 @@ int encoder_aac::encode(AVFrame *frame, AVPacket *packet)
                 al_warn("Input frame has invalid timestamp (AV_NOPTS_VALUE), packet will have invalid timestamp");
             }
             
-            // 立即检查编码器输出的原始包大小
-            al_debug("Raw encoder output: size=%d, data=%p", packet->size, packet->data);
-            
-            // 验证AAC数据包的有效性
-            if (packet->data == nullptr) {
-                al_warn("AAC packet data is null, skipping");
-                av_packet_unref(packet);
-                continue;
-            }
-            
-            // 验证音频包大小,确保符合RTMP要求
-            // AAC数据包至少需要包含ADTS头部(7字节)+ 音频数据
-            if (packet->size < 7) {
-                al_warn("AAC packet size too small: %d bytes (minimum 7 required), skipping", packet->size);
+            // 验证编码器输出的包有效性
+            if (packet->data == nullptr || packet->size <= 0) {
+                al_warn("AAC packet is empty, skipping");
                 av_packet_unref(packet);
                 continue;
             }
             
-            // 检查ADTS头部的同步字(0xFFF)
-            if (packet->size >= 2 && (packet->data[0] != 0xFF || (packet->data[1] & 0xF0) != 0xF0)) {
-                al_debug("Raw AAC data detected, adding ADTS header");
-                // 为raw AAC数据添加ADTS头部
-                int adts_ret = add_adts_header(packet);
-                if (adts_ret != AE_NO) {
-                    al_error("Failed to add ADTS header: %d", adts_ret);
-                    av_packet_unref(packet);
-                    continue;
-                }
-            } else {
-                al_debug("ADTS header already present");
-            }
-            
-            al_debug("AAC packet: size=%d, pts=%lld, dts=%lld, header=0x%02X%02X", 
-                     packet->size, packet->pts, packet->dts, 
-                     packet->size >= 2 ? packet->data[0] : 0,
-                     packet->size >= 2 ? packet->data[1] : 0);
+            // 不再手动添加ADTS头部,完全由复用器/容器处理需要的打包格式
+            al_debug("AAC packet ready: size=%d, pts=%lld, dts=%lld", 
+                     packet->size, packet->pts, packet->dts);
             
             if (_on_data)
                 _on_data(packet);

+ 17 - 118
libs/Recorder/muxer_ffmpeg.cpp

@@ -789,45 +789,24 @@ int muxer_ffmpeg::add_audio_stream(const MUX_SETTING_T &setting,
         _a_stream->st = st;
 
         _a_stream->setting = setting;
-        // 对于RTMP推流,不使用aac_adtstoasc过滤器,保持ADTS格式
-        // 检查输出格式是否为FLV(RTMP使用FLV容器)
-        if (_fmt_ctx->oformat && strcmp(_fmt_ctx->oformat->name, "flv") == 0) {
-            // RTMP推流,不使用过滤器
-            _a_stream->filter = nullptr;
-            al_debug("RTMP output detected, skipping aac_adtstoasc filter");
-        } else {
-            // 其他格式(如MP4/RTSP),使用aac_adtstoasc过滤器以去除可能存在的ADTS头
-            _a_stream->filter = ffmpeg_bitstream_filter_init("aac_adtstoasc");
-            al_debug("Non-RTMP output, using aac_adtstoasc filter");
-        }
-        if (_fmt_ctx->oformat) {
-            const char *ofmt = _fmt_ctx->oformat->name;
-            // FLV/RTMP、RTSP、MP4等容器需要原始AAC(无ADTS),因此启用 aac_adtstoasc 过滤器
-            if (strcmp(ofmt, "flv") == 0 || strcmp(ofmt, "rtsp") == 0 || strcmp(ofmt, "mp4") == 0
-                || strcmp(ofmt, "mov") == 0 || strcmp(ofmt, "matroska") == 0) {
-                _a_stream->filter = ffmpeg_bitstream_filter_init("aac_adtstoasc");
-                al_debug("Container '%s' requires raw AAC, enabling aac_adtstoasc filter", ofmt);
-            } else {
-                // 对于期望ADTS的容器(如 mpegts/adts),不使用过滤器
-                _a_stream->filter = nullptr;
-                al_debug("Container '%s' supports ADTS, skipping aac_adtstoasc filter", ofmt);
-            }
-        }
+        // 统一关闭 AAC 比特流过滤器:编码器输出原始 AAC(无 ADTS),由容器负责正确封装
+        _a_stream->filter = nullptr;
+        al_debug("AAC bitstream filter disabled; container will handle framing based on extradata");
 
-    } while (0);
+        } while (0);
 
-    return error;
-}
+        return error;
+    }
 
-int muxer_ffmpeg::open_output(const char *output_file, const MUX_SETTING_T &setting)
-{
-    int error = AE_NO;
-    int ret = 0;
+    int muxer_ffmpeg::open_output(const char *output_file, const MUX_SETTING_T &setting)
+    {
+        int error = AE_NO;
+        int ret = 0;
 
-    do {
-        if (!(_fmt->flags & AVFMT_NOFILE)) {
-            ret = avio_open(&_fmt_ctx->pb, output_file, AVIO_FLAG_WRITE);
-            if (ret < 0) {
+        do {
+            if (!(_fmt->flags & AVFMT_NOFILE)) {
+                ret = avio_open(&_fmt_ctx->pb, output_file, AVIO_FLAG_WRITE);
+                if (ret < 0) {
                 error = AE_FFMPEG_OPEN_IO_FAILED;
                 break;
             }
@@ -1044,90 +1023,10 @@ int muxer_ffmpeg::write_audio(AVPacket *packet)
         return -1;
     }
     
-    // 验证AAC包大小,确保符合RTMP推流要求
-    if (packet->size < 7) {
-        al_warn("AAC packet size too small: %d bytes (minimum 7 required for ADTS), skipping write", packet->size);
-        return -1;
-    }
-    
-    // 检查是否为RTMP推流(FLV格式)
-    bool isRtmpStream = (_fmt_ctx->oformat && strcmp(_fmt_ctx->oformat->name, "flv") == 0);
-    
-    if (isRtmpStream) {
-        // RTMP推流需要验证ADTS头部
-        if (packet->size >= 2) {
-            // 检查ADTS同步字(0xFFF)
-            if ((packet->data[0] != 0xFF) || ((packet->data[1] & 0xF0) != 0xF0)) {
-                al_warn("Invalid AAC ADTS header for RTMP: 0x%02X%02X, packet may be corrupted", 
-                       packet->data[0], packet->data[1]);
-                // 对于RTMP,这可能导致播放问题,但仍然尝试发送
-            }
-        }
-        al_debug("RTMP AAC packet: size=%d, header=0x%02X%02X", 
-                packet->size, packet->data[0], packet->data[1]);
-    }
-    // 根据容器判断是否期望ADTS头部
-    bool expectsAdts = false;
-    if (_fmt_ctx->oformat && _fmt_ctx->oformat->name) {
-        const char *ofmt = _fmt_ctx->oformat->name;
-        if (strcmp(ofmt, "mpegts") == 0 || strcmp(ofmt, "adts") == 0) {
-            expectsAdts = true;
-        }
-    }
-
-    if (expectsAdts) {
-        // 期望ADTS:做最基本校验
-        if (packet->size < 7) {
-            al_warn("AAC packet too small for ADTS: %d bytes (min 7)", packet->size);
-            return -1;
-        }
-        if (packet->size >= 2 && (packet->data[0] != 0xFF || (packet->data[1] & 0xF0) != 0xF0)) {
-            al_warn("Missing ADTS syncword in ADTS-expected container, header=0x%02X%02X",
-                    packet->data[0],
-                    packet->data[1]);
-        }
-    } else {
-        // 不期望ADTS(如 RTSP/FLV/MP4 等):如果存在ADTS,仅打印调试信息
-        if (packet->size >= 2 && packet->data[0] == 0xFF && (packet->data[1] & 0xF0) == 0xF0) {
-            al_debug(
-                "ADTS header present but container doesn't require it; filter may strip it later");
-        }
-    }
+    // 不再强制检查ADTS头部,容器将根据extradata与编码器输出决定封装格式
 
-    // 应用bitstream过滤器(如果存在)
-    AVPacket *filtered_packet = packet;
-    if (_a_stream->filter) {
-        AVPacket *temp_packet = av_packet_alloc();
-        if (temp_packet) {
-            av_packet_ref(temp_packet, packet);
-            int filter_ret = ffmpeg_bitstream_filter_filter(_a_stream->filter, temp_packet);
-            if (filter_ret >= 0) {
-                // 验证过滤后的包大小
-                if (temp_packet->size < 2) {
-                    al_warn("Filtered AAC packet too small: %d bytes, using original packet",
-                            temp_packet->size);
-                    av_packet_free(&temp_packet);
-                } else {
-                    filtered_packet = temp_packet;
-                    al_debug("Applied aac_adtstoasc filter, original size: %d, filtered size: %d",
-                             packet->size,
-                             temp_packet->size);
-                }
-            } else {
-                al_warn("Failed to apply bitstream filter: %d, using original packet", filter_ret);
-                av_packet_free(&temp_packet);
-            }
-        } else {
-            al_warn("Failed to allocate temporary packet for filtering");
-        }
-    }
-
-    int ret = av_interleaved_write_frame(_fmt_ctx, filtered_packet);
-    
-    // 如果使用了过滤器,需要释放临时包
-    if (filtered_packet != packet) {
-        av_packet_free(&filtered_packet);
-    }
+    // 不应用任何 AAC 比特流过滤器,编码器输出的原始 AAC 数据由容器决定封装
+    int ret = av_interleaved_write_frame(_fmt_ctx, packet);
     if (ret != 0) {
         al_fatal("write audio frame error:%d", ret);
     }