diff --git a/libhb/avfilter.c b/libhb/avfilter.c index 5f98f310c982..febd239c94b2 100644 --- a/libhb/avfilter.c +++ b/libhb/avfilter.c @@ -68,6 +68,9 @@ static int rotate_init(hb_filter_object_t * filter, hb_filter_init_t * init); static int deinterlace_init(hb_filter_object_t * filter, hb_filter_init_t * init); +static int colorspace_init(hb_filter_object_t * filter, + hb_filter_init_t * init); + hb_filter_object_t hb_filter_avfilter = { .id = HB_FILTER_AVFILTER, @@ -149,6 +152,23 @@ hb_filter_object_t hb_filter_deinterlace = .settings_template = deint_template, }; +const char colorspace_template[] = + "format=^"HB_ALL_REG"$:range=^"HB_ALL_REG"$:primaries=^"HB_ALL_REG"$:" + "matrix=^"HB_ALL_REG"$:transfer=^"HB_ALL_REG"$"; + +hb_filter_object_t hb_filter_colorspace = +{ + .id = HB_FILTER_COLORSPACE, + .enforce_order = 1, + .skip = 1, + .name = "Colorspace", + .settings = NULL, + .init = colorspace_init, + .work = null_work, + .close = avfilter_alias_close, + .settings_template = colorspace_template, +}; + static int null_work( hb_filter_object_t * filter, hb_buffer_t ** buf_in, hb_buffer_t ** buf_out ) { @@ -241,14 +261,6 @@ hb_avfilter_graph_init(hb_value_t * settings, hb_filter_init_t * init) } graph->input = avfilter; - // Convert input to pix fmt YUV420P - avfilter = append_filter(graph, "format", "yuv420p"); - if (avfilter == NULL) - { - hb_error("hb_avfilter_graph_init: failed to create pix format filter"); - goto fail; - } - // Link input to filter chain created by avfilter_graph_parse2 result = avfilter_link(graph->last, 0, in->filter_ctx, 0); if (result < 0) @@ -267,8 +279,8 @@ hb_avfilter_graph_init(hb_value_t * settings, hb_filter_init_t * init) #if 0 // Set output pix fmt to YUV420P enum AVPixelFormat pix_fmts[2] = {AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}; - if ((ret = av_opt_set_int_list(avfilter, "pix_fmts", pix_fmts, - AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0) + if (av_opt_set_int_list(avfilter, "pix_fmts", pix_fmts, + AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN) < 0) { hb_error("hb_avfilter_graph_init: failed to set buffersink pix_fmt"); goto fail; @@ -697,7 +709,7 @@ void hb_append_filter_dict(hb_value_array_t * filters, hb_value_array_append(filters, filter_dict); } -static const char * color_format_range(enum AVPixelFormat format) +static const char * color_format_range(enum AVPixelFormat format, int range) { switch (format) { @@ -707,7 +719,7 @@ static const char * color_format_range(enum AVPixelFormat format) case AV_PIX_FMT_YUVJ440P: return "full"; default: - return "limited"; + return range == AVCOL_RANGE_JPEG ? "full" : "limited"; } } @@ -772,28 +784,34 @@ static int crop_scale_init(hb_filter_object_t * filter, hb_filter_init_t * init) case HB_COLR_MAT_BT709: matrix = "bt709"; break; - case HB_COLR_MAT_SMPTE170M: - matrix = "smpte170m"; + case HB_COLR_MAT_FCC: + matrix = "fcc"; break; case HB_COLR_MAT_SMPTE240M: matrix = "smpte240m"; break; + case HB_COLR_MAT_BT470BG: + case HB_COLR_MAT_SMPTE170M: + matrix = "smpte170m"; + break; case HB_COLR_MAT_BT2020_NCL: case HB_COLR_MAT_BT2020_CL: matrix = "bt2020"; break; default: case HB_COLR_MAT_UNDEF: - matrix = "bt601"; + matrix = NULL; break; } - hb_dict_set_string(avsettings, "in_color_matrix", matrix); - hb_dict_set_string(avsettings, "out_color_matrix", matrix); + if (matrix != NULL) + { + hb_dict_set_string(avsettings, "in_color_matrix", matrix); + hb_dict_set_string(avsettings, "out_color_matrix", matrix); + } hb_dict_set_string(avsettings, "in_range", - color_format_range(init->pix_fmt)); - hb_dict_set_string(avsettings, "out_range", - color_format_range(AV_PIX_FMT_YUV420P)); + color_format_range(init->pix_fmt, init->color_range)); + hb_dict_set_string(avsettings, "out_range", "limited"); hb_dict_set(avfilter, "scale", avsettings); hb_value_array_append(avfilters, avfilter); @@ -1147,3 +1165,62 @@ static int deinterlace_init(hb_filter_object_t * filter, return 0; } + +static int colorspace_init(hb_filter_object_t * filter, hb_filter_init_t * init) +{ + hb_filter_private_t * pv = NULL; + + pv = calloc(1, sizeof(struct hb_filter_private_s)); + filter->private_data = pv; + if (pv == NULL) + { + return 1; + } + pv->input = *init; + + hb_dict_t * settings = filter->settings; + + char * format = NULL, * range = NULL; + char * primaries = NULL, * transfer = NULL, * matrix = NULL; + + hb_dict_extract_string(&format, settings, "format"); + hb_dict_extract_string(&range, settings, "range"); + hb_dict_extract_string(&primaries, settings, "primaries"); + hb_dict_extract_string(&transfer, settings, "transfer"); + hb_dict_extract_string(&matrix, settings, "matrix"); + + if (!(format || range || primaries || transfer || matrix)) + { + return 0; + } + + hb_dict_t * avfilter = hb_dict_init(); + hb_dict_t * avsettings = hb_dict_init(); + + if (format) + { + hb_dict_set_string(avsettings, "format", format); + } + if (range) + { + hb_dict_set_string(avsettings, "range", range); + } + if (primaries) + { + hb_dict_set_string(avsettings, "primaries", primaries); + } + if (transfer) + { + hb_dict_set_string(avsettings, "trc", transfer); + } + if (matrix) + { + hb_dict_set_string(avsettings, "space", matrix); + } + hb_dict_set(avfilter, "colorspace", avsettings); + pv->avfilters = avfilter; + + pv->output = *init; + + return 0; +} diff --git a/libhb/common.c b/libhb/common.c index 8bc47adbe835..cffca581be0e 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -3786,9 +3786,11 @@ static void job_setup(hb_job_t * job, hb_title_t * title) job->pass_id = HB_PASS_ENCODE; job->vrate = title->vrate; + job->pix_fmt = AV_PIX_FMT_YUV420P; job->color_prim = title->color_prim; job->color_transfer = title->color_transfer; job->color_matrix = title->color_matrix; + job->color_range = title->color_range; job->mux = HB_MUX_MP4; @@ -4085,6 +4087,10 @@ hb_filter_object_t * hb_filter_get( int filter_id ) filter = &hb_filter_deinterlace; break; + case HB_FILTER_COLORSPACE: + filter = &hb_filter_colorspace; + break; + case HB_FILTER_VFR: filter = &hb_filter_vfr; break; @@ -5724,3 +5730,129 @@ void hb_chapter_dequeue(hb_chapter_queue_t *q, hb_buffer_t *buf) free(item); } } + +// Only return values supported by 'colorspace' avfilter: +const char * hb_get_format_name(int format) +{ + switch (format) + { + case AV_PIX_FMT_YUV420P: + return "yuv420p"; + case AV_PIX_FMT_YUV420P10: + return "yuv420p10"; + case AV_PIX_FMT_YUV420P12: + return "yuv420p12"; + case AV_PIX_FMT_YUV422P: + return "yuv422p"; + case AV_PIX_FMT_YUV422P10: + return "yuv422p10"; + case AV_PIX_FMT_YUV422P12: + return "yuv422p12"; + case AV_PIX_FMT_YUV444P: + return "yuv444p"; + case AV_PIX_FMT_YUV444P10: + return "yuv444p10"; + default: + return NULL; + } +} + +// Only return values supported by 'colorspace' avfilter: +const char * hb_get_primaries_name(int primaries) +{ + switch (primaries) + { + case HB_COLR_PRI_BT709: + return "bt709"; + case HB_COLR_PRI_BT470M: + return "bt470m"; + case HB_COLR_PRI_EBUTECH: + return "bt470bg"; + case HB_COLR_PRI_SMPTEC: + return "smpte170m"; + case HB_COLR_PRI_SMPTE240M: + return "smpte240m"; + case HB_COLR_PRI_SMPTE428: + return "smpte428"; + case HB_COLR_PRI_FILM: + return "film"; + case HB_COLR_PRI_SMPTE431: + return "smpte431"; + case HB_COLR_PRI_SMPTE432: + return "smpte432"; + case HB_COLR_PRI_BT2020: + return "bt2020"; + case HB_COLR_PRI_JEDEC_P22: + return "jedec-p22"; + default: + return NULL; + } +} + +// Only return values supported by 'colorspace' avfilter: +const char * hb_get_transfer_name(int transfer) +{ + switch (transfer) + { + case HB_COLR_TRA_BT709: + return "bt709"; + case HB_COLR_TRA_GAMMA22: + return "gamma22"; + case HB_COLR_TRA_GAMMA28: + return "gamma28"; + case HB_COLR_TRA_SMPTE170M: + return "smpte170m"; + case HB_COLR_TRA_SMPTE240M: + return "smpte240m"; + case HB_COLR_TRA_IEC61966_2_1: + return "iec61966-2-1"; + case HB_COLR_TRA_IEC61966_2_4: + return "iec61966-2-4"; + case HB_COLR_TRA_BT2020_10: + return "bt2020-10"; + case HB_COLR_TRA_BT2020_12: + return "bt2020-12"; + default: + return NULL; + } +} + +// Only return values supported by 'colorspace' avfilter: +const char * hb_get_matrix_name(int matrix) +{ + switch (matrix) + { + case HB_COLR_MAT_BT709: + return "bt709"; + case HB_COLR_MAT_FCC: + return "fcc"; + case HB_COLR_MAT_BT470BG: + return "bt470bg"; + case HB_COLR_MAT_SMPTE170M: + return "smpte170m"; + case HB_COLR_MAT_SMPTE240M: + return "smpte240m"; + case HB_COLR_MAT_YCGCO: + return "ycgco"; + case HB_COLR_MAT_RGB: + return "gbr"; + case HB_COLR_MAT_BT2020_NCL: + return "bt2020ncl"; + default: + return NULL; + } +} + +// Only return values supported by 'colorspace' avfilter: +const char * hb_get_color_range_name(int range) +{ + switch (range) + { + case AVCOL_RANGE_MPEG: + return "mpeg"; + case AVCOL_RANGE_JPEG: + return "jpeg"; + default: + return "mpeg"; + } +} diff --git a/libhb/common.h b/libhb/common.h index bc65e9cbb7cb..bdbf5c53951b 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -560,32 +560,59 @@ struct hb_job_s char *encoder_level; int areBframes; + int pix_fmt; int color_prim; int color_transfer; int color_matrix; + int color_range; // see https://developer.apple.com/library/content/technotes/tn2162/_index.html // https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-125526 // libav pixfmt.h #define HB_COLR_PRI_BT709 1 #define HB_COLR_PRI_UNDEF 2 +#define HB_COLR_PRI_BT470M 4 #define HB_COLR_PRI_EBUTECH 5 // use for bt470bg -#define HB_COLR_PRI_SMPTEC 6 // smpte170m; also use for bt470m and smpte240m +#define HB_COLR_PRI_SMPTEC 6 // smpte170m +#define HB_COLR_PRI_SMPTE240M 7 +#define HB_COLR_PRI_FILM 8 // Illuminant C #define HB_COLR_PRI_BT2020 9 +#define HB_COLR_PRI_SMPTE428 10 +#define HB_COLR_PRI_SMPTE431 11 +#define HB_COLR_PRI_SMPTE432 12 +#define HB_COLR_PRI_JEDEC_P22 22 // 0, 3-4, 7-8, 10-65535: reserved/not implemented #define HB_COLR_TRA_BT709 1 // also use for bt470m, bt470bg, smpte170m, bt2020_10 and bt2020_12 #define HB_COLR_TRA_UNDEF 2 +#define HB_COLR_TRA_GAMMA22 4 +#define HB_COLR_TRA_GAMMA28 5 +#define HB_COLR_TRA_SMPTE170M 6 #define HB_COLR_TRA_SMPTE240M 7 +#define HB_COLR_TRA_LINEAR 8 +#define HB_COLR_TRA_LOG 9 +#define HB_COLR_TRA_LOG_SQRT 10 +#define HB_COLR_TRA_IEC61966_2_4 11 +#define HB_COLR_TRA_BT1361_ECG 12 +#define HB_COLR_TRA_IEC61966_2_1 13 #define HB_COLR_TRA_BT2020_10 14 #define HB_COLR_TRA_BT2020_12 15 #define HB_COLR_TRA_SMPTEST2084 16 +#define HB_COLR_TRA_SMPTE428 17 #define HB_COLR_TRA_ARIB_STD_B67 18 //known as "Hybrid log-gamma" // 0, 3-6, 8-15, 17-65535: reserved/not implemented +#define HB_COLR_MAT_RGB 0 #define HB_COLR_MAT_BT709 1 #define HB_COLR_MAT_UNDEF 2 +#define HB_COLR_MAT_FCC 4 +#define HB_COLR_MAT_BT470BG 5 #define HB_COLR_MAT_SMPTE170M 6 // also use for fcc and bt470bg #define HB_COLR_MAT_SMPTE240M 7 +#define HB_COLR_MAT_YCGCO 8 #define HB_COLR_MAT_BT2020_NCL 9 #define HB_COLR_MAT_BT2020_CL 10 +#define HB_COLR_MAT_SMPTE2085 11 +#define HB_COLR_MAT_CD_NCL 12 // chromaticity derived non-constant lum +#define HB_COLR_MAT_CD_CL 13 // chromaticity derived constant lum +#define HB_COLR_MAT_ICTCP 14 // ITU-R BT.2100-0, ICtCp // 0, 3-5, 8, 11-65535: reserved/not implemented hb_list_t * list_chapter; @@ -1044,9 +1071,11 @@ struct hb_title_s hb_geometry_t geometry; hb_rational_t dar; // aspect ratio for the title's video hb_rational_t container_dar; // aspect ratio from container (0 if none) + int pix_fmt; int color_prim; int color_transfer; int color_matrix; + int color_range; hb_rational_t vrate; int crop[4]; enum {HB_DVD_DEMUXER, HB_TS_DEMUXER, HB_PS_DEMUXER, HB_NULL_DEMUXER} demuxer; @@ -1149,9 +1178,11 @@ typedef struct hb_work_info_s struct { // info only valid for video decoders hb_geometry_t geometry; + int pix_fmt; int color_prim; int color_transfer; int color_matrix; + int color_range; int video_decode_support; }; struct @@ -1254,6 +1285,7 @@ typedef struct hb_filter_init_s int color_prim; int color_transfer; int color_matrix; + int color_range; hb_geometry_t geometry; int crop[4]; hb_rational_t vrate; @@ -1337,6 +1369,7 @@ enum HB_FILTER_ROTATE, HB_FILTER_GRAYSCALE, HB_FILTER_PAD, + HB_FILTER_COLORSPACE, // Finally filters that don't care what order they are in, // except that they must be after the above filters diff --git a/libhb/deblock.c b/libhb/deblock.c index 64cf277bb670..c334b4ef22b5 100644 --- a/libhb/deblock.c +++ b/libhb/deblock.c @@ -47,6 +47,9 @@ struct hb_filter_private_s int pp7_mpeg2; int pp7_temp_stride; uint8_t * pp7_src; + + hb_filter_init_t input; + hb_filter_init_t output; }; static int hb_deblock_init( hb_filter_object_t * filter, @@ -346,6 +349,7 @@ static int hb_deblock_init( hb_filter_object_t * filter, filter->private_data = calloc( sizeof(struct hb_filter_private_s), 1 ); hb_filter_private_t * pv = filter->private_data; + pv->input = *init; pv->pp7_qp = PP7_QP_DEFAULT; pv->pp7_mode = PP7_MODE_DEFAULT; pv->pp7_mpeg2 = 1; /*mpi->qscale_type;*/ @@ -378,6 +382,7 @@ static int hb_deblock_init( hb_filter_object_t * filter, pv->pp7_temp_stride = (init->geometry.width + 16 + 15) & (~15); pv->pp7_src = (uint8_t*)malloc( pv->pp7_temp_stride*(h+8)*sizeof(uint8_t) ); + pv->output = *init; return 0; } @@ -411,7 +416,12 @@ static int hb_deblock_work( hb_filter_object_t * filter, if( /*TODO: mpi->qscale ||*/ pv->pp7_qp ) { - out = hb_video_buffer_init( in->f.width, in->f.height ); + out = hb_frame_buffer_init(pv->output.pix_fmt, + in->f.width, in->f.height ); + out->f.color_prim = pv->output.color_prim; + out->f.color_transfer = pv->output.color_transfer; + out->f.color_matrix = pv->output.color_matrix; + out->f.color_range = pv->output.color_range ; pp7_filter( pv, out->plane[0].data, diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index f93a24878f94..85237d1d938a 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -1118,6 +1118,7 @@ int reinit_video_filters(hb_work_private_t * pv) hb_value_array_t * filters; hb_dict_t * settings; hb_filter_init_t filter_init; + enum AVPixelFormat pix_fmt; #ifdef USE_QSV if (pv->qsv.decode && @@ -1134,6 +1135,7 @@ int reinit_video_filters(hb_work_private_t * pv) // of incoming video if not even. orig_width = pv->context->width & ~1; orig_height = pv->context->height & ~1; + pix_fmt = AV_PIX_FMT_YUV420P; } else { @@ -1148,9 +1150,10 @@ int reinit_video_filters(hb_work_private_t * pv) orig_width = pv->job->title->geometry.width; orig_height = pv->job->title->geometry.height; } + pix_fmt = pv->job->pix_fmt; } - if (AV_PIX_FMT_YUV420P == pv->frame->format && + if (pix_fmt == pv->frame->format && orig_width == pv->frame->width && orig_height == pv->frame->height && HB_ROTATION_0 == pv->title->rotation) @@ -1184,7 +1187,7 @@ int reinit_video_filters(hb_work_private_t * pv) vrate.den = pv->duration * (clock / 90000.); filters = hb_value_array_init(); - if (AV_PIX_FMT_YUV420P != pv->frame->format || + if (pix_fmt != pv->frame->format || orig_width != pv->frame->width || orig_height != pv->frame->height) { @@ -1222,9 +1225,9 @@ int reinit_video_filters(hb_work_private_t * pv) } } + filter_init.pix_fmt = pv->frame->format; filter_init.geometry.width = pv->frame->width; filter_init.geometry.height = pv->frame->height; - filter_init.pix_fmt = pv->frame->format; filter_init.geometry.par.num = pv->frame->sample_aspect_ratio.num; filter_init.geometry.par.den = pv->frame->sample_aspect_ratio.den; filter_init.time_base.num = 1; @@ -2027,9 +2030,13 @@ static int decavcodecvInfo( hb_work_object_t *w, hb_work_info_t *info ) 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->pix_fmt = pv->context->pix_fmt; + 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->color_matrix = get_color_matrix(pv->context->colorspace, + info->geometry); + info->color_range = pv->context->color_range; info->video_decode_support = HB_DECODE_SUPPORT_SW; diff --git a/libhb/decomb.c b/libhb/decomb.c index 6f1cf62a1eb1..d6589c3ad3f4 100644 --- a/libhb/decomb.c +++ b/libhb/decomb.c @@ -150,6 +150,9 @@ struct hb_filter_private_s taskset_t eedi2_taskset; // Threads for eedi2 - one per plane hb_buffer_list_t out_list; + + hb_filter_init_t input; + hb_filter_init_t output; }; typedef struct @@ -935,6 +938,7 @@ static int hb_decomb_init( hb_filter_object_t * filter, { filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) ); hb_filter_private_t * pv = filter->private_data; + pv->input = *init; hb_buffer_list_clear(&pv->out_list); pv->deinterlaced = 0; @@ -1118,6 +1122,7 @@ static int hb_decomb_init( hb_filter_object_t * filter, } } + pv->output = *init; init->job->use_decomb = 1; return 0; @@ -1249,6 +1254,10 @@ static void process_frame( hb_filter_private_t * pv ) buf = hb_frame_buffer_init(pv->ref[1]->f.fmt, pv->ref[1]->f.width, pv->ref[1]->f.height); + buf->f.color_prim = pv->output.color_prim; + buf->f.color_transfer = pv->output.color_transfer; + buf->f.color_matrix = pv->output.color_matrix; + buf->f.color_range = pv->output.color_range ; yadif_filter(pv, buf, parity, tff); /* Copy buffered settings to output buffer settings */ diff --git a/libhb/denoise.c b/libhb/denoise.c index 208d399a557c..58c7935c114b 100644 --- a/libhb/denoise.c +++ b/libhb/denoise.c @@ -29,6 +29,9 @@ struct hb_filter_private_s short hqdn3d_coef[6][512*16]; unsigned short * hqdn3d_line; unsigned short * hqdn3d_frame[3]; + + hb_filter_init_t input; + hb_filter_init_t output; }; static int hb_denoise_init( hb_filter_object_t * filter, @@ -227,6 +230,7 @@ static int hb_denoise_init( hb_filter_object_t * filter, double spatial_luma, spatial_chroma_b, spatial_chroma_r; double temporal_luma, temporal_chroma_b, temporal_chroma_r; + pv->input = *init; if (!hb_dict_extract_double(&spatial_luma, filter->settings, "y-spatial")) { spatial_luma = HQDN3D_SPATIAL_LUMA_DEFAULT; @@ -261,6 +265,8 @@ static int hb_denoise_init( hb_filter_object_t * filter, hqdn3d_precalc_coef( pv->hqdn3d_coef[4], spatial_chroma_r ); hqdn3d_precalc_coef( pv->hqdn3d_coef[5], temporal_chroma_r ); + pv->output = *init; + return 0; } @@ -312,7 +318,12 @@ static int hb_denoise_work( hb_filter_object_t * filter, return HB_FILTER_DONE; } - out = hb_video_buffer_init( in->f.width, in->f.height ); + out = hb_frame_buffer_init(pv->output.pix_fmt, in->f.width, in->f.height); + out->f.color_prim = pv->output.color_prim; + out->f.color_transfer = pv->output.color_transfer; + out->f.color_matrix = pv->output.color_matrix; + out->f.color_range = pv->output.color_range ; + if( !pv->hqdn3d_line ) { diff --git a/libhb/detelecine.c b/libhb/detelecine.c index a0a5367f112f..a9abf86012e6 100644 --- a/libhb/detelecine.c +++ b/libhb/detelecine.c @@ -92,6 +92,9 @@ struct hb_filter_private_s struct pullup_context * pullup_ctx; int pullup_fakecount; int pullup_skipflag; + + hb_filter_init_t input; + hb_filter_init_t output; }; static int hb_detelecine_init( hb_filter_object_t * filter, @@ -821,10 +824,12 @@ void pullup_flush_fields( struct pullup_context * c ) static int hb_detelecine_init( hb_filter_object_t * filter, hb_filter_init_t * init ) { - filter->private_data = calloc( sizeof(struct hb_filter_private_s), 1 ); - hb_filter_private_t * pv = filter->private_data; + filter->private_data = calloc(sizeof(struct hb_filter_private_s), 1); + hb_filter_private_t * pv = filter->private_data; struct pullup_context * ctx; + + pv->input = *init; pv->pullup_ctx = ctx = pullup_alloc_context(); ctx->junk_left = ctx->junk_right = 1; @@ -877,6 +882,7 @@ static int hb_detelecine_init( hb_filter_object_t * filter, pv->pullup_skipflag = 0; init->job->use_detelecine = 1; + pv->output = *init; return 0; } @@ -1017,7 +1023,11 @@ static int hb_detelecine_work( hb_filter_object_t * filter, pullup_pack_frame( ctx, frame ); } - out = hb_video_buffer_init( in->f.width, in->f.height ); + out = hb_frame_buffer_init(pv->output.pix_fmt, in->f.width, in->f.height); + out->f.color_prim = pv->output.color_prim; + out->f.color_transfer = pv->output.color_transfer; + out->f.color_matrix = pv->output.color_matrix; + out->f.color_range = pv->output.color_range ; /* Copy pullup frame buffer into output buffer */ memcpy( out->plane[0].data, frame->buffer->planes[0], frame->buffer->size[0] ); diff --git a/libhb/hb.c b/libhb/hb.c index a9dc2cdc60dc..2032a42eef7f 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -630,7 +630,7 @@ 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); + int colorspace = hb_sws_get_colorspace(title->color_matrix); // Get scaling context context = hb_sws_get_context( diff --git a/libhb/hb_json.c b/libhb/hb_json.c index 2399adf45dfa..ce93444d9666 100644 --- a/libhb/hb_json.c +++ b/libhb/hb_json.c @@ -231,8 +231,8 @@ static hb_dict_t* hb_title_to_dict_internal( hb_title_t *title ) "s:{s:o, s:o, s:{s:o, s:o}}," // Crop[Top, Bottom, Left, Right]} "s:[oooo]," - // Color {Primary, Transfer, Matrix} - "s:{s:o, s:o, s:o}," + // Color {Format, Range, Primary, Transfer, Matrix} + "s:{s:o, s:o, s:o, s:o, s:o}," // FrameRate {Num, Den} "s:{s:o, s:o}," // InterlaceDetected, VideoCodec @@ -262,6 +262,8 @@ static hb_dict_t* hb_title_to_dict_internal( hb_title_t *title ) hb_value_int(title->crop[2]), hb_value_int(title->crop[3]), "Color", + "Format", hb_value_int(title->pix_fmt), + "Range", hb_value_int(title->color_range), "Primary", hb_value_int(title->color_prim), "Transfer", hb_value_int(title->color_transfer), "Matrix", hb_value_int(title->color_matrix), @@ -645,6 +647,10 @@ hb_dict_t* hb_job_to_dict( const hb_job_t * job ) hb_dict_set(source_dict, "Range", range_dict); hb_dict_t *video_dict = hb_dict_get(dict, "Video"); + hb_dict_set(video_dict, "ColorFormat", + hb_value_int(job->pix_fmt)); + hb_dict_set(video_dict, "ColorRange", + hb_value_int(job->color_range)); hb_dict_set(video_dict, "ColorPrimaries", hb_value_int(job->color_prim)); hb_dict_set(video_dict, "ColorTransfer", @@ -1004,10 +1010,12 @@ hb_job_t* hb_dict_to_job( hb_handle_t * h, hb_dict_t *dict ) // PAR {Num, Den} "s?{s:i, s:i}," // Video {Codec, Quality, Bitrate, Preset, Tune, Profile, Level, Options - // TwoPass, Turbo, ColorPrimaries, ColorTransfer, ColorMatrix, + // TwoPass, Turbo, ColorFormat, ColorRange, ColorPrimaries, + // ColorTransfer, ColorMatrix, // QSV {Decode, AsyncDepth}} "s:{s:o, s?f, s?i, s?s, s?s, s?s, s?s, s?s," " s?b, s?b, s?i, s?i, s?i," + " s?i, s?i," " s?{s?b, s?i}}," // Audio {CopyMask, FallbackEncoder, AudioList} "s?{s?o, s?o, s?o}," @@ -1051,6 +1059,8 @@ hb_job_t* hb_dict_to_job( hb_handle_t * h, hb_dict_t *dict ) "Options", unpack_s(&video_options), "TwoPass", unpack_b(&job->twopass), "Turbo", unpack_b(&job->fastfirstpass), + "ColorFormat", unpack_i(&job->pix_fmt), + "ColorRange", unpack_i(&job->color_range), "ColorPrimaries", unpack_i(&job->color_prim), "ColorTransfer", unpack_i(&job->color_transfer), "ColorMatrix", unpack_i(&job->color_matrix), diff --git a/libhb/hbffmpeg.c b/libhb/hbffmpeg.c index c604bf703faf..e0168a8cb7ea 100644 --- a/libhb/hbffmpeg.c +++ b/libhb/hbffmpeg.c @@ -37,6 +37,12 @@ void hb_video_buffer_to_avframe(AVFrame *frame, hb_buffer_t * buf) frame->format = buf->f.fmt; frame->interlaced_frame = !!buf->s.combed; frame->top_field_first = !!(buf->s.flags & PIC_FLAG_TOP_FIELD_FIRST); + + frame->format = buf->f.fmt; + frame->color_primaries = hb_colr_pri_hb_to_ff(buf->f.color_prim); + frame->color_trc = hb_colr_tra_hb_to_ff(buf->f.color_transfer); + frame->colorspace = hb_colr_mat_hb_to_ff(buf->f.color_matrix); + frame->color_range = buf->f.color_range; } void hb_avframe_set_video_buffer_flags(hb_buffer_t * buf, AVFrame *frame, @@ -70,7 +76,12 @@ void hb_avframe_set_video_buffer_flags(hb_buffer_t * buf, AVFrame *frame, { buf->s.flags |= PIC_FLAG_REPEAT_FRAME; } - buf->s.frametype = get_frame_type(frame->pict_type); + buf->s.frametype = get_frame_type(frame->pict_type); + buf->f.fmt = frame->format; + buf->f.color_prim = hb_colr_pri_ff_to_hb(frame->color_primaries); + buf->f.color_transfer = hb_colr_tra_ff_to_hb(frame->color_trc); + buf->f.color_matrix = hb_colr_mat_ff_to_hb(frame->colorspace); + buf->f.color_range = frame->color_range; } hb_buffer_t * hb_avframe_to_video_buffer(AVFrame *frame, AVRational time_base) @@ -163,7 +174,7 @@ hb_sws_get_context(int srcW, int srcH, enum AVPixelFormat srcFormat, return ctx; } -int hb_ff_get_colorspace(int color_matrix) +int hb_sws_get_colorspace(int color_matrix) { int color_space = SWS_CS_DEFAULT; @@ -189,6 +200,229 @@ int hb_ff_get_colorspace(int color_matrix) return color_space; } +int hb_colr_pri_hb_to_ff(int colr_prim) +{ + switch (colr_prim) + { + case HB_COLR_PRI_BT709: + return AVCOL_PRI_BT709; + case HB_COLR_PRI_EBUTECH: + return AVCOL_PRI_BT470BG; + case HB_COLR_PRI_BT470M: + return AVCOL_PRI_BT470M; + case HB_COLR_PRI_SMPTEC: + return AVCOL_PRI_SMPTE170M; + case HB_COLR_PRI_SMPTE240M: + return AVCOL_PRI_SMPTE240M; + case HB_COLR_PRI_BT2020: + return AVCOL_PRI_BT2020; + case HB_COLR_PRI_SMPTE428: + return AVCOL_PRI_SMPTE428; + case HB_COLR_PRI_SMPTE431: + return AVCOL_PRI_SMPTE431; + case HB_COLR_PRI_SMPTE432: + return AVCOL_PRI_SMPTE432; + case HB_COLR_PRI_JEDEC_P22: + return AVCOL_PRI_JEDEC_P22; + default: + case HB_COLR_PRI_UNDEF: + return AVCOL_PRI_UNSPECIFIED; + } +} + +int hb_colr_tra_hb_to_ff(int colr_tra) +{ + switch (colr_tra) + { + case HB_COLR_TRA_BT709: + return AVCOL_TRC_BT709; + case HB_COLR_TRA_GAMMA22: + return AVCOL_TRC_GAMMA22; + case HB_COLR_TRA_GAMMA28: + return AVCOL_TRC_GAMMA28; + case HB_COLR_TRA_SMPTE170M: + return AVCOL_TRC_SMPTE170M; + case HB_COLR_TRA_SMPTE240M: + return AVCOL_TRC_SMPTE240M; + case HB_COLR_TRA_LINEAR: + return AVCOL_TRC_LINEAR; + case HB_COLR_TRA_LOG: + return AVCOL_TRC_LOG; + case HB_COLR_TRA_LOG_SQRT: + return AVCOL_TRC_LOG_SQRT; + case HB_COLR_TRA_IEC61966_2_4: + return AVCOL_TRC_IEC61966_2_4; + case HB_COLR_TRA_BT1361_ECG: + return AVCOL_TRC_BT1361_ECG; + case HB_COLR_TRA_IEC61966_2_1: + return AVCOL_TRC_IEC61966_2_1; + case HB_COLR_TRA_BT2020_10: + return AVCOL_TRC_BT2020_10; + case HB_COLR_TRA_BT2020_12: + return AVCOL_TRC_BT2020_12; + case HB_COLR_TRA_SMPTEST2084: + return AVCOL_TRC_SMPTE2084; + case HB_COLR_TRA_SMPTE428: + return AVCOL_TRC_SMPTE428; + case HB_COLR_TRA_ARIB_STD_B67: + return AVCOL_TRC_ARIB_STD_B67; + default: + case HB_COLR_TRA_UNDEF: + return AVCOL_TRC_UNSPECIFIED; + } +} + +int hb_colr_mat_hb_to_ff(int colr_mat) +{ + switch (colr_mat) + { + case HB_COLR_MAT_RGB: + return AVCOL_SPC_RGB; + case HB_COLR_MAT_BT709: + return AVCOL_SPC_BT709; + case HB_COLR_MAT_FCC: + return AVCOL_SPC_FCC; + case HB_COLR_MAT_BT470BG: + return AVCOL_SPC_BT470BG; + case HB_COLR_MAT_SMPTE170M: + return AVCOL_SPC_SMPTE170M; + case HB_COLR_MAT_SMPTE240M: + return AVCOL_SPC_SMPTE240M; + case HB_COLR_MAT_YCGCO: + return AVCOL_SPC_YCGCO; + case HB_COLR_MAT_BT2020_NCL: + return AVCOL_SPC_BT2020_NCL; + case HB_COLR_MAT_BT2020_CL: + return AVCOL_SPC_BT2020_CL; + case HB_COLR_MAT_SMPTE2085: + return AVCOL_SPC_SMPTE2085; + case HB_COLR_MAT_CD_NCL: + return AVCOL_SPC_CHROMA_DERIVED_NCL; + case HB_COLR_MAT_CD_CL: + return AVCOL_SPC_CHROMA_DERIVED_CL; + case HB_COLR_MAT_ICTCP: + return AVCOL_SPC_ICTCP; + default: + case HB_COLR_MAT_UNDEF: + return AVCOL_SPC_UNSPECIFIED; + } +} + +int hb_colr_pri_ff_to_hb(int colr_prim) +{ + switch (colr_prim) + { + case AVCOL_PRI_BT709: + return HB_COLR_PRI_BT709; + case AVCOL_PRI_BT470M: + return HB_COLR_PRI_BT470M; + case AVCOL_PRI_BT470BG: + return HB_COLR_PRI_EBUTECH; + case AVCOL_PRI_SMPTE170M: + return HB_COLR_PRI_SMPTEC; + case AVCOL_PRI_SMPTE240M: + return HB_COLR_PRI_SMPTE240M; + case AVCOL_PRI_FILM: + return HB_COLR_PRI_FILM; + case AVCOL_PRI_BT2020: + return HB_COLR_PRI_BT2020; + case AVCOL_PRI_SMPTE428: + return HB_COLR_PRI_SMPTE428; + case AVCOL_PRI_SMPTE431: + return HB_COLR_PRI_SMPTE431; + case AVCOL_PRI_SMPTE432: + return HB_COLR_PRI_SMPTE432; + case AVCOL_PRI_JEDEC_P22: + return HB_COLR_PRI_JEDEC_P22; + default: + case AVCOL_PRI_RESERVED: + case AVCOL_PRI_RESERVED0: + case AVCOL_PRI_UNSPECIFIED: + return HB_COLR_PRI_UNDEF; + } +} + +int hb_colr_tra_ff_to_hb(int colr_tra) +{ + switch (colr_tra) + { + case AVCOL_TRC_BT709: + return HB_COLR_TRA_BT709; + case AVCOL_TRC_GAMMA22: + return HB_COLR_TRA_GAMMA22; + case AVCOL_TRC_GAMMA28: + return HB_COLR_TRA_GAMMA28; + case AVCOL_TRC_SMPTE170M: + return HB_COLR_TRA_SMPTE170M; + case AVCOL_TRC_SMPTE240M: + return HB_COLR_TRA_SMPTE240M; + case AVCOL_TRC_LINEAR: + return HB_COLR_TRA_LINEAR; + case AVCOL_TRC_LOG: + return HB_COLR_TRA_LOG; + case AVCOL_TRC_LOG_SQRT: + return HB_COLR_TRA_LOG_SQRT; + case AVCOL_TRC_IEC61966_2_4: + return HB_COLR_TRA_IEC61966_2_4; + case AVCOL_TRC_BT1361_ECG: + return HB_COLR_TRA_BT1361_ECG; + case AVCOL_TRC_IEC61966_2_1: + return HB_COLR_TRA_IEC61966_2_1; + case AVCOL_TRC_BT2020_10: + return HB_COLR_TRA_BT2020_10; + case AVCOL_TRC_BT2020_12: + return HB_COLR_TRA_BT2020_12; + case AVCOL_TRC_SMPTE2084: + return HB_COLR_TRA_SMPTEST2084; + case AVCOL_TRC_SMPTE428: + return HB_COLR_TRA_SMPTE428; + case AVCOL_TRC_ARIB_STD_B67: + return HB_COLR_TRA_ARIB_STD_B67; + default: + case AVCOL_TRC_UNSPECIFIED: + case AVCOL_TRC_RESERVED: + case AVCOL_TRC_RESERVED0: + return HB_COLR_TRA_UNDEF; + } +} + +int hb_colr_mat_ff_to_hb(int colr_mat) +{ + switch (colr_mat) + { + case AVCOL_SPC_RGB: + return HB_COLR_MAT_RGB; + case AVCOL_SPC_BT709: + return HB_COLR_MAT_BT709; + case AVCOL_SPC_FCC: + return HB_COLR_MAT_FCC; + case AVCOL_SPC_BT470BG: + return HB_COLR_MAT_BT470BG; + case AVCOL_SPC_SMPTE170M: + return HB_COLR_MAT_SMPTE170M; + case AVCOL_SPC_SMPTE240M: + return HB_COLR_MAT_SMPTE240M; + case AVCOL_SPC_YCGCO: + return HB_COLR_MAT_YCGCO; + case AVCOL_SPC_BT2020_NCL: + return HB_COLR_MAT_BT2020_NCL; + case AVCOL_SPC_BT2020_CL: + return HB_COLR_MAT_BT2020_CL; + case AVCOL_SPC_SMPTE2085: + return HB_COLR_MAT_SMPTE2085; + case AVCOL_SPC_CHROMA_DERIVED_NCL: + return HB_COLR_MAT_CD_NCL; + case AVCOL_SPC_CHROMA_DERIVED_CL: + return HB_COLR_MAT_CD_CL; + case AVCOL_SPC_ICTCP: + return HB_COLR_MAT_ICTCP; + default: + case AVCOL_SPC_UNSPECIFIED: + case AVCOL_SPC_RESERVED: + return HB_COLR_MAT_UNDEF; + } +} + uint64_t hb_ff_mixdown_xlat(int hb_mixdown, int *downmix_mode) { uint64_t ff_layout = 0; diff --git a/libhb/hbffmpeg.h b/libhb/hbffmpeg.h index 648089c372b5..119347153a30 100644 --- a/libhb/hbffmpeg.h +++ b/libhb/hbffmpeg.h @@ -33,7 +33,13 @@ 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); +int hb_sws_get_colorspace(int color_matrix); +int hb_colr_pri_hb_to_ff(int colr_prim); +int hb_colr_tra_hb_to_ff(int colr_tra); +int hb_colr_mat_hb_to_ff(int colr_mat); +int hb_colr_pri_ff_to_hb(int colr_prim); +int hb_colr_tra_ff_to_hb(int colr_tra); +int hb_colr_mat_ff_to_hb(int colr_mat); struct SwsContext* hb_sws_get_context(int srcW, int srcH, enum AVPixelFormat srcFormat, diff --git a/libhb/internal.h b/libhb/internal.h index fb121a9bf679..eea87b0e9bdf 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -113,6 +113,10 @@ struct hb_image_format_s int width; int height; int fmt; + int color_prim; + int color_transfer; + int color_matrix; + int color_range; int max_plane; int window_width; int window_height; @@ -464,6 +468,7 @@ extern hb_filter_object_t hb_filter_lapsharp; extern hb_filter_object_t hb_filter_unsharp; extern hb_filter_object_t hb_filter_avfilter; extern hb_filter_object_t hb_filter_mt_frame; +extern hb_filter_object_t hb_filter_colorspace; #ifdef USE_QSV extern hb_filter_object_t hb_filter_qsv; diff --git a/libhb/lapsharp.c b/libhb/lapsharp.c index d7146c031788..e80a8480b3d7 100644 --- a/libhb/lapsharp.c +++ b/libhb/lapsharp.c @@ -85,6 +85,9 @@ static kernel_t kernels[] = struct hb_filter_private_s { lapsharp_plane_context_t plane_ctx[3]; + + hb_filter_init_t input; + hb_filter_init_t output; }; static int hb_lapsharp_init(hb_filter_object_t *filter, @@ -163,6 +166,8 @@ static int hb_lapsharp_init(hb_filter_object_t *filter, char *kernel_string[3]; + pv->input = *init; + // Mark parameters unset for (int c = 0; c < 3; c++) { @@ -252,6 +257,7 @@ static int hb_lapsharp_init(hb_filter_object_t *filter, ctx->kernel = c ? LAPSHARP_KERNEL_CHROMA_DEFAULT : LAPSHARP_KERNEL_LUMA_DEFAULT; } } + pv->output = *init; return 0; } @@ -284,7 +290,11 @@ static int hb_lapsharp_work(hb_filter_object_t *filter, } hb_frame_buffer_mirror_stride(in); - out = hb_frame_buffer_init(in->f.fmt, in->f.width, in->f.height); + out = hb_frame_buffer_init(pv->output.pix_fmt, in->f.width, in->f.height); + out->f.color_prim = pv->output.color_prim; + out->f.color_transfer = pv->output.color_transfer; + out->f.color_matrix = pv->output.color_matrix; + out->f.color_range = pv->output.color_range ; int c; for (c = 0; c < 3; c++) diff --git a/libhb/nlmeans.c b/libhb/nlmeans.c index d8e5aa01a940..e68e24739402 100644 --- a/libhb/nlmeans.c +++ b/libhb/nlmeans.c @@ -143,7 +143,10 @@ struct hb_filter_private_s int max_frames; taskset_t taskset; - nlmeans_thread_arg_t **thread_data; + nlmeans_thread_arg_t ** thread_data; + + hb_filter_init_t input; + hb_filter_init_t output; }; static int nlmeans_init(hb_filter_object_t *filter, hb_filter_init_t *init); @@ -895,6 +898,8 @@ static int nlmeans_init(hb_filter_object_t *filter, hb_filter_private_t *pv = filter->private_data; NLMeansFunctions *functions = &pv->functions; + pv->input = *init; + functions->build_integral = build_integral_scalar; #if defined(ARCH_X86) nlmeans_init_x86(functions); @@ -1041,6 +1046,7 @@ static int nlmeans_init(hb_filter_object_t *filter, goto fail; } } + pv->output = *init; return 0; @@ -1113,7 +1119,13 @@ static void nlmeans_filter_thread(void *thread_args_v) Frame *frame = &pv->frame[segment]; hb_buffer_t *buf; - buf = hb_frame_buffer_init(frame->fmt, frame->width, frame->height); + buf = hb_frame_buffer_init(pv->output.pix_fmt, + frame->width, frame->height); + buf->f.color_prim = pv->output.color_prim; + buf->f.color_transfer = pv->output.color_transfer; + buf->f.color_matrix = pv->output.color_matrix; + buf->f.color_range = pv->output.color_range ; + NLMeansFunctions *functions = &pv->functions; @@ -1244,7 +1256,12 @@ static hb_buffer_t * nlmeans_filter_flush(hb_filter_private_t *pv) { Frame *frame = &pv->frame[f]; hb_buffer_t *buf; - buf = hb_frame_buffer_init(frame->fmt, frame->width, frame->height); + buf = hb_frame_buffer_init(pv->output.pix_fmt, + frame->width, frame->height); + buf->f.color_prim = pv->output.color_prim; + buf->f.color_transfer = pv->output.color_transfer; + buf->f.color_matrix = pv->output.color_matrix; + buf->f.color_range = pv->output.color_range ; NLMeansFunctions *functions = &pv->functions; diff --git a/libhb/rendersub.c b/libhb/rendersub.c index 866e277f4087..68ba4d8e52e4 100644 --- a/libhb/rendersub.c +++ b/libhb/rendersub.c @@ -34,6 +34,9 @@ struct hb_filter_private_s // SRT int line; hb_buffer_t * current_sub; + + hb_filter_init_t input; + hb_filter_init_t output; }; // VOBSUB @@ -224,7 +227,14 @@ static hb_buffer_t * ScaleSubtitle(hb_filter_private_t *pv, width = sub->f.width * xfactor; height = sub->f.height * yfactor; - scaled = hb_frame_buffer_init(AV_PIX_FMT_YUVA420P, width, height); + scaled = hb_frame_buffer_init(pv->output.pix_fmt, width, height); + if (scaled == NULL) + return NULL; + scaled->f.color_prim = pv->output.color_prim; + scaled->f.color_transfer = pv->output.color_transfer; + scaled->f.color_matrix = pv->output.color_matrix; + scaled->f.color_range = pv->output.color_range ; + scaled->f.x = sub->f.x * xfactor; scaled->f.y = sub->f.y * yfactor; @@ -456,9 +466,13 @@ static hb_buffer_t * RenderSSAFrame( hb_filter_private_t * pv, ASS_Image * frame unsigned frameV = (yuv >> 8 ) & 0xff; unsigned frameU = (yuv >> 0 ) & 0xff; - sub = hb_frame_buffer_init( AV_PIX_FMT_YUVA420P, frame->w, frame->h ); - if( sub == NULL ) + sub = hb_frame_buffer_init(pv->output.pix_fmt, frame->w, frame->h); + if (sub == NULL) return NULL; + sub->f.color_prim = pv->output.color_prim; + sub->f.color_transfer = pv->output.color_transfer; + sub->f.color_matrix = pv->output.color_matrix; + sub->f.color_range = pv->output.color_range ; uint8_t *y_out, *u_out, *v_out, *a_out; y_out = sub->plane[0].data; @@ -940,6 +954,8 @@ static int hb_rendersub_init( hb_filter_object_t * filter, hb_subtitle_t *subtitle; int ii; + pv->input = *init; + // Find the subtitle we need for( ii = 0; ii < hb_list_count(init->job->list_subtitle); ii++ ) { @@ -957,6 +973,8 @@ static int hb_rendersub_init( hb_filter_object_t * filter, hb_log("rendersub: no subtitle marked for burn"); return 1; } + pv->output = *init; + return 0; } diff --git a/libhb/scan.c b/libhb/scan.c index 74a5add7bb17..640ffdddbb44 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -1005,9 +1005,11 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title, int flush ) { title->geometry.par = vid_info.geometry.par; } + title->pix_fmt = vid_info.pix_fmt; title->color_prim = vid_info.color_prim; title->color_transfer = vid_info.color_transfer; title->color_matrix = vid_info.color_matrix; + title->color_range = vid_info.color_range; title->video_decode_support = vid_info.video_decode_support; diff --git a/libhb/unsharp.c b/libhb/unsharp.c index 0584408725d2..0206283c408f 100644 --- a/libhb/unsharp.c +++ b/libhb/unsharp.c @@ -42,6 +42,9 @@ struct hb_filter_private_s unsharp_plane_context_t plane_ctx[3]; unsharp_thread_context3_t * thread_ctx; int threads; + + hb_filter_init_t input; + hb_filter_init_t output; }; static int unsharp_init(hb_filter_object_t *filter, @@ -167,6 +170,8 @@ static int unsharp_init(hb_filter_object_t *filter, } hb_filter_private_t * pv = filter->private_data; + pv->input = *init; + // Mark parameters unset for (int c = 0; c < 3; c++) { @@ -236,6 +241,8 @@ static int unsharp_init(hb_filter_object_t *filter, return -1; } + pv->output = *init; + return 0; } @@ -318,7 +325,11 @@ static int unsharp_work_thread(hb_filter_object_t *filter, return HB_FILTER_DONE; } - out = hb_frame_buffer_init(in->f.fmt, in->f.width, in->f.height); + out = hb_frame_buffer_init(pv->output.pix_fmt, in->f.width, in->f.height); + out->f.color_prim = pv->output.color_prim; + out->f.color_transfer = pv->output.color_transfer; + out->f.color_matrix = pv->output.color_matrix; + out->f.color_range = pv->output.color_range ; int c; for (c = 0; c < 3; c++) diff --git a/libhb/work.c b/libhb/work.c index f5654b45d763..e22fbaca99a3 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -1464,10 +1464,11 @@ static void do_job(hb_job_t *job) init.time_base.num = 1; init.time_base.den = 90000; init.job = job; - init.pix_fmt = AV_PIX_FMT_YUV420P; + init.pix_fmt = title->pix_fmt; init.color_prim = title->color_prim; init.color_transfer = title->color_transfer; init.color_matrix = title->color_matrix; + init.color_range = title->color_range; init.geometry.width = title->geometry.width; init.geometry.height = title->geometry.height;