movtextenc.c
Go to the documentation of this file.
1 /*
2  * 3GPP TS 26.245 Timed Text encoder
3  * Copyright (c) 2012 Philip Langdale <philipl@overt.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <stdarg.h>
23 #include "avcodec.h"
24 #include "libavutil/avassert.h"
25 #include "libavutil/avstring.h"
26 #include "libavutil/intreadwrite.h"
27 #include "ass_split.h"
28 #include "ass.h"
29 
30 typedef struct {
32  char buffer[2048];
33  char *ptr;
34  char *end;
36 
37 
39 {
40  /*
41  * For now, we'll use a fixed default style. When we add styling
42  * support, this will be generated from the ASS style.
43  */
44  static uint8_t text_sample_entry[] = {
45  0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags
46  0x01, // int8_t horizontal-justification
47  0xFF, // int8_t vertical-justification
48  0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4]
49  // BoxRecord {
50  0x00, 0x00, // int16_t top
51  0x00, 0x00, // int16_t left
52  0x00, 0x00, // int16_t bottom
53  0x00, 0x00, // int16_t right
54  // };
55  // StyleRecord {
56  0x00, 0x00, // uint16_t startChar
57  0x00, 0x00, // uint16_t endChar
58  0x00, 0x01, // uint16_t font-ID
59  0x00, // uint8_t face-style-flags
60  0x12, // uint8_t font-size
61  0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4]
62  // };
63  // FontTableBox {
64  0x00, 0x00, 0x00, 0x12, // uint32_t size
65  'f', 't', 'a', 'b', // uint8_t name[4]
66  0x00, 0x01, // uint16_t entry-count
67  // FontRecord {
68  0x00, 0x01, // uint16_t font-ID
69  0x05, // uint8_t font-name-length
70  'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length]
71  // };
72  // };
73  };
74 
75  MovTextContext *s = avctx->priv_data;
76 
77  avctx->extradata_size = sizeof text_sample_entry;
78  avctx->extradata = av_mallocz(avctx->extradata_size);
79  if (!avctx->extradata)
80  return AVERROR(ENOMEM);
81 
82  memcpy(avctx->extradata, text_sample_entry, avctx->extradata_size);
83 
85  return s->ass_ctx ? 0 : AVERROR_INVALIDDATA;
86 }
87 
88 static void mov_text_text_cb(void *priv, const char *text, int len)
89 {
90  MovTextContext *s = priv;
91  av_assert0(s->end >= s->ptr);
92  av_strlcpy(s->ptr, text, FFMIN(s->end - s->ptr, len + 1));
93  s->ptr += FFMIN(s->end - s->ptr, len);
94 }
95 
96 static void mov_text_new_line_cb(void *priv, int forced)
97 {
98  MovTextContext *s = priv;
99  av_assert0(s->end >= s->ptr);
100  av_strlcpy(s->ptr, "\n", FFMIN(s->end - s->ptr, 2));
101  if (s->end > s->ptr)
102  s->ptr++;
103 }
104 
107  .new_line = mov_text_new_line_cb,
108 };
109 
110 static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
111  int bufsize, const AVSubtitle *sub)
112 {
113  MovTextContext *s = avctx->priv_data;
114  ASSDialog *dialog;
115  int i, len, num;
116 
117  s->ptr = s->buffer;
118  s->end = s->ptr + sizeof(s->buffer);
119 
120  for (i = 0; i < sub->num_rects; i++) {
121 
122  if (sub->rects[i]->type != SUBTITLE_ASS) {
123  av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
124  return AVERROR(ENOSYS);
125  }
126 
127  dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num);
128  for (; dialog && num--; dialog++) {
129  ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
130  }
131  }
132 
133  if (s->ptr == s->buffer)
134  return 0;
135 
136  AV_WB16(buf, strlen(s->buffer));
137  buf += 2;
138 
139  len = av_strlcpy(buf, s->buffer, bufsize - 2);
140 
141  if (len > bufsize-3) {
142  av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
143  return AVERROR(EINVAL);
144  }
145 
146  return len + 2;
147 }
148 
150 {
151  MovTextContext *s = avctx->priv_data;
153  return 0;
154 }
155 
157  .name = "mov_text",
158  .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
159  .type = AVMEDIA_TYPE_SUBTITLE,
160  .id = AV_CODEC_ID_MOV_TEXT,
161  .priv_data_size = sizeof(MovTextContext),
163  .encode_sub = mov_text_encode_frame,
165 };
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
fields extracted from the [Events] section
Definition: ass_split.h:56
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
ASSSplitContext * ff_ass_split(const char *buf)
Split a full ASS file or a ASS header from a string buffer and store the split structure in a newly a...
Definition: ass_split.c:303
static av_cold int mov_text_encode_init(AVCodecContext *avctx)
Definition: movtextenc.c:38
text(-8, 1,'a)')
AVSubtitleRect ** rects
char * text
actual text which will be displayed as a subtitle, can include style override control codes (see ff_a...
Definition: ass_split.h:61
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint8_t
#define av_cold
Definition: attributes.h:78
ASSSplitContext * ass_ctx
Definition: movtextenc.c:31
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, const char *buf)
Split override codes out of a ASS "Dialogue" Text field.
Definition: ass_split.c:370
static void mov_text_text_cb(void *priv, const char *text, int len)
Definition: movtextenc.c:88
ASSDialog * ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf, int cache, int *number)
Split one or several ASS "Dialogue" lines from a string buffer and store them in a already initialize...
Definition: ass_split.c:338
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
external API header
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:82
#define FFMIN(a, b)
Definition: common.h:58
char buffer[2048]
Definition: movtextenc.c:32
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
Definition: ass_split.h:119
AVCodec ff_movtext_encoder
Definition: movtextenc.c:156
static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, int bufsize, const AVSubtitle *sub)
Definition: movtextenc.c:110
static const ASSCodesCallbacks mov_text_callbacks
Definition: movtextenc.c:105
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
static int mov_text_encode_close(AVCodecContext *avctx)
Definition: movtextenc.c:149
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
synthesis window for stochastic i
#define AV_WB16(p, darg)
Definition: intreadwrite.h:237
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
void(* text)(void *priv, const char *text, int len)
Definition: ass_split.h:124
the buffer and buffer reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFilterBuffer structures They must not be accessed but through references stored in AVFilterBufferRef structures Several references can point to the same buffer
static void mov_text_new_line_cb(void *priv, int forced)
Definition: movtextenc.c:96
Formatted text, the ass field must be set by the decoder and is authoritative.
int len
char * ass
0 terminated ASS/SSA compatible event line.
void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
Definition: ass_split.c:357
enum AVSubtitleType type
uint8_t * subtitle_header
Header containing style information for text subtitles.