diff mbox

[FFmpeg-devel] lavc/libzvbi: base support for multiple levels

Message ID 20170217214336.99700-1-josh@itanimul.li
State Rejected
Headers show

Commit Message

Josh Dekker Feb. 17, 2017, 9:43 p.m. UTC
Also add support for level 1.0 explicitly.

Signed-off-by: Josh de Kock <josh@itanimul.li>
---
 libavcodec/libzvbi-teletextdec.c | 60 ++++++++++++++++++++++++++++------------
 1 file changed, 42 insertions(+), 18 deletions(-)

Comments

Marton Balint Feb. 18, 2017, 12:51 a.m. UTC | #1
On Fri, 17 Feb 2017, Josh de Kock wrote:

> Also add support for level 1.0 explicitly.
>

What is the use case for this? Reducing the number of colors?

I don't think you can reduce the number of colors based on teletext level, 
because libzvbi uses high (>32) colors for navigation, which is also part 
of level 1.0.

Also, I don't think you can skip fix_transparency.

And by reducing to level 1.0, you are excluding a lot of users, many 
countries use the extra international characters level 1.5 provides.

If you only want to reduce the number of colors, then I prefer an option 
which makes the code go through every pixel, find the minimum color 
value, and sets nb_colors to that.  Still a hack, but IMHO small enough to 
be acceptable, until subtitle filters are implemented, and you can do this 
with a filter.

Regards,
Marton



