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 == NULL)
262  return -1;
263 
264  *q++ = 0x00; /* subtitle_stream_id */
265 
266  /* page composition segment */
267 
268  *q++ = 0x0f; /* sync_byte */
269  *q++ = 0x10; /* segment_type */
270  bytestream_put_be16(&q, page_id);
271  pseg_len = q;
272  q += 2; /* segment length */
273  *q++ = 30; /* page_timeout (seconds) */
274  page_state = 2; /* mode change */
275  /* page_version = 0 + page_state */
276  *q++ = (s->object_version << 4) | (page_state << 2) | 3;
277 
278  for (region_id = 0; region_id < h->num_rects; region_id++) {
279  *q++ = region_id;
280  *q++ = 0xff; /* reserved */
281  bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */
282  bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */
283  }
284 
285  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
286 
287  if (h->num_rects) {
288  for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
289 
290  /* CLUT segment */
291 
292  if (h->rects[clut_id]->nb_colors <= 4) {
293  /* 2 bpp, some decoders do not support it correctly */
294  bpp_index = 0;
295  } else if (h->rects[clut_id]->nb_colors <= 16) {
296  /* 4 bpp, standard encoding */
297  bpp_index = 1;
298  } else if (h->rects[clut_id]->nb_colors <= 256) {
299  /* 8 bpp, standard encoding */
300  bpp_index = 2;
301  } else {
302  return -1;
303  }
304 
305 
306  /* CLUT segment */
307  *q++ = 0x0f; /* sync byte */
308  *q++ = 0x12; /* CLUT definition segment */
309  bytestream_put_be16(&q, page_id);
310  pseg_len = q;
311  q += 2; /* segment length */
312  *q++ = clut_id;
313  *q++ = (0 << 4) | 0xf; /* version = 0 */
314 
315  for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
316  *q++ = i; /* clut_entry_id */
317  *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
318  {
319  int a, r, g, b;
320  uint32_t x= ((uint32_t*)h->rects[clut_id]->pict.data[1])[i];
321  a = (x >> 24) & 0xff;
322  r = (x >> 16) & 0xff;
323  g = (x >> 8) & 0xff;
324  b = (x >> 0) & 0xff;
325 
326  *q++ = RGB_TO_Y_CCIR(r, g, b);
327  *q++ = RGB_TO_V_CCIR(r, g, b, 0);
328  *q++ = RGB_TO_U_CCIR(r, g, b, 0);
329  *q++ = 255 - a;
330  }
331  }
332 
333  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
334  }
335  }
336 
337  for (region_id = 0; region_id < h->num_rects; region_id++) {
338 
339  /* region composition segment */
340 
341  if (h->rects[region_id]->nb_colors <= 4) {
342  /* 2 bpp, some decoders do not support it correctly */
343  bpp_index = 0;
344  } else if (h->rects[region_id]->nb_colors <= 16) {
345  /* 4 bpp, standard encoding */
346  bpp_index = 1;
347  } else {
348  return -1;
349  }
350 
351  *q++ = 0x0f; /* sync_byte */
352  *q++ = 0x11; /* segment_type */
353  bytestream_put_be16(&q, page_id);
354  pseg_len = q;
355  q += 2; /* segment length */
356  *q++ = region_id;
357  *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
358  bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
359  bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
360  *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
361  *q++ = region_id; /* clut_id == region_id */
362  *q++ = 0; /* 8 bit fill colors */
363  *q++ = 0x03; /* 4 bit and 2 bit fill colors */
364 
365  bytestream_put_be16(&q, region_id); /* object_id == region_id */
366  *q++ = (0 << 6) | (0 << 4);
367  *q++ = 0;
368  *q++ = 0xf0;
369  *q++ = 0;
370 
371  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
372  }
373 
374  if (h->num_rects) {
375 
376  for (object_id = 0; object_id < h->num_rects; object_id++) {
377  void (*dvb_encode_rle)(uint8_t **pq,
378  const uint8_t *bitmap, int linesize,
379  int w, int h);
380 
381  /* bpp_index maths */
382  if (h->rects[object_id]->nb_colors <= 4) {
383  /* 2 bpp, some decoders do not support it correctly */
384  dvb_encode_rle = dvb_encode_rle2;
385  } else if (h->rects[object_id]->nb_colors <= 16) {
386  /* 4 bpp, standard encoding */
387  dvb_encode_rle = dvb_encode_rle4;
388  } else if (h->rects[object_id]->nb_colors <= 256) {
389  /* 8 bpp, standard encoding */
390  dvb_encode_rle = dvb_encode_rle8;
391  } else {
392  return -1;
393  }
394 
395  /* Object Data segment */
396  *q++ = 0x0f; /* sync byte */
397  *q++ = 0x13;
398  bytestream_put_be16(&q, page_id);
399  pseg_len = q;
400  q += 2; /* segment length */
401 
402  bytestream_put_be16(&q, object_id);
403  *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
404  onject_coding_method,
405  non_modifying_color_flag */
406  {
407  uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
408 
409  ptop_field_len = q;
410  q += 2;
411  pbottom_field_len = q;
412  q += 2;
413 
414  top_ptr = q;
415  dvb_encode_rle(&q, h->rects[object_id]->pict.data[0], h->rects[object_id]->w * 2,
416  h->rects[object_id]->w, h->rects[object_id]->h >> 1);
417  bottom_ptr = q;
418  dvb_encode_rle(&q, h->rects[object_id]->pict.data[0] + h->rects[object_id]->w,
419  h->rects[object_id]->w * 2, h->rects[object_id]->w,
420  h->rects[object_id]->h >> 1);
421 
422  bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
423  bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
424  }
425 
426  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
427  }
428  }
429 
430  /* end of display set segment */
431 
432  *q++ = 0x0f; /* sync_byte */
433  *q++ = 0x80; /* segment_type */
434  bytestream_put_be16(&q, page_id);
435  pseg_len = q;
436  q += 2; /* segment length */
437 
438  bytestream_put_be16(&pseg_len, q - pseg_len - 2);
439 
440  *q++ = 0xff; /* end of PES data */
441 
442  s->object_version = (s->object_version + 1) & 0xf;
443  return q - outbuf;
444 }
445 
446 static int dvbsub_encode(AVCodecContext *avctx,
447  unsigned char *buf, int buf_size,
448  const AVSubtitle *sub)
449 {
450  DVBSubtitleContext *s = avctx->priv_data;
451  int ret;
452 
453  ret = encode_dvb_subtitles(s, buf, sub);
454  return ret;
455 }
456 
458  .name = "dvbsub",
459  .type = AVMEDIA_TYPE_SUBTITLE,
461  .priv_data_size = sizeof(DVBSubtitleContext),
462  .encode_sub = dvbsub_encode,
463  .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
464 };