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

Reply via email to