当前位置: 首页 > 知识库问答 >
问题:

FFMPEG AAC编码器问题

胥宏义
2023-03-14

我正在尝试捕获和编码音频数据,我正在使用FFMPEG AAC编码音频,为了捕获PCM数据,我使用ALSA,捕获部分在我的情况下工作,但是AAC编码器不工作。

我试图播放test.aac文件使用

ffplaytest.aac

但它包含很多噪音。

附加aac编码器代码:

#include "AudioEncoder.h"

void* AudioEncoder::run(void *ctx)
{
    return ((AudioEncoder *)ctx)->execute();
}

static int frameCount = 0;

void* AudioEncoder::execute(void)
{
    float buf[size], *temp;
    int totalSize = 0;
    int fd = open("in.pcm", O_CREAT| O_RDWR, 0666);
    int frameSize = 128 * snd_pcm_format_width(SND_PCM_FORMAT_FLOAT) / 8 * 2;
    av_new_packet(&pkt,size);
    cout << size << endl;
    while (!Main::stopThread)
    {
        temp = (Main::fbAudio)->dequeue();
        memcpy(buf + totalSize, temp, frameSize);
        write(fd, temp, frameSize); // Can play in.pcm with no noise in it.
        totalSize += frameSize;
        delete temp;
        if (totalSize >= size)
        {
            totalSize = 0;
            //frame_buf = (uint8_t *) buf;
            pFrame->data[0] = (uint8_t *)buf;  //PCM Data

            pFrame->pts=frameCount;
            frameCount++;
            got_frame=0;
            //Encode
            ret = avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame);
            if(ret < 0){
                cerr << "Failed to encode!\n";
                return NULL;
            }
            if (got_frame==1){
                printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size);
                pkt.stream_index = audio_st->index;
#ifdef DUMP_TEST
                ret = av_write_frame(pFormatCtx, &pkt);
#endif
                av_free_packet(&pkt);
            }
            //memset(buf, 0, sizeof(float)*size);
        }
        //delete temp;
        //if (buf.size() >= m_audio_output_decoder_ctx->frame_size)
        /* encode the audio*/
    }
        close(fd);
    Main::stopThread = true;
    return NULL;
}

int AudioEncoder::flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){
    int ret;
    int got_frame;
    AVPacket enc_pkt;
    if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
        CODEC_CAP_DELAY))
        return 0;
    while (1) {
        enc_pkt.data = NULL;
        enc_pkt.size = 0;
        av_init_packet(&enc_pkt);
        ret = avcodec_encode_audio2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
            NULL, &got_frame);
        av_frame_free(NULL);
        if (ret < 0)
            break;
        if (!got_frame){
            ret=0;
            break;
        }
        printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);
        /* mux encoded frame */
#ifdef DUMP_TEST
        ret = av_write_frame(fmt_ctx, &enc_pkt);
        if (ret < 0)
            break;
#endif
    }
    return ret;
}

void AudioEncoder::start(void)
{
    pthread_t encoder;
    pthread_create(&encoder, NULL, &AudioEncoder::run, this);
}

AudioEncoder::AudioEncoder() : out_file("test.aac")
{
    got_frame = 0;
    ret = 0;
    size = 0;
    av_register_all();
    avcodec_register_all();
    //Method 1.
    pFormatCtx = avformat_alloc_context();
    fmt = av_guess_format(NULL, out_file, NULL);
    pFormatCtx->oformat = fmt;

#ifdef DUMP_TEST
    if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
        cerr << "Failed to open output file!\n";
        return;
    }
#endif
    audio_st = avformat_new_stream(pFormatCtx, 0);
    if (audio_st==NULL){
        return;
    }
    pCodecCtx = audio_st->codec;
    pCodecCtx->codec_id = fmt->audio_codec;
    pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
    pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
    pCodecCtx->sample_rate= 8000;
    pCodecCtx->channel_layout=AV_CH_LAYOUT_STEREO;
    pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
//    pCodecCtx->bit_rate = 64000;

#ifdef DUMP_TEST
    //Show some information
    av_dump_format(pFormatCtx, 0, out_file, 1);
