Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 18 Jan 2012 01:07:42 +0000 (02:07 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 18 Jan 2012 01:08:12 +0000 (02:08 +0100)
* qatar/master:
  tta: cast output data pointer to the correct type
  avconv: fix -frames for video encoders with delay.

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
avconv.c
ffmpeg.c
libavcodec/tta.c

diff --cc avconv.c
Simple merge
diff --cc ffmpeg.c
+++ b/ffmpeg.c
@@@ -974,143 -637,152 +974,155 @@@ static void choose_pixel_fmt(AVStream *
      }
  }
  
 -static OutputStream *new_output_stream(AVFormatContext *oc, int file_idx, AVCodec *codec)
 +static double get_sync_ipts(const OutputStream *ost)
  {
 -    OutputStream *ost;
 -    AVStream *st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0);
 -    int idx      = oc->nb_streams - 1;
 -
 -    if (!st) {
 -        av_log(NULL, AV_LOG_ERROR, "Could not alloc stream.\n");
 -        exit_program(1);
 -    }
 -
 -    output_streams_for_file[file_idx] =
 -        grow_array(output_streams_for_file[file_idx],
 -                   sizeof(*output_streams_for_file[file_idx]),
 -                   &nb_output_streams_for_file[file_idx],
 -                   oc->nb_streams);
 -    ost = output_streams_for_file[file_idx][idx] =
 -        av_mallocz(sizeof(OutputStream));
 -    if (!ost) {
 -        fprintf(stderr, "Could not alloc output stream\n");
 -        exit_program(1);
 -    }
 -    ost->file_index = file_idx;
 -    ost->index = idx;
 -    ost->st    = st;
 -    ost->enc   = codec;
 -    if (codec)
 -        ost->opts  = filter_codec_opts(codec_opts, codec->id, oc, st);
 -
 -    avcodec_get_context_defaults3(st->codec, codec);
 -
 -    ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
 -    return ost;
 +    const InputStream *ist = ost->sync_ist;
 +    OutputFile *of = &output_files[ost->file_index];
 +    return (double)(ist->pts - of->start_time) / AV_TIME_BASE;
  }
  
 -static int read_avserver_streams(AVFormatContext *s, const char *filename)
 +static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
  {
 -    int i, err;
 -    AVFormatContext *ic = NULL;
 -
 -    err = avformat_open_input(&ic, filename, NULL, NULL);
 -    if (err < 0)
 -        return err;
 -    /* copy stream format */
 -    for(i=0;i<ic->nb_streams;i++) {
 -        AVStream *st;
 -        OutputStream *ost;
 -        AVCodec *codec;
 -
 -        codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
 -        ost   = new_output_stream(s, nb_output_files, codec);
 -        st    = ost->st;
 +    AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
 +    AVCodecContext          *avctx = ost->st->codec;
 +    int ret;
  
 -        // FIXME: a more elegant solution is needed
 -        memcpy(st, ic->streams[i], sizeof(AVStream));
 -        st->info = NULL;
 -        avcodec_copy_context(st->codec, ic->streams[i]->codec);
++    /*
++     * Audio encoders may split the packets --  #frames in != #packets out.
++     * But there is no reordering, so we can limit the number of output packets
++     * by simply dropping them here.
++     * Counting encoded video frames needs to be done separately because of
++     * reordering, see do_video_out()
++     */
++    if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) {
++        if (ost->frame_number >= ost->max_frames)
++            return;
++        ost->frame_number++;
++    }
 -        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
 -            if (audio_stream_copy) {
 -                st->stream_copy = 1;
 -            } else
 -                choose_sample_fmt(st, codec);
 -        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 -            if (video_stream_copy) {
 -                st->stream_copy = 1;
 -            } else
 -                choose_pixel_fmt(st, codec);
 +    while (bsfc) {
 +        AVPacket new_pkt = *pkt;
 +        int a = av_bitstream_filter_filter(bsfc, avctx, NULL,
 +                                           &new_pkt.data, &new_pkt.size,
 +                                           pkt->data, pkt->size,
 +                                           pkt->flags & AV_PKT_FLAG_KEY);
 +        if (a > 0) {
 +            av_free_packet(pkt);
 +            new_pkt.destruct = av_destruct_packet;
 +        } else if (a < 0) {
 +            av_log(NULL, AV_LOG_ERROR, "Failed to open bitstream filter %s for stream %d with codec %s",
 +                   bsfc->filter->name, pkt->stream_index,
 +                   avctx->codec ? avctx->codec->name : "copy");
 +            print_error("", a);
 +            if (exit_on_error)
 +                exit_program(1);
          }
 +        *pkt = new_pkt;
 +
 +        bsfc = bsfc->next;
      }
  
 -    av_close_input_file(ic);
 -    return 0;
 +    ret = av_interleaved_write_frame(s, pkt);
 +    if (ret < 0) {
 +        print_error("av_interleaved_write_frame()", ret);
 +        exit_program(1);
 +    }
-     ost->frame_number++;
  }
  
 -static double
 -get_sync_ipts(const OutputStream *ost)
 +static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_t size)
  {
 -    const InputStream *ist = ost->sync_ist;
 -    return (double)(ist->pts - start_time)/AV_TIME_BASE;
 +    int fill_char = 0x00;
 +    if (sample_fmt == AV_SAMPLE_FMT_U8)
 +        fill_char = 0x80;
 +    memset(buf, fill_char, size);
  }
  
 -static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
 -    int ret;
 +static int encode_audio_frame(AVFormatContext *s, OutputStream *ost,
 +                              const uint8_t *buf, int buf_size)
 +{
 +    AVCodecContext *enc = ost->st->codec;
 +    AVFrame *frame = NULL;
 +    AVPacket pkt;
 +    int ret, got_packet;
  
 -    while(bsfc){
 -        AVPacket new_pkt= *pkt;
 -        int a= av_bitstream_filter_filter(bsfc, avctx, NULL,
 -                                          &new_pkt.data, &new_pkt.size,
 -                                          pkt->data, pkt->size,
 -                                          pkt->flags & AV_PKT_FLAG_KEY);
 -        if(a>0){
 -            av_free_packet(pkt);
 -            new_pkt.destruct= av_destruct_packet;
 -        } else if(a<0){
 -            fprintf(stderr, "%s failed for stream %d, codec %s",
 -                    bsfc->filter->name, pkt->stream_index,
 -                    avctx->codec ? avctx->codec->name : "copy");
 -            print_error("", a);
 -            if (exit_on_error)
 +    av_init_packet(&pkt);
 +    pkt.data = NULL;
 +    pkt.size = 0;
 +
 +    if (buf) {
 +        if (!ost->output_frame) {
 +            ost->output_frame = avcodec_alloc_frame();
 +            if (!ost->output_frame) {
 +                av_log(NULL, AV_LOG_FATAL, "out-of-memory in encode_audio_frame()\n");
                  exit_program(1);
 +            }
 +        }
 +        frame = ost->output_frame;
 +        if (frame->extended_data != frame->data)
 +            av_freep(&frame->extended_data);
 +        avcodec_get_frame_defaults(frame);
 +
 +        frame->nb_samples  = buf_size /
 +                             (enc->channels * av_get_bytes_per_sample(enc->sample_fmt));
 +        if ((ret = avcodec_fill_audio_frame(frame, enc->channels, enc->sample_fmt,
 +                                            buf, buf_size, 1)) < 0) {
 +            av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
 +            exit_program(1);
          }
 -        *pkt= new_pkt;
 -
 -        bsfc= bsfc->next;
      }
  
 -    ret= av_interleaved_write_frame(s, pkt);
 -    if(ret < 0){
 -        print_error("av_interleaved_write_frame()", ret);
 +    got_packet = 0;
 +    if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
 +        av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
          exit_program(1);
      }
 -}
  
 -#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
 +    ret = pkt.size;
  
 -static void do_audio_out(AVFormatContext *s,
 -                         OutputStream *ost,
 -                         InputStream *ist,
 -                         unsigned char *buf, int size)
 +    if (got_packet) {
 +        pkt.stream_index = ost->index;
 +        if (pkt.pts != AV_NOPTS_VALUE)
 +            pkt.pts      = av_rescale_q(pkt.pts,      enc->time_base, ost->st->time_base);
 +        if (pkt.duration > 0)
 +            pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
 +
 +        write_frame(s, &pkt, ost);
 +
 +        audio_size += pkt.size;
 +
 +        av_free_packet(&pkt);
 +    }
 +
 +    if (frame)
 +        ost->sync_opts += frame->nb_samples;
 +
 +    return ret;
 +}
 +
 +static void do_audio_out(AVFormatContext *s, OutputStream *ost,
 +                         InputStream *ist, AVFrame *decoded_frame)
  {
      uint8_t *buftmp;
 -    int64_t audio_out_size, audio_buf_size;
 -    int64_t allocated_for_size= size;
 +    int64_t audio_buf_size, size_out;
  
 -    int size_out, frame_bytes, ret, resample_changed;
 -    AVCodecContext *enc= ost->st->codec;
 -    AVCodecContext *dec= ist->st->codec;
 +    int frame_bytes, resample_changed;
 +    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);
 -    const int coded_bps = av_get_bits_per_sample(enc->codec->id);
 +    uint8_t *buf = decoded_frame->data[0];
 +    int size     = decoded_frame->nb_samples * dec->channels * isize;
 +    int64_t allocated_for_size = size;
  
  need_realloc:
 -    audio_buf_size= (allocated_for_size + isize*dec->channels - 1) / (isize*dec->channels);
 -    audio_buf_size= (audio_buf_size*enc->sample_rate + dec->sample_rate) / dec->sample_rate;
 -    audio_buf_size= audio_buf_size*2 + 10000; //safety factors for the deprecated resampling API
 -    audio_buf_size= FFMAX(audio_buf_size, enc->frame_size);
 -    audio_buf_size*= osize*enc->channels;
 -
 -    audio_out_size= FFMAX(audio_buf_size, enc->frame_size * osize * enc->channels);
 -    if(coded_bps > 8*osize)
 -        audio_out_size= audio_out_size * coded_bps / (8*osize);
 -    audio_out_size += FF_MIN_BUFFER_SIZE;
 -
 -    if(audio_out_size > INT_MAX || audio_buf_size > INT_MAX){
 -        fprintf(stderr, "Buffer sizes too large\n");
 +    audio_buf_size  = (allocated_for_size + isize * dec->channels - 1) / (isize * dec->channels);
 +    audio_buf_size  = (audio_buf_size * enc->sample_rate + dec->sample_rate) / dec->sample_rate;
 +    audio_buf_size  = audio_buf_size * 2 + 10000; // safety factors for the deprecated resampling API
 +    audio_buf_size  = FFMAX(audio_buf_size, enc->frame_size);
 +    audio_buf_size *= osize * enc->channels;
 +
 +    if (audio_buf_size > INT_MAX) {
 +        av_log(NULL, AV_LOG_FATAL, "Buffer sizes too large\n");
          exit_program(1);
      }
  
@@@ -1568,6 -1274,7 +1580,12 @@@ static void do_video_out(AVFormatContex
              }
          }
          ost->sync_opts++;
++        /*
++         * For video, number of frames in == number of packets out.
++         * But there may be reordering, so we can't throw away frames on encoder
++         * flush, we need to limit them here, before they go into encoder.
++         */
+         ost->frame_number++;
      }
  }
  
Simple merge