Le vendredi 8 novembre 2013, 23:42:11 Anton Khirnov a écrit :
> ---
> avconv.c | 79
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ avconv.h |
> 15 +++++++++++
> avconv_filter.c | 3 ++-
> avconv_opt.c | 18 ++++++++++++-
> doc/avconv.texi | 20 ++++++++++++++
> 5 files changed, 133 insertions(+), 2 deletions(-)
>
> diff --git a/avconv.c b/avconv.c
> index 8d8c802..33a9a73 100644
> --- a/avconv.c
> +++ b/avconv.c
> @@ -1165,6 +1165,13 @@ static int decode_video(InputStream *ist, AVPacket
> *pkt, int *got_output) return ret;
> }
>
> + if (ist->hwaccel_retrieve_data) {
> + err = ist->hwaccel_retrieve_data(ist->st->codec, decoded_frame);
> + if (err < 0)
> + goto fail;
> + ist->hwaccel_pix_fmt = decoded_frame->format;
> + }
> +
> decoded_frame->pts = guess_correct_pts(&ist->pts_ctx,
> decoded_frame->pkt_pts, decoded_frame->pkt_dts); pkt->size = 0;
> @@ -1212,6 +1219,7 @@ static int decode_video(InputStream *ist, AVPacket
> *pkt, int *got_output) break;
> }
>
> +fail:
> av_frame_unref(ist->filter_frame);
> av_frame_unref(decoded_frame);
> return err < 0 ? err : ret;
> @@ -1359,6 +1367,70 @@ static void print_sdp(void)
> av_freep(&avc);
> }
>
> +typedef struct HWAccel {
> + const char *name;
> + int (*init)(AVCodecContext *s);
> + enum HWAccelID id;
> + enum AVPixelFormat pix_fmt;
> +} HWAccel;
> +
> +static const HWAccel hwaccels[] = {
> + { 0 },
> +};
> +
> +static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt)
> +{
> + int i;
> + for (i = 0; hwaccels[i].name; i++)
> + if (hwaccels[i].pix_fmt == pix_fmt)
> + return &hwaccels[i];
> + return NULL;
> +}
> +
> +static enum AVPixelFormat get_format(AVCodecContext *s, const enum
> AVPixelFormat *pix_fmts)
> +{
> + InputStream *ist = s->opaque;
> + const enum AVPixelFormat *p;
> + int ret;
> +
> + for (p = pix_fmts; *p != -1; p++) {
> + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
> + const HWAccel *hwaccel = get_hwaccel(*p);
Should this not be after the following if() ?
> +
> + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
> + break;
> + else if (!hwaccel ||
> + (ist->active_hwaccel_id && ist->active_hwaccel_id !=
> hwaccel->id) ||
I don't really follow why you need to keep track of and cross-check the
current hardware acceleration identifier.
> + (ist->hwaccel_id != HWACCEL_AUTO &&
> ist->hwaccel_id != hwaccel->id))
> + continue;
> +
> + ret = hwaccel->init(s);
> + if (ret < 0) {
> + if (ist->hwaccel_id == hwaccel->id) {
> + av_log(NULL, AV_LOG_FATAL,
> + "%s hwaccel requested for input stream #%d:%d, "
> + "but cannot be initialized.\n", hwaccel->name,
> + ist->file_index, ist->st->index);
> + exit_program(1);
> + }
> + continue;
> + }
> + ist->active_hwaccel_id = hwaccel->id;
> + break;
> + }
> +
> + return *p;
> +}
> +
> +static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
> +{
> + InputStream *ist = s->opaque;
> +
> + if (ist->hwaccel_get_buffer)
Does it really make sense for this to be NULL ever? This get_buffer() callback
is only used with hwaccel afterall.
> + return ist->hwaccel_get_buffer(s, frame, flags);
> + return avcodec_default_get_buffer2(s, frame, flags);
> +}
> +
> static int init_input_stream(int ist_index, char *error, int error_len)
> {
> int i, ret;
> @@ -1381,6 +1453,11 @@ static int init_input_stream(int ist_index, char
> *error, int error_len) }
> }
>
> + ist->st->codec->opaque = ist;
> + ist->st->codec->get_format = get_format;
> + ist->st->codec->get_buffer2 = get_buffer;
> + ist->st->codec->thread_safe_callbacks = 1;
> +
> av_opt_set_int(ist->st->codec, "refcounted_frames", 1, 0);
>
> if (!av_dict_get(ist->opts, "threads", NULL, 0))
> @@ -2272,6 +2349,8 @@ static int transcode(void)
> ist = input_streams[i];
> if (ist->decoding_needed) {
> avcodec_close(ist->st->codec);
> + if (ist->hwaccel_uninit)
> + ist->hwaccel_uninit(ist->st->codec);
> }
> }
>
> diff --git a/avconv.h b/avconv.h
> index cb3005d..232182a 100644
> --- a/avconv.h
> +++ b/avconv.h
> @@ -94,6 +94,8 @@ typedef struct OptionsContext {
> int nb_ts_scale;
> SpecifierOpt *dump_attachment;
> int nb_dump_attachment;
> + SpecifierOpt *hwaccels;
> + int nb_hwaccels;
>
> /* output options */
> StreamMap *stream_maps;
> @@ -195,6 +197,11 @@ typedef struct FilterGraph {
> int nb_outputs;
> } FilterGraph;
>
> +enum HWAccelID {
> + HWACCEL_NONE = 0,
> + HWACCEL_AUTO,
> +};
> +
> typedef struct InputStream {
> int file_index;
> AVStream *st;
> @@ -230,6 +237,14 @@ typedef struct InputStream {
> * currently video and audio only */
> InputFilter **filters;
> int nb_filters;
> +
> + enum HWAccelID hwaccel_id;
> + enum HWAccelID active_hwaccel_id;
> + void *hwaccel_ctx;
> + void (*hwaccel_uninit)(AVCodecContext *s);
> + int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int
> flags); + int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame
> *frame); + enum AVPixelFormat hwaccel_pix_fmt;
> } InputStream;
>
> typedef struct InputFile {
> diff --git a/avconv_filter.c b/avconv_filter.c
> index 348196f..ff1cf59 100644
> --- a/avconv_filter.c
> +++ b/avconv_filter.c
> @@ -433,7 +433,8 @@ static int configure_input_video_filter(FilterGraph *fg,
> InputFilter *ifilter, ist->st->sample_aspect_ratio :
> ist->st->codec->sample_aspect_ratio;
> snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d",
> ist->st->codec->width, - ist->st->codec->height,
> ist->st->codec->pix_fmt,
> + ist->st->codec->height,
> + ist->hwaccel_retrieve_data ? ist->hwaccel_pix_fmt :
> ist->st->codec->pix_fmt, tb.num, tb.den, sar.num, sar.den);
> snprintf(name, sizeof(name), "graph %d input from stream %d:%d",
> fg->index, ist->file_index, ist->st->index);
> diff --git a/avconv_opt.c b/avconv_opt.c
> index 70cbd71..d3677be 100644
> --- a/avconv_opt.c
> +++ b/avconv_opt.c
> @@ -455,7 +455,7 @@ static void add_input_streams(OptionsContext *o,
> AVFormatContext *ic) AVStream *st = ic->streams[i];
> AVCodecContext *dec = st->codec;
> InputStream *ist = av_mallocz(sizeof(*ist));
> - char *framerate = NULL;
> + char *framerate = NULL, *hwaccel = NULL;
>
> if (!ist)
> exit_program(1);
> @@ -488,6 +488,19 @@ static void add_input_streams(OptionsContext *o,
> AVFormatContext *ic) exit_program(1);
> }
>
> + MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st);
> + if (hwaccel) {
> + if (!strcmp(hwaccel, "none"))
> + ist->hwaccel_id = HWACCEL_NONE;
> + else if (!strcmp(hwaccel, "auto"))
> + ist->hwaccel_id = HWACCEL_AUTO;
> + else {
> + av_log(NULL, AV_LOG_ERROR, "Unrecognized hwaccel:
> %s.\n", + hwaccel);
> + exit_program(1);
> + }
> + }
> +
> break;
> case AVMEDIA_TYPE_AUDIO:
> guess_input_channel_layout(ist);
> @@ -2282,6 +2295,9 @@ const OptionDef options[] = {
> { "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
> OPT_SPEC | OPT_OUTPUT,
> { .off = OFFSET(forced_key_frames) }, "force key frames at specified
> timestamps", "timestamps" }, + { "hwaccel", OPT_VIDEO |
> OPT_STRING | HAS_ARG | OPT_EXPERT | + OPT_SPEC |
> OPT_INPUT, { .off = OFFSET(hwaccels) }, +
> "use HW accelerated decoding", "hwaccel name" },
>
> /* audio options */
> { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT,
> { .func_arg = opt_audio_frames }, diff --git a/doc/avconv.texi
> b/doc/avconv.texi
> index 714b0e7..3ff433a 100644
> --- a/doc/avconv.texi
> +++ b/doc/avconv.texi
> @@ -552,6 +552,26 @@ The timestamps must be specified in ascending order.
> @item -copyinkf[:@var{stream_specifier}] (@emph{output,per-stream})
> When doing stream copy, copy also non-key frames found at the
> beginning.
> +
> +@item -hwaccel[:@var{stream_specifier}] @var{hwaccel}
> (@emph{input,per-stream}) +Use hardware acceleration to decode the matching
> stream(s). The allowed values +of @var{hwaccel} are:
> +@table @option
> +@item none
> +Do not use any hardware acceleration (the default).
> +
> +@item auto
> +Automatically select the hardware acceleration method.
> +@end table
> +
> +This option has no effect if the selected hwaccel is not available or not
> +supported by the chosen decoder.
> +
> +Note that most acceleration methods are intended for playback and will not
> be +faster than software decoding on modern CPUs. Additionally,
> @command{avconv} +will usually need to copy the decoded frames from the GPU
> memory into the system +memory, resulting in further performance loss. This
> option is thus mainly +useful for testing.
> @end table
>
> @section Audio Options
--
Rémi Denis-Courmont
http://www.remlab.net/
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel