将 AAC 的 avcodec 配置转换为 HLS/MPEG-TS[mpegts @ 0x7fc4c00343c0] AAC 比特流不是 ADTS 格式且缺少额外数据

如何解决将 AAC 的 avcodec 配置转换为 HLS/MPEG-TS[mpegts @ 0x7fc4c00343c0] AAC 比特流不是 ADTS 格式且缺少额外数据

我们正在将视频编码为 H264,并将原始 PCM 样本编码为 AAC 以进行 HLS 流式传输。视频工作正常,但在 libavcodec 中配置 AAC 编码器时遇到问题。

This SO question 说:

有两种方法可以将 AAC 放入传输流中。

1.使用 ADTS 语法(MPEG2 风格)

在这种情况下,PMT 的 stream_type 应指定为 0x0F (ISO/IEC 13818-7 带有 ADTS 传输语法的音频)。

因此,您只能使用“旧”(MPEG2) AAC 版本,而不能 SBR 和 PS。

2.使用 LATM+LOAS/AudioSyncStream 语法(MPEG4 风格)。

在这种情况下,PMT 的 stream_type 应指定为 0x11 (ISO/IEC 14496-3 使用 LATM 传输语法的音频)。

并且您可以使用“新”(MPEG4) AAC 功能的所有功能包括 SBR 和 PS。

此外,DVB 标准 ETSI TS 101 154 要求:HEv1/HEv2 AAC 应 使用 LATM 语法传输。

但经过大量搜索后,我找不到任何有关如何执行其中任何一项的文档。在将编码音频传递到 MPEG-TS 多路复用器(用于输出到 HLS)之前,下面的配置缺少什么以获取带有 ADTS 或 LATM 的编码音频?

设置 AAC 编解码器的当前代码给出了错误 [mpegts @ 0x7fc4c00343c0] AAC bitstream not in ADTS format and exTradata missing

AAC 编码器设置(为简洁起见,已删除错误检查)

/// Set up Encoder ///
mpAudioCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
mpAudioCodecContext = avcodec_alloc_context3(mpAudioCodec);

mpAudioCodecContext->bit_rate       = DEFAULT_AUD_BITRATE;
mpAudioCodecContext->sample_rate    = DEFAULT_AUD_SAMPLE_RATE;
mpAudioCodecContext->channel_layout = DEFAULT_AUD_CHAN_LAYOUT;
mpAudioCodecContext->channels       = 2; 
mpAudioCodecContext->sample_fmt     = AV_SAMPLE_FMT_FLTP; // S16 not supported. Must convert

mpAudioCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

rc = avcodec_open2(mpAudioCodecContext,mpAudioCodec,0);

HLS MUX 设置

avformat_alloc_output_context2(&mpOutputMux,"hls",path.c_str());

// VIDEO TRACK
mpVideoTrack = avformat_new_stream(mpOutputMux,0);
mpVideoTrack->id = 0;
mpVideoTrack->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
mpVideoTrack->codecpar->codec_id   = AV_CODEC_ID_H264;

mpVideoTrack->time_base      = (AVRational) { 1,mFrameRate };
mpVideoTrack->avg_frame_rate = (AVRational) { mFrameRate,1          };

// AUdio TRACK
mpAudioTrack = avformat_new_stream(mpOutputMux,0);
mpAudioTrack->id = 1;

mpAudioTrack->codecpar->codec_type  = AVMEDIA_TYPE_AUdio;
mpAudioTrack->codecpar->codec_id    = DEFAULT_AUdio_CODEC;
mpAudioTrack->codecpar->sample_rate = mpAudioCodecContext->sample_rate;

mpAudioTrack->time_base.den = mpAudioCodecContext->sample_rate;
mpAudioTrack->time_base.num = 1;

AVDictionary *hlsOptions = NULL;
av_dict_set(&hlsOptions,"hls_segment_type","mpegts",0);
av_dict_set(&hlsOptions,"segment_list_type","m3u8",0);
av_dict_set_int(&hlsOptions,"hls_list_size",mPlaylistSize,"hls_time",mChunkDurSec,"hls_flags","delete_segments","hls_segment_filename",segPath.c_str(),0);

av_dict_set_int(&hlsOptions,"reference_stream",mpVideoTrack->index,"segment_list_flags","cache+live",0);

int ret = avformat_write_header(mpOutputMux,&hlsOptions);

编码循环

int bytescopied = mAudEsBuffer.popData(mpPcmS16Buf,mpPcmAudioFrame->nb_samples);

// resample to float
int rc = swr_convert(mpAudioResampleCtx,mpPcmAudioFrame->data,mpPcmAudioFrame->nb_samples,(const uint8_t**) &mpPcmS16Buf,mpPcmAudioFrame->nb_samples);

/* Set a timestamp based on the sample rate for the container. */
mCurAudPts += mpPcmAudioFrame->nb_samples;
mpPcmAudioFrame->pts = mCurAudPts;

// send frame for encoding to AAC
rc = avcodec_send_frame(mpAudioCodecContext,mpPcmAudioFrame);

/* read all the available output packets (in general there may be any number of them */
while (rc >= 0)
{
    // need to init packet every time??
    /* Set the packet data and size so that it is recognized as being empty. */
    av_init_packet(mpEncAudioPacket);
    mpEncAudioPacket->data = NULL;
    mpEncAudioPacket->size = 0;

    rc = avcodec_receive_packet(mpAudioCodecContext,mpEncAudioPacket);
    if (rc < 0)
    {
        printf("TqHlsLib::readAndMuxAudio() - Error encoding audio frame: %s\n",av_make_error_string(mpErr,TQERRLEN,rc));
        return HLS_DEC_ERROR;
    }

    TRACE(("%T %t TqHlsLib::readAndMuxAudio() - Got an encoded audio packet. %u bytes\n",mpEncAudioPacket->size ));

    /* rescale output packet timestamp values from codec to stream timebase */
    av_packet_rescale_ts(mpEncAudioPacket,mpAudioTrack->time_base,mpAudioTrack->time_base);
    mpEncAudioPacket->stream_index = mpAudioTrack->index;

    /* Write the compressed frame to the media file. */
    rc = av_interleaved_write_frame(mpOutputMux,mpEncAudioPacket);
    if (rc < 0)
    {
        fprintf(stderr,"TqHlsLib::addVideoH264Packet - Error while writing audio packet: %s\n",ret));

        // return some error here
    }
    av_packet_unref(mpEncAudioPacket);

}

输出

[mpegts @ 0x7fb280144e00] AAC bitstream not in ADTS format and exTradata missing
20:24:52.327418 24388 TqHlsLib::readAndMuxAudio() - Got an encoded audio packet. 185 bytes
[mpegts @ 0x7fb280144e00] AAC bitstream not in ADTS format and exTradata missing
20:24:52.372975 24388 TqHlsLib::readAndMuxAudio() - Got an encoded audio packet. 188 bytes
[mpegts @ 0x7fb280144e00] AAC bitstream not in ADTS format and exTradata missing

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?