> Signed-off-by: Josh de Kock <josh@itanimul.li>
> ---
> libavcodec/libzvbi-teletextdec.c | 60 ++++++++++++++++++++++++++++------------
> 1 file changed, 42 insertions(+), 18 deletions(-)
>
> diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c
> index 687b6af..b4316f4 100644
> --- a/libavcodec/libzvbi-teletextdec.c
> +++ b/libavcodec/libzvbi-teletextdec.c
> @@ -76,6 +76,7 @@ typedef struct TeletextContext
>     vbi_sliced      sliced[MAX_SLICES];
>
>     int             readorder;
> +    int             wst_level;
> } TeletextContext;
> 
> static int chop_spaces_utf8(const unsigned char* t, int len)
> @@ -248,32 +249,51 @@ static int gen_sub_bitmap(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_pa
>                             sub_rect->data[0], sub_rect->linesize[0],
>                             0, chop_top, page->columns, page->rows - chop_top,
>                             /*reveal*/ 1, /*flash*/ 1);
> -
> -    fix_transparency(ctx, sub_rect, page, chop_top, resx, resy);
> +    if (ctx->opacity != -1)
> +        fix_transparency(ctx, sub_rect, page, chop_top, resx, resy);
>     sub_rect->x = ctx->x_offset;
>     sub_rect->y = ctx->y_offset + chop_top * BITMAP_CHAR_HEIGHT;
>     sub_rect->w = resx;
>     sub_rect->h = resy;
> -    sub_rect->nb_colors = ctx->opacity > 0 && ctx->opacity < 255 ? 2 * VBI_NB_COLORS : VBI_NB_COLORS;
> +    sub_rect->type = SUBTITLE_BITMAP;
> +
>     sub_rect->data[1] = av_mallocz(AVPALETTE_SIZE);
>     if (!sub_rect->data[1]) {
>         av_freep(&sub_rect->data[0]);
>         return AVERROR(ENOMEM);
>     }
> -    for (ci = 0; ci < VBI_NB_COLORS; ci++) {
> -        int r, g, b, a;
> -
> -        r = VBI_R(page->color_map[ci]);
> -        g = VBI_G(page->color_map[ci]);
> -        b = VBI_B(page->color_map[ci]);
> -        a = VBI_A(page->color_map[ci]);
> -        ((uint32_t *)sub_rect->data[1])[ci] = RGBA(r, g, b, a);
> -        ((uint32_t *)sub_rect->data[1])[ci + VBI_NB_COLORS] = RGBA(r, g, b, ctx->opacity);
> -        ff_dlog(ctx, "palette %0x\n", ((uint32_t *)sub_rect->data[1])[ci]);
> +
> +    switch (ctx->wst_level) {
> +    case VBI_WST_LEVEL_1:
> +        sub_rect->nb_colors = 16;
> +        for (ci = 0; ci < VBI_NB_COLORS; ci ++)
> +            ((uint32_t *)sub_rect->data[1])[ci] = ci < 16 ? RGBA(VBI_R(page->color_map[ci]), VBI_G(page->color_map[ci]),
> +                                                                 VBI_B(page->color_map[ci]), VBI_A(page->color_map[ci])) :
> +                                                            RGBA(0, 0, 0, 0);
> +        break;
> +    case VBI_WST_LEVEL_1p5:
> +    case VBI_WST_LEVEL_2p5:
> +        return AVERROR_PATCHWELCOME;
> +        break;
> +    case VBI_WST_LEVEL_3p5:
> +        sub_rect->nb_colors = ctx->opacity > 0 && ctx->opacity < 255 ? 2 * VBI_NB_COLORS : VBI_NB_COLORS;
> +        for (ci = 0; ci < VBI_NB_COLORS; ci++) {
> +            int r, g, b, a;
> +
> +            r = VBI_R(page->color_map[ci]);
> +            g = VBI_G(page->color_map[ci]);
> +            b = VBI_B(page->color_map[ci]);
> +            a = VBI_A(page->color_map[ci]);
> +            ((uint32_t *)sub_rect->data[1])[ci] = RGBA(r, g, b, a);
> +            ((uint32_t *)sub_rect->data[1])[ci + VBI_NB_COLORS] = RGBA(r, g, b, ctx->opacity);
> +            av_log(ctx, AV_LOG_DEBUG, "palette %08x pallete opacity %08x\n",
> +                ((uint32_t *)sub_rect->data[1])[ci], ((uint32_t *)sub_rect->data[1])[ci + VBI_NB_COLORS]);
> +        }
>     }
> +
>     ((uint32_t *)sub_rect->data[1])[VBI_TRANSPARENT_BLACK] = RGBA(0, 0, 0, 0);
>     ((uint32_t *)sub_rect->data[1])[VBI_TRANSPARENT_BLACK + VBI_NB_COLORS] = RGBA(0, 0, 0, 0);
> -    sub_rect->type = SUBTITLE_BITMAP;
> +
>     return 0;
> }
> 
> @@ -301,7 +321,7 @@ static void handler(vbi_event *ev, void *user_data)
>     res = vbi_fetch_vt_page(ctx->vbi, &page,
>                             ev->ev.ttx_page.pgno,
>                             ev->ev.ttx_page.subno,
> -                            VBI_WST_LEVEL_3p5, 25, TRUE);
> +                            ctx->wst_level, 25, TRUE);
>
>     if (!res)
>         return;
> @@ -549,9 +569,13 @@ static const AVOption options[] = {
>     {"txt_top",         "y offset of generated bitmaps",                     OFFSET(y_offset),       AV_OPT_TYPE_INT,    {.i64 = 0},        0, 65535,    SD},
>     {"txt_chop_spaces", "chops leading and trailing spaces from text",       OFFSET(chop_spaces),    AV_OPT_TYPE_INT,    {.i64 = 1},        0, 1,        SD},
>     {"txt_duration",    "display duration of teletext pages in msecs",       OFFSET(sub_duration),   AV_OPT_TYPE_INT,    {.i64 = 30000},    0, 86400000, SD},
> -    {"txt_transparent", "force transparent background of the teletext",      OFFSET(transparent_bg), AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,        SD},
> -    {"txt_opacity",     "set opacity of the transparent background",         OFFSET(opacity),        AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 255,      SD},
> -    { NULL },
> +    {"txt_transparent", "force transparent background of the teletext (doesn't work with level 1.0)", OFFSET(transparent_bg), AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,        SD},
> +    {"txt_opacity",     "set opacity of the transparent background (doesn't work with level 1.0)",    OFFSET(opacity),        AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 255,      SD},
> +    {"txt_level",       "set the output level of the teletext bitmap",       OFFSET(wst_level),      AV_OPT_TYPE_INT,    {.i64 = VBI_WST_LEVEL_3p5}, VBI_WST_LEVEL_1, VBI_WST_LEVEL_3p5, SD, "txt_level"},
> +    {"1.0",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_1},   0, 0, SD, "txt_level"},
> +    {"1.5",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_1p5}, 0, 0, SD, "txt_level"},
> +    {"2.5",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_2p5}, 0, 0, SD, "txt_level"},
> +    {"3.5",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_3p5}, 0, 0, SD, "txt_level"},
> };
> 
> static const AVClass teletext_class = {
> -- 
> 2.10.1 (Apple Git-78)
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Josh Dekker Feb. 18, 2017, 2:48 a.m. UTC | #2
On 18/02/2017 00:51, Marton Balint wrote:
> 
> On Fri, 17 Feb 2017, Josh de Kock wrote:
> 
>> Also add support for level 1.0 explicitly.
>>
> 
> What is the use case for this? Reducing the number of colors?
> 

Pretty much.

> I don't think you can reduce the number of colors based on teletext
> level, because libzvbi uses high (>32) colors for navigation, which is
> also part of level 1.0.
> 
> Also, I don't think you can skip fix_transparency.
> 

Does level 1.0 support transparency?

> And by reducing to level 1.0, you are excluding a lot of users, many
> countries use the extra international characters level 1.5 provides.
> 

1.5 could be done instead.

> If you only want to reduce the number of colors, then I prefer an option
> which makes the code go through every pixel, find the minimum color
> value, and sets nb_colors to that.  Still a hack, but IMHO small enough
> to be acceptable, until subtitle filters are implemented, and you can do
> this with a filter.
> 

Not entirely sure what you mean by this, shouldn't the nb_colors be set
based on the CLUT?

>
> [...]
>
Marton Balint Feb. 18, 2017, 4:31 p.m. UTC | #3
On Sat, 18 Feb 2017, Josh de Kock wrote:

> On 18/02/2017 00:51, Marton Balint wrote:
>> 
>> On Fri, 17 Feb 2017, Josh de Kock wrote:
>> 
>>> Also add support for level 1.0 explicitly.
>>>
>> 
>> What is the use case for this? Reducing the number of colors?
>> 
>
> Pretty much.
>
>> I don't think you can reduce the number of colors based on teletext
>> level, because libzvbi uses high (>32) colors for navigation, which is
>> also part of level 1.0.
>> 
>> Also, I don't think you can skip fix_transparency.
>> 
>
> Does level 1.0 support transparency?

Not as a color, but as a feature. See Start Box/End Box. Typical for 
subtitles.

>
>> And by reducing to level 1.0, you are excluding a lot of users, many
>> countries use the extra international characters level 1.5 provides.
>> 
>
> 1.5 could be done instead.
>
>> If you only want to reduce the number of colors, then I prefer an option
>> which makes the code go through every pixel, find the minimum color
>> value, and sets nb_colors to that.  Still a hack, but IMHO small enough
>> to be acceptable, until subtitle filters are implemented, and you can do
>> this with a filter.
>> 
>
> Not entirely sure what you mean by this, shouldn't the nb_colors be set
> based on the CLUT?

As long as according to zvbi docs it has internal colors from index 32 to 
39 for navigation, it does not matter how many CLUT the page uses.

What I am saying is that it's simpler to add a txt_reduce_colors 
option, and if that is set, find the maximum used color index, and set 
nb_colors to that + 1.

I think the original teletext patch had such a feature, but I removed it, 
hoping that it can be achieved with a subtitle filter later in the 
future...

Or if you are specifically aiming for 16 colors, then the 
txt_reduce_colors option can do a modulo 16 for each color index instead 
of finding the maximum index, which may vary between different pages, and 
I don't know how the dvb subtitle encoder would behave in that case.

Regards,
Marton
diff mbox

Patch

diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c
index 687b6af..b4316f4 100644
--- a/libavcodec/libzvbi-teletextdec.c
+++ b/libavcodec/libzvbi-teletextdec.c
@@ -76,6 +76,7 @@  typedef struct TeletextContext
     vbi_sliced      sliced[MAX_SLICES];
 
     int             readorder;
+    int             wst_level;
 } TeletextContext;
 
 static int chop_spaces_utf8(const unsigned char* t, int len)
