FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
movtextdec.c
Go to the documentation of this file.
1 /*
2  * 3GPP TS 26.245 Timed Text decoder
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 "avcodec.h"
23 #include "ass.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/common.h"
26 #include "libavutil/bprint.h"
27 #include "libavutil/intreadwrite.h"
28 #include "libavutil/mem.h"
29 
30 #define STYLE_FLAG_BOLD 1
31 #define STYLE_FLAG_ITALIC 2
32 #define STYLE_FLAG_UNDERLINE 4
33 
34 static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end,
35  char **style_start, char **style_end,
36  uint8_t **style_flags, int style_entries)
37 {
38  int i = 0;
39  while (text < text_end) {
40  for (i = 0; i < style_entries; i++) {
41  if (*style_flags[i] && text == style_start[i]) {
42  if (*style_flags[i] & STYLE_FLAG_BOLD)
43  av_bprintf(buf, "{\\b1}");
44  if (*style_flags[i] & STYLE_FLAG_ITALIC)
45  av_bprintf(buf, "{\\i1}");
46  if (*style_flags[i] & STYLE_FLAG_UNDERLINE)
47  av_bprintf(buf, "{\\u1}");
48  }
49  }
50 
51  switch (*text) {
52  case '\r':
53  break;
54  case '\n':
55  av_bprintf(buf, "\\N");
56  break;
57  default:
58  av_bprint_chars(buf, *text, 1);
59  break;
60  }
61 
62  for (i = 0; i < style_entries; i++) {
63  if (*style_flags[i] && text == style_end[i]) {
64  if (*style_flags[i] & STYLE_FLAG_BOLD)
65  av_bprintf(buf, "{\\b0}");
66  if (*style_flags[i] & STYLE_FLAG_ITALIC)
67  av_bprintf(buf, "{\\i0}");
68  if (*style_flags[i] & STYLE_FLAG_UNDERLINE)
69  av_bprintf(buf, "{\\u0}");
70  }
71  }
72  text++;
73  }
74 
75  return 0;
76 }
77 
78 static int mov_text_init(AVCodecContext *avctx) {
79  /*
80  * TODO: Handle the default text style.
81  * NB: Most players ignore styles completely, with the result that
82  * it's very common to find files where the default style is broken
83  * and respecting it results in a worse experience than ignoring it.
84  */
85  return ff_ass_subtitle_header_default(avctx);
86 }
87 
89  void *data, int *got_sub_ptr, AVPacket *avpkt)
90 {
91  AVSubtitle *sub = data;
92  int ret, ts_start, ts_end;
93  AVBPrint buf;
94  char *ptr = avpkt->data;
95  char *end;
96  //char *ptr_temp;
97  int text_length, tsmb_type, style_entries;
98  uint64_t tsmb_size, tracksize;
99  char **style_start = { 0, };
100  char **style_end = { 0, };
101  uint8_t **style_flags = { 0, };
102  const uint8_t *tsmb;
103  int index, i, size_var;
104  uint8_t *flag;
105  char *style_pos;
106 
107  if (!ptr || avpkt->size < 2)
108  return AVERROR_INVALIDDATA;
109 
110  /*
111  * A packet of size two with value zero is an empty subtitle
112  * used to mark the end of the previous non-empty subtitle.
113  * We can just drop them here as we have duration information
114  * already. If the value is non-zero, then it's technically a
115  * bad packet.
116  */
117  if (avpkt->size == 2)
118  return AV_RB16(ptr) == 0 ? 0 : AVERROR_INVALIDDATA;
119 
120  /*
121  * The first two bytes of the packet are the length of the text string
122  * In complex cases, there are style descriptors appended to the string
123  * so we can't just assume the packet size is the string size.
124  */
125  text_length = AV_RB16(ptr);
126  end = ptr + FFMIN(2 + text_length, avpkt->size);
127  ptr += 2;
128 
129  ts_start = av_rescale_q(avpkt->pts,
130  avctx->time_base,
131  (AVRational){1,100});
132  ts_end = av_rescale_q(avpkt->pts + avpkt->duration,
133  avctx->time_base,
134  (AVRational){1,100});
135 
136  tsmb_size = 0;
137  tracksize = 2 + text_length;
138  // Note that the spec recommends lines be no longer than 2048 characters.
140  if (text_length + 2 != avpkt->size) {
141  while (tracksize + 8 <= avpkt->size) {
142  // A box is a minimum of 8 bytes.
143  tsmb = ptr + tracksize - 2;
144  tsmb_size = AV_RB32(tsmb);
145  tsmb += 4;
146  tsmb_type = AV_RB32(tsmb);
147  tsmb += 4;
148 
149  if (tsmb_size == 1) {
150  if (tracksize + 16 > avpkt->size)
151  break;
152  tsmb_size = AV_RB64(tsmb);
153  tsmb += 8;
154  size_var = 18;
155  } else
156  size_var = 10;
157  //size_var is equal to 10 or 18 depending on the size of box
158 
159  if (tracksize + tsmb_size > avpkt->size)
160  break;
161 
162  if (tsmb_type == MKBETAG('s','t','y','l')) {
163  if (tracksize + size_var > avpkt->size)
164  break;
165  style_entries = AV_RB16(tsmb);
166  tsmb += 2;
167 
168  // A single style record is of length 12 bytes.
169  if (tracksize + size_var + style_entries * 12 > avpkt->size)
170  break;
171 
172  for(i = 0; i < style_entries; i++) {
173  style_pos = ptr + AV_RB16(tsmb);
174  index = i;
175  av_dynarray_add(&style_start, &index, style_pos);
176  tsmb += 2;
177  style_pos = ptr + AV_RB16(tsmb);
178  index = i;
179  av_dynarray_add(&style_end, &index, style_pos);
180  tsmb += 2;
181  // fontID = AV_RB16(tsmb);
182  tsmb += 2;
183  flag = av_malloc(1);
184  if (!flag)
185  return AVERROR(ENOMEM);
186  *flag = AV_RB8(tsmb);
187  index = i;
188  av_dynarray_add(&style_flags, &index, flag);
189  //fontsize=AV_RB8(tsmb);
190  tsmb += 2;
191  // text-color-rgba
192  tsmb += 4;
193  }
194  text_to_ass(&buf, ptr, end, style_start, style_end, style_flags, style_entries);
195 
196  for(i = 0; i < style_entries; i++) {
197  av_freep(&style_flags[i]);
198  }
199  av_freep(&style_start);
200  av_freep(&style_end);
201  av_freep(&style_flags);
202  }
203  tracksize = tracksize + tsmb_size;
204  }
205  } else
206  text_to_ass(&buf, ptr, end, NULL, NULL, 0, 0);
207 
208  ret = ff_ass_add_rect_bprint(sub, &buf, ts_start, ts_end - ts_start);
210  if (ret < 0)
211  return ret;
212  *got_sub_ptr = sub->num_rects > 0;
213  return avpkt->size;
214 }
215 
217  .name = "mov_text",
218  .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
219  .type = AVMEDIA_TYPE_SUBTITLE,
220  .id = AV_CODEC_ID_MOV_TEXT,
221  .init = mov_text_init,
222  .decode = mov_text_decode_frame,
223 };
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
memory handling functions
int size
Definition: avcodec.h:1163
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:85
AVCodec.
Definition: avcodec.h:3181
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1369
uint8_t
#define av_malloc(s)
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:67
int ff_ass_subtitle_header_default(AVCodecContext *avctx)
Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS with default style.
Definition: ass.c:80
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:85
static int mov_text_init(AVCodecContext *avctx)
Definition: movtextdec.c:78
uint8_t * data
Definition: avcodec.h:1162
#define STYLE_FLAG_UNDERLINE
Definition: movtextdec.c:32
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:140
#define AV_BPRINT_SIZE_UNLIMITED
#define AVERROR(e)
Definition: error.h:43
static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, char **style_start, char **style_end, uint8_t **style_flags, int style_entries)
Definition: movtextdec.c:34
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:175
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
const char * name
Name of the codec implementation.
Definition: avcodec.h:3188
void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
Definition: mem.c:322
Libavcodec external API header.
#define STYLE_FLAG_ITALIC
Definition: movtextdec.c:31
#define FFMIN(a, b)
Definition: common.h:66
ret
Definition: avfilter.c:974
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_WB16 unsigned int_TMPL AV_RB8
Definition: bytestream.h:85
int ff_ass_add_rect_bprint(AVSubtitle *sub, AVBPrint *buf, int ts_start, int duration)
Same as ff_ass_add_rect_bprint, but taking an AVBPrint buffer instead of a string, and assuming raw=0.
Definition: ass.c:178
main external API structure.
Definition: avcodec.h:1241
void * buf
Definition: avisynth_c.h:553
int index
Definition: gxfenc.c:89
rational number numerator/denominator
Definition: rational.h:43
#define STYLE_FLAG_BOLD
Definition: movtextdec.c:30
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_RB64
Definition: bytestream.h:85
common internal and external API header
AVCodec ff_movtext_decoder
Definition: movtextdec.c:216
#define MKBETAG(a, b, c, d)
Definition: common.h:316
#define av_freep(p)
static int mov_text_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *avpkt)
Definition: movtextdec.c:88
This structure stores compressed data.
Definition: avcodec.h:1139
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1155
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition: bprint.c:140