Go to the documentation of this file.
   34 #define TEXT_MAXSZ    (25 * (56 + 1) * 4 + 2) 
   35 #define VBI_NB_COLORS 40 
   36 #define VBI_TRANSPARENT_BLACK 8 
   37 #define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) 
   38 #define VBI_R(rgba)   (((rgba) >> 0) & 0xFF) 
   39 #define VBI_G(rgba)   (((rgba) >> 8) & 0xFF) 
   40 #define VBI_B(rgba)   (((rgba) >> 16) & 0xFF) 
   41 #define VBI_A(rgba)   (((rgba) >> 24) & 0xFF) 
   42 #define MAX_BUFFERED_PAGES 25 
   43 #define BITMAP_CHAR_WIDTH  12 
   44 #define BITMAP_CHAR_HEIGHT 10 
  103         "&Hffffff,&Hffffff,&H0,&H0,"  
  113         "&Hffffff,&Hffffff,&H0,&H0,"  
  135         if (*--t != 
' ' || (
len-1 > 0 && *(t-1) & 0x80))
 
  177     sz = vbi_print_page_region(page, vbi_text, 
TEXT_MAXSZ-1, 
"UTF-8",
 
  180                                    page->columns, page->rows-chop_top);
 
  190     if (
ctx->chop_spaces) {
 
  195             in += strspn(in, 
" \n");
 
  197             for (nl = 0; in[nl]; ++nl)
 
  198                 if (in[nl] == 
'\n' && (nl==0 || !(in[nl-1] & 0x80)))
 
  222         if (!sub_rect->
ass) {
 
  236     int r = 
VBI_R(page->color_map[ci]);
 
  237     int g = 
VBI_G(page->color_map[ci]);
 
  238     int b = 
VBI_B(page->color_map[ci]);
 
  242 #define IS_TXT_SPACE(ch) ((ch).unicode < 0x0020 || (ch).unicode >= 0xe000 || (ch).unicode == 0x00a0 ||\ 
  243                           (ch).size > VBI_DOUBLE_SIZE || (ch).opacity == VBI_TRANSPARENT_SPACE) 
  245 static void get_trim_info(vbi_page *page, vbi_char *row, 
int *leading, 
int *trailing, 
int *olen)
 
  252     for (
i = 0; 
i < page->columns; 
i++) {
 
  255         if (
out == 32 && !char_seen)
 
  258             char_seen = 1, 
len = 
i - (*leading) + 1;
 
  262     *trailing = 
len > 0 ? page->columns - *leading - 
len : page->columns;
 
  266                           int start, 
int end, vbi_color *cur_color, vbi_color *cur_back_color)
 
  270     for (
i = start; 
i < end; 
i++) {
 
  273         if (*cur_color != row[
i].foreground) {
 
  275             *cur_color = row[
i].foreground;
 
  277         if (*cur_back_color != row[
i].background) {
 
  279             *cur_back_color = row[
i].background;
 
  284         } 
else if (
out == 
'\\' || 
out == 
'{' || 
out == 
'}') {
 
  298     int leading, trailing, 
len;
 
  299     int last_trailing = -1, last_leading = -1;
 
  300     int min_trailing = page->columns, min_leading = page->columns;
 
  302     int vertical_align = -1;
 
  303     int can_align_left = 1, can_align_right = 1, can_align_center = 1;
 
  304     int is_subtitle_page = 
ctx->subtitle_map[page->pgno & 0x7ff];
 
  306     vbi_color cur_color = VBI_WHITE;
 
  307     vbi_color cur_back_color = VBI_BLACK;
 
  312     for (
i = chop_top; 
i < page->rows; 
i++) {
 
  313         vbi_char *row = page->text + 
i * page->columns;
 
  318             if (last_leading != -1 && last_leading != leading || leading > 5)
 
  320             if (last_trailing != -1 && last_trailing != trailing || trailing > 2)
 
  322             if (last_trailing != -1 && (
FFABS((trailing - leading) - (last_trailing - last_leading)) > 1) || trailing - leading > 4)
 
  323                 can_align_center = 0;
 
  324             last_leading = leading;
 
  325             last_trailing = trailing;
 
  326             min_leading = 
FFMIN(leading, min_leading);
 
  327             min_trailing = 
FFMIN(trailing, min_trailing);
 
  331     if (!can_align_right && can_align_left && !can_align_center) {
 
  332         ctx->last_ass_alignment = alignment = 1;
 
  333     } 
else if (!can_align_right && !can_align_left && can_align_center) {
 
  334         ctx->last_ass_alignment = alignment = 2;
 
  335     } 
else if (can_align_right && !can_align_left && !can_align_center) {
 
  336         ctx->last_ass_alignment = alignment = 3;
 
  338         if (
ctx->last_ass_alignment == 1 && can_align_left ||
 
  339             ctx->last_ass_alignment == 2 && can_align_center ||
 
  340             ctx->last_ass_alignment == 3 && can_align_right)
 
  341             alignment = 
ctx->last_ass_alignment;
 
  344     for (
i = chop_top; 
i < page->rows; 
i++) {
 
  346         vbi_char *row = page->text + 
i * page->columns;
 
  347         int is_transparent_line;
 
  349         for (j = 0; j < page->columns; j++)
 
  350             if (row[j].opacity != VBI_TRANSPARENT_SPACE)
 
  352         is_transparent_line = (j == page->columns);
 
  354         len = is_transparent_line ? 0 : page->columns;
 
  355         leading = trailing = is_transparent_line ? page->columns : 0;
 
  357         if (is_subtitle_page) {
 
  358             if (!is_transparent_line)
 
  361             if (vertical_align == -1 && 
len) {
 
  362                 vertical_align = (2 - (
av_clip(
i + 1, 0, 23) / 8));
 
  363                 av_bprintf(&buf, 
"{\\an%d}", alignment + vertical_align * 3);
 
  364                 if (vertical_align != 2)
 
  368             if (
len && empty_lines > 1)
 
  369                 for (empty_lines /= 2; empty_lines > 0; empty_lines--)
 
  372             if (alignment == 1 || alignment == 2 && !can_align_center)
 
  373                 leading = min_leading;
 
  374             if (alignment == 3 || alignment == 2 && !can_align_center)
 
  375                 trailing = min_trailing;
 
  378         if (
len || !is_subtitle_page) {
 
  379             decode_string(page, row, &buf, leading, page->columns - trailing, &cur_color, &cur_back_color);
 
  387     if (vertical_align == 0)
 
  388         for (empty_lines = (empty_lines - 1) / 2; empty_lines > 0; empty_lines--)
 
  400         if (!sub_rect->
ass) {
 
  413                              int chop_top, 
int resx, 
int resy)
 
  418     for (iy = 0; iy < resy; iy++) {
 
  421         vbi_char *vcnext = vc + page->columns;
 
  422         for (; vc < vcnext; vc++) {
 
  424             switch (vc->opacity) {
 
  425                 case VBI_TRANSPARENT_SPACE:
 
  429                     if (!
ctx->transparent_bg)
 
  431                 case VBI_SEMI_TRANSPARENT:
 
  432                     if (
ctx->opacity > 0) {
 
  433                         if (
ctx->opacity < 255)
 
  435                                 if (*
pixel == vc->background)
 
  439                 case VBI_TRANSPARENT_FULL:
 
  441                         if (*
pixel == vc->background)
 
  456     vbi_char *vc = page->text + (chop_top * page->columns);
 
  457     vbi_char *vcend = page->text + (page->rows * page->columns);
 
  459     for (; vc < vcend; vc++) {
 
  460         if (vc->opacity != VBI_TRANSPARENT_SPACE)
 
  472     if (!sub_rect->
data[0])
 
  475     vbi_draw_vt_page_region(page, VBI_PIXFMT_PAL8,
 
  477                             0, chop_top, page->columns, page->rows - chop_top,
 
  481     sub_rect->
x = 
ctx->x_offset;
 
  487     if (!sub_rect->
data[1]) {
 
  494         r = 
VBI_R(page->color_map[ci]);
 
  495         g = 
VBI_G(page->color_map[ci]);
 
  496         b = 
VBI_B(page->color_map[ci]);
 
  497         a = 
VBI_A(page->color_map[ci]);
 
  500         ff_dlog(
ctx, 
"palette %0x\n", ((uint32_t *)sub_rect->
data[1])[ci]);
 
  516     int is_subtitle_page = 
ctx->subtitle_map[ev->ev.ttx_page.pgno & 0x7ff];
 
  518     snprintf(pgno_str, 
sizeof pgno_str, 
"%03x", ev->ev.ttx_page.pgno);
 
  520            pgno_str, ev->ev.ttx_page.subno & 0xFF);
 
  522     if (strcmp(
ctx->pgno, 
"*") && (strcmp(
ctx->pgno, 
"subtitle") || !is_subtitle_page) && !strstr(
ctx->pgno, pgno_str))
 
  524     if (
ctx->handler_ret < 0)
 
  527     res = vbi_fetch_vt_page(
ctx->vbi, &page,
 
  528                             ev->ev.ttx_page.pgno,
 
  529                             ev->ev.ttx_page.subno,
 
  530                             VBI_WST_LEVEL_3p5, 25, TRUE);
 
  535     chop_top = 
ctx->chop_top || ((page.rows > 1) && is_subtitle_page);
 
  538            page.columns, page.rows, chop_top);
 
  543             ctx->pages = new_pages;
 
  546             cur_page->
pgno = ev->ev.ttx_page.pgno;
 
  547             cur_page->
subno = ev->ev.ttx_page.subno;
 
  549                 switch (
ctx->format_id) {
 
  565                     ctx->handler_ret = res;
 
  567                     ctx->pages[
ctx->nb_pages++] = *cur_page;
 
  581     vbi_unref_page(&page);
 
  588         int data_unit_id     = buf[0];
 
  589         int data_unit_length = buf[1];
 
  590         if (data_unit_length + 2 > 
size)
 
  593             if (data_unit_length != 0x2c)
 
  596                 int line_offset  = buf[2] & 0x1f;
 
  597                 int field_parity = buf[2] & 0x20;
 
  598                 uint8_t *p = 
ctx->sliced[lines].data;
 
  600                 ctx->sliced[lines].id = VBI_SLICED_TELETEXT_B;
 
  601                 ctx->sliced[lines].line = (line_offset > 0 ? (line_offset + (field_parity ? 0 : 313)) : 0);
 
  602                 for (
i = 0; 
i < 42; 
i++)
 
  603                     p[
i] = vbi_rev8(buf[4 + 
i]);
 
  607                 pmag = vbi_unham16p(p);
 
  608                 if (pmag >= 0 && pmag >> 3 == 0) {   
 
  609                     int page = vbi_unham16p(p + 2);
 
  610                     int flags1 = vbi_unham16p(p + 6);
 
  611                     int flags2 = vbi_unham16p(p + 8);
 
  612                     if (page >= 0 && flags1 >= 0 && flags2 >= 0) {
 
  613                         int pgno = ((pmag & 7) << 8) + page;
 
  615                         ctx->subtitle_map[pgno] = (!(flags1 & 0x40) && flags1 & 0x80 && flags2 & 0x01);
 
  617                         if (
ctx->subtitle_map[pgno] && pgno == 
ctx->last_pgno) {
 
  618                             int last_byte9 = vbi_unham8(
ctx->last_p5);
 
  619                             if (last_byte9 >= 0 && last_byte9 & 0x8) {
 
  620                                 int byte9 = vbi_unham8(p[5]);
 
  622                                     p[5] = vbi_ham8(byte9 | 0x8);
 
  625                         ctx->last_pgno = pgno;
 
  632         size -= data_unit_length + 2;
 
  633         buf += data_unit_length + 2;
 
  647         if (!(
ctx->vbi = vbi_decoder_new()))
 
  649         if (
ctx->default_region != -1) {
 
  651             vbi_teletext_set_default_region(
ctx->vbi, 
ctx->default_region);
 
  653         if (!vbi_event_handler_register(
ctx->vbi, VBI_EVENT_TTX_PAGE, 
handler, 
ctx)) {
 
  654             vbi_decoder_delete(
ctx->vbi);
 
  665         const int full_pes_size = 
pkt->
size + 45; 
 
  668         if (full_pes_size < 184 || full_pes_size > 65504 || full_pes_size % 184 != 0)
 
  676             ff_dlog(avctx, 
"ctx=%p buf_size=%d lines=%u pkt_pts=%7.3f\n",
 
  679                 vbi_decode(
ctx->vbi, 
ctx->sliced, lines, 0.0);
 
  680                 ctx->lines_processed += lines;
 
  697         sub->
pts = 
ctx->pages->pts;
 
  703                 sub->
rects[0] = 
ctx->pages->sub_rect;
 
  714         for (
i = 0; 
i < 
ctx->nb_pages - 1; 
i++)
 
  729     unsigned int maj, 
min, rev;
 
  731     vbi_version(&maj, &
min, &rev);
 
  732     if (!(maj > 0 || 
min > 2 || 
min == 2 && rev >= 26)) {
 
  737     if (
ctx->format_id == 0) {
 
  745     ctx->last_ass_alignment = 2;
 
  747     if (
ctx->opacity == -1)
 
  748         ctx->opacity = 
ctx->transparent_bg ? 0 : 255;
 
  752     switch (
ctx->format_id) {
 
  767     ff_dlog(avctx, 
"lines_total=%u\n", 
ctx->lines_processed);
 
  768     while (
ctx->nb_pages)
 
  772     vbi_decoder_delete(
ctx->vbi);
 
  776     ctx->last_ass_alignment = 2;
 
  777     memset(
ctx->subtitle_map, 0, 
sizeof(
ctx->subtitle_map));
 
  788 #define OFFSET(x) offsetof(TeletextContext, x) 
  789 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM 
  791     {
"txt_page",        
"page numbers to decode, subtitle for subtitles, * for all", 
OFFSET(pgno),   
AV_OPT_TYPE_STRING, {.str = 
"*"},      0, 0,        
SD},
 
  792     {
"txt_default_region", 
"default G0 character set used for decoding",     
OFFSET(default_region), 
AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 87,       
SD},
 
  794     {
"txt_format",      
"format of the subtitles (bitmap or text or ass)",   
OFFSET(format_id),      
AV_OPT_TYPE_INT,    {.i64 = 0},        0, 2,        
SD,  .unit = 
"txt_format"},
 
  800     {
"txt_chop_spaces", 
"chops leading and trailing spaces from text",       
OFFSET(chop_spaces),    
AV_OPT_TYPE_INT,    {.i64 = 1},        0, 1,        
SD},
 
  801     {
"txt_duration",    
"display duration of teletext pages in msecs",       
OFFSET(sub_duration),   
AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 86400000, 
SD},
 
  802     {
"txt_transparent", 
"force transparent background of the teletext",      
OFFSET(transparent_bg), 
AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,        
SD},
 
  803     {
"txt_opacity",     
"set opacity of the transparent background",         
OFFSET(opacity),        
AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 255,      
SD},
 
  815     .
p.
name         = 
"libzvbi_teletextdec",
 
  821     .p.wrapper_name = 
"libzvbi",
 
  
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_BPRINT_SIZE_UNLIMITED
#define PUT_UTF8(val, tmp, PUT_BYTE)
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
int ff_ass_subtitle_header_default(AVCodecContext *avctx)
Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS with default style.
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
char * av_asprintf(const char *fmt,...)
@ AV_CODEC_ID_DVB_TELETEXT
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
static int gen_sub_text(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page *page, int chop_top)
uint8_t * subtitle_header
static int gen_sub_ass(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page *page, int chop_top)
static char * create_ass_text(TeletextContext *ctx, const char *text)
#define AV_LOG_VERBOSE
Detailed information.
static av_always_inline int ff_data_identifier_is_teletext(int data_identifier)
const FFCodec ff_libzvbi_teletext_decoder
@ SUBTITLE_ASS
Formatted text, the ass field must be set by the decoder and is authoritative.
static av_cold void close(AVCodecParserContext *s)
AVCodec p
The public AVCodec.
int x
top left corner of pict, undefined when pict is not set
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
static void decode_string(vbi_page *page, vbi_char *row, AVBPrint *buf, int start, int end, vbi_color *cur_color, vbi_color *cur_back_color)
char * ass
0 terminated ASS/SSA compatible event line.
char * ff_ass_get_dialog(int readorder, int layer, const char *style, const char *speaker, const char *text)
Craft an ASS dialog string.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
int y
top left corner of pict, undefined when pict is not set
static void get_trim_info(vbi_page *page, vbi_char *row, int *leading, int *trailing, int *olen)
#define MAX_BUFFERED_PAGES
void ff_ass_bprint_text_event(AVBPrint *buf, const char *p, int size, const char *linebreaks, int keep_ass_markup)
Escape a text subtitle using ASS syntax into an AVBPrint buffer.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
int64_t pts
Same as packet pts, in AV_TIME_BASE.
static void handler(vbi_event *ev, void *user_data)
#define CODEC_LONG_NAME(str)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
int w
width of pict, undefined when pict is not set
#define LIBAVUTIL_VERSION_INT
Describe the class of an AVClass context structure.
static int teletext_close_decoder(AVCodecContext *avctx)
static int slice_to_vbi_lines(TeletextContext *ctx, const uint8_t *buf, int size)
uint8_t subtitle_map[2048]
static void bprint_color(const char *type, AVBPrint *buf, vbi_page *page, unsigned ci)
#define BITMAP_CHAR_HEIGHT
const char * av_default_item_name(void *ptr)
Return the context name.
int subtitle_header_size
Header containing style information for text subtitles.
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
#define BITMAP_CHAR_WIDTH
static int teletext_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, const AVPacket *pkt)
int flags2
AV_CODEC_FLAG2_*.
int(* init)(AVBSFContext *ctx)
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
#define AV_NOPTS_VALUE
Undefined timestamp value.
static int FUNC() user_data(CodedBitstreamContext *ctx, RWContext *rw, MPEG2RawUserData *current)
uint32_t end_display_time
static av_always_inline int ff_data_unit_id_is_teletext(int data_unit_id)
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
#define AVERROR_EXTERNAL
Generic error in an external library.
static int teletext_init_decoder(AVCodecContext *avctx)
@ SUBTITLE_BITMAP
A bitmap, pict will be set.
#define AV_LOG_INFO
Standard information.
#define i(width, name, range_min, range_max)
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
int nb_colors
number of colors in pict, undefined when pict is not set
#define VBI_TRANSPARENT_BLACK
static const AVOption options[]
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
const char * name
Name of the codec implementation.
static void teletext_flush(AVCodecContext *avctx)
int h
height of pict, undefined when pict is not set
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static void subtitle_rect_free(AVSubtitleRect **sub_rect)
vbi_sliced sliced[MAX_SLICES]
void av_bprintf(AVBPrint *buf, const char *fmt,...)
main external API structure.
static const AVClass teletext_class
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
#define FF_CODEC_DECODE_SUB_CB(func)
AVSubtitleRect * sub_rect
This structure stores compressed data.
static int gen_sub_bitmap(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page *page, int chop_top)
int width
picture width / height.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
#define AV_CODEC_FLAG2_RO_FLUSH_NOOP
Do not reset ASS ReadOrder field on flush (subtitles decoding)
static void fix_transparency(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page *page, int chop_top, int resx, int resy)
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
static int chop_spaces_utf8(const unsigned char *t, int len)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
uint32_t start_display_time
static int my_ass_subtitle_header(AVCodecContext *avctx)