mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-06 18:52:07 +00:00
dwrite: Import libcaption source code
Import the code from gst-plugins-rs (origin is https://github.com/szatmary/libcaption) Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4929>
This commit is contained in:
parent
37c7c92c03
commit
713f74f4f9
14 changed files with 3028 additions and 0 deletions
|
@ -1,4 +1,5 @@
|
|||
subprojects/gst-plugins-bad/ext/sctp/usrsctp/usrsctplib/
|
||||
subprojects/gst-plugins-bad/sys/dwrite/libcaption/
|
||||
subprojects/gstreamer-rs/
|
||||
subprojects/gstreamer-rs-sys/
|
||||
subprojects/gst-plugins-rs/
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License
|
||||
|
||||
Copyright 2016-2017 Twitch Interactive, Inc. or its affiliates. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
529
subprojects/gst-plugins-bad/sys/dwrite/libcaption/caption.c
Normal file
529
subprojects/gst-plugins-bad/sys/dwrite/libcaption/caption.c
Normal file
|
@ -0,0 +1,529 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2017 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include "caption.h"
|
||||
#include "eia608.h"
|
||||
#include "utf8.h"
|
||||
#include "xds.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
caption_frame_buffer_clear (caption_frame_buffer_t * buff)
|
||||
{
|
||||
memset (buff, 0, sizeof (caption_frame_buffer_t));
|
||||
}
|
||||
|
||||
void
|
||||
caption_frame_state_clear (caption_frame_t * frame)
|
||||
{
|
||||
frame->write = 0;
|
||||
frame->timestamp = -1;
|
||||
frame->state = (caption_frame_state_t) {
|
||||
0, 0, 0, SCREEN_ROWS - 1, 0, 0}; // clear global state
|
||||
}
|
||||
|
||||
void
|
||||
caption_frame_init (caption_frame_t * frame)
|
||||
{
|
||||
xds_init (&frame->xds);
|
||||
caption_frame_state_clear (frame);
|
||||
caption_frame_buffer_clear (&frame->back);
|
||||
caption_frame_buffer_clear (&frame->front);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
static caption_frame_cell_t *
|
||||
frame_buffer_cell (caption_frame_buffer_t * buff, int row, int col)
|
||||
{
|
||||
if (!buff || 0 > row || SCREEN_ROWS <= row || 0 > col || SCREEN_COLS <= col) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return &buff->cell[row][col];
|
||||
}
|
||||
|
||||
int caption_frame_clear_char (caption_frame_t * frame, int row, int col)
|
||||
{
|
||||
if (!frame->write) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
caption_frame_cell_t *cell = frame_buffer_cell (frame->write, row, col);
|
||||
|
||||
if (cell) {
|
||||
memset (cell, 0, sizeof (caption_frame_cell_t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t _eia608_from_utf8 (const char *s); // function is in eia608.c.re2c
|
||||
int
|
||||
caption_frame_write_char (caption_frame_t * frame, int row, int col,
|
||||
eia608_style_t style, int underline, const char *c)
|
||||
{
|
||||
if (!frame->write || !_eia608_from_utf8 (c)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
caption_frame_cell_t *cell = frame_buffer_cell (frame->write, row, col);
|
||||
|
||||
if (cell && utf8_char_copy (&cell->data[0], c)) {
|
||||
cell->uln = underline;
|
||||
cell->sty = style;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const utf8_char_t *
|
||||
caption_frame_read_char (caption_frame_t * frame, int row, int col,
|
||||
eia608_style_t * style, int *underline)
|
||||
{
|
||||
// always read from front
|
||||
caption_frame_cell_t *cell = frame_buffer_cell (&frame->front, row, col);
|
||||
|
||||
if (!cell) {
|
||||
if (style) {
|
||||
(*style) = eia608_style_white;
|
||||
}
|
||||
|
||||
if (underline) {
|
||||
(*underline) = 0;
|
||||
}
|
||||
|
||||
return EIA608_CHAR_NULL;
|
||||
}
|
||||
|
||||
if (style) {
|
||||
(*style) = cell->sty;
|
||||
}
|
||||
|
||||
if (underline) {
|
||||
(*underline) = cell->uln;
|
||||
}
|
||||
|
||||
return &cell->data[0];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Parsing
|
||||
libcaption_stauts_t
|
||||
caption_frame_carriage_return (caption_frame_t * frame)
|
||||
{
|
||||
if (0 > frame->state.row || SCREEN_ROWS <= frame->state.row) {
|
||||
return LIBCAPTION_ERROR;
|
||||
}
|
||||
|
||||
int r = frame->state.row - (frame->state.rup - 1);
|
||||
|
||||
if (0 >= r || !caption_frame_rollup (frame)) {
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
|
||||
for (; r < SCREEN_ROWS; ++r) {
|
||||
uint8_t *dst = (uint8_t *) frame_buffer_cell (frame->write, r - 1, 0);
|
||||
uint8_t *src = (uint8_t *) frame_buffer_cell (frame->write, r - 0, 0);
|
||||
memcpy (dst, src, sizeof (caption_frame_cell_t) * SCREEN_COLS);
|
||||
}
|
||||
|
||||
frame->state.col = 0;
|
||||
caption_frame_cell_t *cell =
|
||||
frame_buffer_cell (frame->write, SCREEN_ROWS - 1, 0);
|
||||
memset (cell, 0, sizeof (caption_frame_cell_t) * SCREEN_COLS);
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
libcaption_stauts_t
|
||||
eia608_write_char (caption_frame_t * frame, char *c)
|
||||
{
|
||||
if (0 == c || 0 == c[0] || SCREEN_ROWS <= frame->state.row
|
||||
|| 0 > frame->state.row || SCREEN_COLS <= frame->state.col
|
||||
|| 0 > frame->state.col) {
|
||||
// NO-OP
|
||||
} else if (caption_frame_write_char (frame, frame->state.row,
|
||||
frame->state.col, frame->state.sty, frame->state.uln, c)) {
|
||||
frame->state.col += 1;
|
||||
}
|
||||
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_end (caption_frame_t * frame)
|
||||
{
|
||||
memcpy (&frame->front, &frame->back, sizeof (caption_frame_buffer_t));
|
||||
caption_frame_buffer_clear (&frame->back); // This is required
|
||||
return LIBCAPTION_READY;
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_decode_preamble (caption_frame_t * frame, uint16_t cc_data)
|
||||
{
|
||||
eia608_style_t sty;
|
||||
int row, col, chn, uln;
|
||||
|
||||
if (eia608_parse_preamble (cc_data, &row, &col, &sty, &chn, &uln)) {
|
||||
frame->state.row = row;
|
||||
frame->state.col = col;
|
||||
frame->state.sty = sty;
|
||||
frame->state.uln = uln;
|
||||
}
|
||||
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_decode_midrowchange (caption_frame_t * frame, uint16_t cc_data)
|
||||
{
|
||||
eia608_style_t sty;
|
||||
int chn, unl;
|
||||
|
||||
if (eia608_parse_midrowchange (cc_data, &chn, &sty, &unl)) {
|
||||
frame->state.sty = sty;
|
||||
frame->state.uln = unl;
|
||||
}
|
||||
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_backspace (caption_frame_t * frame)
|
||||
{
|
||||
// do not reverse wrap (tw 28:20)
|
||||
frame->state.col = (0 < frame->state.col) ? (frame->state.col - 1) : 0;
|
||||
caption_frame_clear_char (frame, frame->state.row, frame->state.col);
|
||||
return LIBCAPTION_READY;
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_delete_to_end_of_row (caption_frame_t * frame)
|
||||
{
|
||||
int c;
|
||||
if (frame->write) {
|
||||
for (c = frame->state.col; c < SCREEN_COLS; ++c) {
|
||||
caption_frame_clear_char (frame, frame->state.row, c);
|
||||
}
|
||||
}
|
||||
// TODO test this and replace loop
|
||||
// uint8_t* dst = (uint8_t*)frame_buffer_cell(frame->write, frame->state.row, frame->state.col);
|
||||
// memset(dst,0,sizeof(caption_frame_cell_t) * (SCREEN_COLS - frame->state.col - 1))
|
||||
|
||||
return LIBCAPTION_READY;
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_decode_control (caption_frame_t * frame, uint16_t cc_data)
|
||||
{
|
||||
int cc;
|
||||
eia608_control_t cmd = eia608_parse_control (cc_data, &cc);
|
||||
|
||||
switch (cmd) {
|
||||
// PAINT ON
|
||||
case eia608_control_resume_direct_captioning:
|
||||
frame->state.rup = 0;
|
||||
frame->write = &frame->front;
|
||||
return LIBCAPTION_OK;
|
||||
|
||||
case eia608_control_erase_display_memory:
|
||||
caption_frame_buffer_clear (&frame->front);
|
||||
return LIBCAPTION_CLEAR;
|
||||
|
||||
// ROLL-UP
|
||||
case eia608_control_roll_up_2:
|
||||
frame->state.rup = 1;
|
||||
frame->write = &frame->front;
|
||||
return LIBCAPTION_OK;
|
||||
|
||||
case eia608_control_roll_up_3:
|
||||
frame->state.rup = 2;
|
||||
frame->write = &frame->front;
|
||||
return LIBCAPTION_OK;
|
||||
|
||||
case eia608_control_roll_up_4:
|
||||
frame->state.rup = 3;
|
||||
frame->write = &frame->front;
|
||||
return LIBCAPTION_OK;
|
||||
|
||||
case eia608_control_carriage_return:
|
||||
return caption_frame_carriage_return (frame);
|
||||
|
||||
// Corrections (Is this only valid as part of paint on?)
|
||||
case eia608_control_backspace:
|
||||
return caption_frame_backspace (frame);
|
||||
case eia608_control_delete_to_end_of_row:
|
||||
return caption_frame_delete_to_end_of_row (frame);
|
||||
|
||||
// POP ON
|
||||
case eia608_control_resume_caption_loading:
|
||||
frame->state.rup = 0;
|
||||
frame->write = &frame->back;
|
||||
return LIBCAPTION_OK;
|
||||
|
||||
case eia608_control_erase_non_displayed_memory:
|
||||
caption_frame_buffer_clear (&frame->back);
|
||||
return LIBCAPTION_OK;
|
||||
|
||||
case eia608_control_end_of_caption:
|
||||
return caption_frame_end (frame);
|
||||
|
||||
// cursor positioning
|
||||
case eia608_tab_offset_0:
|
||||
case eia608_tab_offset_1:
|
||||
case eia608_tab_offset_2:
|
||||
case eia608_tab_offset_3:
|
||||
frame->state.col += (cmd - eia608_tab_offset_0);
|
||||
return LIBCAPTION_OK;
|
||||
|
||||
// Unhandled
|
||||
default:
|
||||
case eia608_control_alarm_off:
|
||||
case eia608_control_alarm_on:
|
||||
case eia608_control_text_restart:
|
||||
case eia608_control_text_resume_text_display:
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_decode_text (caption_frame_t * frame, uint16_t cc_data)
|
||||
{
|
||||
int chan;
|
||||
char char1[5], char2[5];
|
||||
size_t chars = eia608_to_utf8 (cc_data, &chan, &char1[0], &char2[0]);
|
||||
|
||||
if (eia608_is_westeu (cc_data)) {
|
||||
// Extended charcters replace the previous charcter for back compatibility
|
||||
caption_frame_backspace (frame);
|
||||
}
|
||||
|
||||
if (0 < chars) {
|
||||
eia608_write_char (frame, char1);
|
||||
}
|
||||
|
||||
if (1 < chars) {
|
||||
eia608_write_char (frame, char2);
|
||||
}
|
||||
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
|
||||
libcaption_stauts_t
|
||||
caption_frame_decode (caption_frame_t * frame, uint16_t cc_data,
|
||||
double timestamp)
|
||||
{
|
||||
if (!eia608_parity_varify (cc_data)) {
|
||||
frame->status = LIBCAPTION_ERROR;
|
||||
return frame->status;
|
||||
}
|
||||
|
||||
if (eia608_is_padding (cc_data)) {
|
||||
frame->status = LIBCAPTION_OK;
|
||||
return frame->status;
|
||||
}
|
||||
|
||||
// skip duplicate controll commands. We also skip duplicate specialna to match the behaviour of iOS/vlc
|
||||
if ((eia608_is_specialna(cc_data) || eia608_is_control(cc_data)) && cc_data == frame->state.cc_data) {
|
||||
if (timestamp < 0 && caption_frame_popon (frame))
|
||||
frame->timestamp += (1 / 29.97);
|
||||
return LIBCAPTION_OK;
|
||||
}
|
||||
|
||||
if (timestamp >= 0) {
|
||||
frame->timestamp = timestamp;
|
||||
frame->status = LIBCAPTION_OK;
|
||||
} else if (caption_frame_popon (frame)) {
|
||||
frame->timestamp += (1 / 29.97);
|
||||
}
|
||||
|
||||
frame->state.cc_data = cc_data;
|
||||
|
||||
if (frame->xds.state) {
|
||||
frame->status = xds_decode (&frame->xds, cc_data);
|
||||
} else if (eia608_is_xds (cc_data)) {
|
||||
frame->status = xds_decode (&frame->xds, cc_data);
|
||||
} else if (eia608_is_control (cc_data)) {
|
||||
frame->status = caption_frame_decode_control (frame, cc_data);
|
||||
} else if (eia608_is_basicna (cc_data) || eia608_is_specialna (cc_data)
|
||||
|| eia608_is_westeu (cc_data)) {
|
||||
|
||||
// Don't decode text if we dont know what mode we are in.
|
||||
if (!frame->write) {
|
||||
frame->status = LIBCAPTION_OK;
|
||||
return frame->status;
|
||||
}
|
||||
|
||||
frame->status = caption_frame_decode_text (frame, cc_data);
|
||||
|
||||
// If we are in paint on mode, display immiditally
|
||||
if (LIBCAPTION_OK == frame->status && caption_frame_painton (frame)) {
|
||||
frame->status = LIBCAPTION_READY;
|
||||
}
|
||||
} else if (eia608_is_preamble (cc_data)) {
|
||||
frame->status = caption_frame_decode_preamble (frame, cc_data);
|
||||
} else if (eia608_is_midrowchange (cc_data)) {
|
||||
frame->status = caption_frame_decode_midrowchange (frame, cc_data);
|
||||
}
|
||||
|
||||
return frame->status;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int
|
||||
caption_frame_from_text (caption_frame_t * frame, const utf8_char_t * data)
|
||||
{
|
||||
ssize_t size = (ssize_t) strlen (data);
|
||||
caption_frame_init (frame);
|
||||
frame->write = &frame->back;
|
||||
|
||||
for (size_t r = 0; (*data) && size && r < SCREEN_ROWS;) {
|
||||
// skip whitespace at start of line
|
||||
while (size && utf8_char_whitespace (data)) {
|
||||
size_t s = utf8_char_length (data);
|
||||
data += s, size -= s;
|
||||
}
|
||||
|
||||
// get charcter count for wrap (or orest of line)
|
||||
utf8_size_t char_count = utf8_wrap_length (data, SCREEN_COLS);
|
||||
// write to caption frame
|
||||
for (size_t c = 0; c < char_count; ++c) {
|
||||
size_t char_length = utf8_char_length (data);
|
||||
caption_frame_write_char (frame, r, c, eia608_style_white, 0, data);
|
||||
data += char_length, size -= char_length;
|
||||
}
|
||||
|
||||
r += char_count ? 1 : 0; // Update row num only if not blank
|
||||
}
|
||||
|
||||
caption_frame_end (frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t
|
||||
caption_frame_to_text (caption_frame_t * frame, utf8_char_t * data, int full)
|
||||
{
|
||||
int r, c, uln, crlf = 0, count = 0;
|
||||
size_t s, size = 0;
|
||||
eia608_style_t sty;
|
||||
(*data) = '\0';
|
||||
|
||||
for (r = 0; r < SCREEN_ROWS; ++r) {
|
||||
crlf += count, count = 0;
|
||||
for (c = 0; c < SCREEN_COLS; ++c) {
|
||||
const utf8_char_t *chr =
|
||||
caption_frame_read_char (frame, r, c, &sty, &uln);
|
||||
// dont start a new line until we encounter at least one printable character
|
||||
if (full ||
|
||||
(0 < utf8_char_length (chr) && (0 < count
|
||||
|| !utf8_char_whitespace (chr)))) {
|
||||
if (0 < crlf) {
|
||||
memcpy (data, "\r\n\0", 3);
|
||||
data += 2, size += 2, crlf = 0;
|
||||
}
|
||||
|
||||
s = utf8_char_copy (data, chr);
|
||||
data += s, size += s, ++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
size_t
|
||||
caption_frame_dump_buffer (caption_frame_t * frame, utf8_char_t * buf)
|
||||
{
|
||||
int r, c;
|
||||
size_t bytes, total = 0;
|
||||
bytes =
|
||||
sprintf (buf,
|
||||
" timestamp: %f\n row: %02d col: %02d roll-up: %d\n",
|
||||
frame->timestamp, frame->state.row, frame->state.col,
|
||||
caption_frame_rollup (frame));
|
||||
total += bytes, buf += bytes;
|
||||
bytes =
|
||||
sprintf (buf,
|
||||
" 00000000001111111111222222222233\t 00000000001111111111222222222233\n"
|
||||
" 01234567890123456789012345678901\t 01234567890123456789012345678901\n"
|
||||
" %s--------------------------------%s\t %s--------------------------------%s\n",
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT);
|
||||
total += bytes;
|
||||
buf += bytes;
|
||||
|
||||
for (r = 0; r < SCREEN_ROWS; ++r) {
|
||||
bytes = sprintf (buf, "%02d%s", r, EIA608_CHAR_VERTICAL_LINE);
|
||||
total += bytes, buf += bytes;
|
||||
|
||||
// front buffer
|
||||
for (c = 0; c < SCREEN_COLS; ++c) {
|
||||
caption_frame_cell_t *cell = frame_buffer_cell (&frame->front, r, c);
|
||||
bytes = utf8_char_copy (buf, (!cell
|
||||
|| 0 == cell->data[0]) ? EIA608_CHAR_SPACE : &cell->data[0]);
|
||||
total += bytes, buf += bytes;
|
||||
}
|
||||
|
||||
bytes =
|
||||
sprintf (buf, "%s\t%02d%s", EIA608_CHAR_VERTICAL_LINE, r,
|
||||
EIA608_CHAR_VERTICAL_LINE);
|
||||
total += bytes, buf += bytes;
|
||||
|
||||
// back buffer
|
||||
for (c = 0; c < SCREEN_COLS; ++c) {
|
||||
caption_frame_cell_t *cell = frame_buffer_cell (&frame->back, r, c);
|
||||
bytes = utf8_char_copy (buf, (!cell
|
||||
|| 0 == cell->data[0]) ? EIA608_CHAR_SPACE : &cell->data[0]);
|
||||
total += bytes, buf += bytes;
|
||||
}
|
||||
|
||||
bytes = sprintf (buf, "%s\n", EIA608_CHAR_VERTICAL_LINE);
|
||||
total += bytes, buf += bytes;
|
||||
}
|
||||
|
||||
bytes =
|
||||
sprintf (buf,
|
||||
" %s--------------------------------%s\t %s--------------------------------%s\n",
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT);
|
||||
total += bytes, buf += bytes;
|
||||
return total;
|
||||
}
|
||||
|
||||
void
|
||||
caption_frame_dump (caption_frame_t * frame)
|
||||
{
|
||||
utf8_char_t buff[CAPTION_FRAME_DUMP_BUF_SIZE];
|
||||
caption_frame_dump_buffer (frame, buff);
|
||||
fprintf (stderr, "%s\n", buff);
|
||||
}
|
136
subprojects/gst-plugins-bad/sys/dwrite/libcaption/caption.h
Normal file
136
subprojects/gst-plugins-bad/sys/dwrite/libcaption/caption.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2017 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#ifndef LIBCAPTION_H
|
||||
#define LIBCAPTION_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "eia608.h"
|
||||
#include "utf8.h"
|
||||
#include "xds.h"
|
||||
|
||||
typedef enum {
|
||||
LIBCAPTION_ERROR = 0,
|
||||
LIBCAPTION_OK = 1,
|
||||
LIBCAPTION_READY = 2,
|
||||
LIBCAPTION_CLEAR = 3,
|
||||
} libcaption_stauts_t;
|
||||
|
||||
static inline libcaption_stauts_t libcaption_status_update(libcaption_stauts_t old_stat, libcaption_stauts_t new_stat)
|
||||
{
|
||||
return (LIBCAPTION_ERROR == old_stat || LIBCAPTION_ERROR == new_stat) ? LIBCAPTION_ERROR : (LIBCAPTION_READY == old_stat) ? LIBCAPTION_READY : new_stat;
|
||||
}
|
||||
|
||||
#define SCREEN_ROWS 15
|
||||
#define SCREEN_COLS 32
|
||||
|
||||
typedef struct {
|
||||
uint8_t uln; //< underline
|
||||
uint8_t sty; //< style
|
||||
utf8_char_t data[5]; //< 4 byte utf8 values plus null term
|
||||
} caption_frame_cell_t;
|
||||
|
||||
typedef struct {
|
||||
caption_frame_cell_t cell[SCREEN_ROWS][SCREEN_COLS];
|
||||
} caption_frame_buffer_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t uln; //< underline
|
||||
uint8_t sty; //< style
|
||||
uint8_t rup; //< roll-up line count minus 1
|
||||
int8_t row, col;
|
||||
uint16_t cc_data;
|
||||
} caption_frame_state_t;
|
||||
|
||||
// timestamp and duration are in seconds
|
||||
typedef struct {
|
||||
double timestamp;
|
||||
xds_t xds;
|
||||
caption_frame_state_t state;
|
||||
caption_frame_buffer_t front;
|
||||
caption_frame_buffer_t back;
|
||||
caption_frame_buffer_t* write;
|
||||
libcaption_stauts_t status;
|
||||
} caption_frame_t;
|
||||
|
||||
/*!
|
||||
\brief Initializes an allocated caption_frame_t instance
|
||||
\param frame Pointer to prealocated caption_frame_t object
|
||||
*/
|
||||
void caption_frame_init(caption_frame_t* frame);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int caption_frame_popon(caption_frame_t* frame) { return (frame->write == &frame->back) ? 1 : 0; }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int caption_frame_painton(caption_frame_t* frame) { return (frame->write == &frame->front) ? 1 : 0; }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
const static int _caption_frame_rollup[] = { 0, 2, 3, 4 };
|
||||
static inline int caption_frame_rollup(caption_frame_t* frame) { return _caption_frame_rollup[frame->state.rup]; }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline double caption_frame_timestamp(caption_frame_t* frame) { return frame->timestamp; }
|
||||
/*! \brief Writes a single charcter to a caption_frame_t object
|
||||
\param frame A pointer to an allocted and initialized caption_frame_t object
|
||||
\param row Row position to write charcter, must be between 0 and SCREEN_ROWS-1
|
||||
\param col Column position to write charcter, must be between 0 and SCREEN_ROWS-1
|
||||
\param style Style to apply to charcter
|
||||
\param underline Set underline attribute, 0 = off any other value = on
|
||||
\param c pointer to a single valid utf8 charcter. Bytes are automatically determined, and a NULL terminator is not required
|
||||
*/
|
||||
int caption_frame_write_char(caption_frame_t* frame, int row, int col, eia608_style_t style, int underline, const utf8_char_t* c);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
const utf8_char_t* caption_frame_read_char(caption_frame_t* frame, int row, int col, eia608_style_t* style, int* underline);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
libcaption_stauts_t caption_frame_decode(caption_frame_t* frame, uint16_t cc_data, double timestamp);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
int caption_frame_from_text(caption_frame_t* frame, const utf8_char_t* data);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
#define CAPTION_FRAME_TEXT_BYTES (4 * ((SCREEN_COLS + 2) * SCREEN_ROWS) + 1)
|
||||
size_t caption_frame_to_text(caption_frame_t* frame, utf8_char_t* data, int full);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
#define CAPTION_FRAME_DUMP_BUF_SIZE 8192
|
||||
size_t caption_frame_dump_buffer(caption_frame_t* frame, utf8_char_t* buf);
|
||||
void caption_frame_dump(caption_frame_t* frame);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
375
subprojects/gst-plugins-bad/sys/dwrite/libcaption/eia608.c
Normal file
375
subprojects/gst-plugins-bad/sys/dwrite/libcaption/eia608.c
Normal file
|
@ -0,0 +1,375 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2017 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include "eia608.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int eia608_row_map[] = { 10, -1, 0, 1, 2, 3, 11, 12, 13, 14, 4, 5, 6, 7, 8, 9 };
|
||||
int eia608_reverse_row_map[] =
|
||||
{ 2, 3, 4, 5, 10, 11, 12, 13, 14, 15, 0, 6, 7, 8, 9, 1 };
|
||||
|
||||
const char *eia608_style_map[] = {
|
||||
"white",
|
||||
"green",
|
||||
"blue",
|
||||
"cyan",
|
||||
"red",
|
||||
"yellow",
|
||||
"magenta",
|
||||
"italics",
|
||||
};
|
||||
|
||||
static inline uint16_t
|
||||
eia608_row_pramble (int row, int chan, int x, int underline)
|
||||
{
|
||||
row = eia608_reverse_row_map[row & 0x0F];
|
||||
return eia608_parity (0x1040 | (chan ? 0x0800 : 0x0000) | ((row << 7) &
|
||||
0x0700) | ((row << 5) & 0x0020) | ((x << 1) & 0x001E) | (underline ?
|
||||
0x0001 : 0x0000));
|
||||
}
|
||||
|
||||
uint16_t
|
||||
eia608_row_column_pramble (int row, int col, int chan, int underline)
|
||||
{
|
||||
return eia608_row_pramble (row, chan, 0x8 | (col / 4), underline);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
eia608_row_style_pramble (int row, int chan, eia608_style_t style,
|
||||
int underline)
|
||||
{
|
||||
return eia608_row_pramble (row, chan, style, underline);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
eia608_midrow_change (int chan, eia608_style_t style, int underline)
|
||||
{
|
||||
return eia608_parity (0x1120 | ((chan << 11) & 0x0800) | ((style << 1) &
|
||||
0x000E) | (underline & 0x0001));
|
||||
}
|
||||
|
||||
int
|
||||
eia608_parse_preamble (uint16_t cc_data, int *row, int *col,
|
||||
eia608_style_t * style, int *chan, int *underline)
|
||||
{
|
||||
(*row) =
|
||||
eia608_row_map[((0x0700 & cc_data) >> 7) | ((0x0020 & cc_data) >> 5)];
|
||||
(*chan) = ! !(0x0800 & cc_data);
|
||||
(*underline) = 0x0001 & cc_data;
|
||||
|
||||
if (0x0010 & cc_data) {
|
||||
(*style) = eia608_style_white;
|
||||
(*col) = 4 * ((0x000E & cc_data) >> 1);
|
||||
} else {
|
||||
(*style) = (0x000E & cc_data) >> 1;
|
||||
(*col) = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
eia608_parse_midrowchange (uint16_t cc_data, int *chan, eia608_style_t * style,
|
||||
int *underline)
|
||||
{
|
||||
(*chan) = ! !(0x0800 & cc_data);
|
||||
|
||||
if (0x1120 == (0x7770 & cc_data)) {
|
||||
(*style) = (0x000E & cc_data) >> 1;
|
||||
(*underline) = 0x0001 & cc_data;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// control command
|
||||
eia608_control_t
|
||||
eia608_parse_control (uint16_t cc_data, int *cc)
|
||||
{
|
||||
if (0x0200 & cc_data) {
|
||||
(*cc) = (cc_data & 0x0800 ? 0x01 : 0x00);
|
||||
return (eia608_control_t) (0x177F & cc_data);
|
||||
} else {
|
||||
(*cc) = (cc_data & 0x0800 ? 0x01 : 0x00) | (cc_data & 0x0100 ? 0x02 : 0x00);
|
||||
return (eia608_control_t) (0x167F & cc_data);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
eia608_control_command (eia608_control_t cmd, int cc)
|
||||
{
|
||||
uint16_t c = (cc & 0x01) ? 0x0800 : 0x0000;
|
||||
uint16_t f = (cc & 0x02) ? 0x0100 : 0x0000;
|
||||
|
||||
if (eia608_tab_offset_0 == (eia608_control_t) (cmd & 0xFFC0)) {
|
||||
return (eia608_control_t) eia608_parity (cmd | c);
|
||||
} else {
|
||||
return (eia608_control_t) eia608_parity (cmd | c | f);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// text
|
||||
static const char *
|
||||
utf8_from_index (int idx)
|
||||
{
|
||||
return (0 <= idx && EIA608_CHAR_COUNT > idx) ? eia608_char_map[idx] : "";
|
||||
}
|
||||
|
||||
static int
|
||||
eia608_to_index (uint16_t cc_data, int *chan, int *c1, int *c2)
|
||||
{
|
||||
(*c1) = (*c2) = -1;
|
||||
(*chan) = 0;
|
||||
cc_data &= 0x7F7F; // strip off parity bits
|
||||
|
||||
// Handle Basic NA BEFORE we strip the channel bit
|
||||
if (eia608_is_basicna (cc_data)) {
|
||||
// we got first char, yes. But what about second char?
|
||||
(*c1) = (cc_data >> 8) - 0x20;
|
||||
cc_data &= 0x00FF;
|
||||
|
||||
if (0x0020 <= cc_data && 0x0080 > cc_data) {
|
||||
(*c2) = cc_data - 0x20;
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
// Check then strip second channel toggle
|
||||
(*chan) = cc_data & 0x0800;
|
||||
cc_data = cc_data & 0xF7FF;
|
||||
|
||||
if (eia608_is_specialna (cc_data)) {
|
||||
// Special North American character
|
||||
(*c1) = cc_data - 0x1130 + 0x60;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0x1220 <= cc_data && 0x1240 > cc_data) {
|
||||
// Extended Western European character set, Spanish/Miscellaneous/French
|
||||
(*c1) = cc_data - 0x1220 + 0x70;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0x1320 <= cc_data && 0x1340 > cc_data) {
|
||||
// Extended Western European character set, Portuguese/German/Danish
|
||||
(*c1) = cc_data - 0x1320 + 0x90;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
eia608_to_utf8 (uint16_t c, int *chan, char *str1, char *str2)
|
||||
{
|
||||
int c1, c2;
|
||||
int size = (int) eia608_to_index (c, chan, &c1, &c2);
|
||||
utf8_char_copy (str1, utf8_from_index (c1));
|
||||
utf8_char_copy (str2, utf8_from_index (c2));
|
||||
return size;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
eia608_from_basicna (uint16_t bna1, uint16_t bna2)
|
||||
{
|
||||
if (!eia608_is_basicna (bna1) || !eia608_is_basicna (bna2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return eia608_parity ((0xFF00 & bna1) | ((0xFF00 & bna2) >> 8));
|
||||
}
|
||||
|
||||
// prototype for re2c generated function
|
||||
uint16_t _eia608_from_utf8 (const utf8_char_t * s);
|
||||
uint16_t
|
||||
eia608_from_utf8_1 (const utf8_char_t * c, int chan)
|
||||
{
|
||||
uint16_t cc_data = _eia608_from_utf8 (c);
|
||||
|
||||
if (0 == cc_data) {
|
||||
return cc_data;
|
||||
}
|
||||
|
||||
if (chan && !eia608_is_basicna (cc_data)) {
|
||||
cc_data |= 0x0800;
|
||||
}
|
||||
|
||||
return eia608_parity (cc_data);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
eia608_from_utf8_2 (const utf8_char_t * c1, const utf8_char_t * c2)
|
||||
{
|
||||
uint16_t cc1 = _eia608_from_utf8 (c1);
|
||||
uint16_t cc2 = _eia608_from_utf8 (c2);
|
||||
return eia608_from_basicna (cc1, cc2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int
|
||||
eia608_to_text (char *buf, ssize_t size, uint16_t cc_data)
|
||||
{
|
||||
eia608_style_t style;
|
||||
const char *text = 0;
|
||||
char char1[5], char2[5];
|
||||
char1[0] = char2[0] = 0;
|
||||
int row, col, chan, underline;
|
||||
int ret;
|
||||
|
||||
if (!eia608_parity_varify (cc_data)) {
|
||||
text = "parity failed";
|
||||
} else if (0 == eia608_parity_strip (cc_data)) {
|
||||
text = "pad";
|
||||
} else if (eia608_is_basicna (cc_data)) {
|
||||
text = "basicna";
|
||||
eia608_to_utf8 (cc_data, &chan, &char1[0], &char2[0]);
|
||||
} else if (eia608_is_specialna (cc_data)) {
|
||||
text = "specialna";
|
||||
eia608_to_utf8 (cc_data, &chan, &char1[0], &char2[0]);
|
||||
} else if (eia608_is_westeu (cc_data)) {
|
||||
text = "westeu";
|
||||
eia608_to_utf8 (cc_data, &chan, &char1[0], &char2[0]);
|
||||
} else if (eia608_is_xds (cc_data)) {
|
||||
text = "xds";
|
||||
} else if (eia608_is_midrowchange (cc_data)) {
|
||||
text = "midrowchange";
|
||||
} else if (eia608_is_norpak (cc_data)) {
|
||||
text = "norpak";
|
||||
} else if (eia608_is_preamble (cc_data)) {
|
||||
eia608_parse_preamble (cc_data, &row, &col, &style, &chan, &underline);
|
||||
ret = snprintf(buf, size, "cc %04X (%04X) '%s' '%s' (preamble: row: %d col: %d style: %d chan: %d underline: %d)",
|
||||
cc_data, eia608_parity_strip (cc_data), char1, char2, row, col, style, chan, underline);
|
||||
} else if (eia608_is_control (cc_data)) {
|
||||
switch (eia608_parse_control (cc_data, &chan)) {
|
||||
|
||||
default:
|
||||
text = "unknown_control";
|
||||
break;
|
||||
|
||||
case eia608_tab_offset_0:
|
||||
text = "eia608_tab_offset_0";
|
||||
break;
|
||||
|
||||
case eia608_tab_offset_1:
|
||||
text = "eia608_tab_offset_1";
|
||||
break;
|
||||
|
||||
case eia608_tab_offset_2:
|
||||
text = "eia608_tab_offset_2";
|
||||
break;
|
||||
|
||||
case eia608_tab_offset_3:
|
||||
text = "eia608_tab_offset_3";
|
||||
break;
|
||||
|
||||
case eia608_control_resume_caption_loading:
|
||||
text = "eia608_control_resume_caption_loading";
|
||||
break;
|
||||
|
||||
case eia608_control_backspace:
|
||||
text = "eia608_control_backspace";
|
||||
break;
|
||||
|
||||
case eia608_control_alarm_off:
|
||||
text = "eia608_control_alarm_off";
|
||||
break;
|
||||
|
||||
case eia608_control_alarm_on:
|
||||
text = "eia608_control_alarm_on";
|
||||
break;
|
||||
|
||||
case eia608_control_delete_to_end_of_row:
|
||||
text = "eia608_control_delete_to_end_of_row";
|
||||
break;
|
||||
|
||||
case eia608_control_roll_up_2:
|
||||
text = "eia608_control_roll_up_2";
|
||||
break;
|
||||
|
||||
case eia608_control_roll_up_3:
|
||||
text = "eia608_control_roll_up_3";
|
||||
break;
|
||||
|
||||
case eia608_control_roll_up_4:
|
||||
text = "eia608_control_roll_up_4";
|
||||
break;
|
||||
|
||||
case eia608_control_resume_direct_captioning:
|
||||
text = "eia608_control_resume_direct_captioning";
|
||||
break;
|
||||
|
||||
case eia608_control_text_restart:
|
||||
text = "eia608_control_text_restart";
|
||||
break;
|
||||
|
||||
case eia608_control_text_resume_text_display:
|
||||
text = "eia608_control_text_resume_text_display";
|
||||
break;
|
||||
|
||||
case eia608_control_erase_display_memory:
|
||||
text = "eia608_control_erase_display_memory";
|
||||
break;
|
||||
|
||||
case eia608_control_carriage_return:
|
||||
text = "eia608_control_carriage_return";
|
||||
break;
|
||||
|
||||
case eia608_control_erase_non_displayed_memory:
|
||||
text = "eia608_control_erase_non_displayed_memory";
|
||||
break;
|
||||
|
||||
case eia608_control_end_of_caption:
|
||||
text = "eia608_control_end_of_caption";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
text = "unhandled";
|
||||
}
|
||||
|
||||
if (text != 0) {
|
||||
ret = snprintf (buf, size, "cc %04X (%04X) '%s' '%s' (%s)", cc_data, eia608_parity_strip (cc_data), char1, char2, text);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
eia608_dump (uint16_t cc_data)
|
||||
{
|
||||
char *text = NULL;
|
||||
int bufsz;
|
||||
|
||||
bufsz = eia608_to_text (NULL, 0, cc_data);
|
||||
text = malloc(bufsz + 1);
|
||||
eia608_to_text (text, bufsz + 1, cc_data);
|
||||
fprintf (stderr, "%s\n", text);
|
||||
|
||||
free (text);
|
||||
}
|
219
subprojects/gst-plugins-bad/sys/dwrite/libcaption/eia608.h
Normal file
219
subprojects/gst-plugins-bad/sys/dwrite/libcaption/eia608.h
Normal file
|
@ -0,0 +1,219 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2017 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#ifndef LIBCAPTION_EIA608_H
|
||||
#define LIBCAPTION_EIA608_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "eia608_charmap.h"
|
||||
#include "utf8.h"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Parity
|
||||
#define EIA608_BX(B, X) (((B) << (X)) & 0x80)
|
||||
#define EIA608_BP(B) ((B)&0x7F) | (0x80 ^ EIA608_BX((B), 1) ^ EIA608_BX((B), 2) ^ EIA608_BX((B), 3) ^ EIA608_BX((B), 4) ^ EIA608_BX((B), 5) ^ EIA608_BX((B), 6) ^ EIA608_BX((B), 7))
|
||||
#define EIA608_B2(B) EIA608_BP((B) + 0), EIA608_BP((B) + 1), EIA608_BP((B) + 2), EIA608_BP((B) + 3), EIA608_BP((B) + 4), EIA608_BP((B) + 5), EIA608_BP((B) + 6), EIA608_BP((B) + 7)
|
||||
#define EIA608_B1(B) EIA608_B2((B) + 0), EIA608_B2((B) + 8), EIA608_B2((B) + 16), EIA608_B2((B) + 24), EIA608_B2((B) + 32), EIA608_B2((B) + 40), EIA608_B2((B) + 48), EIA608_B2((B) + 56)
|
||||
|
||||
static const uint8_t eia608_parity_table[] = { EIA608_B1(0), EIA608_B1(64) };
|
||||
extern const char* eia608_style_map[];
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifndef inline
|
||||
#define inline __inline
|
||||
#endif
|
||||
// ssize_t is POSIX and does not exist on Windows
|
||||
#if defined(_WIN64)
|
||||
typedef signed long ssize_t;
|
||||
#else
|
||||
typedef signed int ssize_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline uint8_t eia608_parity_byte(uint8_t cc_data) { return eia608_parity_table[0x7F & cc_data]; }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline uint16_t eia608_parity_word(uint16_t cc_data) { return (uint16_t)((eia608_parity_byte((uint8_t)(cc_data >> 8)) << 8) | eia608_parity_byte((uint8_t)cc_data)); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline uint16_t eia608_parity(uint16_t cc_data) { return eia608_parity_word(cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_parity_varify(uint16_t cc_data) { return eia608_parity_word(cc_data) == cc_data ? 1 : 0; }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_parity_strip(uint16_t cc_data) { return cc_data & 0x7F7F; }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_test_second_channel_bit(uint16_t cc_data) { return (cc_data & 0x0800); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cc_data types
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_basicna(uint16_t cc_data) { return 0x0000 != (0x6000 & cc_data); /*&& 0x1F00 < (0x7F00 & cc_data);*/ }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_preamble(uint16_t cc_data) { return 0x1040 == (0x7040 & cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_midrowchange(uint16_t cc_data) { return 0x1120 == (0x7770 & cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_specialna(uint16_t cc_data) { return 0x1130 == (0x7770 & cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_xds(uint16_t cc_data) { return 0x0000 == (0x7070 & cc_data) && 0x0000 != (0x0F0F & cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_westeu(uint16_t cc_data) { return 0x1220 == (0x7660 & cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_control(uint16_t cc_data) { return 0x1420 == (0x7670 & cc_data) || 0x1720 == (0x7770 & cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_norpak(uint16_t cc_data) { return 0x1724 == (0x777C & cc_data) || 0x1728 == (0x777C & cc_data); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline int eia608_is_padding(uint16_t cc_data) { return 0x8080 == cc_data; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// preamble
|
||||
typedef enum {
|
||||
eia608_style_white = 0,
|
||||
eia608_style_green = 1,
|
||||
eia608_style_blue = 2,
|
||||
eia608_style_cyan = 3,
|
||||
eia608_style_red = 4,
|
||||
eia608_style_yellow = 5,
|
||||
eia608_style_magenta = 6,
|
||||
eia608_style_italics = 7,
|
||||
} eia608_style_t;
|
||||
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
int eia608_parse_preamble(uint16_t cc_data, int* row, int* col, eia608_style_t* style, int* chan, int* underline);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
int eia608_parse_midrowchange(uint16_t cc_data, int* chan, eia608_style_t* style, int* underline);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
uint16_t eia608_row_column_pramble(int row, int col, int chan, int underline);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
uint16_t eia608_row_style_pramble(int row, int chan, eia608_style_t style, int underline);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
uint16_t eia608_midrow_change(int chan, eia608_style_t style, int underline);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// control command
|
||||
typedef enum {
|
||||
eia608_tab_offset_0 = 0x1720,
|
||||
eia608_tab_offset_1 = 0x1721,
|
||||
eia608_tab_offset_2 = 0x1722,
|
||||
eia608_tab_offset_3 = 0x1723,
|
||||
eia608_control_resume_caption_loading = 0x1420,
|
||||
eia608_control_backspace = 0x1421,
|
||||
eia608_control_alarm_off = 0x1422,
|
||||
eia608_control_alarm_on = 0x1423,
|
||||
eia608_control_delete_to_end_of_row = 0x1424,
|
||||
eia608_control_roll_up_2 = 0x1425,
|
||||
eia608_control_roll_up_3 = 0x1426,
|
||||
eia608_control_roll_up_4 = 0x1427,
|
||||
eia608_control_resume_direct_captioning = 0x1429,
|
||||
eia608_control_text_restart = 0x142A,
|
||||
eia608_control_text_resume_text_display = 0x142B,
|
||||
eia608_control_erase_display_memory = 0x142C,
|
||||
eia608_control_carriage_return = 0x142D,
|
||||
eia608_control_erase_non_displayed_memory = 0x142E,
|
||||
eia608_control_end_of_caption = 0x142F,
|
||||
} eia608_control_t;
|
||||
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
uint16_t eia608_control_command(eia608_control_t cmd, int cc);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
static inline uint16_t eia608_tab(int size, int cc) { return eia608_control_command((eia608_control_t)(eia608_tab_offset_0 | (size & 0x0F)), cc); }
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
eia608_control_t eia608_parse_control(uint16_t cc_data, int* cc);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// text
|
||||
/*! \brief
|
||||
\param c
|
||||
*/
|
||||
uint16_t eia608_from_utf8_1(const utf8_char_t* c, int chan);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
uint16_t eia608_from_utf8_2(const utf8_char_t* c1, const utf8_char_t* c2);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
uint16_t eia608_from_basicna(uint16_t bna1, uint16_t bna2);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
int eia608_to_utf8(uint16_t c, int* chan, utf8_char_t* char1, utf8_char_t* char2);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
void eia608_dump(uint16_t cc_data);
|
||||
/*! \brief
|
||||
\param
|
||||
*/
|
||||
int eia608_to_text (char *buf, ssize_t size, uint16_t cc_data);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,208 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2017 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#include "eia608_charmap.h"
|
||||
// 0 - 95: Basic North American character set
|
||||
// 96 - 111: Special North American character
|
||||
// 112 - 127: Extended Western European character set : Extended Spanish/Miscellaneous
|
||||
// 128 - 143: Extended Western European character set : Extended French
|
||||
// 144 - 159: Extended Western European character set : Portuguese
|
||||
// 160 - 175: Extended Western European character set : German/Danish
|
||||
const char *eia608_char_map[] = {
|
||||
EIA608_CHAR_SPACE,
|
||||
EIA608_CHAR_EXCLAMATION_MARK,
|
||||
EIA608_CHAR_QUOTATION_MARK,
|
||||
EIA608_CHAR_NUMBER_SIGN,
|
||||
EIA608_CHAR_DOLLAR_SIGN,
|
||||
EIA608_CHAR_PERCENT_SIGN,
|
||||
EIA608_CHAR_AMPERSAND,
|
||||
EIA608_CHAR_RIGHT_SINGLE_QUOTATION_MARK,
|
||||
EIA608_CHAR_LEFT_PARENTHESIS,
|
||||
EIA608_CHAR_RIGHT_PARENTHESIS,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_ACUTE,
|
||||
EIA608_CHAR_PLUS_SIGN,
|
||||
EIA608_CHAR_COMMA,
|
||||
EIA608_CHAR_HYPHEN_MINUS,
|
||||
EIA608_CHAR_FULL_STOP,
|
||||
EIA608_CHAR_SOLIDUS,
|
||||
EIA608_CHAR_DIGIT_ZERO,
|
||||
EIA608_CHAR_DIGIT_ONE,
|
||||
EIA608_CHAR_DIGIT_TWO,
|
||||
EIA608_CHAR_DIGIT_THREE,
|
||||
EIA608_CHAR_DIGIT_FOUR,
|
||||
EIA608_CHAR_DIGIT_FIVE,
|
||||
EIA608_CHAR_DIGIT_SIX,
|
||||
EIA608_CHAR_DIGIT_SEVEN,
|
||||
EIA608_CHAR_DIGIT_EIGHT,
|
||||
EIA608_CHAR_DIGIT_NINE,
|
||||
EIA608_CHAR_COLON,
|
||||
EIA608_CHAR_SEMICOLON,
|
||||
EIA608_CHAR_LESS_THAN_SIGN,
|
||||
EIA608_CHAR_EQUALS_SIGN,
|
||||
EIA608_CHAR_GREATER_THAN_SIGN,
|
||||
EIA608_CHAR_QUESTION_MARK,
|
||||
EIA608_CHAR_COMMERCIAL_AT,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_A,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_B,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_C,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_D,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_E,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_F,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_G,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_H,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_I,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_J,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_K,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_L,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_M,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_N,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_O,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_P,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_Q,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_R,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_S,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_T,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_U,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_V,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_W,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_X,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_Y,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_Z,
|
||||
EIA608_CHAR_LEFT_SQUARE_BRACKET,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_ACUTE,
|
||||
EIA608_CHAR_RIGHT_SQUARE_BRACKET,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_A,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_B,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_C,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_D,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_E,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_F,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_G,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_H,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_I,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_J,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_K,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_L,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_M,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_N,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_O,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_P,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_Q,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_R,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_S,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_T,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_U,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_V,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_W,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_X,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_Y,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_Z,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_C_WITH_CEDILLA,
|
||||
EIA608_CHAR_DIVISION_SIGN,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_N_WITH_TILDE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_N_WITH_TILDE,
|
||||
EIA608_CHAR_FULL_BLOCK,
|
||||
EIA608_CHAR_REGISTERED_SIGN,
|
||||
EIA608_CHAR_DEGREE_SIGN,
|
||||
EIA608_CHAR_VULGAR_FRACTION_ONE_HALF,
|
||||
EIA608_CHAR_INVERTED_QUESTION_MARK,
|
||||
EIA608_CHAR_TRADE_MARK_SIGN,
|
||||
EIA608_CHAR_CENT_SIGN,
|
||||
EIA608_CHAR_POUND_SIGN,
|
||||
EIA608_CHAR_EIGHTH_NOTE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_GRAVE,
|
||||
EIA608_CHAR_NO_BREAK_SPACE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LEFT_SINGLE_QUOTATION_MARK,
|
||||
EIA608_CHAR_INVERTED_EXCLAMATION_MARK,
|
||||
EIA608_CHAR_ASTERISK,
|
||||
EIA608_CHAR_APOSTROPHE,
|
||||
EIA608_CHAR_EM_DASH,
|
||||
EIA608_CHAR_COPYRIGHT_SIGN,
|
||||
EIA608_CHAR_SERVICE_MARK,
|
||||
EIA608_CHAR_BULLET,
|
||||
EIA608_CHAR_LEFT_DOUBLE_QUOTATION_MARK,
|
||||
EIA608_CHAR_RIGHT_DOUBLE_QUOTATION_MARK,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_C_WITH_CEDILLA,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_E_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_E_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_U_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_U_WITH_CIRCUMFLEX,
|
||||
EIA608_CHAR_LEFT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK,
|
||||
EIA608_CHAR_RIGHT_POINTING_DOUBLE_ANGLE_QUOTATION_MARK,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_TILDE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_TILDE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_ACUTE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_I_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_I_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_GRAVE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_TILDE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_TILDE,
|
||||
EIA608_CHAR_LEFT_CURLY_BRACKET,
|
||||
EIA608_CHAR_RIGHT_CURLY_BRACKET,
|
||||
EIA608_CHAR_REVERSE_SOLIDUS,
|
||||
EIA608_CHAR_CIRCUMFLEX_ACCENT,
|
||||
EIA608_CHAR_LOW_LINE,
|
||||
EIA608_CHAR_VERTICAL_LINE,
|
||||
EIA608_CHAR_TILDE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_DIAERESIS,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_SHARP_S,
|
||||
EIA608_CHAR_YEN_SIGN,
|
||||
EIA608_CHAR_CURRENCY_SIGN,
|
||||
EIA608_CHAR_BROKEN_BAR,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_A_WITH_RING_ABOVE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_A_WITH_RING_ABOVE,
|
||||
EIA608_CHAR_LATIN_CAPITAL_LETTER_O_WITH_STROKE,
|
||||
EIA608_CHAR_LATIN_SMALL_LETTER_O_WITH_STROKE,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_RIGHT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_DOWN_AND_LEFT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_RIGHT,
|
||||
EIA608_CHAR_BOX_DRAWINGS_LIGHT_UP_AND_LEFT,
|
||||
};
|
|
@ -0,0 +1,236 @@
|
|||
/**********************************************************************************************/
|
||||
/* The MIT License */
|
||||
/* */
|
||||
/* Copyright 2016-2017 Twitch Interactive, Inc. or its affiliates. All Rights Reserved. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
|
||||
/* of this software and associated documentation files (the "Software"), to deal */
|
||||
/* in the Software without restriction, including without limitation the rights */
|
||||
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
|
||||
/* copies of the Software, and to permit persons to whom the Software is */
|
||||
/* furnished to do so, subject to the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be included in */
|
||||
/* all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
|
||||
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
|
||||
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
|
||||
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
|
||||
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN */
|
||||
/* THE SOFTWARE. */
|
||||
/**********************************************************************************************/
|
||||
#ifndef LIBCAPTION_EIA608_CHARMAP_H
|
||||
#define LIBCAPTION_EIA608_CHARMAP_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define EIA608_CHAR_COUNT 176
|
||||
extern const char* eia608_char_map[EIA608_CHAR_COUNT];
|
||||
|
||||
// Helper char
|
||||