Statistics
| Branch: | Revision:

ffmpeg / libavcodec / dvbsub.c @ 689abe56

History | View | Annotate | Download (13 KB)

1
/*
2
 * DVB subtitle encoding for ffmpeg
3
 * Copyright (c) 2005 Fabrice Bellard.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
#include "avcodec.h"
20

    
21
typedef struct DVBSubtitleContext {
22
    int hide_state;
23
    int object_version;
24
} DVBSubtitleContext;
25

    
26
#define PUTBITS2(val)\
27
{\
28
    bitbuf |= (val) << bitcnt;\
29
    bitcnt -= 2;\
30
    if (bitcnt < 0) {\
31
        bitcnt = 6;\
32
        *q++ = bitbuf;\
33
        bitbuf = 0;\
34
    }\
35
}
36

    
37
static void dvb_encode_rle2(uint8_t **pq,
38
                            const uint8_t *bitmap, int linesize,
39
                            int w, int h)
40
{
41
    uint8_t *q;
42
    unsigned int bitbuf;
43
    int bitcnt;
44
    int x, y, len, x1, v, color;
45

    
46
    q = *pq;
47
    
48
    for(y = 0; y < h; y++) {
49
        *q++ = 0x10;
50
        bitbuf = 0;
51
        bitcnt = 6;
52
        
53
        x = 0;
54
        while (x < w) {
55
            x1 = x;
56
            color = bitmap[x1++];
57
            while (x1 < w && bitmap[x1] == color)
58
                x1++;
59
            len = x1 - x;
60
            if (color == 0 && len == 2) {
61
                PUTBITS2(0);
62
                PUTBITS2(0);
63
                PUTBITS2(1);
64
            } else if (len >= 3 && len <= 10) {
65
                v = len - 3;
66
                PUTBITS2(0);
67
                PUTBITS2((v >> 2) | 2);
68
                PUTBITS2(v & 3);
69
                PUTBITS2(color);
70
            } else if (len >= 12 && len <= 27) {
71
                v = len - 12;
72
                PUTBITS2(0);
73
                PUTBITS2(0);
74
                PUTBITS2(2);
75
                PUTBITS2(v >> 2);
76
                PUTBITS2(v & 3);
77
                PUTBITS2(color);
78
            } else if (len >= 29) {
79
                /* length = 29 ... 284 */
80
                if (len > 284)
81
                    len = 284;
82
                v = len - 29;
83
                PUTBITS2(0);
84
                PUTBITS2(0);
85
                PUTBITS2(3);
86
                PUTBITS2((v >> 6));
87
                PUTBITS2((v >> 4) & 3);
88
                PUTBITS2((v >> 2) & 3);
89
                PUTBITS2(v & 3);
90
                PUTBITS2(color);
91
            } else {
92
                PUTBITS2(color);
93
                if (color == 0) {
94
                    PUTBITS2(1);
95
                }
96
                len = 1;
97
            }
98
            x += len;
99
        }
100
        /* end of line */
101
        PUTBITS2(0);
102
        PUTBITS2(0);
103
        PUTBITS2(0);
104
        if (bitcnt != 6) {
105
            *q++ = bitbuf;
106
        }
107
        *q++ = 0xf0;
108
        bitmap += linesize;
109
    }
110
    *pq = q;
111
}
112

    
113
#define PUTBITS4(val)\
114
{\
115
    bitbuf |= (val) << bitcnt;\
116
    bitcnt -= 4;\
117
    if (bitcnt < 0) {\
118
        bitcnt = 4;\
119
        *q++ = bitbuf;\
120
        bitbuf = 0;\
121
    }\
122
}
123

    
124
/* some DVB decoders only implement 4 bits/pixel */
125
static void dvb_encode_rle4(uint8_t **pq,
126
                            const uint8_t *bitmap, int linesize,
127
                            int w, int h)
