Skip to content

Commit

Permalink
video/image_writer: tag bits_per_raw_sample when pixfmt changes
Browse files Browse the repository at this point in the history
This populates the AVCodecContext->bits_per_raw_sample field value when
the pixel format of the screenshot being written doesn't match the pixel format
of the original video. For example, if the original video was 10-bit and the
screenshot is 16-bit, it populates this field so the encoder can make use of it.

Currently only the libjxl encoder respects this tag although PNG supports sBIT.
Once lavc's PNG encoder respects this tag it will work seamlessly with this commit
as well.

This feature is only enabled if screenshot-high-bit-depth=yes is enabled, because
bits_per_raw_sample shouldn't be set for 8-bit screenshots.
  • Loading branch information
Traneptora committed Jan 31, 2023
1 parent e4e3a8f commit 7de7814
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions video/image_writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <libavcodec/avcodec.h>
#include <libavutil/mem.h>
#include <libavutil/opt.h>
#include <libavutil/pixdesc.h>

#include "config.h"

Expand Down Expand Up @@ -128,6 +129,24 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
avctx->height = image->h;
avctx->color_range = mp_csp_levels_to_avcol_range(image->params.color.levels);
avctx->pix_fmt = imgfmt2pixfmt(image->imgfmt);

/*
* tagging avctx->bits_per_raw_sample indicates the number of significant
* bits. For example, if the original video was 10-bit, and the GPU buffer is
* 16-bit, this tells lavc that only 10 bits are significant. lavc encoders may
* ignore this value, but some codecs can make use of it (for example, PNG's
* sBIT chunk or JXL's bit depth header)
*/
if (ctx->opts->high_bit_depth && ctx->original_format.id != image->imgfmt) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(imgfmt2pixfmt(ctx->original_format.id));
int depth = 0;
for (int i = 0; i < desc->nb_components; i++) {
if (desc->comp[i].depth > depth)
depth = desc->comp[i].depth;
}
avctx->bits_per_raw_sample = depth;
}

if (codec->id == AV_CODEC_ID_MJPEG) {
// Annoying deprecated garbage for the jpg encoder.
if (image->params.color.levels == MP_CSP_LEVELS_PC)
Expand Down

0 comments on commit 7de7814

Please sign in to comment.