diff mbox

[FFmpeg-devel,1/2] avcodec/libzvbi-teletextdec: add support for selecting subtitle pages only

Message ID 20180506210514.7390-1-cus@passwd.hu
State Accepted
Headers show

Commit Message

Marton Balint May 6, 2018, 9:05 p.m. UTC
Signed-off-by: Marton Balint <cus@passwd.hu>
---
 doc/decoders.texi                |  5 +++--
 libavcodec/libzvbi-teletextdec.c | 31 ++++++++++++++++++++++---------
 2 files changed, 25 insertions(+), 11 deletions(-)

Comments

Aman Karmani May 7, 2018, 7:28 p.m. UTC | #1
On Sun, May 6, 2018 at 2:05 PM, Marton Balint <cus@passwd.hu> wrote:

> Signed-off-by: Marton Balint <cus@passwd.hu>
> ---
>  doc/decoders.texi                |  5 +++--
>  libavcodec/libzvbi-teletextdec.c | 31 ++++++++++++++++++++++---------
>  2 files changed, 25 insertions(+), 11 deletions(-)
>
> diff --git a/doc/decoders.texi b/doc/decoders.texi
> index a551d5d0fd..8f07bc1afb 100644
> --- a/doc/decoders.texi
> +++ b/doc/decoders.texi
> @@ -248,8 +248,9 @@ configuration. You need to explicitly configure the
> build with
>
>  @table @option
>  @item txt_page
> -List of teletext page numbers to decode. You may use the special * string
> to
> -match all pages. Pages that do not match the specified list are dropped.
> +List of teletext page numbers to decode. Pages that do not match the
> specified
> +list are dropped. You may use the special @code{*} string to match all
> pages,
> +or @code{subtitle} to match all subtitle pages.
>

Thanks for adding this. It works as expected for me.

Might be worth documenting in the AVOption.help text as well.

Aman


