首页 > 解决方案 > 将 pcm 流数据转换为编码的 aac 数据

问题描述

我尝试使用 ffmpeg 将脉冲音频 pcm 流数据转换为 aac 编码数据。
但是在编码之后,我得到了充满噪声的数据,而不是正确的数据。在这里我发布我的代码,任何人都可以帮助我一些想法。

初始配置:

    av_register_all();

    int error;
    if ((error = avio_open(&output_io_context,"out.aac",AVIO_FLAG_WRITE))<0) {
            printf("could not open output file\n");
    }

    if (!(output_format_context = avformat_alloc_context())) {
            printf("output_format_context error\n");
    }

    output_format_context->pb = output_io_context;

    if(!(output_format_context->oformat = av_guess_format(NULL, "out.aac", NULL))) {
            printf("guess format error\n");
    }

    codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
    if (codec == NULL) {
            printf("avcodec_find_encoder: ERROR\n");
    }

    if (!(stream = avformat_new_stream(output_format_context, NULL))) {
            printf("stream create error\n");
    }
    output_codec_context = avcodec_alloc_context3(codec);
    if(!output_codec_context) {
            printf("output_codec_context is null\n");
    }

    output_codec_context->channels       = CHANNELS;
    output_codec_context->channel_layout = av_get_default_channel_layout(CHANNELS);
    output_codec_context->sample_rate    = SAMPLE_RATE; //input_codec_context->sample_rate;
    output_codec_context->sample_fmt     = codec->sample_fmts[0];
    output_codec_context->bit_rate       = 48000; //OUTPUT_BIT_RATE;

    stream->time_base.den = SAMPLE_RATE;//input_codec_context->sample_rate;
    stream->time_base.num = 1;

    if(output_format_context->oformat->flags & AVFMT_GLOBALHEADER)
            output_codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

    if ((error = avcodec_open2(output_codec_context, codec, NULL)) < 0) {
        printf("error");
    }

    error = avcodec_parameters_from_context(stream->codecpar, output_codec_context);

    if (write_output_file_header(output_format_context)) {
            printf("write header failure...\n");
    }

数据编码:

AVFrame *output_frame;
int frame_pos = 0, ctx_frame_size = output_codec_context->frame_size;
int size = av_samples_get_buffer_size(NULL, CHANNELS,
              output_codec_context->frame_size,output_codec_context->sample_fmt, 1);
if((x =  avcodec_fill_audio_frame(output_frame, CHANNELS,
               output_codec_context->sample_fmt, data, length, 1)) < 0) {
      printf("avcodec_fill_audio_frame error : %s\n", av_err2str(x));
}

 int data_written;
 if (encode_audio_frame(output_frame, output_format_context,
            output_codec_context, &data_written)) {
        printf("encode_audio_frame error\n");
  }

  av_frame_free(&output_frame);

助手功能:

 int encode_audio_frame(AVFrame *frame,AVFormatContext *output_format_context,
              AVCodecContext *output_codec_context, int *data_present)
 {
   AVPacket output_packet;
   int error;
   init_packet(&output_packet);

   if (frame) {
      frame->pts = pts;
      pts += frame->nb_samples;
   }

   error = avcodec_send_frame(output_codec_context, frame);
   if (error == AVERROR_EOF) {
     error = 0;
     goto cleanup;
   } else if (error < 0) {
      fprintf(stderr, "Could not send packet for encoding (error '%s')\n",
            av_err2str(error));
      return error;
   }

   error = avcodec_receive_packet(output_codec_context, &output_packet);
   if (error == AVERROR(EAGAIN)) {
     error = 0;
     goto cleanup;
   } else if (error == AVERROR_EOF) {
      error = 0;
      goto cleanup;
   } else if (error < 0) {
      fprintf(stderr, "Could not encode frame (error '%s')\n",
            av_err2str(error));
      goto cleanup;
   } else {
      *data_present = 1;
  }

  if (*data_present &&
      (error = av_write_frame(output_format_context, &output_packet)) < 0) {
      fprintf(stderr, "Could not write frame (error '%s')\n",
             av_err2str(error));
      goto cleanup;
  }

  cleanup:
      av_packet_unref(&output_packet);
      return error;
 }

蒂亚 :) !!

标签: linuxaudioffmpegaacpulseaudio

解决方案


推荐阅读