X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=bbd21b6d4bb0c48e3e3417c9ab85c0eb1079950a;hb=8a6ae87b9915ad82de4d20a056fe67bc17e16de7;hp=acaa523170fb475e00a6069cb3c52b5335975ead;hpb=5c7e9e16c961f1f7258734426afac3cee4349580;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index acaa523170f..bbd21b6d4bb 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -109,6 +109,15 @@ const int program_birth_year = 2000; static FILE *vstats_file; +const char *const forced_keyframes_const_names[] = { + "n", + "n_forced", + "prev_forced_n", + "prev_forced_t", + "t", + NULL +}; + static void do_video_stats(OutputStream *ost, int frame_size); static int64_t getutime(void); @@ -437,6 +446,7 @@ static void exit_program(void) avcodec_free_frame(&output_streams[i]->filtered_frame); av_freep(&output_streams[i]->forced_keyframes); + av_expr_free(output_streams[i]->forced_keyframes_pexpr); av_freep(&output_streams[i]->avfilter); av_freep(&output_streams[i]->logfile_prefix); av_freep(&output_streams[i]); @@ -873,8 +883,9 @@ static void do_video_out(AVFormatContext *s, video_size += pkt.size; write_frame(s, &pkt, ost); } else { - int got_packet; + int got_packet, forced_keyframe = 0; AVFrame big_picture; + double pts_time; big_picture = *in_picture; /* better than nothing: use input picture interlaced @@ -898,11 +909,41 @@ static void do_video_out(AVFormatContext *s, big_picture.quality = ost->st->codec->global_quality; if (!enc->me_threshold) big_picture.pict_type = 0; + + pts_time = big_picture.pts != AV_NOPTS_VALUE ? + big_picture.pts * av_q2d(enc->time_base) : NAN; if (ost->forced_kf_index < ost->forced_kf_count && big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) { - big_picture.pict_type = AV_PICTURE_TYPE_I; ost->forced_kf_index++; + forced_keyframe = 1; + } else if (ost->forced_keyframes_pexpr) { + double res; + ost->forced_keyframes_expr_const_values[FKF_T] = pts_time; + res = av_expr_eval(ost->forced_keyframes_pexpr, + ost->forced_keyframes_expr_const_values, NULL); + av_dlog(NULL, "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n", + ost->forced_keyframes_expr_const_values[FKF_N], + ost->forced_keyframes_expr_const_values[FKF_N_FORCED], + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N], + ost->forced_keyframes_expr_const_values[FKF_T], + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T], + res); + if (res) { + forced_keyframe = 1; + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = + ost->forced_keyframes_expr_const_values[FKF_N]; + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = + ost->forced_keyframes_expr_const_values[FKF_T]; + ost->forced_keyframes_expr_const_values[FKF_N_FORCED] += 1; + } + + ost->forced_keyframes_expr_const_values[FKF_N] += 1; + } + if (forced_keyframe) { + big_picture.pict_type = AV_PICTURE_TYPE_I; + av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); } + update_benchmark(NULL); ret = avcodec_encode_video2(enc, &pkt, &big_picture, &got_packet); update_benchmark("encode_video %d.%d", ost->file_index, ost->index); @@ -1443,6 +1484,8 @@ int guess_input_channel_layout(InputStream *ist) if (!dec->channel_layout) { char layout_name[256]; + if (dec->channels > ist->guess_layout_max) + return 0; dec->channel_layout = av_get_default_channel_layout(dec->channels); if (!dec->channel_layout) return 0; @@ -1870,7 +1913,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) static void print_sdp(void) { - char sdp[2048]; + char sdp[16384]; int i; AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files); @@ -1931,19 +1974,25 @@ static InputStream *get_input_stream(OutputStream *ost) return NULL; } +static int compare_int64(const void *a, const void *b) +{ + int64_t va = *(int64_t *)a, vb = *(int64_t *)b; + return va < vb ? -1 : va > vb ? +1 : 0; +} + static void parse_forced_key_frames(char *kf, OutputStream *ost, AVCodecContext *avctx) { char *p; - int n = 1, i; - int64_t t; + int n = 1, i, size, index = 0; + int64_t t, *pts; for (p = kf; *p; p++) if (*p == ',') n++; - ost->forced_kf_count = n; - ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n); - if (!ost->forced_kf_pts) { + size = n; + pts = av_malloc(sizeof(*pts) * size); + if (!pts) { av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); exit(1); } @@ -1955,11 +2004,43 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, if (next) *next++ = 0; - t = parse_time_or_die("force_key_frames", p, 1); - ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base); + if (!memcmp(p, "chapters", 8)) { + + AVFormatContext *avf = output_files[ost->file_index]->ctx; + int j; + + if (avf->nb_chapters > INT_MAX - size || + !(pts = av_realloc_f(pts, size += avf->nb_chapters - 1, + sizeof(*pts)))) { + av_log(NULL, AV_LOG_FATAL, + "Could not allocate forced key frames array.\n"); + exit(1); + } + t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0; + t = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base); + + for (j = 0; j < avf->nb_chapters; j++) { + AVChapter *c = avf->chapters[j]; + av_assert1(index < size); + pts[index++] = av_rescale_q(c->start, c->time_base, + avctx->time_base) + t; + } + + } else { + + t = parse_time_or_die("force_key_frames", p, 1); + av_assert1(index < size); + pts[index++] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base); + + } p = next; } + + av_assert0(index == size); + qsort(pts, size, sizeof(*pts), compare_int64); + ost->forced_kf_count = size; + ost->forced_kf_pts = pts; } static void report_new_stream(int input_index, AVPacket *pkt) @@ -2046,9 +2127,10 @@ static int transcode_init(void) codec->codec_type = icodec->codec_type; if (!codec->codec_tag) { + unsigned int codec_tag; if (!oc->oformat->codec_tag || av_codec_get_id (oc->oformat->codec_tag, icodec->codec_tag) == codec->codec_id || - av_codec_get_tag(oc->oformat->codec_tag, icodec->codec_id) <= 0) + !av_codec_get_tag2(oc->oformat->codec_tag, icodec->codec_id, &codec_tag)) codec->codec_tag = icodec->codec_tag; } @@ -2100,6 +2182,12 @@ static int transcode_init(void) codec->time_base.num *= icodec->ticks_per_frame; } } + if ( codec->codec_tag == AV_RL32("tmcd") + && icodec->time_base.num < icodec->time_base.den + && icodec->time_base.num > 0 + && 121LL*icodec->time_base.num > icodec->time_base.den) { + codec->time_base = icodec->time_base; + } if(ost->frame_rate.num) codec->time_base = av_inv_q(ost->frame_rate); @@ -2193,7 +2281,7 @@ static int transcode_init(void) codec->sample_fmt = ost->filter->filter->inputs[0]->format; codec->sample_rate = ost->filter->filter->inputs[0]->sample_rate; codec->channel_layout = ost->filter->filter->inputs[0]->channel_layout; - codec->channels = av_get_channel_layout_nb_channels(codec->channel_layout); + codec->channels = avfilter_link_get_channels(ost->filter->filter->inputs[0]); codec->time_base = (AVRational){ 1, codec->sample_rate }; break; case AVMEDIA_TYPE_VIDEO: @@ -2225,9 +2313,23 @@ static int transcode_init(void) codec->bits_per_raw_sample = frame_bits_per_raw_sample; } - if (ost->forced_keyframes) - parse_forced_key_frames(ost->forced_keyframes, ost, - ost->st->codec); + if (ost->forced_keyframes) { + if (!strncmp(ost->forced_keyframes, "expr:", 5)) { + ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5, + forced_keyframes_const_names, NULL, NULL, NULL, NULL, 0, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Invalid force_key_frames expression '%s'\n", ost->forced_keyframes+5); + return ret; + } + ost->forced_keyframes_expr_const_values[FKF_N] = 0; + ost->forced_keyframes_expr_const_values[FKF_N_FORCED] = 0; + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N] = NAN; + ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T] = NAN; + } else { + parse_forced_key_frames(ost->forced_keyframes, ost, ost->st->codec); + } + } break; case AVMEDIA_TYPE_SUBTITLE: codec->time_base = (AVRational){1, 1000};