title: Sample rate & format conversion with LibAV API (libavresample)
body: <p>I'm writing a code which will merge multiple audios (with different formats) and create a single audio. When i set the encoder <em>sample_rate</em> and <em>sample_fmt</em> same with the input videos i have no problem merging the audios. However as obvious, all of the input audio formats are not same with the output format, so i have to do format conversion. I tried to use "avresample" for this purpose but could not manage to encode the output frames when <em>sample_rate</em> and <em>sample_fmt</em> are different for input&amp;output.</p>
  
  <p>It might be done manually by hand (by sample dropping, interpolation etc.), but since libav provides a conversion api i think this can (and may be should for tidyness) be done automatically.</p>
  
  <p>Here is how i set encoder and resampling context params:</p>
  
  <pre><code>AVCodecContext* avAudioEncoder = outputAudioStream-&gt;codec;
  AVCodec * audioEncoder = avcodec_find_encoder(AV_CODEC_ID_MP3);
  
  avcodec_get_context_defaults3(avAudioEncoder, audioEncoder);
  
  avAudioEncoder-&gt;sample_fmt = AV_SAMPLE_FMT_S16P;
  avAudioEncoder-&gt;sample_rate = 48000;
  avAudioEncoder-&gt;channels = 2;
  avAudioEncoder-&gt;time_base.num = 1;
  avAudioEncoder-&gt;time_base.den = 48000;
  avAudioEncoder-&gt;strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
  
  if (outputAVFormat-&gt;oformat-&gt;flags &amp; AVFMT_GLOBALHEADER)
  {
      avAudioEncoder-&gt;flags |= CODEC_FLAG_GLOBAL_HEADER;
  }
  
  avcodec_open2(avAudioEncoder, audioEncoder, nullptr);
  
  std::shared_ptr&lt;AVAudioResampleContext&gt; avAudioResampleContext(avresample_alloc_context(), [](AVAudioResampleContext * avARC){avresample_close(avARC), avresample_free(&amp;avARC); });
  
  av_opt_set_int(avAudioResampleContext.get(), "in_channel_layout", 2, 0);
  av_opt_set_int(avAudioResampleContext.get(), "in_sample_rate", 44100, 0);
  av_opt_set_int(avAudioResampleContext.get(), "in_sample_fmt", AV_SAMPLE_FMT_S16P, 0);
  av_opt_set_int(avAudioResampleContext.get(), "out_channel_layout", avAudioEncoder-&gt;channels, 0);
  av_opt_set_int(avAudioResampleContext.get(), "out_sample_rate", avAudioEncoder-&gt;sample_rate, 0);
  av_opt_set_int(avAudioResampleContext.get(), "out_sample_fmt", avAudioEncoder-&gt;sample_fmt, 0);
  </code></pre>
  
  <p>And here is how i read &amp; encode the frames</p>
  
  <pre><code>...
  int result = avcodec_decode_audio4(avAudioDecoder.get(), audioFrame.get(), &amp;isFrameAvailable, &amp;decodingPacket);
  ...
  if (isFrameAvailable)
  {
      decodingPacket.size -= result;
      decodingPacket.data += result;
  
      encodeAudioFrame-&gt;format = outputAudioStream-&gt;codec-&gt;sample_fmt;
      encodeAudioFrame-&gt;channel_layout = outputAudioStream-&gt;codec-&gt;channel_layout;
  
      auto available = avresample_available(avAudioResampleContext.get());
      auto delay = avresample_get_delay(avAudioResampleContext.get());
  
      encodeAudioFrame-&gt;nb_samples =  available + av_rescale_rnd( delay + audioFrame-&gt;nb_samples, avAudioEncoder-&gt;sample_rate, audioStream-&gt;codec-&gt;sample_rate, AV_ROUND_ZERO);
      int linesize;
      av_samples_alloc(encodeAudioFrame-&gt;data, &amp;linesize, avAudioEncoder-&gt;channels, encodeAudioFrame-&gt;nb_samples, avAudioEncoder-&gt;sample_fmt, 1);
      encodeAudioFrame-&gt;linesize[0] = linesize;
  
      avresample_convert(avAudioResampleContext.get(), nullptr, encodeAudioFrame-&gt;linesize[0], encodeAudioFrame-&gt;nb_samples, &amp;audioFrame-&gt;data[0], audioFrame-&gt;linesize[0], audioFrame-&gt;nb_samples*outputAudioStream-&gt;codec-&gt;channels); 
  
  
      std::shared_ptr&lt;AVPacket&gt; outPacket(new AVPacket, [](AVPacket* p){ av_free_packet(p); delete p; });
      av_init_packet(outPacket.get());
      outPacket-&gt;data = nullptr;
      outPacket-&gt;size = 0;
  
      while (avresample_available(avAudioResampleContext.get()) &gt;= encodeAudioFrame-&gt;nb_samples)
      {
          avresample_read(avAudioResampleContext.get(), &amp;encodeAudioFrame-&gt;data[0], encodeAudioFrame-&gt;nb_samples*outputAudioStream-&gt;codec-&gt;channels);
  
  
          encodeAudioFrame-&gt;pts = av_rescale_q(++encodedAudioPts, outputAudioStream-&gt;codec-&gt;time_base, outputAudioStream-&gt;time_base);
  
          encodeAudioFrame-&gt;pts *= avAudioEncoder-&gt;frame_size;
          ... 
          auto ret = avcodec_encode_audio2(avAudioEncoder, outPacketPtr, encodeAudioFramePtr, &amp;got_output);
          ...
      }
  </code></pre>
  
  <p>It seems i can't use avresample properly, but i could not figure out how to solve this problem. Any help will be appreciated.</p>