gstreamer/ext/closedcaption/gstcea708decoder.h
2019-03-08 01:18:39 +00:00

488 lines
13 KiB
C

/* 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__ */