/* GStreamer * Copyright (C) 2013 CableLabs, Louisville, CO 80027 * Copyright (C) 2015 Samsung Electronics Co., Ltd. * @Author: Chengjun Wang <cjun.wang@samsung.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __GST_CEA708_DEC_H__ #define __GST_CEA708_DEC_H__ #include <gst/gst.h> #include <pango/pangocairo.h> G_BEGIN_DECLS /* from ATSC A/53 Part 4 * DTVCC packets are 128 bytes MAX, length is only 6 bits, header is 2 bytes, * the last byte is flag-fill, that leaves 125 possible bytes of data to be * represented in 6 bits, hence the length encoding */ /* should never be more than 128 */ #define DTVCC_LENGTH 128 #define DTVCC_PKT_SIZE(sz_byte) (((sz_byte) == 0) ? 127 : ((sz_byte) * 2) -1) #define CCTYPE_VALID_MASK 0x04 #define CCTYPE_TYPE_MASK 0x03 #define NUM_608_CCTYPES 2 /* CEA-708-B commands */ /* EndOfText */ #define CC_COMMAND_ETX 0x03 /* SetCurrentWindow0 */ #define CC_COMMAND_CW0 0x80 #define CC_COMMAND_CW1 0x81 #define CC_COMMAND_CW2 0x82 #define CC_COMMAND_CW3 0x83 #define CC_COMMAND_CW4 0x84 #define CC_COMMAND_CW5 0x85 #define CC_COMMAND_CW6 0x86 #define CC_COMMAND_CW7 0x87 /* ClearWindows */ #define CC_COMMAND_CLW 0x88 /* DisplayWindows */ #define CC_COMMAND_DSW 0x89 /* HideWindows */ #define CC_COMMAND_HDW 0x8A /* ToggleWindows */ #define CC_COMMAND_TGW 0x8B /* DeleteWindows */ #define CC_COMMAND_DLW 0x8C /* Delay */ #define CC_COMMAND_DLY 0x8D /* DelayCancel */ #define CC_COMMAND_DLC 0x8E /* Reset */ #define CC_COMMAND_RST 0x8F /* SetPenAttributes */ #define CC_COMMAND_SPA 0x90 /* SetPenColor */ #define CC_COMMAND_SPC 0x91 /* SetPenLocation */ #define CC_COMMAND_SPL 0x92 /* SetWindowAttributes */ #define CC_COMMAND_SWA 0x97 /* DefineWindow0 */ #define CC_COMMAND_DF0 0x98 #define CC_COMMAND_DF1 0x99 #define CC_COMMAND_DF2 0x9A #define CC_COMMAND_DF3 0x9B #define CC_COMMAND_DF4 0x9C #define CC_COMMAND_DF5 0x9D #define CC_COMMAND_DF6 0x9E #define CC_COMMAND_DF7 0x9F /* music note unicode */ #define CC_SPECIAL_CODE_MUSIC_NOTE 0x266a #define CC_UTF8_MAX_LENGTH 6 #define CC_MAX_CODE_SET_SIZE 96 /* Per CEA-708 spec there may be 8 CC windows */ #define MAX_708_WINDOWS 8 /* Each 708 window contains a grid of character positions. These are the * max limits defined, but each window has a row/col count which is typically * smaller than the limits. Note this is just one window, not the entire screen. */ /* max row count */ #define WINDOW_MAX_ROWS 15 /* max column width */ #define WINDOW_MAX_COLS 42 /* The linebuffer contains text for 1 line pango text corresponding to 1 line of 708 text. * The linebuffer could be a lot larger than the window text because of required markup. * example <u> </u> for underline. * The size given is an estimate, to be changed if determined that a larger * buffer is needed */ #define LINEBUFFER_SIZE 1024 /* The screen width/height defined by 708 - not character units, these are * used only to determine the position of the anchor on the screen. */ #define SCREEN_WIDTH_16_9 209 #define SCREEN_HEIGHT_16_9 74 #define SCREEN_WIDTH_4_3 159 #define SCREEN_HEIGHT_4_3 74 /* raw bytes of "define window" command */ #define WIN_DEF_SIZE 6 /* The maximum size of a 708 window in character units. This is used to * calculate the position of windows based on window anchor positions. */ #define SCREEN_HEIGHT_708 15 #define SCREEN_WIDTH_708 32 /* cea708 minimum color list */ #define CEA708_COLOR_INVALID 0xFF #define CEA708_COLOR_BLACK 0x00 #define CEA708_COLOR_WHITE 0x2A #define CEA708_COLOR_RED 0x20 #define CEA708_COLOR_GREEN 0x08 #define CEA708_COLOR_BLUE 0x02 #define CEA708_COLOR_YELLOW 0x28 #define CEA708_COLOR_MAGENTA 0x22 #define CEA708_COLOR_CYAN 0x0A #define CEA708_PANGO_SPAN_MARKUP_START "<span" #define CEA708_PANGO_SPAN_MARKUP_END "</span>" #define CEA708_PANGO_SPAN_ATTRIBUTES_UNDERLINE_SINGLE " underline='single'" #define CEA708_PANGO_SPAN_ATTRIBUTES_STYLE_ITALIC " style='italic'" #define CEA708_PANGO_SPAN_ATTRIBUTES_FONT " font_desc=" #define CEA708_PANGO_SPAN_ATTRIBUTES_FOREGROUND " foreground=" #define CEA708_PANGO_SPAN_ATTRIBUTES_BACKGROUND " background=" #define MINIMUM_OUTLINE_OFFSET 1.0 #define WINDOW_IN_LIST_IS_ACTIVE(list) (list & 0x1) typedef struct _Cea708Dec Cea708Dec; typedef enum { COLOR_TYPE_BLACK = 0, COLOR_TYPE_WHITE, COLOR_TYPE_RED, COLOR_TYPE_GREEN, COLOR_TYPE_BLUE, COLOR_TYPE_YELLOW, COLOR_TYPE_MAGENTA, COLOR_TYPE_CYAN, COLOR_TYPE_RESEVER } Cea708ColorType; typedef enum { NO_CHANGE = 0, SWITCH_TO_HIDE, SWITCH_TO_SHOW, TOGGLE } VisibilityControl; typedef enum { SOLID = 0, FLASH, TRANSLUCENT, TRANSPARENT } Opacity; typedef enum { WIN_STYLE_NORMAL = 1, WIN_STYLE_TRANSPARENT, WIN_STYLE_NORMAL_CENTERED, WIN_STYLE_NORMAL_WORD_WRAP, WIN_STYLE_TRANSPARENT_WORD_WRAP, WIN_STYLE_TRANSPARENT_CENTERED, WIN_STYLE_ROTATED } WindowStyle; typedef enum { PEN_STYLE_DEFAULT = 1, PEN_STYLE_MONO_SERIF, PEN_STYLE_PROP_SERIF, PEN_STYLE_MONO_SANS, PEN_STYLE_PROP_SANS, PEN_STYLE_MONO_SANS_TRANSPARENT, PEN_STYLE_PROP_SANS_TRANSPARENT } PenStyle; typedef enum { ANCHOR_PT_TOP_LEFT = 0, ANCHOR_PT_TOP_CENTER, ANCHOR_PT_TOP_RIGHT, ANCHOR_PT_MIDDLE_LEFT, ANCHOR_PT_CENTER, ANCHOR_PT_MIDDLE_RIGHT, ANCHOR_PT_BOTTOM_LEFT, ANCHOR_PT_BOTTOM_CENTER, ANCHOR_PT_BOTTOM_RIGHT, } AnchorPoint; typedef enum { TAG_DIALOG = 0, TAG_SPEAKER_ID, TAG_ELECTRONIC_VOICE, TAG_ALT_LANGUAGE_DIALOG, TAG_VOICEOVER, TAG_AUDIBLE_TRANSLATION, TAG_SUBTITLE_TRANSLATION, TAG_VOICE_QUALITY_DESCRIPTION, TAG_SONG_LYRICS, TAG_SOUND_EFFECT_DESCRIPTION, TAG_MUSICAL_SCORE_DESCRIPTION, TAG_EXPLETIVE, TAG_UNDEF1, TAG_UNDEF2, TAG_UNDEF3, TAG_NOT_DISPLAYED } TagType; typedef enum { JUSTIFY_LEFT = 0, JUSTIFY_RIGHT, JUSTIFY_CENTER, JUSTIFY_FULL } JUSTIFY_MODE; typedef enum { PRINT_DIR_LEFT_TO_RIGHT = 0, PRINT_DIR_RIGHT_TO_LEFT, PRINT_DIR_TOP_TO_BOTTOM, PRINT_DIR_BOTTOM_TO_TOP } PRINT_DIRECTION; typedef enum { SCROLL_DIR_LEFT_TO_RIGHT = 0, SCROLL_DIR_RIGHT_TO_LEFT, SCROLL_DIR_TOP_TO_BOTTOM, SCROLL_DIR_BOTTOM_TO_TOP } SCROLL_DIRECTION; typedef enum { DISPLAY_EFFECT_SNAP = 0, DISPLAY_EFFECT_FADE, DISPLAY_EFFECT_WIPE } DisplayEffect; typedef enum { EFFECT_DIR_LEFT_TO_RIGHT = 0, EFFECT_DIR_RIGHT_TO_LEFT, EFFECT_DIR_TOP_TO_BOTTOM, EFFECT_DIR_BOTTOM_TO_TOP } EFFECT_DIRECTION; typedef enum { BORDER_TYPE_NONE = 0, BORDER_TYPE_RAISED, BORDER_TYPE_DEPRESSED, BORDER_TYPE_UNIFORM } BORDER_TYPE; typedef enum { PEN_SIZE_SMALL = 0, PEN_SIZE_STANDARD, PEN_SIZE_LARGE, PEN_SIZE_INVALID } PenSize; typedef enum { PEN_OFFSET_SUBSCRIPT = 0, PEN_OFFSET_NORMAL, PEN_OFFSET_SUPERSCRIPT, PEN_OFFSET_INVALID } PenOffset; typedef enum { EDGE_TYPE_NONE = 0, EDGE_TYPE_RAISED, EDGE_TYPE_DEPRESSED, EDGE_TYPE_UNIFORM, EDGE_TYPE_LEFT_DROP_SHADOW, EDGE_TYPE_RIGHT_DROP_SHADOW, EDGE_TYPE_INVALID_1, EDGE_TYPE_INVALID_2 } EdgeType; typedef enum { FONT_STYLE_DEFAULT = 0, FONT_STYLE_MONO_SERIF, FONT_STYLE_PROP_SERIF, FONT_STYLE_MONO_SANS, FONT_STYLE_PROP_SANS, FONT_STYLE_CASUAL, FONT_STYLE_CURSIVE, FONT_STYLE_SMALLCAPS } FontStyle; typedef struct { guint8 fg_color; guint8 fg_opacity; guint8 bg_color; guint8 bg_opacity; guint8 edge_color; } cea708PenColor; typedef struct { gboolean span_start_flag; gboolean span_end_flag; gboolean span_txt_flag; gboolean span_next_flag; gboolean underline; gboolean italics; guint8 size; guint8 fg_color; guint8 bg_color; FontStyle font_style; } cea708PangoSpanControl; typedef struct { PenSize pen_size; FontStyle font_style; TagType text_tag; PenOffset offset; gboolean italics; gboolean underline; EdgeType edge_type; } cea708PenAttributes; /* The char records one cell location in the window, with the character and all of its attributes */ typedef struct { cea708PenColor pen_color; cea708PenAttributes pen_attributes; guint8 justify_mode; gunichar c; } cea708char; /* This struct keeps track of one cea-708 CC window. There are up to 8. As new * windows are created, the text they contain is visible on the screen (if the * window visible flag is set). When a window is deleted, all text within the * window is erased from the screen. Windows may be initialized and made visible * then hidden. Each transition should cause new text cues to be emitted as * text is displayed and removed from the screen. */ typedef struct { /* The current attributes which will be used for the next text string */ cea708PenColor pen_color; cea708PenAttributes pen_attributes; /* true to indicate the window has not been created. * set to true on delete, false on subsequent define command * if true, reset pen position to 0,0 on window creation */ gboolean deleted; /* Text position */ guint16 pen_row; guint16 pen_col; /* window display priority */ guint8 priority; /* window position on screen 0-8 */ guint8 anchor_point; /* 1 = anchor vertical/horizontal coordinates, 0 = physical screen coordinate, aka. rp */ guint8 relative_position; /* vertical position of windows anchor point, 0-74 or if rp=1 then 0-99 */ guint8 anchor_vertical; /* horz position of window anchor point, 0-209(16:9) 0-159(4:3) or if rp=1 then 0-99 */ guint8 anchor_horizontal; /* vert position of upper left corner of window */ gfloat screen_vertical; /* horz position of upper left corner of window */ gfloat screen_horizontal; /* virtual rows of text - 1, (ex. rc=2 means there are 3 rows) */ guint8 row_count; /* virtual columns of text, 0-41(16:9) 0-31(4:3) - 1 */ guint8 column_count; /* 1 = fixes #rows of caption text, 0 = more rows may be added */ guint8 row_lock; /* 1 = fixes #columns of caption text, 0 = more columns may be added */ guint8 column_lock; /* TRUE = window is visible, FALSE = window not visible */ gboolean visible; /* specifies 1 of 7 static preset window. attribute styles, during window create, * 0 = use style #1, during window update, 0 = no window, attributes will be changed */ guint8 style_id; /* specifies 1 of 7 static preset pen attributes, during window create, * 0 = use pen style #1, during window update, 0 = do not change pen attributes */ guint8 pen_style_id; /* timestamp when this window became visible */ guint64 start_time; /* window attributes */ guint8 justify_mode; guint8 print_direction; guint8 scroll_direction; gboolean word_wrap; guint8 display_effect; guint8 effect_direction; guint8 effect_speed; guint8 fill_color; guint8 fill_opacity; guint8 border_type; guint8 border_color; /* Character position offsets for the upper left corner of the window */ guint v_offset; guint h_offset; /* The char array that text is written into, using the current pen position */ cea708char text[WINDOW_MAX_ROWS][WINDOW_MAX_COLS]; PangoLayout *layout; gdouble shadow_offset; gdouble outline_offset; guchar *text_image; gint image_width; gint image_height; gboolean updated; } cea708Window; struct _Cea708Dec { /* output data storage */ GSList *text_list; /* simulation of 708 CC windows */ cea708Window *cc_windows[MAX_708_WINDOWS]; guint8 current_window; gchar *default_font_desc; PangoContext *pango_context; /* a counter used to ignore bytes in CC text stream following commands */ gint8 output_ignore; /* most recent timestamp from userdata */ guint64 current_time; /* desired_service selects the service that will be decoded. If * desired_service = -1 (default) no decoding based on service number will * occur. Service #0 is reserved, and the valid range of service numbers * is 1-7. with 1 being primary caption service and 2 being the secondary * language service. If service_number is 7, then the extended_service_number is added and used instead of the service_number */ gint8 desired_service; gboolean use_ARGB; gint width; gint height; }; Cea708Dec *gst_cea708dec_create (PangoContext * pango_context); void gst_cea708dec_free (Cea708Dec *dec); void gst_cea708dec_set_service_number (Cea708Dec * decoder, gint8 desired_service); gboolean gst_cea708dec_process_dtvcc_packet (Cea708Dec * decoder, guint8 * dtvcc_buffer, gsize dtvcc_size); void gst_cea708dec_set_video_width_height (Cea708Dec * decoder, gint width, gint height); void gst_cea708_decoder_init_debug(void); G_END_DECLS #endif /* __GST_CEA708_DEC_H__ */