]> granicus.if.org Git - handbrake/commitdiff
decavcodec: enable QSV-accelerated H.264 decoding with libavcodec.
authorTim Walker <tdskywalker@gmail.com>
Sun, 11 Sep 2016 00:45:52 +0000 (02:45 +0200)
committerTim Walker <tdskywalker@gmail.com>
Sun, 11 Sep 2016 00:45:52 +0000 (02:45 +0200)
Videos get decoded to NV12 in system memory and converted to our
internal colorspace via libswscale. It should be noted that QSV-
accelerated decoding now works with all our videos encoders :-)

libhb/decavcodec.c
libhb/enc_qsv.c
libhb/qsv_common.c
libhb/work.c

index eef1059df6cc187934283dc8d996faa54b6e570c..7951ad05459dbf6ae7a995dc53c8691aabe4cd04 100644 (file)
@@ -347,7 +347,8 @@ static void closePrivData( hb_work_private_t ** ppv )
              * still need that session for QSV filtering and/or encoding, so we
              * we can't close the context here until we implement a proper fix.
              */
-            if (!pv->qsv.decode)
+            if (pv->qsv.decode == NULL ||
+                pv->qsv.config.io_pattern != MFX_IOPATTERN_OUT_OPAQUE_MEMORY)
 #endif
             {
                 hb_avcodec_close(pv->context);
@@ -1036,7 +1037,9 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
     }
 
 #ifdef USE_QSV
-    if (pv->qsv.decode && pv->job->qsv.ctx == NULL && pv->video_codec_opened > 0)
+    if (pv->qsv.decode &&
+        pv->qsv.config.io_pattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY &&
+        pv->job->qsv.ctx == NULL && pv->video_codec_opened > 0)
     {
         // this is quite late, but we can't be certain that the QSV context is
         // available until after we call avcodec_decode_video2() at least once
@@ -1288,7 +1291,8 @@ static void decodeVideo( hb_work_object_t *w, hb_buffer_t * in)
             continue;
         }
 #ifdef USE_QSV
-        if (pv->qsv.decode)
+        if (pv->qsv.decode &&
+            pv->qsv.config.io_pattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY)
         {
             // flush a second time
             while (decodeFrame(w, NULL))
@@ -1317,12 +1321,13 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
     hb_buffer_list_clear(&pv->list);
 
 #ifdef USE_QSV
-    if (hb_qsv_decode_is_enabled(job))
+    if ((pv->qsv.decode = hb_qsv_decode_is_enabled(job)))
     {
-        // determine which encoder we're using
+        pv->qsv.codec_name = hb_qsv_decode_get_codec_name(w->codec_param);
+        pv->qsv.config.io_pattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
+#if 0 // TODO: re-implement QSV zerocopy path
         hb_qsv_info_t *info = hb_qsv_info_get(job->vcodec);
-        pv->qsv.decode = info != NULL;
-        if (pv->qsv.decode)
+        if (info != NULL)
         {
             // setup the QSV configuration
             pv->qsv.config.io_pattern         = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
@@ -1336,12 +1341,8 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
                 // more surfaces may be needed for the lookahead
                 pv->qsv.config.additional_buffers = 160;
             }
-            pv->qsv.codec_name = hb_qsv_decode_get_codec_name(w->codec_param);
         }
-    }
-    else
-    {
-        pv->qsv.decode = 0;
+#endif // QSV zerocopy path
     }
 #endif
 
@@ -1379,7 +1380,8 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
         pv->context->error_concealment = FF_EC_GUESS_MVS|FF_EC_DEBLOCK;
 
 #ifdef USE_QSV
-        if (pv->qsv.decode)
+        if (pv->qsv.decode &&
+            pv->qsv.config.io_pattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY)
         {
             // set the QSV configuration before opening the decoder
             pv->context->hwaccel_context = &pv->qsv.config;
@@ -1545,7 +1547,8 @@ static int decavcodecvWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
         }
 
 #ifdef USE_QSV
-        if (pv->qsv.decode)
+        if (pv->qsv.decode &&
+            pv->qsv.config.io_pattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY)
         {
             // set the QSV configuration before opening the decoder
             pv->context->hwaccel_context = &pv->qsv.config;
@@ -1769,21 +1772,25 @@ static int decavcodecvInfo( hb_work_object_t *w, hb_work_info_t *info )
     }
 
     info->video_decode_support = HB_DECODE_SUPPORT_SW;
-    switch (pv->context->codec_id)
-    {
-        case AV_CODEC_ID_H264:
-            if (pv->context->pix_fmt == AV_PIX_FMT_YUV420P ||
-                pv->context->pix_fmt == AV_PIX_FMT_YUVJ420P)
-            {
+
 #ifdef USE_QSV
-                info->video_decode_support |= HB_DECODE_SUPPORT_QSV;
-#endif
-            }
-            break;
+    if (avcodec_find_decoder_by_name(hb_qsv_decode_get_codec_name(pv->context->codec_id)))
+    {
+        switch (pv->context->codec_id)
+        {
+            case AV_CODEC_ID_H264:
+                if (pv->context->pix_fmt == AV_PIX_FMT_YUV420P ||
+                    pv->context->pix_fmt == AV_PIX_FMT_YUVJ420P)
+                {
+                    info->video_decode_support |= HB_DECODE_SUPPORT_QSV;
+                }
+                break;
 
-        default:
-            break;
+            default:
+                break;
+        }
     }
+#endif
 
     return 1;
 }