>  Default value is *.
>  @item txt_chop_top
>  Discards the top teletext line. Default value is 1.
> diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-
> teletextdec.c
> index a800ad34ae..56a7182882 100644
> --- a/libavcodec/libzvbi-teletextdec.c
> +++ b/libavcodec/libzvbi-teletextdec.c
> @@ -73,6 +73,7 @@ typedef struct TeletextContext
>      vbi_sliced      sliced[MAX_SLICES];
>
>      int             readorder;
> +    uint8_t         subtitle_map[2048];
>  } TeletextContext;
>
>  static int chop_spaces_utf8(const unsigned char* t, int len)
> @@ -281,16 +282,14 @@ static void handler(vbi_event *ev, void *user_data)
>      vbi_page page;
>      int res;
>      char pgno_str[12];
> -    vbi_subno subno;
> -    vbi_page_type vpt;
>      int chop_top;
> -    char *lang;
> +    int is_subtitle_page = ctx->subtitle_map[ev->ev.ttx_page.pgno &
> 0x7ff];
>
>      snprintf(pgno_str, sizeof pgno_str, "%03x", ev->ev.ttx_page.pgno);
>      av_log(ctx, AV_LOG_DEBUG, "decoded page %s.%02x\n",
>             pgno_str, ev->ev.ttx_page.subno & 0xFF);
>
> -    if (strcmp(ctx->pgno, "*") && !strstr(ctx->pgno, pgno_str))
> +    if (strcmp(ctx->pgno, "*") && (strcmp(ctx->pgno, "subtitle") ||
> !is_subtitle_page) && !strstr(ctx->pgno, pgno_str))
>          return;
>      if (ctx->handler_ret < 0)
>          return;
> @@ -303,9 +302,7 @@ static void handler(vbi_event *ev, void *user_data)
>      if (!res)
>          return;
>
> -    vpt = vbi_classify_page(ctx->vbi, ev->ev.ttx_page.pgno, &subno,
> &lang);
> -    chop_top = ctx->chop_top ||
> -        ((page.rows > 1) && (vpt == VBI_SUBTITLE_PAGE));
> +    chop_top = ctx->chop_top || ((page.rows > 1) && is_subtitle_page);
>
>      av_log(ctx, AV_LOG_DEBUG, "%d x %d page chop:%d\n",
>             page.columns, page.rows, chop_top);
> @@ -357,11 +354,26 @@ static int slice_to_vbi_lines(TeletextContext *ctx,
> uint8_t* buf, int size)
>              else {
>                  int line_offset  = buf[2] & 0x1f;
>                  int field_parity = buf[2] & 0x20;
> -                int i;
> +                uint8_t *p = ctx->sliced[lines].data;
> +                int i, pmag;
>                  ctx->sliced[lines].id = VBI_SLICED_TELETEXT_B;
>                  ctx->sliced[lines].line = (line_offset > 0 ? (line_offset
> + (field_parity ? 0 : 313)) : 0);
>                  for (i = 0; i < 42; i++)
> -                    ctx->sliced[lines].data[i] = vbi_rev8(buf[4 + i]);
> +                    p[i] = vbi_rev8(buf[4 + i]);
> +                /* Unfortunately libzvbi does not expose page flags, and
> +                 * vbi_classify_page only checks MIP, so we have to
> manually
> +                 * decode the page flags and store the results. */
> +                pmag = vbi_unham16p(p);
> +                if (pmag >= 0 && pmag >> 3 == 0) {   // We found a row 0
> header
> +                    int page = vbi_unham16p(p + 2);
> +                    int flags1 = vbi_unham16p(p + 6);
> +                    int flags2 = vbi_unham16p(p + 8);
> +                    if (page >= 0 && flags1 >= 0 && flags2 >= 0) {
> +                        int pgno = ((pmag & 7) << 8) + page;
> +                        // Check for disabled NEWSFLASH flag and enabled
> SUBTITLE and SUPRESS_HEADER flags
> +                        ctx->subtitle_map[pgno] = (!(flags1 & 0x40) &&
> flags1 & 0x80 && flags2 & 0x01);
> +                    }
> +                }
>                  lines++;
>              }
>          }
> @@ -502,6 +514,7 @@ static int teletext_close_decoder(AVCodecContext
> *avctx)
>      vbi_decoder_delete(ctx->vbi);
>      ctx->vbi = NULL;
>      ctx->pts = AV_NOPTS_VALUE;
> +    memset(ctx->subtitle_map, 0, sizeof(ctx->subtitle_map));
>      if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
>          ctx->readorder = 0;
>      return 0;
> --
> 2.13.6
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Marton Balint June 10, 2018, 9:59 p.m. UTC | #2
On Mon, 7 May 2018, Aman Gupta wrote:

> On Sun, May 6, 2018 at 2:05 PM, Marton Balint <cus@passwd.hu> wrote:
>
>> Signed-off-by: Marton Balint <cus@passwd.hu>
>> ---
>>  doc/decoders.texi                |  5 +++--
>>  libavcodec/libzvbi-teletextdec.c | 31 ++++++++++++++++++++++---------
>>  2 files changed, 25 insertions(+), 11 deletions(-)
>>
>> diff --git a/doc/decoders.texi b/doc/decoders.texi
>> index a551d5d0fd..8f07bc1afb 100644
>> --- a/doc/decoders.texi
>> +++ b/doc/decoders.texi
>> @@ -248,8 +248,9 @@ configuration. You need to explicitly configure the
>> build with
>>
>>  @table @option
>>  @item txt_page
>> -List of teletext page numbers to decode. You may use the special * string
>> to
>> -match all pages. Pages that do not match the specified list are dropped.
>> +List of teletext page numbers to decode. Pages that do not match the
>> specified
>> +list are dropped. You may use the special @code{*} string to match all
>> pages,
>> +or @code{subtitle} to match all subtitle pages.
>>
>
> Thanks for adding this. It works as expected for me.
>
> Might be worth documenting in the AVOption.help text as well.

Done, and pushed.

Thanks,
Marton
Carl Eugen Hoyos June 13, 2018, 9:47 a.m. UTC | #3
2018-05-06 23:05 GMT+02:00, Marton Balint <cus@passwd.hu>:

