FFmpeg
dvbsubenc.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 
271 static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size,
272  const AVSubtitle *h)
273 {
274  DVBSubtitleContext *s = avctx->priv_data;
275  uint8_t *q, *pseg_len;
276  int page_id, region_id, clut_id, object_id, i, bpp_index, page_state;
277 
278 
279  q = outbuf;
280 
281  page_id = 1;
282 
283  if (h->num_rects && !h->rects)
284  return AVERROR(EINVAL);
285 
286  if (avctx->width > 0 && avctx->height > 0) {
287  if (buf_size < 11)
289  /* display definition segment */
290  *q++ = 0x0f; /* sync_byte */
291  *q++ = 0x14; /* segment_type */
292  bytestream_put_be16(&q, page_id);
293  pseg_len = q;
294  q += 2; /* segment length */
295  *q++ = 0x00; /* dds version number & display window flag */
296  bytestream_put_be16(&q, avctx->width - 1); /* display width */
297  bytestream_put_be16(&q, avctx->height - 1); /* display height */
298  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
299  buf_size -= 11;
300  }
301 
302  /* page composition segment */
303 
304  if (buf_size < 8 + h->num_rects * 6)
306  *q++ = 0x0f; /* sync_byte */
307  *q++ = 0x10; /* segment_type */
308  bytestream_put_be16(&q, page_id);
309  pseg_len = q;
310  q += 2; /* segment length */
311  *q++ = 30; /* page_timeout (seconds) */
312  page_state = 2; /* mode change */
313  /* page_version = 0 + page_state */
314  *q++ = (s->object_version << 4) | (page_state << 2) | 3;
315 
316  for (region_id = 0; region_id < h->num_rects; region_id++) {
317  *q++ = region_id;
318  *q++ = 0xff; /* reserved */
319  bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */
320  bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */
321  }
322 
323  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
324  buf_size -= 8 + h->num_rects * 6;
325 
326  if (h->num_rects) {
327  for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
328  if (buf_size < 6 + h->rects[clut_id]->nb_colors * 6)
330 
331  /* CLUT segment */
332 
333  if (h->rects[clut_id]->nb_colors <= 4) {
334  /* 2 bpp, some decoders do not support it correctly */
335  bpp_index = 0;
336  } else if (h->rects[clut_id]->nb_colors <= 16) {
337  /* 4 bpp, standard encoding */
338  bpp_index = 1;
339  } else if (h->rects[clut_id]->nb_colors <= 256) {
340  /* 8 bpp, standard encoding */
341  bpp_index = 2;
342  } else {
343  return AVERROR(EINVAL);
344  }
345 
346 
347  /* CLUT segment */
348  *q++ = 0x0f; /* sync byte */
349  *q++ = 0x12; /* CLUT definition segment */
350  bytestream_put_be16(&q, page_id);
351  pseg_len = q;
352  q += 2; /* segment length */
353  *q++ = clut_id;
354  *q++ = (0 << 4) | 0xf; /* version = 0 */
355 
356  for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
357  *q++ = i; /* clut_entry_id */
358  *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
359  {
360  int a, r, g, b;
361  uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i];
362  a = (x >> 24) & 0xff;
363  r = (x >> 16) & 0xff;
364  g = (x >> 8) & 0xff;
365  b = (x >> 0) & 0xff;
366 
367  *q++ = RGB_TO_Y_CCIR(r, g, b);
368  *q++ = RGB_TO_V_CCIR(r, g, b, 0);
369  *q++ = RGB_TO_U_CCIR(r, g, b, 0);
370  *q++ = 255 - a;
371  }
372  }
373 
374  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
375  buf_size -= 6 + h->rects[clut_id]->nb_colors * 6;
376  }
377 
378  if (buf_size < h->num_rects * 22)
380  for (region_id = 0; region_id < h->num_rects; region_id++) {
381 
382  /* region composition segment */
383 
384  if (h->rects[region_id]->nb_colors <= 4) {
385  /* 2 bpp, some decoders do not support it correctly */
386  bpp_index = 0;
387  } else if (h->rects[region_id]->nb_colors <= 16) {
388  /* 4 bpp, standard encoding */
389  bpp_index = 1;
390  } else if (h->rects[region_id]->nb_colors <= 256) {
391  /* 8 bpp, standard encoding */
392  bpp_index = 2;
393  } else {
394  return AVERROR(EINVAL);
395  }
396 
397  *q++ = 0x0f; /* sync_byte */
398  *q++ = 0x11; /* segment_type */
399  bytestream_put_be16(&q, page_id);
400  pseg_len = q;
401  q += 2; /* segment length */
402  *q++ = region_id;
403  *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
404  bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
405  bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
406  *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
407  *q++ = region_id; /* clut_id == region_id */
408  *q++ = 0; /* 8 bit fill colors */
409  *q++ = 0x03; /* 4 bit and 2 bit fill colors */
410 
411  bytestream_put_be16(&q, region_id); /* object_id == region_id */
412  *q++ = (0 << 6) | (0 << 4);
413  *q++ = 0;
414  *q++ = 0xf0;
415  *q++ = 0;
416 
417  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
418  }
419  buf_size -= h->num_rects * 22;
420 
421  for (object_id = 0; object_id < h->num_rects; object_id++) {
422  int (*dvb_encode_rle)(uint8_t **pq, int buf_size,
423  const uint8_t *bitmap, int linesize,
424  int w, int h);
425 
426  if (buf_size < 13)
428 
429  /* bpp_index maths */
430  if (h->rects[object_id]->nb_colors <= 4) {
431  /* 2 bpp, some decoders do not support it correctly */
432  dvb_encode_rle = dvb_encode_rle2;
433  } else if (h->rects[object_id]->nb_colors <= 16) {
434  /* 4 bpp, standard encoding */
435  dvb_encode_rle = dvb_encode_rle4;
436  } else if (h->rects[object_id]->nb_colors <= 256) {
437  /* 8 bpp, standard encoding */
438  dvb_encode_rle = dvb_encode_rle8;
439  } else {
440  return AVERROR(EINVAL);
441  }
442 
443  /* Object Data segment */
444  *q++ = 0x0f; /* sync byte */
445  *q++ = 0x13;
446  bytestream_put_be16(&q, page_id);
447  pseg_len = q;
448  q += 2; /* segment length */
449 
450  bytestream_put_be16(&q, object_id);
451  *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
452  object_coding_method,
453  non_modifying_color_flag */
454  {
455  uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
456  int ret;
457 
458  ptop_field_len = q;
459  q += 2;
460  pbottom_field_len = q;
461  q += 2;
462  buf_size -= 13;
463 
464  top_ptr = q;
465  ret = dvb_encode_rle(&q, buf_size,
466  h->rects[object_id]->data[0],
467  h->rects[object_id]->w * 2,
468  h->rects[object_id]->w,
469  h->rects[object_id]->h >> 1);
470  if (ret < 0)
471  return ret;
472  buf_size -= ret;
473  bottom_ptr = q;
474  ret = dvb_encode_rle(&q, buf_size,
475  h->rects[object_id]->data[0] + h->rects[object_id]->w,
476  h->rects[object_id]->w * 2,
477  h->rects[object_id]->w,
478  h->rects[object_id]->h >> 1);
479  if (ret < 0)
480  return ret;
481  buf_size -= ret;
482 
483  bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
484  bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
485  }
486 
487  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
488  }
489  }
490 
491  /* end of display set segment */
492 
493  if (buf_size < 6)
495  *q++ = 0x0f; /* sync_byte */
496  *q++ = 0x80; /* segment_type */
497  bytestream_put_be16(&q, page_id);
498  pseg_len = q;
499  q += 2; /* segment length */
500 
501  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
502  buf_size -= 6;
503 
504  s->object_version = (s->object_version + 1) & 0xf;
505  return q - outbuf;
506 }
507 
509  .name = "dvbsub",
510  .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
511  .type = AVMEDIA_TYPE_SUBTITLE,
513  .priv_data_size = sizeof(DVBSubtitleContext),
514  .encode_sub = dvbsub_encode,
515 };
#define PUTBITS2(val)
Definition: dvbsubenc.c:29
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
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
#define PUTBITS4(val)
Definition: dvbsubenc.c:123
static int dvb_encode_rle4(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsubenc.c:135
AVSubtitleRect ** rects
Definition: avcodec.h:2699
int w
width of pict, undefined when pict is not set
Definition: avcodec.h:2662
static int dvb_encode_rle2(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsubenc.c:40
uint8_t
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:2663
static int dvb_encode_rle8(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsubenc.c:210
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
#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
uint8_t w
Definition: llviddspenc.c:38
AVCodec ff_dvbsub_encoder
Definition: dvbsubenc.c:508
#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.
static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, const AVSubtitle *h)
Definition: dvbsubenc.c:271
main external API structure.
Definition: avcodec.h:526
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