index 4030cd30c0a9ad1033e65c3cbc1f54ad3d9ada7e..ced5f3e1c49240c45b1ad49df7b9582ee9bc34a0 100644 (file)
@@ -668,8 +668,8 @@ int encqsvInit(hb_work_object_t *w, hb_job_t *job)
     hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t));
     w->private_data       = pv;
 
+    pv->is_sys_mem         = 1; // TODO: re-implement QSV VPP filtering support
     pv->job                = job;
-    pv->is_sys_mem         = hb_qsv_decode_is_enabled(job) == 0;
     pv->qsv_info           = hb_qsv_info_get(job->vcodec);
     pv->delayed_processing = hb_list_init();
     pv->last_start         = INT64_MIN;
index 27e44a7bcf2dec1b3915e40646785f3f6aa3f63a..28cc12ad7057dc136ff55f88bf94b91ebcc1e832 100644 (file)
@@ -905,6 +905,12 @@ const char* hb_qsv_decode_get_codec_name(enum AVCodecID codec_id)
         case AV_CODEC_ID_H264:
             return "h264_qsv";
 
+        case AV_CODEC_ID_HEVC:
+            return "hevc_qsv";
+
+        case AV_CODEC_ID_MPEG2VIDEO:
+            return "mpeg2_qsv";
+
         default:
             return NULL;
     }
@@ -912,17 +918,8 @@ const char* hb_qsv_decode_get_codec_name(enum AVCodecID codec_id)
 
 int hb_qsv_decode_is_enabled(hb_job_t *job)
 {
-    /*
-     * XXX: we haven't yet adjusted our QSV decoder wrapper to use libav's new
-     *      QSV-accelerated decoder, and our old custom QSV-accelerated decoder
-     *      for libav hasn't been updated to work with newer libav releases, so
-     *      we can't use QSV-accelerated decoding at all for the time being.
-     *
-     * return ((job != NULL && job->qsv.decode)                        &&
-     *         (job->vcodec                      & HB_VCODEC_QSV_MASK) &&
-     *         (job->title->video_decode_support & HB_DECODE_SUPPORT_QSV));
-     */
-    return 0;
+    return ((job != NULL && job->qsv.decode) &&
+            (job->title->video_decode_support & HB_DECODE_SUPPORT_QSV));
 }
 
 int hb_qsv_copyframe_is_slow(int encoder)
index a2290cc8b0830a006efa60a199d2a7eb8b20bf6f..4b8d95d47927b53a959e0f4476231491ccfcd101 100644 (file)
@@ -1124,6 +1124,7 @@ static int sanitize_audio(hb_job_t *job)
 static int sanitize_qsv( hb_job_t * job )
 {
 #ifdef USE_QSV
+#if 0 // TODO: re-implement QSV VPP filtering and QSV zerocopy path
     int i;
 
     /*
@@ -1177,10 +1178,10 @@ static int sanitize_qsv( hb_job_t * job )
     }
 
     /*
-     * When QSV is used for decoding, not all CPU-based filters are supported,
-     * so we need to do a little extra setup here.
+     * When QSV's VPP is used for filtering, not all CPU filters
+     * are supported, so we need to do a little extra setup here.
      */
-    if (hb_qsv_decode_is_enabled(job))
+    if (job->vcodec & HB_VCODEC_QSV_MASK)
     {
         int vpp_settings[7];
         int num_cpu_filters = 0;
@@ -1291,7 +1292,8 @@ static int sanitize_qsv( hb_job_t * job )
             }
         }
     }
-#endif
+#endif // QSV VPP filtering and QSV zerocopy path
+#endif // USE_QSV
 
     return 0;
 }
@@ -1481,7 +1483,8 @@ static void do_job(hb_job_t *job)
                job->vrate.num,  job->vrate.den);
 
 #ifdef USE_QSV
-    if (hb_qsv_decode_is_enabled(job))
+#if 0 // TODO: re-implement QSV zerocopy path
+    if (hb_qsv_decode_is_enabled(job) && (job->vcodec & HB_VCODEC_QSV_MASK))
     {
         job->fifo_mpeg2  = hb_fifo_init( FIFO_MINI, FIFO_MINI_WAKE );
         job->fifo_raw    = hb_fifo_init( FIFO_MINI, FIFO_MINI_WAKE );
@@ -1494,6 +1497,7 @@ static void do_job(hb_job_t *job)
         }
     }
     else
+#endif // QSV zerocopy path
 #endif
     {
         job->fifo_mpeg2  = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE );