ref: 7bbebdb4639ee20fa3213396b223ebdc1db91210
parent: f01fd0f1e5ab18fd3dcd1c4e32e33bf84170b38e
author: Niklas Haas <git@haasn.xyz>
date: Sun May 17 21:53:42 EDT 2020
dav1dplay: handle all supported csps/reprs/bitdepths Generalize the code to set the right pl_image metadata based on the values signaled in the Dav1dPictureParameters / Dav1dSequenceHeader. Some values are not mapped, in which case stdout will be spammed. Whatever. Hopefully somebody sees that error spam and opens a bug report for libplacebo to implement it.
--- a/examples/dp_renderer_placebo.c
+++ b/examples/dp_renderer_placebo.c
@@ -358,23 +358,133 @@
int width = dav1d_pic->p.w;
int height = dav1d_pic->p.h;
+ int sub_x = 0, sub_y = 0;
+ int bytes = (dav1d_pic->p.bpc + 7) / 8; // rounded up
+ enum pl_chroma_location chroma_loc = PL_CHROMA_UNKNOWN;
- enum Dav1dPixelLayout dav1d_layout = dav1d_pic->p.layout;
-
- if (DAV1D_PIXEL_LAYOUT_I420 != dav1d_layout || dav1d_pic->p.bpc != 8) {
- fprintf(stderr, "Unsupported pixel format, only 8bit 420 supported so far.\n");
- exit(50);
- }
-
struct pl_image *image = &rd_priv_ctx->image;
*image = (struct pl_image) {
.num_planes = 3,
- .repr = pl_color_repr_hdtv,
- .color = pl_color_space_unknown,
.width = width,
.height = height,
+
+ .repr = {
+ .bits = {
+ .sample_depth = bytes * 8,
+ .color_depth = dav1d_pic->p.bpc,
+ },
+ },
};
+ // Figure out the correct plane dimensions/count
+ switch (dav1d_pic->p.layout) {
+ case DAV1D_PIXEL_LAYOUT_I400:
+ image->num_planes = 1;
+ break;
+ case DAV1D_PIXEL_LAYOUT_I420:
+ sub_x = sub_y = 1;
+ break;
+ case DAV1D_PIXEL_LAYOUT_I422:
+ sub_x = 1;
+ break;
+ case DAV1D_PIXEL_LAYOUT_I444:
+ break;
+ }
+
+ // Set the right colorspace metadata etc.
+ switch (dav1d_pic->seq_hdr->pri) {
+ case DAV1D_COLOR_PRI_UNKNOWN: image->color.primaries = PL_COLOR_PRIM_UNKNOWN; break;
+ case DAV1D_COLOR_PRI_BT709: image->color.primaries = PL_COLOR_PRIM_BT_709; break;
+ case DAV1D_COLOR_PRI_BT470M: image->color.primaries = PL_COLOR_PRIM_BT_470M; break;
+ case DAV1D_COLOR_PRI_BT470BG: image->color.primaries = PL_COLOR_PRIM_BT_601_625; break;
+ case DAV1D_COLOR_PRI_BT601: image->color.primaries = PL_COLOR_PRIM_BT_601_625; break;
+ case DAV1D_COLOR_PRI_BT2020: image->color.primaries = PL_COLOR_PRIM_BT_2020; break;
+
+ case DAV1D_COLOR_PRI_XYZ:
+ // Handled below
+ assert(dav1d_pic->seq_hdr->mtrx == DAV1D_MC_IDENTITY);
+ break;
+
+ default:
+ printf("warning: unknown dav1d color primaries %d.. ignoring, picture "
+ "may be very incorrect\n", dav1d_pic->seq_hdr->pri);
+ break;
+ }
+
+ switch (dav1d_pic->seq_hdr->trc) {
+ case DAV1D_TRC_BT709:
+ case DAV1D_TRC_BT470M:
+ case DAV1D_TRC_BT470BG:
+ case DAV1D_TRC_BT601:
+ case DAV1D_TRC_SMPTE240:
+ case DAV1D_TRC_BT2020_10BIT:
+ case DAV1D_TRC_BT2020_12BIT:
+ // These all map to the effective "SDR" CRT-based EOTF, BT.1886
+ image->color.transfer = PL_COLOR_TRC_BT_1886;
+ break;
+
+ case DAV1D_TRC_UNKNOWN: image->color.transfer = PL_COLOR_TRC_UNKNOWN; break;
+ case DAV1D_TRC_LINEAR: image->color.transfer = PL_COLOR_TRC_LINEAR; break;
+ case DAV1D_TRC_SRGB: image->color.transfer = PL_COLOR_TRC_SRGB; break;
+ case DAV1D_TRC_SMPTE2084: image->color.transfer = PL_COLOR_TRC_PQ; break;
+ case DAV1D_TRC_HLG: image->color.transfer = PL_COLOR_TRC_HLG; break;
+
+ default:
+ printf("warning: unknown dav1d color transfer %d.. ignoring, picture "
+ "may be very incorrect\n", dav1d_pic->seq_hdr->trc);
+ break;
+ }
+
+ switch (dav1d_pic->seq_hdr->mtrx) {
+ case DAV1D_MC_IDENTITY:
+ // This is going to be either RGB or XYZ
+ if (dav1d_pic->seq_hdr->pri == DAV1D_COLOR_PRI_XYZ) {
+ image->repr.sys = PL_COLOR_SYSTEM_XYZ;
+ } else {
+ image->repr.sys = PL_COLOR_SYSTEM_RGB;
+ }
+ break;
+
+ case DAV1D_MC_UNKNOWN:
+ // PL_COLOR_SYSTEM_UNKNOWN maps to RGB, so hard-code this one
+ image->repr.sys = pl_color_system_guess_ycbcr(width, height);
+ break;
+
+ case DAV1D_MC_BT709: image->repr.sys = PL_COLOR_SYSTEM_BT_709; break;
+ case DAV1D_MC_BT601: image->repr.sys = PL_COLOR_SYSTEM_BT_601; break;
+ case DAV1D_MC_SMPTE240: image->repr.sys = PL_COLOR_SYSTEM_SMPTE_240M; break;
+ case DAV1D_MC_SMPTE_YCGCO: image->repr.sys = PL_COLOR_SYSTEM_YCGCO; break;
+ case DAV1D_MC_BT2020_NCL: image->repr.sys = PL_COLOR_SYSTEM_BT_2020_NC; break;
+ case DAV1D_MC_BT2020_CL: image->repr.sys = PL_COLOR_SYSTEM_BT_2020_C; break;
+
+ case DAV1D_MC_ICTCP:
+ // This one is split up based on the actual HDR curve in use
+ if (dav1d_pic->seq_hdr->trc == DAV1D_TRC_HLG) {
+ image->repr.sys = PL_COLOR_SYSTEM_BT_2100_HLG;
+ } else {
+ image->repr.sys = PL_COLOR_SYSTEM_BT_2100_PQ;
+ }
+ break;
+
+ default:
+ printf("warning: unknown dav1d color matrix %d.. ignoring, picture "
+ "may be very incorrect\n", dav1d_pic->seq_hdr->mtrx);
+ break;
+ }
+
+ if (dav1d_pic->seq_hdr->color_range) {
+ image->repr.levels = PL_COLOR_LEVELS_PC;
+ } else {
+ image->repr.levels = PL_COLOR_LEVELS_TV;
+ }
+
+ switch (dav1d_pic->seq_hdr->chr) {
+ case DAV1D_CHR_UNKNOWN: chroma_loc = PL_CHROMA_UNKNOWN; break;
+ case DAV1D_CHR_VERTICAL: chroma_loc = PL_CHROMA_LEFT; break;
+ case DAV1D_CHR_COLOCATED: chroma_loc = PL_CHROMA_TOP_LEFT; break;
+ }
+
+ // Upload the actual planes
struct pl_plane_data data[3] = {
{
// Y plane
@@ -381,27 +491,27 @@
.type = PL_FMT_UNORM,
.width = width,
.height = height,
- .pixel_stride = 1,
+ .pixel_stride = bytes,
.row_stride = dav1d_pic->stride[0],
- .component_size = {8},
+ .component_size = {bytes * 8},
.component_map = {0},
}, {
// U plane
.type = PL_FMT_UNORM,
- .width = width >> 1,
- .height = height >> 1,
- .pixel_stride = 1,
+ .width = width >> sub_x,
+ .height = height >> sub_y,
+ .pixel_stride = bytes,
.row_stride = dav1d_pic->stride[1],
- .component_size = {8},
+ .component_size = {bytes * 8},
.component_map = {1},
}, {
// V plane
.type = PL_FMT_UNORM,
- .width = width >> 1,
- .height = height >> 1,
- .pixel_stride = 1,
+ .width = width >> sub_x,
+ .height = height >> sub_y,
+ .pixel_stride = bytes,
.row_stride = dav1d_pic->stride[1],
- .component_size = {8},
+ .component_size = {bytes * 8},
.component_map = {2},
},
};
@@ -408,8 +518,7 @@
bool ok = true;
- // Upload the actual planes
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < image->num_planes; i++) {
if (settings->zerocopy) {
const struct pl_buf *buf = dav1d_pic->allocator_data;
assert(buf);
@@ -422,16 +531,9 @@
ok &= pl_upload_plane(rd_priv_ctx->gpu, &image->planes[i], &rd_priv_ctx->plane_tex[i], &data[i]);
}
- // Set the right chroma shift based on the Dav1dPicture metadata
- switch (dav1d_pic->seq_hdr->chr) {
- case DAV1D_CHR_VERTICAL:
- pl_chroma_location_offset(PL_CHROMA_LEFT, &image->planes[1].shift_x, &image->planes[1].shift_y);
- pl_chroma_location_offset(PL_CHROMA_LEFT, &image->planes[2].shift_x, &image->planes[2].shift_y);
- break;
- case DAV1D_CHR_UNKNOWN:
- case DAV1D_CHR_COLOCATED:
- break; // no shift
- }
+ // Apply the correct chroma plane shift. This has to be done after pl_upload_plane
+ pl_chroma_location_offset(chroma_loc, &image->planes[1].shift_x, &image->planes[1].shift_y);
+ pl_chroma_location_offset(chroma_loc, &image->planes[2].shift_x, &image->planes[2].shift_y);
if (!ok) {
fprintf(stderr, "Failed uploading planes!\n");