FFmpeg
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  DVBSubtitleContext *s = avctx->priv_data;
254  uint8_t *q, *pseg_len;
255  int page_id, region_id, clut_id, object_id, i, bpp_index, page_state;
256 
257 
258  q = outbuf;
259 
260  page_id = 1;
261 
262  if (h->num_rects && !h->rects)
263  return -1;
264 
265  if (avctx->width > 0 && avctx->height > 0) {
266  /* display definition segment */
267  *q++ = 0x0f; /* sync_byte */
268  *q++ = 0x14; /* segment_type */
269  bytestream_put_be16(&q, page_id);
270  pseg_len = q;
271  q += 2; /* segment length */
272  *q++ = 0x00; /* dds version number & display window flag */
273  bytestream_put_be16(&q, avctx->width - 1); /* display width */
274  bytestream_put_be16(&q, avctx->height - 1); /* display height */
275  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
276  }
277 
278  /* page composition segment */
279 
280  *q++ = 0x0f; /* sync_byte */
281  *q++ = 0x10; /* segment_type */
282  bytestream_put_be16(&q, page_id);
283  pseg_len = q;
284  q += 2; /* segment length */
285  *q++ = 30; /* page_timeout (seconds) */
286  page_state = 2; /* mode change */
287  /* page_version = 0 + page_state */
288  *q++ = (s->object_version << 4) | (page_state << 2) | 3;
289 
290  for (region_id = 0; region_id < h->num_rects; region_id++) {
291  *q++ = region_id;
292  *q++ = 0xff; /* reserved */
293  bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */
294  bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */
295  }
296 
297  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
298 
299  if (h->num_rects) {
300  for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
301 
302  /* CLUT segment */
303 
304  if (h->rects[clut_id]->nb_colors <= 4) {
305  /* 2 bpp, some decoders do not support it correctly */
306  bpp_index = 0;
307  } else if (h->rects[clut_id]->nb_colors <= 16) {
308  /* 4 bpp, standard encoding */
309  bpp_index = 1;
310  } else if (h->rects[clut_id]->nb_colors <= 256) {
311  /* 8 bpp, standard encoding */
312  bpp_index = 2;
313  } else {
314  return -1;
315  }
316 
317 
318  /* CLUT segment */
319  *q++ = 0x0f; /* sync byte */
320  *q++ = 0x12; /* CLUT definition segment */
321  bytestream_put_be16(&q, page_id);
322  pseg_len = q;
323  q += 2; /* segment length */
324  *q++ = clut_id;
325  *q++ = (0 << 4) | 0xf; /* version = 0 */
326 
327  for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
328  *q++ = i; /* clut_entry_id */
329  *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
330  {
331  int a, r, g, b;
332  uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i];
333  a = (x >> 24) & 0xff;
334  r = (x >> 16) & 0xff;
335  g = (x >> 8) & 0xff;
336  b = (x >> 0) & 0xff;
337 
338  *q++ = RGB_TO_Y_CCIR(r, g, b);
339  *q++ = RGB_TO_V_CCIR(r, g, b, 0);
340  *q++ = RGB_TO_U_CCIR(r, g, b, 0);
341  *q++ = 255 - a;
342  }
343  }
344 
345  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
346  }
347  }
348 
349  for (region_id = 0; region_id < h->num_rects; region_id++) {
350 
351  /* region composition segment */
352 
353  if (h->rects[region_id]->nb_colors <= 4) {
354  /* 2 bpp, some decoders do not support it correctly */
355  bpp_index = 0;
356  } else if (h->rects[region_id]->nb_colors <= 16) {
357  /* 4 bpp, standard encoding */
358  bpp_index = 1;
359  } else if (h->rects[region_id]->nb_colors <= 256) {
360  /* 8 bpp, standard encoding */
361  bpp_index = 2;
362  } else {
363  return -1;
364  }
365 
366  *q++ = 0x0f; /* sync_byte */
367  *q++ = 0x11; /* segment_type */
368  bytestream_put_be16(&q, page_id);
369  pseg_len = q;
370  q += 2; /* segment length */
371  *q++ = region_id;
372  *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
373  bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
374  bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
375  *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
376  *q++ = region_id; /* clut_id == region_id */
377  *q++ = 0; /* 8 bit fill colors */
378  *q++ = 0x03; /* 4 bit and 2 bit fill colors */
379 
380  bytestream_put_be16(&q, region_id); /* object_id == region_id */
381  *q++ = (0 << 6) | (0 << 4);
382  *q++ = 0;
383  *q++ = 0xf0;
384  *q++ = 0;
385 
386  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
387  }
388 
389  if (h->num_rects) {
390 
391  for (object_id = 0; object_id < h->num_rects; object_id++) {
392  void (*dvb_encode_rle)(uint8_t **pq,
393  const uint8_t *bitmap, int linesize,
394  int w, int h);
395 
396  /* bpp_index maths */
397  if (h->rects[object_id]->nb_colors <= 4) {
398  /* 2 bpp, some decoders do not support it correctly */
399  dvb_encode_rle = dvb_encode_rle2;
400  } else if (h->rects[object_id]->nb_colors <= 16) {
401  /* 4 bpp, standard encoding */
402  dvb_encode_rle = dvb_encode_rle4;
403  } else if (h->rects[object_id]->nb_colors <= 256) {
404  /* 8 bpp, standard encoding */
405  dvb_encode_rle = dvb_encode_rle8;
406  } else {
407  return -1;
408  }
409 
410  /* Object Data segment */
411  *q++ = 0x0f; /* sync byte */
412  *q++ = 0x13;
413  bytestream_put_be16(&q, page_id);
414  pseg_len = q;
415  q += 2; /* segment length */
416 
417  bytestream_put_be16(&q, object_id);
418  *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
419  onject_coding_method,
420  non_modifying_color_flag */
421  {
422  uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
423 
424  ptop_field_len = q;
425  q += 2;
426  pbottom_field_len = q;
427  q += 2;
428 
429  top_ptr = q;
430  dvb_encode_rle(&q, h->rects[object_id]->data[0], h->rects[object_id]->w * 2,
431  h->rects[object_id]->w, h->rects[object_id]->h >> 1);
432  bottom_ptr = q;
433  dvb_encode_rle(&q, h->rects[object_id]->data[0] + h->rects[object_id]->w,
434  h->rects[object_id]->w * 2, h->rects[object_id]->w,
435  h->rects[object_id]->h >> 1);
436 
437  bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
438  bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
439  }
440 
441  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
442  }
443  }
444 
445  /* end of display set segment */
446 
447  *q++ = 0x0f; /* sync_byte */
448  *q++ = 0x80; /* segment_type */
449  bytestream_put_be16(&q, page_id);
450  pseg_len = q;
451  q += 2; /* segment length */
452 
453  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
454 
455  s->object_version = (s->object_version + 1) & 0xf;
456  return q - outbuf;
457 }
458 
459 static int dvbsub_encode(AVCodecContext *avctx,
460  unsigned char *buf, int buf_size,
461  const AVSubtitle *sub)
462 {
463  int ret;
464 
465  ret = encode_dvb_subtitles(avctx, buf, sub);
466  return ret;
467 }
468 
470  .name = "dvbsub",
471  .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
472  .type = AVMEDIA_TYPE_SUBTITLE,
474  .priv_data_size = sizeof(DVBSubtitleContext),
475  .encode_sub = dvbsub_encode,
476 };
int object_version
Definition: dvbsub.c:26
int x
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:3902
const char * g
Definition: vf_curves.c:115
#define PUTBITS4(val)
Definition: dvbsub.c:116
int nb_colors
number of colors in pict, undefined when pict is not set
Definition: avcodec.h:3906
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:36
unsigned num_rects
Definition: avcodec.h:3940
AVCodec.
Definition: avcodec.h:3484
AVCodec ff_dvbsub_encoder
Definition: dvbsub.c:469
AVSubtitleRect ** rects
Definition: avcodec.h:3941
int w
width of pict, undefined when pict is not set
Definition: avcodec.h:3904
uint8_t
static int encode_dvb_subtitles(AVCodecContext *avctx, uint8_t *outbuf, const AVSubtitle *h)
Definition: dvbsub.c:250
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
int h
height of pict, undefined when pict is not set
Definition: avcodec.h:3905
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
Various defines for YUV<->RGB conversion.
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:3903
#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:114
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:102
const char * name
Name of the codec implementation.
Definition: avcodec.h:3491
#define b
Definition: input.c:41
#define FFMIN(a, b)
Definition: common.h:96
int width
picture width / height.
Definition: avcodec.h:1741
static int dvbsub_encode(AVCodecContext *avctx, unsigned char *buf, int buf_size, const AVSubtitle *sub)
Definition: dvbsub.c:459
uint8_t w
Definition: llviddspenc.c:38
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
#define s(width, name)
Definition: cbs_vp9.c:257
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:3919
Libavcodec external API header.
main external API structure.
Definition: avcodec.h:1568
void * buf
Definition: avisynth_c.h:766
#define PUTBITS2(val)
Definition: dvbsub.c:29
void * priv_data
Definition: avcodec.h:1595
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:664
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
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:98