#endif

    pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
    if (!pCodec){
        printf("Can not find encoder!\n");
        return;
    }
    if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){
        printf("Failed to open encoder!\n");
        return;
    }
    pFrame = av_frame_alloc();
    pFrame->nb_samples= pCodecCtx->frame_size;
    pFrame->format= pCodecCtx->sample_fmt;

    size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1);
    frame_buf = (uint8_t *)av_malloc(size);
    avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1);
    //Write Header
#ifdef DUMP_TEST
    avformat_write_header(pFormatCtx,NULL);
#endif
}

AudioEncoder::~AudioEncoder()
{
    //Flush Encoder
    ret = flush_encoder(pFormatCtx,0);
    if (ret < 0) {
        cerr << "Flushing encoder failed\n";
        return;
    }

#ifdef DUMP_TEST
    //Write Trailer
    av_write_trailer(pFormatCtx);
#endif
    //Clean
    if (audio_st){
        avcodec_close(audio_st->codec);
        av_free(pFrame);
        av_free(frame_buf);
    }
    avio_close(pFormatCtx->pb);
    avformat_free_context(pFormatCtx);
}

这里,请忽略DUMP_TEST标志,我已经启用了。

有人能告诉我什么是问题吗?

谢谢,哈希尔

共有1个答案

都才俊
2023-03-14

通过正确地将缓冲区从ALSA传递到AAC编码器,我能够解决这个问题。

这里AAC预计缓冲区大小为4096字节,但我从deque传递了1024字节,这导致了问题,我还将音频通道更新为单声道,而不是立体声。附加我的工作代码片段以了解更多信息:

#include "AudioEncoder.h"

void* AudioEncoder::run(void *ctx)
{
    return ((AudioEncoder *)ctx)->execute();
}

static int frameCount = 0;

void* AudioEncoder::execute(void)
{
    float *temp;
#ifdef DUMP_TEST
    int fd = open("in.pcm", O_CREAT| O_RDWR, 0666);
#endif
    int frameSize = 1024 * snd_pcm_format_width(SND_PCM_FORMAT_FLOAT) / 8 * 1;
    av_new_packet(&pkt,size);
    while (!Main::stopThread)
    {
        temp = (Main::fbAudio)->dequeue();
        frame_buf = (uint8_t *) temp;
        pFrame->data[0] = frame_buf;
        pFrame->pts=frameCount*100;
        frameCount++;
        got_frame=0;
        //Encode
        ret = avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame);
        if(ret < 0){
            cerr << "Failed to encode!\n";
            return NULL;
        }
        if (got_frame==1){
            cout << "Encoded frame\n";
            pkt.stream_index = audio_st->index;
#ifdef DUMP_TEST
            write(fd, temp, frameSize);
            ret = av_interleaved_write_frame(pFormatCtx, &pkt);
#endif
            av_free_packet(&pkt);
        }
        delete temp;
    }
#ifdef DUMP_TEST
    close(fd);
#endif
    Main::stopThread = true;
    return NULL;
}

int AudioEncoder::flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){
    int ret;
    int got_frame;
    AVPacket enc_pkt;
    if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
        CODEC_CAP_DELAY))
        return 0;
    while (1) {
        enc_pkt.data = NULL;
        enc_pkt.size = 0;
        av_init_packet(&enc_pkt);
        ret = avcodec_encode_audio2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
            NULL, &got_frame);
        av_frame_free(NULL);
        if (ret < 0)
            break;
        if (!got_frame){
            ret=0;
            break;
        }
        printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);
        /* mux encoded frame */
#ifdef DUMP_TEST
        ret = av_write_frame(fmt_ctx, &enc_pkt);
        if (ret < 0)
            break;
#endif
    }
    return ret;
}

void AudioEncoder::start(void)
{
    pthread_t encoder;
    pthread_create(&encoder, NULL, &AudioEncoder::run, this);
}

AudioEncoder::AudioEncoder() : out_file("test.aac")
{
    got_frame = 0;
    ret = 0;
    size = 0;
    av_register_all();
    avcodec_register_all();
    //Method 1.
    pFormatCtx = avformat_alloc_context();
    fmt = av_guess_format(NULL, out_file, NULL);
    pFormatCtx->oformat = fmt;

#ifdef DUMP_TEST
    if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
        cerr << "Failed to open output file!\n";
        return;
    }
