【问题标题】:ffmpeg transcodeffmpeg 转码
【发布时间】:2013-01-07 03:10:08
【问题描述】:

我想使用 ffmpeg 库进行音频转码。现在我有文件,但我只能听噪音。 我的程序的步骤是: 1) 打开输入文件并使用 avcodec_decode_audio4 以原始格式解码 2)编码并保存原始格式。 我不知道我错在哪里。这是我的代码。

/* 
 * File:   newmain.c
 * Author: antonello
 *
 * Created on 23 gennaio 2013, 11.24
 */

#include <stdio.h>
#include <stdlib.h>


#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libavcodec/old_codec_ids.h>

static AVCodecContext *get_encoder(int sampleRate, int channels, int audioBitrate)
{ 
    AVCodecContext  *audioCodec;
    AVCodec *codec;



    //Set up audio encoder
    codec = avcodec_find_encoder(CODEC_ID_AAC);
    if (codec == NULL) 
    {
        printf("avcodec_find_encoder: ERROR\n");
        return NULL;
    }
    audioCodec = avcodec_alloc_context();
    audioCodec->bit_rate = audioBitrate;
    audioCodec->sample_fmt = AV_SAMPLE_FMT_S16P;
    audioCodec->sample_rate = sampleRate;
    audioCodec->channels = channels;
    audioCodec->profile = FF_PROFILE_AAC_MAIN;
    audioCodec->channel_layout=AV_CH_LAYOUT_MONO;
    //audioCodec->time_base = (AVRational){1, sampleRate};
    audioCodec->time_base.num  = 1;
    audioCodec->time_base.den  = sampleRate;

    audioCodec->codec_type = AVMEDIA_TYPE_AUDIO;
    if (avcodec_open(audioCodec, codec) < 0) 
    {
        printf("avcodec_open: ERROR\n");
        return NULL;
    }

    return audioCodec;
}


int main(int argc, char** argv) {
  AVFormatContext *aFormatCtx_decoder = NULL;
  AVFormatContext *aFormatCtx_encoder = NULL;
  int             i, audioStream;
  AVPacket        packet_decoder;
  AVPacket        packet_encoder;
  int             got_frame=0;
  int             complete_decode=0;
  int             len;
  AVFrame         *decoded_frame = NULL;
  AVCodecContext  *aCodec_decoderCtx = NULL;
  AVCodec         *aCodec_decoder = NULL;
  FILE            *outfile;
  //reding input file
  avcodec_register_all();

   //register all codecs
    av_register_all();

 //open file
    if(avformat_open_input(&aFormatCtx_decoder, "sample.aac", NULL, NULL)!=0){
        fprintf(stderr, "Could not open source file \n");
        return -1; // Couldn't open file
    }

  // Retrieve stream information
  if(avformat_find_stream_info(aFormatCtx_decoder, NULL)<0){
      fprintf(stderr, "Couldn't find stream information \n");
      return -1; // Couldn't find stream information
  }

  // Dump information about file onto standard error
  //av_dump_format(aFormatCtx_decode, 0, argv[1], 0);

  // Find the first audio stream
  audioStream=-1;

  for(i=0; i<aFormatCtx_decoder->nb_streams; i++) {
    if(aFormatCtx_decoder->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
       audioStream < 0) {
      audioStream=i;
    }
  }
  if(audioStream==-1){
      fprintf(stderr, "File haven't sudio stream \n");
      return -1;
  }

  //get audio codec contex
  aCodec_decoderCtx=aFormatCtx_decoder->streams[audioStream]->codec;
  //get audio codec
  aCodec_decoder = avcodec_find_decoder(aCodec_decoderCtx->codec_id);
  aCodec_decoder->sample_fmts=AV_SAMPLE_FMT_S16P;
  if(!aCodec_decoder) {
    fprintf(stderr, "Unsupported codec!\n");
    return -1;//Unsupported codec!
  }
  //open codec
  // Open codec
  if(avcodec_open2(aCodec_decoderCtx, aCodec_decoder, NULL)<0)
    return -1; // Could not open codec
  // allocate audio frame
  decoded_frame = avcodec_alloc_frame();
  if (!decoded_frame) {
    fprintf(stderr, "Could not allocate audio frame\n");
    return -1;//Could not allocate audio frame
    }
  aCodec_decoderCtx->bit_rate=12000;
  aFormatCtx_encoder=get_encoder(8000,1,12000);
  av_init_packet(&packet_encoder);

  printf("param %d %d %d",aCodec_decoderCtx->sample_fmt,aCodec_decoderCtx->channels,aCodec_decoderCtx->bit_rate);

  outfile = fopen("out.aac", "wb");
    if (!outfile) {
        printf(stderr, "Could not open outfile \n");
        return -1;//Could not open outfile
    }
  while(av_read_frame(aFormatCtx_decoder, &packet_decoder)>=0) {
     // decode frame
     len = avcodec_decode_audio4(aCodec_decoderCtx, decoded_frame, &got_frame, &packet_decoder);
        if (len < 0) {
            fprintf(stderr, "Error while decoding\n");
            return -1;
            }

        if (got_frame){
          avcodec_encode_audio2(aFormatCtx_encoder,&packet_encoder,decoded_frame,&complete_decode);
          if(complete_decode){
          //    printf("complete decode frame");
              fwrite(packet_encoder.data, 1, packet_encoder.size, outfile);
              av_free_packet(&packet_encoder);
          }
        }



    }
  fclose(outfile);
    return (EXIT_SUCCESS);
}

【问题讨论】:

    标签: c audio ffmpeg


    【解决方案1】:

    修改为这个,效果很好

    aCodec_decoder->sample_fmts=audioCodec->sample_fmt; 
    

    【讨论】:

      【解决方案2】:

      使用以下代码进行示例格式转换。 您可以在 ffmpeg/doc/examples/resampling_audio.c 中获得示例

              SwrContext *swr = swr_alloc();
      
      
              av_opt_set_int(node_handle->swr,        "in_channel_layout",    decoded_frame->channel_layout,          0);
              av_opt_set_int(node_handle->swr,        "out_channel_layout",   encoder_ctx->channel_layout,    0);
      
              av_opt_set_int(node_handle->swr,        "in_sample_rate",       decoded_frame->sample_rate,             0);
              av_opt_set_int(node_handle->swr,        "out_sample_rate",      encoder_ctx->sample_rate,       0);
      
              av_opt_set_sample_fmt(swr, "in_sample_fmt",        decoded_frame->format,                  0); 
              av_opt_set_sample_fmt(swr, "out_sample_fmt",       encoder_ctx->sample_fmt,        0);
      
              swr_init(swr);
      
              uint8_t* swr_out_data;
              int linesize;
              av_samples_alloc(&swr_out_data,
                                   linesize,
                                   encoder_ctx->nb_channels,
                                   decoded_frame->nb_samples,
                                   encoder_ctx->sample_fmt,
                                   0
                               );
              swr_convert(swr,&swr_out_data, decoded_frame->nb_samples, decoded_frame->data, decoded_frame->nb_samples);
      

      【讨论】:

        【解决方案3】:

        你不能设置变量sample_fmts的任意值:

        aCodec_decoder-&gt;sample_fmts=AV_SAMPLE_FMT_S16P; // It's wrong

        解码将始终使用编解码器设置的参数进行。 你必须创建SwrContext并执行格式转换到目标(SwrContext转换采样格式、采样率和通道布局)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-10
          • 1970-01-01
          • 2021-02-19
          • 1970-01-01
          • 1970-01-01
          • 2023-02-07
          • 2012-02-04
          • 2020-09-15
          相关资源
          最近更新 更多