FFmpeg  4.4.5
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 };
uint8_t
Libavcodec external API header.
#define s(width, name)
Definition: cbs_vp9.c:257
#define FFMIN(a, b)
Definition: common.h:105
static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, const AVSubtitle *h)
Definition: dvbsubenc.c:271
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
AVCodec ff_dvbsub_encoder
Definition: dvbsubenc.c:508
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
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
#define PUTBITS4(val)
Definition: dvbsubenc.c:123
#define PUTBITS2(val)
Definition: dvbsubenc.c:29
int
@ AV_CODEC_ID_DVB_SUBTITLE
Definition: codec_id.h:524
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition: error.h:51
#define AVERROR(e)
Definition: error.h:43
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
int i
Definition: input.c:407
Various defines for YUV<->RGB conversion.
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:102
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:98
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
uint8_t w
Definition: llviddspenc.c:39
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
main external API structure.
Definition: avcodec.h:536
int width
picture width / height.
Definition: avcodec.h:709
void * priv_data
Definition: avcodec.h:563
AVCodec.
Definition: codec.h:197
const char * name
Name of the codec implementation.
Definition: codec.h:204
const char * b
Definition: vf_curves.c:118
const char * g
Definition: vf_curves.c:117
const char * r
Definition: vf_curves.c:116
int len