FFmpeg: libavcodec/srtenc.c Source File

FFmpeg
srtenc.c
Go to the documentation of this file.
1 /*
2  * SubRip subtitle encoder
3  * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.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/avstring.h"
25 #include "libavutil/bprint.h"
26 #include "ass_split.h"
27 #include "ass.h"
28 
29 
30  #define SRT_STACK_SIZE 64
31 
32  typedef struct {
33   AVCodecContext *avctx;
34   ASSSplitContext *ass_ctx;
35   AVBPrint buffer;
36   char stack[SRT_STACK_SIZE];
37   int stack_ptr;
38   int alignment_applied;
39 } SRTContext;
40 
41 
42 #ifdef __GNUC__
43 __attribute__ ((__format__ (__printf__, 2, 3)))
44 #endif
45  static void srt_print(SRTContext *s, const char *str, ...)
46 {
47  va_list vargs;
48  va_start(vargs, str);
49  av_vbprintf(&s->buffer, str, vargs);
50  va_end(vargs);
51 }
52 
53  static int srt_stack_push(SRTContext *s, const char c)
54 {
55  if (s->stack_ptr >= SRT_STACK_SIZE)
56  return -1;
57  s->stack[s->stack_ptr++] = c;
58  return 0;
59 }
60 
61  static char srt_stack_pop(SRTContext *s)
62 {
63  if (s->stack_ptr <= 0)
64  return 0;
65  return s->stack[--s->stack_ptr];
66 }
67 
68  static int srt_stack_find(SRTContext *s, const char c)
69 {
70  int i;
71  for (i = s->stack_ptr-1; i >= 0; i--)
72  if (s->stack[i] == c)
73  break;
74  return i;
75 }
76 
77  static void srt_close_tag(SRTContext *s, char tag)
78 {
79  srt_print(s, "</%c%s>", tag, tag == 'f' ? "ont" : "");
80 }
81 
82  static void srt_stack_push_pop(SRTContext *s, const char c, int close)
83 {
84  if (close) {
85  int i = c ? srt_stack_find(s, c) : 0;
86  if (i < 0)
87  return;
88  while (s->stack_ptr != i)
89  srt_close_tag(s, srt_stack_pop(s));
90  } else if (srt_stack_push(s, c) < 0)
91  av_log(s->avctx, AV_LOG_ERROR, "tag stack overflow\n");
92 }
93 
94  static void srt_style_apply(SRTContext *s, const char *style)
95 {
96  ASSStyle *st = ff_ass_style_get(s->ass_ctx, style);
97  if (st) {
98  int c = st->primary_color & 0xFFFFFF;
99  if (st->font_name && strcmp(st->font_name, ASS_DEFAULT_FONT) ||
100  st->font_size != ASS_DEFAULT_FONT_SIZE ||
101  c != ASS_DEFAULT_COLOR) {
102  srt_print(s, "<font");
103  if (st->font_name && strcmp(st->font_name, ASS_DEFAULT_FONT))
104  srt_print(s, " face=\"%s\"", st->font_name);
105  if (st->font_size != ASS_DEFAULT_FONT_SIZE)
106  srt_print(s, " size=\"%d\"", st->font_size);
107  if (c != ASS_DEFAULT_COLOR)
108  srt_print(s, " color=\"#%06x\"",
109  (c & 0xFF0000) >> 16 | c & 0xFF00 | (c & 0xFF) << 16);
110  srt_print(s, ">");
111  srt_stack_push(s, 'f');
112  }
113  if (st->bold != ASS_DEFAULT_BOLD) {
114  srt_print(s, "<b>");
115  srt_stack_push(s, 'b');
116  }
117  if (st->italic != ASS_DEFAULT_ITALIC) {
118  srt_print(s, "<i>");
119  srt_stack_push(s, 'i');
120  }
121  if (st->underline != ASS_DEFAULT_UNDERLINE) {
122  srt_print(s, "<u>");
123  srt_stack_push(s, 'u');
124  }
125  if (st->alignment != ASS_DEFAULT_ALIGNMENT) {
126  srt_print(s, "{\\an%d}", st->alignment);
127  s->alignment_applied = 1;
128  }
129  }
130 }
131 
132 
133  static av_cold int srt_encode_init(AVCodecContext *avctx)
134 {
135  SRTContext *s = avctx->priv_data;
136  s->avctx = avctx;
137  s->ass_ctx = ff_ass_split(avctx->subtitle_header);
138  av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED);
139  return s->ass_ctx ? 0 : AVERROR_INVALIDDATA;
140 }
141 
142  static void srt_text_cb(void *priv, const char *text, int len)
143 {
144  SRTContext *s = priv;
145  av_bprint_append_data(&s->buffer, text, len);
146 }
147 
148  static void srt_new_line_cb(void *priv, int forced)
149 {
150  srt_print(priv, "\r\n");
151 }
152 
153  static void srt_style_cb(void *priv, char style, int close)
154 {
155  srt_stack_push_pop(priv, style, close);
156  if (!close)
157  srt_print(priv, "<%c>", style);
158 }
159 
160  static void srt_color_cb(void *priv, unsigned int color, unsigned int color_id)
161 {
162  if (color_id > 1)
163  return;
164  srt_stack_push_pop(priv, 'f', color == 0xFFFFFFFF);
165  if (color != 0xFFFFFFFF)
166  srt_print(priv, "<font color=\"#%06x\">",
167  (color & 0xFF0000) >> 16 | color & 0xFF00 | (color & 0xFF) << 16);
168 }
169 
170  static void srt_font_name_cb(void *priv, const char *name)
171 {
172  srt_stack_push_pop(priv, 'f', !name);
173  if (name)
174  srt_print(priv, "<font face=\"%s\">", name);
175 }
176 
177  static void srt_font_size_cb(void *priv, int size)
178 {
179  srt_stack_push_pop(priv, 'f', size < 0);
180  if (size >= 0)
181  srt_print(priv, "<font size=\"%d\">", size);
182 }
183 
184  static void srt_alignment_cb(void *priv, int alignment)
185 {
186  SRTContext *s = priv;
187  if (!s->alignment_applied && alignment >= 0) {
188  srt_print(s, "{\\an%d}", alignment);
189  s->alignment_applied = 1;
190  }
191 }
192 
193  static void srt_cancel_overrides_cb(void *priv, const char *style)
194 {
195  srt_stack_push_pop(priv, 0, 1);
196  srt_style_apply(priv, style);
197 }
198 
199  static void srt_move_cb(void *priv, int x1, int y1, int x2, int y2,
200  int t1, int t2)
201 {
202  // TODO: add a AV_PKT_DATA_SUBTITLE_POSITION side data when a new subtitles
203  // encoding API passing the AVPacket is available.
204 }
205 
206  static void srt_end_cb(void *priv)
207 {
208  srt_stack_push_pop(priv, 0, 1);
209 }
210 
211  static const ASSCodesCallbacks srt_callbacks = {
212  .text = srt_text_cb,
213  .new_line = srt_new_line_cb,
214  .style = srt_style_cb,
215  .color = srt_color_cb,
216  .font_name = srt_font_name_cb,
217  .font_size = srt_font_size_cb,
218  .alignment = srt_alignment_cb,
219  .cancel_overrides = srt_cancel_overrides_cb,
220  .move = srt_move_cb,
221  .end = srt_end_cb,
222 };
223 
224  static const ASSCodesCallbacks text_callbacks = {
225  .text = srt_text_cb,
226  .new_line = srt_new_line_cb,
227 };
228 
229  static int encode_frame(AVCodecContext *avctx,
230  unsigned char *buf, int bufsize, const AVSubtitle *sub,
231  const ASSCodesCallbacks *cb)
232 {
233  SRTContext *s = avctx->priv_data;
234  ASSDialog *dialog;
235  int i;
236 
237  av_bprint_clear(&s->buffer);
238 
239  for (i=0; i<sub->num_rects; i++) {
240  const char *ass = sub->rects[i]->ass;
241 
242  if (sub->rects[i]->type != SUBTITLE_ASS) {
243  av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
244  return AVERROR(ENOSYS);
245  }
246 
247 #if FF_API_ASS_TIMING
248  if (!strncmp(ass, "Dialogue: ", 10)) {
249  int num;
250  dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num);
251  for (; dialog && num--; dialog++) {
252  s->alignment_applied = 0;
253  if (avctx->codec_id == AV_CODEC_ID_SUBRIP)
254  srt_style_apply(s, dialog->style);
255  ff_ass_split_override_codes(cb, s, dialog->text);
256  }
257  } else {
258 #endif
259  dialog = ff_ass_split_dialog2(s->ass_ctx, ass);
260  if (!dialog)
261  return AVERROR(ENOMEM);
262  s->alignment_applied = 0;
263  if (avctx->codec_id == AV_CODEC_ID_SUBRIP)
264  srt_style_apply(s, dialog->style);
265  ff_ass_split_override_codes(cb, s, dialog->text);
266  ff_ass_free_dialog(&dialog);
267 #if FF_API_ASS_TIMING
268  }
269 #endif
270  }
271 
272  if (!av_bprint_is_complete(&s->buffer))
273  return AVERROR(ENOMEM);
274  if (!s->buffer.len)
275  return 0;
276 
277  if (s->buffer.len > bufsize) {
278  av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
279  return -1;
280  }
281  memcpy(buf, s->buffer.str, s->buffer.len);
282 
283  return s->buffer.len;
284 }
285 
286  static int srt_encode_frame(AVCodecContext *avctx,
287  unsigned char *buf, int bufsize, const AVSubtitle *sub)
288 {
289  return encode_frame(avctx, buf, bufsize, sub, &srt_callbacks);
290 }
291 
292  static int text_encode_frame(AVCodecContext *avctx,
293  unsigned char *buf, int bufsize, const AVSubtitle *sub)
294 {
295  return encode_frame(avctx, buf, bufsize, sub, &text_callbacks);
296 }
297 
298  static int srt_encode_close(AVCodecContext *avctx)
299 {
300  SRTContext *s = avctx->priv_data;
301  ff_ass_split_free(s->ass_ctx);
302  av_bprint_finalize(&s->buffer, NULL);
303  return 0;
304 }
305 
306 #if CONFIG_SRT_ENCODER
307 /* deprecated encoder */
308 AVCodec ff_srt_encoder = {
309  .name = "srt",
310  .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"),
311  .type = AVMEDIA_TYPE_SUBTITLE,
312  .id = AV_CODEC_ID_SUBRIP,
313  .priv_data_size = sizeof(SRTContext),
314  .init = srt_encode_init,
315  .encode_sub = srt_encode_frame,
316  .close = srt_encode_close,
317 };
318 #endif
319 
320 #if CONFIG_SUBRIP_ENCODER
321 AVCodec ff_subrip_encoder = {
322  .name = "subrip",
323  .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"),
324  .type = AVMEDIA_TYPE_SUBTITLE,
325  .id = AV_CODEC_ID_SUBRIP,
326  .priv_data_size = sizeof(SRTContext),
327  .init = srt_encode_init,
328  .encode_sub = srt_encode_frame,
329  .close = srt_encode_close,
330 };
331 #endif
332 
333 #if CONFIG_TEXT_ENCODER
334 AVCodec ff_text_encoder = {
335  .name = "text",
336  .long_name = NULL_IF_CONFIG_SMALL("Raw text subtitle"),
337  .type = AVMEDIA_TYPE_SUBTITLE,
338  .id = AV_CODEC_ID_TEXT,
339  .priv_data_size = sizeof(SRTContext),
340  .init = srt_encode_init,
341  .encode_sub = text_encode_frame,
342  .close = srt_encode_close,
343 };
344 #endif
SRT_STACK_SIZE
#define SRT_STACK_SIZE
Definition: srtenc.c:30
ASSDialog::style
char * style
name of the ASSStyle to use with this dialog
Definition: ass_split.h:76
NULL
#define NULL
Definition: coverity.c:32
s
const char * s
Definition: avisynth_c.h:768
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
text_encode_frame
static int text_encode_frame(AVCodecContext *avctx, unsigned char *buf, int bufsize, const AVSubtitle *sub)
Definition: srtenc.c:292
ASSDialog
fields extracted from the [Events] section
Definition: ass_split.h:71
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
ff_ass_split_dialog2
ASSDialog * ff_ass_split_dialog2(ASSSplitContext *ctx, const char *buf)
Split one ASS Dialogue line from a string buffer.
Definition: ass_split.c:442
ff_ass_split
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:374
srt_callbacks
static const ASSCodesCallbacks srt_callbacks
Definition: srtenc.c:211
srt_encode_init
static av_cold int srt_encode_init(AVCodecContext *avctx)
Definition: srtenc.c:133
SRTContext
Definition: srtenc.c:32
srt_encode_frame
static int srt_encode_frame(AVCodecContext *avctx, unsigned char *buf, int bufsize, const AVSubtitle *sub)
Definition: srtenc.c:286
AVSubtitle::num_rects
unsigned num_rects
Definition: avcodec.h:3864
AVCodec
AVCodec.
Definition: avcodec.h:3408
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
AVSubtitle::rects
AVSubtitleRect ** rects
Definition: avcodec.h:3865
ASSDialog::text
char * text
actual text which will be displayed as a subtitle, can include style override control codes (see ff_a...
Definition: ass_split.h:82
ASSStyle::alignment
int alignment
position of the text (left, center, top...), defined after the layout of the numpad (1-3 sub...
Definition: ass_split.h:58
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:112
ASSSplitContext
This struct can be casted to ASS to access to the split data.
Definition: ass_split.c:197
ASS_DEFAULT_ALIGNMENT
#define ASS_DEFAULT_ALIGNMENT
Definition: ass.h:42
av_cold
#define av_cold
Definition: attributes.h:82
srt_stack_pop
static char srt_stack_pop(SRTContext *s)
Definition: srtenc.c:61
ff_ass_free_dialog
void ff_ass_free_dialog(ASSDialog **dialogp)
Free a dialogue obtained from ff_ass_split_dialog2().
Definition: ass_split.c:430
srt_font_size_cb
static void srt_font_size_cb(void *priv, int size)
Definition: srtenc.c:177
ASSStyle::bold
int bold
whether text is bold (1) or not (0)
Definition: ass_split.h:47
SRTContext::stack_ptr
int stack_ptr
Definition: srtenc.c:37
ff_ass_split_override_codes
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:492
av_bprint_append_data
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition: bprint.c:158
tag
uint32_t tag
Definition: movenc.c:1455
srt_encode_close
static int srt_encode_close(AVCodecContext *avctx)
Definition: srtenc.c:298
size
ptrdiff_t size
Definition: opengl_enc.c:101
ff_ass_split_dialog
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 an already initializ...
Definition: ass_split.c:411
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
SRTContext::alignment_applied
int alignment_applied
Definition: srtenc.c:38
SRTContext::avctx
AVCodecContext * avctx
Definition: srtenc.c:33
ASS_DEFAULT_UNDERLINE
#define ASS_DEFAULT_UNDERLINE
Definition: ass.h:41
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
AVERROR
#define AVERROR(e)
Definition: error.h:43
ASS_DEFAULT_FONT
#define ASS_DEFAULT_FONT
Definition: ass.h:35
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
t1
#define t1
Definition: regdef.h:29
ASSStyle::font_size
int font_size
font height
Definition: ass_split.h:42
AVCodec::name
const char * name
Name of the codec implementation.
Definition: avcodec.h:3415
ASS_DEFAULT_FONT_SIZE
#define ASS_DEFAULT_FONT_SIZE
Definition: ass.h:36
SRTContext::stack
char stack[SRT_STACK_SIZE]
Definition: srtenc.c:36
encode_frame
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int bufsize, const AVSubtitle *sub, const ASSCodesCallbacks *cb)
Definition: srtenc.c:229
srt_color_cb
static void srt_color_cb(void *priv, unsigned int color, unsigned int color_id)
Definition: srtenc.c:160
srt_close_tag
static void srt_close_tag(SRTContext *s, char tag)
Definition: srtenc.c:77
ASSCodesCallbacks::text
void(* text)(void *priv, const char *text, int len)
Definition: ass_split.h:159
srt_move_cb
static void srt_move_cb(void *priv, int x1, int y1, int x2, int y2, int t1, int t2)
Definition: srtenc.c:199
srt_stack_push
static int srt_stack_push(SRTContext *s, const char c)
Definition: srtenc.c:53
ASSStyle::italic
int italic
whether text is italic (1) or not (0)
Definition: ass_split.h:48
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:185
ASSCodesCallbacks
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
Definition: ass_split.h:154
srt_style_apply
static void srt_style_apply(SRTContext *s, const char *style)
Definition: srtenc.c:94
ASSStyle::primary_color
int primary_color
color that a subtitle will normally appear in
Definition: ass_split.h:43
avcodec.h
Libavcodec external API header.
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:1528
AVCodecContext
main external API structure.
Definition: avcodec.h:1518
SRTContext::ass_ctx
ASSSplitContext * ass_ctx
Definition: srtenc.c:34
ff_subrip_encoder
AVCodec ff_subrip_encoder
buf
void * buf
Definition: avisynth_c.h:690
av_vbprintf
void av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg)
Append a formatted string to a print buffer.
Definition: bprint.c:117
srt_cancel_overrides_cb
static void srt_cancel_overrides_cb(void *priv, const char *style)
Definition: srtenc.c:193
ff_srt_encoder
AVCodec ff_srt_encoder
ASSStyle::font_name
char * font_name
font face (case sensitive)
Definition: ass_split.h:41
ASSStyle
fields extracted from the [V4(+) Styles] section
Definition: ass_split.h:39
ff_ass_style_get
ASSStyle * ff_ass_style_get(ASSSplitContext *ctx, const char *style)
Find an ASSStyle structure by its name.
Definition: ass_split.c:587
srt_style_cb
static void srt_style_cb(void *priv, char style, int close)
Definition: srtenc.c:153
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
ff_text_encoder
AVCodec ff_text_encoder
srt_font_name_cb
static void srt_font_name_cb(void *priv, const char *name)
Definition: srtenc.c:170
SRTContext::buffer
AVBPrint buffer
Definition: srtenc.c:35
ASS_DEFAULT_COLOR
#define ASS_DEFAULT_COLOR
Definition: ass.h:37
AV_CODEC_ID_TEXT
raw UTF-8 text
Definition: avcodec.h:645
c
static double c[64]
Definition: vsrc_mptestsrc.c:87
srt_new_line_cb
static void srt_new_line_cb(void *priv, int forced)
Definition: srtenc.c:148
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:1545
SUBTITLE_ASS
Formatted text, the ass field must be set by the decoder and is authoritative.
Definition: avcodec.h:3820
ASS_DEFAULT_ITALIC
#define ASS_DEFAULT_ITALIC
Definition: ass.h:40
srt_stack_find
static int srt_stack_find(SRTContext *s, const char c)
Definition: srtenc.c:68
srt_print
static void srt_print(SRTContext *s, const char *str,...)
Definition: srtenc.c:45
len
int len
Definition: vorbis_enc_data.h:452
ASS_DEFAULT_BOLD
#define ASS_DEFAULT_BOLD
Definition: ass.h:39
AVSubtitleRect::ass
char * ass
0 terminated ASS/SSA compatible event line.
Definition: avcodec.h:3855
srt_alignment_cb
static void srt_alignment_cb(void *priv, int alignment)
Definition: srtenc.c:184
ff_ass_split_free
void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
Definition: ass_split.c:479
srt_text_cb
static void srt_text_cb(void *priv, const char *text, int len)
Definition: srtenc.c:142
srt_end_cb
static void srt_end_cb(void *priv)
Definition: srtenc.c:206
AVSubtitleRect::type
enum AVSubtitleType type
Definition: avcodec.h:3846
t2
#define t2
Definition: regdef.h:30
ASSStyle::underline
int underline
whether text is underlined (1) or not (0)
Definition: ass_split.h:49
srt_stack_push_pop
static void srt_stack_push_pop(SRTContext *s, const char c, int close)
Definition: srtenc.c:82
text_callbacks
static const ASSCodesCallbacks text_callbacks
Definition: srtenc.c:224
name
const char * name
Definition: opengl_enc.c:103
AVCodecContext::subtitle_header
uint8_t * subtitle_header
Header containing style information for text subtitles.
Definition: avcodec.h:2985

Generated on Sun May 13 2018 02:03:55 for FFmpeg by   doxygen 1.8.6

AltStyle によって変換されたページ (->オリジナル) /