]> granicus.if.org Git - handbrake/commitdiff
Select the appropriate coefficients for yuv<->rgb conversions.
authorDamiano Galassi <damiog@gmail.com>
Mon, 7 Nov 2016 10:46:40 +0000 (11:46 +0100)
committerDamiano Galassi <damiog@gmail.com>
Tue, 8 Nov 2016 09:06:48 +0000 (10:06 +0100)
libhb/cropscale.c
libhb/decavcodec.c
libhb/hb.c
libhb/hbffmpeg.h
libhb/qsv_filter_pp.c
libhb/rendersub.c

index 33fc156f73d82a4b4020b1853ea889ed23ce2f98..0ee653ce08bcc008b3088c1a39fc039c05d4568e 100644 (file)
@@ -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;
index 3f66b83d4581e3ab7704cc7ecf9580f452c3fb3b..e021880b646747fdca27e7fa26e004096159da1b 100644 (file)
@@ -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)
index 05af0495368f5820f103ba808cbda6d953c04eb0..cbca91b4dca885b1cf8bb4d12f30f0d28863fdde 100644 (file)
@@ -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)
     {
index 5efd4244b249ed65e9a62465840a3ded7647aca2..63bee540226034f663d001bed2f7bce9a95fb039 100644 (file)
@@ -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);
index 55aa30357c9a40f6f10fc097230aef0fea510f38..7850d3b9ab6b293f2703ad9b8899af173f0686b8 100644 (file)
@@ -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 ){
index 4ecb726d8b23e704b4cabaf7a99d57c31ebf4524..6ebfffcb5afdc97e58bc805bd6d8142050b8f35c 100644 (file)
@@ -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;
         }