Mercurial > libavcodec.hg
annotate xsubdec.c @ 9830:bd0879f752e6 libavcodec
Express the H.264 parser dependency on the golomb code in configure instead of
in the Makefile as it is done for all other parts that depend on golomb.
author | diego |
---|---|
date | Tue, 09 Jun 2009 20:29:52 +0000 |
parents | 0dce4fe6e6f3 |
children | b8a9cfe64488 |
rev | line source |
---|---|
5493 | 1 /* |
2 * XSUB subtitle decoder | |
3 * Copyright (c) 2007 Reimar Döffinger | |
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 */ | |
5483 | 21 #include "avcodec.h" |
9428 | 22 #include "get_bits.h" |
5483 | 23 #include "bytestream.h" |
24 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6218
diff
changeset
|
25 static av_cold int decode_init(AVCodecContext *avctx) { |
5483 | 26 avctx->pix_fmt = PIX_FMT_PAL8; |
27 return 0; | |
28 } | |
29 | |
5484 | 30 static const uint8_t tc_offsets[9] = { 0, 1, 3, 4, 6, 7, 9, 10, 11 }; |
8769 | 31 static const uint8_t tc_muls[9] = { 10, 6, 10, 6, 10, 10, 10, 10, 1 }; |
5484 | 32 |
6218 | 33 static uint64_t parse_timecode(const uint8_t *buf) { |
5484 | 34 int i; |
35 int64_t ms = 0; | |
36 if (buf[2] != ':' || buf[5] != ':' || buf[8] != '.') | |
37 return AV_NOPTS_VALUE; | |
38 for (i = 0; i < sizeof(tc_offsets); i++) { | |
39 uint8_t c = buf[tc_offsets[i]] - '0'; | |
40 if (c > 9) return AV_NOPTS_VALUE; | |
41 ms = (ms + c) * tc_muls[i]; | |
42 } | |
43 return ms; | |
44 } | |
45 | |
5483 | 46 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8810
diff
changeset
|
47 AVPacket *avpkt) { |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8810
diff
changeset
|
48 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8810
diff
changeset
|
49 int buf_size = avpkt->size; |
5483 | 50 AVSubtitle *sub = data; |
6218 | 51 const uint8_t *buf_end = buf + buf_size; |
5483 | 52 uint8_t *bitmap; |
53 int w, h, x, y, rlelen, i; | |
54 GetBitContext gb; | |
55 | |
8810
367e4d405cd9
Set AVSubtitle format to 0. Neither dvdsubdec nor xsubdec intializes format
diego
parents:
8769
diff
changeset
|
56 sub->format = 0; |
367e4d405cd9
Set AVSubtitle format to 0. Neither dvdsubdec nor xsubdec intializes format
diego
parents:
8769
diff
changeset
|
57 |
5483 | 58 // check that at least header fits |
59 if (buf_size < 27 + 7 * 2 + 4 * 3) { | |
60 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); | |
61 return -1; | |
62 } | |
63 | |
5484 | 64 // read start and end time |
65 if (buf[0] != '[' || buf[13] != '-' || buf[26] != ']') { | |
66 av_log(avctx, AV_LOG_ERROR, "invalid time code\n"); | |
67 return -1; | |
68 } | |
5492
922a668222f0
Remove AVCodecContext parameter from parse_timecode function
reimar
parents:
5491
diff
changeset
|
69 sub->start_display_time = parse_timecode(buf + 1); |
922a668222f0
Remove AVCodecContext parameter from parse_timecode function
reimar
parents:
5491
diff
changeset
|
70 sub->end_display_time = parse_timecode(buf + 14); |
5484 | 71 buf += 27; |
72 | |
5483 | 73 // read header |
74 w = bytestream_get_le16(&buf); | |
75 h = bytestream_get_le16(&buf); | |
76 if (avcodec_check_dimensions(avctx, w, h) < 0) | |
77 return -1; | |
78 x = bytestream_get_le16(&buf); | |
79 y = bytestream_get_le16(&buf); | |
80 // skip bottom right position, it gives no new information | |
81 bytestream_get_le16(&buf); | |
82 bytestream_get_le16(&buf); | |
83 rlelen = bytestream_get_le16(&buf); | |
84 | |
85 // allocate sub and set values | |
86 if (!sub->rects) { | |
8512
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
87 sub->rects = av_mallocz(sizeof(*sub->rects)); |
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
88 sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); |
5483 | 89 sub->num_rects = 1; |
90 } | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
91 av_freep(&sub->rects[0]->pict.data[0]); |
8512
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
92 sub->rects[0]->x = x; sub->rects[0]->y = y; |
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
93 sub->rects[0]->w = w; sub->rects[0]->h = h; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
94 sub->rects[0]->pict.linesize[0] = w; |
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
95 sub->rects[0]->pict.data[0] = av_malloc(w * h); |
8512
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
96 sub->rects[0]->nb_colors = 4; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
97 sub->rects[0]->pict.data[1] = av_malloc(sub->rects[0]->nb_colors * 4); |
5483 | 98 |
99 // read palette | |
8512
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
100 for (i = 0; i < sub->rects[0]->nb_colors; i++) |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
101 ((uint32_t*)sub->rects[0]->pict.data[1])[i] = bytestream_get_be24(&buf); |
5489
dc54869af30b
Colours except background should not be transparent
reimar
parents:
5488
diff
changeset
|
102 // make all except background (first entry) non-transparent |
8512
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
103 for (i = 1; i < sub->rects[0]->nb_colors; i++) |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
104 ((uint32_t*)sub->rects[0]->pict.data[1])[i] |= 0xff000000; |
5483 | 105 |
106 // process RLE-compressed data | |
107 rlelen = FFMIN(rlelen, buf_end - buf); | |
108 init_get_bits(&gb, buf, rlelen * 8); | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
109 bitmap = sub->rects[0]->pict.data[0]; |
5483 | 110 for (y = 0; y < h; y++) { |
5490 | 111 // interlaced: do odd lines |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
112 if (y == (h + 1) / 2) bitmap = sub->rects[0]->pict.data[0] + w; |
5483 | 113 for (x = 0; x < w; ) { |
114 int log2 = ff_log2_tab[show_bits(&gb, 8)]; | |
5487
3039b660bf35
get rid of xsubdec array and calculate value instead
reimar
parents:
5486
diff
changeset
|
115 int run = get_bits(&gb, 14 - 4 * (log2 >> 1)); |
5982 | 116 int color = get_bits(&gb, 2); |
5483 | 117 run = FFMIN(run, w - x); |
118 // run length 0 means till end of row | |
119 if (!run) run = w - x; | |
5982 | 120 memset(bitmap, color, run); |
5483 | 121 bitmap += run; |
122 x += run; | |
123 } | |
5490 | 124 // interlaced, skip every second line |
125 bitmap += w; | |
5483 | 126 align_get_bits(&gb); |
127 } | |
128 *data_size = 1; | |
129 return buf_size; | |
130 } | |
131 | |
132 AVCodec xsub_decoder = { | |
133 "xsub", | |
134 CODEC_TYPE_SUBTITLE, | |
135 CODEC_ID_XSUB, | |
136 0, | |
137 decode_init, | |
138 NULL, | |
139 NULL, | |
140 decode_frame, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6710
diff
changeset
|
141 .long_name = NULL_IF_CONFIG_SMALL("XSUB"), |
5483 | 142 }; |