diff --git a/cmdutils.c b/cmdutils.c index 2349b70..8f7ad3e 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -47,6 +47,7 @@ #endif const char **opt_names; +const char **opt_values; static int opt_name_count; AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB]; AVFormatContext *avformat_opts; @@ -213,15 +214,25 @@ int opt_default(const char *opt, const char *arg){ exit(1); } if (!o) { + AVCodec *p = NULL; + while ((p=av_codec_next(p))){ + AVClass *c= p->priv_class; + if(c && av_find_opt(&c, opt, NULL, 0, 0)) + break; + } + if(!p){ fprintf(stderr, "Unrecognized option '%s'\n", opt); exit(1); + } } // av_log(NULL, AV_LOG_ERROR, "%s:%s: %f 0x%0X\n", opt, arg, av_get_double(avcodec_opts, opt, NULL), (int)av_get_int(avcodec_opts, opt, NULL)); //FIXME we should always use avcodec_opts, ... for storing options so there will not be any need to keep track of what i set over this + opt_values= av_realloc(opt_values, sizeof(void*)*(opt_name_count+1)); + opt_values[opt_name_count]= o ? NULL : arg; opt_names= av_realloc(opt_names, sizeof(void*)*(opt_name_count+1)); - opt_names[opt_name_count++]= o->name; + opt_names[opt_name_count++]= o ? o->name : opt; if(avcodec_opts[0]->debug || avformat_opts->debug) av_log_set_level(AV_LOG_DEBUG); @@ -276,9 +287,16 @@ int opt_timelimit(const char *opt, const char *arg) return 0; } -void set_context_opts(void *ctx, void *opts_ctx, int flags) +void set_context_opts(void *ctx, void *opts_ctx, int flags, AVCodec *codec) { int i; + void *priv_ctx=NULL; + if(!strcmp("AVCodecContext", (*(AVClass**)ctx)->class_name)){ + AVCodecContext *avctx= ctx; + if(codec && codec->priv_class && avctx->priv_data){ + priv_ctx= avctx->priv_data; + } + } for(i=0; iflags & flags) == flags)) av_set_string3(ctx, opt_names[i], str, 1, NULL); + /* We need to use a differnt system to pass options to the private context because + it is not known which codec and thus context kind that will be when parsing options + we thus use opt_values directly instead of opts_ctx */ + if(!str && priv_ctx && av_get_string(priv_ctx, opt_names[i], &opt, buf, sizeof(buf))){ + av_set_string3(priv_ctx, opt_names[i], opt_values[i], 1, NULL); + } } } diff --git a/cmdutils.h b/cmdutils.h index 5656370..011d84b 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -132,7 +132,7 @@ void show_help_options(const OptionDef *options, const char *msg, int mask, int void parse_options(int argc, char **argv, const OptionDef *options, void (* parse_arg_function)(const char*)); -void set_context_opts(void *ctx, void *opts_ctx, int flags); +void set_context_opts(void *ctx, void *opts_ctx, int flags, AVCodec *codec); /** * Prints an error message to stderr, indicating filename and a human diff --git a/ffmpeg.c b/ffmpeg.c index 6b9380f..c386430 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -2988,7 +2988,7 @@ static void opt_input_file(const char *filename) ap->channel = video_channel; ap->standard = video_standard; - set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM); + set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL); ic->video_codec_id = find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0, @@ -3063,45 +3063,46 @@ static void opt_input_file(const char *filename) /* update the current parameters so that they match the one of the input stream */ for(i=0;inb_streams;i++) { AVStream *st = ic->streams[i]; - AVCodecContext *enc = st->codec; - avcodec_thread_init(enc, thread_count); - switch(enc->codec_type) { + AVCodecContext *dec = st->codec; + avcodec_thread_init(dec, thread_count); + switch (dec->codec_type) { case AVMEDIA_TYPE_AUDIO: - set_context_opts(enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM); - //fprintf(stderr, "\nInput Audio channels: %d", enc->channels); - channel_layout = enc->channel_layout; - audio_channels = enc->channels; - audio_sample_rate = enc->sample_rate; - audio_sample_fmt = enc->sample_fmt; input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(audio_codec_name); + set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_icodecs-1]); + //fprintf(stderr, "\nInput Audio channels: %d", dec->channels); + channel_layout = dec->channel_layout; + audio_channels = dec->channels; + audio_sample_rate = dec->sample_rate; + audio_sample_fmt = dec->sample_fmt; if(audio_disable) st->discard= AVDISCARD_ALL; break; case AVMEDIA_TYPE_VIDEO: - set_context_opts(enc, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM); - frame_height = enc->height; - frame_width = enc->width; + input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(video_codec_name); + set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_icodecs-1]); + frame_height = dec->height; + frame_width = dec->width; if(ic->streams[i]->sample_aspect_ratio.num) frame_aspect_ratio=av_q2d(ic->streams[i]->sample_aspect_ratio); else - frame_aspect_ratio=av_q2d(enc->sample_aspect_ratio); - frame_aspect_ratio *= (float) enc->width / enc->height; - frame_pix_fmt = enc->pix_fmt; + frame_aspect_ratio=av_q2d(dec->sample_aspect_ratio); + frame_aspect_ratio *= (float) dec->width / dec->height; + frame_pix_fmt = dec->pix_fmt; rfps = ic->streams[i]->r_frame_rate.num; rfps_base = ic->streams[i]->r_frame_rate.den; - if(enc->lowres) { - enc->flags |= CODEC_FLAG_EMU_EDGE; - frame_height >>= enc->lowres; - frame_width >>= enc->lowres; + if (dec->lowres) { + dec->flags |= CODEC_FLAG_EMU_EDGE; + frame_height >>= dec->lowres; + frame_width >>= dec->lowres; } if(me_threshold) - enc->debug |= FF_DEBUG_MV; + dec->debug |= FF_DEBUG_MV; - if (enc->time_base.den != rfps*enc->ticks_per_frame || enc->time_base.num != rfps_base) { + if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) { if (verbose >= 0) fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n", - i, (float)enc->time_base.den / enc->time_base.num, enc->time_base.den, enc->time_base.num, + i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num, (float)rfps / rfps_base, rfps, rfps_base); } @@ -3109,7 +3110,6 @@ static void opt_input_file(const char *filename) frame_rate.num = rfps; frame_rate.den = rfps_base; - input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(video_codec_name); if(video_disable) st->discard= AVDISCARD_ALL; else if(video_discard) @@ -3188,13 +3188,27 @@ static void new_video_stream(AVFormatContext *oc) AVStream *st; AVCodecContext *video_enc; enum CodecID codec_id; + AVCodec *codec= NULL; st = av_new_stream(oc, oc->nb_streams); if (!st) { fprintf(stderr, "Could not alloc stream\n"); av_exit(1); } - avcodec_get_context_defaults2(st->codec, AVMEDIA_TYPE_VIDEO); + + if(!video_stream_copy){ + if (video_codec_name) { + codec_id = find_codec_or_die(video_codec_name, AVMEDIA_TYPE_VIDEO, 1, + avcodec_opts[AVMEDIA_TYPE_VIDEO]->strict_std_compliance); + codec = avcodec_find_encoder_by_name(video_codec_name); + output_codecs[nb_ocodecs] = codec; + } else { + codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO); + codec = avcodec_find_encoder(codec_id); + } + } + + avcodec_get_context_defaults3(st->codec, codec); bitstream_filters[nb_output_files][oc->nb_streams - 1]= video_bitstream_filters; video_bitstream_filters= NULL; @@ -3223,22 +3237,10 @@ static void new_video_stream(AVFormatContext *oc) } else { const char *p; int i; - AVCodec *codec; 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, - video_enc->strict_std_compliance); - codec = avcodec_find_encoder_by_name(video_codec_name); - output_codecs[nb_ocodecs] = codec; - } else { - codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO); - codec = avcodec_find_encoder(codec_id); - } - video_enc->codec_id = codec_id; - - set_context_opts(video_enc, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(video_enc, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec); if (codec && codec->supported_framerates && !force_fps) fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)]; @@ -3324,6 +3326,7 @@ static void new_video_stream(AVFormatContext *oc) static void new_audio_stream(AVFormatContext *oc) { AVStream *st; + AVCodec *codec= NULL; AVCodecContext *audio_enc; enum CodecID codec_id; @@ -3332,7 +3335,20 @@ static void new_audio_stream(AVFormatContext *oc) fprintf(stderr, "Could not alloc stream\n"); av_exit(1); } - avcodec_get_context_defaults2(st->codec, AVMEDIA_TYPE_AUDIO); + + if(!audio_stream_copy){ + if (audio_codec_name) { + codec_id = find_codec_or_die(audio_codec_name, AVMEDIA_TYPE_AUDIO, 1, + avcodec_opts[AVMEDIA_TYPE_AUDIO]->strict_std_compliance); + codec = avcodec_find_encoder_by_name(audio_codec_name); + output_codecs[nb_ocodecs] = codec; + } else { + codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO); + codec = avcodec_find_encoder(codec_id); + } + } + + avcodec_get_context_defaults3(st->codec, codec); bitstream_filters[nb_output_files][oc->nb_streams - 1]= audio_bitstream_filters; audio_bitstream_filters= NULL; @@ -3354,20 +3370,8 @@ static void new_audio_stream(AVFormatContext *oc) audio_enc->channels = audio_channels; audio_enc->sample_rate = audio_sample_rate; } else { - AVCodec *codec; - - 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, - audio_enc->strict_std_compliance); - codec = avcodec_find_encoder_by_name(audio_codec_name); - output_codecs[nb_ocodecs] = codec; - } else { - codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_AUDIO); - codec = avcodec_find_encoder(codec_id); - } audio_enc->codec_id = codec_id; + set_context_opts(audio_enc, avcodec_opts[AVMEDIA_TYPE_AUDIO], AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec); if (audio_qscale > QSCALE_NONE) { audio_enc->flags |= CODEC_FLAG_QSCALE; @@ -3398,6 +3402,7 @@ static void new_audio_stream(AVFormatContext *oc) static void new_subtitle_stream(AVFormatContext *oc) { AVStream *st; + AVCodec *codec=NULL; AVCodecContext *subtitle_enc; st = av_new_stream(oc, oc->nb_streams); @@ -3405,12 +3410,17 @@ static void new_subtitle_stream(AVFormatContext *oc) fprintf(stderr, "Could not alloc stream\n"); av_exit(1); } - avcodec_get_context_defaults2(st->codec, AVMEDIA_TYPE_SUBTITLE); + subtitle_enc = st->codec; + if(!subtitle_stream_copy){ + subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 1, + avcodec_opts[AVMEDIA_TYPE_SUBTITLE]->strict_std_compliance); + codec= output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name); + } + avcodec_get_context_defaults3(st->codec, codec); bitstream_filters[nb_output_files][oc->nb_streams - 1]= subtitle_bitstream_filters; subtitle_bitstream_filters= NULL; - subtitle_enc = st->codec; subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE; if(subtitle_codec_tag) @@ -3419,10 +3429,7 @@ static void new_subtitle_stream(AVFormatContext *oc) if (subtitle_stream_copy) { 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->strict_std_compliance); - output_codecs[nb_ocodecs] = avcodec_find_encoder_by_name(subtitle_codec_name); + set_context_opts(avcodec_opts[AVMEDIA_TYPE_SUBTITLE], subtitle_enc, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM, codec); } nb_ocodecs++; @@ -3615,7 +3622,7 @@ static void opt_output_file(const char *filename) oc->loop_output = loop_output; oc->flags |= AVFMT_FLAG_NONBLOCK; - set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM); + set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL); } /* same option as mencoder */ diff --git a/ffplay.c b/ffplay.c index e79e17b..9c58940 100644 --- a/ffplay.c +++ b/ffplay.c @@ -2206,7 +2206,7 @@ static int stream_component_open(VideoState *is, int stream_index) avctx->error_concealment= error_concealment; avcodec_thread_init(avctx, thread_count); - set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0); + set_context_opts(avctx, avcodec_opts[avctx->codec_type], 0, codec); if (!codec || avcodec_open(avctx, codec) < 0) @@ -2384,7 +2384,7 @@ static int decode_thread(void *arg) ap->time_base= (AVRational){1, 25}; ap->pix_fmt = frame_pix_fmt; - set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM); + set_context_opts(ic, avformat_opts, AV_OPT_FLAG_DECODING_PARAM, NULL); err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap); if (err < 0) { diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 974e87c..6a6f2a7 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -30,7 +30,7 @@ #include "libavutil/avutil.h" #define LIBAVCODEC_VERSION_MAJOR 52 -#define LIBAVCODEC_VERSION_MINOR 72 +#define LIBAVCODEC_VERSION_MINOR 73 #define LIBAVCODEC_VERSION_MICRO 2 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -2652,6 +2652,15 @@ typedef struct AVCodecContext { * - decoding: unused */ int rc_lookahead; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; } AVCodecContext; /** @@ -2693,6 +2702,7 @@ typedef struct AVCodec { const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 const enum SampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 const int64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 + AVClass *priv_class; ///< AVClass for the private context } AVCodec; /** @@ -3327,6 +3337,10 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int linesize_align[4]); +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec); + /** * Checks if the given dimension of a picture is valid, meaning that all * bytes of the picture can be addressed with a signed int. @@ -3344,6 +3358,10 @@ int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, v int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); //FIXME func typedef +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +AVCodecContext *avcodec_alloc_context3(AVCodec *codec); + /** * Initializes the AVCodecContext to use the given AVCodec. Prior to using this * function the context has to be allocated. diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index fa393b8..37b51b2 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -30,19 +30,20 @@ #include "avcodec.h" #include "libavutil/base64.h" +#include "libavcodec/opt.h" /** * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. * One encoded frame returned from the library. */ struct FrameListData { - void *buf; /**≤ compressed data buffer */ - size_t sz; /**≤ length of compressed data */ - int64_t pts; /**≤ time stamp to show frame + void *buf; /**< compressed data buffer */ + size_t sz; /**< length of compressed data */ + int64_t pts; /**< time stamp to show frame (in timebase units) */ - unsigned long duration; /**≤ duration to show frame + unsigned long duration; /**< duration to show frame (in timebase units) */ - uint32_t flags; /**≤ flags for this frame */ + uint32_t flags; /**< flags for this frame */ struct FrameListData *next; }; @@ -50,10 +51,32 @@ typedef struct VP8EncoderContext { struct vpx_codec_ctx encoder; struct vpx_image rawimg; struct vpx_fixed_buf twopass_stats; - unsigned long deadline; //i.e., RT/GOOD/BEST + int deadline; //i.e., RT/GOOD/BEST struct FrameListData *coded_frame_list; + + int cpuused; + + /** + * VP8 specific flags, see VP8F_* below. + */ + int flags; +#define VP8F_ERROR_RESILIENT 0x00000001 ///< Enable measures appropriate for streaming over lossy links +#define VP8F_AUTO_ALT_REF 0x00000002 ///< Enable automatic alternate reference frame generation } VP8Context; +static const AVOption options[]={ +{"speed", "", offsetof(VP8Context, cpuused), FF_OPT_TYPE_INT, 3, -16, 16, AV_OPT_FLAG_ENCODING_PARAM}, +{"quality", "", offsetof(VP8Context, deadline), FF_OPT_TYPE_INT, VPX_DL_GOOD_QUALITY, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "quality"}, +{"best", NULL, 0, FF_OPT_TYPE_CONST, VPX_DL_BEST_QUALITY, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "quality"}, +{"good", NULL, 0, FF_OPT_TYPE_CONST, VPX_DL_GOOD_QUALITY, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "quality"}, +{"realtime", NULL, 0, FF_OPT_TYPE_CONST, VPX_DL_REALTIME, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "quality"}, +{"vp8flags", "", offsetof(VP8Context, flags), FF_OPT_TYPE_FLAGS, 0, 0, UINT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flags"}, +{"error_resilient", "enable error resilience", 0, FF_OPT_TYPE_CONST, VP8F_ERROR_RESILIENT, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flags"}, +{"altref", "enable use of alternate reference frames (VP8/2-pass only)", 0, FF_OPT_TYPE_CONST, VP8F_AUTO_ALT_REF, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flags"}, +{NULL} +}; +static const AVClass class = { "libvpx", av_default_item_name, options, LIBAVUTIL_VERSION_INT }; + /** String mappings for enum vp8e_enc_control_id */ static const char *ctlidstr[] = { [VP8E_UPD_ENTROPY] = "VP8E_UPD_ENTROPY", @@ -204,7 +227,6 @@ static av_cold int vp8_init(AVCodecContext *avctx) { VP8Context *ctx = avctx->priv_data; const struct vpx_codec_iface *iface = &vpx_codec_vp8_cx_algo; - int cpuused = 3; struct vpx_codec_enc_cfg enccfg; int res; @@ -218,11 +240,21 @@ static av_cold int vp8_init(AVCodecContext *avctx) } dump_enc_cfg(avctx, &enccfg); + /* With altref set an additional frame at the same pts may be produced. + Increasing the time_base gives the library a window to place these frames + ensuring strictly increasing timestamps. */ + if (ctx->flags & VP8F_AUTO_ALT_REF) { + avctx->ticks_per_frame = 2; + avctx->time_base = av_mul_q(avctx->time_base, + (AVRational){1, avctx->ticks_per_frame}); + } + enccfg.g_w = avctx->width; enccfg.g_h = avctx->height; enccfg.g_timebase.num = avctx->time_base.num; enccfg.g_timebase.den = avctx->time_base.den; enccfg.g_threads = avctx->thread_count; + enccfg.g_lag_in_frames= FFMIN(avctx->rc_lookahead, 25); //0-25, avoids init failure if (avctx->flags & CODEC_FLAG_PASS1) enccfg.g_pass = VPX_RC_FIRST_PASS; @@ -240,11 +272,27 @@ static av_cold int vp8_init(AVCodecContext *avctx) //convert [1,51] -> [0,63] enccfg.rc_min_quantizer = ((avctx->qmin * 5 + 1) >> 2) - 1; enccfg.rc_max_quantizer = ((avctx->qmax * 5 + 1) >> 2) - 1; - + enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold; + + //0-100 (0 => CBR, 100 => VBR) + enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); + enccfg.rc_2pass_vbr_minsection_pct = + avctx->rc_min_rate * 100LL / avctx->bit_rate; + if (avctx->rc_max_rate) + enccfg.rc_2pass_vbr_maxsection_pct = + avctx->rc_max_rate * 100LL / avctx->bit_rate; + + if (avctx->rc_buffer_size) + enccfg.rc_buf_sz = + avctx->rc_buffer_size * 1000LL / avctx->bit_rate; + if (avctx->rc_initial_buffer_occupancy) + enccfg.rc_buf_initial_sz = + avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate; + enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6; + enccfg.rc_undershoot_pct = round(avctx->rc_buffer_aggressivity * 100); + + //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO if (avctx->keyint_min == avctx->gop_size) - enccfg.kf_mode = VPX_KF_FIXED; - //_enc_init() will balk if kf_min_dist is set in this case - if (enccfg.kf_mode != VPX_KF_AUTO) enccfg.kf_min_dist = avctx->keyint_min; enccfg.kf_max_dist = avctx->gop_size; @@ -277,7 +325,13 @@ static av_cold int vp8_init(AVCodecContext *avctx) enccfg.rc_twopass_stats_in = ctx->twopass_stats; } - ctx->deadline = VPX_DL_GOOD_QUALITY; + /* 0-3: For non-zero values the encoder increasingly optimizes for reduced + complexity playback on low powered devices at the expense of encode + quality. */ + if (avctx->profile != FF_PROFILE_UNKNOWN) + enccfg.g_profile = avctx->profile; + + enccfg.g_error_resilient = ctx->flags & VP8F_ERROR_RESILIENT; dump_enc_cfg(avctx, &enccfg); /* Construct Encoder Context */ @@ -289,8 +343,12 @@ static av_cold int vp8_init(AVCodecContext *avctx) //codec control failures are currently treated only as warnings av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n"); - codecctl_int(avctx, VP8E_SET_CPUUSED, cpuused); + codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpuused); codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction); + codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); + codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, !!(ctx->flags & VP8F_AUTO_ALT_REF)); + + av_log(avctx, AV_LOG_DEBUG, "Using deadline: %d\n", ctx->deadline); //provide dummy value to initialize wrapper, values will be updated each _encode() vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, @@ -486,4 +544,5 @@ AVCodec libvpx_encoder = { CODEC_CAP_DELAY, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), + .priv_class= &class, }; diff --git a/libavcodec/options.c b/libavcodec/options.c index 97d705e..73dcb85 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -411,6 +411,7 @@ static const AVOption options[]={ {"aq_strength", "specify aq strength", OFFSET(aq_strength), FF_OPT_TYPE_FLOAT, 1.0, 0, FLT_MAX, V|E}, {"rc_lookahead", "specify number of frames to look ahead for frametype", OFFSET(rc_lookahead), FF_OPT_TYPE_INT, 40, 0, INT_MAX, V|E}, {"ssim", "ssim will be calculated during encoding", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_SSIM, INT_MIN, INT_MAX, V|E, "flags2"}, +{"slices", "number of slices, used in parallelized decoding", OFFSET(slices), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|E}, {NULL}, }; @@ -453,6 +454,36 @@ void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_typ s->reordered_opaque= AV_NOPTS_VALUE; } +int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec){ + avcodec_get_context_defaults2(s, codec ? codec->type : AVMEDIA_TYPE_UNKNOWN); + if(codec && codec->priv_data_size){ + if(!s->priv_data){ + s->priv_data= av_mallocz(codec->priv_data_size); + if (!s->priv_data) { + return AVERROR(ENOMEM); + } + } + if(codec->priv_class){ + *(AVClass**)s->priv_data= codec->priv_class; + av_opt_set_defaults(s->priv_data); + } + } + return 0; +} + +AVCodecContext *avcodec_alloc_context3(AVCodec *codec){ + AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); + + if(avctx==NULL) return NULL; + + if(avcodec_get_context_defaults3(avctx, codec) < 0){ + av_free(avctx); + return NULL; + } + + return avctx; +} + AVCodecContext *avcodec_alloc_context2(enum AVMediaType codec_type){ AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 014427d..99e754e 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -479,11 +479,17 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) goto end; if (codec->priv_data_size > 0) { + if(!avctx->priv_data){ avctx->priv_data = av_mallocz(codec->priv_data_size); if (!avctx->priv_data) { ret = AVERROR(ENOMEM); goto end; } + if(codec->priv_class){ //this can be droped once all user apps use avcodec_get_context_defaults3() + *(AVClass**)avctx->priv_data= codec->priv_class; + av_opt_set_defaults(avctx->priv_data); + } + } } else { avctx->priv_data = NULL; } diff --git a/libavutil/log.c b/libavutil/log.c index 9a8b66e..f1501c5 100644 --- a/libavutil/log.c +++ b/libavutil/log.c @@ -55,6 +55,10 @@ static void colored_fputs(int color, const char *str){ } } +const char* av_default_item_name(void* ptr){ + return (*(AVClass**)ptr)->class_name; +} + void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) { static int print_prefix=1; diff --git a/libavutil/log.h b/libavutil/log.h index 1c3e490..cf61f0c 100644 --- a/libavutil/log.h +++ b/libavutil/log.h @@ -119,5 +119,6 @@ int av_log_get_level(void); void av_log_set_level(int); void av_log_set_callback(void (*)(void*, int, const char*, va_list)); void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl); +const char* av_default_item_name(void* ctx); #endif /* AVUTIL_LOG_H */ Index: ffpresets/libvpx-720p50_60.ffpreset =================================================================== --- ffpresets/libvpx-720p50_60.ffpreset (revision 0) +++ ffpresets/libvpx-720p50_60.ffpreset (revision 0) @@ -0,0 +1,14 @@ +vcodec=libvpx +g=120 +rc_lookahead=25 +quality=good +speed=0 +profile=0 +qmax=51 +qmin=11 +slices=4 +vb=2M + +#ignored unless using -pass 2 +maxrate=24M +minrate=100k Index: ffpresets/libvpx-1080p.ffpreset =================================================================== --- ffpresets/libvpx-1080p.ffpreset (revision 0) +++ ffpresets/libvpx-1080p.ffpreset (revision 0) @@ -0,0 +1,14 @@ +vcodec=libvpx +g=120 +rc_lookahead=16 +quality=good +speed=0 +profile=1 +qmax=51 +qmin=11 +slices=4 +vb=2M + +#ignored unless using -pass 2 +maxrate=24M +minrate=100k Index: ffpresets/libvpx-1080p50_60.ffpreset =================================================================== --- ffpresets/libvpx-1080p50_60.ffpreset (revision 0) +++ ffpresets/libvpx-1080p50_60.ffpreset (revision 0) @@ -0,0 +1,14 @@ +vcodec=libvpx +g=120 +rc_lookahead=25 +quality=good +speed=0 +profile=1 +qmax=51 +qmin=11 +slices=4 +vb=2M + +#ignored unless using -pass 2 +maxrate=24M +minrate=100k Index: ffpresets/libvpx-360p.ffpreset =================================================================== --- ffpresets/libvpx-360p.ffpreset (revision 0) +++ ffpresets/libvpx-360p.ffpreset (revision 0) @@ -0,0 +1,13 @@ +vcodec=libvpx +g=120 +rc_lookahead=16 +quality=good +speed=0 +profile=0 +qmax=63 +qmin=0 +vb=768k + +#ignored unless using -pass 2 +maxrate=1.5M +minrate=40k Index: ffpresets/libvpx-720p.ffpreset =================================================================== --- ffpresets/libvpx-720p.ffpreset (revision 0) +++ ffpresets/libvpx-720p.ffpreset (revision 0) @@ -0,0 +1,14 @@ +vcodec=libvpx +g=120 +rc_lookahead=16 +quality=good +speed=0 +profile=0 +qmax=51 +qmin=11 +slices=4 +vb=2M + +#ignored unless using -pass 2 +maxrate=24M +minrate=100k