summaryrefslogtreecommitdiffstats
path: root/libhb/work.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/work.c')
-rw-r--r--libhb/work.c186
1 files changed, 172 insertions, 14 deletions
diff --git a/libhb/work.c b/libhb/work.c
index b23a3619a..7f00ddab3 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -11,6 +11,11 @@
#include "a52dec/a52.h"
#include "libavformat/avformat.h"
+#ifdef USE_QSV
+#include "qsv_common.h"
+#include "qsv_filter_pp.h"
+#endif
+
typedef struct
{
hb_list_t * jobs;
@@ -231,8 +236,18 @@ void hb_display_job_info(hb_job_t *job)
hb_log(" * video track");
- hb_log(" + decoder: %s", title->video_codec_name );
-
+#ifdef USE_QSV
+ if (hb_qsv_decode_is_enabled(job))
+ {
+ hb_log(" + decoder: %s",
+ hb_qsv_decode_get_codec_name(title->video_codec_param));
+ }
+ else
+#endif
+ {
+ hb_log(" + decoder: %s", title->video_codec_name);
+ }
+
if( title->video_bitrate )
{
hb_log( " + bitrate %d kbps", title->video_bitrate / 1000 );
@@ -307,15 +322,15 @@ void hb_display_job_info(hb_job_t *job)
{
hb_log(" + options: %s", job->advanced_opts);
}
- if( job->h264_profile && *job->h264_profile &&
- job->vcodec == HB_VCODEC_X264 )
+ if (job->h264_profile != NULL && *job->h264_profile &&
+ (job->vcodec & HB_VCODEC_H264_MASK))
{
- hb_log( " + h264 profile: %s", job->h264_profile );
+ hb_log(" + h264 profile: %s", job->h264_profile);
}
- if( job->h264_level && *job->h264_level &&
- job->vcodec == HB_VCODEC_X264 )
+ if (job->h264_level != NULL && *job->h264_level &&
+ (job->vcodec & HB_VCODEC_H264_MASK))
{
- hb_log( " + h264 level: %s", job->h264_level );
+ hb_log(" + h264 level: %s", job->h264_level);
}
if (job->vquality >= 0)
@@ -659,6 +674,114 @@ static void do_job(hb_job_t *job)
}
}
+#ifdef USE_QSV
+ /*
+ * When QSV is used for decoding, not all CPU-based filters are supported,
+ * so we need to do a little extra setup here.
+ */
+ if (hb_qsv_decode_is_enabled(job))
+ {
+ int vpp_settings[7];
+ int num_cpu_filters = 0;
+ hb_filter_object_t *filter;
+ // default values for VPP filter
+ vpp_settings[0] = job->title->width;
+ vpp_settings[1] = job->title->height;
+ vpp_settings[2] = job->title->crop[0];
+ vpp_settings[3] = job->title->crop[1];
+ vpp_settings[4] = job->title->crop[2];
+ vpp_settings[5] = job->title->crop[3];
+ vpp_settings[6] = 0; // deinterlace: off
+ if (job->list_filter != NULL && hb_list_count(job->list_filter) > 0)
+ {
+ while (hb_list_count(job->list_filter) > num_cpu_filters)
+ {
+ filter = hb_list_item(job->list_filter, num_cpu_filters);
+ switch (filter->id)
+ {
+ // cropping and scaling always done via VPP filter
+ case HB_FILTER_CROP_SCALE:
+ if (filter->settings == NULL || *filter->settings == '\0')
+ {
+ // VPP defaults were set above, so not a problem
+ // however, this should never happen, print an error
+ hb_error("do_job: '%s': no settings!", filter->name);
+ }
+ else
+ {
+ sscanf(filter->settings, "%d:%d:%d:%d:%d:%d",
+ &vpp_settings[0], &vpp_settings[1],
+ &vpp_settings[2], &vpp_settings[3],
+ &vpp_settings[4], &vpp_settings[5]);
+ }
+ hb_list_rem(job->list_filter, filter);
+ hb_filter_close(&filter);
+ break;
+
+ // pick VPP or CPU deinterlace depending on settings
+ case HB_FILTER_DEINTERLACE:
+ if (filter->settings == NULL || !strcmp(filter->settings, "qsv"))
+ {
+ // deinterlacing via VPP filter
+ vpp_settings[6] = 1;
+ hb_list_rem(job->list_filter, filter);
+ hb_filter_close(&filter);
+ }
+ else
+ {
+ // validated
+ num_cpu_filters++;
+ }
+ break;
+
+ // then, validated filters
+ case HB_FILTER_ROTATE: // TODO: use Media SDK for this
+ case HB_FILTER_RENDER_SUB:
+ num_cpu_filters++;
+ break;
+
+ // finally, drop all unsupported filters
+ default:
+ hb_log("do_job: full QSV path, removing unsupported filter '%s'",
+ filter->name);
+ hb_list_rem(job->list_filter, filter);
+ hb_filter_close(&filter);
+ break;
+ }
+ }
+ if (num_cpu_filters > 0)
+ {
+ // we need filters to copy to system memory and back
+ filter = hb_filter_init(HB_FILTER_QSV_PRE);
+ hb_add_filter(job, filter, NULL);
+ filter = hb_filter_init(HB_FILTER_QSV_POST);
+ hb_add_filter(job, filter, NULL);
+ }
+ if (vpp_settings[0] != job->title->width ||
+ vpp_settings[1] != job->title->height ||
+ vpp_settings[2] >= 1 /* crop */ ||
+ vpp_settings[3] >= 1 /* crop */ ||
+ vpp_settings[4] >= 1 /* crop */ ||
+ vpp_settings[5] >= 1 /* crop */ ||
+ vpp_settings[6] >= 1 /* deinterlace */)
+ {
+ // we need the VPP filter
+ char *settings = hb_strdup_printf("%d:%d:%d:%d:%d:%d_dei:%d",
+ vpp_settings[0],
+ vpp_settings[1],
+ vpp_settings[2],
+ vpp_settings[3],
+ vpp_settings[4],
+ vpp_settings[5],
+ vpp_settings[6]);
+ filter = hb_filter_init(HB_FILTER_QSV);
+ hb_add_filter(job, filter, settings);
+ free(settings);
+ }
+ }
+ }
+#endif
+
// Filters have an effect on settings.
// So initialize the filters and update the job.
if( job->list_filter && hb_list_count( job->list_filter ) )
@@ -720,12 +843,25 @@ static void do_job(hb_job_t *job)
}
}
}
-
- job->fifo_mpeg2 = hb_fifo_init( FIFO_LARGE, FIFO_LARGE_WAKE );
- job->fifo_raw = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE );
- job->fifo_sync = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE );
- job->fifo_mpeg4 = hb_fifo_init( FIFO_LARGE, FIFO_LARGE_WAKE );
- job->fifo_render = NULL; // Attached to filter chain
+
+#ifdef USE_QSV
+ if (hb_qsv_decode_is_enabled(job))
+ {
+ job->fifo_mpeg2 = hb_fifo_init( FIFO_MINI, FIFO_MINI_WAKE );
+ job->fifo_raw = hb_fifo_init( FIFO_MINI, FIFO_MINI_WAKE );
+ job->fifo_sync = hb_fifo_init( FIFO_MINI, FIFO_MINI_WAKE );
+ job->fifo_render = hb_fifo_init( FIFO_MINI, FIFO_MINI_WAKE );
+ job->fifo_mpeg4 = hb_fifo_init( FIFO_MINI, FIFO_MINI_WAKE );
+ }
+ else
+#endif
+ {
+ job->fifo_mpeg2 = hb_fifo_init( FIFO_LARGE, FIFO_LARGE_WAKE );
+ job->fifo_raw = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE );
+ job->fifo_sync = hb_fifo_init( FIFO_SMALL, FIFO_SMALL_WAKE );
+ job->fifo_mpeg4 = hb_fifo_init( FIFO_LARGE, FIFO_LARGE_WAKE );
+ job->fifo_render = NULL; // Attached to filter chain
+ }
/* Audio fifos must be initialized before sync */
if (!job->indepth_scan)
@@ -1028,6 +1164,9 @@ static void do_job(hb_job_t *job)
case HB_VCODEC_X264:
w = hb_get_work( WORK_ENCX264 );
break;
+ case HB_VCODEC_QSV_H264:
+ w = hb_get_work( WORK_ENCQSV );
+ break;
case HB_VCODEC_THEORA:
w = hb_get_work( WORK_ENCTHEORA );
break;
@@ -1524,8 +1663,27 @@ static void filter_loop( void * _f )
}
buf_out = NULL;
+
+#ifdef USE_QSV
+ hb_buffer_t *last_buf_in = buf_in;
+#endif
+
f->status = f->work( f, &buf_in, &buf_out );
+#ifdef USE_QSV
+ if (f->status == HB_FILTER_DELAY &&
+ last_buf_in->qsv_details.filter_details != NULL && buf_out == NULL)
+ {
+ hb_filter_private_t_qsv *qsv_user = buf_in ? buf_in->qsv_details.filter_details : last_buf_in->qsv_details.filter_details ;
+ qsv_user->post.status = f->status;
+
+ hb_lock(qsv_user->post.frame_completed_lock);
+ qsv_user->post.frame_go = 1;
+ hb_cond_broadcast(qsv_user->post.frame_completed);
+ hb_unlock(qsv_user->post.frame_completed_lock);
+
+ }
+#endif
if ( buf_out && f->chapter_val && f->chapter_time <= buf_out->s.start )
{
buf_out->s.new_chap = f->chapter_val;