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