FFmpeg
Loading...
Searching...
No Matches
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"
25#include "libavutil/opt.h"
26
32
33#define PUTBITS2(val)\
34{\
35 bitbuf |= (val) << bitcnt;\
36 bitcnt -= 2;\
37 if (bitcnt < 0) {\
38 bitcnt = 6;\
39 *q++ = bitbuf;\
40 bitbuf = 0;\
41 }\
42}
43
44static int dvb_encode_rle2(uint8_t **pq, int buf_size,
45 const uint8_t *bitmap, int linesize,
46 int w, int h)
47{
48 uint8_t *q, *line_begin;
49 unsigned int bitbuf;
50 int bitcnt;
51 int x, y, len, x1, v, color;
52
53 q = *pq;
54
55 for(y = 0; y < h; y++) {
56 // Worst case line is 3 bits per value + 4 bytes overhead
57 if (buf_size * 8 < w * 3 + 32)
59 line_begin = q;
60 *q++ = 0x10;
61 bitbuf = 0;
62 bitcnt = 6;
63
64 x = 0;
65 while (x < w) {
66 x1 = x;
67 color = bitmap[x1++];
68 while (x1 < w && bitmap[x1] == color)
69 x1++;
70 len = x1 - x;
71 if (color == 0 && len == 2) {
72 PUTBITS2(0);
73 PUTBITS2(0);
74 PUTBITS2(1);
75 } else if (len >= 3 && len <= 10) {
76 v = len - 3;
77 PUTBITS2(0);
78 PUTBITS2((v >> 2) | 2);
79 PUTBITS2(v & 3);
81 } else if (len >= 12 && len <= 27) {
82 v = len - 12;
83 PUTBITS2(0);
84 PUTBITS2(0);
85 PUTBITS2(2);
86 PUTBITS2(v >> 2);
87 PUTBITS2(v & 3);
89 } else if (len >= 29) {
90 /* length = 29 ... 284 */
91 if (len > 284)
92 len = 284;
93 v = len - 29;
94 PUTBITS2(0);
95 PUTBITS2(0);
96 PUTBITS2(3);
97 PUTBITS2((v >> 6));
98 PUTBITS2((v >> 4) & 3);
99 PUTBITS2((v >> 2) & 3);
100 PUTBITS2(v & 3);
102 } else {
104 if (color == 0) {
105 PUTBITS2(1);
106 }
107 len = 1;
108 }
109 x += len;
110 }
111 /* end of line */
112 PUTBITS2(0);
113 PUTBITS2(0);
114 PUTBITS2(0);
115 if (bitcnt != 6) {
116 *q++ = bitbuf;
117 }
118 *q++ = 0xf0;
119 bitmap += linesize;
120 buf_size -= q - line_begin;
121 }
122 len = q - *pq;
123 *pq = q;
124 return len;
125}
126
127#define PUTBITS4(val)\
128{\
129 bitbuf |= (val) << bitcnt;\
130 bitcnt -= 4;\
131 if (bitcnt < 0) {\
132 bitcnt = 4;\
133 *q++ = bitbuf;\
134 bitbuf = 0;\
135 }\
136}
137
138/* some DVB decoders only implement 4 bits/pixel */
139static int dvb_encode_rle4(uint8_t **pq, int buf_size,
140 const uint8_t *bitmap, int linesize,
141 int w, int h)
142{
143 uint8_t *q, *line_begin;
144 unsigned int bitbuf;
145 int bitcnt;
146 int x, y, len, x1, v, color;
147
148 q = *pq;
149
150 for(y = 0; y < h; y++) {
151 // Worst case line is 6 bits per value, + 4 bytes overhead
152 if (buf_size * 8 < w * 6 + 32)
154 line_begin = q;
155 *q++ = 0x11;
156 bitbuf = 0;
157 bitcnt = 4;
158
159 x = 0;
160 while (x < w) {
161 x1 = x;
162 color = bitmap[x1++];
163 while (x1 < w && bitmap[x1] == color)
164 x1++;
165 len = x1 - x;
166 if (color == 0 && len == 2) {
167 PUTBITS4(0);
168 PUTBITS4(0xd);
169 } else if (color == 0 && (len >= 3 && len <= 9)) {
170 PUTBITS4(0);
171 PUTBITS4(len - 2);
172 } else if (len >= 4 && len <= 7) {
173 PUTBITS4(0);
174 PUTBITS4(8 + len - 4);
176 } else if (len >= 9 && len <= 24) {
177 PUTBITS4(0);
178 PUTBITS4(0xe);
179 PUTBITS4(len - 9);
181 } else if (len >= 25) {
182 if (len > 280)
183 len = 280;
184 v = len - 25;
185 PUTBITS4(0);
186 PUTBITS4(0xf);
187 PUTBITS4(v >> 4);
188 PUTBITS4(v & 0xf);
190 } else {
192 if (color == 0) {
193 PUTBITS4(0xc);
194 }
195 len = 1;
196 }
197 x += len;
198 }
199 /* end of line */
200 PUTBITS4(0);
201 PUTBITS4(0);
202 if (bitcnt != 4) {
203 *q++ = bitbuf;
204 }
205 *q++ = 0xf0;
206 bitmap += linesize;
207 buf_size -= q - line_begin;
208 }
209 len = q - *pq;
210 *pq = q;
211 return len;
212}
213
214static int dvb_encode_rle8(uint8_t **pq, int buf_size,
215 const uint8_t *bitmap, int linesize,
216 int w, int h)
217{
218 uint8_t *q, *line_begin;
219 int x, y, len, x1, color;
220
221 q = *pq;
222
223 for (y = 0; y < h; y++) {
224 // Worst case line is 12 bits per value, + 3 bytes overhead
225 if (buf_size * 8 < w * 12 + 24)
227 line_begin = q;
228 *q++ = 0x12;
229
230 x = 0;
231 while (x < w) {
232 x1 = x;
233 color = bitmap[x1++];
234 while (x1 < w && bitmap[x1] == color)
235 x1++;
236 len = x1 - x;
237 if (len == 1 && color) {
238 // 00000001 to 11111111 1 pixel in colour x
239 *q++ = color;
240 } else {
241 if (color == 0x00) {
242 // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0)
243 len = FFMIN(len, 127);
244 *q++ = 0x00;
245 *q++ = len;
246 } else if (len > 2) {
247 // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2)
248 len = FFMIN(len, 127);
249 *q++ = 0x00;
250 *q++ = 0x80+len;
251 *q++ = color;
252 }
253 else if (len == 2) {
254 *q++ = color;
255 *q++ = color;
256 } else {
257 *q++ = color;
258 len = 1;
259 }
260 }
261 x += len;
262 }
263 /* end of line */
264 // 00000000 00000000 end of 8-bit/pixel_code_string
265 *q++ = 0x00;
266 *q++ = 0x00;
267 *q++ = 0xf0;
268 bitmap += linesize;
269 buf_size -= q - line_begin;
270 }
271 len = q - *pq;
272 *pq = q;
273 return len;
274}
275
276static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size,
277 const AVSubtitle *h)
278{
280 uint8_t *q, *pseg_len;
281 int page_id, region_id, clut_id, object_id, i, bpp_index, page_state, min_colors;
282
283
284 q = outbuf;
285
286 page_id = 1;
287
288 switch(s->min_bpp) {
289 case 2:
290 case 4:
291 case 8:
292 min_colors = 1 << s->min_bpp;
293 break;
294 default:
295 av_log(avctx, AV_LOG_ERROR, "Invalid min_bpp value %d.\n", s->min_bpp);
296 return AVERROR(EINVAL);
297 }
298
299 if (h->num_rects && !h->rects)
300 return AVERROR(EINVAL);
301
302 if (h->num_rects >= 256)
303 return AVERROR(EINVAL);
304
305 if (avctx->width > 0 && avctx->height > 0) {
306 if (buf_size < 11)
308 /* display definition segment */
309 *q++ = 0x0f; /* sync_byte */
310 *q++ = 0x14; /* segment_type */
311 bytestream_put_be16(&q, page_id);
312 pseg_len = q;
313 q += 2; /* segment length */
314 *q++ = 0x00; /* dds version number & display window flag */
315 bytestream_put_be16(&q, avctx->width - 1); /* display width */
316 bytestream_put_be16(&q, avctx->height - 1); /* display height */
317 bytestream_put_be16(&pseg_len, q - pseg_len - 2);
318 buf_size -= 11;
319 }
320
321 /* page composition segment */
322
323 if (buf_size < 8 + h->num_rects * 6)
325 *q++ = 0x0f; /* sync_byte */
326 *q++ = 0x10; /* segment_type */
327 bytestream_put_be16(&q, page_id);
328 pseg_len = q;
329 q += 2; /* segment length */
330 *q++ = 30; /* page_timeout (seconds) */
331 page_state = 2; /* mode change */
332 /* page_version = 0 + page_state */
333 *q++ = (s->object_version << 4) | (page_state << 2) | 3;
334
335 for (region_id = 0; region_id < h->num_rects; region_id++) {
336 *q++ = region_id;
337 *q++ = 0xff; /* reserved */
338 bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */
339 bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */
340 }
341
342 bytestream_put_be16(&pseg_len, q - pseg_len - 2);
343 buf_size -= 8 + h->num_rects * 6;
344
345 if (h->num_rects) {
346 for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
347 /* CLUT segment */
348 int nb_colors = FFMAX(min_colors, h->rects[clut_id]->nb_colors);
349
350 if (nb_colors <= 4U) {
351 /* 2 bpp, some decoders do not support it correctly */
352 bpp_index = 0;
353 } else if (nb_colors <= 16U) {
354 /* 4 bpp, standard encoding */
355 bpp_index = 1;
356 } else if (nb_colors <= 256U) {
357 /* 8 bpp, standard encoding */
358 bpp_index = 2;
359 } else {
360 return AVERROR(EINVAL);
361 }
362
363 if (buf_size < 6 + h->rects[clut_id]->nb_colors * 6)
365
366 /* CLUT segment */
367 *q++ = 0x0f; /* sync byte */
368 *q++ = 0x12; /* CLUT definition segment */
369 bytestream_put_be16(&q, page_id);
370 pseg_len = q;
371 q += 2; /* segment length */
372 *q++ = clut_id;
373 *q++ = (0 << 4) | 0xf; /* version = 0 */
374
375 for(i = 0; i < h->rects[clut_id]->nb_colors; i++) {
376 *q++ = i; /* clut_entry_id */
377 *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
378 {
379 int a, r, g, b;
380 uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i];
381 a = (x >> 24) & 0xff;
382 r = (x >> 16) & 0xff;
383 g = (x >> 8) & 0xff;
384 b = (x >> 0) & 0xff;
385
386 *q++ = RGB_TO_Y_CCIR(r, g, b);
387 *q++ = RGB_TO_V_CCIR(r, g, b, 0);
388 *q++ = RGB_TO_U_CCIR(r, g, b, 0);
389 *q++ = 255 - a;
390 }
391 }
392
393 bytestream_put_be16(&pseg_len, q - pseg_len - 2);
394 buf_size -= 6 + h->rects[clut_id]->nb_colors * 6;
395 }
396
397 if (buf_size < h->num_rects * 22)
399 for (region_id = 0; region_id < h->num_rects; region_id++) {
400
401 /* region composition segment */
402 int nb_colors = FFMAX(min_colors, h->rects[region_id]->nb_colors);
403
404 if (nb_colors <= 4) {
405 /* 2 bpp, some decoders do not support it correctly */
406 bpp_index = 0;
407 } else if (nb_colors <= 16) {
408 /* 4 bpp, standard encoding */
409 bpp_index = 1;
410 } else if (nb_colors <= 256) {
411 /* 8 bpp, standard encoding */
412 bpp_index = 2;
413 } else {
414 return AVERROR(EINVAL);
415 }
416
417 *q++ = 0x0f; /* sync_byte */
418 *q++ = 0x11; /* segment_type */
419 bytestream_put_be16(&q, page_id);
420 pseg_len = q;
421 q += 2; /* segment length */
422 *q++ = region_id;
423 *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
424 bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */
425 bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */
426 *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
427 *q++ = region_id; /* clut_id == region_id */
428 *q++ = 0; /* 8 bit fill colors */
429 *q++ = 0x03; /* 4 bit and 2 bit fill colors */
430
431 bytestream_put_be16(&q, region_id); /* object_id == region_id */
432 *q++ = (0 << 6) | (0 << 4);
433 *q++ = 0;
434 *q++ = 0xf0;
435 *q++ = 0;
436
437 bytestream_put_be16(&pseg_len, q - pseg_len - 2);
438 }
439 buf_size -= h->num_rects * 22;
440
441 for (object_id = 0; object_id < h->num_rects; object_id++) {
442 int (*dvb_encode_rle)(uint8_t **pq, int buf_size,
443 const uint8_t *bitmap, int linesize,
444 int w, int h);
445
446 int nb_colors = FFMAX(min_colors, h->rects[object_id]->nb_colors);
447
448 if (buf_size < 13)
450
451 /* bpp_index maths */
452 if (nb_colors <= 4) {
453 /* 2 bpp, some decoders do not support it correctly */
454 dvb_encode_rle = dvb_encode_rle2;
455 } else if (nb_colors <= 16) {
456 /* 4 bpp, standard encoding */
457 dvb_encode_rle = dvb_encode_rle4;
458 } else if (nb_colors <= 256) {
459 /* 8 bpp, standard encoding */
460 dvb_encode_rle = dvb_encode_rle8;
461 } else {
462 return AVERROR(EINVAL);
463 }
464
465 /* Object Data segment */
466 *q++ = 0x0f; /* sync byte */
467 *q++ = 0x13;
468 bytestream_put_be16(&q, page_id);
469 pseg_len = q;
470 q += 2; /* segment length */
471
472 bytestream_put_be16(&q, object_id);
473 *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
474 object_coding_method,
475 non_modifying_color_flag */
476 {
477 uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
478 int ret;
479
480 ptop_field_len = q;
481 q += 2;
482 pbottom_field_len = q;
483 q += 2;
484 buf_size -= 13;
485
486 top_ptr = q;
487 ret = dvb_encode_rle(&q, buf_size,
488 h->rects[object_id]->data[0],
489 h->rects[object_id]->w * 2,
490 h->rects[object_id]->w,
491 h->rects[object_id]->h >> 1);
492 if (ret < 0)
493 return ret;
494 buf_size -= ret;
495 bottom_ptr = q;
496 ret = dvb_encode_rle(&q, buf_size,
497 h->rects[object_id]->data[0] + h->rects[object_id]->w,
498 h->rects[object_id]->w * 2,
499 h->rects[object_id]->w,
500 h->rects[object_id]->h >> 1);
501 if (ret < 0)
502 return ret;
503 buf_size -= ret;
504
505 bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr);
506 bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
507 }
508
509 bytestream_put_be16(&pseg_len, q - pseg_len - 2);
510 }
511 }
512
513 /* end of display set segment */
514
515 if (buf_size < 6)
517 *q++ = 0x0f; /* sync_byte */
518 *q++ = 0x80; /* segment_type */
519 bytestream_put_be16(&q, page_id);
520 pseg_len = q;
521 q += 2; /* segment length */
522
523 bytestream_put_be16(&pseg_len, q - pseg_len - 2);
524 buf_size -= 6;
525
526 s->object_version = (s->object_version + 1) & 0xf;
527 return q - outbuf;
528}
529
530#define OFFSET(x) offsetof(DVBSubtitleContext, x)
531#define SE AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM
532static const AVOption options[] = {
533 {"min_bpp", "minimum bits-per-pixel for subtitle colors (2, 4 or 8)", OFFSET(min_bpp), AV_OPT_TYPE_INT, {.i64 = 4}, 2, 8, SE},
534 { NULL },
535};
536
537static const AVClass dvbsubenc_class = {
538 .class_name = "DVBSUB subtitle encoder",
539 .item_name = av_default_item_name,
540 .option = options,
541 .version = LIBAVUTIL_VERSION_INT,
542};
543
545 .p.name = "dvbsub",
546 CODEC_LONG_NAME("DVB subtitles"),
547 .p.type = AVMEDIA_TYPE_SUBTITLE,
549 .priv_data_size = sizeof(DVBSubtitleContext),
551 .p.priv_class = &dvbsubenc_class,
552};
const FFCodec ff_dvbsub_encoder
Definition dvbsubenc.c:544
Libavcodec external API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FF_CODEC_ENCODE_SUB_CB(func)
#define CODEC_LONG_NAME(str)
#define NULL
Definition coverity.c:32
static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, const AVSubtitle *h)
Definition dvbsubenc.c:276
static int dvb_encode_rle4(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition dvbsubenc.c:139
#define SE
Definition dvbsubenc.c:531
static int dvb_encode_rle2(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition dvbsubenc.c:44
static const AVClass dvbsubenc_class
Definition dvbsubenc.c:537
static int dvb_encode_rle8(uint8_t **pq, int buf_size, const uint8_t *bitmap, int linesize, int w, int h)
Definition dvbsubenc.c:214
#define PUTBITS4(val)
Definition dvbsubenc.c:127
#define OFFSET(x)
Definition dvbsubenc.c:530
#define PUTBITS2(val)
Definition dvbsubenc.c:33
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_CODEC_ID_DVB_SUBTITLE
Definition codec_id.h:567
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition error.h:53
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
@ AVMEDIA_TYPE_SUBTITLE
Definition avutil.h:203
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
int a
#define r
Definition input.c:42
#define b
Definition input.c:43
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
uint8_t w
Definition llvidencdsp.c:39
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
AVOptions.
Describe the class of an AVClass context structure.
Definition log.h:76
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
void * priv_data
Definition avcodec.h:470
AVOption.
Definition opt.h:428
#define av_log(a,...)
const char * g
Definition vf_curves.c:128
int len