[FFmpeg-devel] [PATCH] dvbsubenc: add a disable_2bpp option to work around some decoders.
Soft Works
softworkz at hotmail.com
Sat Mar 1 14:55:01 EET 2025
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces at ffmpeg.org> On Behalf Of Waider
> Sent: Samstag, 1. März 2025 12:43
> To: ffmpeg-devel at ffmpeg.org
> Subject: [FFmpeg-devel] [PATCH] dvbsubenc: add a disable_2bpp option to
> work around some decoders.
>
> As noted in the code in several places, some DVB subtitle decoders
> don't handle 2bpp color. This patch adds a disable_2bpp option which
> disables the 2bpp format; subtitles which would use 2bpp will be bumped
> up to 4bpp.
>
> Signed-off-by: Ronan Waide <waider at waider.ie>
> ---
> doc/encoders.texi | 24 ++++++++++++
> libavcodec/dvbsubenc.c | 85 +++++++++++++++++++++++++++++++++---------
> 2 files changed, 92 insertions(+), 17 deletions(-)
>
> diff --git a/doc/encoders.texi b/doc/encoders.texi
> index f3fcc1aa60..d6dc92a047 100644
> --- a/doc/encoders.texi
> +++ b/doc/encoders.texi
> @@ -4484,6 +4484,30 @@ Reduces detail but attempts to preserve color at
> extremely low bitrates.
> @chapter Subtitles Encoders
> @c man begin SUBTITLES ENCODERS
>
> + at section dvbsub
> +
> +This codec encodes the bitmap subtitle format that is used in DVB
> +broadcasts and recordings. The bitmaps are typically embedded in a
> +container such as MPEG-TS as a separate stream.
> +
> + at subsection Options
> +
> + at table @option
> + at item disable_2bpp @var{boolean}
> +Disable the 2 bits-per-pixel encoding format.
> +
> +DVB supports 2, 4, and 8 bits-per-pixel color lookup tables. However,
> +not all players support or properly support 2 bits-per-pixel,
> +resulting in unusable subtitles.
> + at table @option
> + at item 0
> +The 2 bits-per-pixel encoding format will be used for subtitles with 4
> +colors or less. (default)
> + at item 1
> +The 2 bits-per-pixel encoding format will be disabled, and subtitles
> +with 4 colors or less will use a 4 bits-per-pixel format.
> + at end table
> +
> @section dvdsub
>
> This codec encodes the bitmap subtitle format that is used in DVDs.
> diff --git a/libavcodec/dvbsubenc.c b/libavcodec/dvbsubenc.c
> index 822e3a5309..727a75e901 100644
> --- a/libavcodec/dvbsubenc.c
> +++ b/libavcodec/dvbsubenc.c
> @@ -22,9 +22,13 @@
> #include "bytestream.h"
> #include "codec_internal.h"
> #include "libavutil/colorspace.h"
> +#include "libavutil/opt.h"
>
> typedef struct DVBSubtitleContext {
> + AVClass * class;
> int object_version;
> + int disable_2bpp;
> + int min_colors;
> } DVBSubtitleContext;
>
> #define PUTBITS2(val)\
> @@ -38,6 +42,18 @@ typedef struct DVBSubtitleContext {
> }\
> }
>
> +static int dvbsub_init(AVCodecContext *avctx)
> +{
> + DVBSubtitleContext *s = avctx->priv_data;
> + if (s->disable_2bpp) {
> + av_log(avctx, AV_LOG_DEBUG, "Disabling 2bpp subtitles.\n");
> + s->min_colors = 16;
> + } else {
> + s->min_colors = 0;
> + }
> + return 0;
> +}
> +
> static int dvb_encode_rle2(uint8_t **pq, int buf_size,
> const uint8_t *bitmap, int linesize,
> int w, int h)
> @@ -326,18 +342,22 @@ static int dvbsub_encode(AVCodecContext *avctx,
> uint8_t *outbuf, int buf_size,
>
> if (h->num_rects) {
> for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
> - if (buf_size < 6 + h->rects[clut_id]->nb_colors * 6)
> + int nb_colors = s->min_colors > h->rects[clut_id]-
> >nb_colors
> + ? s->min_colors
> + : h->rects[clut_id]->nb_colors;
> +
> + if (buf_size < 6 + nb_colors * 6)
> return AVERROR_BUFFER_TOO_SMALL;
>
> /* CLUT segment */
>
> - if (h->rects[clut_id]->nb_colors <= 4) {
> + if (nb_colors <= 4) {
> /* 2 bpp, some decoders do not support it correctly */
> bpp_index = 0;
> - } else if (h->rects[clut_id]->nb_colors <= 16) {
> + } else if (nb_colors <= 16) {
> /* 4 bpp, standard encoding */
> bpp_index = 1;
> - } else if (h->rects[clut_id]->nb_colors <= 256) {
> + } else if (nb_colors <= 256) {
> /* 8 bpp, standard encoding */
> bpp_index = 2;
> } else {
> @@ -354,16 +374,24 @@ static int dvbsub_encode(AVCodecContext *avctx,
> uint8_t *outbuf, int buf_size,
> *q++ = clut_id;
> *q++ = (0 << 4) | 0xf; /* version = 0 */
>
> - for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
> + for(i = 0; i < nb_colors; i++) {
> *q++ = i; /* clut_entry_id */
> *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2
> bits/pixel full range */
> {
> int a, r, g, b;
> - uint32_t x= ((uint32_t*)h->rects[clut_id]-
> >data[1])[i];
> - a = (x >> 24) & 0xff;
> - r = (x >> 16) & 0xff;
> - g = (x >> 8) & 0xff;
> - b = (x >> 0) & 0xff;
> + if (i < h->rects[clut_id]->nb_colors) {
> + uint32_t x= ((uint32_t*)h->rects[clut_id]-
> >data[1])[i];
> + a = (x >> 24) & 0xff;
> + r = (x >> 16) & 0xff;
> + g = (x >> 8) & 0xff;
> + b = (x >> 0) & 0xff;
> + } else {
> + /* pad out the CLUT */
> + a = 0;
> + r = 0;
> + g = 0;
> + b = 0;
> + }
>
> *q++ = RGB_TO_Y_CCIR(r, g, b);
> *q++ = RGB_TO_V_CCIR(r, g, b, 0);
> @@ -373,7 +401,7 @@ static int dvbsub_encode(AVCodecContext *avctx,
> uint8_t *outbuf, int buf_size,
> }
>
> bytestream_put_be16(&pseg_len, q - pseg_len - 2);
> - buf_size -= 6 + h->rects[clut_id]->nb_colors * 6;
> + buf_size -= 6 + nb_colors * 6;
> }
>
> if (buf_size < h->num_rects * 22)
> @@ -381,14 +409,17 @@ static int dvbsub_encode(AVCodecContext *avctx,
> uint8_t *outbuf, int buf_size,
> for (region_id = 0; region_id < h->num_rects; region_id++) {
>
> /* region composition segment */
> + int nb_colors = s->min_colors > h->rects[region_id]-
> >nb_colors
> + ? s->min_colors
> + : h->rects[region_id]->nb_colors;
>
> - if (h->rects[region_id]->nb_colors <= 4) {
> + if (nb_colors <= 4) {
> /* 2 bpp, some decoders do not support it correctly */
> bpp_index = 0;
> - } else if (h->rects[region_id]->nb_colors <= 16) {
> + } else if (nb_colors <= 16) {
> /* 4 bpp, standard encoding */
> bpp_index = 1;
> - } else if (h->rects[region_id]->nb_colors <= 256) {
> + } else if (nb_colors <= 256) {
> /* 8 bpp, standard encoding */
> bpp_index = 2;
> } else {
> @@ -424,17 +455,21 @@ static int dvbsub_encode(AVCodecContext *avctx,
> uint8_t *outbuf, int buf_size,
> const uint8_t *bitmap, int linesize,
> int w, int h);
>
> + int nb_colors = s->min_colors > h->rects[object_id]-
> >nb_colors
> + ? s->min_colors
> + : h->rects[object_id]->nb_colors;
> +
> if (buf_size < 13)
> return AVERROR_BUFFER_TOO_SMALL;
>
> /* bpp_index maths */
> - if (h->rects[object_id]->nb_colors <= 4) {
> + if (nb_colors <= 4) {
> /* 2 bpp, some decoders do not support it correctly */
> dvb_encode_rle = dvb_encode_rle2;
> - } else if (h->rects[object_id]->nb_colors <= 16) {
> + } else if (nb_colors <= 16) {
> /* 4 bpp, standard encoding */
> dvb_encode_rle = dvb_encode_rle4;
> - } else if (h->rects[object_id]->nb_colors <= 256) {
> + } else if (nb_colors <= 256) {
> /* 8 bpp, standard encoding */
> dvb_encode_rle = dvb_encode_rle8;
> } else {
> @@ -506,6 +541,20 @@ static int dvbsub_encode(AVCodecContext *avctx,
> uint8_t *outbuf, int buf_size,
> return q - outbuf;
> }
>
> +#define OFFSET(x) offsetof(DVBSubtitleContext, x)
> +#define SE AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM
> +static const AVOption options[] = {
> + {"disable_2bpp", "disable the 2bpp subtitle encoder",
> OFFSET(disable_2bpp), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, SE},
> + { NULL },
> +};
> +
> +static const AVClass dvbsubenc_class = {
> + .class_name = "DVBSUB subtitle encoder",
> + .item_name = av_default_item_name,
> + .option = options,
> + .version = LIBAVUTIL_VERSION_INT,
> +};
> +
> const FFCodec ff_dvbsub_encoder = {
> .p.name = "dvbsub",
> CODEC_LONG_NAME("DVB subtitles"),
> @@ -513,4 +562,6 @@ const FFCodec ff_dvbsub_encoder = {
> .p.id = AV_CODEC_ID_DVB_SUBTITLE,
> .priv_data_size = sizeof(DVBSubtitleContext),
> FF_CODEC_ENCODE_SUB_CB(dvbsub_encode),
> + .init = dvbsub_init,
> + .p.priv_class = &dvbsubenc_class,
> };
> --
Hi,
thanks for your contribution.
Your patch fails to apply:
https://patchwork.ffmpeg.org/project/ffmpeg/patch/1D1812F5-DB2A-4847-89DB-EF3A1A6C9BCF@waider.ie/
It appears to be created against an older version of the code. Patches need to be made with the current HEAD of the master branch as the base.
Best,
sw
More information about the ffmpeg-devel
mailing list