/src/vlc/modules/codec/dvbsub.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * dvbsub.c : DVB subtitles decoder |
3 | | * DVB subtitles encoder (developed for Anevia, www.anevia.com) |
4 | | ***************************************************************************** |
5 | | * Copyright (C) 2003 ANEVIA |
6 | | * Copyright (C) 2003-2009 VLC authors and VideoLAN |
7 | | * |
8 | | * Authors: Gildas Bazin <gbazin@videolan.org> |
9 | | * Damien LUCAS <damien.lucas@anevia.com> |
10 | | * Laurent Aimar <fenrir@via.ecp.fr> |
11 | | * Jean-Paul Saman <jpsaman #_at_# m2x dot nl> |
12 | | * Derk-Jan Hartman <hartman #at# videolan dot org> |
13 | | * Simon Hailes <simon _a_ screen.subtitling.com> |
14 | | * |
15 | | * This program is free software; you can redistribute it and/or modify it |
16 | | * under the terms of the GNU Lesser General Public License as published by |
17 | | * the Free Software Foundation; either version 2.1 of the License, or |
18 | | * (at your option) any later version. |
19 | | * |
20 | | * This program is distributed in the hope that it will be useful, |
21 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | | * GNU Lesser General Public License for more details. |
24 | | * |
25 | | * You should have received a copy of the GNU Lesser General Public License |
26 | | * along with this program; if not, write to the Free Software Foundation, Inc., |
27 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
28 | | *****************************************************************************/ |
29 | | |
30 | | /***************************************************************************** |
31 | | * Preamble |
32 | | * |
33 | | * FIXME: |
34 | | * DVB subtitles coded as strings of characters are not handled correctly. |
35 | | * The character codes in the string should actually be indexes referring to a |
36 | | * character table identified in the subtitle descriptor. |
37 | | * |
38 | | * The spec is quite vague in this area, but what is meant is perhaps that it |
39 | | * refers to the character index in the codepage belonging to the language |
40 | | * specified in the subtitle descriptor. Potentially it's designed for widechar |
41 | | * (but not for UTF-*) codepages. |
42 | | ***************************************************************************** |
43 | | * |
44 | | ***************************************************************************** |
45 | | * Notes on DDS (Display Definition Segment) |
46 | | * ----------------------------------------- |
47 | | * DDS (Display Definition Segment) tells the decoder how the subtitle image |
48 | | * relates to the video image. |
49 | | * For SD, the subtitle image is always considered to be for display at |
50 | | * 720x576 (although it's assumed that for NTSC, this is 720x480, this |
51 | | * is not documented well) Also, for SD, the subtitle image is drawn 'on |
52 | | * the glass' (i.e. after video scaling, letterbox, etc.) |
53 | | * For 'HD' (subs marked type 0x14/0x24 in PSI), a DDS must be present, |
54 | | * and the subs area is drawn onto the video area (scales if necessary). |
55 | | * The DDS tells the decoder what resolution the subtitle images were |
56 | | * intended for, and hence how to scale the subtitle images for a |
57 | | * particular video size |
58 | | * i.e. if HD video is presented as letterbox, the subs will be in the |
59 | | * same place on the video as if the video was presented on an HD set |
60 | | * indeed, if the HD video was pillarboxed by the decoder, the subs may |
61 | | * be cut off as well as the video. The intent here is that the subs can |
62 | | * be placed accurately on the video - something which was missed in the |
63 | | * original spec. |
64 | | * |
65 | | * A DDS may also specify a window - this is where the subs images are moved so that the (0,0) |
66 | | * origin of decode is offset. |
67 | | ********************************************************************************************/ |
68 | | |
69 | | #ifdef HAVE_CONFIG_H |
70 | | # include "config.h" |
71 | | #endif |
72 | | |
73 | | #include <vlc_common.h> |
74 | | #include <vlc_configuration.h> |
75 | | #include <vlc_plugin.h> |
76 | | #include <vlc_codec.h> |
77 | | #include <vlc_sout.h> |
78 | | #include <vlc_arrays.h> |
79 | | |
80 | | #include <vlc_bits.h> |
81 | | |
82 | | #include <limits.h> |
83 | | #include <stdckdint.h> |
84 | | |
85 | | /* #define DEBUG_DVBSUB 1 */ |
86 | | |
87 | | #define POSX_TEXT N_("Decoding X coordinate") |
88 | | #define POSX_LONGTEXT N_("X coordinate of the rendered subtitle") |
89 | | |
90 | | #define POSY_TEXT N_("Decoding Y coordinate") |
91 | | #define POSY_LONGTEXT N_("Y coordinate of the rendered subtitle") |
92 | | |
93 | | #define POS_TEXT N_("Subpicture position") |
94 | | #define POS_LONGTEXT N_( \ |
95 | | "You can enforce the subpicture position on the video " \ |
96 | | "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \ |
97 | | "also use combinations of these values, e.g. 6=top-right).") |
98 | | |
99 | | #define ENC_POSX_TEXT N_("Encoding X coordinate") |
100 | | #define ENC_POSX_LONGTEXT N_("X coordinate of the encoded subtitle" ) |
101 | | #define ENC_POSY_TEXT N_("Encoding Y coordinate") |
102 | | #define ENC_POSY_LONGTEXT N_("Y coordinate of the encoded subtitle" ) |
103 | | |
104 | | static const int pi_pos_values[] = { |
105 | | 0, |
106 | | SUBPICTURE_ALIGN_LEFT, |
107 | | SUBPICTURE_ALIGN_RIGHT, |
108 | | SUBPICTURE_ALIGN_TOP, |
109 | | SUBPICTURE_ALIGN_BOTTOM, |
110 | | SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT, |
111 | | SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_RIGHT, |
112 | | SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_LEFT, |
113 | | SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_RIGHT, |
114 | | }; |
115 | | static const char *const ppsz_pos_descriptions[] = |
116 | | { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"), |
117 | | N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") }; |
118 | | |
119 | | /***************************************************************************** |
120 | | * Module descriptor. |
121 | | *****************************************************************************/ |
122 | | static int Open ( vlc_object_t * ); |
123 | | static void Close( vlc_object_t * ); |
124 | | static int Decode( decoder_t *, block_t * ); |
125 | | static void Flush( decoder_t * ); |
126 | | |
127 | | #ifdef ENABLE_SOUT |
128 | | static int OpenEncoder ( vlc_object_t * ); |
129 | | static void CloseEncoder( encoder_t * ); |
130 | | static block_t *Encode ( encoder_t *, subpicture_t * ); |
131 | | #endif |
132 | | |
133 | 174 | vlc_module_begin () |
134 | 87 | # define DVBSUB_CFG_PREFIX "dvbsub-" |
135 | 87 | set_description( N_("DVB subtitles decoder") ) |
136 | 87 | set_shortname( N_("DVB subtitles") ) |
137 | 87 | set_capability( "spu decoder", 80 ) |
138 | 87 | set_subcategory( SUBCAT_INPUT_SCODEC ) |
139 | 87 | set_callbacks( Open, Close ) |
140 | | |
141 | 87 | add_integer( DVBSUB_CFG_PREFIX "position", 8, POS_TEXT, POS_LONGTEXT ) |
142 | 87 | change_integer_list( pi_pos_values, ppsz_pos_descriptions ) |
143 | 87 | add_integer( DVBSUB_CFG_PREFIX "x", -1, POSX_TEXT, POSX_LONGTEXT ) |
144 | 87 | add_integer( DVBSUB_CFG_PREFIX "y", -1, POSY_TEXT, POSY_LONGTEXT ) |
145 | | |
146 | 87 | #ifdef ENABLE_SOUT |
147 | 87 | # define ENC_CFG_PREFIX "sout-dvbsub-" |
148 | 87 | add_submodule () |
149 | 87 | set_description( N_("DVB subtitles encoder") ) |
150 | 87 | set_capability( "spu encoder", 100 ) |
151 | 87 | set_callback( OpenEncoder ) |
152 | | |
153 | 87 | add_integer( ENC_CFG_PREFIX "x", -1, ENC_POSX_TEXT, ENC_POSX_LONGTEXT ) |
154 | 87 | add_integer( ENC_CFG_PREFIX "y", -1, ENC_POSY_TEXT, ENC_POSY_LONGTEXT ) |
155 | 87 | #endif |
156 | 87 | vlc_module_end () |
157 | | |
158 | | static const char *const ppsz_enc_options[] = { "x", "y", NULL }; |
159 | | |
160 | | /**************************************************************************** |
161 | | * Local structures |
162 | | **************************************************************************** |
163 | | * Those structures refer closely to the ETSI 300 743 Object model |
164 | | ****************************************************************************/ |
165 | | |
166 | | /* The object definition gives the position of the object in a region [7.2.5] */ |
167 | | typedef struct dvbsub_objectdef_s |
168 | | { |
169 | | int i_id; |
170 | | int i_type; |
171 | | int i_x; |
172 | | int i_y; |
173 | | int i_fg_pc; |
174 | | int i_bg_pc; |
175 | | char *psz_text; /* for string of characters objects */ |
176 | | |
177 | | } dvbsub_objectdef_t; |
178 | | |
179 | | /* The entry in the palette CLUT */ |
180 | | typedef struct |
181 | | { |
182 | | uint8_t Y; |
183 | | uint8_t Cr; |
184 | | uint8_t Cb; |
185 | | uint8_t T; |
186 | | |
187 | | } dvbsub_color_t; |
188 | | |
189 | | /* The displays dimensions [7.2.1] */ |
190 | | typedef struct dvbsub_display_s |
191 | | { |
192 | | uint8_t i_id; |
193 | | uint8_t i_version; |
194 | | |
195 | | uint16_t i_width_minus1; |
196 | | uint16_t i_height_minus1; |
197 | | |
198 | | bool b_windowed; |
199 | | /* these values are only relevant if windowed */ |
200 | | int i_x; |
201 | | int i_y; |
202 | | int i_max_x; |
203 | | int i_max_y; |
204 | | |
205 | | } dvbsub_display_t; |
206 | | |
207 | | /* [7.2.4] */ |
208 | | typedef struct dvbsub_clut_s |
209 | | { |
210 | | uint8_t i_id; |
211 | | uint8_t i_version; |
212 | | dvbsub_color_t c_2b[4]; |
213 | | dvbsub_color_t c_4b[16]; |
214 | | dvbsub_color_t c_8b[256]; |
215 | | int c_8b_entries; |
216 | | video_color_range_t color_range; |
217 | | int dynamic_range_and_colour_gamut; |
218 | | |
219 | | struct dvbsub_clut_s *p_next; |
220 | | |
221 | | } dvbsub_clut_t; |
222 | | |
223 | | /* The Region is an area on the image [7.2.3] |
224 | | * with a list of the object definitions associated and a CLUT */ |
225 | | typedef struct dvbsub_region_s |
226 | | { |
227 | | int i_id; |
228 | | int i_version; |
229 | | int i_x; |
230 | | int i_y; |
231 | | int i_width; |
232 | | int i_height; |
233 | | int i_level_comp; |
234 | | int i_depth; |
235 | | int i_clut; |
236 | | |
237 | | uint8_t *p_pixbuf; |
238 | | |
239 | | int i_object_defs; |
240 | | dvbsub_objectdef_t *p_object_defs; |
241 | | |
242 | | struct dvbsub_region_s *p_next; |
243 | | |
244 | | } dvbsub_region_t; |
245 | | |
246 | | /* The object definition gives the position of the object in a region */ |
247 | | typedef struct dvbsub_regiondef_s |
248 | | { |
249 | | int i_id; |
250 | | int i_x; |
251 | | int i_y; |
252 | | |
253 | | } dvbsub_regiondef_t; |
254 | | |
255 | | /* The page defines the list of regions [7.2.2] */ |
256 | | typedef struct |
257 | | { |
258 | | int i_id; |
259 | | int i_timeout; /* in seconds */ |
260 | | int i_state; |
261 | | int i_version; |
262 | | |
263 | | int i_region_defs; |
264 | | dvbsub_regiondef_t *p_region_defs; |
265 | | |
266 | | } dvbsub_page_t; |
267 | | |
268 | | typedef struct |
269 | | { |
270 | | bs_t bs; |
271 | | |
272 | | /* Decoder internal data */ |
273 | | int i_id; |
274 | | int i_ancillary_id; |
275 | | vlc_tick_t i_pts; |
276 | | |
277 | | int i_spu_position; |
278 | | int i_spu_x; |
279 | | int i_spu_y; |
280 | | |
281 | | bool b_page; |
282 | | dvbsub_page_t *p_page; |
283 | | dvbsub_region_t *p_regions; |
284 | | dvbsub_clut_t *p_cluts; |
285 | | /* this is very small, so keep forever */ |
286 | | dvbsub_display_t display; |
287 | | dvbsub_clut_t default_clut; |
288 | | } decoder_sys_t; |
289 | | |
290 | | |
291 | | /* List of different SEGMENT TYPES */ |
292 | | /* According to EN 300-743, table 2 */ |
293 | 4.32k | #define DVBSUB_ST_PAGE_COMPOSITION 0x10 |
294 | 3.80k | #define DVBSUB_ST_REGION_COMPOSITION 0x11 |
295 | 2.88k | #define DVBSUB_ST_CLUT_DEFINITION 0x12 |
296 | 4.64k | #define DVBSUB_ST_OBJECT_DATA 0x13 |
297 | 4.85k | #define DVBSUB_ST_DISPLAY_DEFINITION 0x14 |
298 | 1.77k | #define DVBSUB_ST_ALTERNATE_CLUT 0x16 |
299 | 830 | #define DVBSUB_ST_ENDOFDISPLAY 0x80 |
300 | 975 | #define DVBSUB_ST_STUFFING 0xff |
301 | | /* List of different OBJECT TYPES */ |
302 | | /* According to EN 300-743, table 6 */ |
303 | 0 | #define DVBSUB_OT_BASIC_BITMAP 0x00 |
304 | 315k | #define DVBSUB_OT_BASIC_CHAR 0x01 |
305 | 315k | #define DVBSUB_OT_COMPOSITE_STRING 0x02 |
306 | | /* Pixel DATA TYPES */ |
307 | | /* According to EN 300-743, table 9 */ |
308 | | #define DVBSUB_DT_2BP_CODE_STRING 0x10 |
309 | | #define DVBSUB_DT_4BP_CODE_STRING 0x11 |
310 | | #define DVBSUB_DT_8BP_CODE_STRING 0x12 |
311 | | #define DVBSUB_DT_24_TABLE_DATA 0x20 |
312 | | #define DVBSUB_DT_28_TABLE_DATA 0x21 |
313 | | #define DVBSUB_DT_48_TABLE_DATA 0x22 |
314 | | #define DVBSUB_DT_END_LINE 0xf0 |
315 | | /* List of different Page Composition Segment state */ |
316 | | /* According to EN 300-743, 7.2.1 table 3 */ |
317 | 600 | #define DVBSUB_PCS_STATE_ACQUISITION 0x01 |
318 | 4.54k | #define DVBSUB_PCS_STATE_CHANGE 0x02 |
319 | | /* According to EN 300-743, 7.2.8 table 33 */ |
320 | 1.04k | #define DVBSUB_ST_BITDEPTH_8BIT 0x00 |
321 | 10.3k | #define DVBSUB_ST_BITDEPTH_10BIT 0x01 |
322 | | /* According to EN 300-743, 7.2.8 table 34 */ |
323 | 2.32k | #define DVBSUB_ST_COLORIMETRY_CDS -1 |
324 | 4 | #define DVBSUB_ST_COLORIMETRY_SDR_709 0x00 |
325 | 0 | #define DVBSUB_ST_COLORIMETRY_SDR_2020 0x01 |
326 | 0 | #define DVBSUB_ST_COLORIMETRY_HDR_PQ 0x02 |
327 | 523 | #define DVBSUB_ST_COLORIMETRY_HDR_HLG 0x03 |
328 | | |
329 | | /***************************************************************************** |
330 | | * Local prototypes |
331 | | *****************************************************************************/ |
332 | | static void decode_segment( decoder_t *, bs_t * ); |
333 | | static void decode_page_composition( decoder_t *, bs_t *, uint16_t ); |
334 | | static void decode_region_composition( decoder_t *, bs_t *, uint16_t ); |
335 | | static void decode_object( decoder_t *, bs_t *, uint16_t ); |
336 | | static void decode_display_definition( decoder_t *, bs_t *, uint16_t ); |
337 | | static void alternative_CLUT( decoder_t *, bs_t *, uint16_t ); |
338 | | static void decode_clut( decoder_t *, bs_t *, uint16_t ); |
339 | | static void free_all( decoder_t * ); |
340 | | |
341 | | static void default_clut_init( decoder_t * ); |
342 | | static void default_dds_init( decoder_t * ); |
343 | | |
344 | | static subpicture_t *render( decoder_t * ); |
345 | | |
346 | | /***************************************************************************** |
347 | | * Open: probe the decoder and return score |
348 | | ***************************************************************************** |
349 | | * Tries to launch a decoder and return score so that the interface is able |
350 | | * to chose. |
351 | | *****************************************************************************/ |
352 | | static int Open( vlc_object_t *p_this ) |
353 | 25.7k | { |
354 | 25.7k | decoder_t *p_dec = (decoder_t *) p_this; |
355 | 25.7k | decoder_sys_t *p_sys; |
356 | 25.7k | int i_posx, i_posy; |
357 | | |
358 | 25.7k | if( p_dec->fmt_in->i_codec != VLC_CODEC_DVBS ) |
359 | 23.6k | { |
360 | 23.6k | return VLC_EGENERIC; |
361 | 23.6k | } |
362 | | |
363 | 2.12k | p_dec->pf_decode = Decode; |
364 | 2.12k | p_dec->pf_flush = Flush; |
365 | 2.12k | p_sys = p_dec->p_sys = calloc( 1, sizeof(decoder_sys_t) ); |
366 | 2.12k | if( !p_sys ) |
367 | 0 | return VLC_ENOMEM; |
368 | | |
369 | 2.12k | p_sys->i_pts = VLC_TICK_INVALID; |
370 | 2.12k | p_sys->i_id = p_dec->fmt_in->subs.dvb.i_id & 0xFFFF; |
371 | 2.12k | p_sys->i_ancillary_id = p_dec->fmt_in->subs.dvb.i_id >> 16; |
372 | | |
373 | 2.12k | p_sys->p_regions = NULL; |
374 | 2.12k | p_sys->p_cluts = NULL; |
375 | 2.12k | p_sys->p_page = NULL; |
376 | | |
377 | | /* configure for SD res in case DDS is not present */ |
378 | 2.12k | default_dds_init( p_dec ); |
379 | | |
380 | 2.12k | p_sys->i_spu_position = var_CreateGetInteger( p_this, |
381 | 2.12k | DVBSUB_CFG_PREFIX "position" ); |
382 | 2.12k | i_posx = var_CreateGetInteger( p_this, DVBSUB_CFG_PREFIX "x" ); |
383 | 2.12k | i_posy = var_CreateGetInteger( p_this, DVBSUB_CFG_PREFIX "y" ); |
384 | | |
385 | | /* Check if subpicture position was overridden */ |
386 | 2.12k | p_sys->i_spu_x = p_sys->i_spu_y = 0; |
387 | | |
388 | 2.12k | if( ( i_posx >= 0 ) && ( i_posy >= 0 ) ) |
389 | 0 | { |
390 | 0 | p_sys->i_spu_x = i_posx; |
391 | 0 | p_sys->i_spu_y = i_posy; |
392 | 0 | } |
393 | | |
394 | 2.12k | p_dec->fmt_out.i_codec = 0; |
395 | | |
396 | 2.12k | default_clut_init( p_dec ); |
397 | | |
398 | 2.12k | return VLC_SUCCESS; |
399 | 2.12k | } |
400 | | |
401 | | /***************************************************************************** |
402 | | * Close: |
403 | | *****************************************************************************/ |
404 | | static void Close( vlc_object_t *p_this ) |
405 | 2.12k | { |
406 | 2.12k | decoder_t *p_dec = (decoder_t*) p_this; |
407 | 2.12k | decoder_sys_t *p_sys = p_dec->p_sys; |
408 | | |
409 | 2.12k | var_Destroy( p_this, DVBSUB_CFG_PREFIX "x" ); |
410 | 2.12k | var_Destroy( p_this, DVBSUB_CFG_PREFIX "y" ); |
411 | 2.12k | var_Destroy( p_this, DVBSUB_CFG_PREFIX "position" ); |
412 | | |
413 | 2.12k | free_all( p_dec ); |
414 | 2.12k | free( p_sys ); |
415 | 2.12k | } |
416 | | |
417 | | /***************************************************************************** |
418 | | * Flush: |
419 | | *****************************************************************************/ |
420 | | static void Flush( decoder_t *p_dec ) |
421 | 0 | { |
422 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
423 | |
|
424 | 0 | p_sys->i_pts = VLC_TICK_INVALID; |
425 | 0 | } |
426 | | |
427 | | /***************************************************************************** |
428 | | * Decode: |
429 | | *****************************************************************************/ |
430 | | static int Decode( decoder_t *p_dec, block_t *p_block ) |
431 | 12.9k | { |
432 | 12.9k | decoder_sys_t *p_sys = p_dec->p_sys; |
433 | | |
434 | 12.9k | if( p_block == NULL ) /* No Drain */ |
435 | 7.52k | return VLCDEC_SUCCESS; |
436 | | |
437 | 5.38k | if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) ) |
438 | 0 | { |
439 | 0 | Flush( p_dec ); |
440 | 0 | if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) |
441 | 0 | goto end; |
442 | 0 | } |
443 | | |
444 | | /* configure for SD res in case DDS is not present */ |
445 | | /* a change of PTS is a good indication we must get a new DDS */ |
446 | 5.38k | if( p_sys->i_pts != p_block->i_pts ) |
447 | 3.86k | default_dds_init( p_dec ); |
448 | | |
449 | 5.38k | p_sys->i_pts = p_block->i_pts; |
450 | 5.38k | if( p_sys->i_pts == VLC_TICK_INVALID ) |
451 | 2 | { |
452 | | #ifdef DEBUG_DVBSUB |
453 | | /* Some DVB channels send stuffing segments in non-dated packets so |
454 | | * don't complain too loudly. */ |
455 | | msg_Warn( p_dec, "non dated subtitle" ); |
456 | | #endif |
457 | 2 | goto end; |
458 | 2 | } |
459 | | |
460 | 5.38k | bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer ); |
461 | | |
462 | 5.38k | if( bs_read( &p_sys->bs, 8 ) != 0x20 ) /* Data identifier */ |
463 | 47 | { |
464 | 47 | msg_Dbg( p_dec, "invalid data identifier" ); |
465 | 47 | goto end; |
466 | 47 | } |
467 | | |
468 | 5.33k | if( bs_read( &p_sys->bs, 8 ) ) /* Subtitle stream id */ |
469 | 62 | { |
470 | 62 | msg_Dbg( p_dec, "invalid subtitle stream id" ); |
471 | 62 | goto end; |
472 | 62 | } |
473 | | |
474 | | #ifdef DEBUG_DVBSUB |
475 | | msg_Dbg( p_dec, "subtitle packet received: %"PRId64, p_sys->i_pts ); |
476 | | #endif |
477 | | |
478 | 5.27k | p_sys->b_page = false; |
479 | | |
480 | 5.27k | uint8_t i_sync_byte = bs_read( &p_sys->bs, 8 ); |
481 | 30.6k | while( i_sync_byte == 0x0f ) /* Sync byte */ |
482 | 25.3k | { |
483 | 25.3k | decode_segment( p_dec, &p_sys->bs ); |
484 | 25.3k | i_sync_byte = bs_read( &p_sys->bs, 8 ); |
485 | 25.3k | } |
486 | | |
487 | 5.27k | if( ( i_sync_byte & 0x3f ) != 0x3f ) /* End marker */ |
488 | 4.10k | { |
489 | 4.10k | msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" ); |
490 | 4.10k | goto end; |
491 | 4.10k | } |
492 | | |
493 | | /* Check if the page is to be displayed */ |
494 | 1.17k | if( p_sys->p_page && p_sys->b_page ) |
495 | 588 | { |
496 | 588 | subpicture_t *p_spu = render( p_dec ); |
497 | 588 | if( p_spu != NULL ) |
498 | 588 | decoder_QueueSub( p_dec, p_spu ); |
499 | 588 | } |
500 | | |
501 | 5.38k | end: |
502 | 5.38k | block_Release(p_block); |
503 | 5.38k | return VLCDEC_SUCCESS; |
504 | 1.17k | } |
505 | | |
506 | | /* following functions are local */ |
507 | | |
508 | | /***************************************************************************** |
509 | | * default_clut_init: default clut as defined in EN 300-743 section 10 |
510 | | *****************************************************************************/ |
511 | | static void default_clut_init( decoder_t *p_dec ) |
512 | 2.12k | { |
513 | 2.12k | decoder_sys_t *p_sys = p_dec->p_sys; |
514 | 2.12k | uint8_t i; |
515 | | |
516 | 42.5k | #define RGB_TO_Y(r, g, b) ((int16_t) 77 * r + 150 * g + 29 * b) / 256; |
517 | 42.5k | #define RGB_TO_U(r, g, b) ((int16_t) -44 * r - 87 * g + 131 * b) / 256; |
518 | 42.5k | #define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256; |
519 | | |
520 | | /* 4 entries CLUT */ |
521 | 10.6k | for( i = 0; i < 4; i++ ) |
522 | 8.50k | { |
523 | 8.50k | uint8_t R = 0, G = 0, B = 0, T = 0; |
524 | | |
525 | 8.50k | if( !(i & 0x2) && !(i & 0x1) ) T = 0xFF; |
526 | 6.37k | else if( !(i & 0x2) && (i & 0x1) ) R = G = B = 0xFF; |
527 | 4.25k | else if( (i & 0x2) && !(i & 0x1) ) R = G = B = 0; |
528 | 2.12k | else R = G = B = 0x7F; |
529 | | |
530 | 8.50k | p_sys->default_clut.c_2b[i].Y = RGB_TO_Y(R,G,B); |
531 | 8.50k | p_sys->default_clut.c_2b[i].Cb = RGB_TO_V(R,G,B); |
532 | 8.50k | p_sys->default_clut.c_2b[i].Cr = RGB_TO_U(R,G,B); |
533 | 8.50k | p_sys->default_clut.c_2b[i].T = T; |
534 | 8.50k | } |
535 | | |
536 | | /* 16 entries CLUT */ |
537 | 36.1k | for( i = 0; i < 16; i++ ) |
538 | 34.0k | { |
539 | 34.0k | uint8_t R = 0, G = 0, B = 0, T = 0; |
540 | | |
541 | 34.0k | if( !(i & 0x8) ) |
542 | 17.0k | { |
543 | 17.0k | if( !(i & 0x4) && !(i & 0x2) && !(i & 0x1) ) |
544 | 2.12k | { |
545 | 2.12k | T = 0xFF; |
546 | 2.12k | } |
547 | 14.8k | else |
548 | 14.8k | { |
549 | 14.8k | R = (i & 0x1) ? 0xFF : 0; |
550 | 14.8k | G = (i & 0x2) ? 0xFF : 0; |
551 | 14.8k | B = (i & 0x4) ? 0xFF : 0; |
552 | 14.8k | } |
553 | 17.0k | } |
554 | 17.0k | else |
555 | 17.0k | { |
556 | 17.0k | R = (i & 0x1) ? 0x7F : 0; |
557 | 17.0k | G = (i & 0x2) ? 0x7F : 0; |
558 | 17.0k | B = (i & 0x4) ? 0x7F : 0; |
559 | 17.0k | } |
560 | | |
561 | 34.0k | p_sys->default_clut.c_4b[i].Y = RGB_TO_Y(R,G,B); |
562 | 34.0k | p_sys->default_clut.c_4b[i].Cr = RGB_TO_V(R,G,B); |
563 | 34.0k | p_sys->default_clut.c_4b[i].Cb = RGB_TO_U(R,G,B); |
564 | 34.0k | p_sys->default_clut.c_4b[i].T = T; |
565 | 34.0k | } |
566 | | |
567 | | /* 256 entries CLUT */ |
568 | 2.12k | memset( p_sys->default_clut.c_8b, 0xFF, 256 * sizeof(dvbsub_color_t) ); |
569 | 2.12k | p_sys->default_clut.c_8b_entries = 256; |
570 | 2.12k | p_sys->default_clut.color_range = COLOR_RANGE_LIMITED; |
571 | 2.12k | p_sys->default_clut.dynamic_range_and_colour_gamut = DVBSUB_ST_COLORIMETRY_CDS; |
572 | 2.12k | } |
573 | | |
574 | | static void decode_segment( decoder_t *p_dec, bs_t *s ) |
575 | 25.3k | { |
576 | 25.3k | decoder_sys_t *p_sys = p_dec->p_sys; |
577 | 25.3k | int i_type; |
578 | 25.3k | int i_page_id; |
579 | 25.3k | int i_size; |
580 | | |
581 | | /* sync_byte (already checked) */ |
582 | | //bs_skip( s, 8 ); |
583 | | |
584 | | /* segment type */ |
585 | 25.3k | i_type = bs_read( s, 8 ); |
586 | | |
587 | | /* page id */ |
588 | 25.3k | i_page_id = bs_read( s, 16 ); |
589 | | |
590 | | /* segment size */ |
591 | 25.3k | i_size = bs_read( s, 16 ); |
592 | | |
593 | 25.3k | if( ( i_page_id != p_sys->i_id ) && |
594 | 741 | ( i_page_id != p_sys->i_ancillary_id ) ) |
595 | 741 | { |
596 | | #ifdef DEBUG_DVBSUB |
597 | | msg_Dbg( p_dec, "subtitle skipped (page id: %i, %i)", |
598 | | i_page_id, p_sys->i_id ); |
599 | | #endif |
600 | 741 | bs_skip( s, 8 * i_size ); |
601 | 741 | return; |
602 | 741 | } |
603 | | |
604 | 24.6k | if( ( p_sys->i_ancillary_id != p_sys->i_id ) && |
605 | 0 | ( i_type == DVBSUB_ST_PAGE_COMPOSITION ) && |
606 | 0 | ( i_page_id == p_sys->i_ancillary_id ) ) |
607 | 0 | { |
608 | | #ifdef DEBUG_DVBSUB |
609 | | msg_Dbg( p_dec, "skipped invalid ancillary subtitle packet" ); |
610 | | #endif |
611 | 0 | bs_skip( s, 8 * i_size ); |
612 | 0 | return; |
613 | 0 | } |
614 | | |
615 | | #ifdef DEBUG_DVBSUB |
616 | | if( i_page_id == p_sys->i_id ) |
617 | | msg_Dbg( p_dec, "segment (id: %i)", i_page_id ); |
618 | | else |
619 | | msg_Dbg( p_dec, "ancillary segment (id: %i)", i_page_id ); |
620 | | #endif |
621 | | |
622 | 24.6k | switch( i_type ) |
623 | 24.6k | { |
624 | 4.32k | case DVBSUB_ST_PAGE_COMPOSITION: |
625 | | #ifdef DEBUG_DVBSUB |
626 | | msg_Dbg( p_dec, "decode_page_composition" ); |
627 | | #endif |
628 | 4.32k | decode_page_composition( p_dec, s, i_size ); |
629 | 4.32k | break; |
630 | | |
631 | 3.80k | case DVBSUB_ST_REGION_COMPOSITION: |
632 | | #ifdef DEBUG_DVBSUB |
633 | | msg_Dbg( p_dec, "decode_region_composition" ); |
634 | | #endif |
635 | 3.80k | decode_region_composition( p_dec, s, i_size ); |
636 | 3.80k | break; |
637 | | |
638 | 2.88k | case DVBSUB_ST_CLUT_DEFINITION: |
639 | | #ifdef DEBUG_DVBSUB |
640 | | msg_Dbg( p_dec, "decode_clut" ); |
641 | | #endif |
642 | 2.88k | decode_clut( p_dec, s, i_size ); |
643 | 2.88k | break; |
644 | | |
645 | 4.64k | case DVBSUB_ST_OBJECT_DATA: |
646 | | #ifdef DEBUG_DVBSUB |
647 | | msg_Dbg( p_dec, "decode_object" ); |
648 | | #endif |
649 | 4.64k | decode_object( p_dec, s, i_size ); |
650 | 4.64k | break; |
651 | | |
652 | 4.85k | case DVBSUB_ST_DISPLAY_DEFINITION: |
653 | | #ifdef DEBUG_DVBSUB |
654 | | msg_Dbg( p_dec, "decode_display_definition" ); |
655 | | #endif |
656 | 4.85k | decode_display_definition( p_dec, s, i_size ); |
657 | 4.85k | break; |
658 | | |
659 | 1.77k | case DVBSUB_ST_ALTERNATE_CLUT: |
660 | | #ifdef DEBUG_DVBSUB |
661 | | msg_Dbg( p_dec, "alternative_CLUT" ); |
662 | | #endif |
663 | 1.77k | alternative_CLUT( p_dec, s, i_size ); |
664 | 1.77k | break; |
665 | | |
666 | 830 | case DVBSUB_ST_ENDOFDISPLAY: |
667 | | #ifdef DEBUG_DVBSUB |
668 | | msg_Dbg( p_dec, "end of display" ); |
669 | | #endif |
670 | 830 | bs_skip( s, 8 * i_size ); |
671 | 830 | break; |
672 | | |
673 | 975 | case DVBSUB_ST_STUFFING: |
674 | | #ifdef DEBUG_DVBSUB |
675 | | msg_Dbg( p_dec, "skip stuffing" ); |
676 | | #endif |
677 | 975 | bs_skip( s, 8 * i_size ); |
678 | 975 | break; |
679 | | |
680 | 559 | default: |
681 | 559 | msg_Warn( p_dec, "unsupported segment type: (%04x)", i_type ); |
682 | 559 | bs_skip( s, 8 * i_size ); |
683 | 559 | break; |
684 | 24.6k | } |
685 | 24.6k | } |
686 | | |
687 | | static void decode_clut( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length ) |
688 | 2.88k | { |
689 | 2.88k | decoder_sys_t *p_sys = p_dec->p_sys; |
690 | 2.88k | uint16_t i_processed_length; |
691 | 2.88k | dvbsub_clut_t *p_clut, *p_next; |
692 | 2.88k | int i_id, i_version; |
693 | | |
694 | 2.88k | i_id = bs_read( s, 8 ); |
695 | 2.88k | i_version = bs_read( s, 4 ); |
696 | | |
697 | | /* Check if we already have this clut */ |
698 | 5.60k | for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next ) |
699 | 4.92k | { |
700 | 4.92k | if( p_clut->i_id == i_id ) break; |
701 | 4.92k | } |
702 | | |
703 | | /* Check version number */ |
704 | 2.88k | if( p_clut && ( p_clut->i_version == i_version ) ) |
705 | 2.13k | { |
706 | | /* Nothing to do */ |
707 | 2.13k | bs_skip( s, 8 * i_segment_length - 12 ); |
708 | 2.13k | return; |
709 | 2.13k | } |
710 | | |
711 | 750 | if( !p_clut ) |
712 | 678 | { |
713 | | #ifdef DEBUG_DVBSUB |
714 | | msg_Dbg( p_dec, "new clut: %i", i_id ); |
715 | | #endif |
716 | 678 | p_clut = malloc( sizeof( dvbsub_clut_t ) ); |
717 | 678 | if( !p_clut ) |
718 | 0 | return; |
719 | 678 | p_clut->p_next = p_sys->p_cluts; |
720 | 678 | p_sys->p_cluts = p_clut; |
721 | 678 | } |
722 | | |
723 | | /* Initialize to default clut */ |
724 | 750 | p_next = p_clut->p_next; |
725 | 750 | *p_clut = p_sys->default_clut; |
726 | 750 | p_clut->p_next = p_next; |
727 | | |
728 | | /* We don't have this version of the CLUT: Parse it */ |
729 | 750 | p_clut->i_version = i_version; |
730 | 750 | p_clut->i_id = i_id; |
731 | 750 | bs_skip( s, 4 ); /* Reserved bits */ |
732 | 750 | i_processed_length = 2; |
733 | 333k | while( i_processed_length < i_segment_length ) |
734 | 332k | { |
735 | 332k | uint8_t y, cb, cr, t; |
736 | 332k | uint_fast8_t cid = bs_read( s, 8 ); |
737 | 332k | uint_fast8_t type = bs_read( s, 3 ); |
738 | | |
739 | 332k | bs_skip( s, 4 ); |
740 | | |
741 | 332k | p_clut->color_range = bs_read( s, 1 ) ? COLOR_RANGE_FULL : COLOR_RANGE_LIMITED; |
742 | 332k | if( p_clut->color_range == COLOR_RANGE_FULL ) |
743 | 1.97k | { |
744 | 1.97k | y = bs_read( s, 8 ); |
745 | 1.97k | cr = bs_read( s, 8 ); |
746 | 1.97k | cb = bs_read( s, 8 ); |
747 | 1.97k | t = bs_read( s, 8 ); |
748 | 1.97k | i_processed_length += 6; |
749 | 1.97k | } |
750 | 330k | else |
751 | 330k | { |
752 | 330k | y = bs_read( s, 6 ) << 2; |
753 | 330k | cr = bs_read( s, 4 ) << 4; |
754 | 330k | cb = bs_read( s, 4 ) << 4; |
755 | 330k | t = bs_read( s, 2 ) << 6; |
756 | 330k | i_processed_length += 4; |
757 | 330k | } |
758 | | |
759 | | /* We are not entirely compliant here as full transparency is indicated |
760 | | * with a luma value of zero, not a transparency value of 0xff |
761 | | * (full transparency would actually be 0xff + 1). */ |
762 | 332k | if( y == 0 ) |
763 | 330k | { |
764 | 330k | cr = cb = 0; |
765 | 330k | t = 0xff; |
766 | 330k | } |
767 | | |
768 | | /* According to EN 300-743 section 7.2.3 note 1, type should |
769 | | * not have more than 1 bit set to one, but some streams don't |
770 | | * respect this note. */ |
771 | 332k | if( ( type & 0x04 ) && ( cid < 4 ) ) |
772 | 656 | { |
773 | 656 | p_clut->c_2b[cid].Y = y; |
774 | 656 | p_clut->c_2b[cid].Cr = cr; |
775 | 656 | p_clut->c_2b[cid].Cb = cb; |
776 | 656 | p_clut->c_2b[cid].T = t; |
777 | 656 | } |
778 | 332k | if( ( type & 0x02 ) && ( cid < 16 ) ) |
779 | 690 | { |
780 | 690 | p_clut->c_4b[cid].Y = y; |
781 | 690 | p_clut->c_4b[cid].Cr = cr; |
782 | 690 | p_clut->c_4b[cid].Cb = cb; |
783 | 690 | p_clut->c_4b[cid].T = t; |
784 | 690 | } |
785 | 332k | if( type & 0x01 ) |
786 | 1.76k | { |
787 | 1.76k | p_clut->c_8b[cid].Y = y; |
788 | 1.76k | p_clut->c_8b[cid].Cr = cr; |
789 | 1.76k | p_clut->c_8b[cid].Cb = cb; |
790 | 1.76k | p_clut->c_8b[cid].T = t; |
791 | 1.76k | } |
792 | 332k | } |
793 | 750 | } |
794 | | |
795 | | static void decode_page_composition( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length ) |
796 | 4.32k | { |
797 | 4.32k | decoder_sys_t *p_sys = p_dec->p_sys; |
798 | 4.32k | int i_version, i_state, i_timeout, i; |
799 | | |
800 | | /* A page is composed by 0 or more region */ |
801 | 4.32k | i_timeout = bs_read( s, 8 ); |
802 | 4.32k | i_version = bs_read( s, 4 ); |
803 | 4.32k | i_state = bs_read( s, 2 ); |
804 | 4.32k | bs_skip( s, 2 ); /* Reserved */ |
805 | | |
806 | 4.32k | if( i_state == DVBSUB_PCS_STATE_CHANGE ) |
807 | 11 | { |
808 | | /* End of an epoch, reset decoder buffer */ |
809 | | #ifdef DEBUG_DVBSUB |
810 | | msg_Dbg( p_dec, "page composition mode change" ); |
811 | | #endif |
812 | 11 | free_all( p_dec ); |
813 | 11 | } |
814 | 4.31k | else if( !p_sys->p_page && ( i_state != DVBSUB_PCS_STATE_ACQUISITION ) && |
815 | 218 | ( i_state != DVBSUB_PCS_STATE_CHANGE ) ) |
816 | 218 | { |
817 | | /* Not a full PCS, we need to wait for one */ |
818 | 218 | msg_Dbg( p_dec, "didn't receive an acquisition page yet" ); |
819 | | |
820 | | #if 0 |
821 | | /* Try to start decoding even without an acquisition page */ |
822 | | bs_skip( s, 8 * (i_segment_length - 2) ); |
823 | | return; |
824 | | #endif |
825 | 218 | } |
826 | | |
827 | | #ifdef DEBUG_DVBSUB |
828 | | if( i_state == DVBSUB_PCS_STATE_ACQUISITION ) |
829 | | msg_Dbg( p_dec, "acquisition page composition" ); |
830 | | #endif |
831 | | |
832 | | /* Check version number */ |
833 | 4.32k | if( p_sys->p_page && ( p_sys->p_page->i_version == i_version ) ) |
834 | 2.15k | { |
835 | 2.15k | bs_skip( s, 8 * (i_segment_length - 2) ); |
836 | 2.15k | return; |
837 | 2.15k | } |
838 | 2.17k | else if( p_sys->p_page ) |
839 | 1.56k | { |
840 | 1.56k | if( p_sys->p_page->i_region_defs ) |
841 | 1.55k | free( p_sys->p_page->p_region_defs ); |
842 | 1.56k | p_sys->p_page->p_region_defs = NULL; |
843 | 1.56k | p_sys->p_page->i_region_defs = 0; |
844 | 1.56k | } |
845 | | |
846 | 2.17k | if( !p_sys->p_page ) |
847 | 611 | { |
848 | | #ifdef DEBUG_DVBSUB |
849 | | msg_Dbg( p_dec, "new page" ); |
850 | | #endif |
851 | | /* Allocate a new page */ |
852 | 611 | p_sys->p_page = malloc( sizeof(dvbsub_page_t) ); |
853 | 611 | if( !p_sys->p_page ) |
854 | 0 | return; |
855 | 611 | } |
856 | | |
857 | 2.17k | p_sys->p_page->i_version = i_version; |
858 | 2.17k | p_sys->p_page->i_timeout = i_timeout; |
859 | 2.17k | p_sys->b_page = true; |
860 | 2.17k | p_sys->p_page->p_region_defs = NULL; |
861 | 2.17k | p_sys->p_page->i_region_defs = 0; |
862 | | |
863 | | /* Number of regions */ |
864 | 2.17k | uint16_t i_region_defs = (i_segment_length - 2) / 6; |
865 | | |
866 | 2.17k | if( i_region_defs == 0 ) return; |
867 | | |
868 | 2.16k | p_sys->p_page->p_region_defs = |
869 | 2.16k | vlc_alloc( i_region_defs, sizeof(dvbsub_regiondef_t) ); |
870 | 2.16k | if( p_sys->p_page->p_region_defs ) |
871 | 2.16k | { |
872 | 2.16k | p_sys->p_page->i_region_defs = i_region_defs; |
873 | 68.0k | for( i = 0; i < p_sys->p_page->i_region_defs; i++ ) |
874 | 65.8k | { |
875 | 65.8k | p_sys->p_page->p_region_defs[i].i_id = bs_read( s, 8 ); |
876 | 65.8k | bs_skip( s, 8 ); /* Reserved */ |
877 | 65.8k | p_sys->p_page->p_region_defs[i].i_x = bs_read( s, 16 ); |
878 | 65.8k | p_sys->p_page->p_region_defs[i].i_y = bs_read( s, 16 ); |
879 | | |
880 | | #ifdef DEBUG_DVBSUB |
881 | | msg_Dbg( p_dec, "page_composition, region %i (%i,%i)", |
882 | | i, p_sys->p_page->p_region_defs[i].i_x, |
883 | | p_sys->p_page->p_region_defs[i].i_y ); |
884 | | #endif |
885 | 65.8k | } |
886 | 2.16k | } |
887 | 2.16k | } |
888 | | |
889 | | static void decode_region_composition( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length ) |
890 | 3.80k | { |
891 | 3.80k | decoder_sys_t *p_sys = p_dec->p_sys; |
892 | 3.80k | dvbsub_region_t *p_region, **pp_region = &p_sys->p_regions; |
893 | 3.80k | int i_processed_length, i_id, i_version; |
894 | 3.80k | int i_width, i_height, i_level_comp, i_depth, i_clut; |
895 | 3.80k | int i_8_bg, i_4_bg, i_2_bg; |
896 | 3.80k | bool b_fill; |
897 | | |
898 | 3.80k | i_id = bs_read( s, 8 ); |
899 | 3.80k | i_version = bs_read( s, 4 ); |
900 | | |
901 | | /* Check if we already have this region */ |
902 | 4.87k | for( p_region = p_sys->p_regions; p_region != NULL; |
903 | 3.80k | p_region = p_region->p_next ) |
904 | 3.94k | { |
905 | 3.94k | pp_region = &p_region->p_next; |
906 | 3.94k | if( p_region->i_id == i_id ) break; |
907 | 3.94k | } |
908 | | |
909 | | /* Check version number */ |
910 | 3.80k | if( p_region && ( p_region->i_version == i_version ) ) |
911 | 2.81k | { |
912 | 2.81k | bs_skip( s, 8 * (i_segment_length - 1) - 4 ); |
913 | 2.81k | return; |
914 | 2.81k | } |
915 | | |
916 | 997 | if( !p_region ) |
917 | 930 | { |
918 | | #ifdef DEBUG_DVBSUB |
919 | | msg_Dbg( p_dec, "new region: %i", i_id ); |
920 | | #endif |
921 | 930 | p_region = *pp_region = calloc( 1, sizeof(dvbsub_region_t) ); |
922 | 930 | if( !p_region ) |
923 | 0 | return; |
924 | 930 | p_region->p_object_defs = NULL; |
925 | 930 | p_region->p_pixbuf = NULL; |
926 | 930 | p_region->p_next = NULL; |
927 | 930 | } |
928 | | |
929 | | /* Region attributes */ |
930 | 997 | p_region->i_id = i_id; |
931 | 997 | p_region->i_version = i_version; |
932 | 997 | b_fill = bs_read( s, 1 ); |
933 | 997 | bs_skip( s, 3 ); /* Reserved */ |
934 | | |
935 | 997 | i_width = bs_read( s, 16 ); |
936 | 997 | i_height = bs_read( s, 16 ); |
937 | | #ifdef DEBUG_DVBSUB |
938 | | msg_Dbg( p_dec, " width=%d height=%d", i_width, i_height ); |
939 | | #endif |
940 | 997 | i_level_comp = bs_read( s, 3 ); |
941 | 997 | i_depth = bs_read( s, 3 ); |
942 | 997 | bs_skip( s, 2 ); /* Reserved */ |
943 | 997 | i_clut = bs_read( s, 8 ); |
944 | | |
945 | 997 | i_8_bg = bs_read( s, 8 ); |
946 | 997 | i_4_bg = bs_read( s, 4 ); |
947 | 997 | i_2_bg = bs_read( s, 2 ); |
948 | 997 | bs_skip( s, 2 ); /* Reserved */ |
949 | | |
950 | | /* Free old object defs */ |
951 | 10.3k | while( p_region->i_object_defs ) |
952 | 9.32k | free( p_region->p_object_defs[--p_region->i_object_defs].psz_text ); |
953 | | |
954 | 997 | free( p_region->p_object_defs ); |
955 | 997 | p_region->p_object_defs = NULL; |
956 | | |
957 | | /* Extra sanity checks */ |
958 | 997 | if( ( p_region->i_width != i_width ) || |
959 | 67 | ( p_region->i_height != i_height ) ) |
960 | 941 | { |
961 | 941 | if( p_region->p_pixbuf ) |
962 | 13 | { |
963 | 13 | msg_Dbg( p_dec, "region size changed (%dx%d->%dx%d)", |
964 | 13 | p_region->i_width, p_region->i_height, i_width, i_height ); |
965 | 13 | } |
966 | | |
967 | 941 | size_t i_alloc; |
968 | 941 | if( ckd_mul( &i_alloc, i_width, i_height ) || i_alloc == 0 ) |
969 | 11 | { |
970 | 11 | free( p_region->p_pixbuf ); |
971 | 11 | p_region->p_pixbuf = NULL; |
972 | 11 | } |
973 | 930 | else |
974 | 930 | { |
975 | 930 | void *r_pixbuf = realloc( p_region->p_pixbuf, i_alloc ); |
976 | 930 | if( unlikely( r_pixbuf == NULL ) ) |
977 | 0 | { |
978 | 0 | free( p_region->p_pixbuf ); |
979 | 0 | p_region->p_pixbuf = NULL; |
980 | 0 | } |
981 | 930 | else |
982 | 930 | p_region->p_pixbuf = r_pixbuf; |
983 | 930 | p_region->i_depth = 0; |
984 | 930 | } |
985 | | |
986 | 941 | b_fill = !!p_region->p_pixbuf; |
987 | 941 | } |
988 | | |
989 | 997 | if( p_region->i_depth && |
990 | 53 | ( ( p_region->i_depth != i_depth ) || |
991 | 44 | ( p_region->i_level_comp != i_level_comp ) || |
992 | 43 | ( p_region->i_clut != i_clut) ) ) |
993 | 13 | { |
994 | 13 | msg_Dbg( p_dec, "region parameters changed (not allowed)" ); |
995 | 13 | } |
996 | | |
997 | | /* Erase background of region */ |
998 | 997 | if( b_fill ) |
999 | 955 | { |
1000 | 955 | int i_background = ( i_depth == 1 ) ? i_2_bg : |
1001 | 955 | ( ( i_depth == 2 ) ? i_4_bg : i_8_bg ); |
1002 | 955 | memset( p_region->p_pixbuf, i_background, (size_t)i_width * i_height ); |
1003 | 955 | } |
1004 | | |
1005 | 997 | p_region->i_width = i_width; |
1006 | 997 | p_region->i_height = i_height; |
1007 | 997 | p_region->i_level_comp = i_level_comp; |
1008 | 997 | p_region->i_depth = i_depth; |
1009 | 997 | p_region->i_clut = i_clut; |
1010 | | |
1011 | | /* List of objects in the region */ |
1012 | 997 | i_processed_length = 10; |
1013 | | |
1014 | | /* Entry can be 6 or 8 bytes */ |
1015 | 997 | unsigned max_object_defs; |
1016 | 997 | if( i_segment_length < 10 ) |
1017 | 11 | max_object_defs = 0; |
1018 | 986 | else |
1019 | 986 | max_object_defs = (i_segment_length - i_processed_length) / 6; |
1020 | 997 | p_region->i_object_defs = 0; |
1021 | 997 | p_region->p_object_defs = malloc( max_object_defs * sizeof(dvbsub_objectdef_t) ); |
1022 | 997 | if( !p_region->p_object_defs ) |
1023 | 0 | return; |
1024 | | |
1025 | 316k | while( i_processed_length + 6 <= i_segment_length ) |
1026 | 315k | { |
1027 | 315k | dvbsub_objectdef_t *p_obj; |
1028 | | |
1029 | | /* We parse object properties */ |
1030 | 315k | p_obj = &p_region->p_object_defs[p_region->i_object_defs]; |
1031 | 315k | p_obj->i_id = bs_read( s, 16 ); |
1032 | 315k | p_obj->i_type = bs_read( s, 2 ); |
1033 | 315k | bs_skip( s, 2 ); /* Provider */ |
1034 | 315k | p_obj->i_x = bs_read( s, 12 ); |
1035 | 315k | bs_skip( s, 4 ); /* Reserved */ |
1036 | 315k | p_obj->i_y = bs_read( s, 12 ); |
1037 | 315k | p_obj->psz_text = NULL; |
1038 | | |
1039 | 315k | i_processed_length += 6; |
1040 | | |
1041 | 315k | if( ( p_obj->i_type == DVBSUB_OT_BASIC_CHAR ) || |
1042 | 315k | ( p_obj->i_type == DVBSUB_OT_COMPOSITE_STRING ) ) |
1043 | 199 | { |
1044 | 199 | if( i_processed_length + 2 > i_segment_length ) |
1045 | 20 | break; |
1046 | 179 | p_obj->i_fg_pc = bs_read( s, 8 ); |
1047 | 179 | p_obj->i_bg_pc = bs_read( s, 8 ); |
1048 | 179 | i_processed_length += 2; |
1049 | 179 | } |
1050 | 315k | p_region->i_object_defs++; |
1051 | 315k | } |
1052 | 997 | } |
1053 | | |
1054 | | /* ETSI 300 743 [7.2.8] */ |
1055 | | static void alternative_CLUT( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length ) |
1056 | 1.77k | { |
1057 | 1.77k | decoder_sys_t *p_sys = p_dec->p_sys; |
1058 | 1.77k | uint16_t i_processed_length; |
1059 | 1.77k | int i_id, i_version; |
1060 | 1.77k | dvbsub_clut_t *p_clut; |
1061 | | |
1062 | 1.77k | i_id = bs_read( s, 8 ); |
1063 | 1.77k | i_version = bs_read( s, 4 ); |
1064 | | |
1065 | | /* Check if we already have this clut */ |
1066 | 2.61k | for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next ) |
1067 | 2.12k | { |
1068 | 2.12k | if( p_clut->i_id == i_id ) |
1069 | 1.28k | { |
1070 | | /* Check version number */ |
1071 | 1.28k | if( p_clut->i_version == i_version ) |
1072 | 1.25k | { |
1073 | | /* Nothing to do */ |
1074 | 1.25k | bs_skip( s, 8 * i_segment_length - 12 ); |
1075 | 1.25k | return; |
1076 | 1.25k | } |
1077 | | |
1078 | 30 | break; |
1079 | 1.28k | } |
1080 | 2.12k | } |
1081 | | |
1082 | 523 | if( !p_clut ) |
1083 | 493 | { |
1084 | | #ifdef DEBUG_DVBSUB |
1085 | | msg_Dbg( p_dec, "new alternative clut: %i", i_id ); |
1086 | | #endif |
1087 | 493 | p_clut = malloc( sizeof( dvbsub_clut_t ) ); |
1088 | 493 | if( !p_clut ) |
1089 | 0 | return; |
1090 | 493 | p_clut->p_next = p_sys->p_cluts; |
1091 | 493 | p_sys->p_cluts = p_clut; |
1092 | 493 | } |
1093 | | |
1094 | | /* We don't have this version of the CLUT: Parse it */ |
1095 | 523 | p_clut->i_version = i_version; |
1096 | 523 | p_clut->i_id = i_id; |
1097 | | |
1098 | 523 | bs_skip( s, 4 ); // reserved_zero_future_use |
1099 | | |
1100 | | // CLUT_parameters |
1101 | 523 | int CLUT_entry_max_number = bs_read( s, 2 ); |
1102 | 523 | int colour_component_type = bs_read( s, 2 ); |
1103 | 523 | int output_bit_depth = bs_read( s, 3 ); |
1104 | 523 | bs_skip( s, 1 ); // reserved_zero_future_use |
1105 | 523 | int dynamic_range_and_colour_gamut = bs_read( s, 8 ); |
1106 | | |
1107 | 523 | bool error = false; |
1108 | 523 | i_processed_length = 4; |
1109 | 523 | if (output_bit_depth != DVBSUB_ST_BITDEPTH_8BIT && |
1110 | 100 | output_bit_depth != DVBSUB_ST_BITDEPTH_10BIT) |
1111 | 93 | { |
1112 | 93 | msg_Err( p_dec, "unsupported alternative clut bitdepth: %i", output_bit_depth ); |
1113 | 93 | error = true; |
1114 | 93 | } |
1115 | 523 | if (CLUT_entry_max_number != 0) // 0: 256 entries |
1116 | 190 | { |
1117 | 190 | msg_Err( p_dec, "unsupported alternative clut max entries: %i", CLUT_entry_max_number ); |
1118 | 190 | error = true; |
1119 | 190 | } |
1120 | 523 | if (colour_component_type != 0) // 0: YCbCr |
1121 | 138 | { |
1122 | 138 | msg_Err( p_dec, "unsupported alternative clut component type: %i", colour_component_type ); |
1123 | 138 | error = true; |
1124 | 138 | } |
1125 | 523 | if (dynamic_range_and_colour_gamut > DVBSUB_ST_COLORIMETRY_HDR_HLG) |
1126 | 87 | { |
1127 | 87 | msg_Err( p_dec, "unsupported alternative clut color range: %i", dynamic_range_and_colour_gamut ); |
1128 | 87 | error = true; |
1129 | 87 | } |
1130 | 523 | if (error) |
1131 | 219 | goto done; |
1132 | | |
1133 | 304 | p_clut->c_8b_entries = 0; |
1134 | 10.4k | while( i_processed_length < i_segment_length ) |
1135 | 10.2k | { |
1136 | 10.2k | uint8_t y, cb, cr, t; |
1137 | 10.2k | if (output_bit_depth == DVBSUB_ST_BITDEPTH_10BIT) |
1138 | 26 | { |
1139 | | // TODO: apply the palette locally to keep 10-bit values |
1140 | 26 | y = bs_read( s, 10 ) >> 2; |
1141 | 26 | cr = bs_read( s, 10 ) >> 2; |
1142 | 26 | cb = bs_read( s, 10 ) >> 2; |
1143 | 26 | t = bs_read( s, 10 ) >> 2; |
1144 | 26 | i_processed_length += 5; |
1145 | 26 | } |
1146 | 10.2k | else |
1147 | 10.2k | { |
1148 | 10.2k | y = bs_read( s, 8 ); |
1149 | 10.2k | cr = bs_read( s, 8 ); |
1150 | 10.2k | cb = bs_read( s, 8 ); |
1151 | 10.2k | t = bs_read( s, 8 ); |
1152 | 10.2k | i_processed_length += 4; |
1153 | 10.2k | } |
1154 | | |
1155 | | /* We are not entirely compliant here as full transparency is indicated |
1156 | | * with a luma value of zero, not a transparency value of 0xff |
1157 | | * (full transparency would actually be 0xff + 1). */ |
1158 | 10.2k | if( y == 0 ) |
1159 | 9.28k | { |
1160 | 9.28k | cr = cb = 0; |
1161 | 9.28k | t = 0xff; |
1162 | 9.28k | } |
1163 | | |
1164 | 10.2k | p_clut->c_8b[p_clut->c_8b_entries].Y = y; |
1165 | 10.2k | p_clut->c_8b[p_clut->c_8b_entries].Cr = cr; |
1166 | 10.2k | p_clut->c_8b[p_clut->c_8b_entries].Cb = cb; |
1167 | 10.2k | p_clut->c_8b[p_clut->c_8b_entries].T = t; |
1168 | 10.2k | p_clut->c_8b_entries++; |
1169 | 10.2k | if (p_clut->c_8b_entries >= (int)ARRAY_SIZE(p_clut->c_8b)) |
1170 | 37 | break; |
1171 | 10.2k | } |
1172 | 304 | p_clut->dynamic_range_and_colour_gamut = dynamic_range_and_colour_gamut; |
1173 | 304 | p_clut->color_range = COLOR_RANGE_FULL; |
1174 | 523 | done: |
1175 | 523 | bs_skip( s, 8 * (i_segment_length - i_processed_length) ); |
1176 | 523 | } |
1177 | | |
1178 | | /* ETSI 300 743 [7.2.1] */ |
1179 | | static void decode_display_definition( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length ) |
1180 | 4.85k | { |
1181 | 4.85k | decoder_sys_t *p_sys = p_dec->p_sys; |
1182 | 4.85k | uint16_t i_processed_length = 40; |
1183 | 4.85k | int i_version; |
1184 | | |
1185 | 4.85k | i_version = bs_read( s, 4 ); |
1186 | | |
1187 | | /* Check version number */ |
1188 | 4.85k | if( p_sys->display.i_version == i_version ) |
1189 | 1.36k | { |
1190 | | /* The definition did not change */ |
1191 | 1.36k | bs_skip( s, 8*i_segment_length - 4 ); |
1192 | 1.36k | return; |
1193 | 1.36k | } |
1194 | | |
1195 | | #ifdef DEBUG_DVBSUB |
1196 | | msg_Dbg( p_dec, "new display definition: %i", i_version ); |
1197 | | #endif |
1198 | | |
1199 | | /* We don't have this version of the display definition: Parse it */ |
1200 | 3.48k | p_sys->display.i_version = i_version; |
1201 | 3.48k | p_sys->display.b_windowed = bs_read( s, 1 ); |
1202 | 3.48k | bs_skip( s, 3 ); /* Reserved bits */ |
1203 | 3.48k | p_sys->display.i_width_minus1 = bs_read( s, 16 ); |
1204 | 3.48k | p_sys->display.i_height_minus1 = bs_read( s, 16 ); |
1205 | | |
1206 | 3.48k | if( p_sys->display.b_windowed ) |
1207 | 17 | { |
1208 | | #ifdef DEBUG_DVBSUB |
1209 | | msg_Dbg( p_dec, "display definition with offsets (windowed)" ); |
1210 | | #endif |
1211 | | /* Coordinates are measured from the top left corner */ |
1212 | 17 | p_sys->display.i_x = bs_read( s, 16 ); |
1213 | 17 | p_sys->display.i_max_x = bs_read( s, 16 ); |
1214 | 17 | p_sys->display.i_y = bs_read( s, 16 ); |
1215 | 17 | p_sys->display.i_max_y = bs_read( s, 16 ); |
1216 | 17 | i_processed_length += 64; |
1217 | 17 | } |
1218 | 3.46k | else |
1219 | 3.46k | { |
1220 | | /* if not windowed, setup the window variables to good defaults */ |
1221 | | /* not necessary, but to avoid future confusion.. */ |
1222 | 3.46k | p_sys->display.i_x = 0; |
1223 | 3.46k | p_sys->display.i_max_x = p_sys->display.i_width_minus1; |
1224 | 3.46k | p_sys->display.i_y = 0; |
1225 | 3.46k | p_sys->display.i_max_y = p_sys->display.i_height_minus1; |
1226 | 3.46k | } |
1227 | | |
1228 | 3.48k | if( i_processed_length != i_segment_length*8 ) |
1229 | 83 | { |
1230 | 83 | msg_Err( p_dec, "processed length %d bytes != segment length %d bytes", |
1231 | 83 | i_processed_length / 8 , i_segment_length ); |
1232 | 83 | } |
1233 | | |
1234 | | #ifdef DEBUG_DVBSUB |
1235 | | msg_Dbg( p_dec, "version: %d, width: %d, height: %d", |
1236 | | p_sys->display.i_version, (int)p_sys->display.i_width_minus1+1, (int)p_sys->display.i_height_minus1+1 ); |
1237 | | if( p_sys->display.b_windowed ) |
1238 | | msg_Dbg( p_dec, "xmin: %d, xmax: %d, ymin: %d, ymax: %d", |
1239 | | p_sys->display.i_x, p_sys->display.i_max_x, p_sys->display.i_y, p_sys->display.i_max_y ); |
1240 | | #endif |
1241 | 3.48k | } |
1242 | | |
1243 | | static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int, |
1244 | | const uint8_t *, int ); |
1245 | | static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int, int * ); |
1246 | | static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int, int * ); |
1247 | | static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int, int * ); |
1248 | | |
1249 | | static void decode_object( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length ) |
1250 | 4.64k | { |
1251 | 4.64k | decoder_sys_t *p_sys = p_dec->p_sys; |
1252 | 4.64k | dvbsub_region_t *p_region; |
1253 | 4.64k | int i_coding_method, i_id, i; |
1254 | | |
1255 | | /* ETSI 300-743 v1.5.1 section 7.2.5 'Object data segment' |
1256 | | * sync_byte, segment_type, page_id and i_segment_length have already been processed. |
1257 | | */ |
1258 | 4.64k | i_id = bs_read( s, 16 ); |
1259 | 4.64k | bs_skip( s, 4 ); /* version */ |
1260 | 4.64k | i_coding_method = bs_read( s, 2 ); |
1261 | | |
1262 | 4.64k | if( i_coding_method > 1 ) |
1263 | 27 | { |
1264 | 27 | msg_Dbg( p_dec, "unknown DVB subtitling coding %d is not handled!", i_coding_method ); |
1265 | 27 | bs_skip( s, 8 * (i_segment_length - 2) - 6 ); |
1266 | 27 | return; |
1267 | 27 | } |
1268 | | |
1269 | | /* Check if the object needs to be rendered in at least one |
1270 | | * of the regions */ |
1271 | 7.46k | for( p_region = p_sys->p_regions; p_region != NULL; |
1272 | 4.61k | p_region = p_region->p_next ) |
1273 | 5.59k | { |
1274 | 83.5k | for( i = 0; i < p_region->i_object_defs; i++ ) |
1275 | 80.7k | if( p_region->p_object_defs[i].i_id == i_id ) break; |
1276 | | |
1277 | 5.59k | if( i != p_region->i_object_defs ) break; |
1278 | 5.59k | } |
1279 | 4.61k | if( !p_region ) |
1280 | 1.87k | { |
1281 | 1.87k | bs_skip( s, 8 * (i_segment_length - 2) - 6 ); |
1282 | 1.87k | return; |
1283 | 1.87k | } |
1284 | | |
1285 | | #ifdef DEBUG_DVBSUB |
1286 | | msg_Dbg( p_dec, "new object: %i", i_id ); |
1287 | | #endif |
1288 | | |
1289 | 2.73k | bs_skip( s, 1 ); /* non_modify_color */ |
1290 | 2.73k | bs_skip( s, 1 ); /* Reserved */ |
1291 | | |
1292 | 2.73k | if( i_coding_method == 0x00 ) |
1293 | 2.71k | { |
1294 | 2.71k | int i_topfield, i_bottomfield; |
1295 | 2.71k | const uint8_t *p_topfield, *p_bottomfield; |
1296 | | |
1297 | 2.71k | i_topfield = bs_read( s, 16 ); |
1298 | 2.71k | i_bottomfield = bs_read( s, 16 ); |
1299 | 2.71k | p_topfield = s->p_start + bs_pos( s ) / 8; |
1300 | 2.71k | p_bottomfield = p_topfield + i_topfield; |
1301 | | |
1302 | 2.71k | bs_skip( s, 8 * (i_segment_length - 7) ); |
1303 | | |
1304 | | /* Sanity check */ |
1305 | 2.71k | if( ( i_segment_length < ( i_topfield + i_bottomfield + 7 ) ) || |
1306 | 1.78k | ( ( p_topfield + i_topfield + i_bottomfield ) > s->p_end ) ) |
1307 | 940 | { |
1308 | 940 | msg_Dbg( p_dec, "corrupted object data" ); |
1309 | 940 | return; |
1310 | 940 | } |
1311 | | |
1312 | 4.57k | for( p_region = p_sys->p_regions; p_region != NULL; |
1313 | 2.79k | p_region = p_region->p_next ) |
1314 | 2.79k | { |
1315 | 320k | for( i = 0; i < p_region->i_object_defs; i++ ) |
1316 | 317k | { |
1317 | 317k | if( p_region->p_object_defs[i].i_id != i_id ) continue; |
1318 | | |
1319 | 315k | dvbsub_render_pdata( p_dec, p_region, |
1320 | 315k | p_region->p_object_defs[i].i_x, |
1321 | 315k | p_region->p_object_defs[i].i_y, |
1322 | 315k | p_topfield, i_topfield ); |
1323 | | |
1324 | 315k | if( i_bottomfield ) |
1325 | 1 | { |
1326 | 1 | dvbsub_render_pdata( p_dec, p_region, |
1327 | 1 | p_region->p_object_defs[i].i_x, |
1328 | 1 | p_region->p_object_defs[i].i_y + 1, |
1329 | 1 | p_bottomfield, i_bottomfield ); |
1330 | 1 | } |
1331 | 315k | else |
1332 | 315k | { |
1333 | | /* Duplicate the top field */ |
1334 | 315k | dvbsub_render_pdata( p_dec, p_region, |
1335 | 315k | p_region->p_object_defs[i].i_x, |
1336 | 315k | p_region->p_object_defs[i].i_y + 1, |
1337 | 315k | p_topfield, i_topfield ); |
1338 | 315k | } |
1339 | 315k | } |
1340 | 2.79k | } |
1341 | 1.77k | } |
1342 | 20 | else |
1343 | 20 | { |
1344 | | /* DVB subtitling as characters */ |
1345 | 20 | int i_number_of_codes = bs_read( s, 8 ); |
1346 | 20 | const uint8_t* p_start = s->p_start + bs_pos( s ) / 8; |
1347 | | |
1348 | | /* Sanity check */ |
1349 | 20 | if( ( i_segment_length < ( i_number_of_codes*2 + 4 ) ) || |
1350 | 18 | ( ( p_start + i_number_of_codes*2 ) > s->p_end ) ) |
1351 | 2 | { |
1352 | 2 | msg_Dbg( p_dec, "corrupted object data" ); |
1353 | 2 | return; |
1354 | 2 | } |
1355 | | |
1356 | 57 | for( p_region = p_sys->p_regions; p_region != NULL; |
1357 | 39 | p_region = p_region->p_next ) |
1358 | 39 | { |
1359 | 5.06k | for( i = 0; i < p_region->i_object_defs; i++ ) |
1360 | 5.02k | { |
1361 | 5.02k | int j; |
1362 | | |
1363 | 5.02k | if( p_region->p_object_defs[i].i_id != i_id ) continue; |
1364 | | |
1365 | 5.00k | char *psz_text = realloc( p_region->p_object_defs[i].psz_text, i_number_of_codes + 1 ); |
1366 | 5.00k | if( unlikely( psz_text == NULL ) ) |
1367 | 0 | { |
1368 | 0 | free( p_region->p_object_defs[i].psz_text ); |
1369 | 0 | p_region->p_object_defs[i].psz_text = NULL; |
1370 | 0 | continue; |
1371 | 0 | } |
1372 | 5.00k | p_region->p_object_defs[i].psz_text = psz_text; |
1373 | | |
1374 | | /* FIXME 16bits -> char ??? See Preamble */ |
1375 | 5.00k | for( j = 0; j < i_number_of_codes; j++ ) |
1376 | 0 | { |
1377 | 0 | psz_text[j] = (char)(bs_read( s, 16 ) & 0xFF); |
1378 | 0 | } |
1379 | | /* Null terminate the string */ |
1380 | 5.00k | psz_text[j] = 0; |
1381 | 5.00k | } |
1382 | 39 | } |
1383 | 18 | } |
1384 | | |
1385 | | #ifdef DEBUG_DVBSUB |
1386 | | msg_Dbg( p_dec, "end object: %i", i_id ); |
1387 | | #endif |
1388 | 2.73k | } |
1389 | | |
1390 | | static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region, |
1391 | | int i_x, int i_y, |
1392 | | const uint8_t *p_field, int i_field ) |
1393 | 631k | { |
1394 | 631k | uint8_t *p_pixbuf; |
1395 | 631k | int i_offset = 0; |
1396 | 631k | bs_t bs; |
1397 | | |
1398 | | /* Sanity check */ |
1399 | 631k | if( !p_region->p_pixbuf ) |
1400 | 80.4k | { |
1401 | 80.4k | msg_Err( p_dec, "region %i has no pixel buffer!", p_region->i_id ); |
1402 | 80.4k | return; |
1403 | 80.4k | } |
1404 | 551k | if( i_y < 0 || i_x < 0 || i_y >= p_region->i_height || |
1405 | 551k | i_x >= p_region->i_width ) |
1406 | 262 | { |
1407 | 262 | msg_Dbg( p_dec, "invalid offset (%i,%i)", i_x, i_y ); |
1408 | 262 | return; |
1409 | 262 | } |
1410 | | |
1411 | 551k | p_pixbuf = p_region->p_pixbuf + (size_t)i_y * p_region->i_width; |
1412 | 551k | bs_init( &bs, p_field, i_field ); |
1413 | | |
1414 | 9.52M | while( !bs_eof( &bs ) ) |
1415 | 8.97M | { |
1416 | | /* Sanity check */ |
1417 | 8.97M | if( i_y >= p_region->i_height ) return; |
1418 | | |
1419 | 8.97M | switch( bs_read( &bs, 8 ) ) |
1420 | 8.97M | { |
1421 | 597k | case 0x10: |
1422 | 597k | dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x, |
1423 | 597k | &i_offset ); |
1424 | 597k | break; |
1425 | | |
1426 | 534k | case 0x11: |
1427 | 534k | dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x, |
1428 | 534k | &i_offset ); |
1429 | 534k | break; |
1430 | | |
1431 | 471k | case 0x12: |
1432 | 471k | dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x, |
1433 | 471k | &i_offset ); |
1434 | 471k | break; |
1435 | | |
1436 | 510k | case 0x20: |
1437 | 1.03M | case 0x21: |
1438 | 1.54M | case 0x22: |
1439 | | /* We don't use map tables */ |
1440 | 1.54M | break; |
1441 | | |
1442 | 510k | case 0xf0: /* End of line code */ |
1443 | 510k | p_pixbuf += 2*p_region->i_width; |
1444 | 510k | i_offset = 0; i_y += 2; |
1445 | 510k | break; |
1446 | 8.97M | } |
1447 | 8.97M | } |
1448 | 551k | } |
1449 | | |
1450 | | static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off ) |
1451 | 597k | { |
1452 | 597k | bool b_stop = false; |
1453 | | |
1454 | 1.27M | while( !b_stop && !bs_eof( s ) ) |
1455 | 678k | { |
1456 | 678k | int i_count = 0, i_color = 0; |
1457 | | |
1458 | 678k | i_color = bs_read( s, 2 ); |
1459 | 678k | if( i_color != 0x00 ) |
1460 | 51.4k | { |
1461 | 51.4k | i_count = 1; |
1462 | 51.4k | } |
1463 | 626k | else |
1464 | 626k | { |
1465 | 626k | if( bs_read( s, 1 ) == 0x01 ) // Switch1 |
1466 | 23.8k | { |
1467 | 23.8k | i_count = 3 + bs_read( s, 3 ); |
1468 | 23.8k | i_color = bs_read( s, 2 ); |
1469 | 23.8k | } |
1470 | 603k | else |
1471 | 603k | { |
1472 | 603k | if( bs_read( s, 1 ) == 0x00 ) //Switch2 |
1473 | 591k | { |
1474 | 591k | switch( bs_read( s, 2 ) ) //Switch3 |
1475 | 591k | { |
1476 | 591k | case 0x00: |
1477 | 591k | b_stop = true; |
1478 | 591k | break; |
1479 | 17 | case 0x01: |
1480 | 17 | i_count = 2; |
1481 | 17 | break; |
1482 | 57 | case 0x02: |
1483 | 57 | i_count = 12 + bs_read( s, 4 ); |
1484 | 57 | i_color = bs_read( s, 2 ); |
1485 | 57 | break; |
1486 | 10 | case 0x03: |
1487 | 10 | i_count = 29 + bs_read( s, 8 ); |
1488 | 10 | i_color = bs_read( s, 2 ); |
1489 | 10 | break; |
1490 | 0 | default: |
1491 | 0 | break; |
1492 | 591k | } |
1493 | 591k | } |
1494 | 11.5k | else |
1495 | 11.5k | { |
1496 | | /* 1 pixel color 0 */ |
1497 | 11.5k | i_count = 1; |
1498 | 11.5k | } |
1499 | 603k | } |
1500 | 626k | } |
1501 | | |
1502 | 678k | if( !i_count ) continue; |
1503 | | |
1504 | | /* Sanity check */ |
1505 | 86.9k | if( ( i_count + *pi_off ) > i_width ) break; |
1506 | | |
1507 | 86.8k | if( i_count == 1 ) p[*pi_off] = i_color; |
1508 | 23.9k | else memset( ( p + *pi_off ), i_color, i_count ); |
1509 | | |
1510 | 86.8k | (*pi_off) += i_count; |
1511 | 86.8k | } |
1512 | | |
1513 | 597k | bs_align( s ); |
1514 | 597k | } |
1515 | | |
1516 | | static void dvbsub_pdata4bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off ) |
1517 | 534k | { |
1518 | 534k | bool b_stop = false; |
1519 | | |
1520 | 1.83M | while( !b_stop && !bs_eof( s ) ) |
1521 | 1.32M | { |
1522 | 1.32M | int i_count = 0, i_color = 0; |
1523 | | |
1524 | 1.32M | i_color = bs_read( s, 4 ); |
1525 | 1.32M | if( i_color != 0x00 ) |
1526 | 708k | { |
1527 | | /* Add 1 pixel */ |
1528 | 708k | i_count = 1; |
1529 | 708k | } |
1530 | 612k | else |
1531 | 612k | { |
1532 | 612k | if( bs_read( s, 1 ) == 0x00 ) // Switch1 |
1533 | 524k | { |
1534 | 524k | i_count = bs_read( s, 3 ); |
1535 | 524k | if( i_count != 0x00 ) |
1536 | 12.9k | { |
1537 | 12.9k | i_count += 2; |
1538 | 12.9k | } |
1539 | 511k | else b_stop = true; |
1540 | 524k | } |
1541 | 87.1k | else |
1542 | 87.1k | { |
1543 | 87.1k | if( bs_read( s, 1 ) == 0x00) //Switch2 |
1544 | 45.6k | { |
1545 | 45.6k | i_count = 4 + bs_read( s, 2 ); |
1546 | 45.6k | i_color = bs_read( s, 4 ); |
1547 | 45.6k | } |
1548 | 41.5k | else |
1549 | 41.5k | { |
1550 | 41.5k | switch ( bs_read( s, 2 ) ) //Switch3 |
1551 | 41.5k | { |
1552 | 13 | case 0x0: |
1553 | 13 | i_count = 1; |
1554 | 13 | break; |
1555 | 41.5k | case 0x1: |
1556 | 41.5k | i_count = 2; |
1557 | 41.5k | break; |
1558 | 12 | case 0x2: |
1559 | 12 | i_count = 9 + bs_read( s, 4 ); |
1560 | 12 | i_color = bs_read( s, 4 ); |
1561 | 12 | break; |
1562 | 10 | case 0x3: |
1563 | 10 | i_count= 25 + bs_read( s, 8 ); |
1564 | 10 | i_color = bs_read( s, 4 ); |
1565 | 10 | break; |
1566 | 41.5k | } |
1567 | 41.5k | } |
1568 | 87.1k | } |
1569 | 612k | } |
1570 | | |
1571 | 1.32M | if( !i_count ) continue; |
1572 | | |
1573 | | /* Sanity check */ |
1574 | 808k | if( ( i_count + *pi_off ) > i_width ) break; |
1575 | | |
1576 | 785k | if( i_count == 1 ) p[*pi_off] = i_color; |
1577 | 88.5k | else memset( ( p + *pi_off ), i_color, i_count ); |
1578 | | |
1579 | 785k | (*pi_off) += i_count; |
1580 | 785k | } |
1581 | | |
1582 | 534k | bs_align( s ); |
1583 | 534k | } |
1584 | | |
1585 | | static void dvbsub_pdata8bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off ) |
1586 | 471k | { |
1587 | 471k | bool b_stop = false; |
1588 | | |
1589 | 919k | while( !b_stop && !bs_eof( s ) ) |
1590 | 482k | { |
1591 | 482k | int i_count = 0, i_color = 0; |
1592 | | |
1593 | 482k | i_color = bs_read( s, 8 ); |
1594 | 482k | if( i_color != 0x00 ) |
1595 | 11.6k | { |
1596 | | /* Add 1 pixel */ |
1597 | 11.6k | i_count = 1; |
1598 | 11.6k | } |
1599 | 471k | else |
1600 | 471k | { |
1601 | 471k | if( bs_read( s, 1 ) == 0x00 ) // Switch1 |
1602 | 471k | { |
1603 | 471k | i_count = bs_read( s, 7 ); |
1604 | 471k | if( i_count == 0x00 ) |
1605 | 436k | b_stop = true; |
1606 | 471k | } |
1607 | 17 | else |
1608 | 17 | { |
1609 | 17 | i_count = bs_read( s, 7 ); |
1610 | 17 | i_color = bs_read( s, 8 ); |
1611 | 17 | } |
1612 | 471k | } |
1613 | | |
1614 | 482k | if( !i_count ) continue; |
1615 | | |
1616 | | /* Sanity check */ |
1617 | 46.2k | if( ( i_count + *pi_off ) > i_width ) break; |
1618 | | |
1619 | 11.6k | if( i_count == 1 ) p[*pi_off] = i_color; |
1620 | 22 | else memset( ( p + *pi_off ), i_color, i_count ); |
1621 | | |
1622 | 11.6k | (*pi_off) += i_count; |
1623 | 11.6k | } |
1624 | | |
1625 | 471k | bs_align( s ); |
1626 | 471k | } |
1627 | | |
1628 | | static void free_all( decoder_t *p_dec ) |
1629 | 2.13k | { |
1630 | 2.13k | decoder_sys_t *p_sys = p_dec->p_sys; |
1631 | 2.13k | dvbsub_region_t *p_reg, *p_reg_next; |
1632 | 2.13k | dvbsub_clut_t *p_clut, *p_clut_next; |
1633 | | |
1634 | | /*free( p_sys->p_display ); No longer malloced */ |
1635 | | |
1636 | 3.30k | for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut_next ) |
1637 | 1.17k | { |
1638 | 1.17k | p_clut_next = p_clut->p_next; |
1639 | 1.17k | free( p_clut ); |
1640 | 1.17k | } |
1641 | 2.13k | p_sys->p_cluts = NULL; |
1642 | | |
1643 | 3.06k | for( p_reg = p_sys->p_regions; p_reg != NULL; p_reg = p_reg_next ) |
1644 | 930 | { |
1645 | 930 | p_reg_next = p_reg->p_next; |
1646 | 307k | for( int i = 0; i < p_reg->i_object_defs; i++ ) |
1647 | 306k | free( p_reg->p_object_defs[i].psz_text ); |
1648 | 930 | free( p_reg->p_object_defs ); |
1649 | 930 | free( p_reg->p_pixbuf ); |
1650 | 930 | free( p_reg ); |
1651 | 930 | } |
1652 | 2.13k | p_sys->p_regions = NULL; |
1653 | | |
1654 | 2.13k | if( p_sys->p_page ) |
1655 | 611 | { |
1656 | 611 | if( p_sys->p_page->i_region_defs ) |
1657 | 608 | free( p_sys->p_page->p_region_defs ); |
1658 | 611 | free( p_sys->p_page ); |
1659 | 611 | } |
1660 | 2.13k | p_sys->p_page = NULL; |
1661 | 2.13k | } |
1662 | | |
1663 | | static subpicture_t *render( decoder_t *p_dec ) |
1664 | 588 | { |
1665 | 588 | decoder_sys_t *p_sys = p_dec->p_sys; |
1666 | 588 | subpicture_t *p_spu; |
1667 | 588 | int i, j; |
1668 | 588 | int i_base_x; |
1669 | 588 | int i_base_y; |
1670 | | |
1671 | 588 | if ( p_sys->p_page == NULL) |
1672 | 0 | { |
1673 | 0 | return NULL; |
1674 | 0 | } |
1675 | | |
1676 | | /* Allocate the subpicture internal data. */ |
1677 | 588 | p_spu = decoder_NewSubpicture( p_dec, NULL ); |
1678 | 588 | if( !p_spu ) |
1679 | 0 | return NULL; |
1680 | | |
1681 | | /* Set the pf_render callback */ |
1682 | 588 | p_spu->i_start = p_sys->i_pts; |
1683 | | //p_spu->i_stop = (vlc_tick_t) 0; |
1684 | 588 | p_spu->b_ephemer = true; |
1685 | | //p_spu->b_fade = true; |
1686 | | //p_spu->i_stop = p_spu->i_start + (vlc_tick_t) (i_timeout * 1000000); |
1687 | 588 | p_spu->b_subtitle = true; |
1688 | | |
1689 | | /* Correct positioning of SPU */ |
1690 | 588 | i_base_x = p_sys->i_spu_x; |
1691 | 588 | i_base_y = p_sys->i_spu_y; |
1692 | | |
1693 | 588 | p_spu->i_original_picture_width = (unsigned)p_sys->display.i_width_minus1 + 1; |
1694 | 588 | p_spu->i_original_picture_height = (unsigned)p_sys->display.i_height_minus1 + 1; |
1695 | | |
1696 | 588 | if( p_sys->display.b_windowed ) |
1697 | 0 | { |
1698 | | /* From en_300743v01 - */ |
1699 | | /* the DDS is there to indicate intended size/position of text */ |
1700 | | /* the intended video area is ->i_width/height */ |
1701 | | /* the window is within this... SO... we should leave i_original_picture_width etc. as is */ |
1702 | | /* and ONLY change i_base_x. effectively i_max_x/y are only there to limit memory requirements*/ |
1703 | | /* we COULD use the upper limits to limit rendering to within these? */ |
1704 | | |
1705 | | /* see notes on DDS at the top of the file */ |
1706 | 0 | i_base_x += p_sys->display.i_x; |
1707 | 0 | i_base_y += p_sys->display.i_y; |
1708 | 0 | } |
1709 | | |
1710 | | /* Loop on region definitions */ |
1711 | | #ifdef DEBUG_DVBSUB |
1712 | | msg_Dbg( p_dec, "rendering %i regions", p_sys->p_page->i_region_defs ); |
1713 | | #endif |
1714 | | |
1715 | 1.27k | for( i = 0; i < p_sys->p_page->i_region_defs; i++ ) |
1716 | 691 | { |
1717 | 691 | dvbsub_region_t *p_region; |
1718 | 691 | dvbsub_regiondef_t *p_regiondef; |
1719 | 691 | dvbsub_clut_t *p_clut; |
1720 | 691 | dvbsub_color_t *p_color; |
1721 | 691 | subpicture_region_t *p_spu_region; |
1722 | 691 | uint8_t *p_src, *p_dst; |
1723 | 691 | video_format_t fmt; |
1724 | 691 | video_palette_t palette; |
1725 | 691 | int i_pitch; |
1726 | | |
1727 | 691 | p_regiondef = &p_sys->p_page->p_region_defs[i]; |
1728 | | |
1729 | | /* Find associated region */ |
1730 | 1.49k | for( p_region = p_sys->p_regions; p_region != NULL; |
1731 | 802 | p_region = p_region->p_next ) |
1732 | 1.03k | { |
1733 | 1.03k | if( p_regiondef->i_id == p_region->i_id ) break; |
1734 | 1.03k | } |
1735 | | |
1736 | | #ifdef DEBUG_DVBSUB |
1737 | | /* if a region exists, then print it's size */ |
1738 | | if (p_region) |
1739 | | { |
1740 | | msg_Dbg( p_dec, "rendering region %i (%i,%i) to (%i,%i)", i, |
1741 | | p_regiondef->i_x, p_regiondef->i_y, |
1742 | | p_regiondef->i_x + p_region->i_width, |
1743 | | p_regiondef->i_y + p_region->i_height ); |
1744 | | } |
1745 | | else |
1746 | | { |
1747 | | msg_Dbg( p_dec, "rendering region %i (%i,%i) (no region matched to render)", i, |
1748 | | p_regiondef->i_x, p_regiondef->i_y ); |
1749 | | } |
1750 | | #endif |
1751 | | |
1752 | 691 | if( !p_region || !p_region->p_pixbuf ) |
1753 | 461 | { |
1754 | 461 | msg_Dbg( p_dec, "region %i not found or invalid", p_regiondef->i_id ); |
1755 | 461 | continue; |
1756 | 461 | } |
1757 | | |
1758 | | /* Find associated CLUT */ |
1759 | 472 | for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next ) |
1760 | 441 | { |
1761 | 441 | if( p_region->i_clut == p_clut->i_id ) break; |
1762 | 441 | } |
1763 | 230 | if( !p_clut ) |
1764 | 31 | { |
1765 | 31 | msg_Dbg( p_dec, "clut %i not found", p_region->i_clut ); |
1766 | 31 | continue; |
1767 | 31 | } |
1768 | | |
1769 | | /* FIXME: don't create a subpicture region with VLC CODEC YUVP |
1770 | | * when it actually is a TEXT region */ |
1771 | | |
1772 | | /* Create new SPU region */ |
1773 | 199 | video_format_Init( &fmt, VLC_CODEC_YUVP ); |
1774 | 199 | fmt.i_sar_num = 0; /* 0 means use aspect ratio of background video */ |
1775 | 199 | fmt.i_sar_den = 1; |
1776 | 199 | fmt.i_width = fmt.i_visible_width = p_region->i_width; |
1777 | 199 | fmt.i_height = fmt.i_visible_height = p_region->i_height; |
1778 | 199 | fmt.i_x_offset = fmt.i_y_offset = 0; |
1779 | 199 | fmt.p_palette = &palette; |
1780 | 199 | fmt.p_palette->i_entries = ( p_region->i_depth == 1 ) ? 4 : |
1781 | 199 | ( ( p_region->i_depth == 2 ) ? 16 : p_clut->c_8b_entries ); |
1782 | 199 | p_color = ( p_region->i_depth == 1 ) ? p_clut->c_2b : |
1783 | 199 | ( ( p_region->i_depth == 2 ) ? p_clut->c_4b : p_clut->c_8b ); |
1784 | 50.1k | for( j = 0; j < fmt.p_palette->i_entries; j++ ) |
1785 | 49.9k | { |
1786 | 49.9k | fmt.p_palette->palette[j][0] = p_color[j].Y; |
1787 | 49.9k | fmt.p_palette->palette[j][1] = p_color[j].Cb; /* U == Cb */ |
1788 | 49.9k | fmt.p_palette->palette[j][2] = p_color[j].Cr; /* V == Cr */ |
1789 | 49.9k | fmt.p_palette->palette[j][3] = 0xff - p_color[j].T; |
1790 | 49.9k | } |
1791 | 199 | switch (p_clut->dynamic_range_and_colour_gamut) |
1792 | 199 | { |
1793 | 195 | case DVBSUB_ST_COLORIMETRY_CDS: |
1794 | 195 | fmt.space = COLOR_SPACE_BT601; |
1795 | 195 | fmt.primaries = COLOR_PRIMARIES_BT601_525; |
1796 | 195 | fmt.transfer = TRANSFER_FUNC_BT709; |
1797 | 195 | break; |
1798 | 4 | case DVBSUB_ST_COLORIMETRY_SDR_709: |
1799 | 4 | fmt.space = COLOR_SPACE_BT709; |
1800 | 4 | fmt.primaries = COLOR_PRIMARIES_BT709; |
1801 | 4 | fmt.transfer = TRANSFER_FUNC_BT709; |
1802 | 4 | break; |
1803 | 0 | case DVBSUB_ST_COLORIMETRY_SDR_2020: |
1804 | 0 | fmt.space = COLOR_SPACE_BT2020; |
1805 | 0 | fmt.primaries = COLOR_PRIMARIES_BT2020; |
1806 | 0 | fmt.transfer = TRANSFER_FUNC_BT709; |
1807 | 0 | break; |
1808 | 0 | case DVBSUB_ST_COLORIMETRY_HDR_PQ: |
1809 | 0 | fmt.space = COLOR_SPACE_BT2020; |
1810 | 0 | fmt.primaries = COLOR_PRIMARIES_BT2020; |
1811 | 0 | fmt.transfer = TRANSFER_FUNC_SMPTE_ST2084; |
1812 | 0 | break; |
1813 | 0 | case DVBSUB_ST_COLORIMETRY_HDR_HLG: |
1814 | 0 | fmt.space = COLOR_SPACE_BT2020; |
1815 | 0 | fmt.primaries = COLOR_PRIMARIES_BT2020; |
1816 | 0 | fmt.transfer = TRANSFER_FUNC_HLG; |
1817 | 0 | break; |
1818 | 199 | } |
1819 | 199 | fmt.color_range = p_clut->color_range; |
1820 | | |
1821 | 199 | p_spu_region = subpicture_region_New( &fmt ); |
1822 | 199 | fmt.p_palette = NULL; /* was stack var */ |
1823 | 199 | video_format_Clean( &fmt ); |
1824 | 199 | if( !p_spu_region ) |
1825 | 0 | { |
1826 | 0 | msg_Err( p_dec, "cannot allocate SPU region" ); |
1827 | 0 | continue; |
1828 | 0 | } |
1829 | 199 | p_spu_region->b_absolute = true; p_spu_region->b_in_window = false; |
1830 | 199 | p_spu_region->i_x = i_base_x + p_regiondef->i_x; |
1831 | 199 | p_spu_region->i_y = i_base_y + p_regiondef->i_y; |
1832 | 199 | p_spu_region->i_align = p_sys->i_spu_position; |
1833 | 199 | vlc_spu_regions_push(&p_spu->regions, p_spu_region); |
1834 | | |
1835 | 199 | p_src = p_region->p_pixbuf; |
1836 | 199 | p_dst = p_spu_region->p_picture->Y_PIXELS; |
1837 | 199 | i_pitch = p_spu_region->p_picture->Y_PITCH; |
1838 | | |
1839 | | /* Copy pixel buffer */ |
1840 | 3.48k | for( j = 0; j < p_region->i_height; j++ ) |
1841 | 3.28k | { |
1842 | 3.28k | memcpy( p_dst, p_src, p_region->i_width ); |
1843 | 3.28k | p_src += p_region->i_width; |
1844 | 3.28k | p_dst += i_pitch; |
1845 | 3.28k | } |
1846 | | |
1847 | | /* Check subtitles encoded as strings of characters |
1848 | | * (since there are not rendered in the pixbuffer) */ |
1849 | 29.6k | for( j = 0; j < p_region->i_object_defs; j++ ) |
1850 | 29.4k | { |
1851 | 29.4k | dvbsub_objectdef_t *p_object_def = &p_region->p_object_defs[j]; |
1852 | | |
1853 | 29.4k | if( ( p_object_def->i_type != 1 ) || !p_object_def->psz_text ) |
1854 | 29.4k | continue; |
1855 | | |
1856 | | /* Create new SPU region */ |
1857 | 0 | p_spu_region = subpicture_region_NewText(); |
1858 | 0 | if( !p_spu_region ) |
1859 | 0 | { |
1860 | 0 | msg_Err( p_dec, "cannot allocate SPU region" ); |
1861 | 0 | continue; |
1862 | 0 | } |
1863 | | |
1864 | 0 | p_spu_region->fmt.i_sar_num = 1; |
1865 | 0 | p_spu_region->fmt.i_sar_den = 1; |
1866 | 0 | p_spu_region->fmt.i_width = p_spu_region->fmt.i_visible_width = p_region->i_width; |
1867 | 0 | p_spu_region->fmt.i_height = p_spu_region->fmt.i_visible_height = p_region->i_height; |
1868 | |
|
1869 | 0 | p_spu_region->p_text = text_segment_New( p_object_def->psz_text ); |
1870 | 0 | p_spu_region->b_absolute = true; p_spu_region->b_in_window = false; |
1871 | 0 | p_spu_region->i_x = i_base_x + p_regiondef->i_x + p_object_def->i_x; |
1872 | 0 | p_spu_region->i_y = i_base_y + p_regiondef->i_y + p_object_def->i_y; |
1873 | 0 | p_spu_region->i_align = p_sys->i_spu_position; |
1874 | 0 | vlc_spu_regions_push(&p_spu->regions, p_spu_region); |
1875 | 0 | } |
1876 | 199 | } |
1877 | | |
1878 | 588 | return p_spu; |
1879 | 588 | } |
1880 | | |
1881 | | /***************************************************************************** |
1882 | | * encoder_sys_t : encoder descriptor |
1883 | | *****************************************************************************/ |
1884 | | typedef struct encoder_region_t |
1885 | | { |
1886 | | int i_width; |
1887 | | int i_height; |
1888 | | |
1889 | | } encoder_region_t; |
1890 | | |
1891 | | typedef struct |
1892 | | { |
1893 | | unsigned int i_page_ver; |
1894 | | unsigned int i_region_ver; |
1895 | | unsigned int i_clut_ver; |
1896 | | |
1897 | | size_t i_regions; |
1898 | | encoder_region_t *p_regions; |
1899 | | |
1900 | | vlc_tick_t i_pts; |
1901 | | |
1902 | | /* subpicture positioning */ |
1903 | | int i_offset_x; |
1904 | | int i_offset_y; |
1905 | | } encoder_sys_t; |
1906 | | |
1907 | | #ifdef ENABLE_SOUT |
1908 | | static void encode_page_composition( encoder_t *, bs_t *, const subpicture_t * ); |
1909 | | static void encode_clut( encoder_t *, bs_t *, subpicture_region_t * ); |
1910 | | static void encode_region_composition( encoder_t *, bs_t *, const subpicture_t * ); |
1911 | | static void encode_object( encoder_t *, bs_t *, const subpicture_t * ); |
1912 | | |
1913 | | /***************************************************************************** |
1914 | | * OpenEncoder: probe the encoder and return score |
1915 | | *****************************************************************************/ |
1916 | | static int OpenEncoder( vlc_object_t *p_this ) |
1917 | 0 | { |
1918 | 0 | encoder_t *p_enc = (encoder_t *)p_this; |
1919 | 0 | encoder_sys_t *p_sys; |
1920 | |
|
1921 | 0 | if( ( p_enc->fmt_out.i_codec != VLC_CODEC_DVBS ) && |
1922 | 0 | !p_enc->obj.force ) |
1923 | 0 | { |
1924 | 0 | return VLC_EGENERIC; |
1925 | 0 | } |
1926 | | |
1927 | | /* Allocate the memory needed to store the decoder's structure */ |
1928 | 0 | p_sys = malloc(sizeof(encoder_sys_t)); |
1929 | 0 | if (p_sys == NULL) |
1930 | 0 | return VLC_ENOMEM; |
1931 | 0 | p_enc->p_sys = p_sys; |
1932 | |
|
1933 | 0 | p_enc->fmt_out.i_codec = VLC_CODEC_DVBS; |
1934 | 0 | p_enc->fmt_out.subs.dvb.i_id = 1 << 16 | 1; |
1935 | |
|
1936 | 0 | config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg ); |
1937 | |
|
1938 | 0 | p_sys->i_page_ver = 0; |
1939 | 0 | p_sys->i_region_ver = 0; |
1940 | 0 | p_sys->i_clut_ver = 0; |
1941 | 0 | p_sys->i_regions = 0; |
1942 | 0 | p_sys->p_regions = 0; |
1943 | |
|
1944 | 0 | p_sys->i_offset_x = var_CreateGetInteger( p_this, ENC_CFG_PREFIX "x" ); |
1945 | 0 | p_sys->i_offset_y = var_CreateGetInteger( p_this, ENC_CFG_PREFIX "y" ); |
1946 | |
|
1947 | 0 | static const struct vlc_encoder_operations ops = |
1948 | 0 | { |
1949 | 0 | .close = CloseEncoder, |
1950 | 0 | .encode_sub = Encode, |
1951 | 0 | }; |
1952 | 0 | p_enc->ops = &ops; |
1953 | |
|
1954 | 0 | return VLC_SUCCESS; |
1955 | 0 | } |
1956 | | |
1957 | | /* FIXME: this routine is a hack to convert VLC_CODEC_YUVA |
1958 | | * into VLC_CODEC_YUVP |
1959 | | */ |
1960 | | static void YuvaYuvp( subpicture_t *p_subpic ) |
1961 | 0 | { |
1962 | 0 | const subpicture_region_t *p_region; |
1963 | |
|
1964 | 0 | vlc_spu_regions_foreach_const(p_region, &p_subpic->regions) |
1965 | 0 | { |
1966 | 0 | video_format_t *p_fmt = &p_region->p_picture->format; |
1967 | 0 | int i = 0, j = 0, n = 0, p = 0; |
1968 | 0 | int i_max_entries = 256; |
1969 | |
|
1970 | | #ifdef RANDOM_DITHERING |
1971 | | int i_seed = 0xdeadbeef; /* random seed */ |
1972 | | #else |
1973 | 0 | int *pi_delta; |
1974 | 0 | #endif |
1975 | 0 | int i_pixels = p_region->p_picture->p[0].i_visible_lines |
1976 | 0 | * p_region->p_picture->Y_PITCH; |
1977 | 0 | int i_iterator = p_region->p_picture->p[0].i_visible_lines * 3 / 4 |
1978 | 0 | * p_region->p_picture->Y_PITCH |
1979 | 0 | + p_region->p_picture->Y_PITCH * 1 / 3; |
1980 | 0 | int i_tolerance = 0; |
1981 | |
|
1982 | | #ifdef DEBUG_DVBSUB1 |
1983 | | /* p_enc not valid here */ |
1984 | | msg_Dbg( p_enc, "YuvaYuvp: i_pixels=%d, i_iterator=%d", i_pixels, i_iterator ); |
1985 | | #endif |
1986 | 0 | p_fmt->i_chroma = VLC_CODEC_YUVP; |
1987 | 0 | p_fmt->p_palette = (video_palette_t *) malloc( sizeof( video_palette_t ) ); |
1988 | 0 | if( !p_fmt->p_palette ) break; |
1989 | 0 | p_fmt->p_palette->i_entries = 0; |
1990 | | |
1991 | | /* Find best iterator using Euclide’s algorithm */ |
1992 | 0 | for( ; i_iterator > 1 ; i_iterator-- ) |
1993 | 0 | { |
1994 | 0 | int a = i_pixels; |
1995 | 0 | int b = i_iterator; |
1996 | 0 | int c; |
1997 | |
|
1998 | 0 | while( b ) |
1999 | 0 | { |
2000 | 0 | c = a % b; |
2001 | 0 | a = b; |
2002 | 0 | b = c; |
2003 | 0 | } |
2004 | |
|
2005 | 0 | if( a == 1 ) |
2006 | 0 | { |
2007 | 0 | break; |
2008 | 0 | } |
2009 | 0 | } |
2010 | | |
2011 | | /* Count colors, build best palette */ |
2012 | 0 | for( i_tolerance = 0; i_tolerance < 128; i_tolerance++ ) |
2013 | 0 | { |
2014 | 0 | bool b_success = true; |
2015 | 0 | p_fmt->p_palette->i_entries = 0; |
2016 | |
|
2017 | 0 | for( i = 0; i < i_pixels ; ) |
2018 | 0 | { |
2019 | 0 | uint8_t y, u, v, a; |
2020 | 0 | y = p_region->p_picture->Y_PIXELS[i]; |
2021 | 0 | u = p_region->p_picture->U_PIXELS[i]; |
2022 | 0 | v = p_region->p_picture->V_PIXELS[i]; |
2023 | 0 | a = p_region->p_picture->A_PIXELS[i]; |
2024 | 0 | for( j = 0; j < p_fmt->p_palette->i_entries; j++ ) |
2025 | 0 | { |
2026 | 0 | if( abs((int)p_fmt->p_palette->palette[j][0] - (int)y) <= i_tolerance && |
2027 | 0 | abs((int)p_fmt->p_palette->palette[j][1] - (int)u) <= i_tolerance && |
2028 | 0 | abs((int)p_fmt->p_palette->palette[j][2] - (int)v) <= i_tolerance && |
2029 | 0 | abs((int)p_fmt->p_palette->palette[j][3] - (int)a) <= i_tolerance / 2 ) |
2030 | 0 | { |
2031 | 0 | break; |
2032 | 0 | } |
2033 | 0 | } |
2034 | 0 | if( j == p_fmt->p_palette->i_entries ) |
2035 | 0 | { |
2036 | 0 | p_fmt->p_palette->palette[j][0] = y; |
2037 | 0 | p_fmt->p_palette->palette[j][1] = u; |
2038 | 0 | p_fmt->p_palette->palette[j][2] = v; |
2039 | 0 | p_fmt->p_palette->palette[j][3] = a; |
2040 | 0 | p_fmt->p_palette->i_entries++; |
2041 | 0 | } |
2042 | 0 | if( p_fmt->p_palette->i_entries >= i_max_entries ) |
2043 | 0 | { |
2044 | 0 | b_success = false; |
2045 | 0 | break; |
2046 | 0 | } |
2047 | 0 | i += i_iterator; |
2048 | 0 | if( i > i_pixels ) |
2049 | 0 | { |
2050 | 0 | i -= i_pixels; |
2051 | 0 | } |
2052 | 0 | } |
2053 | |
|
2054 | 0 | if( b_success ) |
2055 | 0 | { |
2056 | 0 | break; |
2057 | 0 | } |
2058 | 0 | } |
2059 | |
|
2060 | | #ifdef DEBUG_DVBSUB1 |
2061 | | /* p_enc not valid here */ |
2062 | | msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries ); |
2063 | | #endif |
2064 | |
|
2065 | 0 | #ifndef RANDOM_DITHERING |
2066 | 0 | pi_delta = calloc( ( p_region->p_picture->Y_PITCH + 1 ) * 4, sizeof(int) ); |
2067 | 0 | if (unlikely(pi_delta == NULL)) |
2068 | 0 | return; |
2069 | 0 | #endif |
2070 | | |
2071 | | /* Fill image with our new colours */ |
2072 | 0 | for( p = 0; p < p_region->p_picture->p[0].i_visible_lines ; p++ ) |
2073 | 0 | { |
2074 | 0 | int i_ydelta = 0, i_udelta = 0, i_vdelta = 0, i_adelta = 0; |
2075 | |
|
2076 | 0 | for( n = 0; n < p_region->p_picture->Y_PITCH ; n++ ) |
2077 | 0 | { |
2078 | 0 | int i_offset = p * p_region->p_picture->Y_PITCH + n; |
2079 | 0 | int y, u, v, a; |
2080 | 0 | int i_mindist, i_best; |
2081 | |
|
2082 | 0 | y = p_region->p_picture->Y_PIXELS[i_offset]; |
2083 | 0 | u = p_region->p_picture->U_PIXELS[i_offset]; |
2084 | 0 | v = p_region->p_picture->V_PIXELS[i_offset]; |
2085 | 0 | a = p_region->p_picture->A_PIXELS[i_offset]; |
2086 | | |
2087 | | /* Add dithering compensation */ |
2088 | | #ifdef RANDOM_DITHERING |
2089 | | y += ((i_seed & 0xff) - 0x80) * i_tolerance / 0x80; |
2090 | | u += (((i_seed >> 8) & 0xff) - 0x80) * i_tolerance / 0x80; |
2091 | | v += (((i_seed >> 16) & 0xff) - 0x80) * i_tolerance / 0x80; |
2092 | | a += (((i_seed >> 24) & 0xff) - 0x80) * i_tolerance / 0x80; |
2093 | | #else |
2094 | 0 | y += i_ydelta + pi_delta[ n * 4 + 0 ]; |
2095 | 0 | u += i_udelta + pi_delta[ n * 4 + 1 ]; |
2096 | 0 | v += i_vdelta + pi_delta[ n * 4 + 2 ]; |
2097 | 0 | a += i_adelta + pi_delta[ n * 4 + 3 ]; |
2098 | 0 | #endif |
2099 | | |
2100 | | /* Find best colour in palette */ |
2101 | 0 | for( i_mindist = INT_MAX, i_best = 0, j = 0; j < p_fmt->p_palette->i_entries; j++ ) |
2102 | 0 | { |
2103 | 0 | int i_dist = 0; |
2104 | |
|
2105 | 0 | i_dist += abs((int)p_fmt->p_palette->palette[j][0] - y); |
2106 | 0 | i_dist += abs((int)p_fmt->p_palette->palette[j][1] - u); |
2107 | 0 | i_dist += abs((int)p_fmt->p_palette->palette[j][2] - v); |
2108 | 0 | i_dist += 2 * abs((int)p_fmt->p_palette->palette[j][3] - a); |
2109 | |
|
2110 | 0 | if( i_dist < i_mindist ) |
2111 | 0 | { |
2112 | 0 | i_mindist = i_dist; |
2113 | 0 | i_best = j; |
2114 | 0 | } |
2115 | 0 | } |
2116 | | |
2117 | | /* Set pixel to best color */ |
2118 | 0 | p_region->p_picture->Y_PIXELS[i_offset] = i_best; |
2119 | | |
2120 | | /* Update dithering state */ |
2121 | | #ifdef RANDOM_DITHERING |
2122 | | i_seed = (i_seed * 0x1283837) ^ 0x789479 ^ (i_seed >> 13); |
2123 | | #else |
2124 | 0 | i_ydelta = y - (int)p_fmt->p_palette->palette[i_best][0]; |
2125 | 0 | i_udelta = u - (int)p_fmt->p_palette->palette[i_best][1]; |
2126 | 0 | i_vdelta = v - (int)p_fmt->p_palette->palette[i_best][2]; |
2127 | 0 | i_adelta = a - (int)p_fmt->p_palette->palette[i_best][3]; |
2128 | 0 | pi_delta[ n * 4 + 0 ] = i_ydelta * 3 / 8; |
2129 | 0 | pi_delta[ n * 4 + 1 ] = i_udelta * 3 / 8; |
2130 | 0 | pi_delta[ n * 4 + 2 ] = i_vdelta * 3 / 8; |
2131 | 0 | pi_delta[ n * 4 + 3 ] = i_adelta * 3 / 8; |
2132 | 0 | i_ydelta = i_ydelta * 5 / 8; |
2133 | 0 | i_udelta = i_udelta * 5 / 8; |
2134 | 0 | i_vdelta = i_vdelta * 5 / 8; |
2135 | 0 | i_adelta = i_adelta * 5 / 8; |
2136 | 0 | #endif |
2137 | 0 | } |
2138 | 0 | } |
2139 | 0 | #ifndef RANDOM_DITHERING |
2140 | 0 | free( pi_delta ); |
2141 | 0 | #endif |
2142 | | |
2143 | | /* pad palette */ |
2144 | 0 | for( i = p_fmt->p_palette->i_entries; i < i_max_entries; i++ ) |
2145 | 0 | memset(p_fmt->p_palette->palette[i], 0, sizeof(p_fmt->p_palette->palette[i])); |
2146 | 0 | p_fmt->p_palette->i_entries = i_max_entries; |
2147 | | #ifdef DEBUG_DVBSUB1 |
2148 | | /* p_enc not valid here */ |
2149 | | msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries ); |
2150 | | #endif |
2151 | 0 | } |
2152 | 0 | } /* End of hack */ |
2153 | | |
2154 | | /**************************************************************************** |
2155 | | * Encode: the whole thing |
2156 | | ****************************************************************************/ |
2157 | | static block_t *Encode( encoder_t *p_enc, subpicture_t *p_subpic ) |
2158 | 0 | { |
2159 | 0 | subpicture_region_t *p_region = NULL; |
2160 | 0 | bs_t bits, *s = &bits; |
2161 | 0 | block_t *p_block; |
2162 | |
|
2163 | 0 | if( !p_subpic || vlc_spu_regions_is_empty(&p_subpic->regions) ) return NULL; |
2164 | | |
2165 | | /* FIXME: this is a hack to convert VLC_CODEC_YUVA into |
2166 | | * VLC_CODEC_YUVP |
2167 | | */ |
2168 | 0 | p_region = vlc_spu_regions_first_or_null(&p_subpic->regions); |
2169 | | /* Sanity check */ |
2170 | 0 | if( !p_region ) return NULL; |
2171 | | |
2172 | 0 | if( !subpicture_region_IsText( p_region ) ) |
2173 | 0 | { |
2174 | 0 | if( p_region->p_picture->format.i_chroma == VLC_CODEC_YUVA ) |
2175 | 0 | { |
2176 | 0 | YuvaYuvp( p_subpic ); |
2177 | 0 | } |
2178 | |
|
2179 | 0 | if( p_region->p_picture->format.i_chroma != VLC_CODEC_YUVP ) |
2180 | 0 | { |
2181 | 0 | msg_Err( p_enc, "chroma %4.4s not supported", (char *)&p_region->p_picture->format.i_chroma ); |
2182 | 0 | return NULL; |
2183 | 0 | } |
2184 | | |
2185 | 0 | if( p_region->p_picture->format.p_palette ) |
2186 | 0 | { |
2187 | 0 | switch( p_region->p_picture->format.p_palette->i_entries ) |
2188 | 0 | { |
2189 | 0 | case 0: |
2190 | 0 | case 4: |
2191 | 0 | case 16: |
2192 | 0 | case 256: |
2193 | 0 | break; |
2194 | 0 | default: |
2195 | 0 | msg_Err( p_enc, "subpicture palette (%d) not handled", |
2196 | 0 | p_region->p_picture->format.p_palette->i_entries ); |
2197 | 0 | return NULL; |
2198 | 0 | } |
2199 | 0 | } |
2200 | 0 | } |
2201 | | /* End of hack */ |
2202 | | |
2203 | | #ifdef DEBUG_DVBSUB |
2204 | | msg_Dbg( p_enc, "encoding subpicture" ); |
2205 | | #endif |
2206 | 0 | p_block = block_Alloc( 64000 ); |
2207 | 0 | if( unlikely(p_block == NULL) ) |
2208 | 0 | return NULL; |
2209 | | |
2210 | 0 | bs_init( s, p_block->p_buffer, p_block->i_buffer ); |
2211 | |
|
2212 | 0 | bs_write( s, 8, 0x20 ); /* Data identifier */ |
2213 | 0 | bs_write( s, 8, 0x0 ); /* Subtitle stream id */ |
2214 | |
|
2215 | 0 | encode_page_composition( p_enc, s, p_subpic ); |
2216 | 0 | encode_region_composition( p_enc, s, p_subpic ); |
2217 | 0 | encode_clut( p_enc, s, p_region ); |
2218 | 0 | encode_object( p_enc, s, p_subpic ); |
2219 | | |
2220 | | /* End of display */ |
2221 | 0 | bs_write( s, 8, 0x0f ); /* Sync byte */ |
2222 | 0 | bs_write( s, 8, DVBSUB_ST_ENDOFDISPLAY ); /* Segment type */ |
2223 | 0 | bs_write( s, 16, 1 ); /* Page id */ |
2224 | 0 | bs_write( s, 16, 0 ); /* Segment length */ |
2225 | |
|
2226 | 0 | bs_write( s, 8, 0xff );/* End marker */ |
2227 | 0 | p_block->i_buffer = bs_pos( s ) / 8; |
2228 | 0 | p_block->i_pts = p_block->i_dts = p_subpic->i_start; |
2229 | 0 | if( !p_subpic->b_ephemer && |
2230 | 0 | ( p_subpic->i_stop != VLC_TICK_INVALID && p_subpic->i_stop > p_subpic->i_start ) ) |
2231 | 0 | { |
2232 | 0 | block_t *p_block_stop; |
2233 | |
|
2234 | 0 | p_block->i_length = p_subpic->i_stop - p_subpic->i_start; |
2235 | | |
2236 | | /* Send another (empty) subtitle to signal the end of display */ |
2237 | 0 | p_block_stop = block_Alloc( 64000 ); |
2238 | 0 | if( unlikely(p_block_stop == NULL) ) |
2239 | 0 | { |
2240 | 0 | block_Release(p_block); |
2241 | 0 | return NULL; |
2242 | 0 | } |
2243 | | |
2244 | 0 | bs_init( s, p_block_stop->p_buffer, p_block_stop->i_buffer ); |
2245 | 0 | bs_write( s, 8, 0x20 ); /* Data identifier */ |
2246 | 0 | bs_write( s, 8, 0x0 ); /* Subtitle stream id */ |
2247 | 0 | encode_page_composition( p_enc, s, 0 ); |
2248 | 0 | bs_write( s, 8, 0x0f ); /* Sync byte */ |
2249 | 0 | bs_write( s, 8, DVBSUB_ST_ENDOFDISPLAY ); /* Segment type */ |
2250 | 0 | bs_write( s, 16, 1 ); /* Page id */ |
2251 | 0 | bs_write( s, 16, 0 ); /* Segment length */ |
2252 | 0 | bs_write( s, 8, 0xff );/* End marker */ |
2253 | 0 | p_block_stop->i_buffer = bs_pos( s ) / 8; |
2254 | 0 | p_block_stop->i_pts = p_block_stop->i_dts = p_subpic->i_stop; |
2255 | 0 | block_ChainAppend( &p_block, p_block_stop ); |
2256 | 0 | p_block_stop->i_length = VLC_TICK_FROM_MS(100); /* p_subpic->i_stop - p_subpic->i_start; */ |
2257 | 0 | } |
2258 | | #ifdef DEBUG_DVBSUB |
2259 | | msg_Dbg( p_enc, "subpicture encoded properly" ); |
2260 | | #endif |
2261 | 0 | return p_block; |
2262 | 0 | } |
2263 | | |
2264 | | /***************************************************************************** |
2265 | | * CloseEncoder: encoder destruction |
2266 | | *****************************************************************************/ |
2267 | | static void CloseEncoder( encoder_t *p_enc ) |
2268 | 0 | { |
2269 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
2270 | |
|
2271 | 0 | var_Destroy( p_enc , ENC_CFG_PREFIX "x" ); |
2272 | 0 | var_Destroy( p_enc , ENC_CFG_PREFIX "y" ); |
2273 | |
|
2274 | 0 | if( p_sys->i_regions ) free( p_sys->p_regions ); |
2275 | 0 | free( p_sys ); |
2276 | 0 | } |
2277 | | |
2278 | | static void encode_page_composition( encoder_t *p_enc, bs_t *s, |
2279 | | const subpicture_t *p_subpic ) |
2280 | 0 | { |
2281 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
2282 | 0 | const subpicture_region_t *p_region; |
2283 | 0 | bool b_mode_change = false; |
2284 | 0 | unsigned int i_regions; |
2285 | 0 | int i_timeout; |
2286 | |
|
2287 | 0 | bs_write( s, 8, 0x0f ); /* Sync byte */ |
2288 | 0 | bs_write( s, 8, DVBSUB_ST_PAGE_COMPOSITION ); /* Segment type */ |
2289 | 0 | bs_write( s, 16, 1 ); /* Page id */ |
2290 | |
|
2291 | 0 | i_regions = 0; |
2292 | 0 | if (p_subpic) |
2293 | 0 | vlc_spu_regions_foreach_const(p_region, &p_subpic->regions) |
2294 | 0 | { |
2295 | 0 | if( i_regions >= p_sys->i_regions ) |
2296 | 0 | { |
2297 | 0 | encoder_region_t region; |
2298 | 0 | region.i_width = region.i_height = 0; |
2299 | 0 | p_sys->p_regions = xrealloc( p_sys->p_regions, |
2300 | 0 | sizeof(encoder_region_t) * (p_sys->i_regions + 1) ); |
2301 | 0 | p_sys->p_regions[p_sys->i_regions++] = region; |
2302 | 0 | } |
2303 | |
|
2304 | 0 | if( ( p_sys->p_regions[i_regions].i_width < |
2305 | 0 | (int)p_region->fmt.i_visible_width ) || |
2306 | 0 | ( p_sys->p_regions[i_regions].i_width > |
2307 | 0 | (int)p_region->fmt.i_visible_width ) ) |
2308 | 0 | { |
2309 | 0 | b_mode_change = true; |
2310 | 0 | msg_Dbg( p_enc, "region %u width change: %i -> %i", |
2311 | 0 | i_regions, p_sys->p_regions[i_regions].i_width, |
2312 | 0 | p_region->fmt.i_visible_width ); |
2313 | 0 | p_sys->p_regions[i_regions].i_width = |
2314 | 0 | p_region->fmt.i_visible_width; |
2315 | 0 | } |
2316 | 0 | if( p_sys->p_regions[i_regions].i_height < |
2317 | 0 | (int)p_region->fmt.i_visible_height ) |
2318 | 0 | { |
2319 | 0 | b_mode_change = true; |
2320 | 0 | msg_Dbg( p_enc, "region %u height change: %i -> %i", |
2321 | 0 | i_regions, p_sys->p_regions[i_regions].i_height, |
2322 | 0 | p_region->fmt.i_visible_height ); |
2323 | 0 | p_sys->p_regions[i_regions].i_height = |
2324 | 0 | p_region->fmt.i_visible_height; |
2325 | 0 | } |
2326 | 0 | i_regions++; |
2327 | 0 | } |
2328 | |
|
2329 | 0 | bs_write( s, 16, i_regions * 6 + 2 ); /* Segment length */ |
2330 | |
|
2331 | 0 | i_timeout = 0; |
2332 | 0 | if( p_subpic && !p_subpic->b_ephemer && |
2333 | 0 | ( p_subpic->i_stop != VLC_TICK_INVALID && p_subpic->i_stop > p_subpic->i_start ) ) |
2334 | 0 | { |
2335 | 0 | i_timeout = SEC_FROM_VLC_TICK(p_subpic->i_stop - p_subpic->i_start); |
2336 | 0 | } |
2337 | |
|
2338 | 0 | bs_write( s, 8, i_timeout ); /* Timeout */ |
2339 | 0 | bs_write( s, 4, p_sys->i_page_ver++ ); |
2340 | 0 | bs_write( s, 2, b_mode_change ? |
2341 | 0 | DVBSUB_PCS_STATE_CHANGE : DVBSUB_PCS_STATE_ACQUISITION ); |
2342 | 0 | bs_write( s, 2, 0 ); /* Reserved */ |
2343 | |
|
2344 | 0 | i_regions = 0; |
2345 | 0 | if (p_subpic) |
2346 | 0 | vlc_spu_regions_foreach_const(p_region, &p_subpic->regions) |
2347 | 0 | { |
2348 | 0 | bs_write( s, 8, i_regions ); |
2349 | 0 | bs_write( s, 8, 0 ); /* Reserved */ |
2350 | 0 | if( (p_sys->i_offset_x > 0) && (p_sys->i_offset_y > 0) ) |
2351 | 0 | { |
2352 | 0 | bs_write( s, 16, p_sys->i_offset_x ); /* override x position */ |
2353 | 0 | bs_write( s, 16, p_sys->i_offset_y ); /* override y position */ |
2354 | 0 | } |
2355 | 0 | else |
2356 | 0 | { |
2357 | 0 | bs_write( s, 16, p_region->i_x ); |
2358 | 0 | bs_write( s, 16, p_region->i_y ); |
2359 | 0 | } |
2360 | 0 | i_regions++; |
2361 | 0 | } |
2362 | 0 | } |
2363 | | |
2364 | | static void encode_clut( encoder_t *p_enc, bs_t *s, subpicture_region_t *p_region ) |
2365 | 0 | { |
2366 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
2367 | 0 | video_palette_t *p_pal, empty_palette = { .i_entries = 4 }; |
2368 | | |
2369 | | /* Sanity check */ |
2370 | 0 | if( !p_region ) return; |
2371 | | |
2372 | 0 | if( !subpicture_region_IsText( p_region ) && p_region->p_picture->format.i_chroma == VLC_CODEC_YUVP ) |
2373 | 0 | { |
2374 | 0 | p_pal = p_region->p_picture->format.p_palette; |
2375 | 0 | } |
2376 | 0 | else |
2377 | 0 | p_pal = &empty_palette; |
2378 | |
|
2379 | 0 | bs_write( s, 8, 0x0f ); /* Sync byte */ |
2380 | 0 | bs_write( s, 8, DVBSUB_ST_CLUT_DEFINITION ); /* Segment type */ |
2381 | 0 | bs_write( s, 16, 1 ); /* Page id */ |
2382 | |
|
2383 | 0 | bs_write( s, 16, p_pal->i_entries * 6 + 2 ); /* Segment length */ |
2384 | 0 | bs_write( s, 8, 1 ); /* Clut id */ |
2385 | 0 | bs_write( s, 4, p_sys->i_clut_ver++ ); |
2386 | 0 | bs_write( s, 4, 0 ); /* Reserved */ |
2387 | |
|
2388 | 0 | for( int i = 0; i < p_pal->i_entries; i++ ) |
2389 | 0 | { |
2390 | 0 | bs_write( s, 8, i ); /* Clut entry id */ |
2391 | 0 | bs_write( s, 1, p_pal->i_entries == 4 ); /* 2bit/entry flag */ |
2392 | 0 | bs_write( s, 1, p_pal->i_entries == 16 ); /* 4bit/entry flag */ |
2393 | 0 | bs_write( s, 1, p_pal->i_entries == 256 ); /* 8bit/entry flag */ |
2394 | 0 | bs_write( s, 4, 0 ); /* Reserved */ |
2395 | 0 | bs_write( s, 1, 1 ); /* Full range flag */ |
2396 | 0 | bs_write( s, 8, p_pal->palette[i][3] ? /* Y value */ |
2397 | 0 | (p_pal->palette[i][0] ? p_pal->palette[i][0] : 16) : 0 ); |
2398 | 0 | bs_write( s, 8, p_pal->palette[i][1] ); /* Cr value */ |
2399 | 0 | bs_write( s, 8, p_pal->palette[i][2] ); /* Cb value */ |
2400 | 0 | bs_write( s, 8, 0xff - p_pal->palette[i][3] ); /* T value */ |
2401 | 0 | } |
2402 | 0 | } |
2403 | | |
2404 | | static void encode_region_composition( encoder_t *p_enc, bs_t *s, |
2405 | | const subpicture_t *p_subpic ) |
2406 | 0 | { |
2407 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
2408 | 0 | const subpicture_region_t *p_region; |
2409 | 0 | unsigned int i_region; |
2410 | |
|
2411 | 0 | i_region = 0; |
2412 | 0 | vlc_spu_regions_foreach_const(p_region, &p_subpic->regions) |
2413 | 0 | { |
2414 | 0 | int i_entries = 4, i_depth = 0x1, i_bg = 0; |
2415 | 0 | bool b_text = subpicture_region_IsText( p_region ); |
2416 | |
|
2417 | 0 | if( !b_text ) |
2418 | 0 | { |
2419 | 0 | video_palette_t *p_pal = p_region->p_picture->format.p_palette; |
2420 | |
|
2421 | 0 | if( !p_pal ) |
2422 | 0 | { |
2423 | 0 | msg_Err( p_enc, "subpicture has no palette - ignoring it" ); |
2424 | 0 | break; |
2425 | 0 | } |
2426 | | |
2427 | 0 | i_entries = p_pal->i_entries; |
2428 | 0 | i_depth = i_entries == 4 ? 0x1 : i_entries == 16 ? 0x2 : 0x3; |
2429 | |
|
2430 | 0 | for( i_bg = 0; i_bg < p_pal->i_entries; i_bg++ ) |
2431 | 0 | { |
2432 | 0 | if( !p_pal->palette[i_bg][3] ) break; |
2433 | 0 | } |
2434 | 0 | } |
2435 | | |
2436 | 0 | bs_write( s, 8, 0x0f ); /* Sync byte */ |
2437 | 0 | bs_write( s, 8, DVBSUB_ST_REGION_COMPOSITION ); /* Segment type */ |
2438 | 0 | bs_write( s, 16, 1 ); /* Page id */ |
2439 | |
|
2440 | 0 | bs_write( s, 16, 10 + 6 + (b_text ? 2 : 0) ); /* Segment length */ |
2441 | 0 | bs_write( s, 8, i_region ); |
2442 | 0 | bs_write( s, 4, p_sys->i_region_ver++ ); |
2443 | | |
2444 | | /* Region attributes */ |
2445 | 0 | bs_write( s, 1, i_bg < i_entries ); /* Fill */ |
2446 | 0 | bs_write( s, 3, 0 ); /* Reserved */ |
2447 | 0 | bs_write( s, 16, p_sys->p_regions[i_region].i_width ); |
2448 | 0 | bs_write( s, 16, p_sys->p_regions[i_region].i_height ); |
2449 | 0 | bs_write( s, 3, i_depth ); /* Region level of compatibility */ |
2450 | 0 | bs_write( s, 3, i_depth ); /* Region depth */ |
2451 | 0 | bs_write( s, 2, 0 ); /* Reserved */ |
2452 | 0 | bs_write( s, 8, 1 ); /* Clut id */ |
2453 | 0 | bs_write( s, 8, i_bg ); /* region 8bit pixel code */ |
2454 | 0 | bs_write( s, 4, i_bg ); /* region 4bit pixel code */ |
2455 | 0 | bs_write( s, 2, i_bg ); /* region 2bit pixel code */ |
2456 | 0 | bs_write( s, 2, 0 ); /* Reserved */ |
2457 | | |
2458 | | /* In our implementation we only have 1 object per region */ |
2459 | 0 | bs_write( s, 16, i_region ); |
2460 | 0 | bs_write( s, 2, b_text ? DVBSUB_OT_BASIC_CHAR:DVBSUB_OT_BASIC_BITMAP ); |
2461 | 0 | bs_write( s, 2, 0 ); /* object provider flag */ |
2462 | 0 | bs_write( s, 12, 0 );/* object horizontal position */ |
2463 | 0 | bs_write( s, 4, 0 ); /* Reserved */ |
2464 | 0 | bs_write( s, 12, 0 );/* object vertical position */ |
2465 | |
|
2466 | 0 | if( b_text ) |
2467 | 0 | { |
2468 | 0 | bs_write( s, 8, 1 ); /* foreground pixel code */ |
2469 | 0 | bs_write( s, 8, 0 ); /* background pixel code */ |
2470 | 0 | } |
2471 | 0 | i_region++; |
2472 | 0 | } |
2473 | 0 | } |
2474 | | |
2475 | | static void encode_pixel_data( encoder_t *p_enc, bs_t *s, |
2476 | | const subpicture_region_t *p_region, |
2477 | | bool b_top ); |
2478 | | |
2479 | | static void encode_object( encoder_t *p_enc, bs_t *s, const subpicture_t *p_subpic ) |
2480 | 0 | { |
2481 | 0 | encoder_sys_t *p_sys = p_enc->p_sys; |
2482 | 0 | const subpicture_region_t *p_region; |
2483 | 0 | int i_region; |
2484 | |
|
2485 | 0 | int i_length_pos, i_update_pos, i_pixel_data_pos; |
2486 | |
|
2487 | 0 | i_region = 0; |
2488 | 0 | vlc_spu_regions_foreach_const(p_region, &p_subpic->regions) |
2489 | 0 | { |
2490 | 0 | bs_write( s, 8, 0x0f ); /* Sync byte */ |
2491 | 0 | bs_write( s, 8, DVBSUB_ST_OBJECT_DATA ); /* Segment type */ |
2492 | 0 | bs_write( s, 16, 1 ); /* Page id */ |
2493 | |
|
2494 | 0 | i_length_pos = bs_pos( s ); |
2495 | 0 | bs_write( s, 16, 0 ); /* Segment length */ |
2496 | 0 | bs_write( s, 16, i_region ); /* Object id */ |
2497 | 0 | bs_write( s, 4, p_sys->i_region_ver++ ); |
2498 | | |
2499 | | /* object coding method */ |
2500 | 0 | if (subpicture_region_IsText( p_region )) |
2501 | 0 | bs_write( s, 2, 1 ); |
2502 | 0 | else if ( p_region->p_picture->format.i_chroma == VLC_CODEC_YUVP ) |
2503 | 0 | bs_write( s, 2, 0 ); |
2504 | 0 | else |
2505 | 0 | { |
2506 | 0 | msg_Err( p_enc, "FOURCC %4.4s not supported by encoder.", |
2507 | 0 | (const char*)&p_region->p_picture->format.i_chroma ); |
2508 | 0 | i_region++; |
2509 | 0 | continue; |
2510 | 0 | } |
2511 | | |
2512 | 0 | bs_write( s, 1, 0 ); /* non modifying color flag */ |
2513 | 0 | bs_write( s, 1, 0 ); /* Reserved */ |
2514 | |
|
2515 | 0 | if(subpicture_region_IsText( p_region )) |
2516 | 0 | { |
2517 | 0 | int i_size, i; |
2518 | |
|
2519 | 0 | if( !p_region->p_text ) |
2520 | 0 | { |
2521 | 0 | i_region++; |
2522 | 0 | continue; |
2523 | 0 | } |
2524 | | |
2525 | 0 | i_size = __MIN( strlen( p_region->p_text->psz_text ), 256 ); |
2526 | |
|
2527 | 0 | bs_write( s, 8, i_size ); /* number of characters in string */ |
2528 | 0 | for( i = 0; i < i_size; i++ ) |
2529 | 0 | { |
2530 | 0 | bs_write( s, 16, p_region->p_text->psz_text[i] ); |
2531 | 0 | } |
2532 | | |
2533 | | /* Update segment length */ |
2534 | 0 | SetWBE( &s->p_start[i_length_pos/8], |
2535 | 0 | (bs_pos(s) - i_length_pos)/8 -2 ); |
2536 | 0 | i_region++; |
2537 | 0 | continue; |
2538 | 0 | } |
2539 | | |
2540 | | /* Coding of a bitmap object */ |
2541 | 0 | i_update_pos = bs_pos( s ); |
2542 | 0 | bs_write( s, 16, 0 ); /* topfield data block length */ |
2543 | 0 | bs_write( s, 16, 0 ); /* bottomfield data block length */ |
2544 | | |
2545 | | /* Top field */ |
2546 | 0 | i_pixel_data_pos = bs_pos( s ); |
2547 | 0 | encode_pixel_data( p_enc, s, p_region, true ); |
2548 | 0 | i_pixel_data_pos = ( bs_pos( s ) - i_pixel_data_pos ) / 8; |
2549 | 0 | SetWBE( &s->p_start[i_update_pos/8], i_pixel_data_pos ); |
2550 | | |
2551 | | /* Bottom field */ |
2552 | 0 | i_pixel_data_pos = bs_pos( s ); |
2553 | 0 | encode_pixel_data( p_enc, s, p_region, false ); |
2554 | 0 | i_pixel_data_pos = ( bs_pos( s ) - i_pixel_data_pos ) / 8; |
2555 | 0 | SetWBE( &s->p_start[i_update_pos/8+2], i_pixel_data_pos ); |
2556 | | |
2557 | | /* Stuffing for word alignment */ |
2558 | 0 | bs_align_0( s ); |
2559 | 0 | if( bs_pos( s ) % 16 ) bs_write( s, 8, 0 ); |
2560 | | |
2561 | | /* Update segment length */ |
2562 | 0 | SetWBE( &s->p_start[i_length_pos/8], (bs_pos(s) - i_length_pos)/8 -2 ); |
2563 | 0 | i_region++; |
2564 | 0 | } |
2565 | 0 | } |
2566 | | |
2567 | | static void encode_pixel_line_2bp( bs_t *s, const subpicture_region_t *p_region, |
2568 | | int i_line ); |
2569 | | static void encode_pixel_line_4bp( bs_t *s, const subpicture_region_t *p_region, |
2570 | | int i_line ); |
2571 | | static void encode_pixel_line_8bp( bs_t *s, const subpicture_region_t *p_region, |
2572 | | int i_line ); |
2573 | | static void encode_pixel_data( encoder_t *p_enc, bs_t *s, |
2574 | | const subpicture_region_t *p_region, |
2575 | | bool b_top ) |
2576 | 0 | { |
2577 | 0 | unsigned int i_line; |
2578 | | |
2579 | | /* Encode line by line */ |
2580 | 0 | for( i_line = !b_top; i_line < p_region->fmt.i_visible_height; |
2581 | 0 | i_line += 2 ) |
2582 | 0 | { |
2583 | 0 | switch( p_region->p_picture->format.p_palette->i_entries ) |
2584 | 0 | { |
2585 | 0 | case 0: |
2586 | 0 | break; |
2587 | | |
2588 | 0 | case 4: |
2589 | 0 | bs_write( s, 8, 0x10 ); /* 2 bit/pixel code string */ |
2590 | 0 | encode_pixel_line_2bp( s, p_region, i_line ); |
2591 | 0 | break; |
2592 | | |
2593 | 0 | case 16: |
2594 | 0 | bs_write( s, 8, 0x11 ); /* 4 bit/pixel code string */ |
2595 | 0 | encode_pixel_line_4bp( s, p_region, i_line ); |
2596 | 0 | break; |
2597 | | |
2598 | 0 | case 256: |
2599 | 0 | bs_write( s, 8, 0x12 ); /* 8 bit/pixel code string */ |
2600 | 0 | encode_pixel_line_8bp( s, p_region, i_line ); |
2601 | 0 | break; |
2602 | | |
2603 | 0 | default: |
2604 | 0 | msg_Err( p_enc, "subpicture palette (%i) not handled", |
2605 | 0 | p_region->p_picture->format.p_palette->i_entries ); |
2606 | 0 | break; |
2607 | 0 | } |
2608 | | |
2609 | 0 | bs_write( s, 8, 0xf0 ); /* End of object line code */ |
2610 | 0 | } |
2611 | 0 | } |
2612 | | |
2613 | | static void encode_pixel_line_2bp( bs_t *s, const subpicture_region_t *p_region, |
2614 | | int i_line ) |
2615 | 0 | { |
2616 | 0 | unsigned int i, i_length = 0; |
2617 | 0 | int i_pitch = p_region->p_picture->p->i_pitch; |
2618 | 0 | uint8_t *p_data = &p_region->p_picture->p->p_pixels[ i_pitch * i_line ]; |
2619 | 0 | int i_last_pixel = p_data[0]; |
2620 | |
|
2621 | 0 | for( i = 0; i <= p_region->fmt.i_visible_width; i++ ) |
2622 | 0 | { |
2623 | 0 | if( ( i != p_region->fmt.i_visible_width ) && |
2624 | 0 | ( p_data[i] == i_last_pixel ) && ( i_length != 284 ) ) |
2625 | 0 | { |
2626 | 0 | i_length++; |
2627 | 0 | continue; |
2628 | 0 | } |
2629 | | |
2630 | 0 | if( ( i_length == 1 ) || ( i_length == 11 ) || ( i_length == 28 ) ) |
2631 | 0 | { |
2632 | | /* 2bit/pixel code */ |
2633 | 0 | if( i_last_pixel ) |
2634 | 0 | bs_write( s, 2, i_last_pixel ); |
2635 | 0 | else |
2636 | 0 | { |
2637 | 0 | bs_write( s, 2, 0 ); |
2638 | 0 | bs_write( s, 1, 0 ); |
2639 | 0 | bs_write( s, 1, 1 ); /* pseudo color 0 */ |
2640 | 0 | } |
2641 | 0 | i_length--; |
2642 | 0 | } |
2643 | |
|
2644 | 0 | if( i_length == 2 ) |
2645 | 0 | { |
2646 | 0 | if( i_last_pixel ) |
2647 | 0 | { |
2648 | 0 | bs_write( s, 2, i_last_pixel ); |
2649 | 0 | bs_write( s, 2, i_last_pixel ); |
2650 | 0 | } |
2651 | 0 | else |
2652 | 0 | { |
2653 | 0 | bs_write( s, 2, 0 ); |
2654 | 0 | bs_write( s, 1, 0 ); |
2655 | 0 | bs_write( s, 1, 0 ); |
2656 | 0 | bs_write( s, 2, 1 ); /* 2 * pseudo color 0 */ |
2657 | 0 | } |
2658 | 0 | } |
2659 | 0 | else if( i_length > 2 ) |
2660 | 0 | { |
2661 | 0 | bs_write( s, 2, 0 ); |
2662 | 0 | if( i_length <= 10 ) |
2663 | 0 | { |
2664 | 0 | bs_write( s, 1, 1 ); |
2665 | 0 | bs_write( s, 3, i_length - 3 ); |
2666 | 0 | bs_write( s, 2, i_last_pixel ); |
2667 | 0 | } |
2668 | 0 | else |
2669 | 0 | { |
2670 | 0 | bs_write( s, 1, 0 ); |
2671 | 0 | bs_write( s, 1, 0 ); |
2672 | |
|
2673 | 0 | if( i_length <= 27 ) |
2674 | 0 | { |
2675 | 0 | bs_write( s, 2, 2 ); |
2676 | 0 | bs_write( s, 4, i_length - 12 ); |
2677 | 0 | bs_write( s, 2, i_last_pixel ); |
2678 | 0 | } |
2679 | 0 | else |
2680 | 0 | { |
2681 | 0 | bs_write( s, 2, 3 ); |
2682 | 0 | bs_write( s, 8, i_length - 29 ); |
2683 | 0 | bs_write( s, 2, i_last_pixel ); |
2684 | 0 | } |
2685 | 0 | } |
2686 | 0 | } |
2687 | |
|
2688 | 0 | if( i == p_region->fmt.i_visible_width ) break; |
2689 | | |
2690 | 0 | i_last_pixel = p_data[i]; |
2691 | 0 | i_length = 1; |
2692 | 0 | } |
2693 | | |
2694 | | /* Stop */ |
2695 | 0 | bs_write( s, 2, 0 ); |
2696 | 0 | bs_write( s, 1, 0 ); |
2697 | 0 | bs_write( s, 1, 0 ); |
2698 | 0 | bs_write( s, 2, 0 ); |
2699 | | |
2700 | | /* Stuffing */ |
2701 | 0 | bs_align_0( s ); |
2702 | 0 | } |
2703 | | |
2704 | | static void encode_pixel_line_4bp( bs_t *s, const subpicture_region_t *p_region, |
2705 | | int i_line ) |
2706 | 0 | { |
2707 | 0 | unsigned int i, i_length = 0; |
2708 | 0 | int i_pitch = p_region->p_picture->p->i_pitch; |
2709 | 0 | uint8_t *p_data = &p_region->p_picture->p->p_pixels[ i_pitch * i_line ]; |
2710 | 0 | int i_last_pixel = p_data[0]; |
2711 | |
|
2712 | 0 | for( i = 0; i <= p_region->fmt.i_visible_width; i++ ) |
2713 | 0 | { |
2714 | 0 | if( i != p_region->fmt.i_visible_width && |
2715 | 0 | p_data[i] == i_last_pixel && i_length != 280 ) |
2716 | 0 | { |
2717 | 0 | i_length++; |
2718 | 0 | continue; |
2719 | 0 | } |
2720 | | |
2721 | 0 | if( ( i_length == 1 ) || |
2722 | 0 | ( ( i_length == 3 ) && i_last_pixel ) || |
2723 | 0 | ( i_length == 8 ) ) |
2724 | 0 | { |
2725 | | /* 4bit/pixel code */ |
2726 | 0 | if( i_last_pixel ) |
2727 | 0 | bs_write( s, 4, i_last_pixel ); |
2728 | 0 | else |
2729 | 0 | { |
2730 | 0 | bs_write( s, 4, 0 ); |
2731 | 0 | bs_write( s, 1, 1 ); |
2732 | 0 | bs_write( s, 1, 1 ); |
2733 | 0 | bs_write( s, 2, 0 ); /* pseudo color 0 */ |
2734 | 0 | } |
2735 | 0 | i_length--; |
2736 | 0 | } |
2737 | |
|
2738 | 0 | if( i_length == 2 ) |
2739 | 0 | { |
2740 | 0 | if( i_last_pixel ) |
2741 | 0 | { |
2742 | 0 | bs_write( s, 4, i_last_pixel ); |
2743 | 0 | bs_write( s, 4, i_last_pixel ); |
2744 | 0 | } |
2745 | 0 | else |
2746 | 0 | { |
2747 | 0 | bs_write( s, 4, 0 ); |
2748 | 0 | bs_write( s, 1, 1 ); |
2749 | 0 | bs_write( s, 1, 1 ); |
2750 | 0 | bs_write( s, 2, 1 ); /* 2 * pseudo color 0 */ |
2751 | 0 | } |
2752 | 0 | } |
2753 | 0 | else if( !i_last_pixel && ( i_length >= 3 ) && ( i_length <= 9 ) ) |
2754 | 0 | { |
2755 | 0 | bs_write( s, 4, 0 ); |
2756 | 0 | bs_write( s, 1, 0 ); |
2757 | 0 | bs_write( s, 3, i_length - 2 ); /* (i_length - 2) * color 0 */ |
2758 | 0 | } |
2759 | 0 | else if( i_length > 2 ) |
2760 | 0 | { |
2761 | 0 | bs_write( s, 4, 0 ); |
2762 | 0 | bs_write( s, 1, 1 ); |
2763 | |
|
2764 | 0 | if( i_length <= 7 ) |
2765 | 0 | { |
2766 | 0 | bs_write( s, 1, 0 ); |
2767 | 0 | bs_write( s, 2, i_length - 4 ); |
2768 | 0 | bs_write( s, 4, i_last_pixel ); |
2769 | 0 | } |
2770 | 0 | else |
2771 | 0 | { |
2772 | 0 | bs_write( s, 1, 1 ); |
2773 | |
|
2774 | 0 | if( i_length <= 24 ) |
2775 | 0 | { |
2776 | 0 | bs_write( s, 2, 2 ); |
2777 | 0 | bs_write( s, 4, i_length - 9 ); |
2778 | 0 | bs_write( s, 4, i_last_pixel ); |
2779 | 0 | } |
2780 | 0 | else |
2781 | 0 | { |
2782 | 0 | bs_write( s, 2, 3 ); |
2783 | 0 | bs_write( s, 8, i_length - 25 ); |
2784 | 0 | bs_write( s, 4, i_last_pixel ); |
2785 | 0 | } |
2786 | 0 | } |
2787 | 0 | } |
2788 | |
|
2789 | 0 | if( i == p_region->fmt.i_visible_width ) break; |
2790 | | |
2791 | 0 | i_last_pixel = p_data[i]; |
2792 | 0 | i_length = 1; |
2793 | 0 | } |
2794 | | |
2795 | | /* Stop */ |
2796 | 0 | bs_write( s, 8, 0 ); |
2797 | | |
2798 | | /* Stuffing */ |
2799 | 0 | bs_align_0( s ); |
2800 | 0 | } |
2801 | | |
2802 | | static void encode_pixel_line_8bp( bs_t *s, const subpicture_region_t *p_region, |
2803 | | int i_line ) |
2804 | 0 | { |
2805 | 0 | unsigned int i, i_length = 0; |
2806 | 0 | int i_pitch = p_region->p_picture->p->i_pitch; |
2807 | 0 | uint8_t *p_data = &p_region->p_picture->p->p_pixels[ i_pitch * i_line ]; |
2808 | 0 | int i_last_pixel = p_data[0]; |
2809 | |
|
2810 | 0 | for( i = 0; i <= p_region->fmt.i_visible_width; i++ ) |
2811 | 0 | { |
2812 | 0 | if( ( i != p_region->fmt.i_visible_width ) && |
2813 | 0 | ( p_data[i] == i_last_pixel ) && ( i_length != 127 ) ) |
2814 | 0 | { |
2815 | 0 | i_length++; |
2816 | 0 | continue; |
2817 | 0 | } |
2818 | | |
2819 | 0 | if( ( i_length == 1 ) && i_last_pixel ) |
2820 | 0 | { |
2821 | | /* 8bit/pixel code */ |
2822 | 0 | bs_write( s, 8, i_last_pixel ); |
2823 | 0 | } |
2824 | 0 | else if( ( i_length == 2 ) && i_last_pixel ) |
2825 | 0 | { |
2826 | | /* 8bit/pixel code */ |
2827 | 0 | bs_write( s, 8, i_last_pixel ); |
2828 | 0 | bs_write( s, 8, i_last_pixel ); |
2829 | 0 | } |
2830 | 0 | else if( i_length <= 127 ) |
2831 | 0 | { |
2832 | 0 | bs_write( s, 8, 0 ); |
2833 | |
|
2834 | 0 | if( !i_last_pixel ) |
2835 | 0 | { |
2836 | 0 | bs_write( s, 1, 0 ); |
2837 | 0 | bs_write( s, 7, i_length ); /* pseudo color 0 */ |
2838 | 0 | } |
2839 | 0 | else |
2840 | 0 | { |
2841 | 0 | bs_write( s, 1, 1 ); |
2842 | 0 | bs_write( s, 7, i_length ); |
2843 | 0 | bs_write( s, 8, i_last_pixel ); |
2844 | 0 | } |
2845 | 0 | } |
2846 | |
|
2847 | 0 | if( i == p_region->fmt.i_visible_width ) break; |
2848 | | |
2849 | 0 | i_last_pixel = p_data[i]; |
2850 | 0 | i_length = 1; |
2851 | 0 | } |
2852 | | |
2853 | | /* Stop */ |
2854 | 0 | bs_write( s, 8, 0 ); |
2855 | 0 | bs_write( s, 8, 0 ); |
2856 | | |
2857 | | /* Stuffing */ |
2858 | 0 | bs_align_0( s ); |
2859 | 0 | } |
2860 | | |
2861 | | #endif |
2862 | | |
2863 | | static void default_dds_init( decoder_t * p_dec ) |
2864 | 5.99k | { |
2865 | 5.99k | decoder_sys_t *p_sys = p_dec->p_sys; |
2866 | | |
2867 | | /* see notes on DDS at the top of the file */ |
2868 | | |
2869 | | /* configure for SD res in case DDS is not present */ |
2870 | 5.99k | p_sys->display.i_version = 0xff; /* an invalid version so it's always different */ |
2871 | 5.99k | p_sys->display.i_width_minus1 = 720-1; |
2872 | 5.99k | p_sys->display.i_height_minus1 = 576-1; |
2873 | | p_sys->display.b_windowed = false; |
2874 | 5.99k | } |