Mercurial > libavcodec.hg
annotate xsubdec.c @ 10345:294c444866f7 libavcodec
Make avcodec_open set codec_id and codec_type if they haven't been set.
This fixes the API breakage introduced by the check that avctx codec id and type
match the opened codec and should make (almost?) all applications work again.
author | reimar |
---|---|
date | Thu, 01 Oct 2009 15:54:55 +0000 |
parents | 8ac9bc10b485 |
children | 8a4984c5cacc |
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 |
10054
8ab9fbad11b2
Fix start_display_time/end_display_time to be relative to packet pts in xsub decoder.
reimar
parents:
10053
diff
changeset
|
33 static int64_t parse_timecode(const uint8_t *buf, int64_t packet_time) { |
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 } | |
10054
8ab9fbad11b2
Fix start_display_time/end_display_time to be relative to packet pts in xsub decoder.
reimar
parents:
10053
diff
changeset
|
43 return ms - packet_time; |
5484 | 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; | |
10054
8ab9fbad11b2
Fix start_display_time/end_display_time to be relative to packet pts in xsub decoder.
reimar
parents:
10053
diff
changeset
|
54 int64_t packet_time = 0; |
5483 | 55 GetBitContext gb; |
56 | |
10050
b8313eb3dca8
Make sure AVSubtitle is initialized, memset it to 0.
reimar
parents:
9988
diff
changeset
|
57 memset(sub, 0, sizeof(*sub)); |
8810
367e4d405cd9
Set AVSubtitle format to 0. Neither dvdsubdec nor xsubdec intializes format
diego
parents:
8769
diff
changeset
|
58 |
5483 | 59 // check that at least header fits |
60 if (buf_size < 27 + 7 * 2 + 4 * 3) { | |
61 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); | |
62 return -1; | |
63 } | |
64 | |
5484 | 65 // read start and end time |
66 if (buf[0] != '[' || buf[13] != '-' || buf[26] != ']') { | |
67 av_log(avctx, AV_LOG_ERROR, "invalid time code\n"); | |
68 return -1; | |
69 } | |
10054
8ab9fbad11b2
Fix start_display_time/end_display_time to be relative to packet pts in xsub decoder.
reimar
parents:
10053
diff
changeset
|
70 if (avpkt->pts != AV_NOPTS_VALUE) |
8ab9fbad11b2
Fix start_display_time/end_display_time to be relative to packet pts in xsub decoder.
reimar
parents:
10053
diff
changeset
|
71 packet_time = av_rescale_q(avpkt->pts, AV_TIME_BASE_Q, (AVRational){1, 1000}); |
8ab9fbad11b2
Fix start_display_time/end_display_time to be relative to packet pts in xsub decoder.
reimar
parents:
10053
diff
changeset
|
72 sub->start_display_time = parse_timecode(buf + 1, packet_time); |
8ab9fbad11b2
Fix start_display_time/end_display_time to be relative to packet pts in xsub decoder.
reimar
parents:
10053
diff
changeset
|
73 sub->end_display_time = parse_timecode(buf + 14, packet_time); |
5484 | 74 buf += 27; |
75 | |
5483 | 76 // read header |
77 w = bytestream_get_le16(&buf); | |
78 h = bytestream_get_le16(&buf); | |
79 if (avcodec_check_dimensions(avctx, w, h) < 0) | |
80 return -1; | |
81 x = bytestream_get_le16(&buf); | |
82 y = bytestream_get_le16(&buf); | |
83 // skip bottom right position, it gives no new information | |
84 bytestream_get_le16(&buf); | |
85 bytestream_get_le16(&buf); | |
86 rlelen = bytestream_get_le16(&buf); | |
87 | |
88 // allocate sub and set values | |
10053 | 89 sub->rects = av_mallocz(sizeof(*sub->rects)); |
90 sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); | |
91 sub->num_rects = 1; | |
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; |
9988
b8a9cfe64488
Set subtitle type in DVD and XSUB subtitle decoders.
stefano
parents:
9428
diff
changeset
|
94 sub->rects[0]->type = SUBTITLE_BITMAP; |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
95 sub->rects[0]->pict.linesize[0] = w; |
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
96 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
|
97 sub->rects[0]->nb_colors = 4; |
10069
8ac9bc10b485
Always allocate a buffer of AVPALETTE_SIZE for palette in the subtitle
reimar
parents:
10054
diff
changeset
|
98 sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); |
5483 | 99 |
100 // read palette | |
8512
aa45029f5cd7
Change AVSubtitle.rects to an array of pointers so ABI does not break
michael
parents:
7040
diff
changeset
|
101 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
|
102 ((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
|
103 // 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
|
104 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
|
105 ((uint32_t*)sub->rects[0]->pict.data[1])[i] |= 0xff000000; |
5483 | 106 |
107 // process RLE-compressed data | |
108 rlelen = FFMIN(rlelen, buf_end - buf); | |
109 init_get_bits(&gb, buf, rlelen * 8); | |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
110 bitmap = sub->rects[0]->pict.data[0]; |
5483 | 111 for (y = 0; y < h; y++) { |
5490 | 112 // interlaced: do odd lines |
8516
315b302fcd1d
Replace AVSubtitleRect.rgba_palette and bitmap by AVPicture.
michael
parents:
8512
diff
changeset
|
113 if (y == (h + 1) / 2) bitmap = sub->rects[0]->pict.data[0] + w; |
5483 | 114 for (x = 0; x < w; ) { |
115 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
|
116 int run = get_bits(&gb, 14 - 4 * (log2 >> 1)); |
5982 | 117 int color = get_bits(&gb, 2); |
5483 | 118 run = FFMIN(run, w - x); |
119 // run length 0 means till end of row | |
120 if (!run) run = w - x; | |
5982 | 121 memset(bitmap, color, run); |
5483 | 122 bitmap += run; |
123 x += run; | |
124 } | |
5490 | 125 // interlaced, skip every second line |
126 bitmap += w; | |
5483 | 127 align_get_bits(&gb); |
128 } | |
129 *data_size = 1; | |
130 return buf_size; | |
131 } | |
132 | |
133 AVCodec xsub_decoder = { | |
134 "xsub", | |
135 CODEC_TYPE_SUBTITLE, | |
136 CODEC_ID_XSUB, | |
137 0, | |
138 decode_init, | |
139 NULL, | |
140 NULL, | |
141 decode_frame, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6710
diff
changeset
|
142 .long_name = NULL_IF_CONFIG_SMALL("XSUB"), |
5483 | 143 }; |