diff options
-rw-r--r-- | libhb/common.h | 22 | ||||
-rw-r--r-- | libhb/decavcodec.c | 68 | ||||
-rw-r--r-- | libhb/decmpeg2.c | 76 | ||||
-rw-r--r-- | libhb/encx264.c | 35 | ||||
-rw-r--r-- | libhb/muxmp4.c | 33 | ||||
-rw-r--r-- | libhb/scan.c | 3 | ||||
-rw-r--r-- | test/test.c | 21 |
7 files changed, 224 insertions, 34 deletions
diff --git a/libhb/common.h b/libhb/common.h index e8ca7e1fd..57d44450b 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -298,10 +298,26 @@ struct hb_job_s char *x264_tune; char *h264_level; int areBframes; + int color_matrix_code; int color_prim; int color_transfer; int color_matrix; +// see https://developer.apple.com/quicktime/icefloe/dispatch019.html#colr +#define HB_COLR_PRI_BT709 1 +#define HB_COLR_PRI_UNDEF 2 +#define HB_COLR_PRI_EBUTECH 5 // use for bt470bg +#define HB_COLR_PRI_SMPTEC 6 // smpte170m; also use for bt470m and smpte240m +// 0, 3-4, 7-65535: reserved +#define HB_COLR_TRA_BT709 1 // also use for bt470m, bt470bg and smpte170m +#define HB_COLR_TRA_UNDEF 2 +#define HB_COLR_TRA_SMPTE240M 7 +// 0, 3-6, 8-65535: reserved +#define HB_COLR_MAT_BT709 1 +#define HB_COLR_MAT_UNDEF 2 +#define HB_COLR_MAT_SMPTE170M 6 // also use for fcc and bt470bg +#define HB_COLR_MAT_SMPTE240M 7 +// 0, 3-5, 8-65535: reserved /* List of audio settings. */ hb_list_t * list_audio; @@ -685,6 +701,9 @@ struct hb_title_s int height; int pixel_aspect_width; int pixel_aspect_height; + int color_prim; + int color_transfer; + int color_matrix; int rate; int rate_base; int crop[4]; @@ -785,6 +804,9 @@ typedef struct hb_work_info_s int height; int pixel_aspect_width; int pixel_aspect_height; + int color_prim; + int color_transfer; + int color_matrix; }; struct { // info only valid for audio decoders int channel_layout; diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 1bba19990..33b45fa12 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -1336,11 +1336,77 @@ static int decavcodecvInfo( hb_work_object_t *w, hb_work_info_t *info ) info->level = pv->context->level; info->name = pv->context->codec->name; + switch( pv->context->color_primaries ) + { + case AVCOL_PRI_BT709: + info->color_prim = HB_COLR_PRI_BT709; + break; + case AVCOL_PRI_BT470BG: + info->color_prim = HB_COLR_PRI_EBUTECH; + break; + case AVCOL_PRI_BT470M: + case AVCOL_PRI_SMPTE170M: + case AVCOL_PRI_SMPTE240M: + info->color_prim = HB_COLR_PRI_SMPTEC; + break; + default: + { + if( ( info->width >= 1280 || info->height >= 720 ) || + ( info->width > 720 && info->height > 576 ) ) + // ITU BT.709 HD content + info->color_prim = HB_COLR_PRI_BT709; + else if( info->rate_base == 1080000 ) + // ITU BT.601 DVD or SD TV content (PAL) + info->color_prim = HB_COLR_PRI_EBUTECH; + else + // ITU BT.601 DVD or SD TV content (NTSC) + info->color_prim = HB_COLR_PRI_SMPTEC; + break; + } + } + + /* AVCOL_TRC_BT709 -> HB_COLR_TRA_BT709 + * AVCOL_TRC_GAMMA22 (bt470m) -> HB_COLR_TRA_BT709 + * AVCOL_TRC_GAMMA28 (bt470bg) -> HB_COLR_TRA_BT709 + * AVCOL_TRC_UNSPECIFIED, AVCOL_TRC_NB: + * -> ITU BT.709 -> HB_COLR_TRA_BT709 + * -> ITU BT.601 -> HB_COLR_TRA_BT709 + * TODO: AVCOL_TRC_SMPTE240M -> HB_COLR_TRA_SMPTE240M but it's not yet in Libav */ + info->color_transfer = HB_COLR_TRA_BT709; + + switch( pv->context->colorspace ) + { + case AVCOL_SPC_BT709: + info->color_matrix = HB_COLR_MAT_BT709; + break; + 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; + case AVCOL_SPC_SMPTE240M: + info->color_matrix = HB_COLR_MAT_SMPTE240M; + break; + default: + { + if( ( info->width >= 1280 || info->height >= 720 ) || + ( info->width > 720 && info->height > 576 ) ) + // ITU BT.709 HD content + info->color_matrix = 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 1; } static int decavcodecvBSInfo( hb_work_object_t *w, const hb_buffer_t *buf, - hb_work_info_t *info ) + hb_work_info_t *info ) { return 0; } diff --git a/libhb/decmpeg2.c b/libhb/decmpeg2.c index 7379964cf..82ba78e31 100644 --- a/libhb/decmpeg2.c +++ b/libhb/decmpeg2.c @@ -894,6 +894,82 @@ static int decmpeg2Info( hb_work_object_t *w, hb_work_info_t *info ) info->profile = m->info->sequence->profile_level_id >> 4; info->level = m->info->sequence->profile_level_id & 0xf; info->name = "mpeg2"; + + if( pv->libmpeg2->info->sequence->flags & SEQ_FLAG_COLOUR_DESCRIPTION ) + { + switch( pv->libmpeg2->info->sequence->colour_primaries ) + { + case 1: // ITU-R Recommendation 709 + info->color_prim = HB_COLR_PRI_BT709; + break; + case 5: // ITU-R Recommendation 624-4 System B, G + info->color_prim = HB_COLR_PRI_EBUTECH; + break; + case 4: // ITU-R Recommendation 624-4 System M + case 6: // SMPTE 170M + case 7: // SMPTE 240M + info->color_prim = HB_COLR_PRI_SMPTEC; + break; + default: + info->color_prim = HB_COLR_PRI_UNDEF; + break; + } + switch( pv->libmpeg2->info->sequence->transfer_characteristics ) + { + case 1: // ITU-R Recommendation 709 + case 4: // ITU-R Recommendation 624-4 System M + case 5: // ITU-R Recommendation 624-4 System B, G + case 6: // SMPTE 170M + info->color_transfer = HB_COLR_TRA_BT709; + break; + case 7: // SMPTE 240M + info->color_transfer = HB_COLR_TRA_SMPTE240M; + break; + default: + info->color_transfer = HB_COLR_TRA_UNDEF; + break; + } + switch( pv->libmpeg2->info->sequence->matrix_coefficients ) + { + case 1: // ITU-R Recommendation 709 + info->color_matrix = HB_COLR_MAT_BT709; + break; + case 4: // FCC + case 5: // ITU-R Recommendation 624-4 System B, G + case 6: // SMPTE 170M + info->color_matrix = HB_COLR_MAT_SMPTE170M; + break; + case 7: // SMPTE 240M + info->color_matrix = HB_COLR_MAT_SMPTE240M; + break; + default: + info->color_matrix = HB_COLR_MAT_UNDEF; + break; + } + } + else if( ( info->width >= 1280 || info->height >= 720 ) || + ( info->width > 720 && info->height > 576 ) ) + { + // ITU BT.709 HD content + info->color_prim = HB_COLR_PRI_BT709; + info->color_transfer = HB_COLR_TRA_BT709; + info->color_matrix = HB_COLR_MAT_BT709; + } + else if( info->rate_base == 1080000 ) + { + // ITU BT.601 DVD or SD TV content (PAL) + info->color_prim = HB_COLR_PRI_EBUTECH; + info->color_transfer = HB_COLR_TRA_BT709; + info->color_matrix = HB_COLR_MAT_SMPTE170M; + } + else + { + // ITU BT.601 DVD or SD TV content (NTSC) + info->color_prim = HB_COLR_PRI_SMPTEC; + info->color_transfer = HB_COLR_TRA_BT709; + info->color_matrix = HB_COLR_MAT_SMPTE170M; + } + return 1; } return 0; diff --git a/libhb/encx264.c b/libhb/encx264.c index f48aa499a..7345ab20e 100644 --- a/libhb/encx264.c +++ b/libhb/encx264.c @@ -139,27 +139,40 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) /* set up the VUI color model & gamma to match what the COLR atom * set in muxmp4.c says. See libhb/muxmp4.c for notes. */ - if( job->color_matrix_code == 3 ) + if( job->color_matrix_code == 4 ) { // Custom param.vui.i_colorprim = job->color_prim; param.vui.i_transfer = job->color_transfer; param.vui.i_colmatrix = job->color_matrix; } - else if( ( job->color_matrix_code == 2 ) || - ( job->color_matrix_code == 0 && ( job->title->width >= 1280 || job->title->height >= 720 ) ) ) + else if( job->color_matrix_code == 3 ) { // ITU BT.709 HD content - param.vui.i_colorprim = 1; - param.vui.i_transfer = 1; - param.vui.i_colmatrix = 1; + param.vui.i_colorprim = HB_COLR_PRI_BT709; + param.vui.i_transfer = HB_COLR_TRA_BT709; + param.vui.i_colmatrix = HB_COLR_MAT_BT709; + } + else if( job->color_matrix_code == 2 ) + { + // ITU BT.601 DVD or SD TV content (PAL) + param.vui.i_colorprim = HB_COLR_PRI_EBUTECH; + param.vui.i_transfer = HB_COLR_TRA_BT709; + param.vui.i_colmatrix = HB_COLR_MAT_SMPTE170M; + } + else if( job->color_matrix_code == 1 ) + { + // ITU BT.601 DVD or SD TV content (NTSC) + param.vui.i_colorprim = HB_COLR_PRI_SMPTEC; + param.vui.i_transfer = HB_COLR_TRA_BT709; + param.vui.i_colmatrix = HB_COLR_MAT_SMPTE170M; } else { - // ITU BT.601 DVD or SD TV content - param.vui.i_colorprim = 6; - param.vui.i_transfer = 1; - param.vui.i_colmatrix = 6; + // detected during scan + param.vui.i_colorprim = job->title->color_prim; + param.vui.i_transfer = job->title->color_transfer; + param.vui.i_colmatrix = job->title->color_matrix; } /* place job->advanced_opts in an hb_dict_t for convenience */ @@ -185,7 +198,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) /* Reload colorimetry settings in case custom values were set * in the advanced_opts string */ - job->color_matrix_code = 3; + job->color_matrix_code = 4; job->color_prim = param.vui.i_colorprim; job->color_transfer = param.vui.i_transfer; job->color_matrix = param.vui.i_colmatrix; diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index 31c235961..cad1d3944 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -214,29 +214,34 @@ static int MP4Init( hb_mux_object_t * m ) hb_error("muxmp4.c: Unsupported video encoder!"); } - // COLR atom for color and gamma correction. - // Per the notes at: - // http://developer.apple.com/quicktime/icefloe/dispatch019.html#colr - // http://forum.doom9.org/showthread.php?t=133982#post1090068 - // the user can set it from job->color_matrix_code, otherwise by default - // we say anything that's likely to be HD content is ITU BT.709 and - // DVD, SD TV & other content is ITU BT.601. We look at the title height - // rather than the job height here to get uncropped input dimensions. - if( job->color_matrix_code == 3 ) + /* COLR atom for color and gamma correction. Per the notes at: + * http://developer.apple.com/quicktime/icefloe/dispatch019.html#colr + * http://forum.doom9.org/showthread.php?t=133982#post1090068 + * The user can set it from job->color_matrix_code. */ + if( job->color_matrix_code == 4 ) { // Custom MP4AddColr(m->file, mux_data->track, job->color_prim, job->color_transfer, job->color_matrix); } - else if( ( job->color_matrix_code == 2 ) || - ( job->color_matrix_code == 0 && ( job->title->width >= 1280 || job->title->height >= 720 ) ) ) + else if( job->color_matrix_code == 3 ) { // ITU BT.709 HD content - MP4AddColr(m->file, mux_data->track, 1, 1, 1); + MP4AddColr(m->file, mux_data->track, HB_COLR_PRI_BT709, HB_COLR_TRA_BT709, HB_COLR_MAT_BT709); + } + else if( job->color_matrix_code == 2 ) + { + // ITU BT.601 DVD or SD TV content (PAL) + MP4AddColr(m->file, mux_data->track, HB_COLR_PRI_EBUTECH, HB_COLR_TRA_BT709, HB_COLR_MAT_SMPTE170M); + } + else if( job->color_matrix_code == 1 ) + { + // ITU BT.601 DVD or SD TV content (NTSC) + MP4AddColr(m->file, mux_data->track, HB_COLR_PRI_SMPTEC, HB_COLR_TRA_BT709, HB_COLR_MAT_SMPTE170M); } else { - // ITU BT.601 DVD or SD TV content - MP4AddColr(m->file, mux_data->track, 6, 1, 6); + // detected during scan + MP4AddColr(m->file, mux_data->track, title->color_prim, title->color_transfer, title->color_matrix); } if( job->anamorphic.mode ) diff --git a/libhb/scan.c b/libhb/scan.c index 29c9caaee..1ad8659b7 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -869,6 +869,9 @@ skip_preview: title->pixel_aspect_width = vid_info.pixel_aspect_width; title->pixel_aspect_height = vid_info.pixel_aspect_height; } + title->color_prim = vid_info.color_prim; + title->color_transfer = vid_info.color_transfer; + title->color_matrix = vid_info.color_matrix; // compute the aspect ratio based on the storage dimensions and the // pixel aspect ratio (if supplied) or just storage dimensions if no PAR. diff --git a/test/test.c b/test/test.c index f8d375b64..504a3507d 100644 --- a/test/test.c +++ b/test/test.c @@ -2898,9 +2898,9 @@ static void ShowHelp() " --modulus Set the number you want the scaled pixel dimensions\n" " <number> to divide cleanly by. Does not affect strict\n" " anamorphic mode, which is always mod 2 (default: 16)\n" - " -M --color-matrix Set the color space signaled by the output\n" - " <601 or 709> (Bt.601 is mostly for SD content, Bt.709 for HD,\n" - " default: set by resolution)\n" + " -M, --color-matrix Set the color space signaled by the output\n" + " Values: 709, pal, ntsc, 601 (same as ntsc)\n" + " (default: detected from source)\n" "\n" "### Filters---------------------------------------------------------\n\n" @@ -3725,11 +3725,16 @@ static int ParseOptions( int argc, char ** argv ) acodec_fallback = strdup( optarg ); break; case 'M': - if( atoi( optarg ) == 601 ) - color_matrix_code = 1; - else if( atoi( optarg ) == 709 ) - color_matrix_code = 2; - break; + if( optarg != NULL ) + { + if( !strcmp( optarg, "601" ) || + !strcmp( optarg, "ntsc" ) ) + color_matrix_code = 1; + else if( !strcmp( optarg, "pal" ) ) + color_matrix_code = 2; + else if( !strcmp( optarg, "709" ) ) + color_matrix_code = 3; + } break; case MIN_DURATION: min_title_duration = strtol( optarg, NULL, 0 ); break; |