avcodec/libzvbi-teletextdec: add support for selecting subtitle pages only
authorMarton Balint <cus@passwd.hu>
Sat, 28 Apr 2018 19:42:34 +0000 (21:42 +0200)
committerMarton Balint <cus@passwd.hu>
Sun, 10 Jun 2018 21:48:23 +0000 (23:48 +0200)
Signed-off-by: Marton Balint <cus@passwd.hu>
doc/decoders.texi
libavcodec/libzvbi-teletextdec.c
libavcodec/version.h

index a551d5d..8f07bc1 100644 (file)
@@ -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.
index a800ad3..ccded23 100644 (file)
@@ -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;
@@ -515,7 +528,7 @@ static void teletext_flush(AVCodecContext *avctx)
 #define OFFSET(x) offsetof(TeletextContext, x)
 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
 static const AVOption options[] = {
-    {"txt_page",        "list of teletext page numbers to decode, * is all", OFFSET(pgno),           AV_OPT_TYPE_STRING, {.str = "*"},      0, 0,        SD},
+    {"txt_page",        "page numbers to decode, subtitle for subtitles, * for all", OFFSET(pgno),   AV_OPT_TYPE_STRING, {.str = "*"},      0, 0,        SD},
     {"txt_chop_top",    "discards the top teletext line",                    OFFSET(chop_top),       AV_OPT_TYPE_INT,    {.i64 = 1},        0, 1,        SD},
     {"txt_format",      "format of the subtitles (bitmap or text)",          OFFSET(format_id),      AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,        SD,  "txt_format"},
     {"bitmap",          NULL,                                                0,                      AV_OPT_TYPE_CONST,  {.i64 = 0},        0, 0,        SD,  "txt_format"},
index b9752ce..5e71b48 100644 (file)
@@ -29,7 +29,7 @@
 
 #define LIBAVCODEC_VERSION_MAJOR  58
 #define LIBAVCODEC_VERSION_MINOR  20
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \