Mercurial > libavcodec.hg
comparison escape124.c @ 6556:8300baeb2b5f libavcodec
Remove flexible array member from Escape 124
Patch by Eli Friedman (eli friedman gmail com)
author | superdump |
---|---|
date | Tue, 01 Apr 2008 01:28:26 +0000 |
parents | 3de38485c56d |
children | a4104482ceef |
comparison
equal
deleted
inserted
replaced
6555:77bb7984b15e | 6556:8300baeb2b5f |
---|---|
35 } SuperBlock; | 35 } SuperBlock; |
36 | 36 |
37 typedef struct CodeBook { | 37 typedef struct CodeBook { |
38 unsigned depth; | 38 unsigned depth; |
39 unsigned size; | 39 unsigned size; |
40 MacroBlock blocks[0]; | 40 MacroBlock* blocks; |
41 } CodeBook; | 41 } CodeBook; |
42 | 42 |
43 typedef struct Escape124Context { | 43 typedef struct Escape124Context { |
44 AVFrame frame; | 44 AVFrame frame; |
45 | 45 |
46 unsigned num_superblocks; | 46 unsigned num_superblocks; |
47 | 47 |
48 CodeBook* codebooks[3]; | 48 CodeBook codebooks[3]; |
49 } Escape124Context; | 49 } Escape124Context; |
50 | 50 |
51 static int can_safely_read(GetBitContext* gb, int bits) { | 51 static int can_safely_read(GetBitContext* gb, int bits) { |
52 return get_bits_count(gb) + bits <= gb->size_in_bits; | 52 return get_bits_count(gb) + bits <= gb->size_in_bits; |
53 } | 53 } |
73 { | 73 { |
74 unsigned i; | 74 unsigned i; |
75 Escape124Context *s = avctx->priv_data; | 75 Escape124Context *s = avctx->priv_data; |
76 | 76 |
77 for (i = 0; i < 3; i++) | 77 for (i = 0; i < 3; i++) |
78 av_free(s->codebooks[i]); | 78 av_free(s->codebooks[i].blocks); |
79 | 79 |
80 if (s->frame.data[0]) | 80 if (s->frame.data[0]) |
81 avctx->release_buffer(avctx, &s->frame); | 81 avctx->release_buffer(avctx, &s->frame); |
82 | 82 |
83 return 0; | 83 return 0; |
84 } | 84 } |
85 | 85 |
86 static CodeBook* unpack_codebook(GetBitContext* gb, unsigned depth, | 86 static CodeBook unpack_codebook(GetBitContext* gb, unsigned depth, |
87 unsigned size) | 87 unsigned size) |
88 { | 88 { |
89 unsigned i, j; | 89 unsigned i, j; |
90 CodeBook* cb; | 90 CodeBook cb = { 0 }; |
91 | 91 |
92 if (!can_safely_read(gb, size * 34)) | 92 if (!can_safely_read(gb, size * 34)) |
93 return NULL; | 93 return cb; |
94 | 94 |
95 if (size >= (INT_MAX - sizeof(CodeBook)) / sizeof(MacroBlock)) | 95 if (size >= INT_MAX / sizeof(MacroBlock)) |
96 return NULL; | 96 return cb; |
97 cb = av_malloc(size * sizeof(MacroBlock) + sizeof(CodeBook)); | 97 cb.blocks = av_malloc(size ? size * sizeof(MacroBlock) : 1); |
98 if (!cb) | 98 if (!cb.blocks) |
99 return NULL; | 99 return cb; |
100 | 100 |
101 cb->depth = depth; | 101 cb.depth = depth; |
102 cb->size = size; | 102 cb.size = size; |
103 for (i = 0; i < size; i++) { | 103 for (i = 0; i < size; i++) { |
104 unsigned mask_bits = get_bits(gb, 4); | 104 unsigned mask_bits = get_bits(gb, 4); |
105 unsigned color0 = get_bits(gb, 15); | 105 unsigned color0 = get_bits(gb, 15); |
106 unsigned color1 = get_bits(gb, 15); | 106 unsigned color1 = get_bits(gb, 15); |
107 | 107 |
108 for (j = 0; j < 4; j++) { | 108 for (j = 0; j < 4; j++) { |
109 if (mask_bits & (1 << j)) | 109 if (mask_bits & (1 << j)) |
110 cb->blocks[i].pixels[j] = color1; | 110 cb.blocks[i].pixels[j] = color1; |
111 else | 111 else |
112 cb->blocks[i].pixels[j] = color0; | 112 cb.blocks[i].pixels[j] = color0; |
113 } | 113 } |
114 } | 114 } |
115 return cb; | 115 return cb; |
116 } | 116 } |
117 | 117 |
147 if (get_bits1(gb)) { | 147 if (get_bits1(gb)) { |
148 static const char transitions[3][2] = { {2, 1}, {0, 2}, {1, 0} }; | 148 static const char transitions[3][2] = { {2, 1}, {0, 2}, {1, 0} }; |
149 *codebook_index = transitions[*codebook_index][get_bits1(gb)]; | 149 *codebook_index = transitions[*codebook_index][get_bits1(gb)]; |
150 } | 150 } |
151 | 151 |
152 depth = s->codebooks[*codebook_index]->depth; | 152 depth = s->codebooks[*codebook_index].depth; |
153 | 153 |
154 // depth = 0 means that this shouldn't read any bits; | 154 // depth = 0 means that this shouldn't read any bits; |
155 // in theory, this is the same as get_bits(gb, 0), but | 155 // in theory, this is the same as get_bits(gb, 0), but |
156 // that doesn't actually work. | 156 // that doesn't actually work. |
157 block_index = depth ? get_bits(gb, depth) : 0; | 157 block_index = depth ? get_bits(gb, depth) : 0; |
158 | 158 |
159 if (*codebook_index == 1) { | 159 if (*codebook_index == 1) { |
160 block_index += superblock_index << s->codebooks[1]->depth; | 160 block_index += superblock_index << s->codebooks[1].depth; |
161 } | 161 } |
162 | 162 |
163 // This condition can occur with invalid bitstreams and | 163 // This condition can occur with invalid bitstreams and |
164 // *codebook_index == 2 | 164 // *codebook_index == 2 |
165 if (block_index >= s->codebooks[*codebook_index]->size) | 165 if (block_index >= s->codebooks[*codebook_index].size) |
166 return (MacroBlock) { { 0 } }; | 166 return (MacroBlock) { { 0 } }; |
167 | 167 |
168 return s->codebooks[*codebook_index]->blocks[block_index]; | 168 return s->codebooks[*codebook_index].blocks[block_index]; |
169 } | 169 } |
170 | 170 |
171 static void insert_mb_into_sb(SuperBlock* sb, MacroBlock mb, unsigned index) { | 171 static void insert_mb_into_sb(SuperBlock* sb, MacroBlock mb, unsigned index) { |
172 // Formula: ((index / 4) * 16 + (index % 4) * 2) / 2 | 172 // Formula: ((index / 4) * 16 + (index % 4) * 2) / 2 |
173 uint32_t *dst = sb->pixels32 + index + (index & -4); | 173 uint32_t *dst = sb->pixels32 + index + (index & -4); |
263 // FIXME: I don't think this handles integer overflow | 263 // FIXME: I don't think this handles integer overflow |
264 // properly | 264 // properly |
265 cb_size = s->num_superblocks << cb_depth; | 265 cb_size = s->num_superblocks << cb_depth; |
266 } | 266 } |
267 } | 267 } |
268 av_free(s->codebooks[i]); | 268 av_free(s->codebooks[i].blocks); |
269 s->codebooks[i] = unpack_codebook(&gb, cb_depth, cb_size); | 269 s->codebooks[i] = unpack_codebook(&gb, cb_depth, cb_size); |
270 if (!s->codebooks[i]) | 270 if (!s->codebooks[i].blocks) |
271 return -1; | 271 return -1; |
272 } | 272 } |
273 } | 273 } |
274 | 274 |
275 new_frame.reference = 3; | 275 new_frame.reference = 3; |