128
{
129
    uint8_t *q;
130
    unsigned int bitbuf;
131
    int bitcnt;
132
    int x, y, len, x1, v, color;
133

    
134
    q = *pq;
135
    
136
    for(y = 0; y < h; y++) {
137
        *q++ = 0x11;
138
        bitbuf = 0;
139
        bitcnt = 4;
140
        
141
        x = 0;
142
        while (x < w) {
143
            x1 = x;
144
            color = bitmap[x1++];
145
            while (x1 < w && bitmap[x1] == color)
146
                x1++;
147
            len = x1 - x;
148
            if (color == 0 && len == 2) {
149
                PUTBITS4(0);
150
                PUTBITS4(0xd);
151
            } else if (color == 0 && (len >= 3 && len <= 9)) {
152
                PUTBITS4(0);
153
                PUTBITS4(len - 2);
154
            } else if (len >= 4 && len <= 7) {
155
                PUTBITS4(0);
156
                PUTBITS4(8 + len - 4);
157
                PUTBITS4(color);
158
            } else if (len >= 9 && len <= 24) {
159
                PUTBITS4(0);
160
                PUTBITS4(0xe);
161
                PUTBITS4(len - 9);
162
                PUTBITS4(color);
163
            } else if (len >= 25) {
164
                if (len > 280)
165
                    len = 280;
166
                v = len - 25;
167
                PUTBITS4(0);
168
                PUTBITS4(0xf);
169
                PUTBITS4(v >> 4);
170
                PUTBITS4(v & 0xf);
171
                PUTBITS4(color);
172
            } else {
173
                PUTBITS4(color);
174
                if (color == 0) {
175
                    PUTBITS4(0xc);
176
                }
177
                len = 1;
178
            }
179
            x += len;
180
        }
181
        /* end of line */
182
        PUTBITS4(0);
183
        PUTBITS4(0);
184
        if (bitcnt != 4) {
185
            *q++ = bitbuf;
186
        }
187
        *q++ = 0xf0;
188
        bitmap += linesize;
189
    }
190
    *pq = q;
191
}
192

    
193
#define SCALEBITS 10
194
#define ONE_HALF  (1 << (SCALEBITS - 1))
195
#define FIX(x)          ((int) ((x) * (1<<SCALEBITS) + 0.5))
196

    
197
#define RGB_TO_Y_CCIR(r, g, b) \
198
((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
199
  FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
200

    
201
#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
202
(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 +         \
203
     FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
204

    
205
#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
206
(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 -           \
207
   FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
208

    
209
static inline void putbe16(uint8_t **pq, uint16_t v)
210
{
211
    uint8_t *q;
212
    q = *pq;
213
    *q++ = v >> 8;
214
    *q++ = v;
215
    *pq = q;
216
}
217

    
218
static int encode_dvb_subtitles(DVBSubtitleContext *s, 
219
                                uint8_t *outbuf, AVSubtitle *h)
220
{
221
    uint8_t *q, *pseg_len;
222
    int page_id, region_id, clut_id, object_id, i, bpp_index, page_state;
223

    
224

    
225
    q = outbuf;
226

    
227
    page_id = 1;
228

    
229
    if (h->num_rects == 0 || h->rects == NULL)
230
        return -1;
231

    
232
    *q++ = 0x00; /* subtitle_stream_id */
233

    
234
    /* page composition segment */
235

    
236
    *q++ = 0x0f; /* sync_byte */
237
    *q++ = 0x10; /* segment_type */
238
    putbe16(&q, page_id);
239
    pseg_len = q;
240
    q += 2; /* segment length */
241
    *q++ = 30; /* page_timeout (seconds) */
242
    if (s->hide_state)
243
        page_state = 0; /* normal case */
244
    else
245
        page_state = 2; /* mode change */
246
    /* page_version = 0 + page_state */
247
    *q++ = s->object_version | (page_state << 2) | 3; 
248

    
249
    for (region_id = 0; region_id < h->num_rects; region_id++) {
250
        *q++ = region_id;
251
        *q++ = 0xff; /* reserved */
252
        putbe16(&q, h->rects[region_id].x); /* left pos */
253
        putbe16(&q, h->rects[region_id].y); /* top pos */
254
    }
255

    
256
    putbe16(&pseg_len, q - pseg_len - 2);
257

    
258
    if (!s->hide_state) {
259
        for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
260

    
261
            /* CLUT segment */
262

    
263
            if (h->rects[clut_id].nb_colors <= 4) {
264
                /* 2 bpp, some decoders do not support it correctly */
265
                bpp_index = 0;
266
            } else if (h->rects[clut_id].nb_colors <= 16) {
267
                /* 4 bpp, standard encoding */
268
                bpp_index = 1;
269
            } else {
270
                return -1;
271
            }
272

    
273
            *q++ = 0x0f; /* sync byte */
274
            *q++ = 0x12; /* CLUT definition segment */
275
            putbe16(&q, page_id);
276
            pseg_len = q;
277
            q += 2; /* segment length */
278
            *q++ = clut_id;
279
            *q++ = (0 << 4) | 0xf; /* version = 0 */
280

    
281
            for(i = 0; i < h->rects[clut_id].nb_colors; i++) {
282
                *q++ = i; /* clut_entry_id */
283
                *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
284
                {
285
                    int a, r, g, b;
286
                    a = (h->rects[clut_id].rgba_palette[i] >> 24) & 0xff;
287
                    r = (h->rects[clut_id].rgba_palette[i] >> 16) & 0xff;
288
                    g = (h->rects[clut_id].rgba_palette[i] >> 8) & 0xff;
289
                    b = (h->rects[clut_id].rgba_palette[i] >> 0) & 0xff;
290

    
291
                    *q++ = RGB_TO_Y_CCIR(r, g, b);
292
                    *q++ = RGB_TO_V_CCIR(r, g, b, 0);
293
                    *q++ = RGB_TO_U_CCIR(r, g, b, 0);
294
                    *q++ = 255 - a;
295
                }
296
            }
297

    
298
            putbe16(&pseg_len, q - pseg_len - 2);
299
        }
300
    }
301

    
302
    for (region_id = 0; region_id < h->num_rects; region_id++) {
303

    
304
        /* region composition segment */
305
        
306
        if (h->rects[region_id].nb_colors <= 4) {
307
            /* 2 bpp, some decoders do not support it correctly */
308
            bpp_index = 0;
309
        } else if (h->rects[region_id].nb_colors <= 16) {
310
            /* 4 bpp, standard encoding */
311
            bpp_index = 1;
312
        } else {
313
            return -1;
314
        }
315

    
316
        *q++ = 0x0f; /* sync_byte */
317
        *q++ = 0x11; /* segment_type */
318
        putbe16(&q, page_id);
319
        pseg_len = q;
320
        q += 2; /* segment length */
321
        *q++ = region_id;
322
        *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */
323
        putbe16(&q, h->rects[region_id].w); /* region width */
324
        putbe16(&q, h->rects[region_id].h); /* region height */
325
        *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
326
        *q++ = region_id; /* clut_id == region_id */
327
        *q++ = 0; /* 8 bit fill colors */
328
        *q++ = 0x03; /* 4 bit and 2 bit fill colors */
329

    
330
        if (!s->hide_state) {
331
            putbe16(&q, region_id); /* object_id == region_id */
332
            *q++ = (0 << 6) | (0 << 4);
333
            *q++ = 0;
334
            *q++ = 0xf0;
335
            *q++ = 0;
336
        }
337

    
338
        putbe16(&pseg_len, q - pseg_len - 2);
339
    }
340

    
341
    if (!s->hide_state) {
342
        
343
        for (object_id = 0; object_id < h->num_rects; object_id++) {
344
            /* Object Data segment */
345

    
346
            if (h->rects[object_id].nb_colors <= 4) {
347
                /* 2 bpp, some decoders do not support it correctly */
348
                bpp_index = 0;
349
            } else if (h->rects[object_id].nb_colors <= 16) {
350
                /* 4 bpp, standard encoding */
351
                bpp_index = 1;
352
            } else {
353
                return -1;
354
            }
355

    
356
            *q++ = 0x0f; /* sync byte */
357
            *q++ = 0x13;
358
            putbe16(&q, page_id);
359
            pseg_len = q;
360
            q += 2; /* segment length */
361

    
362
            putbe16(&q, object_id);
363
            *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
364
                                                                       onject_coding_method,
365
                                                                       non_modifying_color_flag */
366
            {
367
                uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
368
                void (*dvb_encode_rle)(uint8_t **pq,
369
                                        const uint8_t *bitmap, int linesize,
370
                                        int w, int h);
371
                ptop_field_len = q;
372
                q += 2;
373
                pbottom_field_len = q;
374
                q += 2;
375

    
376
                if (bpp_index == 0)
377
                    dvb_encode_rle = dvb_encode_rle2;
378
                else
379
                    dvb_encode_rle = dvb_encode_rle4;
380

    
381
                top_ptr = q;
382
                dvb_encode_rle(&q, h->rects[object_id].bitmap, h->rects[object_id].w * 2,
383
                                    h->rects[object_id].w, h->rects[object_id].h >> 1);
384
                bottom_ptr = q;
385
                dvb_encode_rle(&q, h->rects[object_id].bitmap + h->rects[object_id].w,
386
                                    h->rects[object_id].w * 2, h->rects[object_id].w,
387
                                    h->rects[object_id].h >> 1);
388

    
389
                putbe16(&ptop_field_len, bottom_ptr - top_ptr);
390
                putbe16(&pbottom_field_len, q - bottom_ptr);
391
            }
392

    
393
            putbe16(&pseg_len, q - pseg_len - 2);
394
        }
395
    }
396

    
397
    /* end of display set segment */
398

    
399
    *q++ = 0x0f; /* sync_byte */
400
    *q++ = 0x80; /* segment_type */
401
    putbe16(&q, page_id);
402
    pseg_len = q;
403
    q += 2; /* segment length */
404

    
405
    putbe16(&pseg_len, q - pseg_len - 2);
406

    
407
    *q++ = 0xff; /* end of PES data */
408

    
409
    s->object_version = (s->object_version + 1) & 0xf;
410
    s->hide_state = !s->hide_state;
411
    return q - outbuf;
412
}
413

    
414
static int dvbsub_init_decoder(AVCodecContext *avctx)
415
{
416
    return 0;
417
}
418

    
419
static int dvbsub_close_decoder(AVCodecContext *avctx)
420
{
421
    return 0;
422
}
423

    
424
static int dvbsub_encode(AVCodecContext *avctx,
425
                       unsigned char *buf, int buf_size, void *data)
426
{
427
    DVBSubtitleContext *s = avctx->priv_data;
428
    AVSubtitle *sub = data;
429
    int ret;
430

    
431
    ret = encode_dvb_subtitles(s, buf, sub);
432
    return ret;
433
}
434

    
435
AVCodec dvbsub_encoder = {
436
    "dvbsub",
437
    CODEC_TYPE_SUBTITLE,
438
    CODEC_ID_DVB_SUBTITLE,
439
    sizeof(DVBSubtitleContext),
440
    dvbsub_init_decoder,
441
    dvbsub_encode,
442
    dvbsub_close_decoder,
443
};