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 "codec_internal.h"
24 #include "libavutil/colorspace.h"
25 
26 typedef struct DVBSubtitleContext {
29 
30 #define PUTBITS2(val)\
31 {\
32  bitbuf |= (val) << bitcnt;\
33  bitcnt -= 2;\
34  if (bitcnt < 0) {\
35  bitcnt = 6;\
36  *q++ = bitbuf;\
37  bitbuf = 0;\
38  }\
39 }
40 
41 static int dvb_encode_rle2(uint8_t **pq, int buf_size,
42  const uint8_t *bitmap, int linesize,
43  int w, int h)
44 {
45  uint8_t *q, *line_begin;
46  unsigned int bitbuf;
47  int bitcnt;
48  int x, y, len, x1, v, color;
49 
50  q = *pq;
51 
52  for(y = 0; y < h; y++) {
53  // Worst case line is 3 bits per value + 4 bytes overhead
54  if (buf_size * 8 < w * 3 + 32)
56  line_begin = q;
57  *q++ = 0x10;
58  bitbuf = 0;
59  bitcnt = 6;
60 
61  x = 0;
62  while (x < w) {
63  x1 = x;
64  color = bitmap[x1++];
65  while (x1 < w && bitmap[x1] == color)
66  x1++;
67  len = x1 - x;
68  if (color == 0 && len == 2) {
69  PUTBITS2(0);
70  PUTBITS2(0);
71  PUTBITS2(1);
72  } else if (len >= 3 && len <= 10) {
73  v = len - 3;
74  PUTBITS2(0);
75  PUTBITS2((v >> 2) | 2);
76  PUTBITS2(v & 3);
77  PUTBITS2(color);
78  } else if (len >= 12 && len <= 27) {
79  v = len - 12;
80  PUTBITS2(0);
81  PUTBITS2(0);
82  PUTBITS2(2);
83  PUTBITS2(v >> 2);
84  PUTBITS2(v & 3);
85  PUTBITS2(color);
86  } else if (len >= 29) {
87  /* length = 29 ... 284 */
88  if (len > 284)
89  len = 284;
90  v = len - 29;
91  PUTBITS2(0);
92  PUTBITS2(0);
93  PUTBITS2(3);
94  PUTBITS2((v >> 6));
95  PUTBITS2((v >> 4) & 3);
96  PUTBITS2((v >> 2) & 3);
97  PUTBITS2(v & 3);
98  PUTBITS2(color);
99  } else {
100  PUTBITS2(color);
101  if (color == 0) {
102  PUTBITS2(1);
103  }
104  len = 1;
105  }
106  x += len;
107  }
108  /* end of line */
109  PUTBITS2(0);
110  PUTBITS2(0);
111  PUTBITS2(0);
112  if (bitcnt != 6) {
113  *q++ = bitbuf;
114  }
115  *q++ = 0xf0;
116  bitmap += linesize;
117  buf_size -= q - line_begin;
118  }
119  len = q - *pq;
120  *pq = q;
121  return len;
122 }
123 
124 #define PUTBITS4(val)\
125 {\
126  bitbuf |= (val) << bitcnt;\
127  bitcnt -= 4;\
128  if (bitcnt < 0) {\
129  bitcnt = 4;\
130  *q++ = bitbuf;\
131  bitbuf = 0;\
132  }\
133 }
134 
135 /* some DVB decoders only implement 4 bits/pixel */
136 static int dvb_encode_rle4(uint8_t **pq, int buf_size,
137  const uint8_t *bitmap, int linesize,
138  int w, int h)
139 {
140  uint8_t *q, *line_begin;
141  unsigned int bitbuf;
142  int bitcnt;
143  int x, y, len, x1, v, color;
144 
145  q = *pq;
146 
147  for(y = 0; y < h; y++) {
148  // Worst case line is 6 bits per value, + 4 bytes overhead
149  if (buf_size * 8 < w * 6 + 32)
151  line_begin = q;
152  *q++ = 0x11;
153  bitbuf = 0;
154  bitcnt = 4;
155 
156  x = 0;
157  while (x < w) {
158  x1 = x;
159  color = bitmap[x1++];
160  while (x1 < w && bitmap[x1] == color)
161  x1++;
162  len = x1 - x;
163  if (color == 0 && len == 2) {
164  PUTBITS4(0);
165  PUTBITS4(0xd);
166  } else if (color == 0 && (len >= 3 && len <= 9)) {
167  PUTBITS4(0);
168  PUTBITS4(len - 2);
169  } else if (len >= 4 && len <= 7) {
170  PUTBITS4(0);
171  PUTBITS4(8 + len - 4);
172  PUTBITS4(color);
173  } else if (len >= 9 && len <= 24) {
174  PUTBITS4(0);
175  PUTBITS4(0xe);
176  PUTBITS4(len - 9);
177  PUTBITS4(color);
178  } else if (len >= 25) {
179  if (len > 280)
180  len = 280;
181  v = len - 25;
182  PUTBITS4(0);
183  PUTBITS4(0xf);
184  PUTBITS4(v >> 4);
185  PUTBITS4(v & 0xf);
186  PUTBITS4(color);
187  } else {
188  PUTBITS4(color);
189  if (color == 0) {
190  PUTBITS4(0xc);
191  }
192  len = 1;
193  }
194  x += len;
195  }
196  /* end of line */
197  PUTBITS4(0);
198  PUTBITS4(0);
199  if (bitcnt != 4) {
200  *q++ = bitbuf;
201  }
202  *q++ = 0xf0;
203  bitmap += linesize;
204  buf_size -= q - line_begin;
205  }
206  len = q - *pq;
207  *pq = q;
208  return len;
209 }
210 
211 static int dvb_encode_rle8(uint8_t **pq, int buf_size,
212  const uint8_t *bitmap, int linesize,
213  int w, int h)
214 {
215  uint8_t *q, *line_begin;
216  int x, y, len, x1, color;
217 
218  q = *pq;
219 
220  for (y = 0; y < h; y++) {
221  // Worst case line is 12 bits per value, + 3 bytes overhead
222  if (buf_size * 8 < w * 12 + 24)
224  line_begin = q;
225  *q++ = 0x12;
226 
227  x = 0;
228  while (x < w) {
229  x1 = x;
230  color = bitmap[x1++];
231  while (x1 < w && bitmap[x1] == color)
232  x1++;
233  len = x1 - x;
234  if (len == 1 && color) {
235  // 00000001 to 11111111 1 pixel in colour x
236  *q++ = color;
237  } else {
238  if (color == 0x00) {
239  // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0)
240  len = FFMIN(len, 127);
241  *q++ = 0x00;
242  *q++ = len;
243  } else if (len > 2) {
244  // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2)
245  len = FFMIN(len, 127);
246  *q++ = 0x00;
247  *q++ = 0x80+len;
248  *q++ = color;
249  }
250  else if (len == 2) {
251  *q++ = color;
252  *q++ = color;
253  } else {
254  *q++ = color;
255  len = 1;
256  }
257  }
258  x += len;
259  }
260  /* end of line */
261  // 00000000 end of 8-bit/pixel_code_string
262  *q++ = 0x00;
263  *q++ = 0xf0;
264  bitmap += linesize;
265  buf_size -= q - line_begin;
266  }
267  len = q - *pq;
268  *pq = q;
269  return len;
270 }
271 
272 static int dvbsub_encode(AVCodecContext *avctx, 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  if (buf_size < h->num_rects * 22)
381  for (region_id = 0; region_id < h->num_rects; region_id++) {
382 
383  /* region composition segment */
384 
385  if (h->rects[region_id]->nb_colors <= 4) {
386  /* 2 bpp, some decoders do not support it correctly */
387  bpp_index = 0;
388  } else if (h->rects[region_id]->nb_colors <= 16) {
389  /* 4 bpp, standard encoding */
390  bpp_index = 1;
391  } else if (h->rects[region_id]->nb_colors <= 256) {
392  /* 8 bpp, standard encoding */
393  bpp_index = 2;
394  } else {
395  return AVERROR(EINVAL);
396  }
397 
398  *q++ = 0x0f; /* sync_byte */
399  *q++ = 0x11; /* segment_type */
400  bytestream_put_be16(&q, page_id);
401  pseg_len = q;
402  q += 2; /* segment length */
403  *q++ = region_id;
404  *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
405  bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
406  bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
407  *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
408  *q++ = region_id; /* clut_id == region_id */
409  *q++ = 0; /* 8 bit fill colors */
410  *q++ = 0x03; /* 4 bit and 2 bit fill colors */
411 
412  bytestream_put_be16(&q, region_id); /* object_id == region_id */
413  *q++ = (0 << 6) | (0 << 4);
414  *q++ = 0;
415  *q++ = 0xf0;
416  *q++ = 0;
417 
418  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
419  }
420  buf_size -= h->num_rects * 22;
421 
422  for (object_id = 0; object_id < h->num_rects; object_id++) {
423  int (*dvb_encode_rle)(uint8_t **pq, int buf_size,
424  const uint8_t *bitmap, int linesize,
425  int w, int h);
426 
427  if (buf_size < 13)
429 
430  /* bpp_index maths */
431  if (h->rects[object_id]->nb_colors <= 4) {
432  /* 2 bpp, some decoders do not support it correctly */
433  dvb_encode_rle = dvb_encode_rle2;
434  } else if (h->rects[object_id]->nb_colors <= 16) {
435  /* 4 bpp, standard encoding */
436  dvb_encode_rle = dvb_encode_rle4;
437  } else if (h->rects[object_id]->nb_colors <= 256) {
438  /* 8 bpp, standard encoding */
439  dvb_encode_rle = dvb_encode_rle8;
440  } else {
441  return AVERROR(EINVAL);
442  }
443 
444  /* Object Data segment */
445  *q++ = 0x0f; /* sync byte */
446  *q++ = 0x13;
447  bytestream_put_be16(&q, page_id);
448  pseg_len = q;
449  q += 2; /* segment length */
450 
451  bytestream_put_be16(&q, object_id);
452  *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
453  object_coding_method,
454  non_modifying_color_flag */
455  {
456  uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
457  int ret;
458 
459  ptop_field_len = q;
460  q += 2;
461  pbottom_field_len = q;
462  q += 2;
463  buf_size -= 13;
464 
465  top_ptr = q;
466  ret = dvb_encode_rle(&q, buf_size,
467  h->rects[object_id]->data[0],
468  h->rects[object_id]->w * 2,
469  h->rects[object_id]->w,
470  h->rects[object_id]->h >> 1);
471  if (ret < 0)
472  return ret;
473  buf_size -= ret;
474  bottom_ptr = q;
475  ret = dvb_encode_rle(&q, buf_size,
476  h->rects[object_id]->data[0] + h->rects[object_id]->w,
477  h->rects[object_id]->w * 2,
478  h->rects[object_id]->w,
479  h->rects[object_id]->h >> 1);
480  if (ret < 0)
481  return ret;
482  buf_size -= ret;
483 
484  bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
485  bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
486  }
487 
488  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
489  }
490  }
491 
492  /* end of display set segment */
493 
494  if (buf_size < 6)
496  *q++ = 0x0f; /* sync_byte */
497  *q++ = 0x80; /* segment_type */
498  bytestream_put_be16(&q, page_id);
499  pseg_len = q;
500  q += 2; /* segment length */
501 
502  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
503  buf_size -= 6;
504 
505  s->object_version = (s->object_version + 1) & 0xf;
506  return q - outbuf;
507 }
508 
510  .p.name = "dvbsub",
511  CODEC_LONG_NAME("DVB subtitles"),
512  .p.type = AVMEDIA_TYPE_SUBTITLE,
513  .p.id = AV_CODEC_ID_DVB_SUBTITLE,
514  .priv_data_size = sizeof(DVBSubtitleContext),
516 };
AVSubtitle
Definition: avcodec.h:2227
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
r
const char * r
Definition: vf_curves.c:126
AVERROR
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
color
Definition: vf_paletteuse.c:511
dvb_encode_rle4
static int dvb_encode_rle4(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsubenc.c:136
RGB_TO_U_CCIR
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:102
w
uint8_t w
Definition: llviddspenc.c:38
b
#define b
Definition: input.c:41
dvbsub_encode
static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, const AVSubtitle *h)
Definition: dvbsubenc.c:272
FFCodec
Definition: codec_internal.h:127
DVBSubtitleContext::object_version
int object_version
Definition: dvbsubenc.c:27
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
AVERROR_BUFFER_TOO_SMALL
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition: error.h:53
AV_CODEC_ID_DVB_SUBTITLE
@ AV_CODEC_ID_DVB_SUBTITLE
Definition: codec_id.h:550
colorspace.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
RGB_TO_Y_CCIR
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:98
g
const char * g
Definition: vf_curves.c:127
dvb_encode_rle8
static int dvb_encode_rle8(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsubenc.c:211
DVBSubtitleContext
Definition: dvbsubenc.c:26
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:272
dvb_encode_rle2
static int dvb_encode_rle2(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition: dvbsubenc.c:41
RGB_TO_V_CCIR
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
FF_CODEC_ENCODE_SUB_CB
#define FF_CODEC_ENCODE_SUB_CB(func)
Definition: codec_internal.h:299
PUTBITS4
#define PUTBITS4(val)
Definition: dvbsubenc.c:124
codec_internal.h
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
a
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:41
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
xf
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:590
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
ff_dvbsub_encoder
const FFCodec ff_dvbsub_encoder
Definition: dvbsubenc.c:509
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
len
int len
Definition: vorbis_enc_data.h:426
AVCodecContext::height
int height
Definition: avcodec.h:618
avcodec.h
ret
ret
Definition: filter_design.txt:187
AVCodecContext
main external API structure.
Definition: avcodec.h:445
PUTBITS2
#define PUTBITS2(val)
Definition: dvbsubenc.c:30
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
bytestream.h
h
h
Definition: vp9dsp_template.c:2038
int
int
Definition: ffmpeg_filter.c:410