X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=e4b4b9eb95aad81edd6d3ee57fb33869f22fc3e2;hb=34630b93dc7cf028a4b483c19c4f6ca4162c25c0;hp=c4a1a149a977395eae4de05ed1491cbba358e30f;hpb=46847a336e7e71559c8f3917bf8512c90635598b;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index c4a1a149a97..e4b4b9eb95a 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -36,7 +36,7 @@ #include "libswscale/swscale.h" #include "libavcodec/opt.h" #include "libavcodec/audioconvert.h" -#include "libavcodec/colorspace.h" +#include "libavutil/colorspace.h" #include "libavutil/fifo.h" #include "libavutil/pixdesc.h" #include "libavutil/avstring.h" @@ -121,16 +121,14 @@ static int nb_stream_maps; static AVMetaDataMap meta_data_maps[MAX_FILES]; static int nb_meta_data_maps; +/* indexed by output file stream index */ +static int streamid_map[MAX_STREAMS]; + static int frame_width = 0; static int frame_height = 0; 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_padtop = 0; -static int frame_padbottom = 0; -static int frame_padleft = 0; -static int frame_padright = 0; -static int padcolor[3] = {16,128,128}; /* default to black */ static int frame_topBand = 0; static int frame_bottomBand = 0; static int frame_leftBand = 0; @@ -144,7 +142,7 @@ static const char *video_rc_override_string=NULL; static int video_disable = 0; static int video_discard = 0; static char *video_codec_name = NULL; -static int video_codec_tag = 0; +static unsigned int video_codec_tag = 0; static char *video_language = NULL; static int same_quality = 0; static int do_deinterlace = 0; @@ -156,7 +154,7 @@ static int loop_output = AVFMT_NOOUTPUTLOOP; static int qp_hist = 0; #if CONFIG_AVFILTER static char *vfilters = NULL; -AVFilterGraph *filt_graph_all = NULL; +AVFilterGraph *graph = NULL; #endif static int intra_only = 0; @@ -167,20 +165,20 @@ static float audio_qscale = QSCALE_NONE; static int audio_disable = 0; static int audio_channels = 1; static char *audio_codec_name = NULL; -static int audio_codec_tag = 0; +static unsigned int audio_codec_tag = 0; static char *audio_language = NULL; static int subtitle_disable = 0; static char *subtitle_codec_name = NULL; static char *subtitle_language = NULL; -static int subtitle_codec_tag = 0; +static unsigned int subtitle_codec_tag = 0; static float mux_preload= 0.5; static float mux_max_delay= 0.7; static int64_t recording_time = INT64_MAX; static int64_t start_time = 0; -static int64_t rec_timestamp = 0; +static int64_t recording_timestamp = 0; static int64_t input_ts_offset = 0; static int file_overwrite = 0; static int metadata_count; @@ -285,13 +283,6 @@ typedef struct AVOutputStream { int original_leftBand; int original_rightBand; - /* padding area sizes */ - int video_pad; - int padtop; - int padbottom; - int padleft; - int padright; - /* audio only */ int audio_resample; ReSampleContext *resample; /* for audio resampling */ @@ -385,6 +376,8 @@ static int get_filtered_video_pic(AVFilterContext *ctx, memcpy(pic2->data, pic->data, sizeof(pic->data)); memcpy(pic2->linesize, pic->linesize, sizeof(pic->linesize)); + pic2->interlaced_frame = pic->interlaced; + pic2->top_field_first = pic->top_field_first; return 1; } @@ -408,77 +401,71 @@ static AVFilter output_filter = static int configure_filters(AVInputStream *ist, AVOutputStream *ost) { - AVFilterContext *curr_filter; + AVFilterContext *last_filter, *filter; /** filter graph containing all filters including input & output */ AVCodecContext *codec = ost->st->codec; AVCodecContext *icodec = ist->st->codec; char args[255]; - filt_graph_all = av_mallocz(sizeof(AVFilterGraph)); + graph = av_mallocz(sizeof(AVFilterGraph)); - if(!(ist->input_video_filter = avfilter_open(avfilter_get_by_name("buffer"), "src"))) + if (!(ist->input_video_filter = avfilter_open(avfilter_get_by_name("buffer"), "src"))) return -1; - if(!(ist->out_video_filter = avfilter_open(&output_filter, "out"))) + if (!(ist->out_video_filter = avfilter_open(&output_filter, "out"))) return -1; snprintf(args, 255, "%d:%d:%d", ist->st->codec->width, ist->st->codec->height, ist->st->codec->pix_fmt); - if(avfilter_init_filter(ist->input_video_filter, args, NULL)) + if (avfilter_init_filter(ist->input_video_filter, args, NULL)) return -1; - if(avfilter_init_filter(ist->out_video_filter, NULL, &codec->pix_fmt)) + if (avfilter_init_filter(ist->out_video_filter, NULL, &codec->pix_fmt)) return -1; /* add input and output filters to the overall graph */ - avfilter_graph_add_filter(filt_graph_all, ist->input_video_filter); - avfilter_graph_add_filter(filt_graph_all, ist->out_video_filter); - - curr_filter = ist->input_video_filter; - - if(ost->video_crop) { - char crop_args[255]; - AVFilterContext *filt_crop; - snprintf(crop_args, 255, "%d:%d:%d:%d", ost->leftBand, ost->topBand, - codec->width - (frame_padleft + frame_padright), - codec->height - (frame_padtop + frame_padbottom)); - filt_crop = avfilter_open(avfilter_get_by_name("crop"), NULL); - if (!filt_crop) + avfilter_graph_add_filter(graph, ist->input_video_filter); + avfilter_graph_add_filter(graph, ist->out_video_filter); + + last_filter = ist->input_video_filter; + + if (ost->video_crop) { + snprintf(args, 255, "%d:%d:%d:%d", ost->leftBand, ost->topBand, + codec->width, + codec->height); + filter = avfilter_open(avfilter_get_by_name("crop"), NULL); + if (!filter) return -1; - if (avfilter_init_filter(filt_crop, crop_args, NULL)) + if (avfilter_init_filter(filter, args, NULL)) return -1; - if (avfilter_link(curr_filter, 0, filt_crop, 0)) + if (avfilter_link(last_filter, 0, filter, 0)) return -1; - curr_filter = filt_crop; - avfilter_graph_add_filter(filt_graph_all, curr_filter); + last_filter = filter; + avfilter_graph_add_filter(graph, last_filter); } if((codec->width != - icodec->width - (frame_leftBand + frame_rightBand) + - (frame_padleft + frame_padright)) || - (codec->height != icodec->height - (frame_topBand + frame_bottomBand) + - (frame_padtop + frame_padbottom))) { - char scale_args[255]; - AVFilterContext *filt_scale; - snprintf(scale_args, 255, "%d:%d:flags=0x%X", - codec->width - (frame_padleft + frame_padright), - codec->height - (frame_padtop + frame_padbottom), + icodec->width - (frame_leftBand + frame_rightBand)) || + (codec->height != icodec->height - (frame_topBand + frame_bottomBand))) { + snprintf(args, 255, "%d:%d:flags=0x%X", + codec->width, + codec->height, (int)av_get_int(sws_opts, "sws_flags", NULL)); - filt_scale = avfilter_open(avfilter_get_by_name("scale"), NULL); - if (!filt_scale) + filter = avfilter_open(avfilter_get_by_name("scale"), NULL); + if (!filter) return -1; - if (avfilter_init_filter(filt_scale, scale_args, NULL)) + if (avfilter_init_filter(filter, args, NULL)) return -1; - if (avfilter_link(curr_filter, 0, filt_scale, 0)) + if (avfilter_link(last_filter, 0, filter, 0)) return -1; - curr_filter = filt_scale; - avfilter_graph_add_filter(filt_graph_all, curr_filter); + last_filter = filter; + avfilter_graph_add_filter(graph, last_filter); } - if(vfilters) { + if (vfilters) { AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut)); AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut)); outputs->name = av_strdup("in"); - outputs->filter = curr_filter; + outputs->filter = last_filter; outputs->pad_idx = 0; outputs->next = NULL; @@ -487,26 +474,23 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost) inputs->pad_idx = 0; inputs->next = NULL; - if (avfilter_graph_parse(filt_graph_all, vfilters, inputs, outputs, NULL) < 0) + if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0) return -1; av_freep(&vfilters); } else { - if(avfilter_link(curr_filter, 0, ist->out_video_filter, 0) < 0) + if (avfilter_link(last_filter, 0, ist->out_video_filter, 0) < 0) return -1; } - { - char scale_sws_opts[128]; - snprintf(scale_sws_opts, sizeof(scale_sws_opts), "flags=0x%X", (int)av_get_int(sws_opts, "sws_flags", NULL)); - filt_graph_all->scale_sws_opts = av_strdup(scale_sws_opts); - } + snprintf(args, sizeof(args), "flags=0x%X", (int)av_get_int(sws_opts, "sws_flags", NULL)); + graph->scale_sws_opts = av_strdup(args); /* configure all the filter links */ - if(avfilter_graph_check_validity(filt_graph_all, NULL)) + if (avfilter_graph_check_validity(graph, NULL)) return -1; - if(avfilter_graph_config_formats(filt_graph_all, NULL)) + if (avfilter_graph_config_formats(graph, NULL)) return -1; - if(avfilter_graph_config_links(filt_graph_all, NULL)) + if (avfilter_graph_config_links(graph, NULL)) return -1; codec->width = ist->out_video_filter->inputs[0]->w; @@ -559,10 +543,6 @@ static void term_init(void) #ifdef SIGXCPU signal(SIGXCPU, sigterm_handler); #endif - -#if CONFIG_BEOS_NETSERVER - fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); -#endif } /* read a key without blocking */ @@ -571,7 +551,6 @@ static int read_key(void) #if HAVE_TERMIOS_H int n = 1; unsigned char ch; -#if !CONFIG_BEOS_NETSERVER struct timeval tv; fd_set rfds; @@ -580,7 +559,6 @@ static int read_key(void) tv.tv_sec = 0; tv.tv_usec = 0; n = select(1, &rfds, NULL, NULL, &tv); -#endif if (n > 0) { n = read(0, &ch, 1); if (n == 1) @@ -643,11 +621,6 @@ static int av_exit(int ret) av_free(video_standard); -#if CONFIG_POWERPC_PERF - void powerpc_display_perf_report(void); - powerpc_display_perf_report(); -#endif /* CONFIG_POWERPC_PERF */ - for (i=0;ichannels - 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); @@ -1221,18 +1195,6 @@ static void do_video_out(AVFormatContext *s, final_picture = formatted_picture; padding_src = formatted_picture; resampling_dst = &ost->pict_tmp; - if (ost->video_pad) { - final_picture = &ost->pict_tmp; - if (ost->video_resample) { - if (av_picture_crop((AVPicture *)&picture_pad_temp, (AVPicture *)final_picture, enc->pix_fmt, ost->padtop, ost->padleft) < 0) { - fprintf(stderr, "error padding picture\n"); - if (exit_on_error) - av_exit(1); - return; - } - resampling_dst = &picture_pad_temp; - } - } if( (ost->resample_height != (ist->st->codec->height - (ost->topBand + ost->bottomBand))) || (ost->resample_width != (ist->st->codec->width - (ost->leftBand + ost->rightBand))) @@ -1279,8 +1241,8 @@ static void do_video_out(AVFormatContext *s, ist->st->codec->width - (ost->leftBand + ost->rightBand), ist->st->codec->height - (ost->topBand + ost->bottomBand), ist->st->codec->pix_fmt, - ost->st->codec->width - (ost->padleft + ost->padright), - ost->st->codec->height - (ost->padtop + ost->padbottom), + ost->st->codec->width, + ost->st->codec->height, ost->st->codec->pix_fmt, sws_flags, NULL, NULL, NULL); if (ost->img_resample_ctx == NULL) { @@ -1293,12 +1255,6 @@ static void do_video_out(AVFormatContext *s, } #endif - if (ost->video_pad) { - av_picture_pad((AVPicture*)final_picture, (AVPicture *)padding_src, - enc->height, enc->width, enc->pix_fmt, - ost->padtop, ost->padbottom, ost->padleft, ost->padright, padcolor); - } - /* duplicates frame if needed */ for(i=0;ist->codec, - &subtitle, &got_subtitle, &avpkt); + &subtitle, &got_picture, &avpkt); if (ret < 0) goto fail_decode; - if (!got_subtitle) { + if (!got_picture) { goto discard_packet; } subtitle_to_free = &subtitle; @@ -1719,14 +1674,14 @@ static int output_packet(AVInputStream *ist, int ist_index, usleep(pts - now); } #if CONFIG_AVFILTER - loop = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || + frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ist->out_video_filter || avfilter_poll_frame(ist->out_video_filter->inputs[0]); #endif /* if output time reached then transcode raw format, encode packets and output them */ if (start_time == 0 || ist->pts >= start_time) #if CONFIG_AVFILTER - while(loop) { + while (frame_available) { if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->out_video_filter) get_filtered_video_pic(ist->out_video_filter, &ist->picref, &picture, &ist->pts); #endif @@ -1819,7 +1774,7 @@ static int output_packet(AVInputStream *ist, int ist_index, } } #if CONFIG_AVFILTER - loop = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && + frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && ist->out_video_filter && avfilter_poll_frame(ist->out_video_filter->inputs[0]); #endif } @@ -1875,17 +1830,17 @@ static int output_packet(AVInputStream *ist, int ist_index, int osize = av_get_bits_per_sample_format(enc->sample_fmt) >> 3; int fs_tmp = enc->frame_size; - av_fifo_generic_read(ost->fifo, samples, fifo_bytes, NULL); + av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL); if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { enc->frame_size = fifo_bytes / (osize * enc->channels); } else { /* pad */ int frame_bytes = enc->frame_size*osize*enc->channels; - if (samples_size < frame_bytes) + if (allocated_audio_buf_size < frame_bytes) av_exit(1); - memset((uint8_t*)samples+fifo_bytes, 0, frame_bytes - fifo_bytes); + memset(audio_buf+fifo_bytes, 0, frame_bytes - fifo_bytes); } - ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples); + ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf); pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den, ost->st->time_base.num, enc->sample_rate); enc->frame_size = fs_tmp; @@ -2193,6 +2148,11 @@ static int av_transcode(AVFormatContext **output_files, codec->chroma_sample_location = icodec->chroma_sample_location; if (ost->st->stream_copy) { + uint64_t extra_size = (uint64_t)icodec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE; + + if (extra_size > INT_MAX) + goto fail; + /* if stream_copy is selected, no need to decode or encode */ codec->codec_id = icodec->codec_id; codec->codec_type = icodec->codec_type; @@ -2205,7 +2165,10 @@ static int av_transcode(AVFormatContext **output_files, } codec->bit_rate = icodec->bit_rate; - codec->extradata= icodec->extradata; + codec->extradata= av_mallocz(extra_size); + if (!codec->extradata) + goto fail; + memcpy(codec->extradata, icodec->extradata, icodec->extradata_size); codec->extradata_size= icodec->extradata_size; if(av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000){ codec->time_base = icodec->time_base; @@ -2259,13 +2222,10 @@ static int av_transcode(AVFormatContext **output_files, av_exit(1); } ost->video_crop = ((frame_leftBand + frame_rightBand + frame_topBand + frame_bottomBand) != 0); - ost->video_pad = ((frame_padleft + frame_padright + frame_padtop + frame_padbottom) != 0); ost->video_resample = ((codec->width != icodec->width - - (frame_leftBand + frame_rightBand) + - (frame_padleft + frame_padright)) || + (frame_leftBand + frame_rightBand)) || (codec->height != icodec->height - - (frame_topBand + frame_bottomBand) + - (frame_padtop + frame_padbottom)) || + (frame_topBand + frame_bottomBand)) || (codec->pix_fmt != icodec->pix_fmt)); if (ost->video_crop) { ost->topBand = ost->original_topBand = frame_topBand; @@ -2273,18 +2233,6 @@ static int av_transcode(AVFormatContext **output_files, ost->leftBand = ost->original_leftBand = frame_leftBand; ost->rightBand = ost->original_rightBand = frame_rightBand; } - if (ost->video_pad) { - ost->padtop = frame_padtop; - ost->padleft = frame_padleft; - ost->padbottom = frame_padbottom; - ost->padright = frame_padright; - if (!ost->video_resample) { - avcodec_get_frame_defaults(&ost->pict_tmp); - if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt, - codec->width, codec->height)) - goto fail; - } - } if (ost->video_resample) { avcodec_get_frame_defaults(&ost->pict_tmp); if(avpicture_alloc((AVPicture*)&ost->pict_tmp, codec->pix_fmt, @@ -2297,8 +2245,8 @@ static int av_transcode(AVFormatContext **output_files, icodec->width - (frame_leftBand + frame_rightBand), icodec->height - (frame_topBand + frame_bottomBand), icodec->pix_fmt, - codec->width - (frame_padleft + frame_padright), - codec->height - (frame_padtop + frame_padbottom), + codec->width, + codec->height, codec->pix_fmt, sws_flags, NULL, NULL, NULL); if (ost->img_resample_ctx == NULL) { @@ -2343,7 +2291,7 @@ static int av_transcode(AVFormatContext **output_files, pass_logfilename_prefix ? pass_logfilename_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX, i); if (codec->flags & CODEC_FLAG_PASS1) { - f = fopen(logfilename, "w"); + f = fopen(logfilename, "wb"); if (!f) { fprintf(stderr, "Cannot write log file '%s' for pass-1 encoding: %s\n", logfilename, strerror(errno)); av_exit(1); @@ -2710,9 +2658,9 @@ static int av_transcode(AVFormatContext **output_files, } } #if CONFIG_AVFILTER - if (filt_graph_all) { - avfilter_graph_destroy(filt_graph_all); - av_freep(&filt_graph_all); + if (graph) { + avfilter_graph_destroy(graph); + av_freep(&graph); } #endif @@ -2734,6 +2682,8 @@ static int av_transcode(AVFormatContext **output_files, for(i=0;ist->stream_copy) + av_freep(&ost->st->codec->extradata); if (ost->logfile) { fclose(ost->logfile); ost->logfile = NULL; @@ -2817,6 +2767,7 @@ static void opt_frame_crop_top(const char *arg) fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); av_exit(1); } + fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n"); frame_height -= frame_topBand; } @@ -2831,6 +2782,7 @@ static void opt_frame_crop_bottom(const char *arg) fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); av_exit(1); } + fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n"); frame_height -= frame_bottomBand; } @@ -2845,6 +2797,7 @@ static void opt_frame_crop_left(const char *arg) fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); av_exit(1); } + fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n"); frame_width -= frame_leftBand; } @@ -2859,6 +2812,7 @@ static void opt_frame_crop_right(const char *arg) fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); av_exit(1); } + fprintf(stderr, "-crop* is deprecated in favor of the crop avfilter\n"); frame_width -= frame_rightBand; } @@ -2870,57 +2824,9 @@ static void opt_frame_size(const char *arg) } } -static void opt_pad_color(const char *arg) { - /* Input is expected to be six hex digits similar to - how colors are expressed in html tags (but without the #) */ - int rgb = strtol(arg, NULL, 16); - int r,g,b; - - r = (rgb >> 16); - g = ((rgb >> 8) & 255); - b = (rgb & 255); - - padcolor[0] = RGB_TO_Y(r,g,b); - padcolor[1] = RGB_TO_U(r,g,b,0); - padcolor[2] = RGB_TO_V(r,g,b,0); -} - -static void opt_frame_pad_top(const char *arg) -{ - frame_padtop = atoi(arg); - if (frame_padtop < 0) { - fprintf(stderr, "Incorrect top pad size\n"); - av_exit(1); - } -} - -static void opt_frame_pad_bottom(const char *arg) -{ - frame_padbottom = atoi(arg); - if (frame_padbottom < 0) { - fprintf(stderr, "Incorrect bottom pad size\n"); - av_exit(1); - } -} - - -static void opt_frame_pad_left(const char *arg) -{ - frame_padleft = atoi(arg); - if (frame_padleft < 0) { - fprintf(stderr, "Incorrect left pad size\n"); - av_exit(1); - } -} - - -static void opt_frame_pad_right(const char *arg) -{ - frame_padright = atoi(arg); - if (frame_padright < 0) { - fprintf(stderr, "Incorrect right pad size\n"); - av_exit(1); - } +static void opt_pad(const char *arg) { + fprintf(stderr, "Please use vf=pad\n"); + av_exit(1); } static void opt_frame_pix_fmt(const char *arg) @@ -3156,9 +3062,9 @@ static int opt_start_time(const char *opt, const char *arg) return 0; } -static int opt_rec_timestamp(const char *opt, const char *arg) +static int opt_recording_timestamp(const char *opt, const char *arg) { - rec_timestamp = parse_time_or_die(opt, arg, 0) / 1000000; + recording_timestamp = parse_time_or_die(opt, arg, 0) / 1000000; return 0; } @@ -3168,7 +3074,7 @@ static int opt_input_ts_offset(const char *opt, const char *arg) return 0; } -static enum CodecID find_codec_or_die(const char *name, int type, int encoder) +static enum CodecID find_codec_or_die(const char *name, int type, int encoder, int strict) { const char *codec_string = encoder ? "encoder" : "decoder"; AVCodec *codec; @@ -3186,6 +3092,19 @@ static enum CodecID find_codec_or_die(const char *name, int type, int encoder) fprintf(stderr, "Invalid %s type '%s'\n", codec_string, name); av_exit(1); } + if(codec->capabilities & CODEC_CAP_EXPERIMENTAL && + strict > FF_COMPLIANCE_EXPERIMENTAL) { + fprintf(stderr, "%s '%s' is experimental and might produce bad " + "results.\nAdd '-strict experimental' if you want to use it.\n", + codec_string, codec->name); + codec = encoder ? + avcodec_find_encoder(codec->id) : + avcodec_find_decoder(codec->id); + if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL)) + fprintf(stderr, "Or use the non experimental %s '%s'.\n", + codec_string, codec->name); + av_exit(1); + } return codec->id; } @@ -3224,8 +3143,8 @@ static void opt_input_file(const char *filename) ap->channels = audio_channels; ap->time_base.den = frame_rate.num; ap->time_base.num = frame_rate.den; - ap->width = frame_width + frame_padleft + frame_padright; - ap->height = frame_height + frame_padtop + frame_padbottom; + ap->width = frame_width; + ap->height = frame_height; ap->pix_fmt = frame_pix_fmt; // ap->sample_fmt = audio_sample_fmt; //FIXME:not implemented in libavformat ap->channel = video_channel; @@ -3233,9 +3152,15 @@ static void opt_input_file(const char *filename) set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM); - ic->video_codec_id = find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0); - ic->audio_codec_id = find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0); - ic->subtitle_codec_id= find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0); + ic->video_codec_id = + find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0, + avcodec_opts[AVMEDIA_TYPE_VIDEO ]->strict_std_compliance); + ic->audio_codec_id = + find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0, + avcodec_opts[AVMEDIA_TYPE_AUDIO ]->strict_std_compliance); + ic->subtitle_codec_id= + find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0, + avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance); ic->flags |= AVFMT_FLAG_NONBLOCK; if(pgmyuv_compatibility_hack) @@ -3426,7 +3351,7 @@ static void new_video_stream(AVFormatContext *oc) AVCodecContext *video_enc; enum CodecID codec_id; - st = av_new_stream(oc, oc->nb_streams); + st = av_new_stream(oc, streamid_map[oc->nb_streams]); if (!st) { fprintf(stderr, "Could not alloc stream\n"); av_exit(1); @@ -3464,7 +3389,8 @@ static void new_video_stream(AVFormatContext *oc) AVRational fps= frame_rate.num ? frame_rate : (AVRational){25,1}; if (video_codec_name) { - codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1); + codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1, + video_enc->strict_std_compliance); codec = avcodec_find_encoder_by_name(video_codec_name); output_codecs[nb_ocodecs] = codec; } else { @@ -3481,8 +3407,8 @@ static void new_video_stream(AVFormatContext *oc) video_enc->time_base.den = fps.num; video_enc->time_base.num = fps.den; - video_enc->width = frame_width + frame_padright + frame_padleft; - video_enc->height = frame_height + frame_padtop + frame_padbottom; + video_enc->width = frame_width; + video_enc->height = frame_height; video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255); video_enc->pix_fmt = frame_pix_fmt; st->sample_aspect_ratio = video_enc->sample_aspect_ratio; @@ -3563,7 +3489,7 @@ static void new_audio_stream(AVFormatContext *oc) AVCodecContext *audio_enc; enum CodecID codec_id; - st = av_new_stream(oc, oc->nb_streams); + st = av_new_stream(oc, streamid_map[oc->nb_streams]); if (!st) { fprintf(stderr, "Could not alloc stream\n"); av_exit(1); @@ -3595,7 +3521,8 @@ static void new_audio_stream(AVFormatContext *oc) set_context_opts(audio_enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); if (audio_codec_name) { - codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1); + codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1, + audio_enc->strict_std_compliance); codec = avcodec_find_encoder_by_name(audio_codec_name); output_codecs[nb_ocodecs] = codec; } else { @@ -3635,7 +3562,7 @@ static void new_subtitle_stream(AVFormatContext *oc) AVStream *st; AVCodecContext *subtitle_enc; - st = av_new_stream(oc, oc->nb_streams); + st = av_new_stream(oc, streamid_map[oc->nb_streams]); if (!st) { fprintf(stderr, "Could not alloc stream\n"); av_exit(1); @@ -3655,7 +3582,8 @@ static void new_subtitle_stream(AVFormatContext *oc) st->stream_copy = 1; } else { set_context_opts(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM); - subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1); + subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1, + subtitle_enc->strict_std_compliance); output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name); } nb_ocodecs++; @@ -3703,6 +3631,27 @@ static void opt_new_subtitle_stream(void) new_subtitle_stream(oc); } +/* arg format is "output-stream-index:streamid-value". */ +static void opt_streamid(const char *opt, const char *arg) +{ + int idx; + char *p; + char idx_str[16]; + + strncpy(idx_str, arg, sizeof(idx_str)); + idx_str[sizeof(idx_str)-1] = '\0'; + p = strchr(idx_str, ':'); + if (!p) { + fprintf(stderr, + "Invalid value '%s' for option '%s', required syntax is 'index:value'\n", + arg, opt); + av_exit(1); + } + *p++ = '\0'; + idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1); + streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); +} + static void opt_output_file(const char *filename) { AVFormatContext *oc; @@ -3789,7 +3738,7 @@ static void opt_output_file(const char *filename) new_subtitle_stream(oc); } - oc->timestamp = rec_timestamp; + oc->timestamp = recording_timestamp; for(; metadata_count>0; metadata_count--){ av_metadata_set2(&oc->metadata, metadata[metadata_count-1].key, @@ -3850,6 +3799,8 @@ static void opt_output_file(const char *filename) oc->flags |= AVFMT_FLAG_NONBLOCK; set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM); + + memset(streamid_map, 0, sizeof(streamid_map)); } /* same option as mencoder */ @@ -4236,7 +4187,7 @@ static const OptionDef options[] = { { "ss", OPT_FUNC2 | HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" }, { "itsoffset", OPT_FUNC2 | HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" }, { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" }, - { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)opt_rec_timestamp}, "set the timestamp ('now' to set the current time)", "time" }, + { "timestamp", OPT_FUNC2 | HAS_ARG, {(void*)opt_recording_timestamp}, "set the recording timestamp ('now' to set the current time)", "time" }, { "metadata", OPT_FUNC2 | HAS_ARG, {(void*)opt_metadata}, "add metadata", "string=string" }, { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[AVMEDIA_TYPE_DATA]}, "set the number of data frames to record", "number" }, { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark}, @@ -4271,15 +4222,15 @@ static const OptionDef options[] = { { "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}, "set top crop band size (in pixels)", "size" }, - { "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_bottom}, "set bottom crop band size (in pixels)", "size" }, - { "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_left}, "set left crop band size (in pixels)", "size" }, - { "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop_right}, "set right crop band size (in pixels)", "size" }, - { "padtop", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_top}, "set top pad band size (in pixels)", "size" }, - { "padbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_bottom}, "set bottom pad band size (in pixels)", "size" }, - { "padleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_left}, "set left pad band size (in pixels)", "size" }, - { "padright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_pad_right}, "set right pad band size (in pixels)", "size" }, - { "padcolor", HAS_ARG | OPT_VIDEO, {(void*)opt_pad_color}, "set color of pad bands (Hex 000000 thru FFFFFF)", "color" }, + { "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" }, + { "padtop", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "set top pad band size (in pixels)", "size" }, + { "padbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "set bottom pad band size (in pixels)", "size" }, + { "padleft", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "set left pad band size (in pixels)", "size" }, + { "padright", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "set right pad band size (in pixels)", "size" }, + { "padcolor", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "set color of pad bands (Hex 000000 thru FFFFFF)", "color" }, { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"}, { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" }, { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" }, @@ -4297,7 +4248,7 @@ static const OptionDef options[] = { { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" }, { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" }, #if CONFIG_AVFILTER - { "vfilters", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" }, + { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" }, #endif { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" }, { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" }, @@ -4308,6 +4259,7 @@ static const OptionDef options[] = { { "vlang", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void *)&video_language}, "set the ISO 639 language code (3 letters) of the current video stream" , "code" }, { "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" }, /* audio options */ { "ab", OPT_FUNC2 | HAS_ARG | OPT_AUDIO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },