FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 void dvb_encode_rle2(uint8_t **pq,
41  const uint8_t *bitmap, int linesize,
42  int w, int h)
43 {
44  uint8_t *q;
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  *q++ = 0x10;
53  bitbuf = 0;
54  bitcnt = 6;
55 
56  x = 0;
57  while (x < w) {
58  x1 = x;
59  color = bitmap[x1++];
60  while (x1 < w && bitmap[x1] == color)
61  x1++;
62  len = x1 - x;
63  if (color == 0 && len == 2) {
64  PUTBITS2(0);
65  PUTBITS2(0);
66  PUTBITS2(1);
67  } else if (len >= 3 && len <= 10) {
68  v = len - 3;
69  PUTBITS2(0);
70  PUTBITS2((v >> 2) | 2);
71  PUTBITS2(v & 3);
72  PUTBITS2(color);
73  } else if (len >= 12 && len <= 27) {
74  v = len - 12;
75  PUTBITS2(0);
76  PUTBITS2(0);
77  PUTBITS2(2);
78  PUTBITS2(v >> 2);
79  PUTBITS2(v & 3);
80  PUTBITS2(color);
81  } else if (len >= 29) {
82  /* length = 29 ... 284 */
83  if (len > 284)
84  len = 284;
85  v = len - 29;
86  PUTBITS2(0);
87  PUTBITS2(0);
88  PUTBITS2(3);
89  PUTBITS2((v >> 6));
90  PUTBITS2((v >> 4) & 3);
91  PUTBITS2((v >> 2) & 3);
92  PUTBITS2(v & 3);
93  PUTBITS2(color);
94  } else {
95  PUTBITS2(color);
96  if (color == 0) {
97  PUTBITS2(1);
98  }
99  len = 1;
100  }
101  x += len;
102  }
103  /* end of line */
104  PUTBITS2(0);
105  PUTBITS2(0);
106  PUTBITS2(0);
107  if (bitcnt != 6) {
108  *q++ = bitbuf;
109  }
110  *q++ = 0xf0;
111  bitmap += linesize;
112  }
113  *pq = q;
114 }
115 
116 #define PUTBITS4(val)\
117 {\
118  bitbuf |= (val) << bitcnt;\
119  bitcnt -= 4;\
120  if (bitcnt < 0) {\
121  bitcnt = 4;\
122  *q++ = bitbuf;\
123  bitbuf = 0;\
124  }\
125 }
126 
127 /* some DVB decoders only implement 4 bits/pixel */
128 static void dvb_encode_rle4(uint8_t **pq,
129  const uint8_t *bitmap, int linesize,
130  int w, int h)
131 {
132  uint8_t *q;
133  unsigned int bitbuf;
134  int bitcnt;
135  int x, y, len, x1, v, color;
136 
137  q = *pq;
138 
139  for(y = 0; y < h; y++) {
140  *q++ = 0x11;
141  bitbuf = 0;
142  bitcnt = 4;
143 
144  x = 0;
145  while (x < w) {
146  x1 = x;
147  color = bitmap[x1++];
148  while (x1 < w && bitmap[x1] == color)
149  x1++;
150  len = x1 - x;
151  if (color == 0 && len == 2) {
152  PUTBITS4(0);
153  PUTBITS4(0xd);
154  } else if (color == 0 && (len >= 3 && len <= 9)) {
155  PUTBITS4(0);
156  PUTBITS4(len - 2);
157  } else if (len >= 4 && len <= 7) {
158  PUTBITS4(0);
159  PUTBITS4(8 + len - 4);
160  PUTBITS4(color);
161  } else if (len >= 9 && len <= 24) {
162  PUTBITS4(0);
163  PUTBITS4(0xe);
164  PUTBITS4(len - 9);
165  PUTBITS4(color);
166  } else if (len >= 25) {
167  if (len > 280)
168  len = 280;
169  v = len - 25;
170  PUTBITS4(0);
171  PUTBITS4(0xf);
172  PUTBITS4(v >> 4);
173  PUTBITS4(v & 0xf);
174  PUTBITS4(color);
175  } else {
176  PUTBITS4(color);
177  if (color == 0) {
178  PUTBITS4(0xc);
179  }
180  len = 1;
181  }
182  x += len;
183  }
184  /* end of line */
185  PUTBITS4(0);
186  PUTBITS4(0);
187  if (bitcnt != 4) {
188  *q++ = bitbuf;
189  }
190  *q++ = 0xf0;
191  bitmap += linesize;
192  }
193  *pq = q;
194 }
195 
196 static void dvb_encode_rle8(uint8_t **pq,
197  const uint8_t *bitmap, int linesize,
198  int w, int h)
199 {
200  uint8_t *q;
201  int x, y, len, x1, color;
202 
203  q = *pq;
204 
205  for (y = 0; y < h; y++) {
206  *q++ = 0x12;
207 
208  x = 0;
209  while (x < w) {
210  x1 = x;
211  color = bitmap[x1++];
212  while (x1 < w && bitmap[x1] == color)
213  x1++;
214  len = x1 - x;
215  if (len == 1 && color) {
216  // 00000001 to 11111111 1 pixel in colour x
217  *q++ = color;
218  } else {
219  if (color == 0x00) {
220  // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0)
221  len = FFMIN(len, 127);
222  *q++ = 0x00;
223  *q++ = len;
224  } else if (len > 2) {
225  // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2)
226  len = FFMIN(len, 127);
227  *q++ = 0x00;
228  *q++ = 0x80+len;
229  *q++ = color;
230  }
231  else if (len == 2) {
232  *q++ = color;
233  *q++ = color;
234  } else {
235  *q++ = color;
236  len = 1;
237  }
238  }
239  x += len;
240  }
241  /* end of line */
242  // 00000000 00000000 end of 8-bit/pixel_code_string
243  *q++ = 0x00;
244  *q++ = 0x00;
245  bitmap += linesize;
246  }
247  *pq = q;
248 }
249 
251  uint8_t *outbuf, const AVSubtitle *h)
252 {
253  uint8_t *q, *pseg_len;
254  int page_id, region_id, clut_id, object_id, i, bpp_index, page_state;
255 
256 
257  q = outbuf;
258 
259  page_id = 1;
260 
261  if (h->num_rects && !h->rects)
262  return -1;
263 
264  /* page composition segment */
265 
266  *q++ = 0x0f; /* sync_byte */
267  *q++ = 0x10; /* segment_type */
268  bytestream_put_be16(&q, page_id);
269  pseg_len = q;
270  q += 2; /* segment length */
271  *q++ = 30; /* page_timeout (seconds) */
272  page_state = 2; /* mode change */
273  /* page_version = 0 + page_state */
274  *q++ = (s->object_version << 4) | (page_state << 2) | 3;
275 
276  for (region_id = 0; region_id < h->num_rects; region_id++) {
277  *q++ = region_id;
278  *q++ = 0xff; /* reserved */
279  bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */
280  bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */
281  }
282 
283  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
284 
285  if (h->num_rects) {
286  for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
287 
288  /* CLUT segment */
289 
290  if (h->rects[clut_id]->nb_colors <= 4) {
291  /* 2 bpp, some decoders do not support it correctly */
292  bpp_index = 0;
293  } else if (h->rects[clut_id]->nb_colors <= 16) {
294  /* 4 bpp, standard encoding */
295  bpp_index = 1;
296  } else if (h->rects[clut_id]->nb_colors <= 256) {
297  /* 8 bpp, standard encoding */
298  bpp_index = 2;
299  } else {
300  return -1;
301  }
302 
303 
304  /* CLUT segment */
305  *q++ = 0x0f; /* sync byte */
306  *q++ = 0x12; /* CLUT definition segment */
307  bytestream_put_be16(&q, page_id);
308  pseg_len = q;
309  q += 2; /* segment length */
310  *q++ = clut_id;
311  *q++ = (0 << 4) | 0xf; /* version = 0 */
312 
313  for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
314  *q++ = i; /* clut_entry_id */
315  *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
316  {
317  int a, r, g, b;
318  uint32_t x= ((uint32_t*)h->rects[clut_id]->pict.data[1])[i];
319  a = (x >> 24) & 0xff;
320  r = (x >> 16) & 0xff;
321  g = (x >> 8) & 0xff;
322  b = (x >> 0) & 0xff;
323 
324  *q++ = RGB_TO_Y_CCIR(r, g, b);
325  *q++ = RGB_TO_V_CCIR(r, g, b, 0);
326  *q++ = RGB_TO_U_CCIR(r, g, b, 0);
327  *q++ = 255 - a;
328  }
329  }
330 
331  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
332  }
333  }
334 
335  for (region_id = 0; region_id < h->num_rects; region_id++) {
336 
337  /* region composition segment */
338 
339  if (h->rects[region_id]->nb_colors <= 4) {
340  /* 2 bpp, some decoders do not support it correctly */
341  bpp_index = 0;
342  } else if (h->rects[region_id]->nb_colors <= 16) {
343  /* 4 bpp, standard encoding */
344  bpp_index = 1;
345  } else {
346  return -1;
347  }
348 
349  *q++ = 0x0f; /* sync_byte */
350  *q++ = 0x11; /* segment_type */
351  bytestream_put_be16(&q, page_id);
352  pseg_len = q;
353  q += 2; /* segment length */
354  *q++ = region_id;
355  *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
356  bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
357  bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
358  *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
359  *q++ = region_id; /* clut_id == region_id */
360  *q++ = 0; /* 8 bit fill colors */
361  *q++ = 0x03; /* 4 bit and 2 bit fill colors */
362 
363  bytestream_put_be16(&q, region_id); /* object_id == region_id */
364  *q++ = (0 << 6) | (0 << 4);
365  *q++ = 0;
366  *q++ = 0xf0;
367  *q++ = 0;
368 
369  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
370  }
371 
372  if (h->num_rects) {
373 
374  for (object_id = 0; object_id < h->num_rects; object_id++) {
375  void (*dvb_encode_rle)(uint8_t **pq,
376  const uint8_t *bitmap, int linesize,
377  int w, int h);
378 
379  /* bpp_index maths */
380  if (h->rects[object_id]->nb_colors <= 4) {
381  /* 2 bpp, some decoders do not support it correctly */
382  dvb_encode_rle = dvb_encode_rle2;
383  } else if (h->rects[object_id]->nb_colors <= 16) {
384  /* 4 bpp, standard encoding */
385  dvb_encode_rle = dvb_encode_rle4;
386  } else if (h->rects[object_id]->nb_colors <= 256) {
387  /* 8 bpp, standard encoding */
388  dvb_encode_rle = dvb_encode_rle8;
389  } else {
390  return -1;
391  }
392 
393  /* Object Data segment */
394  *q++ = 0x0f; /* sync byte */
395  *q++ = 0x13;
396  bytestream_put_be16(&q, page_id);
397  pseg_len = q;
398  q += 2; /* segment length */
399 
400  bytestream_put_be16(&q, object_id);
401  *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
402  onject_coding_method,
403  non_modifying_color_flag */
404  {
405  uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
406 
407  ptop_field_len = q;
408  q += 2;
409  pbottom_field_len = q;
410  q += 2;
411 
412  top_ptr = q;
413  dvb_encode_rle(&q, h->rects[object_id]->pict.data[0], h->rects[object_id]->w * 2,
414  h->rects[object_id]->w, h->rects[object_id]->h >> 1);
415  bottom_ptr = q;
416  dvb_encode_rle(&q, h->rects[object_id]->pict.data[0] + h->rects[object_id]->w,
417  h->rects[object_id]->w * 2, h->rects[object_id]->w,
418  h->rects[object_id]->h >> 1);
419 
420  bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
421  bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
422  }
423 
424  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
425  }
426  }
427 
428  /* end of display set segment */
429 
430  *q++ = 0x0f; /* sync_byte */
431  *q++ = 0x80; /* segment_type */
432  bytestream_put_be16(&q, page_id);
433  pseg_len = q;
434  q += 2; /* segment length */
435 
436  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
437 
438  s->object_version = (s->object_version + 1) & 0xf;
439  return q - outbuf;
440 }
441 
442 static int dvbsub_encode(AVCodecContext *avctx,
443  unsigned char *buf, int buf_size,
444  const AVSubtitle *sub)
445 {
446  DVBSubtitleContext *s = avctx->priv_data;
447  int ret;
448 
449  ret = encode_dvb_subtitles(s, buf, sub);
450  return ret;
451 }
452 
454  .name = "dvbsub",
455  .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
456  .type = AVMEDIA_TYPE_SUBTITLE,
458  .priv_data_size = sizeof(DVBSubtitleContext),
459  .encode_sub = dvbsub_encode,
460 };