]> git.sesse.net Git - ffmpeg/blobdiff - fftools/ffmpeg_hw.c
hwcontext_vulkan: dlopen libvulkan
[ffmpeg] / fftools / ffmpeg_hw.c
index 2ec181385430b260c662b53ea97275a80aa7c59f..fc4a5d31d6aeaeca7a4dd762dc485a5d364c55ce 100644 (file)
@@ -19,6 +19,8 @@
 #include <string.h>
 
 #include "libavutil/avstring.h"
+#include "libavutil/pixdesc.h"
+#include "libavfilter/buffersink.h"
 
 #include "ffmpeg.h"
 
@@ -99,7 +101,7 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
     // -> av_hwdevice_ctx_create_derived()
 
     AVDictionary *options = NULL;
-    char *type_name = NULL, *name = NULL, *device = NULL;
+    const char *type_name = NULL, *name = NULL, *device = NULL;
     enum AVHWDeviceType type;
     HWDevice *dev, *src;
     AVBufferRef *device_ref = NULL;
@@ -155,10 +157,12 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
         ++p;
         q = strchr(p, ',');
         if (q) {
-            device = av_strndup(p, q - p);
-            if (!device) {
-                err = AVERROR(ENOMEM);
-                goto fail;
+            if (q - p > 0) {
+                device = av_strndup(p, q - p);
+                if (!device) {
+                    err = AVERROR(ENOMEM);
+                    goto fail;
+                }
             }
             err = av_dict_parse_string(&options, q + 1, "=", ",", 0);
             if (err < 0) {
@@ -168,7 +172,8 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
         }
 
         err = av_hwdevice_ctx_create(&device_ref, type,
-                                     device ? device : p, options, 0);
+                                     q ? device : p[0] ? p : NULL,
+                                     options, 0);
         if (err < 0)
             goto fail;
 
@@ -413,18 +418,57 @@ int hw_device_setup_for_decode(InputStream *ist)
 
 int hw_device_setup_for_encode(OutputStream *ost)
 {
-    HWDevice *dev;
+    const AVCodecHWConfig *config;
+    HWDevice *dev = NULL;
+    AVBufferRef *frames_ref = NULL;
+    int i;
+
+    if (ost->filter) {
+        frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter);
+        if (frames_ref &&
+            ((AVHWFramesContext*)frames_ref->data)->format ==
+            ost->enc_ctx->pix_fmt) {
+            // Matching format, will try to use hw_frames_ctx.
+        } else {
+            frames_ref = NULL;
+        }
+    }
+
+    for (i = 0;; i++) {
+        config = avcodec_get_hw_config(ost->enc, i);
+        if (!config)
+            break;
+
+        if (frames_ref &&
+            config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX &&
+            (config->pix_fmt == AV_PIX_FMT_NONE ||
+             config->pix_fmt == ost->enc_ctx->pix_fmt)) {
+            av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input "
+                   "frames context (format %s) with %s encoder.\n",
+                   av_get_pix_fmt_name(ost->enc_ctx->pix_fmt),
+                   ost->enc->name);
+            ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref);
+            if (!ost->enc_ctx->hw_frames_ctx)
+                return AVERROR(ENOMEM);
+            return 0;
+        }
+
+        if (!dev &&
+            config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)
+            dev = hw_device_get_by_type(config->device_type);
+    }
 
-    dev = hw_device_match_by_codec(ost->enc);
     if (dev) {
+        av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s "
+               "(type %s) with %s encoder.\n", dev->name,
+               av_hwdevice_get_type_name(dev->type), ost->enc->name);
         ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
         if (!ost->enc_ctx->hw_device_ctx)
             return AVERROR(ENOMEM);
-        return 0;
     } else {
         // No device required, or no device available.
-        return 0;
     }
+    return 0;
 }
 
 static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
@@ -477,3 +521,31 @@ int hwaccel_decode_init(AVCodecContext *avctx)
 
     return 0;
 }
+
+int hw_device_setup_for_filter(FilterGraph *fg)
+{
+    HWDevice *dev;
+    int i;
+
+    // If the user has supplied exactly one hardware device then just
+    // give it straight to every filter for convenience.  If more than
+    // one device is available then the user needs to pick one explcitly
+    // with the filter_hw_device option.
+    if (filter_hw_device)
+        dev = filter_hw_device;
+    else if (nb_hw_devices == 1)
+        dev = hw_devices[0];
+    else
+        dev = NULL;
+
+    if (dev) {
+        for (i = 0; i < fg->graph->nb_filters; i++) {
+            fg->graph->filters[i]->hw_device_ctx =
+                av_buffer_ref(dev->device_ref);
+            if (!fg->graph->filters[i]->hw_device_ctx)
+                return AVERROR(ENOMEM);
+        }
+    }
+
+    return 0;
+}