func: static void do_audio_out(AVFormatContext *s, OutputStream *ost,
  
                           InputStream *ist, AVFrame *decoded_frame)
  
  {
  
      uint8_t *buftmp;
  
  
  
      int size_out, frame_bytes, resample_changed, ret;
  
      AVCodecContext *enc = ost->st->codec;
  
      AVCodecContext *dec = ist->st->codec;
  
      int osize = av_get_bytes_per_sample(enc->sample_fmt);
  
      int isize = av_get_bytes_per_sample(dec->sample_fmt);
  
      uint8_t *buf = decoded_frame->data[0];
  
      int size     = decoded_frame->nb_samples * dec->channels * isize;
  
      int out_linesize = 0;
  
      int buf_linesize = decoded_frame->linesize[0];
  
  
  
      get_default_channel_layouts(ost, ist);
  
  
  
      if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples, &out_linesize) < 0) {
  
          av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
  
          exit_program(1);
  
      }
  
  
  
      if (audio_sync_method > 1                      ||
  
          enc->channels       != dec->channels       ||
  
          enc->channel_layout != dec->channel_layout ||
  
          enc->sample_rate    != dec->sample_rate    ||
  
          dec->sample_fmt     != enc->sample_fmt)
  
          ost->audio_resample = 1;
  
  
  
      resample_changed = ost->resample_sample_fmt  != dec->sample_fmt ||
  
                         ost->resample_channels    != dec->channels   ||
  
                         ost->resample_channel_layout != dec->channel_layout ||
  
                         ost->resample_sample_rate != dec->sample_rate;
  
  
  
      if ((ost->audio_resample && !ost->avr) || resample_changed) {
  
          if (resample_changed) {
  
              av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:0x%"PRIx64" to rate:%d fmt:%s ch:%d chl:0x%"PRIx64"\n",
  
                     ist->file_index, ist->st->index,
  
                     ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt),
  
                     ost->resample_channels, ost->resample_channel_layout,
  
                     dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt),
  
                     dec->channels, dec->channel_layout);
  
              ost->resample_sample_fmt  = dec->sample_fmt;
  
              ost->resample_channels    = dec->channels;
  
              ost->resample_channel_layout = dec->channel_layout;
  
              ost->resample_sample_rate = dec->sample_rate;
  
              if (ost->avr)
  
                  avresample_close(ost->avr);
  
          }
  
          /* if audio_sync_method is >1 the resampler is needed for audio drift compensation */
  
          if (audio_sync_method <= 1 &&
  
              ost->resample_sample_fmt  == enc->sample_fmt &&
  
              ost->resample_channels    == enc->channels   &&
  
              ost->resample_channel_layout == enc->channel_layout &&
  
              ost->resample_sample_rate == enc->sample_rate) {
  
              ost->audio_resample = 0;
  
          } else if (ost->audio_resample) {
  
              if (!ost->avr) {
  
                  ost->avr = avresample_alloc_context();
  
                  if (!ost->avr) {
  
                      av_log(NULL, AV_LOG_FATAL, "Error allocating context for libavresample\n");
  
                      exit_program(1);
  
                  }
  
              }
  
  
  
              av_opt_set_int(ost->avr, "in_channel_layout",  dec->channel_layout, 0);
  
              av_opt_set_int(ost->avr, "in_sample_fmt",      dec->sample_fmt,     0);
  
              av_opt_set_int(ost->avr, "in_sample_rate",     dec->sample_rate,    0);
  
              av_opt_set_int(ost->avr, "out_channel_layout", enc->channel_layout, 0);
  
              av_opt_set_int(ost->avr, "out_sample_fmt",     enc->sample_fmt,     0);
  
              av_opt_set_int(ost->avr, "out_sample_rate",    enc->sample_rate,    0);
  
              if (audio_sync_method > 1)
  
                  av_opt_set_int(ost->avr, "force_resampling", 1, 0);
  
  
  
              /* if both the input and output formats are s16 or u8, use s16 as
  
                 the internal sample format */
  
              if (av_get_bytes_per_sample(dec->sample_fmt) <= 2 &&
  
                  av_get_bytes_per_sample(enc->sample_fmt) <= 2) {
  
                  av_opt_set_int(ost->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0);
  
              }
  
  
  
              ret = avresample_open(ost->avr);
  
              if (ret < 0) {
  
                  av_log(NULL, AV_LOG_FATAL, "Error opening libavresample\n");
  
                  exit_program(1);
  
              }
  
          }
  
      }
  
  
  
      if (audio_sync_method > 0) {
  
          double delta = get_sync_ipts(ost, ist->last_dts) * enc->sample_rate - ost->sync_opts -
  
                         av_fifo_size(ost->fifo) / (enc->channels * osize);
  
          int idelta = delta * dec->sample_rate / enc->sample_rate;
  
          int byte_delta = idelta * isize * dec->channels;
  
  
  
          // FIXME resample delay
  
          if (fabs(delta) > 50) {
  
              if (ist->is_start || fabs(delta) > audio_drift_threshold*enc->sample_rate) {
  
                  if (byte_delta < 0) {
  
                      byte_delta = FFMAX(byte_delta, -size);
  
                      size += byte_delta;
  
                      buf  -= byte_delta;
  
                      av_log(NULL, AV_LOG_VERBOSE, "discarding %d audio samples\n",
  
                             -byte_delta / (isize * dec->channels));
  
                      if (!size)
  
                          return;
  
                      ist->is_start = 0;
  
                  } else {
  
                      av_fast_malloc(&async_buf, &allocated_async_buf_size,
  
                                     byte_delta + size);
  
                      if (!async_buf) {
  
                          av_log(NULL, AV_LOG_FATAL, "Out of memory in do_audio_out\n");
  
                          exit_program(1);
  
                      }
  
  
  
                      if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta, &out_linesize) < 0) {
  
                          av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
  
                          exit_program(1);
  
                      }
  
                      ist->is_start = 0;
  
  
  
                      generate_silence(async_buf, dec->sample_fmt, byte_delta);
  
                      memcpy(async_buf + byte_delta, buf, size);
  
                      buf = async_buf;
  
                      size += byte_delta;
  
                      buf_linesize = allocated_async_buf_size;
  
                      av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", idelta);
  
                  }
  
              } else if (audio_sync_method > 1) {
  
                  int comp = av_clip(delta, -audio_sync_method, audio_sync_method);
  
                  av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n",
  
                         delta, comp, enc->sample_rate);
  
  //                fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
  
                  avresample_set_compensation(ost->avr, comp, enc->sample_rate);
  
              }
  
          }
  
      } else if (audio_sync_method == 0)
  
          ost->sync_opts = lrintf(get_sync_ipts(ost, ist->last_dts) * enc->sample_rate) -
  
                                  av_fifo_size(ost->fifo) / (enc->channels * osize); // FIXME wrong
  
  
  
      if (ost->audio_resample) {
  
          buftmp = audio_buf;
  
          size_out = avresample_convert(ost->avr, (void **)&buftmp,
  
                                        allocated_audio_buf_size, out_linesize,
  
                                        (void **)&buf, buf_linesize,
  
                                        size / (dec->channels * isize));
  
          size_out = size_out * enc->channels * osize;
  
      } else {
  
          buftmp = buf;
  
          size_out = size;
  
      }
  
  
  
      /* now encode as many frames as possible */
  
      if (!(enc->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
  
          /* output resampled raw samples */
  
          if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) {
  
              av_log(NULL, AV_LOG_FATAL, "av_fifo_realloc2() failed\n");
  
              exit_program(1);
  
          }
  
          av_fifo_generic_write(ost->fifo, buftmp, size_out, NULL);
  
  
  
          frame_bytes = enc->frame_size * osize * enc->channels;
  
  
  
          while (av_fifo_size(ost->fifo) >= frame_bytes) {
  
              av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL);
  
              encode_audio_frame(s, ost, audio_buf, frame_bytes);
  
          }
  
      } else {
  
          encode_audio_frame(s, ost, buftmp, size_out);
  
      }
  
  }
  