FFmpeg  4.3.6
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
const char * b
Definition: vf_curves.c:116
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
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
Various defines for YUV<->RGB conversion.
int y
top left corner of pict, undefined when pict is not set
Definition: avcodec.h:2661
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
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 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:668
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
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