Merge commit '56ee3f9de7b9f6090d599a27d33a392890a2f7b8'
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 6 Aug 2013 08:25:32 +0000 (10:25 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 6 Aug 2013 08:25:32 +0000 (10:25 +0200)
* commit '56ee3f9de7b9f6090d599a27d33a392890a2f7b8':
  avconv: distinguish between -ss 0 and -ss not being used

Conflicts:
ffmpeg.c
ffmpeg_opt.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
ffmpeg.c
ffmpeg_filter.c
ffmpeg_opt.c

diff --cc ffmpeg.c
+++ b/ffmpeg.c
@@@ -750,10 -454,8 +750,12 @@@ static void do_subtitle_out(AVFormatCon
      else
          nb = 1;
  
-     pts = sub->pts - output_files[ost->file_index]->start_time;
 +    /* shift timestamp to honor -ss and make check_recording_time() work with -t */
++    pts = sub->pts;
++    if (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE)
++        pts -= output_files[ost->file_index]->start_time;
      for (i = 0; i < nb; i++) {
 -        ost->sync_opts = av_rescale_q(pts, ist->st->time_base, enc->time_base);
 +        ost->sync_opts = av_rescale_q(pts, AV_TIME_BASE_Q, enc->time_base);
          if (!check_recording_time(ost))
              return;
  
@@@ -1031,90 -626,120 +1033,91 @@@ static void do_video_stats(OutputStrea
      }
  }
  
 -/*
 - * Read one frame for lavfi output for ost and encode it.
 - */
 -static int poll_filter(OutputStream *ost)
 -{
 -    OutputFile    *of = output_files[ost->file_index];
 -    AVFrame *filtered_frame = NULL;
 -    int frame_size, ret;
 -
 -    if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
 -        return AVERROR(ENOMEM);
 -    } else
 -        avcodec_get_frame_defaults(ost->filtered_frame);
 -    filtered_frame = ost->filtered_frame;
 -
 -    if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
 -        !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE))
 -        ret = av_buffersink_get_samples(ost->filter->filter, filtered_frame,
 -                                         ost->st->codec->frame_size);
 -    else
 -        ret = av_buffersink_get_frame(ost->filter->filter, filtered_frame);
 -
 -    if (ret < 0)
 -        return ret;
 -
 -    if (filtered_frame->pts != AV_NOPTS_VALUE) {
 -        int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
 -        filtered_frame->pts = av_rescale_q(filtered_frame->pts,
 -                                           ost->filter->filter->inputs[0]->time_base,
 -                                           ost->st->codec->time_base) -
 -                              av_rescale_q(start_time,
 -                                           AV_TIME_BASE_Q,
 -                                           ost->st->codec->time_base);
 -    }
 -
 -    switch (ost->filter->filter->inputs[0]->type) {
 -    case AVMEDIA_TYPE_VIDEO:
 -        if (!ost->frame_aspect_ratio)
 -            ost->st->codec->sample_aspect_ratio = filtered_frame->sample_aspect_ratio;
 -
 -        do_video_out(of->ctx, ost, filtered_frame, &frame_size);
 -        if (vstats_filename && frame_size)
 -            do_video_stats(ost, frame_size);
 -        break;
 -    case AVMEDIA_TYPE_AUDIO:
 -        do_audio_out(of->ctx, ost, filtered_frame);
 -        break;
 -    default:
 -        // TODO support subtitle filters
 -        av_assert0(0);
 -    }
 -
 -    av_frame_unref(filtered_frame);
 -
 -    return 0;
 -}
 -
 -/*
 - * Read as many frames from possible from lavfi and encode them.
 +/**
 + * Get and encode new output from any of the filtergraphs, without causing
 + * activity.
   *
 - * Always read from the active stream with the lowest timestamp. If no frames
 - * are available for it then return EAGAIN and wait for more input. This way we
 - * can use lavfi sources that generate unlimited amount of frames without memory
 - * usage exploding.
 + * @return  0 for success, <0 for severe errors
   */
 -static int poll_filters(void)
 +static int reap_filters(void)
  {
 -    int i, j, ret = 0;
 -
 -    while (ret >= 0 && !received_sigterm) {
 -        OutputStream *ost = NULL;
 -        int64_t min_pts = INT64_MAX;
 +    AVFrame *filtered_frame = NULL;
 +    int i;
 +    int64_t frame_pts;
  
 -        /* choose output stream with the lowest timestamp */
 -        for (i = 0; i < nb_output_streams; i++) {
 -            int64_t pts = output_streams[i]->sync_opts;
 +    /* Reap all buffers present in the buffer sinks */
 +    for (i = 0; i < nb_output_streams; i++) {
 +        OutputStream *ost = output_streams[i];
 +        OutputFile    *of = output_files[ost->file_index];
 +        int ret = 0;
  
 -            if (!output_streams[i]->filter || output_streams[i]->finished)
 -                continue;
 +        if (!ost->filter)
 +            continue;
  
 -            pts = av_rescale_q(pts, output_streams[i]->st->codec->time_base,
 -                               AV_TIME_BASE_Q);
 -            if (pts < min_pts) {
 -                min_pts = pts;
 -                ost = output_streams[i];
 +        if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
 +            return AVERROR(ENOMEM);
 +        } else
 +            avcodec_get_frame_defaults(ost->filtered_frame);
 +        filtered_frame = ost->filtered_frame;
 +
 +        while (1) {
 +            ret = av_buffersink_get_frame_flags(ost->filter->filter, filtered_frame,
 +                                               AV_BUFFERSINK_FLAG_NO_REQUEST);
 +            if (ret < 0) {
 +                if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
 +                    av_log(NULL, AV_LOG_WARNING,
 +                           "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret));
 +                }
 +                break;
              }
 -        }
 -
 -        if (!ost)
 -            break;
 -
 -        ret = poll_filter(ost);
 +            frame_pts = AV_NOPTS_VALUE;
 +            if (filtered_frame->pts != AV_NOPTS_VALUE) {
++                int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
 +                filtered_frame->pts = frame_pts = av_rescale_q(filtered_frame->pts,
 +                                                ost->filter->filter->inputs[0]->time_base,
 +                                                ost->st->codec->time_base) -
-                                     av_rescale_q(of->start_time,
++                                    av_rescale_q(start_time,
 +                                                AV_TIME_BASE_Q,
 +                                                ost->st->codec->time_base);
 +            }
 +            //if (ost->source_index >= 0)
 +            //    *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold
  
 -        if (ret == AVERROR_EOF) {
 -            OutputFile *of = output_files[ost->file_index];
  
 -            ost->finished = 1;
 +            switch (ost->filter->filter->inputs[0]->type) {
 +            case AVMEDIA_TYPE_VIDEO:
 +                filtered_frame->pts = frame_pts;
 +                if (!ost->frame_aspect_ratio.num)
 +                    ost->st->codec->sample_aspect_ratio = filtered_frame->sample_aspect_ratio;
  
 -            if (of->shortest) {
 -                for (j = 0; j < of->ctx->nb_streams; j++)
 -                    output_streams[of->ost_index + j]->finished = 1;
 +                do_video_out(of->ctx, ost, filtered_frame);
 +                break;
 +            case AVMEDIA_TYPE_AUDIO:
 +                filtered_frame->pts = frame_pts;
 +                if (!(ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE) &&
 +                    ost->st->codec->channels != av_frame_get_channels(filtered_frame)) {
 +                    av_log(NULL, AV_LOG_ERROR,
 +                           "Audio filter graph output is not normalized and encoder does not support parameter changes\n");
 +                    break;
 +                }
 +                do_audio_out(of->ctx, ost, filtered_frame);
 +                break;
 +            default:
 +                // TODO support subtitle filters
 +                av_assert0(0);
              }
  
 -            ret = 0;
 -        } else if (ret == AVERROR(EAGAIN))
 -            return 0;
 +            av_frame_unref(filtered_frame);
 +        }
      }
  
 -    return ret;
 +    return 0;
  }
  
 -static void print_report(int is_last_report, int64_t timer_start)
 +static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
  {
      char buf[1024];
 +    AVBPrint buf_script;
      OutputStream *ost;
      AVFormatContext *oc;
      int64_t total_size;
@@@ -1377,7 -949,7 +1380,7 @@@ static int check_output_constraints(Inp
      if (ost->source_index != ist_index)
          return 0;
  
-     if (of->start_time && ist->pts < of->start_time)
 -    if (of->start_time != AV_NOPTS_VALUE && ist->last_dts < of->start_time)
++    if (of->start_time != AV_NOPTS_VALUE && ist->pts < of->start_time)
          return 0;
  
      return 1;
  static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt)
  {
      OutputFile *of = output_files[ost->file_index];
-     int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
-     int64_t ist_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ist->st->time_base);
+     int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
+     int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base);
++    int64_t ist_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ist->st->time_base);
 +    AVPicture pict;
      AVPacket opkt;
  
      av_init_packet(&opkt);
          !ost->copy_initial_nonkeyframes)
          return;
  
-         if (!ost->frame_number && ist->pts < of->start_time &&
 +    if (pkt->pts == AV_NOPTS_VALUE) {
++        if (!ost->frame_number && ist->pts < start_time &&
 +            !ost->copy_prior_start)
 +            return;
 +    } else {
 +        if (!ost->frame_number && pkt->pts < ist_tb_start_time &&
 +            !ost->copy_prior_start)
 +            return;
 +    }
 +
      if (of->recording_time != INT64_MAX &&
-         ist->pts >= of->recording_time + of->start_time) {
 -        ist->last_dts >= of->recording_time + start_time) {
 -        ost->finished = 1;
++        ist->pts >= of->recording_time + start_time) {
 +        close_output_stream(ost);
          return;
      }
  
diff --cc ffmpeg_filter.c
@@@ -286,13 -183,9 +286,13 @@@ static int insert_trim(OutputStream *os
      char filter_name[128];
      int ret = 0;
  
-     if (of->recording_time == INT64_MAX && !of->start_time)
+     if (of->recording_time == INT64_MAX && of->start_time == AV_NOPTS_VALUE)
          return 0;
  
-     if (!of->start_time)
 +    // Use with duration and without output starttime is buggy with trim filters
++    if (of->start_time == AV_NOPTS_VALUE)
 +        return 0;
 +
      trim = avfilter_get_by_name(name);
      if (!trim) {
          av_log(NULL, AV_LOG_ERROR, "%s filter not present, cannot limit "
diff --cc ffmpeg_opt.c
@@@ -138,15 -112,9 +138,16 @@@ static void init_options(OptionsContex
  {
      memset(o, 0, sizeof(*o));
  
 +    if (!is_input && recording_time != INT64_MAX) {
 +        o->recording_time = recording_time;
 +        av_log(NULL, AV_LOG_WARNING,
 +                "-t is not an input option, keeping it for the next output;"
 +                " consider fixing your command line.\n");
 +    } else
 +        o->recording_time = INT64_MAX;
 +    o->stop_time = INT64_MAX;
      o->mux_max_delay  = 0.7;
 -    o->recording_time = INT64_MAX;
+     o->start_time     = AV_NOPTS_VALUE;
      o->limit_filesize = UINT64_MAX;
      o->chapters_input_file = INT_MAX;
  }
@@@ -830,8 -665,8 +831,8 @@@ static int open_input_file(OptionsConte
          timestamp += ic->start_time;
  
      /* if seeking requested, we execute it */
-     if (o->start_time != 0) {
+     if (o->start_time != AV_NOPTS_VALUE) {
 -        ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
 +        ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, timestamp, 0);
          if (ret < 0) {
              av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
                     filename, (double)timestamp / AV_TIME_BASE);
@@@ -1580,20 -1303,6 +1582,21 @@@ static int open_output_file(OptionsCont
          exit_program(1);
      }
  
-         if (o->stop_time <= o->start_time) {
 +    if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
 +        o->stop_time = INT64_MAX;
 +        av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
 +    }
 +
 +    if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) {
-             o->recording_time = o->stop_time - o->start_time;
++        int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time;
++        if (o->stop_time <= start_time) {
 +            av_log(NULL, AV_LOG_WARNING, "-to value smaller than -ss; ignoring -to.\n");
 +            o->stop_time = INT64_MAX;
 +        } else {
++            o->recording_time = o->stop_time - start_time;
 +        }
 +    }
 +
      GROW_ARRAY(output_files, nb_output_files);
      of = av_mallocz(sizeof(*of));
      if (!of)