@@ -248,32 +249,51 @@  static int gen_sub_bitmap(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_pa
                             sub_rect->data[0], sub_rect->linesize[0],
                             0, chop_top, page->columns, page->rows - chop_top,
                             /*reveal*/ 1, /*flash*/ 1);
-
-    fix_transparency(ctx, sub_rect, page, chop_top, resx, resy);
+    if (ctx->opacity != -1)
+        fix_transparency(ctx, sub_rect, page, chop_top, resx, resy);
     sub_rect->x = ctx->x_offset;
     sub_rect->y = ctx->y_offset + chop_top * BITMAP_CHAR_HEIGHT;
     sub_rect->w = resx;
     sub_rect->h = resy;
-    sub_rect->nb_colors = ctx->opacity > 0 && ctx->opacity < 255 ? 2 * VBI_NB_COLORS : VBI_NB_COLORS;
+    sub_rect->type = SUBTITLE_BITMAP;
+
     sub_rect->data[1] = av_mallocz(AVPALETTE_SIZE);
     if (!sub_rect->data[1]) {
         av_freep(&sub_rect->data[0]);
         return AVERROR(ENOMEM);
     }
-    for (ci = 0; ci < VBI_NB_COLORS; ci++) {
-        int r, g, b, a;
-
-        r = VBI_R(page->color_map[ci]);
-        g = VBI_G(page->color_map[ci]);
-        b = VBI_B(page->color_map[ci]);
-        a = VBI_A(page->color_map[ci]);
-        ((uint32_t *)sub_rect->data[1])[ci] = RGBA(r, g, b, a);
-        ((uint32_t *)sub_rect->data[1])[ci + VBI_NB_COLORS] = RGBA(r, g, b, ctx->opacity);
-        ff_dlog(ctx, "palette %0x\n", ((uint32_t *)sub_rect->data[1])[ci]);
+
+    switch (ctx->wst_level) {
+    case VBI_WST_LEVEL_1:
+        sub_rect->nb_colors = 16;
+        for (ci = 0; ci < VBI_NB_COLORS; ci ++)
+            ((uint32_t *)sub_rect->data[1])[ci] = ci < 16 ? RGBA(VBI_R(page->color_map[ci]), VBI_G(page->color_map[ci]),
+                                                                 VBI_B(page->color_map[ci]), VBI_A(page->color_map[ci])) :
+                                                            RGBA(0, 0, 0, 0);
+        break;
+    case VBI_WST_LEVEL_1p5:
+    case VBI_WST_LEVEL_2p5:
+        return AVERROR_PATCHWELCOME;
+        break;
+    case VBI_WST_LEVEL_3p5:
+        sub_rect->nb_colors = ctx->opacity > 0 && ctx->opacity < 255 ? 2 * VBI_NB_COLORS : VBI_NB_COLORS;
+        for (ci = 0; ci < VBI_NB_COLORS; ci++) {
+            int r, g, b, a;
+
+            r = VBI_R(page->color_map[ci]);
+            g = VBI_G(page->color_map[ci]);
+            b = VBI_B(page->color_map[ci]);
+            a = VBI_A(page->color_map[ci]);
+            ((uint32_t *)sub_rect->data[1])[ci] = RGBA(r, g, b, a);
+            ((uint32_t *)sub_rect->data[1])[ci + VBI_NB_COLORS] = RGBA(r, g, b, ctx->opacity);
+            av_log(ctx, AV_LOG_DEBUG, "palette %08x pallete opacity %08x\n",
+                ((uint32_t *)sub_rect->data[1])[ci], ((uint32_t *)sub_rect->data[1])[ci + VBI_NB_COLORS]);
+        }
     }
+
     ((uint32_t *)sub_rect->data[1])[VBI_TRANSPARENT_BLACK] = RGBA(0, 0, 0, 0);
     ((uint32_t *)sub_rect->data[1])[VBI_TRANSPARENT_BLACK + VBI_NB_COLORS] = RGBA(0, 0, 0, 0);
-    sub_rect->type = SUBTITLE_BITMAP;
+
     return 0;
 }
 
