---
 avconv.c        |   79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 avconv.h        |   15 +++++++++++
 avconv_filter.c |    3 ++-
 avconv_opt.c    |   18 ++++++++++++-
 doc/avconv.texi |   18 +++++++++++++
 5 files changed, 131 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);
+
+        if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
+            break;
+        else if (!hwaccel ||
+                 (ist->active_hwaccel_id && ist->active_hwaccel_id != 
hwaccel->id) ||
+                 (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)
+        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..3fb6277 100644
--- a/doc/avconv.texi
+++ b/doc/avconv.texi
@@ -552,6 +552,24 @@ 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 since @command{avconv} has to copy the decoded frames from the GPU
+memory into main memory, hardware acceleration is not necessarily faster than
+software decoding. This option is thus mainly intended for testing.
 @end table
 
 @section Audio Options
-- 
1.7.10.4

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to