Skip to content

Commit e4af9b5

Browse files
committed
Add Dolby Vision Profile 7 FEL support
1 parent ccb4bea commit e4af9b5

4 files changed

Lines changed: 488 additions & 369 deletions

File tree

src/dovi_meta.h

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
#include <libdovi/rpu_parser.h>
77

88
static struct pl_dovi_metadata *create_dovi_meta(DoviRpuOpaque *rpu,
9-
const DoviRpuDataHeader *hdr)
9+
const DoviRpuDataHeader *hdr,
10+
const bool el_present)
1011
{
1112
static struct pl_dovi_metadata dovi_meta; // persist state
1213
if (hdr->use_prev_vdr_rpu_flag)
@@ -16,10 +17,9 @@ static struct pl_dovi_metadata *create_dovi_meta(DoviRpuOpaque *rpu,
1617
if (!mapping)
1718
goto skip_mapping;
1819

19-
const uint8_t bits = hdr->bl_bit_depth_minus8 + 8;
20-
const float scale = 1.0f / (1 << hdr->coefficient_log2_denom);
20+
const uint8_t bl_bit_depth = hdr->bl_bit_depth_minus8 + 8;
21+
const float coef_scale_d = 1.0f / (1ULL << hdr->coefficient_log2_denom);
2122

22-
#if RPU_PARSER_MAJOR >= 3
2323
for (int c = 0; c < 3; c++) {
2424
const DoviReshapingCurve curve = mapping->curves[c];
2525

@@ -30,7 +30,7 @@ static struct pl_dovi_metadata *create_dovi_meta(DoviRpuOpaque *rpu,
3030
uint16_t pivot = 0;
3131
for (int pivot_idx = 0; pivot_idx < cmp->num_pivots; pivot_idx++) {
3232
pivot += curve.pivots.data[pivot_idx];
33-
cmp->pivots[pivot_idx] = (float) pivot / ((1 << bits) - 1);
33+
cmp->pivots[pivot_idx] = (float) pivot / ((1 << bl_bit_depth) - 1);
3434
}
3535

3636
for (int i = 0; i < cmp->num_pivots - 1; i++) {
@@ -42,62 +42,55 @@ static struct pl_dovi_metadata *create_dovi_meta(DoviRpuOpaque *rpu,
4242
for (int k = 0; k <= poly_curve->poly_order_minus1.data[i] + 1; k++) {
4343
int64_t ipart = poly_curve->poly_coef_int.list[i]->data[k];
4444
uint64_t fpart = poly_curve->poly_coef.list[i]->data[k];
45-
cmp->poly_coeffs[i][k] = ipart + scale * fpart;
45+
cmp->poly_coeffs[i][k] = ipart + coef_scale_d * fpart;
4646
}
4747
} else if (curve.mmr) {
4848
const DoviMMRCurve *mmr_curve = curve.mmr;
4949

5050
int64_t ipart = mmr_curve->mmr_constant_int.data[i];
5151
uint64_t fpart = mmr_curve->mmr_constant.data[i];
52-
cmp->mmr_constant[i] = ipart + scale * fpart;
52+
cmp->mmr_constant[i] = ipart + coef_scale_d * fpart;
5353
cmp->mmr_order[i] = mmr_curve->mmr_order_minus1.data[i] + 1;
5454

5555
for (int j = 0; j < cmp->mmr_order[i]; j++) {
5656
for (int k = 0; k < 7; k++) {
5757
ipart = mmr_curve->mmr_coef_int.list[i]->list[j]->data[k];
5858
fpart = mmr_curve->mmr_coef.list[i]->list[j]->data[k];
59-
cmp->mmr_coeffs[i][j][k] = ipart + scale * fpart;
59+
cmp->mmr_coeffs[i][j][k] = ipart + coef_scale_d * fpart;
6060
}
6161
}
6262
}
6363
}
6464
}
65-
#else
66-
for (int c = 0; c < 3; c++) {
67-
struct pl_reshape_data *cmp = &dovi_meta.comp[c];
68-
uint16_t pivot = 0;
69-
cmp->num_pivots = hdr->num_pivots_minus_2[c] + 2;
70-
for (int pivot_idx = 0; pivot_idx < cmp->num_pivots; pivot_idx++) {
71-
pivot += hdr->pred_pivot_value[c].data[pivot_idx];
72-
cmp->pivots[pivot_idx] = (float) pivot / ((1 << bits) - 1);
73-
}
7465

75-
for (int i = 0; i < cmp->num_pivots - 1; i++) {
76-
memset(cmp->poly_coeffs[i], 0, sizeof(cmp->poly_coeffs[i]));
77-
cmp->method[i] = mapping->mapping_idc[c].data[i];
78-
79-
switch (cmp->method[i]) {
80-
case 0: // polynomial
81-
for (int k = 0; k <= mapping->poly_order_minus1[c].data[i] + 1; k++) {
82-
int64_t ipart = mapping->poly_coef_int[c].list[i]->data[k];
83-
uint64_t fpart = mapping->poly_coef[c].list[i]->data[k];
84-
cmp->poly_coeffs[i][k] = ipart + scale * fpart;
85-
}
86-
break;
87-
case 1: // MMR
88-
int64_t ipart = mapping->mmr_constant_int[c].data[i];
89-
uint64_t fpart = mapping->mmr_constant[c].data[i];
90-
cmp->mmr_constant[i] = ipart + scale * fpart;
91-
cmp->mmr_order[i] = mapping->mmr_order_minus1[c].data[i] + 1;
92-
for (int j = 1; j <= cmp->mmr_order[i]; j++) {
93-
for (int k = 0; k < 7; k++) {
94-
ipart = mapping->mmr_coef_int[c].list[i]->list[j]->data[k];
95-
fpart = mapping->mmr_coef[c].list[i]->list[j]->data[k];
96-
cmp->mmr_coeffs[i][j - 1][k] = ipart + scale * fpart;
97-
}
98-
}
99-
break;
100-
}
66+
#if PL_API_VER >= 369
67+
// See `pl_map_dovi_metadata` for documentation
68+
// Re-implemented using libdovi
69+
dovi_meta.nlq_active = el_present &&
70+
!hdr->disable_residual_flag &&
71+
strcmp(hdr->el_type, "FEL") == 0 &&
72+
mapping->nlq_method_idc == 0; // LINEAR_DZ NLQ
73+
74+
if (dovi_meta.nlq_active && mapping->nlq) {
75+
const uint8_t el_bit_depth = hdr->el_bit_depth_minus8 + 8;
76+
const float el_scale = 1.0f / ((1 << el_bit_depth) - 1);
77+
78+
const double slope_scale_d = ((1ULL << el_bit_depth) - 1) * coef_scale_d;
79+
80+
const DoviRpuDataNlq *src = mapping->nlq;
81+
for (int c = 0; c < 3; c++) {
82+
struct pl_dovi_nlq_data *dst = &dovi_meta.nlq[c];
83+
84+
uint64_t slope_ipart = src->linear_deadzone_slope_int[c];
85+
uint64_t slope_fpart = src->linear_deadzone_slope[c];
86+
uint64_t thr_ipart = src->linear_deadzone_threshold_int[c];
87+
uint64_t thr_fpart = src->linear_deadzone_threshold[c];
88+
89+
const double S = (slope_ipart << hdr->coefficient_log2_denom) | slope_fpart;
90+
const double T = (thr_ipart << hdr->coefficient_log2_denom) | thr_fpart;
91+
dst->offset = el_scale * src->nlq_offset[c];
92+
dst->deadzone_slope = slope_scale_d * S;
93+
dst->deadzone_threshold = coef_scale_d * (T - 0.5 * S);
10194
}
10295
}
10396
#endif

0 commit comments

Comments
 (0)