@@ -301,7 +321,7 @@  static void handler(vbi_event *ev, void *user_data)
     res = vbi_fetch_vt_page(ctx->vbi, &page,
                             ev->ev.ttx_page.pgno,
                             ev->ev.ttx_page.subno,
-                            VBI_WST_LEVEL_3p5, 25, TRUE);
+                            ctx->wst_level, 25, TRUE);
 
     if (!res)
         return;
@@ -549,9 +569,13 @@  static const AVOption options[] = {
     {"txt_top",         "y offset of generated bitmaps",                     OFFSET(y_offset),       AV_OPT_TYPE_INT,    {.i64 = 0},        0, 65535,    SD},
     {"txt_chop_spaces", "chops leading and trailing spaces from text",       OFFSET(chop_spaces),    AV_OPT_TYPE_INT,    {.i64 = 1},        0, 1,        SD},
     {"txt_duration",    "display duration of teletext pages in msecs",       OFFSET(sub_duration),   AV_OPT_TYPE_INT,    {.i64 = 30000},    0, 86400000, SD},
-    {"txt_transparent", "force transparent background of the teletext",      OFFSET(transparent_bg), AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,        SD},
-    {"txt_opacity",     "set opacity of the transparent background",         OFFSET(opacity),        AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 255,      SD},
-    { NULL },
+    {"txt_transparent", "force transparent background of the teletext (doesn't work with level 1.0)", OFFSET(transparent_bg), AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,        SD},
+    {"txt_opacity",     "set opacity of the transparent background (doesn't work with level 1.0)",    OFFSET(opacity),        AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 255,      SD},
+    {"txt_level",       "set the output level of the teletext bitmap",       OFFSET(wst_level),      AV_OPT_TYPE_INT,    {.i64 = VBI_WST_LEVEL_3p5}, VBI_WST_LEVEL_1, VBI_WST_LEVEL_3p5, SD, "txt_level"},
+    {"1.0",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_1},   0, 0, SD, "txt_level"},
+    {"1.5",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_1p5}, 0, 0, SD, "txt_level"},
+    {"2.5",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_2p5}, 0, 0, SD, "txt_level"},
+    {"3.5",             NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = VBI_WST_LEVEL_3p5}, 0, 0, SD, "txt_level"},
 };
 
 static const AVClass teletext_class = {