Skip to content

Commit

Permalink
libhb: propagate color matrix info through the pipeline
Browse files Browse the repository at this point in the history
Propagates pix_fmt, range, primaries, transfer, and matrix everywhere.

Everything that passes or creates video frames tags the frames with
their color matrix info.

All filters know the expected color matrix info of input frames.
  • Loading branch information
jstebbins committed Apr 8, 2019
1 parent 248c880 commit 3712b29
Show file tree
Hide file tree
Showing 19 changed files with 650 additions and 47 deletions.
117 changes: 97 additions & 20 deletions libhb/avfilter.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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 )
{
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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";
}
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
132 changes: 132 additions & 0 deletions libhb/common.c
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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";
}
}

0 comments on commit 3712b29

Please sign in to comment.