#endif
    audio_st = avformat_new_stream(pFormatCtx, 0);
    if (audio_st==NULL){
        return;
    }
    pCodecCtx = audio_st->codec;
    pCodecCtx->codec_id = fmt->audio_codec;
    pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
    pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
    pCodecCtx->sample_rate= 8000;
    pCodecCtx->channel_layout=AV_CH_LAYOUT_MONO;
    pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
    pCodecCtx->bit_rate = 64000;

#ifdef DUMP_TEST
    //Show some information
    av_dump_format(pFormatCtx, 0, out_file, 1);
#endif

    pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
    if (!pCodec){
        printf("Can not find encoder!\n");
        return;
    }
    if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){
        printf("Failed to open encoder!\n");
        return;
    }
    pFrame = av_frame_alloc();
    pFrame->nb_samples= pCodecCtx->frame_size;
    pFrame->format= pCodecCtx->sample_fmt;

    size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1);
    frame_buf = (uint8_t *)av_malloc(size);
    avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1);
    //Write Header
#ifdef DUMP_TEST
    avformat_write_header(pFormatCtx,NULL);
#endif
}

AudioEncoder::~AudioEncoder()
{
    //Flush Encoder
    ret = flush_encoder(pFormatCtx,0);
    if (ret < 0) {
        cerr << "Flushing encoder failed\n";
        return;
    }

#ifdef DUMP_TEST
    //Write Trailer
    av_write_trailer(pFormatCtx);
#endif
    //Clean
    if (audio_st){
        avcodec_close(audio_st->codec);
        av_free(pFrame);
        av_free(frame_buf);
    }
    avio_close(pFormatCtx->pb);
    avformat_free_context(pFormatCtx);
}
 类似资料:
  • 我正在尝试在linux上构建ffmpeg编码器。我从一个定制的服务器Dual 1366 2.6 Ghz Xeon CPU(6核)开始,具有16 GB RAM和Ubuntu 16.04最小安装。使用h264和aac构建ffmpeg。我正在获取实时源OTA频道并使用以下参数对它们进行编码/流式传输 -vcodec libx264-预设超高速-crf 25-x264opts keyint=60:min

  • 我的密码编码器有问题, 我的代码: 错误: 应用程序启动失败 描述: org.spring.service.UserService中构造函数的参数0需要找不到类型org.springframework.security.crypto.password.PasswordEncoder的bean。 行动: 考虑定义“org”类型的bean。springframework。安全加密。暗语配置中的Pass

  • 最近,我们正在将java构建作业从serverA迁移到serverB,java源代码(包含中文字符)在使用Ant的原始serverA上编译良好( ),但是,当我们将相同的代码签出到新的serverB并运行相同的Ant脚本时,出现了编码错误,如“用于编码GBK的Unmappable character”(Unmappable character for encoding GBK)。(JDK版本相同)

  • 我有一个(非常简单的)java Spring Boot/REST服务,它从输入中呈现PDF并使用IntelliJ对其进行测试。 我使用pdfbox作为创建此类pdf的工具。 一个特点是,除了它想要的常规内容外,客户端还可以将附件作为字节[]提供。 当用户尝试该服务时,最终文档只有附件部分的空白页。 使用IntelliJ和HTTP REST客户端进行了尝试,但遇到了相同的问题 当我注意到使用post

  • 当从其中一个web服务获取数据时,引号(“)将显示为(?)当我使用Rest模板时。我在chrome上的postman中测试了web服务,并给出了正确的字符。我尝试编码UTF-8,但没有成功。 我检查了以下是从Web服务提供商编码: 高速缓存控制→私有连接→关闭内容编码→gzip内容长度→3407内容类型→text/xml; charset=ISO-8859-1日期→周三,2015 13:35:53

  • 我使用Java/Jsp开发了一个web应用程序,该应用程序运行在带有Tomcat 8的Ubuntu14.04 LTS服务器上,下面的UTF-8编码问题与部分符号§apperas有关。 在服务器端输入的任何章节符号§都将转换为§,我不知道为什么。 简单系统输出: