title: FFMPEG audio transcoding using libav* libraries
body: <p>I am writing an audio transcoding application using ffmpeg libraries. 
  Here is my code </p>
  
  <pre><code>    /*
       * File:   main.cpp
       * Author: vinod
       * Compile with "g++ -std=c++11 -o audiotranscode main.cpp -lavformat -lavcodec -lavutil -lavfilter"
       * 
       */
  
  
      #if !defined PRId64 || PRI_MACROS_BROKEN
      #undef PRId64
      #define PRId64 "lld"
      #endif
  
      #define __STDC_FORMAT_MACROS
  
      #ifdef   __cplusplus
      extern "C" {
      #endif
  
      #include &lt;stdio.h&gt;
      #include &lt;stdlib.h&gt;
      #include &lt;sys/types.h&gt;
      #include &lt;stdint.h&gt;
      #include &lt;libavutil/imgutils.h&gt;
      #include &lt;libavutil/samplefmt.h&gt;
      #include &lt;libavutil/frame.h&gt;
      #include &lt;libavutil/timestamp.h&gt;
      #include &lt;libavformat/avformat.h&gt;
      #include &lt;libavfilter/avfilter.h&gt;
      #include &lt;libavfilter/buffersrc.h&gt;
      #include &lt;libavfilter/buffersink.h&gt;
      #include &lt;libswscale/swscale.h&gt;
      #include &lt;libavutil/opt.h&gt;
  
      #ifdef   __cplusplus
      }
      #endif
  
      #include &lt;iostream&gt;
      using namespace std;
  
      int select_stream, got_frame, got_packet;
  
      AVFormatContext *in_fmt_ctx = NULL, *out_fmt_ctx = NULL;
      AVCodec *dec_codec = NULL, * enc_codec = NULL;
      AVStream *audio_st = NULL;
      AVCodecContext *enc_ctx = NULL, *dec_ctx = NULL;
  
      AVFrame *pFrame = NULL, * pFrameFiltered = NULL;
  
      AVFilterGraph *filter_graph = NULL;
      AVFilterContext *buffersrc_ctx = NULL;
      AVFilterContext *buffersink_ctx = NULL;
  
      AVPacket packet;
  
      string inFileName = "/home/vinod/vinod/Media/univac.webm";
      string outFileName = "audio_extracted.m4a";
  
      int target_bit_rate = 128000,
          sample_rate = 22050,
          channels = 1;
      AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
      string filter_description = "aresample=22050,aformat=sample_fmts=s16:channel_layouts=mono";
  
      int log_averror(int errcode)
      {
              char *errbuf = (char *) calloc(AV_ERROR_MAX_STRING_SIZE, sizeof(char));
              av_strerror(errcode, errbuf, AV_ERROR_MAX_STRING_SIZE);
              std::cout &lt;&lt; "Error - " &lt;&lt; errbuf &lt;&lt; std::endl;
              delete [] errbuf;
              return -1;
      }
  
      /**
       * Initialize conversion filter */
      int initialize_audio_filter()
      {
              char args[512];
              int ret;
              AVFilter *buffersrc = avfilter_get_by_name("abuffer");
              AVFilter *buffersink = avfilter_get_by_name("abuffersink");
              AVFilterInOut *outputs = avfilter_inout_alloc();
              AVFilterInOut *inputs = avfilter_inout_alloc();
              filter_graph = avfilter_graph_alloc();
              const enum AVSampleFormat out_sample_fmts[] = {sample_fmt, AV_SAMPLE_FMT_NONE};
              const int64_t out_channel_layouts[] = {av_get_default_channel_layout(out_fmt_ctx -&gt; streams[0] -&gt; codec -&gt; channels), -1};
              const int out_sample_rates[] = {out_fmt_ctx -&gt; streams[0] -&gt; codec -&gt; sample_rate, -1};
  
              if (!dec_ctx-&gt;channel_layout)
                      dec_ctx-&gt;channel_layout = av_get_default_channel_layout(dec_ctx-&gt;channels);
  
              snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%" PRIx64,
                       in_fmt_ctx -&gt; streams[select_stream] -&gt; time_base.num, in_fmt_ctx -&gt; streams[select_stream] -&gt; time_base.den,
                       dec_ctx-&gt;sample_rate,
                       av_get_sample_fmt_name(dec_ctx-&gt;sample_fmt),
                       dec_ctx-&gt;channel_layout);
              ret = avfilter_graph_create_filter(&amp;buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph);
  
              if (ret &lt; 0) {
                      av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
                      return -1;
              }
  
              ret = avfilter_graph_create_filter(&amp;buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph);
  
              if (ret &lt; 0) {
                      av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
                      return ret;
              }
  
              ret = av_opt_set_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1,
                                        AV_OPT_SEARCH_CHILDREN);
  
              if (ret &lt; 0) {
                      av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
                      return ret;
              }
  
              ret = av_opt_set_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1,
                                        AV_OPT_SEARCH_CHILDREN);
  
              if (ret &lt; 0) {
                      av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
                      return ret;
              }
  
              ret = av_opt_set_int_list(buffersink_ctx, "sample_rates", out_sample_rates, -1,
                                        AV_OPT_SEARCH_CHILDREN);
  
              if (ret &lt; 0) {
                      av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
                      return ret;
              }
  
              /* Endpoints for the filter graph. */
              outputs -&gt; name = av_strdup("in");
              outputs -&gt; filter_ctx = buffersrc_ctx;
              outputs -&gt; pad_idx = 0;
              outputs -&gt; next = NULL;
              /* Endpoints for the filter graph. */
              inputs -&gt; name = av_strdup("out");
              inputs -&gt; filter_ctx = buffersink_ctx;
              inputs -&gt; pad_idx = 0;
              inputs -&gt; next = NULL;
              string filter_desc = filter_description;
  
              if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_desc.c_str(), &amp;inputs, &amp;outputs, NULL)) &lt; 0) {
                      log_averror(ret);
                      exit(1);
              }
  
              if ((ret = avfilter_graph_config(filter_graph, NULL)) &lt; 0) {
                      log_averror(ret);
                      exit(1);
              }
  
              /* Print summary of the sink buffer
               * Note: args buffer is reused to store channel layout string */
              AVFilterLink *outlink = buffersink_ctx-&gt;inputs[0];
              av_get_channel_layout_string(args, sizeof(args), -1, outlink-&gt;channel_layout);
              av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n",
                     (int) outlink-&gt;sample_rate,
                     (char *) av_x_if_null(av_get_sample_fmt_name((AVSampleFormat) outlink-&gt;format), "?"),
                     args);
              return 0;
      }
  
      /*
       *
       */
      int main(int argc, char **argv)
      {
              int ret;
              cout &lt;&lt; "Hello World" &lt;&lt; endl;
              printf("abcd");
              avcodec_register_all();
              av_register_all();
              avfilter_register_all();
  
              /* open input file, and allocate format context */
              if (avformat_open_input(&amp;in_fmt_ctx, inFileName.c_str(), NULL, NULL) &lt; 0) {
                      std::cout &lt;&lt; "error opening input file - " &lt;&lt; inFileName &lt;&lt; std::endl;
                      return -1;
              }
  
              /* retrieve stream information */
              if (avformat_find_stream_info(in_fmt_ctx, NULL) &lt; 0) {
                      std::cerr &lt;&lt; "Could not find stream information in the input file " &lt;&lt; inFileName &lt;&lt; std::endl;
              }
  
              /* Dump format details */
              printf("\n ---------------------------------------------------------------------- \n");
              av_dump_format(in_fmt_ctx, 0, inFileName.c_str(), 0);
              printf("\n ---------------------------------------------------------------------- \n");
              /* Choose a audio stream */
              select_stream = av_find_best_stream(in_fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &amp;dec_codec, 0);
  
              if (select_stream == AVERROR_STREAM_NOT_FOUND) {
                      std::cerr &lt;&lt; "No audio stream found" &lt;&lt; std::endl;
                      return -1;
              }
  
              if (select_stream == AVERROR_DECODER_NOT_FOUND) {
                      std::cerr &lt;&lt; "No suitable decoder found" &lt;&lt; std::endl;
                      return -1;
              }
  
              dec_ctx = in_fmt_ctx -&gt; streams[ select_stream] -&gt; codec;
              av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0);
  
              /* init the audio decoder */
              if ((ret = avcodec_open2(dec_ctx, dec_codec, NULL)) &lt; 0) {
                      av_log(NULL, AV_LOG_ERROR, "Cannot open audio decoder\n");
                      return ret;
              }
  
              /* allocate output context */
              ret = avformat_alloc_output_context2(&amp;out_fmt_ctx, NULL, NULL,
                                                   outFileName.c_str());
  
              if (ret &lt; 0) {
                      std::cerr &lt;&lt; "Could not create output context for the file " &lt;&lt; outFileName &lt;&lt; std::endl;
                      return -1;
              }
  
              /* find the encoder */
              enum AVCodecID codec_id = out_fmt_ctx -&gt; oformat -&gt; audio_codec;
              enc_codec = avcodec_find_encoder(codec_id);
  
              if (!(enc_codec)) {
                      std::cerr &lt;&lt; "Could not find encoder for - " &lt;&lt; avcodec_get_name(codec_id) &lt;&lt; std::endl;
                      return -1;
              }
  
              /* add a new stream */
              audio_st = avformat_new_stream(out_fmt_ctx, enc_codec);
  
              if (!audio_st) {
                      std::cerr &lt;&lt; "Could not add audio stream - " &lt;&lt; std::endl;
              }
  
              /* Initialise audio codec */
              audio_st -&gt; id = out_fmt_ctx -&gt; nb_streams - 1;
              enc_ctx = audio_st -&gt; codec;
              enc_ctx -&gt; codec_id = codec_id;
              enc_ctx -&gt; codec_type = AVMEDIA_TYPE_AUDIO;
              enc_ctx -&gt; bit_rate = target_bit_rate;
              enc_ctx -&gt; sample_rate = sample_rate;
              enc_ctx -&gt; sample_fmt = sample_fmt;
              enc_ctx -&gt; channels = channels;
              enc_ctx -&gt; channel_layout = av_get_default_channel_layout(enc_ctx -&gt; channels);
  
              /* Some formats want stream headers to be separate. */
              if (out_fmt_ctx -&gt; oformat -&gt; flags &amp; AVFMT_GLOBALHEADER) {
                      enc_ctx -&gt; flags |= CODEC_FLAG_GLOBAL_HEADER;
              }
  
              ret = avcodec_open2(out_fmt_ctx -&gt; streams[0] -&gt; codec, enc_codec, NULL);
  
              if (ret &lt; 0) {
                      std::cerr &lt;&lt; "Could not create codec context for the file " &lt;&lt; outFileName &lt;&lt; std::endl;
                      return -1;
              }
  
              /* Initialize filter */
              initialize_audio_filter();
  
              if (!(out_fmt_ctx -&gt; oformat -&gt; flags &amp; AVFMT_NOFILE)) {
                      int ret = avio_open(&amp; out_fmt_ctx -&gt; pb, outFileName.c_str(),
                                          AVIO_FLAG_WRITE);
  
                      if (ret &lt; 0) {
                              log_averror(ret);
                              return -1;
                      }
              }
  
              /* Write header */
              if (avformat_write_header(out_fmt_ctx, NULL) &lt; 0) {
                      if (ret &lt; 0) {
                              log_averror(ret);
                              return -1;
                      }
              }
  
              /* Allocate frame */
              pFrame = av_frame_alloc();
  
              if (!pFrame) {
                      std::cerr &lt;&lt; "Could not allocate frame\n";
                      return -1;
              }
  
              pFrameFiltered = av_frame_alloc();
  
              if (!pFrameFiltered) {
                      std::cerr &lt;&lt; "Could not allocate frame\n";
                      return -1;
              }
  
              av_init_packet(&amp;packet);
              packet.data = NULL;
              packet.size = 0;
  
              /* Read packet from the stream */
              while (av_read_frame(in_fmt_ctx, &amp;packet) &gt;= 0) {
                      if (packet.stream_index == select_stream) {
                              avcodec_get_frame_defaults(pFrame);
                              ret = avcodec_decode_audio4(dec_ctx, pFrame, &amp;got_frame, &amp;packet);
  
                              if (ret &lt; 0) {
                                      log_averror(ret);
                                      return ret;
                              }
  
                              printf("Decoded packet pts : %ld ", packet.pts);
                              printf("Frame Best Effor pts : %ld \n", pFrame-&gt;best_effort_timestamp);
                              /* Set frame pts */
                              pFrame -&gt; pts = av_frame_get_best_effort_timestamp(pFrame);
  
                              if (got_frame) {
                                      /* push the decoded frame into the filtergraph */
                                      ret = av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF);
  
                                      if (ret &lt; 0) {
                                              log_averror(ret);
                                              return ret;
                                      }
  
                                      /* pull filtered frames from the filtergraph */
                                      while (1) {
                                              ret = av_buffersink_get_frame(buffersink_ctx, pFrameFiltered);
  
                                              if ((ret == AVERROR(EAGAIN)) || (ret == AVERROR_EOF)) {
                                                      break;
                                              }
  
                                              if (ret &lt; 0) {
                                                      printf("Error while getting filtered frames from filtergraph\n");
                                                      log_averror(ret);
                                                      return -1;
                                              }
  
                                              /* Initialize the packets */
                                              AVPacket encodedPacket = {0};
                                              av_init_packet(&amp;encodedPacket);
                                              ret = avcodec_encode_audio2(out_fmt_ctx -&gt; streams[0] -&gt; codec, &amp;encodedPacket, pFrameFiltered, &amp;got_packet);
  
                                              if (!ret &amp;&amp; got_packet &amp;&amp; encodedPacket.size) {
                                                      /* Set correct pts and dts */
                                                      if (encodedPacket.pts != AV_NOPTS_VALUE) {
                                                              encodedPacket.pts = av_rescale_q(encodedPacket.pts, buffersink_ctx -&gt; inputs[0] -&gt; time_base,
                                                                                               out_fmt_ctx -&gt; streams[0] -&gt; time_base);
                                                      }
  
                                                      if (encodedPacket.dts != AV_NOPTS_VALUE) {
                                                              encodedPacket.dts = av_rescale_q(encodedPacket.dts, buffersink_ctx -&gt; inputs[0] -&gt; time_base,
                                                                                               out_fmt_ctx -&gt; streams[0] -&gt; time_base);
                                                      }
  
                                                      printf("Encoded packet pts %ld\n", encodedPacket.pts);
                                                      /* Write the compressed frame to the media file. */
                                                      ret = av_interleaved_write_frame(out_fmt_ctx, &amp;encodedPacket);
  
                                                      if (ret &lt; 0) {
                                                              log_averror(ret);
                                                              return -1;
                                                      }
                                              } else if (ret &lt; 0) {
                                                      log_averror(ret);
                                                      return -1;
                                              }
  
                                              av_frame_unref(pFrameFiltered);
                                      }
  
                                      av_frame_unref(pFrame);
                              }
                      }
              }
  
              /* Flush delayed frames from encoder*/
              got_packet=1;
              while (got_packet) {
                      AVPacket encodedPacket = {0};
                      av_init_packet(&amp;encodedPacket);
                      ret = avcodec_encode_audio2(out_fmt_ctx -&gt; streams[0] -&gt; codec, &amp;encodedPacket, NULL, &amp;got_packet);
  
                      if (!ret &amp;&amp; got_packet &amp;&amp; encodedPacket.size) {
                              /* Set correct pts and dts */
                              if (encodedPacket.pts != AV_NOPTS_VALUE) {
                                      encodedPacket.pts = av_rescale_q(encodedPacket.pts, buffersink_ctx -&gt; inputs[0] -&gt; time_base,
                                                                       out_fmt_ctx -&gt; streams[0] -&gt; time_base);
                              }
  
                              if (encodedPacket.dts != AV_NOPTS_VALUE) {
                                      encodedPacket.dts = av_rescale_q(encodedPacket.dts, buffersink_ctx -&gt; inputs[0] -&gt; time_base,
                                                                       out_fmt_ctx -&gt; streams[0] -&gt; time_base);
                              }
  
                              printf("Encoded packet pts %ld\n", encodedPacket.pts);
                              /* Write the compressed frame to the media file. */
                              ret = av_interleaved_write_frame(out_fmt_ctx, &amp;encodedPacket);
  
                              if (ret &lt; 0) {
                                      log_averror(ret);
                                      return -1;
                              }
                      } else if (ret &lt; 0) {
                              log_averror(ret);
                              return -1;
                      }
              }
  
              /* Write Trailer */
              av_write_trailer(out_fmt_ctx);
              avfilter_graph_free(&amp;filter_graph);
  
              if (dec_ctx)
                      avcodec_close(dec_ctx);
  
              avformat_close_input(&amp;in_fmt_ctx);
              av_frame_free(&amp;pFrame);
              av_frame_free(&amp;pFrameFiltered);
  
              if (!(out_fmt_ctx -&gt; oformat -&gt; flags &amp; AVFMT_NOFILE))
                      avio_close(out_fmt_ctx -&gt; pb);
              avcodec_close(out_fmt_ctx-&gt;streams[0]-&gt;codec);
              avformat_free_context(out_fmt_ctx);
              return 0;
      }
  </code></pre>
  
  <p>The audio file after transcoding is same duration as the input. But its completely noisy. Can somebody tell me what I am doing wrong here!</p>