> +List of teletext page numbers to decode. Pages that do not match the
> specified
> +list are dropped. You may use the special @code{*} string to match all
> pages,
> +or @code{subtitle} to match all subtitle pages.

Shouldn't this default to "subtitle"? The current default is useless iirc.

Carl Eugen
Jan Ekström June 13, 2018, 5:20 p.m. UTC | #4
On Wed, Jun 13, 2018 at 12:47 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> 2018-05-06 23:05 GMT+02:00, Marton Balint <cus@passwd.hu>:
>
>> +List of teletext page numbers to decode. Pages that do not match the
>> specified
>> +list are dropped. You may use the special @code{*} string to match all
>> pages,
>> +or @code{subtitle} to match all subtitle pages.
>
> Shouldn't this default to "subtitle"? The current default is useless iirc.
>
> Carl Eugen

I think one of the major problems is that IIRC currently the receiving
end has no idea for which page a subtitle was received for (be it
image or text).

Not only would it let the default be * (in case someone wants to
render teletext on the screen in general), but also there are channels
where a single teletext stream has at least two or three different
subtitle pages, and if the API client would be able to distinguish
between them without making multiple decoder instances I'd think
that'd be neat.

Best regards,
Jan
Marton Balint June 13, 2018, 6:18 p.m. UTC | #5
On Wed, 13 Jun 2018, Carl Eugen Hoyos wrote:

> 2018-05-06 23:05 GMT+02:00, Marton Balint <cus@passwd.hu>:
>
>> +List of teletext page numbers to decode. Pages that do not match the
>> specified
>> +list are dropped. You may use the special @code{*} string to match all
>> pages,
>> +or @code{subtitle} to match all subtitle pages.
>
> Shouldn't this default to "subtitle"? The current default is useless iirc.

Fine by me.

Regards,
Marton
Marton Balint June 13, 2018, 7:38 p.m. UTC | #6
On Wed, 13 Jun 2018, Jan Ekström wrote:

> On Wed, Jun 13, 2018 at 12:47 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>> 2018-05-06 23:05 GMT+02:00, Marton Balint <cus@passwd.hu>:
>>
>>> +List of teletext page numbers to decode. Pages that do not match the
>>> specified
>>> +list are dropped. You may use the special @code{*} string to match all
>>> pages,
>>> +or @code{subtitle} to match all subtitle pages.
>>
>> Shouldn't this default to "subtitle"? The current default is useless iirc.
>>
>> Carl Eugen
>
> I think one of the major problems is that IIRC currently the receiving
> end has no idea for which page a subtitle was received for (be it
> image or text).
>
> Not only would it let the default be * (in case someone wants to
> render teletext on the screen in general), but also there are channels
> where a single teletext stream has at least two or three different
> subtitle pages, and if the API client would be able to distinguish
> between them without making multiple decoder instances I'd think
> that'd be neat.

Some side data would be good to specify the originating page number, 
but AVSubtitle has no side data. I guess this will have to wait until the 
AVSubtitle -> AVFrame conversion happens...

Regards,
Marton
diff mbox

Patch

diff --git a/doc/decoders.texi b/doc/decoders.texi
index a551d5d0fd..8f07bc1afb 100644
--- a/doc/decoders.texi
+++ b/doc/decoders.texi
@@ -248,8 +248,9 @@  configuration. You need to explicitly configure the build with
 
 @table @option
 @item txt_page
-List of teletext page numbers to decode. You may use the special * string to
-match all pages. Pages that do not match the specified list are dropped.
+List of teletext page numbers to decode. Pages that do not match the specified
+list are dropped. You may use the special @code{*} string to match all pages,
+or @code{subtitle} to match all subtitle pages.
 Default value is *.
 @item txt_chop_top
 Discards the top teletext line. Default value is 1.
diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c
index a800ad34ae..56a7182882 100644
--- a/libavcodec/libzvbi-teletextdec.c
+++ b/libavcodec/libzvbi-teletextdec.c
@@ -73,6 +73,7 @@  typedef struct TeletextContext
     vbi_sliced      sliced[MAX_SLICES];
 
     int             readorder;
