Go to the documentation of this file.
26 #define SCREEN_ROWS 15
27 #define SCREEN_COLUMNS 32
29 #define SET_FLAG(var, val) ( (var) |= ( 1 << (val)) )
30 #define UNSET_FLAG(var, val) ( (var) &= ~( 1 << (val)) )
31 #define CHECK_FLAG(var, val) ( (var) & ( 1 << (val)) )
265 ctx->cursor_row = 10;
287 ctx->pktbuf_size = 0;
294 ctx->screen[0].row_used = 0;
295 ctx->screen[1].row_used = 0;
296 ctx->prev_cmd[0] = 0;
297 ctx->prev_cmd[1] = 0;
300 ctx->cursor_row = 10;
301 ctx->cursor_column = 0;
302 ctx->cursor_font = 0;
303 ctx->cursor_color = 0;
304 ctx->cursor_charset = 0;
305 ctx->active_screen = 0;
306 ctx->last_real_time = 0;
307 ctx->screen_touched = 0;
308 ctx->buffer_changed = 0;
321 char *font = screen->
fonts[
ctx->cursor_row];
326 font[col] =
ctx->cursor_font;
327 charset[col] =
ctx->cursor_charset;
329 if (ch)
ctx->cursor_column++;
352 uint8_t cc_valid = (*cc_data_pair & 4) >>2;
353 uint8_t cc_type = *cc_data_pair & 3;
359 if (cc_type==0 || cc_type==1) {
360 if (!av_parity(cc_data_pair[2])) {
363 if (!av_parity(cc_data_pair[1])) {
364 cc_data_pair[1]=0x7F;
369 if ((cc_data_pair[0] == 0xFA || cc_data_pair[0] == 0xFC || cc_data_pair[0] == 0xFD)
370 && (cc_data_pair[1] & 0x7F) == 0 && (cc_data_pair[2] & 0x7F) == 0)
374 if (cc_type == 3 || cc_type == 2)
378 cc_data_pair[1] &= 0x7F;
379 cc_data_pair[2] &= 0x7F;
389 return ctx->screen + !
ctx->active_screen;
394 return ctx->screen +
ctx->active_screen;
413 keep_lines =
FFMIN(
ctx->cursor_row + 1,
ctx->rollup);
416 if (
i >
ctx->cursor_row - keep_lines && i <= ctx->cursor_row)
421 for (
i = 0;
i < keep_lines && screen->
row_used;
i++) {
422 const int i_row =
ctx->cursor_row - keep_lines +
i + 1;
438 struct Screen *screen =
ctx->screen +
ctx->active_screen;
446 const char *charset = screen->
charsets[
i];
459 const char *font = screen->
fonts[
i];
460 const char *charset = screen->
charsets[
i];
461 const char *
override;
462 int x, y, seen_char = 0;
474 const char *e_tag =
"", *s_tag =
"";
479 if (prev_font != font[j]) {
488 e_tag =
"{\\u0}{\\i0}";
499 s_tag =
"{\\u1}{\\i1}";
508 }
else if (row[j] ==
' ' && !seen_char) {
522 ctx->buffer.len -= 2;
523 ctx->buffer.str[
ctx->buffer.len] = 0;
525 ctx->buffer_changed = 1;
554 static const int8_t row_map[] = {
555 11, -1, 1, 2, 3, 4, 12, 13, 14, 15, 5, 6, 7, 8, 9, 10
557 const int index = ( (hi<<1) & 0x0e) | ( (lo>>5) & 0x01 );
561 if (row_map[
index] <= 0) {
568 ctx->cursor_row = row_map[
index] - 1;
572 ctx->cursor_column = 0;
574 for (
i = 0;
i < indent;
i++) {
584 struct Screen *screen =
ctx->screen +
ctx->active_screen;
606 ctx->active_screen = !
ctx->active_screen;
607 ctx->cursor_column = 0;
632 if (
ctx->cursor_column > 0)
633 ctx->cursor_column -= 1;
637 if (
ctx->cursor_column > 0)
638 ctx->cursor_column -= 1;
653 ctx->screen_touched = 1;
663 if (hi ==
ctx->prev_cmd[0] && lo ==
ctx->prev_cmd[1]) {
669 ctx->prev_cmd[0] = hi;
670 ctx->prev_cmd[1] = lo;
672 if ( (hi == 0x10 && (lo >= 0x40 && lo <= 0x5f)) ||
673 ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) {
675 }
else if ( ( hi == 0x11 && lo >= 0x20 && lo <= 0x2f ) ||
676 ( hi == 0x17 && lo >= 0x2e && lo <= 0x2f) ) {
678 }
else if (hi == 0x14 || hi == 0x15 || hi == 0x1c) {
690 ctx->rollup = lo - 0x23;
711 ctx->cursor_column = 0;
717 if (
ctx->real_time) {
718 struct Screen *screen =
ctx->screen + !
ctx->active_screen;
728 ff_dlog(
ctx,
"Unknown command 0x%hhx 0x%hhx\n", hi, lo);
731 }
else if (hi >= 0x11 && hi <= 0x13) {
734 }
else if (hi >= 0x20) {
737 ctx->prev_cmd[0] =
ctx->prev_cmd[1] = 0;
738 }
else if (hi == 0x17 && lo >= 0x21 && lo <= 0x23) {
741 for (
i = 0;
i < lo - 0x20;
i++) {
746 ff_dlog(
ctx,
"Unknown command 0x%hhx 0x%hhx\n", hi, lo);
768 for (
i = 0;
i <
len;
i += 3) {
778 if (!
ctx->buffer_changed)
780 ctx->buffer_changed = 0;
782 if (*
ctx->buffer.str ||
ctx->real_time)
794 ctx->buffer_changed = 0;
795 ctx->last_real_time = sub->
pts;
796 ctx->screen_touched = 0;
800 if (
ctx->real_time &&
ctx->screen_touched &&
802 ctx->last_real_time = sub->
pts;
803 ctx->screen_touched = 0;
806 ctx->buffer_changed = 0;
818 #define OFFSET(x) offsetof(CCaptionSubContext, x)
819 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
821 {
"real_time",
"emit subtitle events as they are decoded for real-time display",
OFFSET(real_time),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
SD },
static struct Screen * get_writing_screen(CCaptionSubContext *ctx)
int ff_ass_subtitle_header(AVCodecContext *avctx, const char *font, int font_size, int color, int back_color, int bold, int italic, int underline, int border_style, int alignment)
Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS.
static void handle_delete_end_of_row(CCaptionSubContext *ctx, char hi, char lo)
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_BPRINT_SIZE_UNLIMITED
static av_cold int init(AVCodecContext *avctx)
#define CHECK_FLAG(var, val)
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 av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
static void handle_edm(CCaptionSubContext *ctx, int64_t pts)
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
@ CCSET_EXTENDED_SPANISH_FRENCH_MISC
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo)
static int validate_cc_data_pair(uint8_t *cc_data_pair)
This function after validating parity bit, also remove it from data pair.
#define ASS_DEFAULT_ALIGNMENT
int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, const char *speaker)
Add an ASS dialog to a subtitle.
static void handle_eoc(CCaptionSubContext *ctx, int64_t pts)
static const struct twinvq_data tab
static void write_char(CCaptionSubContext *ctx, struct Screen *screen, char ch)
uint8_t characters[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
static int reap_screen(CCaptionSubContext *ctx, int64_t pts)
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
AVCodec ff_ccaption_decoder
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.
#define ASS_DEFAULT_BACK_COLOR
#define LIBAVUTIL_VERSION_INT
Describe the class of an AVClass context structure.
static void flush(AVCodecContext *avctx)
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Rational number (pair of numerator and denominator).
const char * av_default_item_name(void *ptr)
Return the context name.
#define ASS_DEFAULT_PLAYRESY
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
int flags2
AV_CODEC_FLAG2_*.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static int64_t start_time
uint8_t charsets[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
#define ASS_DEFAULT_PLAYRESX
static const unsigned char pac2_attribs[32][3]
static void flush_decoder(AVCodecContext *avctx)
uint32_t end_display_time
static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt)
#define SET_FLAG(var, val)
#define ASS_DEFAULT_UNDERLINE
static av_cold int init_decoder(AVCodecContext *avctx)
@ CCFONT_UNDERLINED_ITALICS
static const char * charset_overrides[4][128]
static const AVOption options[]
#define i(width, name, range_min, range_max)
static int capture_screen(CCaptionSubContext *ctx)
#define UNSET_FLAG(var, val)
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional AV_INPUT_BUFFER_PADDING_SIZE at the end w...
const char * name
Name of the codec implementation.
#define ASS_DEFAULT_ITALIC
#define ASS_DEFAULT_COLOR
static void handle_textattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
void av_bprintf(AVBPrint *buf, const char *fmt,...)
uint8_t colors[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
#define ASS_DEFAULT_FONT_SIZE
main external API structure.
static av_cold int close_decoder(AVCodecContext *avctx)
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
uint8_t fonts[SCREEN_ROWS+1][SCREEN_COLUMNS+1]
static const AVClass ccaption_dec_class
@ CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH
This structure stores compressed data.
static void handle_pac(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
int64_t start_time
Position of the first frame of the component, in AV_TIME_BASE fractional seconds.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static const AVRational ms_tb
static void roll_up(CCaptionSubContext *ctx)
#define AV_CODEC_FLAG2_RO_FLUSH_NOOP
Do not reset ASS ReadOrder field on flush (subtitles decoding)