FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dvbsub.c
Go to the documentation of this file.
1 /*
2  * DVB subtitle encoding
3  * Copyright (c) 2005 Fabrice Bellard
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 #include "avcodec.h"
22 #include "bytestream.h"
23 #include "libavutil/colorspace.h"
24 
25 typedef struct DVBSubtitleContext {
28 
29 #define PUTBITS2(val)\
30 {\
31  bitbuf |= (val) << bitcnt;\
32  bitcnt -= 2;\
33  if (bitcnt < 0) {\
34  bitcnt = 6;\
35  *q++ = bitbuf;\
36  bitbuf = 0;\
37  }\
38 }
39 
40 static void dvb_encode_rle2(uint8_t **pq,
41  const uint8_t *bitmap, int linesize,
42  int w, int h)
43 {
44  uint8_t *q;
45  unsigned int bitbuf;
46  int bitcnt;
47  int x, y, len, x1, v, color;
48 
49  q = *pq;
50 
51  for(y = 0; y < h; y++) {
52  *q++ = 0x10;
53  bitbuf = 0;
54  bitcnt = 6;
55 
56  x = 0;
57  while (x < w) {
58  x1 = x;
59  color = bitmap[x1++];
60  while (x1 < w && bitmap[x1] == color)
61  x1++;
62  len = x1 - x;
63  if (color == 0 && len == 2) {
64  PUTBITS2(0);
65  PUTBITS2(0);
66  PUTBITS2(1);
67  } else if (len >= 3 && len <= 10) {
68  v = len - 3;
69  PUTBITS2(0);
70  PUTBITS2((v >> 2) | 2);
71  PUTBITS2(v & 3);
72  PUTBITS2(color);
73  } else if (len >= 12 && len <= 27) {
74  v = len - 12;
75  PUTBITS2(0);
76  PUTBITS2(0);
77  PUTBITS2(2);
78  PUTBITS2(v >> 2);
79  PUTBITS2(v & 3);
80  PUTBITS2(color);
81  } else if (len >= 29) {
82  /* length = 29 ... 284 */
83  if (len > 284)
84  len = 284;
85  v = len - 29;
86  PUTBITS2(0);
87  PUTBITS2(0);
88  PUTBITS2(3);
89  PUTBITS2((v >> 6));
90  PUTBITS2((v >> 4) & 3);
91  PUTBITS2((v >> 2) & 3);
92  PUTBITS2(v & 3);
93  PUTBITS2(color);
94  } else {
95  PUTBITS2(color);
96  if (color == 0) {
97  PUTBITS2(1);
98  }
99  len = 1;
100  }
101  x += len;
102  }
103  /* end of line */
104  PUTBITS2(0);
105  PUTBITS2(0);
106  PUTBITS2(0);
107  if (bitcnt != 6) {
108  *q++ = bitbuf;
109  }
110  *q++ = 0xf0;
111  bitmap += linesize;
112  }
113  *pq = q;
114 }
115 
116 #define PUTBITS4(val)\
117 {\
118  bitbuf |= (val) << bitcnt;\
119  bitcnt -= 4;\
120  if (bitcnt < 0) {\
121  bitcnt = 4;\
122  *q++ = bitbuf;\
123  bitbuf = 0;\
124  }\
125 }
126 
127 /* some DVB decoders only implement 4 bits/pixel */
128 static void dvb_encode_rle4(uint8_t **pq,
129  const uint8_t *bitmap, int linesize,
130  int w, int h)
131 {
132  uint8_t *q;
133  unsigned int bitbuf;
134  int bitcnt;
135  int x, y, len, x1, v, color;
136 
137  q = *pq;
138 
139  for(y = 0; y < h; y++) {
140  *q++ = 0x11;
141  bitbuf = 0;
142  bitcnt = 4;
143 
144  x = 0;
145  while (x < w) {
146  x1 = x;
147  color = bitmap[x1++];
148  while (x1 < w && bitmap[x1] == color)
149  x1++;
150  len = x1 - x;
151  if (color == 0 && len == 2) {
152  PUTBITS4(0);
153  PUTBITS4(0xd);
154  } else if (color == 0 && (len >= 3 && len <= 9)) {
155  PUTBITS4(0);
156  PUTBITS4(len - 2);
157  } else if (len >= 4 && len <= 7) {
158  PUTBITS4(0);
159  PUTBITS4(8 + len - 4);
160  PUTBITS4(color);
161  } else if (len >= 9 && len <= 24) {
162  PUTBITS4(0);
163  PUTBITS4(0xe);
164  PUTBITS4(len - 9);
165  PUTBITS4(color);
166  } else if (len >= 25) {
167  if (len > 280)
168  len = 280;
169  v = len - 25;
170  PUTBITS4(0);
171  PUTBITS4(0xf);
172  PUTBITS4(v >> 4);
173  PUTBITS4(v & 0xf);
174  PUTBITS4(color);
175  } else {
176  PUTBITS4(color);
177  if (color == 0) {
178  PUTBITS4(0xc);
179  }
180  len = 1;
181  }
182  x += len;
183  }
184  /* end of line */
185  PUTBITS4(0);
186  PUTBITS4(0);
187  if (bitcnt != 4) {
188  *q++ = bitbuf;
189  }
190  *q++ = 0xf0;
191  bitmap += linesize;
192  }
193  *pq = q;
194 }
195 
196 static void dvb_encode_rle8(uint8_t **pq,
197  const uint8_t *bitmap, int linesize,
198  int w, int h)
199 {
200  uint8_t *q;
201  int x, y, len, x1, color;
202 
203  q = *pq;
204 
205  for (y = 0; y < h; y++) {
206  *q++ = 0x12;
207 
208  x = 0;
209  while (x < w) {
210  x1 = x;
211  color = bitmap[x1++];
212  while (x1 < w && bitmap[x1] == color)
213  x1++;
214  len = x1 - x;
215  if (len == 1 && color) {
216  // 00000001 to 11111111 1 pixel in colour x
217  *q++ = color;
218  } else {
219  if (color == 0x00) {
220  // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0)
221  len = FFMIN(len, 127);
222  *q++ = 0x00;
223  *q++ = len;
224  } else if (len > 2) {
225  // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2)
226  len = FFMIN(len, 127);
227  *q++ = 0x00;
228  *q++ = 0x80+len;
229  *q++ = color;
230  }
231  else if (len == 2) {
232  *q++ = color;
233  *q++ = color;
234  } else {
235  *q++ = color;
236  len = 1;
237  }
238  }
239  x += len;
240  }
241  /* end of line */
242  // 00000000 end of 8-bit/pixel_code_string
243  *q++ = 0x00;
244  *q++ = 0xf0;
245  bitmap += linesize;
246  }
247  *pq = q;
248 }
249 
251  uint8_t *outbuf, const AVSubtitle *h)
252 {
253  uint8_t *q, *pseg_len;
254  int page_id, region_id, clut_id, object_id, i, bpp_index, page_state;
255 
256 
257  q = outbuf;
258 
259  page_id = 1;
260 
261  if (h->num_rects && !h->rects)
262  return -1;
263 
264  /* page composition segment */
265 
266  *q++ = 0x0f; /* sync_byte */
267  *q++ = 0x10; /* segment_type */
268  bytestream_put_be16(&q, page_id);
269  pseg_len = q;
270  q += 2; /* segment length */
271  *q++ = 30; /* page_timeout (seconds) */
272  page_state = 2; /* mode change */
273  /* page_version = 0 + page_state */
274  *q++ = (s->object_version << 4) | (page_state << 2) | 3;
275 
276  for (region_id = 0; region_id < h->num_rects; region_id++) {
277  *q++ = region_id;
278  *q++ = 0xff; /* reserved */
279  bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */
280  bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */
281  }
282 
283  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
284 
285  if (h->num_rects) {
286  for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
287 
288  /* CLUT segment */
289 
290  if (h->rects[clut_id]->nb_colors <= 4) {
291  /* 2 bpp, some decoders do not support it correctly */
292  bpp_index = 0;
293  } else if (h->rects[clut_id]->nb_colors <= 16) {
294  /* 4 bpp, standard encoding */
295  bpp_index = 1;
296  } else if (h->rects[clut_id]->nb_colors <= 256) {
297  /* 8 bpp, standard encoding */
298  bpp_index = 2;
299  } else {
300  return -1;
301  }
302 
303 
304  /* CLUT segment */
305  *q++ = 0x0f; /* sync byte */
306  *q++ = 0x12; /* CLUT definition segment */
307  bytestream_put_be16(&q, page_id);
308  pseg_len = q;
309  q += 2; /* segment length */
310  *q++ = clut_id;
311  *q++ = (0 << 4) | 0xf; /* version = 0 */
312 
313  for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
314  *q++ = i; /* clut_entry_id */
315  *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
316  {
317  int a, r, g, b;
318  uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i];
319  a = (x >> 24) & 0xff;
320  r = (x >> 16) & 0xff;
321  g = (x >> 8) & 0xff;
322  b = (x >> 0) & 0xff;
323 
324  *q++ = RGB_TO_Y_CCIR(r, g, b);
325  *q++ = RGB_TO_V_CCIR(r, g, b, 0);
326  *q++ = RGB_TO_U_CCIR(r, g, b, 0);
327  *q++ = 255 - a;
328  }
329  }
330 
331  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
332  }
333  }
334 
335  for (region_id = 0; region_id < h->num_rects; region_id++) {
336 
337  /* region composition segment */
338 
339  if (h->rects[region_id]->nb_colors <= 4) {
340  /* 2 bpp, some decoders do not support it correctly */
341  bpp_index = 0;
342  } else if (h->rects[region_id]->nb_colors <= 16) {
343  /* 4 bpp, standard encoding */
344  bpp_index = 1;
345  } else if (h->rects[region_id]->nb_colors <= 256) {
346  /* 8 bpp, standard encoding */
347  bpp_index = 2;
348  } else {
349  return -1;
350  }
351 
352  *q++ = 0x0f; /* sync_byte */
353  *q++ = 0x11; /* segment_type */
354  bytestream_put_be16(&q, page_id);
355  pseg_len = q;
356  q += 2; /* segment length */
357  *q++ = region_id;
358  *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
359  bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
360  bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
361  *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
362  *q++ = region_id; /* clut_id == region_id */
363  *q++ = 0; /* 8 bit fill colors */
364  *q++ = 0x03; /* 4 bit and 2 bit fill colors */
365 
366  bytestream_put_be16(&q, region_id); /* object_id == region_id */
367  *q++ = (0 << 6) | (0 << 4);
368  *q++ = 0;
369  *q++ = 0xf0;
370  *q++ = 0;
371 
372  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
373  }
374 
375  if (h->num_rects) {
376 
377  for (object_id = 0; object_id < h->num_rects; object_id++) {
378  void (*dvb_encode_rle)(uint8_t **pq,
379  const uint8_t *bitmap, int linesize,
380  int w, int h);
381 
382  /* bpp_index maths */
383  if (h->rects[object_id]->nb_colors <= 4) {
384  /* 2 bpp, some decoders do not support it correctly */
385  dvb_encode_rle = dvb_encode_rle2;
386  } else if (h->rects[object_id]->nb_colors <= 16) {
387  /* 4 bpp, standard encoding */
388  dvb_encode_rle = dvb_encode_rle4;
389  } else if (h->rects[object_id]->nb_colors <= 256) {
390  /* 8 bpp, standard encoding */
391  dvb_encode_rle = dvb_encode_rle8;
392  } else {
393  return -1;
394  }
395 
396  /* Object Data segment */
397  *q++ = 0x0f; /* sync byte */
398  *q++ = 0x13;
399  bytestream_put_be16(&q, page_id);
400  pseg_len = q;
401  q += 2; /* segment length */
402 
403  bytestream_put_be16(&q, object_id);
404  *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
405  onject_coding_method,
406  non_modifying_color_flag */
407  {
408  uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
409 
410  ptop_field_len = q;
411  q += 2;
412  pbottom_field_len = q;
413  q += 2;
414 
415  top_ptr = q;
416  dvb_encode_rle(&q, h->rects[object_id]->data[0], h->rects[object_id]->w * 2,
417  h->rects[object_id]->w, h->rects[object_id]->h >> 1);
418  bottom_ptr = q;
419  dvb_encode_rle(&q, h->rects[object_id]->data[0] + h->rects[object_id]->w,
420  h->rects[object_id]->w * 2, h->rects[object_id]->w,
421  h->rects[object_id]->h >> 1);
422 
423  bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
424  bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
425  }
426 
427  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
428  }
429  }
430 
431  /* end of display set segment */
432 
433  *q++ = 0x0f; /* sync_byte */
434  *q++ = 0x80; /* segment_type */
435  bytestream_put_be16(&q, page_id);
436  pseg_len = q;
437  q += 2; /* segment length */
438 
439  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
440 
441  s->object_version = (s->object_version + 1) & 0xf;
442  return q - outbuf;
443 }
444 
445 static int dvbsub_encode(AVCodecContext *avctx,
446  unsigned char *buf, int buf_size,
447  const AVSubtitle *sub)
448 {
449  DVBSubtitleContext *s = avctx->priv_data;
450  int ret;
451 
452  ret = encode_dvb_subtitles(s, buf, sub);
453  return ret;
454 }
455 
457  .name = "dvbsub",
458  .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
459  .type = AVMEDIA_TYPE_SUBTITLE,
461  .priv_data_size = sizeof(DVBSubtitleContext),
462  .encode_sub = dvbsub_encode,
463 };
int object_version
Definition: dvbsub.c:26
const char * s
Definition: avisynth_c.h:768
int x
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3754
const char * g
Definition: vf_curves.c:112
#define PUTBITS4(val)
Definition: dvbsub.c:116
int nb_colors
number of colors in pict, undefined when pict is not set
Definition: avcodec.h:3758
const char * b
Definition: vf_curves.c:113
Various defines for YUV<->RGB conversion.
unsigned num_rects
Definition: avcodec.h:3792
AVCodec.
Definition: avcodec.h:3351
static int encode_dvb_subtitles(DVBSubtitleContext *s, uint8_t *outbuf, const AVSubtitle *h)
Definition: dvbsub.c:250
AVCodec ff_dvbsub_encoder
Definition: dvbsub.c:456
AVSubtitleRect ** rects
Definition: avcodec.h:3793
int w
width of pict, undefined when pict is not set
Definition: avcodec.h:3756
uint8_t
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
int h
height of pict, undefined when pict is not set
Definition: avcodec.h:3757
static void dvb_encode_rle4(uint8_t **pq, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsub.c:128
int y
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3755
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
const char * r
Definition: vf_curves.c:111
const char * name
Name of the codec implementation.
Definition: avcodec.h:3358
#define FFMIN(a, b)
Definition: common.h:96
static int dvbsub_encode(AVCodecContext *avctx, unsigned char *buf, int buf_size, const AVSubtitle *sub)
Definition: dvbsub.c:445
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:3771
Libavcodec external API header.
main external API structure.
Definition: avcodec.h:1488
void * buf
Definition: avisynth_c.h:690
#define PUTBITS2(val)
Definition: dvbsub.c:29
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:102
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
void * priv_data
Definition: avcodec.h:1515
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:98
static void dvb_encode_rle8(uint8_t **pq, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsub.c:196
static void dvb_encode_rle2(uint8_t **pq, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsub.c:40
int len