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 int dvb_encode_rle2(uint8_t **pq, int buf_size,
41  const uint8_t *bitmap, int linesize,
42  int w, int h)
43 {
44  uint8_t *q, *line_begin;
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  // Worst case line is 3 bits per value + 4 bytes overhead
53  if (buf_size * 8 < w * 3 + 32)
55  line_begin = q;
56  *q++ = 0x10;
57  bitbuf = 0;
58  bitcnt = 6;
59 
60  x = 0;
61  while (x < w) {
62  x1 = x;
63  color = bitmap[x1++];
64  while (x1 < w && bitmap[x1] == color)
65  x1++;
66  len = x1 - x;
67  if (color == 0 && len == 2) {
68  PUTBITS2(0);
69  PUTBITS2(0);
70  PUTBITS2(1);
71  } else if (len >= 3 && len <= 10) {
72  v = len - 3;
73  PUTBITS2(0);
74  PUTBITS2((v >> 2) | 2);
75  PUTBITS2(v & 3);
76  PUTBITS2(color);
77  } else if (len >= 12 && len <= 27) {
78  v = len - 12;
79  PUTBITS2(0);
80  PUTBITS2(0);
81  PUTBITS2(2);
82  PUTBITS2(v >> 2);
83  PUTBITS2(v & 3);
84  PUTBITS2(color);
85  } else if (len >= 29) {
86  /* length = 29 ... 284 */
87  if (len > 284)
88  len = 284;
89  v = len - 29;
90  PUTBITS2(0);
91  PUTBITS2(0);
92  PUTBITS2(3);
93  PUTBITS2((v >> 6));
94  PUTBITS2((v >> 4) & 3);
95  PUTBITS2((v >> 2) & 3);
96  PUTBITS2(v & 3);
97  PUTBITS2(color);
98  } else {
99  PUTBITS2(color);
100  if (color == 0) {
101  PUTBITS2(1);
102  }
103  len = 1;
104  }
105  x += len;
106  }
107  /* end of line */
108  PUTBITS2(0);
109  PUTBITS2(0);
110  PUTBITS2(0);
111  if (bitcnt != 6) {
112  *q++ = bitbuf;
113  }
114  *q++ = 0xf0;
115  bitmap += linesize;
116  buf_size -= q - line_begin;
117  }
118  len = q - *pq;
119  *pq = q;
120  return len;
121 }
122 
123 #define PUTBITS4(val)\
124 {\
125  bitbuf |= (val) << bitcnt;\
126  bitcnt -= 4;\
127  if (bitcnt < 0) {\
128  bitcnt = 4;\
129  *q++ = bitbuf;\
130  bitbuf = 0;\
131  }\
132 }
133 
134 /* some DVB decoders only implement 4 bits/pixel */
135 static int dvb_encode_rle4(uint8_t **pq, int buf_size,
136  const uint8_t *bitmap, int linesize,
137  int w, int h)
138 {
139  uint8_t *q, *line_begin;
140  unsigned int bitbuf;
141  int bitcnt;
142  int x, y, len, x1, v, color;
143 
144  q = *pq;
145 
146  for(y = 0; y < h; y++) {
147  // Worst case line is 6 bits per value, + 4 bytes overhead
148  if (buf_size * 8 < w * 6 + 32)
150  line_begin = q;
151  *q++ = 0x11;
152  bitbuf = 0;
153  bitcnt = 4;
154 
155  x = 0;
156  while (x < w) {
157  x1 = x;
158  color = bitmap[x1++];
159  while (x1 < w && bitmap[x1] == color)
160  x1++;
161  len = x1 - x;
162  if (color == 0 && len == 2) {
163  PUTBITS4(0);
164  PUTBITS4(0xd);
165  } else if (color == 0 && (len >= 3 && len <= 9)) {
166  PUTBITS4(0);
167  PUTBITS4(len - 2);
168  } else if (len >= 4 && len <= 7) {
169  PUTBITS4(0);
170  PUTBITS4(8 + len - 4);
171  PUTBITS4(color);
172  } else if (len >= 9 && len <= 24) {
173  PUTBITS4(0);
174  PUTBITS4(0xe);
175  PUTBITS4(len - 9);
176  PUTBITS4(color);
177  } else if (len >= 25) {
178  if (len > 280)
179  len = 280;
180  v = len - 25;
181  PUTBITS4(0);
182  PUTBITS4(0xf);
183  PUTBITS4(v >> 4);
184  PUTBITS4(v & 0xf);
185  PUTBITS4(color);
186  } else {
187  PUTBITS4(color);
188  if (color == 0) {
189  PUTBITS4(0xc);
190  }
191  len = 1;
192  }
193  x += len;
194  }
195  /* end of line */
196  PUTBITS4(0);
197  PUTBITS4(0);
198  if (bitcnt != 4) {
199  *q++ = bitbuf;
200  }
201  *q++ = 0xf0;
202  bitmap += linesize;
203  buf_size -= q - line_begin;
204  }
205  len = q - *pq;
206  *pq = q;
207  return len;
208 }
209 
210 static int dvb_encode_rle8(uint8_t **pq, int buf_size,
211  const uint8_t *bitmap, int linesize,
212  int w, int h)
213 {
214  uint8_t *q, *line_begin;
215  int x, y, len, x1, color;
216 
217  q = *pq;
218 
219  for (y = 0; y < h; y++) {
220  // Worst case line is 12 bits per value, + 3 bytes overhead
221  if (buf_size * 8 < w * 12 + 24)
223  line_begin = q;
224  *q++ = 0x12;
225 
226  x = 0;
227  while (x < w) {
228  x1 = x;
229  color = bitmap[x1++];
230  while (x1 < w && bitmap[x1] == color)
231  x1++;
232  len = x1 - x;
233  if (len == 1 && color) {
234  // 00000001 to 11111111 1 pixel in colour x
235  *q++ = color;
236  } else {
237  if (color == 0x00) {
238  // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0)
239  len = FFMIN(len, 127);
240  *q++ = 0x00;
241  *q++ = len;
242  } else if (len > 2) {
243  // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2)
244  len = FFMIN(len, 127);
245  *q++ = 0x00;
246  *q++ = 0x80+len;
247  *q++ = color;
248  }
249  else if (len == 2) {
250  *q++ = color;
251  *q++ = color;
252  } else {
253  *q++ = color;
254  len = 1;
255  }
256  }
257  x += len;
258  }
259  /* end of line */
260  // 00000000 end of 8-bit/pixel_code_string
261  *q++ = 0x00;
262  *q++ = 0xf0;
263  bitmap += linesize;
264  buf_size -= q - line_begin;
265  }
266  len = q - *pq;
267  *pq = q;
268  return len;
269 }
270 
272  uint8_t *outbuf, int buf_size,
273  const AVSubtitle *h)
274 {
275  DVBSubtitleContext *s = avctx->priv_data;
276  uint8_t *q, *pseg_len;
277  int page_id, region_id, clut_id, object_id, i, bpp_index, page_state;
278 
279 
280  q = outbuf;
281 
282  page_id = 1;
283 
284  if (h->num_rects && !h->rects)
285  return AVERROR(EINVAL);
286 
287  if (avctx->width > 0 && avctx->height > 0) {
288  if (buf_size < 11)
290  /* display definition segment */
291  *q++ = 0x0f; /* sync_byte */
292  *q++ = 0x14; /* segment_type */
293  bytestream_put_be16(&q, page_id);
294  pseg_len = q;
295  q += 2; /* segment length */
296  *q++ = 0x00; /* dds version number & display window flag */
297  bytestream_put_be16(&q, avctx->width - 1); /* display width */
298  bytestream_put_be16(&q, avctx->height - 1); /* display height */
299  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
300  buf_size -= 11;
301  }
302 
303  /* page composition segment */
304 
305  if (buf_size < 8 + h->num_rects * 6)
307  *q++ = 0x0f; /* sync_byte */
308  *q++ = 0x10; /* segment_type */
309  bytestream_put_be16(&q, page_id);
310  pseg_len = q;
311  q += 2; /* segment length */
312  *q++ = 30; /* page_timeout (seconds) */
313  page_state = 2; /* mode change */
314  /* page_version = 0 + page_state */
315  *q++ = (s->object_version << 4) | (page_state << 2) | 3;
316 
317  for (region_id = 0; region_id < h->num_rects; region_id++) {
318  *q++ = region_id;
319  *q++ = 0xff; /* reserved */
320  bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */
321  bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */
322  }
323 
324  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
325  buf_size -= 8 + h->num_rects * 6;
326 
327  if (h->num_rects) {
328  for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
329  if (buf_size < 6 + h->rects[clut_id]->nb_colors * 6)
331 
332  /* CLUT segment */
333 
334  if (h->rects[clut_id]->nb_colors <= 4) {
335  /* 2 bpp, some decoders do not support it correctly */
336  bpp_index = 0;
337  } else if (h->rects[clut_id]->nb_colors <= 16) {
338  /* 4 bpp, standard encoding */
339  bpp_index = 1;
340  } else if (h->rects[clut_id]->nb_colors <= 256) {
341  /* 8 bpp, standard encoding */
342  bpp_index = 2;
343  } else {
344  return AVERROR(EINVAL);
345  }
346 
347 
348  /* CLUT segment */
349  *q++ = 0x0f; /* sync byte */
350  *q++ = 0x12; /* CLUT definition segment */
351  bytestream_put_be16(&q, page_id);
352  pseg_len = q;
353  q += 2; /* segment length */
354  *q++ = clut_id;
355  *q++ = (0 << 4) | 0xf; /* version = 0 */
356 
357  for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
358  *q++ = i; /* clut_entry_id */
359  *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
360  {
361  int a, r, g, b;
362  uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i];
363  a = (x >> 24) & 0xff;
364  r = (x >> 16) & 0xff;
365  g = (x >> 8) & 0xff;
366  b = (x >> 0) & 0xff;
367 
368  *q++ = RGB_TO_Y_CCIR(r, g, b);
369  *q++ = RGB_TO_V_CCIR(r, g, b, 0);
370  *q++ = RGB_TO_U_CCIR(r, g, b, 0);
371  *q++ = 255 - a;
372  }
373  }
374 
375  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
376  buf_size -= 6 + h->rects[clut_id]->nb_colors * 6;
377  }
378  }
379 
380  if (buf_size < h->num_rects * 22)
382  for (region_id = 0; region_id < h->num_rects; region_id++) {
383 
384  /* region composition segment */
385 
386  if (h->rects[region_id]->nb_colors <= 4) {
387  /* 2 bpp, some decoders do not support it correctly */
388  bpp_index = 0;
389  } else if (h->rects[region_id]->nb_colors <= 16) {
390  /* 4 bpp, standard encoding */
391  bpp_index = 1;
392  } else if (h->rects[region_id]->nb_colors <= 256) {
393  /* 8 bpp, standard encoding */
394  bpp_index = 2;
395  } else {
396  return AVERROR(EINVAL);
397  }
398 
399  *q++ = 0x0f; /* sync_byte */
400  *q++ = 0x11; /* segment_type */
401  bytestream_put_be16(&q, page_id);
402  pseg_len = q;
403  q += 2; /* segment length */
404  *q++ = region_id;
405  *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
406  bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
407  bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
408  *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
409  *q++ = region_id; /* clut_id == region_id */
410  *q++ = 0; /* 8 bit fill colors */
411  *q++ = 0x03; /* 4 bit and 2 bit fill colors */
412 
413  bytestream_put_be16(&q, region_id); /* object_id == region_id */
414  *q++ = (0 << 6) | (0 << 4);
415  *q++ = 0;
416  *q++ = 0xf0;
417  *q++ = 0;
418 
419  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
420  }
421  buf_size -= h->num_rects * 22;
422 
423  if (h->num_rects) {
424 
425  for (object_id = 0; object_id < h->num_rects; object_id++) {
426  int (*dvb_encode_rle)(uint8_t **pq, int buf_size,
427  const uint8_t *bitmap, int linesize,
428  int w, int h);
429 
430  if (buf_size < 13)
432 
433  /* bpp_index maths */
434  if (h->rects[object_id]->nb_colors <= 4) {
435  /* 2 bpp, some decoders do not support it correctly */
436  dvb_encode_rle = dvb_encode_rle2;
437  } else if (h->rects[object_id]->nb_colors <= 16) {
438  /* 4 bpp, standard encoding */
439  dvb_encode_rle = dvb_encode_rle4;
440  } else if (h->rects[object_id]->nb_colors <= 256) {
441  /* 8 bpp, standard encoding */
442  dvb_encode_rle = dvb_encode_rle8;
443  } else {
444  return AVERROR(EINVAL);
445  }
446 
447  /* Object Data segment */
448  *q++ = 0x0f; /* sync byte */
449  *q++ = 0x13;
450  bytestream_put_be16(&q, page_id);
451  pseg_len = q;
452  q += 2; /* segment length */
453 
454  bytestream_put_be16(&q, object_id);
455  *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
456  onject_coding_method,
457  non_modifying_color_flag */
458  {
459  uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
460  int ret;
461 
462  ptop_field_len = q;
463  q += 2;
464  pbottom_field_len = q;
465  q += 2;
466  buf_size -= 13;
467 
468  top_ptr = q;
469  ret = dvb_encode_rle(&q, buf_size,
470  h->rects[object_id]->data[0],
471  h->rects[object_id]->w * 2,
472  h->rects[object_id]->w,
473  h->rects[object_id]->h >> 1);
474  if (ret < 0)
475  return ret;
476  buf_size -= ret;
477  bottom_ptr = q;
478  ret = dvb_encode_rle(&q, buf_size,
479  h->rects[object_id]->data[0] + h->rects[object_id]->w,
480  h->rects[object_id]->w * 2,
481  h->rects[object_id]->w,
482  h->rects[object_id]->h >> 1);
483  if (ret < 0)
484  return ret;
485  buf_size -= ret;
486 
487  bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
488  bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
489  }
490 
491  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
492  }
493  }
494 
495  /* end of display set segment */
496 
497  if (buf_size < 6)
499  *q++ = 0x0f; /* sync_byte */
500  *q++ = 0x80; /* segment_type */
501  bytestream_put_be16(&q, page_id);
502  pseg_len = q;
503  q += 2; /* segment length */
504 
505  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
506  buf_size -= 6;
507 
508  s->object_version = (s->object_version + 1) & 0xf;
509  return q - outbuf;
510 }
511 
512 static int dvbsub_encode(AVCodecContext *avctx,
513  unsigned char *buf, int buf_size,
514  const AVSubtitle *sub)
515 {
516  int ret;
517 
518  ret = encode_dvb_subtitles(avctx, buf, buf_size, sub);
519  return ret;
520 }
521 
523  .name = "dvbsub",
524  .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
525  .type = AVMEDIA_TYPE_SUBTITLE,
527  .priv_data_size = sizeof(DVBSubtitleContext),
528  .encode_sub = dvbsub_encode,
529 };
int object_version
Definition: dvbsub.c:26
int x
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:2660
const char * g
Definition: vf_curves.c:115
#define PUTBITS4(val)
Definition: dvbsub.c:123
int nb_colors
number of colors in pict, undefined when pict is not set
Definition: avcodec.h:2664
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:2698
AVCodec.
Definition: codec.h:190
static int dvb_encode_rle8(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsub.c:210
AVCodec ff_dvbsub_encoder
Definition: dvbsub.c:522
AVSubtitleRect ** rects
Definition: avcodec.h:2699
int w
width of pict, undefined when pict is not set
Definition: avcodec.h:2662
uint8_t
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
static int encode_dvb_subtitles(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, const AVSubtitle *h)
Definition: dvbsub.c:271
int h
height of pict, undefined when pict is not set
Definition: avcodec.h:2663
Various defines for YUV<->RGB conversion.
int y
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:2661
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
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: codec.h:197
static int dvb_encode_rle2(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsub.c:40
#define b
Definition: input.c:41
#define FFMIN(a, b)
Definition: common.h:96
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition: error.h:51
int width
picture width / height.
Definition: avcodec.h:699
static int dvbsub_encode(AVCodecContext *avctx, unsigned char *buf, int buf_size, const AVSubtitle *sub)
Definition: dvbsub.c:512
uint8_t w
Definition: llviddspenc.c:38
#define s(width, name)
Definition: cbs_vp9.c:257
uint8_t * data[4]
data+linesize for the bitmap of this subtitle.
Definition: avcodec.h:2677
Libavcodec external API header.
main external API structure.
Definition: avcodec.h:526
#define PUTBITS2(val)
Definition: dvbsub.c:29
int
void * priv_data
Definition: avcodec.h:553
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:663
int len
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame 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.Frame references ownership and permissions
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:98
int i
Definition: input.c:407
static int dvb_encode_rle4(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsub.c:135