+    uint8_t         subtitle_map[2048];
 } TeletextContext;
 
 static int chop_spaces_utf8(const unsigned char* t, int len)
@@ -281,16 +282,14 @@  static void handler(vbi_event *ev, void *user_data)
     vbi_page page;
     int res;
     char pgno_str[12];
-    vbi_subno subno;
-    vbi_page_type vpt;
     int chop_top;
-    char *lang;
+    int is_subtitle_page = ctx->subtitle_map[ev->ev.ttx_page.pgno & 0x7ff];
 
     snprintf(pgno_str, sizeof pgno_str, "%03x", ev->ev.ttx_page.pgno);
     av_log(ctx, AV_LOG_DEBUG, "decoded page %s.%02x\n",
            pgno_str, ev->ev.ttx_page.subno & 0xFF);
 
-    if (strcmp(ctx->pgno, "*") && !strstr(ctx->pgno, pgno_str))
+    if (strcmp(ctx->pgno, "*") && (strcmp(ctx->pgno, "subtitle") || !is_subtitle_page) && !strstr(ctx->pgno, pgno_str))
         return;
     if (ctx->handler_ret < 0)
         return;
@@ -303,9 +302,7 @@  static void handler(vbi_event *ev, void *user_data)
     if (!res)
         return;
 
-    vpt = vbi_classify_page(ctx->vbi, ev->ev.ttx_page.pgno, &subno, &lang);
-    chop_top = ctx->chop_top ||
-        ((page.rows > 1) && (vpt == VBI_SUBTITLE_PAGE));
+    chop_top = ctx->chop_top || ((page.rows > 1) && is_subtitle_page);
 
     av_log(ctx, AV_LOG_DEBUG, "%d x %d page chop:%d\n",
            page.columns, page.rows, chop_top);
@@ -357,11 +354,26 @@  static int slice_to_vbi_lines(TeletextContext *ctx, uint8_t* buf, int size)
             else {
                 int line_offset  = buf[2] & 0x1f;
                 int field_parity = buf[2] & 0x20;
-                int i;
+                uint8_t *p = ctx->sliced[lines].data;
+                int i, pmag;
                 ctx->sliced[lines].id = VBI_SLICED_TELETEXT_B;
                 ctx->sliced[lines].line = (line_offset > 0 ? (line_offset + (field_parity ? 0 : 313)) : 0);
                 for (i = 0; i < 42; i++)
-                    ctx->sliced[lines].data[i] = vbi_rev8(buf[4 + i]);
+                    p[i] = vbi_rev8(buf[4 + i]);
+                /* Unfortunately libzvbi does not expose page flags, and
+                 * vbi_classify_page only checks MIP, so we have to manually
+                 * decode the page flags and store the results. */
+                pmag = vbi_unham16p(p);
+                if (pmag >= 0 && pmag >> 3 == 0) {   // We found a row 0 header
+                    int page = vbi_unham16p(p + 2);
+                    int flags1 = vbi_unham16p(p + 6);
+                    int flags2 = vbi_unham16p(p + 8);
+                    if (page >= 0 && flags1 >= 0 && flags2 >= 0) {
+                        int pgno = ((pmag & 7) << 8) + page;
+                        // Check for disabled NEWSFLASH flag and enabled SUBTITLE and SUPRESS_HEADER flags
+                        ctx->subtitle_map[pgno] = (!(flags1 & 0x40) && flags1 & 0x80 && flags2 & 0x01);
+                    }
+                }
                 lines++;
             }
         }
@@ -502,6 +514,7 @@  static int teletext_close_decoder(AVCodecContext *avctx)
     vbi_decoder_delete(ctx->vbi);
     ctx->vbi = NULL;
     ctx->pts = AV_NOPTS_VALUE;
+    memset(ctx->subtitle_map, 0, sizeof(ctx->subtitle_map));
     if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
         ctx->readorder = 0;
     return 0;