1 /*
2  * This file is part of libbluray
3  * Copyright (C) 2010  Petri Hintukainen <phintuka@users.sourceforge.net>
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.1 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, see
17  * <http://www.gnu.org/licenses/>.
18  */
19 
20 #if HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "pg_decode.h"
25 
26 #include "util/refcnt.h"
27 #include "util/macro.h"
28 #include "util/logging.h"
29 #include "util/bits.h"
30 
31 #include <string.h>
32 #include <stdlib.h>
33 
34 /*
35  *
36  */
37 
pg_decode_video_descriptor(BITBUFFER * bb,BD_PG_VIDEO_DESCRIPTOR * p)38 void pg_decode_video_descriptor(BITBUFFER *bb, BD_PG_VIDEO_DESCRIPTOR *p)
39 {
40     p->video_width  = bb_read(bb, 16);
41     p->video_height = bb_read(bb, 16);
42     p->frame_rate   = bb_read(bb, 4);
43     bb_skip(bb, 4);
44 }
45 
pg_decode_composition_descriptor(BITBUFFER * bb,BD_PG_COMPOSITION_DESCRIPTOR * p)46 void pg_decode_composition_descriptor(BITBUFFER *bb, BD_PG_COMPOSITION_DESCRIPTOR *p)
47 {
48     p->number = bb_read(bb, 16);
49     p->state  = bb_read(bb, 2);
50     bb_skip(bb, 6);
51 }
52 
pg_decode_sequence_descriptor(BITBUFFER * bb,BD_PG_SEQUENCE_DESCRIPTOR * p)53 void pg_decode_sequence_descriptor(BITBUFFER *bb, BD_PG_SEQUENCE_DESCRIPTOR *p)
54 {
55     p->first_in_seq = bb_read(bb, 1);
56     p->last_in_seq  = bb_read(bb, 1);
57     bb_skip(bb, 6);
58 }
59 
pg_decode_window(BITBUFFER * bb,BD_PG_WINDOW * p)60 void pg_decode_window(BITBUFFER *bb, BD_PG_WINDOW *p)
61 {
62     p->id     = bb_read(bb, 8);
63     p->x      = bb_read(bb, 16);
64     p->y      = bb_read(bb, 16);
65     p->width  = bb_read(bb, 16);
66     p->height = bb_read(bb, 16);
67 }
68 
pg_decode_composition_object(BITBUFFER * bb,BD_PG_COMPOSITION_OBJECT * p)69 void pg_decode_composition_object(BITBUFFER *bb, BD_PG_COMPOSITION_OBJECT *p)
70 {
71     p->object_id_ref = bb_read(bb, 16);
72     p->window_id_ref = bb_read(bb, 8);
73 
74     p->crop_flag      = bb_read(bb, 1);
75     p->forced_on_flag = bb_read(bb, 1);
76     bb_skip(bb, 6);
77 
78     p->x = bb_read(bb, 16);
79     p->y = bb_read(bb, 16);
80 
81     if (p->crop_flag) {
82         p->crop_x = bb_read(bb, 16);
83         p->crop_y = bb_read(bb, 16);
84         p->crop_w = bb_read(bb, 16);
85         p->crop_h = bb_read(bb, 16);
86     }
87 }
88 
pg_decode_palette_entry(BITBUFFER * bb,BD_PG_PALETTE_ENTRY * entry)89 void pg_decode_palette_entry(BITBUFFER *bb, BD_PG_PALETTE_ENTRY *entry)
90 {
91     uint8_t entry_id = bb_read(bb, 8);
92 
93     entry[entry_id].Y  = bb_read(bb, 8);
94     entry[entry_id].Cr = bb_read(bb, 8);
95     entry[entry_id].Cb = bb_read(bb, 8);
96     entry[entry_id].T  = bb_read(bb, 8);
97 }
98 
99 /*
100  * segments
101  */
102 
pg_decode_palette_update(BITBUFFER * bb,BD_PG_PALETTE * p)103 int pg_decode_palette_update(BITBUFFER *bb, BD_PG_PALETTE *p)
104 {
105     p->id      = bb_read(bb, 8);
106     p->version = bb_read(bb, 8);
107 
108     while (!bb_eof(bb)) {
109         pg_decode_palette_entry(bb, p->entry);
110     }
111 
112     return 1;
113 }
114 
pg_decode_palette(BITBUFFER * bb,BD_PG_PALETTE * p)115 int pg_decode_palette(BITBUFFER *bb, BD_PG_PALETTE *p)
116 {
117     memset(p->entry, 0, sizeof(p->entry));
118 
119     return pg_decode_palette_update(bb, p);
120 }
121 
_decode_rle(BITBUFFER * bb,BD_PG_OBJECT * p)122 static int _decode_rle(BITBUFFER *bb, BD_PG_OBJECT *p)
123 {
124     BD_PG_RLE_ELEM *tmp;
125     int pixels_left = p->width * p->height;
126     int num_rle     = 0;
127     int rle_size    = p->width * p->height / 4;
128 
129     if (rle_size < 1)
130         rle_size = 1;
131 
132     tmp = refcnt_realloc(p->img, rle_size * sizeof(BD_PG_RLE_ELEM), NULL);
133     if (!tmp) {
134         BD_DEBUG(DBG_DECODE | DBG_CRIT, "pg_decode_object(): realloc failed\n");
135         return 0;
136     }
137     p->img = tmp;
138 
139     while (!bb_eof(bb)) {
140         uint32_t len   = 1;
141         uint8_t  color = 0;
142 
143         if (!(color = bb_read(bb, 8))) {
144             if (!bb_read(bb, 1)) {
145                 if (!bb_read(bb, 1)) {
146                     len = bb_read(bb, 6);
147                 } else {
148                     len = bb_read(bb, 14);
149                 }
150             } else {
151                 if (!bb_read(bb, 1)) {
152                     len = bb_read(bb, 6);
153                 } else {
154                     len = bb_read(bb, 14);
155                 }
156                 color = bb_read(bb, 8);
157             }
158         }
159 
160         p->img[num_rle].len   = len;
161         p->img[num_rle].color = color;
162 
163         pixels_left -= len;
164 
165         if (pixels_left < 0) {
166             BD_DEBUG(DBG_DECODE, "pg_decode_object(): too many pixels (%d)\n", -pixels_left);
167             return 0;
168         }
169 
170         num_rle++;
171         if (num_rle >= rle_size) {
172             rle_size *= 2;
173             tmp = refcnt_realloc(p->img, rle_size * sizeof(BD_PG_RLE_ELEM), NULL);
174             if (!tmp) {
175                 BD_DEBUG(DBG_DECODE | DBG_CRIT, "pg_decode_object(): realloc failed\n");
176                 return 0;
177             }
178             p->img = tmp;
179         }
180     }
181 
182     if (pixels_left > 0) {
183         BD_DEBUG(DBG_DECODE, "pg_decode_object(): missing %d pixels\n", pixels_left);
184         return 0;
185     }
186 
187     return 1;
188 }
189 
pg_decode_object(BITBUFFER * bb,BD_PG_OBJECT * p)190 int pg_decode_object(BITBUFFER *bb, BD_PG_OBJECT *p)
191 {
192     BD_PG_SEQUENCE_DESCRIPTOR sd;
193 
194     p->id      = bb_read(bb, 16);
195     p->version = bb_read(bb, 8);
196 
197     pg_decode_sequence_descriptor(bb, &sd);
198 
199     /* splitted segments should be already joined */
200     if (!sd.first_in_seq) {
201         BD_DEBUG(DBG_DECODE, "pg_decode_object(): not first in sequence\n");
202         return 0;
203     }
204     if (!sd.last_in_seq) {
205         BD_DEBUG(DBG_DECODE, "pg_decode_object(): not last in sequence\n");
206         return 0;
207     }
208 
209     if (!bb_is_align(bb, 0x07)) {
210       BD_DEBUG(DBG_DECODE, "pg_decode_object(): alignment error\n");
211       return 0;
212     }
213 
214     uint32_t data_len = bb_read(bb, 24);
215     uint32_t buf_len  = bb->p_end - bb->p;
216     if (data_len != buf_len) {
217         BD_DEBUG(DBG_DECODE, "pg_decode_object(): buffer size mismatch (expected %d, have %d)\n", data_len, buf_len);
218         return 0;
219     }
220 
221     p->width  = bb_read(bb, 16);
222     p->height = bb_read(bb, 16);
223 
224     return _decode_rle(bb, p);
225 }
226 
pg_decode_composition(BITBUFFER * bb,BD_PG_COMPOSITION * p)227 int pg_decode_composition(BITBUFFER *bb, BD_PG_COMPOSITION *p)
228 {
229     unsigned ii;
230 
231     pg_decode_video_descriptor(bb, &p->video_descriptor);
232     pg_decode_composition_descriptor(bb, &p->composition_descriptor);
233 
234     p->palette_update_flag = bb_read(bb, 1);
235     bb_skip(bb, 7);
236 
237     p->palette_id_ref      = bb_read(bb, 8);
238 
239     p->num_composition_objects = bb_read(bb, 8);
240     p->composition_object      = calloc(p->num_composition_objects, sizeof(BD_PG_COMPOSITION_OBJECT));
241     if (!p->composition_object) {
242         BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
243         return 0;
244     }
245 
246     for (ii = 0; ii < p->num_composition_objects; ii++) {
247         pg_decode_composition_object(bb, &p->composition_object[ii]);
248     }
249 
250     return 1;
251 }
252 
pg_decode_windows(BITBUFFER * bb,BD_PG_WINDOWS * p)253 int pg_decode_windows(BITBUFFER *bb, BD_PG_WINDOWS *p)
254 {
255     unsigned ii;
256 
257     p->num_windows = bb_read(bb, 8);
258     p->window = calloc(p->num_windows, sizeof(BD_PG_WINDOW));
259     if (!p->window) {
260         BD_DEBUG(DBG_DECODE | DBG_CRIT, "out of memory\n");
261         return 0;
262     }
263 
264     for (ii = 0; ii < p->num_windows; ii++) {
265         pg_decode_window(bb, &p->window[ii]);
266     }
267 
268     return 1;
269 }
270 
271 /*
272  * cleanup
273  */
274 
pg_clean_object(BD_PG_OBJECT * p)275 void pg_clean_object(BD_PG_OBJECT *p)
276 {
277     if (p) {
278         bd_refcnt_dec(p->img);
279         p->img = NULL;
280     }
281 }
282 
pg_clean_windows(BD_PG_WINDOWS * p)283 void pg_clean_windows(BD_PG_WINDOWS *p)
284 {
285     if (p) {
286         X_FREE(p->window);
287     }
288 }
289 
pg_clean_composition(BD_PG_COMPOSITION * p)290 static void pg_clean_composition(BD_PG_COMPOSITION *p)
291 {
292     if (p) {
293         X_FREE(p->composition_object);
294     }
295 }
296 
pg_free_composition(BD_PG_COMPOSITION ** p)297 void pg_free_composition(BD_PG_COMPOSITION **p)
298 {
299     if (p && *p) {
300         pg_clean_composition(*p);
301         X_FREE(*p);
302     }
303 }
304