| Index: source/patched-ffmpeg-mt/ffmpeg.c
|
| ===================================================================
|
| --- source/patched-ffmpeg-mt/ffmpeg.c (revision 65184)
|
| +++ source/patched-ffmpeg-mt/ffmpeg.c (working copy)
|
| @@ -136,10 +136,6 @@
|
| static float frame_aspect_ratio = 0;
|
| static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
|
| static enum SampleFormat audio_sample_fmt = SAMPLE_FMT_NONE;
|
| -static int frame_topBand = 0;
|
| -static int frame_bottomBand = 0;
|
| -static int frame_leftBand = 0;
|
| -static int frame_rightBand = 0;
|
| static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX};
|
| static AVRational frame_rate;
|
| static float video_qscale = 0;
|
| @@ -188,8 +184,7 @@
|
| static int64_t recording_timestamp = 0;
|
| static int64_t input_ts_offset = 0;
|
| static int file_overwrite = 0;
|
| -static int metadata_count;
|
| -static AVMetadataTag *metadata;
|
| +static AVMetadata *metadata;
|
| static int do_benchmark = 0;
|
| static int do_hex_dump = 0;
|
| static int do_pkt_dump = 0;
|
| @@ -230,6 +225,7 @@
|
| static int input_sync;
|
| static uint64_t limit_filesize = 0;
|
| static int force_fps = 0;
|
| +static char *forced_key_frames = NULL;
|
|
|
| static int pgmyuv_compatibility_hack=0;
|
| static float dts_delta_threshold = 10;
|
| @@ -247,8 +243,6 @@
|
| static AVBitStreamFilterContext *video_bitstream_filters=NULL;
|
| static AVBitStreamFilterContext *audio_bitstream_filters=NULL;
|
| static AVBitStreamFilterContext *subtitle_bitstream_filters=NULL;
|
| -static AVBitStreamFilterContext **bitstream_filters[MAX_FILES] = {NULL};
|
| -static int nb_bitstream_filters[MAX_FILES] = {0};
|
|
|
| #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
|
|
|
| @@ -266,6 +260,7 @@
|
| //double sync_ipts; /* dts from the AVPacket of the demuxer in second units */
|
| struct AVInputStream *sync_ist; /* input stream to sync against */
|
| int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number
|
| + AVBitStreamFilterContext *bitstream_filters;
|
| /* video only */
|
| int video_resample;
|
| AVFrame pict_tmp; /* temporary image for resampling */
|
| @@ -278,19 +273,11 @@
|
| int original_height;
|
| int original_width;
|
|
|
| - /* cropping area sizes */
|
| - int video_crop;
|
| - int topBand;
|
| - int bottomBand;
|
| - int leftBand;
|
| - int rightBand;
|
| + /* forced key frames */
|
| + int64_t *forced_kf_pts;
|
| + int forced_kf_count;
|
| + int forced_kf_index;
|
|
|
| - /* cropping area of first frame */
|
| - int original_topBand;
|
| - int original_bottomBand;
|
| - int original_leftBand;
|
| - int original_rightBand;
|
| -
|
| /* audio only */
|
| int audio_resample;
|
| ReSampleContext *resample; /* for audio resampling */
|
| @@ -300,6 +287,9 @@
|
| FILE *logfile;
|
| } AVOutputStream;
|
|
|
| +static AVOutputStream **output_streams_for_file[MAX_FILES] = { NULL };
|
| +static int nb_output_streams_for_file[MAX_FILES] = { 0 };
|
| +
|
| typedef struct AVInputStream {
|
| int file_index;
|
| int index;
|
| @@ -339,81 +329,14 @@
|
| #endif
|
|
|
| #if CONFIG_AVFILTER
|
| -typedef struct {
|
| - int pix_fmt;
|
| -} FilterOutPriv;
|
|
|
| -
|
| -static int output_init(AVFilterContext *ctx, const char *args, void *opaque)
|
| -{
|
| - FilterOutPriv *priv = ctx->priv;
|
| -
|
| - if(!opaque) return -1;
|
| -
|
| - priv->pix_fmt = *((int *)opaque);
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -static void output_end_frame(AVFilterLink *link)
|
| -{
|
| -}
|
| -
|
| -static int output_query_formats(AVFilterContext *ctx)
|
| -{
|
| - FilterOutPriv *priv = ctx->priv;
|
| - enum PixelFormat pix_fmts[] = { priv->pix_fmt, PIX_FMT_NONE };
|
| -
|
| - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
|
| - return 0;
|
| -}
|
| -
|
| -static int get_filtered_video_pic(AVFilterContext *ctx,
|
| - AVFilterBufferRef **picref, AVFrame *pic2,
|
| - uint64_t *pts)
|
| -{
|
| - AVFilterBufferRef *pic;
|
| -
|
| - if(avfilter_request_frame(ctx->inputs[0]))
|
| - return -1;
|
| - if(!(pic = ctx->inputs[0]->cur_buf))
|
| - return -1;
|
| - *picref = pic;
|
| - ctx->inputs[0]->cur_buf = NULL;
|
| -
|
| - *pts = pic->pts;
|
| -
|
| - memcpy(pic2->data, pic->data, sizeof(pic->data));
|
| - memcpy(pic2->linesize, pic->linesize, sizeof(pic->linesize));
|
| - pic2->interlaced_frame = pic->video->interlaced;
|
| - pic2->top_field_first = pic->video->top_field_first;
|
| -
|
| - return 1;
|
| -}
|
| -
|
| -static AVFilter output_filter =
|
| -{
|
| - .name = "ffmpeg_output",
|
| -
|
| - .priv_size = sizeof(FilterOutPriv),
|
| - .init = output_init,
|
| -
|
| - .query_formats = output_query_formats,
|
| -
|
| - .inputs = (AVFilterPad[]) {{ .name = "default",
|
| - .type = AVMEDIA_TYPE_VIDEO,
|
| - .end_frame = output_end_frame,
|
| - .min_perms = AV_PERM_READ, },
|
| - { .name = NULL }},
|
| - .outputs = (AVFilterPad[]) {{ .name = NULL }},
|
| -};
|
| -
|
| static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
|
| {
|
| AVFilterContext *last_filter, *filter;
|
| /** filter graph containing all filters including input & output */
|
| AVCodecContext *codec = ost->st->codec;
|
| AVCodecContext *icodec = ist->st->codec;
|
| + FFSinkContext ffsink_ctx = { .pix_fmt = codec->pix_fmt };
|
| char args[255];
|
| int ret;
|
|
|
| @@ -421,14 +344,15 @@
|
|
|
| if ((ret = avfilter_open(&ist->input_video_filter, avfilter_get_by_name("buffer"), "src")) < 0)
|
| return ret;
|
| - if ((ret = avfilter_open(&ist->output_video_filter, &output_filter, "out")) < 0)
|
| + if ((ret = avfilter_open(&ist->output_video_filter, &ffsink, "out")) < 0)
|
| return ret;
|
|
|
| - snprintf(args, 255, "%d:%d:%d", ist->st->codec->width,
|
| - ist->st->codec->height, ist->st->codec->pix_fmt);
|
| + snprintf(args, 255, "%d:%d:%d:%d:%d", ist->st->codec->width,
|
| + ist->st->codec->height, ist->st->codec->pix_fmt,
|
| + ist->st->time_base.num, ist->st->time_base.den);
|
| if ((ret = avfilter_init_filter(ist->input_video_filter, args, NULL)) < 0)
|
| return ret;
|
| - if ((ret = avfilter_init_filter(ist->output_video_filter, NULL, &codec->pix_fmt)) < 0)
|
| + if ((ret = avfilter_init_filter(ist->output_video_filter, NULL, &ffsink_ctx)) < 0)
|
| return ret;
|
|
|
| /* add input and output filters to the overall graph */
|
| @@ -437,23 +361,7 @@
|
|
|
| last_filter = ist->input_video_filter;
|
|
|
| - if (ost->video_crop) {
|
| - snprintf(args, 255, "%d:%d:%d:%d",
|
| - codec->width, codec->height,
|
| - ost->leftBand, ost->topBand);
|
| - if ((ret = avfilter_open(&filter, avfilter_get_by_name("crop"), NULL)) < 0)
|
| - return ret;
|
| - if ((ret = avfilter_init_filter(filter, args, NULL)) < 0)
|
| - return ret;
|
| - if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
|
| - return ret;
|
| - last_filter = filter;
|
| - avfilter_graph_add_filter(graph, last_filter);
|
| - }
|
| -
|
| - if((codec->width !=
|
| - icodec->width - (frame_leftBand + frame_rightBand)) ||
|
| - (codec->height != icodec->height - (frame_topBand + frame_bottomBand))) {
|
| + if (codec->width != icodec->width || codec->height != icodec->height) {
|
| snprintf(args, 255, "%d:%d:flags=0x%X",
|
| codec->width,
|
| codec->height,
|
| @@ -493,13 +401,8 @@
|
| return ret;
|
| }
|
|
|
| - /* configure all the filter links */
|
| - if ((ret = avfilter_graph_check_validity(graph, NULL)) < 0)
|
| + if ((ret = avfilter_graph_config(graph, NULL)) < 0)
|
| return ret;
|
| - if ((ret = avfilter_graph_config_formats(graph, NULL)) < 0)
|
| - return ret;
|
| - if ((ret = avfilter_graph_config_links(graph, NULL)) < 0)
|
| - return ret;
|
|
|
| codec->width = ist->output_video_filter->inputs[0]->w;
|
| codec->height = ist->output_video_filter->inputs[0]->h;
|
| @@ -612,7 +515,7 @@
|
| }
|
| av_metadata_free(&s->metadata);
|
| av_free(s);
|
| - av_free(bitstream_filters[i]);
|
| + av_free(output_streams_for_file[i]);
|
| }
|
| for(i=0;i<nb_input_files;i++) {
|
| av_close_input_file(input_files[i]);
|
| @@ -1001,7 +904,7 @@
|
| if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
| pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
| pkt.flags |= AV_PKT_FLAG_KEY;
|
| - write_frame(s, &pkt, enc, bitstream_filters[ost->file_index][pkt.stream_index]);
|
| + write_frame(s, &pkt, enc, ost->bitstream_filters);
|
|
|
| ost->sync_opts += enc->frame_size;
|
| }
|
| @@ -1036,7 +939,7 @@
|
| if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
| pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
| pkt.flags |= AV_PKT_FLAG_KEY;
|
| - write_frame(s, &pkt, enc, bitstream_filters[ost->file_index][pkt.stream_index]);
|
| + write_frame(s, &pkt, enc, ost->bitstream_filters);
|
| }
|
| }
|
|
|
| @@ -1141,7 +1044,7 @@
|
| else
|
| pkt.pts += 90 * sub->end_display_time;
|
| }
|
| - write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
|
| + write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters);
|
| }
|
| }
|
|
|
| @@ -1155,17 +1058,10 @@
|
| int *frame_size)
|
| {
|
| int nb_frames, i, ret;
|
| -#if !CONFIG_AVFILTER
|
| - int64_t topBand, bottomBand, leftBand, rightBand;
|
| -#endif
|
| AVFrame *final_picture, *formatted_picture, *resampling_dst, *padding_src;
|
| - AVFrame picture_crop_temp, picture_pad_temp;
|
| AVCodecContext *enc, *dec;
|
| double sync_ipts;
|
|
|
| - avcodec_get_frame_defaults(&picture_crop_temp);
|
| - avcodec_get_frame_defaults(&picture_pad_temp);
|
| -
|
| enc = ost->st->codec;
|
| dec = ist->st->codec;
|
|
|
| @@ -1205,28 +1101,13 @@
|
| if (nb_frames <= 0)
|
| return;
|
|
|
| -#if CONFIG_AVFILTER
|
| formatted_picture = in_picture;
|
| -#else
|
| - if (ost->video_crop) {
|
| - if (av_picture_crop((AVPicture *)&picture_crop_temp, (AVPicture *)in_picture, dec->pix_fmt, ost->topBand, ost->leftBand) < 0) {
|
| - fprintf(stderr, "error cropping picture\n");
|
| - if (exit_on_error)
|
| - ffmpeg_exit(1);
|
| - return;
|
| - }
|
| - formatted_picture = &picture_crop_temp;
|
| - } else {
|
| - formatted_picture = in_picture;
|
| - }
|
| -#endif
|
| -
|
| final_picture = formatted_picture;
|
| padding_src = formatted_picture;
|
| resampling_dst = &ost->pict_tmp;
|
|
|
| - if( (ost->resample_height != (ist->st->codec->height - (ost->topBand + ost->bottomBand)))
|
| - || (ost->resample_width != (ist->st->codec->width - (ost->leftBand + ost->rightBand)))
|
| + if ( ost->resample_height != ist->st->codec->height
|
| + || ost->resample_width != ist->st->codec->width
|
| || (ost->resample_pix_fmt!= ist->st->codec->pix_fmt) ) {
|
|
|
| fprintf(stderr,"Input Stream #%d.%d frame size changed to %dx%d, %s\n", ist->file_index, ist->index, ist->st->codec->width, ist->st->codec->height,avcodec_get_pix_fmt_name(ist->st->codec->pix_fmt));
|
| @@ -1238,37 +1119,16 @@
|
| if (ost->video_resample) {
|
| padding_src = NULL;
|
| final_picture = &ost->pict_tmp;
|
| - if( (ost->resample_height != (ist->st->codec->height - (ost->topBand + ost->bottomBand)))
|
| - || (ost->resample_width != (ist->st->codec->width - (ost->leftBand + ost->rightBand)))
|
| + if( ost->resample_height != ist->st->codec->height
|
| + || ost->resample_width != ist->st->codec->width
|
| || (ost->resample_pix_fmt!= ist->st->codec->pix_fmt) ) {
|
|
|
| - /* keep bands proportional to the frame size */
|
| - topBand = ((int64_t)ist->st->codec->height * ost->original_topBand / ost->original_height) & ~1;
|
| - bottomBand = ((int64_t)ist->st->codec->height * ost->original_bottomBand / ost->original_height) & ~1;
|
| - leftBand = ((int64_t)ist->st->codec->width * ost->original_leftBand / ost->original_width) & ~1;
|
| - rightBand = ((int64_t)ist->st->codec->width * ost->original_rightBand / ost->original_width) & ~1;
|
| -
|
| - /* sanity check to ensure no bad band sizes sneak in */
|
| - av_assert0(topBand <= INT_MAX && topBand >= 0);
|
| - av_assert0(bottomBand <= INT_MAX && bottomBand >= 0);
|
| - av_assert0(leftBand <= INT_MAX && leftBand >= 0);
|
| - av_assert0(rightBand <= INT_MAX && rightBand >= 0);
|
| -
|
| - ost->topBand = topBand;
|
| - ost->bottomBand = bottomBand;
|
| - ost->leftBand = leftBand;
|
| - ost->rightBand = rightBand;
|
| -
|
| - ost->resample_height = ist->st->codec->height - (ost->topBand + ost->bottomBand);
|
| - ost->resample_width = ist->st->codec->width - (ost->leftBand + ost->rightBand);
|
| - ost->resample_pix_fmt= ist->st->codec->pix_fmt;
|
| -
|
| /* initialize a new scaler context */
|
| sws_freeContext(ost->img_resample_ctx);
|
| sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
|
| ost->img_resample_ctx = sws_getContext(
|
| - ist->st->codec->width - (ost->leftBand + ost->rightBand),
|
| - ist->st->codec->height - (ost->topBand + ost->bottomBand),
|
| + ist->st->codec->width,
|
| + ist->st->codec->height,
|
| ist->st->codec->pix_fmt,
|
| ost->st->codec->width,
|
| ost->st->codec->height,
|
| @@ -1301,7 +1161,7 @@
|
| pkt.pts= av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base);
|
| pkt.flags |= AV_PKT_FLAG_KEY;
|
|
|
| - write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
|
| + write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters);
|
| enc->coded_frame = old_frame;
|
| } else {
|
| AVFrame big_picture;
|
| @@ -1326,6 +1186,11 @@
|
| big_picture.pts= ost->sync_opts;
|
| // big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
|
| //av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);
|
| + if (ost->forced_kf_index < ost->forced_kf_count &&
|
| + big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
|
| + big_picture.pict_type = FF_I_TYPE;
|
| + ost->forced_kf_index++;
|
| + }
|
| ret = avcodec_encode_video(enc,
|
| bit_buffer, bit_buffer_size,
|
| &big_picture);
|
| @@ -1345,7 +1210,7 @@
|
|
|
| if(enc->coded_frame->key_frame)
|
| pkt.flags |= AV_PKT_FLAG_KEY;
|
| - write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
|
| + write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters);
|
| *frame_size = ret;
|
| video_size += ret;
|
| //fprintf(stderr,"\nFrame: %3d size: %5d type: %d",
|
| @@ -1714,8 +1579,11 @@
|
| if (start_time == 0 || ist->pts >= start_time)
|
| #if CONFIG_AVFILTER
|
| while (frame_available) {
|
| + AVRational ist_pts_tb;
|
| if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->output_video_filter)
|
| - get_filtered_video_pic(ist->output_video_filter, &ist->picref, &picture, &ist->pts);
|
| + get_filtered_video_frame(ist->output_video_filter, &picture, &ist->picref, &ist_pts_tb);
|
| + if (ist->picref)
|
| + ist->pts = ist->picref->pts;
|
| #endif
|
| for(i=0;i<nb_ostreams;i++) {
|
| int frame_size;
|
| @@ -1800,7 +1668,7 @@
|
| opkt.size = data_size;
|
| }
|
|
|
| - write_frame(os, &opkt, ost->st->codec, bitstream_filters[ost->file_index][opkt.stream_index]);
|
| + write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters);
|
| ost->st->codec->frame_number++;
|
| ost->frame_number++;
|
| av_free_packet(&opkt);
|
| @@ -1909,7 +1777,7 @@
|
| pkt.size= ret;
|
| if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
|
| pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
|
| - write_frame(os, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
|
| + write_frame(os, &pkt, ost->st->codec, ost->bitstream_filters);
|
| }
|
| }
|
| }
|
| @@ -1971,6 +1839,29 @@
|
| return 0;
|
| }
|
|
|
| +static void parse_forced_key_frames(char *kf, AVOutputStream *ost,
|
| + AVCodecContext *avctx)
|
| +{
|
| + char *p;
|
| + int n = 1, i;
|
| + int64_t t;
|
| +
|
| + 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) {
|
| + av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
|
| + ffmpeg_exit(1);
|
| + }
|
| + for (i = 0; i < n; i++) {
|
| + p = i ? strchr(p, ',') + 1 : kf;
|
| + 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);
|
| + }
|
| +}
|
| +
|
| /*
|
| * The following code is the main loop of the file converter
|
| */
|
| @@ -2075,21 +1966,12 @@
|
| ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams);
|
| if (!ost_table)
|
| goto fail;
|
| - for(i=0;i<nb_ostreams;i++) {
|
| - ost = av_mallocz(sizeof(AVOutputStream));
|
| - if (!ost)
|
| - goto fail;
|
| - ost_table[i] = ost;
|
| - }
|
| -
|
| n = 0;
|
| for(k=0;k<nb_output_files;k++) {
|
| os = output_files[k];
|
| for(i=0;i<os->nb_streams;i++,n++) {
|
| int found;
|
| - ost = ost_table[n];
|
| - ost->file_index = k;
|
| - ost->index = i;
|
| + ost = ost_table[n] = output_streams_for_file[k][i];
|
| ost->st = os->streams[i];
|
| if (nb_stream_maps > 0) {
|
| ost->source_index = file_table[stream_maps[n].file_index].ist_index +
|
| @@ -2260,18 +2142,9 @@
|
| fprintf(stderr, "Video pixel format is unknown, stream cannot be encoded\n");
|
| ffmpeg_exit(1);
|
| }
|
| - ost->video_crop = ((frame_leftBand + frame_rightBand + frame_topBand + frame_bottomBand) != 0);
|
| - ost->video_resample = ((codec->width != icodec->width -
|
| - (frame_leftBand + frame_rightBand)) ||
|
| - (codec->height != icodec->height -
|
| - (frame_topBand + frame_bottomBand)) ||
|
| + ost->video_resample = (codec->width != icodec->width ||
|
| + codec->height != icodec->height ||
|
| (codec->pix_fmt != icodec->pix_fmt));
|
| - if (ost->video_crop) {
|
| - ost->topBand = ost->original_topBand = frame_topBand;
|
| - ost->bottomBand = ost->original_bottomBand = frame_bottomBand;
|
| - ost->leftBand = ost->original_leftBand = frame_leftBand;
|
| - ost->rightBand = ost->original_rightBand = frame_rightBand;
|
| - }
|
| if (ost->video_resample) {
|
| avcodec_get_frame_defaults(&ost->pict_tmp);
|
| if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt,
|
| @@ -2281,8 +2154,8 @@
|
| }
|
| sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
|
| ost->img_resample_ctx = sws_getContext(
|
| - icodec->width - (frame_leftBand + frame_rightBand),
|
| - icodec->height - (frame_topBand + frame_bottomBand),
|
| + icodec->width,
|
| + icodec->height,
|
| icodec->pix_fmt,
|
| codec->width,
|
| codec->height,
|
| @@ -2299,8 +2172,8 @@
|
| #endif
|
| codec->bits_per_raw_sample= 0;
|
| }
|
| - ost->resample_height = icodec->height - (frame_topBand + frame_bottomBand);
|
| - ost->resample_width = icodec->width - (frame_leftBand + frame_rightBand);
|
| + ost->resample_height = icodec->height;
|
| + ost->resample_width = icodec->width;
|
| ost->resample_pix_fmt= icodec->pix_fmt;
|
| ost->encoding_needed = 1;
|
| ist->decoding_needed = 1;
|
| @@ -2448,8 +2321,6 @@
|
| mtag=NULL;
|
| while((mtag=av_metadata_get(in_file->metadata, "", mtag, AV_METADATA_IGNORE_SUFFIX)))
|
| av_metadata_set2(&out_file->metadata, mtag->key, mtag->value, AV_METADATA_DONT_OVERWRITE);
|
| - av_metadata_conv(out_file, out_file->oformat->metadata_conv,
|
| - in_file->iformat->metadata_conv);
|
| }
|
|
|
| /* copy chapters from the first input file that has them*/
|
| @@ -2732,6 +2603,7 @@
|
| av_fifo_free(ost->fifo); /* works even if fifo is not
|
| initialized but set to zero */
|
| av_free(ost->pict_tmp.data[0]);
|
| + av_free(ost->forced_kf_pts);
|
| if (ost->video_resample)
|
| sws_freeContext(ost->img_resample_ctx);
|
| if (ost->resample)
|
| @@ -2797,66 +2669,12 @@
|
| return 0;
|
| }
|
|
|
| -static void opt_frame_crop_top(const char *arg)
|
| +static int opt_frame_crop(const char *opt, const char *arg)
|
| {
|
| - frame_topBand = atoi(arg);
|
| - if (frame_topBand < 0) {
|
| - fprintf(stderr, "Incorrect top crop size\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - if ((frame_topBand) >= frame_height){
|
| - fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n");
|
| - frame_height -= frame_topBand;
|
| + fprintf(stderr, "Option '%s' has been removed, use the crop filter instead\n", opt);
|
| + return AVERROR(EINVAL);
|
| }
|
|
|
| -static void opt_frame_crop_bottom(const char *arg)
|
| -{
|
| - frame_bottomBand = atoi(arg);
|
| - if (frame_bottomBand < 0) {
|
| - fprintf(stderr, "Incorrect bottom crop size\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - if ((frame_bottomBand) >= frame_height){
|
| - fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n");
|
| - frame_height -= frame_bottomBand;
|
| -}
|
| -
|
| -static void opt_frame_crop_left(const char *arg)
|
| -{
|
| - frame_leftBand = atoi(arg);
|
| - if (frame_leftBand < 0) {
|
| - fprintf(stderr, "Incorrect left crop size\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - if ((frame_leftBand) >= frame_width){
|
| - fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n");
|
| - frame_width -= frame_leftBand;
|
| -}
|
| -
|
| -static void opt_frame_crop_right(const char *arg)
|
| -{
|
| - frame_rightBand = atoi(arg);
|
| - if (frame_rightBand < 0) {
|
| - fprintf(stderr, "Incorrect right crop size\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - if ((frame_rightBand) >= frame_width){
|
| - fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
|
| - ffmpeg_exit(1);
|
| - }
|
| - fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n");
|
| - frame_width -= frame_rightBand;
|
| -}
|
| -
|
| static void opt_frame_size(const char *arg)
|
| {
|
| if (av_parse_video_size(&frame_width, &frame_height, arg) < 0) {
|
| @@ -2918,10 +2736,7 @@
|
| }
|
| *mid++= 0;
|
|
|
| - metadata_count++;
|
| - metadata= av_realloc(metadata, sizeof(*metadata)*metadata_count);
|
| - metadata[metadata_count-1].key = av_strdup(arg);
|
| - metadata[metadata_count-1].value= av_strdup(mid);
|
| + av_metadata_set2(&metadata, arg, mid, 0);
|
|
|
| return 0;
|
| }
|
| @@ -3394,9 +3209,31 @@
|
| *has_subtitle_ptr = has_subtitle;
|
| }
|
|
|
| +static AVOutputStream *new_output_stream(AVFormatContext *oc, int file_idx)
|
| +{
|
| + int idx = oc->nb_streams - 1;
|
| + AVOutputStream *ost;
|
| +
|
| + 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(AVOutputStream));
|
| + if (!ost) {
|
| + fprintf(stderr, "Could not alloc output stream\n");
|
| + ffmpeg_exit(1);
|
| + }
|
| + ost->file_index = file_idx;
|
| + ost->index = idx;
|
| + return ost;
|
| +}
|
| +
|
| static void new_video_stream(AVFormatContext *oc, int file_idx)
|
| {
|
| AVStream *st;
|
| + AVOutputStream *ost;
|
| AVCodecContext *video_enc;
|
| enum CodecID codec_id;
|
| AVCodec *codec= NULL;
|
| @@ -3406,6 +3243,7 @@
|
| fprintf(stderr, "Could not alloc stream\n");
|
| ffmpeg_exit(1);
|
| }
|
| + ost = new_output_stream(oc, file_idx);
|
|
|
| output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
|
| if(!video_stream_copy){
|
| @@ -3421,11 +3259,7 @@
|
| }
|
|
|
| avcodec_get_context_defaults3(st->codec, codec);
|
| - bitstream_filters[file_idx] =
|
| - grow_array(bitstream_filters[file_idx],
|
| - sizeof(*bitstream_filters[file_idx]),
|
| - &nb_bitstream_filters[file_idx], oc->nb_streams);
|
| - bitstream_filters[file_idx][oc->nb_streams - 1]= video_bitstream_filters;
|
| + ost->bitstream_filters = video_bitstream_filters;
|
| video_bitstream_filters= NULL;
|
|
|
| st->codec->thread_count= thread_count;
|
| @@ -3525,6 +3359,9 @@
|
| video_enc->flags |= CODEC_FLAG_PASS2;
|
| }
|
| }
|
| +
|
| + if (forced_key_frames)
|
| + parse_forced_key_frames(forced_key_frames, ost, video_enc);
|
| }
|
| if (video_language) {
|
| av_metadata_set2(&st->metadata, "language", video_language, 0);
|
| @@ -3534,6 +3371,7 @@
|
| /* reset some key parameters */
|
| video_disable = 0;
|
| av_freep(&video_codec_name);
|
| + av_freep(&forced_key_frames);
|
| video_stream_copy = 0;
|
| frame_pix_fmt = PIX_FMT_NONE;
|
| }
|
| @@ -3541,6 +3379,7 @@
|
| static void new_audio_stream(AVFormatContext *oc, int file_idx)
|
| {
|
| AVStream *st;
|
| + AVOutputStream *ost;
|
| AVCodec *codec= NULL;
|
| AVCodecContext *audio_enc;
|
| enum CodecID codec_id;
|
| @@ -3550,6 +3389,7 @@
|
| fprintf(stderr, "Could not alloc stream\n");
|
| ffmpeg_exit(1);
|
| }
|
| + ost = new_output_stream(oc, file_idx);
|
|
|
| output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
|
| if(!audio_stream_copy){
|
| @@ -3566,11 +3406,7 @@
|
|
|
| avcodec_get_context_defaults3(st->codec, codec);
|
|
|
| - bitstream_filters[file_idx] =
|
| - grow_array(bitstream_filters[file_idx],
|
| - sizeof(*bitstream_filters[file_idx]),
|
| - &nb_bitstream_filters[file_idx], oc->nb_streams);
|
| - bitstream_filters[file_idx][oc->nb_streams - 1]= audio_bitstream_filters;
|
| + ost->bitstream_filters = audio_bitstream_filters;
|
| audio_bitstream_filters= NULL;
|
|
|
| st->codec->thread_count= thread_count;
|
| @@ -3621,6 +3457,7 @@
|
| static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
|
| {
|
| AVStream *st;
|
| + AVOutputStream *ost;
|
| AVCodec *codec=NULL;
|
| AVCodecContext *subtitle_enc;
|
|
|
| @@ -3629,6 +3466,7 @@
|
| fprintf(stderr, "Could not alloc stream\n");
|
| ffmpeg_exit(1);
|
| }
|
| + ost = new_output_stream(oc, file_idx);
|
| subtitle_enc = st->codec;
|
| output_codecs = grow_array(output_codecs, sizeof(*output_codecs), &nb_output_codecs, nb_output_codecs + 1);
|
| if(!subtitle_stream_copy){
|
| @@ -3638,11 +3476,7 @@
|
| }
|
| avcodec_get_context_defaults3(st->codec, codec);
|
|
|
| - bitstream_filters[file_idx] =
|
| - grow_array(bitstream_filters[file_idx],
|
| - sizeof(*bitstream_filters[file_idx]),
|
| - &nb_bitstream_filters[file_idx], oc->nb_streams);
|
| - bitstream_filters[file_idx][oc->nb_streams - 1]= subtitle_bitstream_filters;
|
| + ost->bitstream_filters = subtitle_bitstream_filters;
|
| subtitle_bitstream_filters= NULL;
|
|
|
| subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
|
| @@ -3713,6 +3547,7 @@
|
| int input_has_video, input_has_audio, input_has_subtitle;
|
| AVFormatParameters params, *ap = ¶ms;
|
| AVOutputFormat *file_oformat;
|
| + AVMetadataTag *tag = NULL;
|
|
|
| if (!strcmp(filename, "-"))
|
| filename = "pipe:";
|
| @@ -3770,35 +3605,19 @@
|
| }
|
|
|
| /* manual disable */
|
| - if (audio_disable) {
|
| - use_audio = 0;
|
| - }
|
| - if (video_disable) {
|
| - use_video = 0;
|
| - }
|
| - if (subtitle_disable) {
|
| - use_subtitle = 0;
|
| - }
|
| + if (audio_disable) use_audio = 0;
|
| + if (video_disable) use_video = 0;
|
| + if (subtitle_disable) use_subtitle = 0;
|
|
|
| - if (use_video) {
|
| - new_video_stream(oc, nb_output_files);
|
| - }
|
| + if (use_video) new_video_stream(oc, nb_output_files);
|
| + if (use_audio) new_audio_stream(oc, nb_output_files);
|
| + if (use_subtitle) new_subtitle_stream(oc, nb_output_files);
|
|
|
| - if (use_audio) {
|
| - new_audio_stream(oc, nb_output_files);
|
| - }
|
| -
|
| - if (use_subtitle) {
|
| - new_subtitle_stream(oc, nb_output_files);
|
| - }
|
| -
|
| oc->timestamp = recording_timestamp;
|
|
|
| - for(; metadata_count>0; metadata_count--){
|
| - av_metadata_set2(&oc->metadata, metadata[metadata_count-1].key,
|
| - metadata[metadata_count-1].value, 0);
|
| - }
|
| - av_metadata_conv(oc, oc->oformat->metadata_conv, NULL);
|
| + while ((tag = av_metadata_get(metadata, "", tag, AV_METADATA_IGNORE_SUFFIX)))
|
| + av_metadata_set2(&oc->metadata, tag->key, tag->value, 0);
|
| + av_metadata_free(&metadata);
|
| }
|
|
|
| output_files[nb_output_files++] = oc;
|
| @@ -3855,6 +3674,7 @@
|
| set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
|
|
|
| nb_streamid_map = 0;
|
| + av_freep(&forced_key_frames);
|
| }
|
|
|
| /* same option as mencoder */
|
| @@ -4267,10 +4087,10 @@
|
| { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" },
|
| { "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
|
| { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format, 'list' as argument shows all the pixel formats supported", "format" },
|
| - { "croptop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_top}, "Deprecated, please use the crop avfilter", "size" },
|
| - { "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_bottom}, "Deprecated, please use the crop avfilter", "size" },
|
| - { "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_left}, "Deprecated, please use the crop avfilter", "size" },
|
| - { "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_right}, "Deprecated, please use the crop avfilter", "size" },
|
| + { "croptop", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
|
| + { "cropbottom", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
|
| + { "cropleft", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
|
| + { "cropright", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
|
| { "padtop", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "size" },
|
| { "padbottom", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "size" },
|
| { "padleft", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "size" },
|
| @@ -4305,6 +4125,7 @@
|
| { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
|
| { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&force_fps}, "force the selected framerate, disable the best supported framerate selection" },
|
| { "streamid", OPT_FUNC2 | HAS_ARG | OPT_EXPERT, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" },
|
| + { "force_key_frames", OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void *)&forced_key_frames}, "force key frames at specified timestamps", "timestamps" },
|
|
|
| /* audio options */
|
| { "ab", OPT_FUNC2 | HAS_ARG | OPT_AUDIO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
|
|
|