summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorDamiano Galassi <[email protected]>2016-11-10 19:39:25 +0100
committerGitHub <[email protected]>2016-11-10 19:39:25 +0100
commit1f35423947b227abe381e47d97eb746dbf0db7b5 (patch)
tree47967c4623df6a40a81cb1d68c0c5352920b4f61 /libhb
parentfd7a36c9ca3f1a2a17af4ba3fab62ef4ed5c2a21 (diff)
parentdfd46b588bfe5bbb668376ede16ef7337e510213 (diff)
Merge pull request #384 from galad87/colorspace
Select the appropriate coefficients for yuv<->rgb conversions.
Diffstat (limited to 'libhb')
-rw-r--r--libhb/cropscale.c3
-rw-r--r--libhb/decavcodec.c135
-rw-r--r--libhb/hb.c32
-rw-r--r--libhb/hbffmpeg.h4
-rw-r--r--libhb/qsv_filter_pp.c4
-rw-r--r--libhb/rendersub.c2
6 files changed, 110 insertions, 70 deletions
diff --git a/libhb/cropscale.c b/libhb/cropscale.c
index 33fc156f7..0ee653ce0 100644
--- a/libhb/cropscale.c
+++ b/libhb/cropscale.c
@@ -194,7 +194,8 @@ static hb_buffer_t* crop_scale( hb_filter_private_t * pv, hb_buffer_t * in )
in->f.width - (pv->crop[2] + pv->crop[3]),
in->f.height - (pv->crop[0] + pv->crop[1]),
in->f.fmt, out->f.width, out->f.height,
- out->f.fmt, SWS_LANCZOS|SWS_ACCURATE_RND);
+ out->f.fmt, SWS_LANCZOS|SWS_ACCURATE_RND,
+ hb_ff_get_colorspace(pv->job->title->color_matrix));
pv->width_in = in->f.width;
pv->height_in = in->f.height;
pv->pix_fmt = in->f.fmt;
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index 3f66b83d4..e021880b6 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -53,6 +53,10 @@ static void decavcodecClose( hb_work_object_t * );
static int decavcodecaInfo( hb_work_object_t *, hb_work_info_t * );
static int decavcodecaBSInfo( hb_work_object_t *, const hb_buffer_t *, hb_work_info_t * );
+static int get_color_prim(int color_primaries, hb_geometry_t geometry, hb_rational_t rate);
+static int get_color_transfer(int color_trc);
+static int get_color_matrix(int colorspace, hb_geometry_t geometry);
+
hb_work_object_t hb_decavcodeca =
{
.id = WORK_DECAVCODEC,
@@ -863,11 +867,16 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv )
{
if (pv->sws_context != NULL)
sws_freeContext(pv->sws_context);
+
+ hb_geometry_t geometry = {context->width, context->height};
+ int color_matrix = get_color_matrix(context->colorspace, geometry);
+
pv->sws_context = hb_sws_get_context(context->width,
context->height,
context->pix_fmt,
w, h, AV_PIX_FMT_YUV420P,
- SWS_LANCZOS|SWS_ACCURATE_RND);
+ SWS_LANCZOS|SWS_ACCURATE_RND,
+ hb_ff_get_colorspace(color_matrix));
pv->sws_width = context->width;
pv->sws_height = context->height;
pv->sws_pix_fmt = context->pix_fmt;
@@ -1676,103 +1685,107 @@ static void compute_frame_duration( hb_work_private_t *pv )
}
}
-static int decavcodecvInfo( hb_work_object_t *w, hb_work_info_t *info )
+static int get_color_prim(int color_primaries, hb_geometry_t geometry, hb_rational_t rate)
{
- hb_work_private_t *pv = w->private_data;
-
- int clock_min, clock_max, clock;
- hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
-
- memset( info, 0, sizeof(*info) );
-
- if (pv->context == NULL)
- return 0;
-
- info->bitrate = pv->context->bit_rate;
- // HandBrake's video pipeline uses yuv420 color. This means all
- // dimensions must be even. So we must adjust the dimensions
- // of incoming video if not even.
- info->geometry.width = pv->context->width & ~1;
- info->geometry.height = pv->context->height & ~1;
-
- info->geometry.par.num = pv->context->sample_aspect_ratio.num;
- info->geometry.par.den = pv->context->sample_aspect_ratio.den;
-
- compute_frame_duration( pv );
- info->rate.num = clock;
- info->rate.den = pv->duration * (clock / 90000.);
-
- info->profile = pv->context->profile;
- info->level = pv->context->level;
- info->name = pv->context->codec->name;
-
- switch( pv->context->color_primaries )
+ switch (color_primaries)
{
case AVCOL_PRI_BT709:
- info->color_prim = HB_COLR_PRI_BT709;
- break;
+ return HB_COLR_PRI_BT709;
case AVCOL_PRI_BT470BG:
- info->color_prim = HB_COLR_PRI_EBUTECH;
- break;
+ return HB_COLR_PRI_EBUTECH;
case AVCOL_PRI_BT470M:
case AVCOL_PRI_SMPTE170M:
case AVCOL_PRI_SMPTE240M:
- info->color_prim = HB_COLR_PRI_SMPTEC;
- break;
+ return HB_COLR_PRI_SMPTEC;
default:
{
- if ((info->geometry.width >= 1280 || info->geometry.height >= 720)||
- (info->geometry.width > 720 && info->geometry.height > 576 ))
+ if ((geometry.width >= 1280 || geometry.height >= 720)||
+ (geometry.width > 720 && geometry.height > 576 ))
// ITU BT.709 HD content
- info->color_prim = HB_COLR_PRI_BT709;
- else if( info->rate.den == 1080000 )
+ return HB_COLR_PRI_BT709;
+ else if (rate.den == 1080000)
// ITU BT.601 DVD or SD TV content (PAL)
- info->color_prim = HB_COLR_PRI_EBUTECH;
+ return HB_COLR_PRI_EBUTECH;
else
// ITU BT.601 DVD or SD TV content (NTSC)
- info->color_prim = HB_COLR_PRI_SMPTEC;
- break;
+ return HB_COLR_PRI_SMPTEC;
}
}
+}
- switch( pv->context->color_trc )
+static int get_color_transfer(int color_trc)
+{
+ switch (color_trc)
{
case AVCOL_TRC_SMPTE240M:
- info->color_transfer = HB_COLR_TRA_SMPTE240M;
- break;
+ return HB_COLR_TRA_SMPTE240M;
default:
// ITU BT.601, BT.709, anything else
- info->color_transfer = HB_COLR_TRA_BT709;
- break;
+ return HB_COLR_TRA_BT709;
}
+}
- switch( pv->context->colorspace )
+static int get_color_matrix(int colorspace, hb_geometry_t geometry)
+{
+ switch (colorspace)
{
case AVCOL_SPC_BT709:
- info->color_matrix = HB_COLR_MAT_BT709;
- break;
+ return HB_COLR_MAT_BT709;
case AVCOL_SPC_FCC:
case AVCOL_SPC_BT470BG:
case AVCOL_SPC_SMPTE170M:
case AVCOL_SPC_RGB: // libswscale rgb2yuv
- info->color_matrix = HB_COLR_MAT_SMPTE170M;
- break;
+ return HB_COLR_MAT_SMPTE170M;
case AVCOL_SPC_SMPTE240M:
- info->color_matrix = HB_COLR_MAT_SMPTE240M;
- break;
+ return HB_COLR_MAT_SMPTE240M;
default:
{
- if ((info->geometry.width >= 1280 || info->geometry.height >= 720)||
- (info->geometry.width > 720 && info->geometry.height > 576 ))
+ if ((geometry.width >= 1280 || geometry.height >= 720)||
+ (geometry.width > 720 && geometry.height > 576 ))
// ITU BT.709 HD content
- info->color_matrix = HB_COLR_MAT_BT709;
+ return HB_COLR_MAT_BT709;
else
// ITU BT.601 DVD or SD TV content (PAL)
// ITU BT.601 DVD or SD TV content (NTSC)
- info->color_matrix = HB_COLR_MAT_SMPTE170M;
- break;
+ return HB_COLR_MAT_SMPTE170M;
}
}
+}
+
+
+static int decavcodecvInfo( hb_work_object_t *w, hb_work_info_t *info )
+{
+ hb_work_private_t *pv = w->private_data;
+
+ int clock_min, clock_max, clock;
+ hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
+
+ memset( info, 0, sizeof(*info) );
+
+ if (pv->context == NULL)
+ return 0;
+
+ info->bitrate = pv->context->bit_rate;
+ // HandBrake's video pipeline uses yuv420 color. This means all
+ // dimensions must be even. So we must adjust the dimensions
+ // of incoming video if not even.
+ info->geometry.width = pv->context->width & ~1;
+ info->geometry.height = pv->context->height & ~1;
+
+ info->geometry.par.num = pv->context->sample_aspect_ratio.num;
+ info->geometry.par.den = pv->context->sample_aspect_ratio.den;
+
+ compute_frame_duration( pv );
+ info->rate.num = clock;
+ info->rate.den = pv->duration * (clock / 90000.);
+
+ info->profile = pv->context->profile;
+ info->level = pv->context->level;
+ info->name = pv->context->codec->name;
+
+ info->color_prim = get_color_prim(pv->context->color_primaries, info->geometry, info->rate);
+ info->color_transfer = get_color_transfer(pv->context->color_trc);
+ info->color_matrix = get_color_matrix(pv->context->colorspace, info->geometry);
info->video_decode_support = HB_DECODE_SUPPORT_SW;
switch (pv->context->codec_id)
diff --git a/libhb/hb.c b/libhb/hb.c
index 05af04953..cbca91b4d 100644
--- a/libhb/hb.c
+++ b/libhb/hb.c
@@ -206,10 +206,32 @@ static int handle_jpeg(enum AVPixelFormat *format)
}
}
+int hb_ff_get_colorspace(int color_matrix)
+{
+ int color_space = SWS_CS_DEFAULT;
+
+ switch (color_matrix)
+ {
+ case HB_COLR_MAT_SMPTE170M:
+ color_space = SWS_CS_ITU601;
+ break;
+ case HB_COLR_MAT_SMPTE240M:
+ color_space = SWS_CS_SMPTE240M;
+ break;
+ case HB_COLR_MAT_BT709:
+ color_space = SWS_CS_ITU709;
+ break;
+ default:
+ break;
+ }
+
+ return color_space;
+}
+
struct SwsContext*
hb_sws_get_context(int srcW, int srcH, enum AVPixelFormat srcFormat,
int dstW, int dstH, enum AVPixelFormat dstFormat,
- int flags)
+ int flags, int colorspace)
{
struct SwsContext * ctx;
@@ -235,9 +257,9 @@ hb_sws_get_context(int srcW, int srcH, enum AVPixelFormat srcFormat,
av_opt_set_int(ctx, "sws_flags", flags, 0);
sws_setColorspaceDetails( ctx,
- sws_getCoefficients( SWS_CS_DEFAULT ), // src colorspace
+ sws_getCoefficients( colorspace ), // src colorspace
srcRange, // src range 0 = MPG, 1 = JPG
- sws_getCoefficients( SWS_CS_DEFAULT ), // dst colorspace
+ sws_getCoefficients( colorspace ), // dst colorspace
dstRange, // dst range 0 = MPG, 1 = JPG
0, // brightness
1 << 16, // contrast
@@ -806,11 +828,13 @@ hb_image_t* hb_get_preview2(hb_handle_t * h, int title_idx, int picture,
geo->crop[0], geo->crop[2] );
}
+ int colorspace = hb_ff_get_colorspace(title->color_matrix);
+
// Get scaling context
context = hb_sws_get_context(
title->geometry.width - (geo->crop[2] + geo->crop[3]),
title->geometry.height - (geo->crop[0] + geo->crop[1]),
- AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_RGB32, swsflags);
+ AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_RGB32, swsflags, colorspace);
if (context == NULL)
{
diff --git a/libhb/hbffmpeg.h b/libhb/hbffmpeg.h
index 5efd4244b..63bee5402 100644
--- a/libhb/hbffmpeg.h
+++ b/libhb/hbffmpeg.h
@@ -29,7 +29,9 @@ const char* const* hb_av_preset_get_names(int encoder);
uint64_t hb_ff_mixdown_xlat(int hb_mixdown, int *downmix_mode);
void hb_ff_set_sample_fmt(AVCodecContext *, AVCodec *, enum AVSampleFormat);
+int hb_ff_get_colorspace(int color_matrix);
+
struct SwsContext*
hb_sws_get_context(int srcW, int srcH, enum AVPixelFormat srcFormat,
int dstW, int dstH, enum AVPixelFormat dstFormat,
- int flags);
+ int flags, int colorspace);
diff --git a/libhb/qsv_filter_pp.c b/libhb/qsv_filter_pp.c
index 55aa30357..7850d3b9a 100644
--- a/libhb/qsv_filter_pp.c
+++ b/libhb/qsv_filter_pp.c
@@ -288,13 +288,13 @@ static int hb_qsv_filter_pre_init( hb_filter_object_t * filter,
AV_PIX_FMT_NV12,
pv->job->title->geometry.width, pv->job->title->geometry.height,
AV_PIX_FMT_YUV420P,
- SWS_LANCZOS|SWS_ACCURATE_RND);
+ SWS_LANCZOS|SWS_ACCURATE_RND, SWS_CS_DEFAULT);
pv->sws_context_to_nv12 = hb_sws_get_context(
pv->job->title->geometry.width, pv->job->title->geometry.height,
AV_PIX_FMT_YUV420P,
pv->job->title->geometry.width, pv->job->title->geometry.height,
AV_PIX_FMT_NV12,
- SWS_LANCZOS|SWS_ACCURATE_RND);
+ SWS_LANCZOS|SWS_ACCURATE_RND, SWS_CS_DEFAULT);
return 0;
}
int pre_process_frame(hb_buffer_t *in, av_qsv_context* qsv, hb_filter_private_t * pv ){
diff --git a/libhb/rendersub.c b/libhb/rendersub.c
index 4ecb726d8..6ebfffcb5 100644
--- a/libhb/rendersub.c
+++ b/libhb/rendersub.c
@@ -240,7 +240,7 @@ static hb_buffer_t * ScaleSubtitle(hb_filter_private_t *pv,
pv->sws = hb_sws_get_context(
sub->f.width, sub->f.height, sub->f.fmt,
scaled->f.width, scaled->f.height, sub->f.fmt,
- SWS_LANCZOS|SWS_ACCURATE_RND);
+ SWS_LANCZOS|SWS_ACCURATE_RND, SWS_CS_DEFAULT);
pv->sws_width = width;
pv->sws_height = height;
}