DVBCore  20.3.0
DVBCore Documentation
stbdsfn.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 //---includes for this file----------------------------------------------------
26 // compiler library header files
27 
28 #include <string.h>
29 
30 // third party header files
31 
32 // Ocean Blue Software header files
33 
34 #include <techtype.h>
35 #include <dbgfuncs.h>
36 
37 #include "stbhwos.h"
38 #include "stbhwav.h"
39 #include "stbhwosd.h"
40 
41 #include "stbheap.h"
42 #include "stbds.h"
43 #include "stbdpc.h"
44 
45 
46 //---constant definitions for this file----------------------------------------
47 
48 /* #define STB_SEGMENT_PRINT_REQUIRED */
49 /* #define STB_SUMMARY_PRINT_REQUIRED */
50 /* #define STB_SUB_DRIVER_PRINT_REQUIRED */
51 /* #define STB_REGION_PRINT_REQUIRED */
52 /* #define STB_ODS_PRINT_REQUIRED */
53 /* #define STB_OBJECT_PRINT_REQUIRED */
54 /* #define STB_PIXMAP_PRINT_REQUIRED */
55 /* #define STB_CDS_PRINT_REQUIRED */
56 /* #define STB_CLUT_PRINT_REQUIRED */
57 /* #define STB_END_PRINT_REQUIRED */
58 
59 //Initialisation checking
60 #ifdef STB_SUB_DRIVER_PRINT_REQUIRED
61  #ifdef STB_SUB_DRIVER_CHANNEL_DEBUG_REQUIRED
62  #define STB_SUB_DRIVER_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
63  #else
64  #define STB_SUB_DRIVER_PRINT(x) STB_SPDebugWrite x
65  #endif
66 #else
67  #define STB_SUB_DRIVER_PRINT(x)
68 #endif
69 
70 //Top level information - brief description of PCS, RCS, ODS etc
71 //Intended to establish context for more detailed dump of individual segment types
72 #ifdef STB_SEGMENT_PRINT_REQUIRED
73  #ifdef STB_SUB_DRIVER_CHANNEL_DEBUG_REQUIRED
74  #define STB_SEGMENT_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
75  #else
76  #define STB_SEGMENT_PRINT(x) STB_SPDebugWrite x
77  #endif
78 #else
79  #define STB_SEGMENT_PRINT(x)
80 #endif
81 
82 //Gives summary of state on reception of EDS
83 #ifdef STB_SUMMARY_PRINT_REQUIRED
84  #ifdef STB_SUB_DRIVER_CHANNEL_DEBUG_REQUIRED
85  #define STB_SUMMARY_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
86  #else
87  #define STB_SUMMARY_PRINT(x) STB_SPDebugWrite x
88  #endif
89 #else
90  #define STB_SUMMARY_PRINT(x)
91 #endif
92 
93 //Check footprint
94 #ifdef STB_REGION_PRINT_REQUIRED
95  #ifdef STB_REGION_CHANNEL_DEBUG_REQUIRED
96  #define STB_REGION_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
97  #else
98  #define STB_REGION_PRINT(x) STB_SPDebugWrite x
99  #endif
100 #else
101  #define STB_REGION_PRINT(x)
102 #endif
103 
104 #ifdef STB_CDS_PRINT_REQUIRED
105  #ifdef STB_CLUT_CHANNEL_DEBUG_REQUIRED
106  #define STB_CDS_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
107  #else
108  #define STB_CDS_PRINT(x) STB_SPDebugWrite x
109  #endif
110 #else
111  #define STB_CDS_PRINT(x)
112 #endif
113 
114 #ifdef STB_CLUT_PRINT_REQUIRED
115  #ifdef STB_CLUT_CHANNEL_DEBUG_REQUIRED
116  #define STB_CLUT_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
117  #else
118  #define STB_CLUT_PRINT(x) STB_SPDebugWrite x
119  #endif
120 #else
121  #define STB_CLUT_PRINT(x)
122 #endif
123 
124 #ifdef STB_ODS_PRINT_REQUIRED
125  #ifdef STB_ODS_CHANNEL_DEBUG_REQUIRED
126  #define STB_ODS_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
127  #else
128  #define STB_ODS_PRINT(x) STB_SPDebugWrite x
129  #endif
130 #else
131  #define STB_ODS_PRINT(x)
132 #endif
133 
134 #ifdef STB_OBJECT_PRINT_REQUIRED
135  #ifdef STB_OBJECT_CHANNEL_DEBUG_REQUIRED
136  #define STB_OBJECT_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
137  #else
138  #define STB_OBJECT_PRINT(x) STB_SPDebugWrite x
139  #endif
140 #else
141  #define STB_OBJECT_PRINT(x)
142 #endif
143 
144 #ifdef STB_PIXMAP_PRINT_REQUIRED
145  #ifdef STB_PIXMAP_CHANNEL_DEBUG_REQUIRED
146  #define STB_PIXMAP_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
147  #else
148  #define STB_PIXMAP_PRINT(x) STB_SPDebugWrite x
149  #endif
150 #else
151  #define STB_PIXMAP_PRINT(x)
152 #endif
153 
154 #ifdef STB_END_PRINT_REQUIRED
155  #ifdef STB_END_CHANNEL_DEBUG_REQUIRED
156  #define STB_END_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
157  #else
158  #define STB_END_PRINT(x) STB_SPDebugWrite x
159  #endif
160 #else
161  #define STB_END_PRINT(x)
162 #endif
163 
164 
165 #define TEMP_BUFFER_SIZE (1024 * 2)
166 #define SCAN_LINE_WIDTH 1950
167 
168 #define MAX_REGION_WIDTH 1920
169 #define MAX_REGION_HEIGHT 1080
170 
171 #define FIELD_SCAN_LINES (MAX_REGION_HEIGHT / 2) // this is a half value because on interlacing
172 
173 #ifdef DS_HEAP_USAGE
174  #define STB_GetMemory(x) STB_DSGetMemory(x)
175  #define STB_FreeMemory(x) STB_DSFreeMemory(x)
176 #endif
177 
178 //---local typedef structs for this file---------------------------------------
179 
180 // pixel subdata block intermediate struct
181 typedef struct pixel_sub_data_block
182 {
183  U16BIT num_lines;
184  U16BIT max_line_size;
185  U16BIT line_size[FIELD_SCAN_LINES];
186  U8BIT *data_line[FIELD_SCAN_LINES];
188 
189 
190 //---local (static) variable declarations for this file------------------------
191 // (internal variables declared static to make them local)
192 
193 static S_DISPLAY_SET subtitle_display_set = {NULL, NULL, NULL, NULL, NULL};
194 static S_PAGE_COMPOSITION page_1;
195 static S_PAGE_COMPOSITION page_2;
196 static U8BIT *temp_buffer;
197 
198 
199 // 32-bit CLUT where the 32bit value is in format of [TYCrCb] as 8bit values
200 // 0xff000000 is trgb transparent
201 
202 // 2 Bit default CLUT
203 static U32BIT default_2_bit_clut[4] =
204 {
205  0xff108080, 0x00478080, 0x00108080, 0x002b8080
206 };
207 
208 // 4 Bit default CLUT
209 static U32BIT default_4_bit_clut[16] =
210 {
211  0xff108080, 0x00209c76, 0x0030686d, 0x00418463, 0x00167b9c, 0x00279792, 0x00376389, 0x00478080,
212  0x00108080, 0x00188e7b, 0x00207476, 0x00288271, 0x00137d8e, 0x001b8b89, 0x00237184, 0x002b8080
213 };
214 
215 // 8 Bit default CLUT
216 static U32BIT default_8_bit_clut[256] =
217 {
218  0xff108080, 0xbf209c76, 0xbf30686d, 0xbf418463, 0xbf167b9c, 0xbf279792, 0xbf376389, 0xbf478080,
219  0x7f108080, 0x7f15897c, 0x7f1a7879, 0x7f208176, 0x7f127e89, 0x7f178786, 0x7f1c7683, 0x7f228080,
220  0x001b9379, 0x00209c76, 0x00258b73, 0x002b9470, 0x001d9182, 0x00229a7f, 0x0028897c, 0x002d9379,
221  0x7f1b9379, 0x7f209c76, 0x7f258b73, 0x7f2b9470, 0x7f1d9182, 0x7f229a7f, 0x7f28897c, 0x7f2d9379,
222  0x00257073, 0x002b7970, 0x0030686d, 0x00367169, 0x00276e7c, 0x002d7779, 0x00326676, 0x00387073,
223  0x7f257073, 0x7f2b7970, 0x7f30686d, 0x7f367169, 0x7f276e7c, 0x7f2d7779, 0x7f326676, 0x7f387073,
224  0x0030836c, 0x00368c69, 0x003b7b66, 0x00418463, 0x00338176, 0x00388a73, 0x003d7970, 0x0043836c,
225  0x7f30836c, 0x7f368c69, 0x7f3b7b66, 0x7f418463, 0x7f338176, 0x7f388a73, 0x7f3d7970, 0x7f43836c,
226  0x00147c93, 0x0019868f, 0x001f758c, 0x00247e89, 0x00167b9c, 0x001b8499, 0x00217396, 0x00267c93,
227  0x7f147c93, 0x7f19868f, 0x7f1f758c, 0x7f247e89, 0x7f167b9c, 0x7f1b8499, 0x7f217396, 0x7f267c93,
228  0x001f8f8c, 0x00249989, 0x002a8886, 0x002f9183, 0x00218e96, 0x00269792, 0x002c868f, 0x00318f8c,
229  0x7f1f8f8c, 0x7f249989, 0x7f2a8886, 0x7f2f9183, 0x7f218e96, 0x7f269792, 0x7f2c868f, 0x7f318f8c,
230  0x002a6c86, 0x002f7683, 0x00346580, 0x003a6e7d, 0x002c6b8f, 0x0031748c, 0x00366389, 0x003c6c86,
231  0x7f2a6c86, 0x7f2f7683, 0x7f346580, 0x7f3a6e7d, 0x7f2c6b8f, 0x7f31748c, 0x7f366389, 0x7f3c6c86,
232  0x00358080, 0x003a897c, 0x00407879, 0x00458176, 0x00377e89, 0x003c8786, 0x00427683, 0x00478080,
233  0x7f358080, 0x7f3a897c, 0x7f407879, 0x7f458176, 0x7f377e89, 0x7f3c8786, 0x7f427683, 0x7f478080,
234  0x00108080, 0x0012847e, 0x00157c7c, 0x0018807b, 0x00117f84, 0x00138383, 0x00167b81, 0x00198080,
235  0x00108080, 0x0012847e, 0x00157c7c, 0x0018807b, 0x00117f84, 0x00138383, 0x00167b81, 0x00198080,
236  0x0015897c, 0x00188e7b, 0x001a8579, 0x001d8a78, 0x00168881, 0x00198d7f, 0x001b847e, 0x001e897c,
237  0x0015897c, 0x00188e7b, 0x001a8579, 0x001d8a78, 0x00168881, 0x00198d7f, 0x001b847e, 0x001e897c,
238  0x001a7879, 0x001d7c78, 0x00207476, 0x00227875, 0x001b777e, 0x001e7c7c, 0x0021737b, 0x00237879,
239  0x001a7879, 0x001d7c78, 0x00207476, 0x00227875, 0x001b777e, 0x001e7c7c, 0x0021737b, 0x00237879,
240  0x00208176, 0x00238675, 0x00257d73, 0x00288271, 0x0021807b, 0x00248579, 0x00267c78, 0x00298176,
241  0x00208176, 0x00238675, 0x00257d73, 0x00288271, 0x0021807b, 0x00248579, 0x00267c78, 0x00298176,
242  0x00127e89, 0x00148387, 0x00177a86, 0x001a7f84, 0x00137d8e, 0x0015828c, 0x0018798a, 0x001b7e89,
243  0x00127e89, 0x00148387, 0x00177a86, 0x001a7f84, 0x00137d8e, 0x0015828c, 0x0018798a, 0x001b7e89,
244  0x00178786, 0x001a8c84, 0x001c8383, 0x001f8881, 0x0018878a, 0x001b8b89, 0x001e8387, 0x00208786,
245  0x00178786, 0x001a8c84, 0x001c8383, 0x001f8881, 0x0018878a, 0x001b8b89, 0x001e8387, 0x00208786,
246  0x001c7683, 0x001f7b81, 0x00227280, 0x0025777e, 0x001d7587, 0x00207a86, 0x00237184, 0x00267683,
247  0x001c7683, 0x001f7b81, 0x00227280, 0x0025777e, 0x001d7587, 0x00207a86, 0x00237184, 0x00267683,
248  0x00228080, 0x0025847e, 0x00277c7c, 0x002a807b, 0x00237f84, 0x00268383, 0x00287b81, 0x002b8080,
249  0x00228080, 0x0025847e, 0x00277c7c, 0x002a807b, 0x00237f84, 0x00268383, 0x00287b81, 0x002b8080
250 };
251 
252 static U8BIT default_2_bit_4_bit_map[4] =
253 {
254  0x00, 0x07, 0x08, 0x0f
255 };
256 
257 static U8BIT default_2_bit_8_bit_map[4] =
258 {
259  0x00, 0x77, 0x88, 0xff
260 };
261 
262 static U8BIT default_4_bit_8_bit_map[16] =
263 {
264  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
265 };
266 
267 #define TOP_FIELD_ONLY 1
268 #define BOTTOM_FIELD_ONLY 2
269 #define BOTH_FIELDS 0
270 
271 //---local function prototypes for this file-----------------------------------
272 // (internal functions declared static to make them local)
273 
274 static BOOLEAN ProcessObjectCodingMethod(U8BIT *data, S_OBJECT *object, U16BIT coding_method, U16BIT seg_len);
275 static BOOLEAN ProcessPixelDataSubBlock(U8BIT *data, S_OBJECT *object, U16BIT field_data_block_length, U8BIT field, S_PIXEL_SUB_DATA_BLOCK *decoded_data_block);
276 static BOOLEAN Process2BitPixelCodeString(U16BIT *run_length, U8BIT *colour,
277  U8BIT *my2_u8p, U16BIT *my2_u16, U8BIT *my2_u8);
278 static BOOLEAN Process4BitPixelCodeString(U16BIT *run_length, U8BIT *colour,
279  U8BIT *my4_u8p, U16BIT *my4_u16, U8BIT *my4_u8);
280 static BOOLEAN Process8BitPixelCodeString(U16BIT *run_length, U8BIT *colour,
281  U8BIT *data, U16BIT *byte_count);
282 static BOOLEAN Process2To4BitMapTable(U8BIT *data, U16BIT *processed_bits, U8BIT *decoded_data);
283 static BOOLEAN Process2To8BitMapTable(U8BIT *data, U16BIT *processed_bits, U8BIT *decoded_data);
284 static BOOLEAN Process4To8BitMapTable(U8BIT *data, U16BIT *processed_bits, U8BIT *decoded_data);
285 static BOOLEAN MakeClutEntry(S_CLUT *clut, U16BIT clut_id, U8BIT clut_entry_id, U8BIT clut_bit_entry_flags, U32BIT palette_entry);
286 #ifdef STB_REGION_PRINT_REQUIRED
287 void CheckRegionFootPrint(S_EPOCH_REGION *region, U16BIT region_width, U16BIT region_height,
288  U16BIT region_level_of_compatability, U16BIT region_depth, U16BIT clut_id);
289 #endif
290 static void DestroyObject(S_OBJECT **obj, BOOLEAN del_obj);
291 static void DeleteObjectList(S_OBJECT **obj);
292 static void DeleteClutList(S_CLUT **clut);
293 static void DeleteEpochRegionList(S_EPOCH_REGION **region_list);
294 static void DeletePageCompositionRegions(S_REGION **comp_pg);
295 static void STB_DSDumpPageState(const char *label);
296 //PDH
297 extern void dump_physical_regions(const char *label);
298 
299 static void Get2Bit_Initialise(const U8BIT *new_root, U8BIT **my2_u8p, U16BIT *my2_u16, U8BIT *my2_u8);
300 static void Get2Bit_SetAlignment(U16BIT *my2_u16, U8BIT *my2_u8);
301 static U16BIT Get2Bit_Offset(U16BIT my2_u16);
302 static U8BIT Get2Bit_Get(U8BIT *my2_u8p, U16BIT *my2_u16, U8BIT *my2_u8);
303 
304 static void Get4Bit_Initialise(const U8BIT *new_root, U8BIT **my4_u8p, U16BIT *my4_u16, U8BIT *my4_u8);
305 static void Get4Bit_SetAlignment(U16BIT *my4_u16, U8BIT *my4_u8);
306 static U16BIT Get4Bit_Offset(U16BIT my4_u16);
307 static U8BIT Get4Bit_Get(U8BIT *my4_u8p, U16BIT *my4_u16, U8BIT *my4_u8);
308 
309 //---local function definitions------------------------------------------------
310 
311 static void Get2Bit_Initialise(const U8BIT *new_root, U8BIT **my_root, U16BIT *my_offset, U8BIT *my_counter)
312 {
313  *my_root = (U8BIT *) new_root;
314  *my_offset = 0;
315  *my_counter = 0;
316 }
317 
318 static void Get2Bit_SetAlignment(U16BIT *my_offset, U8BIT *my_counter)
319 {
320  // If not byte aligned, move to start of next byte
321  if (*my_counter != 0)
322  {
323  *my_counter = 0;
324  *my_offset += 1;
325  }
326  // else - nothing to do
327 }
328 
329 //A bit overkill, but trying to make the point - how the 2bit code works ISN'T CLIENT'S BUSINESS!!
330 //OO approach - these are my internal variables, you shouldn't be aware of them, let alone
331 //using them!
332 static U16BIT Get2Bit_Offset(U16BIT my_offset)
333 {
334  return my_offset;
335 }
336 
337 static U8BIT Get2Bit_Get(U8BIT *my_root, U16BIT *my_offset, U8BIT *my_counter)
338 {
339  U8BIT retval = 0xff;
340 
341  switch (*my_counter)
342  {
343  case 0:
344  retval = (my_root[*my_offset]) >> 6;
345  break;
346  case 1:
347  retval = (((my_root[*my_offset]) >> 4) & 0x03);
348  break;
349  case 2:
350  retval = (((my_root[*my_offset]) >> 2) & 0x03);
351  break;
352  case 3:
353  retval = ((my_root[*my_offset]) & 0x03);
354  *my_offset += 1;
355  break;
356  default:
357  // Hell no! somebody's being playing with my state, or not initialised me
358  *my_offset = 0xffff;
359  break;
360  }
361 
362  *my_counter = (*my_counter + 1) % 4;
363 
364  return retval;
365 }
366 
367 static void Get4Bit_Initialise(const U8BIT *new_root, U8BIT **my_root, U16BIT *my_offset, U8BIT *my_counter)
368 {
369  *my_root = (U8BIT *) new_root;
370  *my_offset = 0;
371  *my_counter = 0;
372 }
373 
374 static void Get4Bit_SetAlignment(U16BIT *my_offset, U8BIT *my_counter)
375 {
376  // If not byte aligned, move to start of next byte
377  if (*my_counter != 0)
378  {
379  *my_counter = 0;
380  *my_offset += 1;
381  }
382  // else - nothing to do
383 }
384 
385 //A bit overkill, but trying to make the point - how the 2bit code works ISN'T CLIENT'S BUSINESS!!
386 //OO approach - these are my internal variables, you shouldn't be aware of them, let alone
387 //using them!
388 static U16BIT Get4Bit_Offset(U16BIT my_offset)
389 {
390  return my_offset;
391 }
392 
393 static U8BIT Get4Bit_Get(U8BIT *my_root, U16BIT *my_offset, U8BIT *my_counter)
394 {
395  U8BIT retval = 0xff;
396 
397  switch (*my_counter)
398  {
399  case 0:
400  retval = (my_root[*my_offset]) >> 4;
401 // STB_OBJECT_PRINT((" G<4> @%x --> %x", my_root+*my_offset, retval));
402 
403  break;
404  case 1:
405  retval = ((my_root[*my_offset]) & 0x0f);
406 // STB_OBJECT_PRINT((" g<4> @%x --> %x", my_root+*my_offset, retval));
407 
408  *my_offset += 1;
409  break;
410  default:
411  // Hell no! somebody's being playing with my state, or not initialised me
412  *my_offset = 0xffff;
413  break;
414  }
415 
416  *my_counter = (*my_counter + 1) % 2;
417 
418  return retval;
419 }
420 
437 static BOOLEAN ProcessObjectCodingMethod(U8BIT *data, S_OBJECT *object, U16BIT coding_method, U16BIT seg_len)
438 {
439  S_PIXEL_SUB_DATA_BLOCK top_field;
440  S_PIXEL_SUB_DATA_BLOCK bottom_field;
441  U16BIT top_field_data_block_length;
442  U16BIT bottom_field_data_block_length;
443  BOOLEAN retval;
444 
445  FUNCTION_START(ProcessObjectCodingMethod);
446 
447  ASSERT(data != NULL);
448  ASSERT(object != NULL);
449 
450  retval = TRUE;
451 
452  switch (coding_method)
453  {
454  case 0:
455  {
456  // coding of pixels
457  memset((void *)&top_field, 0x00, sizeof(S_PIXEL_SUB_DATA_BLOCK));
458  memset((void *)&bottom_field, 0x00, sizeof(S_PIXEL_SUB_DATA_BLOCK));
459 
460  top_field_data_block_length = (data[0] << 8) + data[1];
461  bottom_field_data_block_length = (data[2] << 8) + data[3];
462 
463  if ((top_field_data_block_length + bottom_field_data_block_length) < seg_len)
464  {
465  // position pointer to beginning of top field data
466  data += 4;
467 
468  if (object->bitmap != NULL)
469  {
470  STB_FreeMemory(object->bitmap);
471  object->bitmap = NULL;
472  }
473 
474  if (bottom_field_data_block_length == 0)
475  {
476  // no data for bottom field ETS 300 743 - 7.2.4
477  // top field data is valid for the bottom field
478  STB_OBJECT_PRINT(("bottom_field_data_block not present"));
479 
480  retval = ProcessPixelDataSubBlock(&data[0], object, top_field_data_block_length, BOTH_FIELDS, &top_field);
481  }
482  else
483  {
484  retval = ProcessPixelDataSubBlock(&data[0], object, top_field_data_block_length, TOP_FIELD_ONLY, &top_field);
485  retval &= ProcessPixelDataSubBlock(&data[top_field_data_block_length], object, bottom_field_data_block_length, BOTTOM_FIELD_ONLY, &bottom_field);
486  }
487  }
488  break;
489  }
490 
491  case 1:
492  {
493  // coding as a string of characters
494  object->num_chars = data[9];
495  object->character_code = (U8BIT *)STB_GetMemory((object->num_chars * 2));
496  if (object->character_code != NULL)
497  {
498  STB_OBJECT_PRINT(("object_coding_method string of %d characters", object->num_chars));
499  memcpy((void *)object->character_code, (void *)&data[10], (size_t)(object->num_chars * 2));
500  }
501  else
502  {
503  STB_OBJECT_PRINT(("object_coding_method char malloc fail"));
504  object->num_chars = 0;
505  retval = FALSE;
506  }
507  break;
508  }
509 
510  case 2:
511  case 3:
512  default:
513  {
514  STB_OBJECT_PRINT(("object_coding_method INVALID"));
515  retval = FALSE;
516  break;
517  }
518  }
519 
520  FUNCTION_FINISH(ProcessObjectCodingMethod);
521 
522  return(retval);
523 }
524 
543 static BOOLEAN ProcessPixelDataSubBlock(U8BIT *data,
544  S_OBJECT *object,
545  U16BIT field_data_block_length,
546  U8BIT field,
547  S_PIXEL_SUB_DATA_BLOCK *decoded_data_block)
548 {
549  U8BIT *decoded_data;
550 
551  U16BIT processed_length;
552  U16BIT decode_data_size;
553  U16BIT run_length;
554  U16BIT scanline;
555  U8BIT data_type;
556  U8BIT colour;
557  BOOLEAN end_of_string;
558  BOOLEAN terminate = FALSE;
559  BOOLEAN retval;
560 
561  //2 bit processing private state
562  U8BIT *my2_u8p;
563  U16BIT my2_u16;
564  U8BIT my2_u8;
565 
566  //4 bit processing private state
567  U8BIT *my4_u8p;
568  U16BIT my4_u16;
569  U8BIT my4_u8;
570 
571  static BOOLEAN error_flag;
572  static BOOLEAN error_line;
573 
574  FUNCTION_START(ProcessPixelDataSubBlock);
575 
576  ASSERT(data != NULL);
577  ASSERT(object != NULL);
578  ASSERT(decoded_data_block != NULL);
579 
580  USE_UNWANTED_PARAM(decoded_data_block);
581 
582  STB_OBJECT_PRINT((" Pixel-data_sub-block %d bytes", field_data_block_length));
583 
584  colour = 0;
585  run_length = 0;
586 
587  retval = FALSE;
588 
589  decode_data_size = 0;
590  processed_length = 0;
591  scanline = 0;
592 
593  decoded_data = temp_buffer;
594 
595  end_of_string = FALSE;
596 
597  switch (field)
598  {
599  case TOP_FIELD_ONLY:
600  {
601  scanline = 0;
602  error_flag = FALSE;
603  error_line = 0;
604  break;
605  }
606 
607  case BOTTOM_FIELD_ONLY:
608  {
609  scanline = 1;
610  break;
611  }
612 
613  case BOTH_FIELDS:
614  {
615  scanline = 0;
616  error_flag = FALSE;
617  error_line = 0;
618  break;
619  }
620 
621  default:
622  {
623  error_flag = FALSE;
624  error_line = 0;
625  terminate = TRUE;
626  break;
627  }
628  }
629 
630  while (!terminate && (processed_length < field_data_block_length))
631  {
632  data_type = data[processed_length];
633 
634  STB_OBJECT_PRINT((" data_type %02x @ %x / %d", data_type, data + processed_length, processed_length));
635 
636  //Move pointer to first byte after data_type field
637  processed_length++;
638 
639  switch (data_type)
640  {
641  case 0x0f:
642  {
643  // This accounts for the unnused bytes sync_byte, segment_byte, segement_length, data_type & page_id
644  processed_length += 6;
645  break;
646  }
647 
648  case 0x10:
649  {
650  //Initialise the 2 bit getter code to start at first byte of bufefr
651  Get2Bit_Initialise((const U8BIT *) (data + processed_length), &my2_u8p, &my2_u16, &my2_u8);
652 
653  do
654  {
655  end_of_string = Process2BitPixelCodeString(&run_length, &colour, my2_u8p, &my2_u16, &my2_u8 );
656 
657  if (((decode_data_size + run_length) > SCAN_LINE_WIDTH) ||
658  (processed_length + Get2Bit_Offset(my2_u16) > field_data_block_length))
659  {
660  break;
661  }
662  else
663  {
664  if (run_length != 0)
665  {
666  static U8BIT lastcolin = 0xff;
667 
668  if ((lastcolin != colour) && (run_length > 12))
669  {
670 // STB_PIXMAP_PRINT((" 10> in %02x -2to8-> %02x",
671 // colour, object->map_table_2_to_8_bit[colour]));
672  lastcolin = colour;
673  }
674 
675  if (object->map_table_2_to_8_bit != default_2_bit_8_bit_map)
676  {
677  /* Convert directly from 2 to 8-bit */
678  colour = object->map_table_2_to_8_bit[colour];
679  }
680  else
681  {
682  /* Convert to 8-bit using the 2-to-4 bit and 4-to-8 colour map because
683  * there may have been a change to the default mapping with the data */
684  colour = object->map_table_2_to_4_bit[colour];
685  colour = object->map_table_4_to_8_bit[colour];
686  }
687 
688  memset((void *)&decoded_data[decode_data_size], colour, run_length);
689  decode_data_size += run_length;
690  }
691  }
692  }
693  while (!end_of_string);
694 
695  //Recover byte alignment
696  Get2Bit_SetAlignment(&my2_u16, &my2_u8);
697 
698  //Update how many bytes have been processed
699  processed_length += Get2Bit_Offset(my2_u16);
700  break;
701  }
702 
703  case 0x11:
704  {
705  //Initialise the 4 bit getter code to start at first byte of bufefr
706  Get4Bit_Initialise((const U8BIT *) (data + processed_length), &my4_u8p, &my4_u16, &my4_u8);
707 
708  do
709  {
710  end_of_string = Process4BitPixelCodeString(&run_length, &colour, my4_u8p, &my4_u16, &my4_u8 );
711 
712  if (((decode_data_size + run_length) > SCAN_LINE_WIDTH) ||
713  (processed_length + Get4Bit_Offset(my4_u16) > field_data_block_length))
714  {
715  if ((decode_data_size + run_length) > SCAN_LINE_WIDTH)
716  {
717  STB_OBJECT_PRINT((" !! Decoded + run length > scan line width %d + %d > %d",
718  decode_data_size, run_length, SCAN_LINE_WIDTH));
719  }
720  if (processed_length + Get4Bit_Offset(my4_u16) > field_data_block_length)
721  {
722  STB_OBJECT_PRINT((" !! processed_length + Get4Bit_Offset(my4_u16) > field_data_block_length %d + %d > %d",
723  processed_length, Get4Bit_Offset(my4_u16), field_data_block_length));
724  }
725 
726  break;
727  }
728  else
729  {
730  if (run_length != 0)
731  {
732  static U8BIT lastcolin = 0xff;
733 
734  if ((lastcolin != colour) && (run_length > 12))
735  {
736 // STB_PIXMAP_PRINT((" 11> in %02x -4to8-> %02x",
737 // colour, object->map_table_4_to_8_bit[colour]));
738  lastcolin = colour;
739  }
740 
741  // Convert to 8bit colour
742  colour = object->map_table_4_to_8_bit[colour];
743  memset((void *)&decoded_data[decode_data_size], colour, run_length);
744  decode_data_size += run_length;
745  }
746  }
747  }
748  while (!end_of_string);
749 
750  //Recover byte alignment
751  Get4Bit_SetAlignment(&my4_u16, &my4_u8);
752 
753  //Update how many bytes have been processed
754  processed_length += Get4Bit_Offset(my4_u16);
755  break;
756  }
757 
758  case 0x12:
759  {
760  // 8 bit/pixel code string group
761  do
762  {
763  end_of_string = Process8BitPixelCodeString(&run_length, &colour, data, &processed_length);
764 
765  if (((decode_data_size + run_length) > SCAN_LINE_WIDTH) || (processed_length > field_data_block_length))
766  {
767  break;
768  }
769  else
770  {
771  if (run_length != 0)
772  {
773  static U8BIT lastcolin = 0xff;
774 
775  if ((lastcolin != colour) && (run_length > 12))
776  {
777 // STB_PIXMAP_PRINT((" 12> in %02x", colour));
778  lastcolin = colour;
779  }
780  memset((void *)&decoded_data[decode_data_size], colour, run_length);
781  decode_data_size += run_length;
782  }
783  }
784  }
785  while (!end_of_string);
786  break;
787  }
788 
789  case 0x20:
790  {
791  // 2 to 4 bit map table data
792  Process2To4BitMapTable(data, &processed_length, decoded_data);
793  if (object->map_table_2_to_4_bit != (U8BIT *)default_2_bit_4_bit_map)
794  {
795  STB_FreeMemory(object->map_table_2_to_4_bit);
796  }
797  object->map_table_2_to_4_bit = (U8BIT *)STB_GetMemory(4);
798  if (object->map_table_2_to_4_bit != NULL)
799  {
800  memcpy((void *)object->map_table_2_to_4_bit, (void *)decoded_data, (size_t)4);
801 
802  STB_OBJECT_PRINT((" 20> 2To4Map %02x %02x %02x %02x",
803  decoded_data[0], decoded_data[1], decoded_data[2], decoded_data[3]));
804  }
805  else
806  {
807  object->map_table_2_to_4_bit = default_2_bit_4_bit_map;
808  }
809  break;
810  }
811 
812  case 0x21:
813  {
814  // 2 to 8 bit map table data
815  Process2To8BitMapTable(data, &processed_length, decoded_data);
816 
817  if (object->map_table_2_to_8_bit != (U8BIT *)default_2_bit_8_bit_map)
818  {
819  STB_FreeMemory(object->map_table_2_to_8_bit);
820  }
821  object->map_table_2_to_8_bit = (U8BIT *)STB_GetMemory(4);
822  if (object->map_table_2_to_8_bit != NULL)
823  {
824  memcpy((void *)object->map_table_2_to_8_bit, (void *)decoded_data, (size_t)4);
825 
826  STB_OBJECT_PRINT((" 21> 2To8Map %02x %02x %02x %02x",
827  decoded_data[0], decoded_data[1], decoded_data[2], decoded_data[3]));
828  }
829  else
830  {
831  object->map_table_2_to_8_bit = default_2_bit_8_bit_map;
832  }
833  break;
834  }
835 
836  case 0x22:
837  {
838  // 4 to 8 bit map table data
839  Process4To8BitMapTable(data, &processed_length, decoded_data);
840 
841  if (object->map_table_4_to_8_bit != (U8BIT *)default_4_bit_8_bit_map)
842  {
843  STB_FreeMemory(object->map_table_4_to_8_bit);
844  }
845  object->map_table_4_to_8_bit = (U8BIT *)STB_GetMemory(16);
846  if (object->map_table_4_to_8_bit != NULL)
847  {
848  memcpy((void *)object->map_table_4_to_8_bit, (void *)decoded_data, (size_t)16);
849  STB_OBJECT_PRINT((" 22> 4To8Map %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
850  decoded_data[ 0], decoded_data[ 1], decoded_data[ 2], decoded_data[ 3],
851  decoded_data[ 4], decoded_data[ 5], decoded_data[ 6], decoded_data[ 7],
852  decoded_data[ 8], decoded_data[ 9], decoded_data[10], decoded_data[11],
853  decoded_data[12], decoded_data[13], decoded_data[14], decoded_data[15]));
854  }
855  else
856  {
857  object->map_table_4_to_8_bit = default_4_bit_8_bit_map;
858  }
859  break;
860  }
861 
862  case 0xf0:
863  {
864  STB_OBJECT_PRINT((" End of Line after %d pixels", decode_data_size));
865  if (decode_data_size != 0)
866  {
867  STB_DSRenderBitmapToRegion(subtitle_display_set.region_list, object, decoded_data,
868  scanline, decode_data_size, 1);
869  }
870 
871  if (field == BOTTOM_FIELD_ONLY)
872  {
873  // error correction bit
874  if (error_flag)
875  {
876  if ((scanline + 1) >= error_line)
877  {
878  scanline++;
879  if (decode_data_size != 0)
880  {
881  STB_DSRenderBitmapToRegion(subtitle_display_set.region_list, object, decoded_data,
882  scanline, decode_data_size, 1);
883  }
884  scanline++;
885  }
886  else
887  {
888  scanline += 2;
889  }
890  }
891  else
892  {
893  scanline += 2;
894  }
895  }
896  else
897  {
898  scanline++;
899  if (decode_data_size != 0)
900  {
901  STB_DSRenderBitmapToRegion(subtitle_display_set.region_list, object, decoded_data,
902  scanline, decode_data_size, 1);
903  }
904  scanline++;
905  }
906  decode_data_size = 0;
907  decoded_data = temp_buffer;
908  break;
909  }
910 
911  default:
912  {
913  STB_OBJECT_PRINT(("Unknown data_type 0x%02x", data_type));
914  terminate = TRUE;
915 
916  if (field == TOP_FIELD_ONLY)
917  {
918  error_flag = TRUE;
919  error_line = scanline;
920  STB_OBJECT_PRINT(("ERR Detected TOP %d", scanline));
921  }
922  else
923  {
924  STB_OBJECT_PRINT(("ERR Detected BOT %d", scanline));
925  }
926  break;
927  }
928  }
929 
930  if (terminate)
931  {
932  break;
933  }
934  }
935 
936  if (terminate)
937  {
938  STB_OBJECT_PRINT(("PIXPARSE TERMINATE @ %d", __LINE__));
939  if (object->map_table_2_to_4_bit != (U8BIT *)default_2_bit_4_bit_map)
940  {
941  STB_FreeMemory(object->map_table_2_to_4_bit);
942  object->map_table_2_to_4_bit = (U8BIT *)default_2_bit_4_bit_map;
943  }
944 
945  if (object->map_table_2_to_8_bit != (U8BIT *)default_2_bit_8_bit_map)
946  {
947  STB_FreeMemory(object->map_table_2_to_8_bit);
948  object->map_table_2_to_8_bit = (U8BIT *)default_2_bit_8_bit_map;
949  }
950 
951  if (object->map_table_4_to_8_bit != (U8BIT *)default_4_bit_8_bit_map)
952  {
953  STB_FreeMemory(object->map_table_4_to_8_bit);
954  object->map_table_4_to_8_bit = (U8BIT *)default_4_bit_8_bit_map;
955  }
956  }
957 
958  if (!terminate && (processed_length == field_data_block_length))
959  {
960  retval = TRUE;
961  }
962 
963  FUNCTION_FINISH(ProcessPixelDataSubBlock);
964 
965  return(retval);
966 }
967 
983 static BOOLEAN Process2BitPixelCodeString(U16BIT *run_length, U8BIT *colour,
984  U8BIT *my2_u8p, U16BIT *my2_u16, U8BIT *my2_u8)
985 {
986  U8BIT bit_pattern;
987  BOOLEAN end_of_2_bit_pixel_code_string = FALSE;
988 
989 
990  FUNCTION_START(Process2BitPixelCodeString);
991 
992  ASSERT(run_length != NULL);
993  ASSERT(colour != NULL);
994 
995  bit_pattern = Get2Bit_Get(my2_u8p, my2_u16, my2_u8);
996 
997  if (bit_pattern != 0x00)
998  {
999  // bit_pattern is a 2 bit pixel code
1000  *run_length = 1;
1001  *colour = bit_pattern;
1002  }
1003  else
1004  {
1005  // 2_bit_zero
1006  bit_pattern = Get2Bit_Get(my2_u8p, my2_u16, my2_u8);
1007  if (bit_pattern == 0x01)
1008  {
1009  // 1 pixel set to entry 00
1010  *run_length = 1;
1011  *colour = 0x00;
1012  }
1013  else
1014  {
1015  if (bit_pattern >= 0x2)
1016  {
1017  // run_length_3_10
1018  *run_length = ((bit_pattern & 1) << 2) + Get2Bit_Get(my2_u8p, my2_u16, my2_u8) + 3;
1019  *colour = Get2Bit_Get(my2_u8p, my2_u16, my2_u8);
1020  }
1021  else
1022  {
1023  if (bit_pattern == 0)
1024  {
1025  // This is switch 3
1026  bit_pattern = Get2Bit_Get(my2_u8p, my2_u16, my2_u8);
1027  if (bit_pattern == 0x1)
1028  {
1029  // 2 pixel set to entry 00
1030  *run_length = 2;
1031  *colour = 0;
1032  }
1033  else
1034  {
1035  if (bit_pattern == 0x2)
1036  {
1037  // run_length_12_27
1038  *run_length = (Get2Bit_Get(my2_u8p, my2_u16, my2_u8) << 2) +
1039  Get2Bit_Get(my2_u8p, my2_u16, my2_u8) + 12;
1040  *colour = Get2Bit_Get(my2_u8p, my2_u16, my2_u8);
1041  }
1042  else
1043  {
1044  if (bit_pattern == 0x3)
1045  {
1046  // run_length_29_284
1047  *run_length = (Get2Bit_Get(my2_u8p, my2_u16, my2_u8) << 6) +
1048  (Get2Bit_Get(my2_u8p, my2_u16, my2_u8) << 4) +
1049  (Get2Bit_Get(my2_u8p, my2_u16, my2_u8) << 2) +
1050  Get2Bit_Get(my2_u8p, my2_u16, my2_u8) + 29;
1051  *colour = Get2Bit_Get(my2_u8p, my2_u16, my2_u8);
1052  }
1053  else
1054  {
1055  // end of 2 bit pixel_code_string
1056  *run_length = 0;
1057  *colour = 0;
1058  end_of_2_bit_pixel_code_string = TRUE;
1059  }
1060  }
1061  }
1062  }
1063  }
1064  }
1065  }
1066 
1067  if (!end_of_2_bit_pixel_code_string)
1068  {
1069  STB_PIXMAP_PRINT((" <2> col %d x %3d", *colour, *run_length));
1070  }
1071  else
1072  {
1073  STB_PIXMAP_PRINT((" <2> End of String"));
1074  }
1075 
1076  FUNCTION_FINISH(Process2BitPixelCodeString);
1077 
1078  return(end_of_2_bit_pixel_code_string);
1079 }
1080 
1096 static BOOLEAN Process4BitPixelCodeString(U16BIT *run_length, U8BIT *colour,
1097  U8BIT *my4_u8p, U16BIT *my4_u16, U8BIT *my4_u8)
1098 {
1099  U8BIT bit_pattern;
1100  BOOLEAN end_of_4_bit_pixel_code_string = FALSE;
1101 
1102 
1103  FUNCTION_START(Process4BitPixelCodeString);
1104 
1105  ASSERT(run_length != NULL);
1106  ASSERT(colour != NULL);
1107 
1108  bit_pattern = (U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8);
1109 
1110  if (bit_pattern > 0x00)
1111  {
1112  // 4_bit_pixel_code
1113  *run_length = 1;
1114  *colour = bit_pattern;
1115  }
1116  else
1117  {
1118  bit_pattern = (U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8);
1119 
1120  if (bit_pattern == 0x00)
1121  {
1122  // end_of_string_signal
1123  *run_length = 0x00;
1124  *colour = 0;
1125  end_of_4_bit_pixel_code_string = TRUE;
1126  }
1127  else
1128  {
1129  if (bit_pattern <= 0x07)
1130  {
1131  // run_length_3_9
1132  *run_length = (bit_pattern + 2);
1133  *colour = 0;
1134  }
1135  else
1136  {
1137  if (bit_pattern <= 0x0b)
1138  {
1139  // run_length_4_7
1140  *run_length = ((bit_pattern & 0x03) + 4);
1141  *colour = (U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8);
1142  }
1143  else
1144  {
1145  if (bit_pattern <= 0x0d)
1146  {
1147  *run_length = ((bit_pattern & 0x03) + 1);
1148  *colour = 0;
1149  }
1150  else
1151  {
1152  if (bit_pattern == 0x0e)
1153  {
1154  // run_length_9_24
1155  *run_length = ((U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8) + 9);
1156  *colour = (U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8);
1157  }
1158  else
1159  {
1160  if (bit_pattern == 0x0f)
1161  {
1162  // run_length_25_280
1163  *run_length = (((U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8) << 4) & 0xf0);
1164  *run_length += (U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8);
1165  *run_length += 25;
1166  *colour = (U8BIT)Get4Bit_Get(my4_u8p, my4_u16, my4_u8);
1167  }
1168  }
1169  }
1170  }
1171  }
1172  }
1173  }
1174 
1175  if (!end_of_4_bit_pixel_code_string)
1176  {
1177  STB_PIXMAP_PRINT((" <4> col %2d x %3d", *colour, *run_length));
1178  }
1179  else
1180  {
1181  STB_PIXMAP_PRINT((" <4> End of String"));
1182  }
1183 
1184  FUNCTION_FINISH(Process4BitPixelCodeString);
1185 
1186  return(end_of_4_bit_pixel_code_string);
1187 }
1188 
1203 static BOOLEAN Process8BitPixelCodeString(U16BIT *run_length, U8BIT *colour, U8BIT *data, U16BIT *byte_count)
1204 {
1205  U8BIT bit_pattern;
1206  BOOLEAN end_of_8_bit_pixel_code_string;
1207 
1208 
1209  FUNCTION_START(Process8BitPixelCodeString);
1210 
1211  ASSERT(data != NULL);
1212  ASSERT(byte_count != NULL);
1213  ASSERT(run_length != NULL);
1214  ASSERT(colour != NULL);
1215 
1216  end_of_8_bit_pixel_code_string = FALSE;
1217 
1218  bit_pattern = data[(*byte_count)];
1219  *byte_count += 1;
1220  if (bit_pattern != 0x00)
1221  {
1222  // bit_pattern is an 8 bit pixel code
1223  *run_length = 1;
1224  *colour = bit_pattern;
1225  }
1226  else
1227  {
1228  // 8 bit zero
1229  bit_pattern = data[(*byte_count)];
1230  *byte_count += 1;
1231  if (bit_pattern == 0x00)
1232  {
1233  // end_of_string_signal
1234  *run_length = 0x00;
1235  *colour = 0;
1236  end_of_8_bit_pixel_code_string = TRUE;
1237  }
1238  else
1239  {
1240  if (bit_pattern <= 0x7f)
1241  {
1242  // run_length_1_127
1243  // n pixel set to entry 00
1244  *run_length = bit_pattern;
1245  *colour = 0;
1246  }
1247  else
1248  {
1249  // run_length_3_127
1250  *run_length = (bit_pattern & 0x7f);
1251  *colour = data[(*byte_count)];
1252  *byte_count += 1;
1253  }
1254  }
1255  }
1256 
1257  if (!end_of_8_bit_pixel_code_string)
1258  {
1259  STB_PIXMAP_PRINT((" <8> col %d x %3d", *colour, *run_length));
1260  }
1261  else
1262  {
1263  STB_PIXMAP_PRINT((" <8> End of String"));
1264  }
1265 
1266  FUNCTION_FINISH(Process8BitPixelCodeString);
1267 
1268  return(end_of_8_bit_pixel_code_string);
1269 }
1270 
1284 static BOOLEAN Process2To4BitMapTable(U8BIT *data, U16BIT *processed_bytes, U8BIT *decoded_data)
1285 {
1286  FUNCTION_START(Process2To4BitMapTable);
1287 
1288  ASSERT(data != NULL);
1289  ASSERT(processed_bytes != NULL);
1290  ASSERT(decoded_data != NULL);
1291 
1292  // 2_to_4_bit_map_table_data
1293  decoded_data[0] = (data[*processed_bytes] & 0xf0) >> 4;
1294  decoded_data[1] = (data[*processed_bytes] & 0x0f);
1295  decoded_data[2] = (data[(*processed_bytes) + 1] & 0xf0) >> 4;
1296  decoded_data[3] = (data[(*processed_bytes) + 1] & 0x0f);
1297  *processed_bytes += 2;
1298 
1299  FUNCTION_FINISH(Process2To4BitMapTable);
1300 
1301  return(TRUE);
1302 }
1303 
1319 static BOOLEAN Process2To8BitMapTable(U8BIT *data, U16BIT *processed_bytes, U8BIT *decoded_data)
1320 {
1321  FUNCTION_START(Process2To8BitMapTable);
1322 
1323  ASSERT(data != NULL);
1324  ASSERT(processed_bytes != NULL);
1325  ASSERT(decoded_data != NULL);
1326 
1327  // 2_to_8_bit_map_table_data
1328  decoded_data[0] = data[*processed_bytes];
1329  decoded_data[1] = data[(*processed_bytes) + 1];
1330  decoded_data[2] = data[(*processed_bytes) + 2];
1331  decoded_data[3] = data[(*processed_bytes) + 3];
1332  *processed_bytes += 4;
1333 
1334  FUNCTION_FINISH(Process2To8BitMapTable);
1335 
1336  return(TRUE);
1337 }
1338 
1353 static BOOLEAN Process4To8BitMapTable(U8BIT *data, U16BIT *processed_bytes, U8BIT *decoded_data)
1354 {
1355  FUNCTION_START(Process4To8BitMapTable);
1356 
1357  ASSERT(data != NULL);
1358  ASSERT(processed_bytes != NULL);
1359  ASSERT(decoded_data != NULL);
1360 
1361  memcpy(decoded_data, data + *processed_bytes, 16);
1362 
1363  *processed_bytes += 16;
1364 
1365  FUNCTION_FINISH(Process4To8BitMapTable);
1366 
1367  return(TRUE);
1368 }
1369 
1386 static BOOLEAN MakeClutEntry(S_CLUT *clut, U16BIT clut_id, U8BIT clut_entry_id, U8BIT clut_bit_entry_flags, U32BIT palette_entry)
1387 {
1388  BOOLEAN retval;
1389 
1390 
1391  FUNCTION_START(MakeClutEntry);
1392 
1393  ASSERT(clut != NULL);
1394 
1395  USE_UNWANTED_PARAM(clut_id);
1396 
1397  retval = TRUE;
1398 
1399  if (clut_bit_entry_flags & 0x4)
1400  {
1401  if (clut_entry_id < 4)
1402  {
1403  if (clut->default_2_bit)
1404  {
1405  clut->clut_2_bit = (U32BIT *)STB_GetMemory(4 * 4);
1406  if (clut->clut_2_bit == NULL)
1407  {
1408  clut->clut_2_bit = default_2_bit_clut;
1409  retval = FALSE;
1410  }
1411  else
1412  {
1413  memcpy((void *)clut->clut_2_bit, (void *)default_2_bit_clut, (size_t)(4 * 4));
1414  clut->default_2_bit = FALSE;
1415  clut->clut_2_bit[clut_entry_id] = palette_entry;
1416  }
1417  }
1418  else
1419  {
1420  clut->clut_2_bit[clut_entry_id] = palette_entry;
1421  }
1422  }
1423  }
1424 
1425  if (clut_bit_entry_flags & 0x2)
1426  {
1427  if (clut_entry_id < 16)
1428  {
1429  if (clut->default_4_bit)
1430  {
1431  clut->clut_4_bit = (U32BIT *)STB_GetMemory(16 * 4);
1432  if (clut->clut_4_bit == NULL)
1433  {
1434  clut->clut_4_bit = default_4_bit_clut;
1435  retval = FALSE;
1436  }
1437  else
1438  {
1439  memcpy((void *)clut->clut_4_bit, (void *)default_4_bit_clut, (size_t)(16 * 4));
1440  clut->default_4_bit = FALSE;
1441  clut->clut_4_bit[clut_entry_id] = palette_entry;
1442  }
1443  }
1444  else
1445  {
1446  clut->clut_4_bit[clut_entry_id] = palette_entry;
1447  }
1448  }
1449  }
1450 
1451  if (clut_bit_entry_flags & 0x1)
1452  {
1453  if (clut->default_8_bit)
1454  {
1455  clut->clut_8_bit = (U32BIT *)STB_GetMemory(256 * 4);
1456  if (clut->clut_8_bit == NULL)
1457  {
1458  clut->clut_8_bit = default_8_bit_clut;
1459  retval = FALSE;
1460  }
1461  else
1462  {
1463  memcpy((void *)clut->clut_8_bit, (void *)default_8_bit_clut, (size_t)(256 * 4));
1464  clut->default_8_bit = FALSE;
1465  clut->clut_8_bit[clut_entry_id] = palette_entry;
1466  }
1467  }
1468  else
1469  {
1470  clut->clut_8_bit[clut_entry_id] = palette_entry;
1471  }
1472  }
1473 
1474  FUNCTION_FINISH(MakeClutEntry);
1475 
1476  return(retval);
1477 }
1478 
1479 #ifdef STB_REGION_PRINT_REQUIRED
1480 
1498 void CheckRegionFootPrint(S_EPOCH_REGION *region, U16BIT region_width, U16BIT region_height,
1499  U16BIT region_level_of_compatability, U16BIT region_depth, U16BIT clut_id)
1500 {
1501  FUNCTION_START(CheckRegionFootPrint);
1502 
1503  // The following fields cannot change once set ETS 300 743 5.1.4
1504  if (region->region_width != region_width)
1505  {
1506  STB_REGION_PRINT(("Attempt to redefine width"));
1507  }
1508  if (region->region_height != region_height)
1509  {
1510  STB_REGION_PRINT(("Attempt to redefine height"));
1511  }
1512  if (region->region_level_of_compatibilty != region_level_of_compatability)
1513  {
1514  STB_REGION_PRINT(("Attempt to redefine compatibilty"));
1515  }
1516  if (region->region_colour_depth != region_depth)
1517  {
1518  STB_REGION_PRINT(("Attempt to redefine depth"));
1519  }
1520  if (region->region_clut_id != clut_id)
1521  {
1522  STB_REGION_PRINT(("Attempt to redefine clut id"));
1523  }
1524 
1525  FUNCTION_FINISH(CheckRegionFootPrint);
1526 }
1527 
1528 #endif
1529 
1543 static void DestroyObject(S_OBJECT **obj, BOOLEAN del_obj)
1544 {
1545  FUNCTION_START(DestroyObject);
1546 
1547  ASSERT(*obj != NULL);
1548 
1549  if ((*obj)->bitmap)
1550  {
1551  STB_FreeMemory((*obj)->bitmap);
1552  }
1553  if ((*obj)->character_code)
1554  {
1555  STB_FreeMemory((*obj)->character_code);
1556  }
1557  if ((*obj)->map_table_2_to_4_bit != (U8BIT *)default_2_bit_4_bit_map)
1558  {
1559  STB_FreeMemory((*obj)->map_table_2_to_4_bit);
1560  }
1561  if ((*obj)->map_table_2_to_8_bit != (U8BIT *)default_2_bit_8_bit_map)
1562  {
1563  STB_FreeMemory((*obj)->map_table_2_to_8_bit);
1564  }
1565  if ((*obj)->map_table_4_to_8_bit != (U8BIT *)default_4_bit_8_bit_map)
1566  {
1567  STB_FreeMemory((*obj)->map_table_4_to_8_bit);
1568  }
1569 
1570  if (del_obj)
1571  {
1572  STB_FreeMemory(*obj);
1573  *obj = NULL;
1574  }
1575  else
1576  {
1577  memset((void *)*obj, 0x00, sizeof(S_OBJECT));
1578  (*obj)->map_table_2_to_4_bit = (U8BIT *)default_2_bit_4_bit_map;
1579  (*obj)->map_table_2_to_8_bit = (U8BIT *)default_2_bit_8_bit_map;
1580  (*obj)->map_table_4_to_8_bit = (U8BIT *)default_4_bit_8_bit_map;
1581  }
1582 
1583  FUNCTION_FINISH(DestroyObject);
1584 }
1585 
1597 static void DeleteObjectList(S_OBJECT **obj)
1598 {
1599  S_OBJECT *ptr_1;
1600  S_OBJECT *ptr_2;
1601 
1602 
1603  FUNCTION_START(DeleteObjectList);
1604 
1605  ptr_1 = *obj;
1606 
1607  while (ptr_1 != NULL)
1608  {
1609  ptr_2 = ptr_1->next;
1610  DestroyObject(&ptr_1, TRUE);
1611  ptr_1 = ptr_2;
1612  }
1613 
1614  *obj = NULL;
1615 
1616  FUNCTION_FINISH(DeleteObjectList);
1617 }
1618 
1630 static void DeleteClutList(S_CLUT **clut)
1631 {
1632  S_CLUT *ptr_1;
1633  S_CLUT *ptr_2;
1634 
1635 
1636  FUNCTION_START(DeleteClutList);
1637 
1638  ptr_1 = *clut;
1639 
1640  while (ptr_1 != NULL)
1641  {
1642  if (!ptr_1->default_2_bit)
1643  {
1644  STB_FreeMemory(ptr_1->clut_2_bit);
1645  }
1646 
1647  if (!ptr_1->default_4_bit)
1648  {
1649  STB_FreeMemory(ptr_1->clut_4_bit);
1650  }
1651 
1652  if (!ptr_1->default_8_bit)
1653  {
1654  STB_FreeMemory(ptr_1->clut_8_bit);
1655  }
1656 
1657  ptr_2 = ptr_1->next;
1658  STB_FreeMemory(ptr_1);
1659  ptr_1 = ptr_2;
1660  }
1661 
1662  *clut = NULL;
1663 
1664  FUNCTION_FINISH(DeleteClutList);
1665 }
1666 
1678 static void DeleteEpochRegionList(S_EPOCH_REGION **region_list)
1679 {
1680  S_EPOCH_REGION *ptr_r1;
1681  S_EPOCH_REGION *ptr_r2;
1682  S_REGION_OBJECT *ptr_o1;
1683  S_REGION_OBJECT *ptr_o2;
1684 
1685 
1686  FUNCTION_START(DeleteEpochRegionList);
1687 
1688  ptr_r1 = *region_list;
1689 
1690  while (ptr_r1 != NULL)
1691  {
1692  ptr_o1 = ptr_r1->region_object_list;
1693  while (ptr_o1 != NULL)
1694  {
1695  // Delete all S_REGION_OBJECT's from each S_EPOCH_REGION
1696  ptr_o2 = ptr_o1->next;
1697  STB_FreeMemory(ptr_o1);
1698  ptr_o1 = ptr_o2;
1699  }
1700 
1701  // Delete S_EPOCH_REGION
1702  ptr_r2 = ptr_r1->next;
1703  STB_FreeMemory(ptr_r1);
1704  ptr_r1 = ptr_r2;
1705  }
1706 
1707  *region_list = NULL;
1708 
1709  FUNCTION_FINISH(DeleteEpochRegionList);
1710 }
1711 
1724 static void DeletePageCompositionRegions(S_REGION **comp_pg)
1725 {
1726  S_REGION *ptr_1;
1727  S_REGION *ptr_2;
1728 
1729 
1730  FUNCTION_START(DeletePageCompositionRegions);
1731 
1732  ptr_1 = *comp_pg;
1733 
1734  while (ptr_1 != NULL)
1735  {
1736  ptr_2 = ptr_1->next;
1737  STB_FreeMemory(ptr_1);
1738  ptr_1 = ptr_2;
1739  }
1740 
1741  *comp_pg = NULL;
1742 
1743  FUNCTION_FINISH(DeletePageCompositionRegions);
1744 }
1745 
1746 //---global function definitions-----------------------------------------------
1747 
1761 {
1763 
1764  temp_buffer = (U8BIT *)STB_GetMemory(TEMP_BUFFER_SIZE);
1765  if (temp_buffer == NULL)
1766  {
1767  STB_SUB_DRIVER_PRINT(("Initialation failure!!!"));
1768  }
1769  else
1770  {
1771  STB_SUB_DRIVER_PRINT(("Initialised OK"));
1772 
1773  memset((void *)&subtitle_display_set, 0x00, sizeof(S_DISPLAY_SET));
1774  memset((void *)&page_1, 0x00, sizeof(S_PAGE_COMPOSITION));
1775  memset((void *)&page_2, 0x00, sizeof(S_PAGE_COMPOSITION));
1776 
1777  /* Initialise the DDS version to an invalid value to ensure the first DDS segment found is used */
1778  page_1.dds_present = FALSE;
1779  page_1.dds_version = 0xff;
1780  page_1.display_width = 719;
1781  page_1.display_height = 575;
1782  page_1.display_window = FALSE;
1783  page_1.page_version_number = 0xff;
1784 
1785  page_2.dds_present = FALSE;
1786  page_2.dds_version = 0xff;
1787  page_2.display_width = 719;
1788  page_2.display_height = 575;
1789  page_2.display_window = FALSE;
1790  page_2.page_version_number = 0xff;
1791 
1792  subtitle_display_set.page_display_buffer = &page_1;
1793  subtitle_display_set.page_composition_buffer = &page_2;
1794  }
1795 
1796  FUNCTION_FINISH(STB_DSInitialiseDVBSubtitlesProcessing);
1797 
1798  return(FALSE);
1799 }
1800 
1814 S_CLUT* STB_DSGetClut(S_CLUT *clut_list, U16BIT clut_id)
1815 {
1816  S_CLUT *clut;
1817 
1818  FUNCTION_START(STB_DSGetClut);
1819 
1820  clut = clut_list;
1821 
1822  // search clut list to find clut ID
1823  while (clut != NULL)
1824  {
1825  if (clut->clut_id == clut_id)
1826  {
1827  break;
1828  }
1829  clut = clut->next;
1830  }
1831 
1832  if (clut == NULL)
1833  {
1834  clut = (S_CLUT *)STB_GetMemory(sizeof(S_CLUT));
1835  if (clut != NULL)
1836  {
1837  STB_CDS_PRINT((" +c%d", clut_id));
1838 
1839  clut->clut_id = clut_id;
1840  clut->next = NULL;
1841  clut->clut_2_bit = default_2_bit_clut;
1842  clut->clut_4_bit = default_4_bit_clut;
1843  clut->clut_8_bit = default_8_bit_clut;
1844  clut->default_2_bit = TRUE;
1845  clut->default_4_bit = TRUE;
1846  clut->default_8_bit = TRUE;
1847  clut->clut_version_number = 0xff;
1848 
1849  // Insert at head of link list of cluts
1850  clut->next = subtitle_display_set.clut_list;
1851  subtitle_display_set.clut_list = clut;
1852  }
1853  else
1854  {
1855  STB_CDS_PRINT(("CLUT %d malloc fail", clut_id));
1856  }
1857  }
1858  // else - found an existing CLUT
1859 
1860  FUNCTION_FINISH(STB_DSGetClut);
1861 
1862  return(clut);
1863 }
1864 
1877 BOOLEAN STB_DSSegmentDDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
1878 {
1879  U16BIT segment_length;
1880  U16BIT processed_length;
1881  U8BIT dds_version;
1882  BOOLEAN display_window;
1883  U16BIT display_width, display_height;
1884  BOOLEAN retval;
1885 
1886  FUNCTION_START(STB_DSSegmentDDS);
1887 
1888  ASSERT(data != NULL);
1889 
1890  // data[0] - sync_byte
1891  // data[1] - segment_type
1892  // data[2] - page_id MS8Bits
1893  // data[3] - page_id LS8Bits
1894 
1895  segment_length = (data[4] << 8) + data[5];
1896 
1897  STB_SEGMENT_PRINT(("DDS: segment_length=%u", segment_length));
1898 
1899  if ((processed_bytes + segment_length + 5) > pes_len)
1900  {
1901  STB_SEGMENT_PRINT(("\n\nABORT DDS processing - pes too short"));
1902  return(FALSE);
1903  }
1904 
1905  dds_version = (data[6] & 0xf0) >> 4;
1906 
1907  display_window = ((data[6] & 0x08) != 0);
1908  display_width = (data[7] << 8) + data[8];
1909  display_height = (data[9] << 8) + data[10];
1910 
1911  processed_length = 10;
1912 
1913  STB_SEGMENT_PRINT(("DDS: display %ux%u", display_width, display_height));
1914 
1915  if (display_window)
1916  {
1917  processed_length += 8;
1918  }
1919 
1920  if (subtitle_display_set.page_composition_buffer != NULL)
1921  {
1922  subtitle_display_set.page_composition_buffer->dds_present = TRUE;
1923 
1924  if (dds_version != subtitle_display_set.page_composition_buffer->dds_version)
1925  {
1926  subtitle_display_set.page_composition_buffer->dds_version = dds_version;
1927 
1928  subtitle_display_set.page_composition_buffer->display_width = display_width;
1929  subtitle_display_set.page_composition_buffer->display_height = display_height;
1930  subtitle_display_set.page_composition_buffer->display_window = display_window;
1931 
1932  if (display_window)
1933  {
1934  subtitle_display_set.page_composition_buffer->window_x = (data[11] << 8) + data[12];
1935  subtitle_display_set.page_composition_buffer->window_width = ((data[13] << 8) + data[14]) -
1936  subtitle_display_set.page_composition_buffer->window_x + 1;
1937  subtitle_display_set.page_composition_buffer->window_y = (data[15] << 8) + data[16];
1938  subtitle_display_set.page_composition_buffer->window_height = ((data[17] << 8) + data[18]) -
1939  subtitle_display_set.page_composition_buffer->window_y + 1;
1940 
1941  STB_SEGMENT_PRINT(("DDS: window %u,%u : %ux%u",
1942  subtitle_display_set.page_composition_buffer->window_x,
1943  subtitle_display_set.page_composition_buffer->window_y,
1944  subtitle_display_set.page_composition_buffer->window_width,
1945  subtitle_display_set.page_composition_buffer->window_height));
1946  }
1947  }
1948  }
1949 
1950  // Return OK only if we processed the number of bytes we were given
1951  retval = (processed_length == (segment_length + 5));
1952 
1953  FUNCTION_FINISH(STB_DSSegmentDDS);
1954 
1955  return(retval);
1956 }
1957 
1972 BOOLEAN STB_DSSegmentPCS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes, BOOLEAN external_force_acquisition)
1973 {
1974  S_REGION *region;
1975  U16BIT segment_length;
1976  U16BIT processed_length;
1977 
1978  U8BIT page_time_out;
1979  U8BIT page_version_number;
1980  U8BIT page_state;
1981  BOOLEAN retval = FALSE;
1982 
1983  static BOOLEAN force_acquisition = TRUE;
1984 
1985  FUNCTION_START(STB_DSSegmentPCS);
1986 
1987  ASSERT(data != NULL);
1988 
1989  // data[0] - sync_byte
1990  // data[1] - segment_type
1991  // data[2] - page_id MS8Bits
1992  // data[3] - page_id LS8Bits
1993 
1994  //force_update if we wanted to last time OR we've been told to this time
1995  force_acquisition |= external_force_acquisition;
1996  // Remember if we've been told to force at any point - in case of errors,
1997  // we can reset force_acquisition
1998  external_force_acquisition = force_acquisition;
1999 
2000  segment_length = (data[4] << 8) + data[5];
2001 
2002  if ((processed_bytes + segment_length + 6) > pes_len)
2003  {
2004  STB_SEGMENT_PRINT(("\n\nABORT PCS processing - pes too short"));
2005 
2006  return(FALSE);
2007  }
2008 
2009  page_time_out = data[6];
2010  page_version_number = (data[7] & 0xf0) >> 4;
2011  page_state = (data[7] & 0x0c) >> 2;
2012 
2013  processed_length = 2;
2014 
2015  // page_state '11' reserved for future use.
2016  if ((subtitle_display_set.page_composition_buffer != NULL) && (page_state != RES_PAGE_STATE))
2017  {
2018  /* Check whether a DDS has been seen */
2019  if (!subtitle_display_set.page_composition_buffer->dds_present)
2020  {
2021  /* Set default display settings */
2022  subtitle_display_set.page_composition_buffer->display_width = 719;
2023  subtitle_display_set.page_composition_buffer->display_height = 575;
2024  subtitle_display_set.page_composition_buffer->display_window = FALSE;
2025  }
2026 
2027  // Check PCS describes a new version of Page
2028  if ((subtitle_display_set.page_display_buffer->page_version_number != page_version_number) || force_acquisition)
2029  {
2030  STB_SEGMENT_PRINT(("\n\nPCS <state %d> Ver v%d ( Comp v%d / Disp v%d ) timeout %d",
2031  page_state, page_version_number,
2032  subtitle_display_set.page_composition_buffer->page_version_number,
2033  subtitle_display_set.page_display_buffer->page_version_number,
2034  page_time_out));
2035 
2036  // Delete the existing page composition buffer of region lists
2038 
2039  if ((page_state == MODE_CHANGE) ||
2040  ((page_state == ACQUISITION_POINT) && force_acquisition))
2041  {
2042  page_state = MODE_CHANGE;
2043  //Okay we're forcing!
2044  force_acquisition = FALSE;
2045  }
2046 
2047  switch (page_state)
2048  {
2049  case NORMAL_CASE:
2050  {
2051  STB_SEGMENT_PRINT(("pcs NORMAL_CASE"));
2052  // '00' normal case The page composition segment is followed by an
2053  // incomplete region set.
2054  break;
2055  }
2056 
2057  case ACQUISITION_POINT:
2058  {
2059  // NB we could have started with an acquisition point, but have been forced to
2060  // treat this as a mode change
2061  STB_SEGMENT_PRINT(("pcs ACQUISITION_POINT - treating as mode change"));
2062  page_state = MODE_CHANGE;
2063  // '01' acquisition point The page composition segment is followed
2064  // by a complete region set describing the current memory plan.
2065  break;
2066  }
2067 
2068  case MODE_CHANGE:
2069  {
2070  if (external_force_acquisition)
2071  {
2072  STB_SEGMENT_PRINT(("pcs FORCED Reset display region list + Obj + CLUT ++ EPOCH"));
2073  }
2074  else
2075  {
2076  STB_SEGMENT_PRINT(("pcs Reset display region list + Obj + CLUT ++ EPOCH"));
2077  }
2078  // '10' mode change The page composition segment is followed by regions
2079  // describing a new memory plan.
2080 
2081  // Forget outdated list of Regions / Objects / Cluts from previous Epoch
2082  DeleteEpochRegionList(&subtitle_display_set.region_list);
2083  DeleteObjectList(&subtitle_display_set.object_list);
2084  DeleteClutList(&subtitle_display_set.clut_list);
2085  // Clear out any OSD resources that we accumulated in previous Epoch
2087  break;
2088  }
2089  }
2090 
2091  // Make the composition buffer ours
2092  subtitle_display_set.page_composition_buffer->page_time_out = page_time_out;
2093  subtitle_display_set.page_composition_buffer->page_version_number = page_version_number;
2094  subtitle_display_set.page_composition_buffer->page_state = page_state;
2095 
2096  // ETS 300 743 7.2.1
2097  // page_time_out: The period, expressed in seconds, after which the page is no longer
2098  // valid and consequently shall be erased from the screen, should it not have been
2099  // redefined before that. The time-out period starts at the first reception of the
2100  // page_composition_segment. If the same segment with the same version number is received
2101  // again the time-out counter shall not be reloaded. The purpose of the time-out period is
2102  // to avoid that a page remains on the screen "for ever" if the IRD happens to have missed
2103  // the page's redefinition or deletion. The time-out period does not need to be counted
2104  // very accurately by the IRD: a reaction inaccuracy of -0/+5 seconds is good enough.
2105  subtitle_display_set.page_composition_buffer->timeout_start = STB_OSGetClockMilliseconds();
2106 
2107  // Move data pointer to 1st region
2108  data += 8;
2109 
2110  // Build list of regions to be displayed in this page
2111  while (processed_length < segment_length)
2112  {
2113  region = (S_REGION *)STB_GetMemory(sizeof(S_REGION));
2114 
2115  if (region != NULL)
2116  {
2117  region->region_id = data[0];
2118  region->region_horizontal_address = (data[2] << 8) + data[3];
2119  region->region_vertical_address = (data[4] << 8) + data[5];
2120 
2121  if (subtitle_display_set.page_composition_buffer->display_window)
2122  {
2123  region->region_horizontal_address += subtitle_display_set.page_composition_buffer->window_x;
2124  region->region_vertical_address += subtitle_display_set.page_composition_buffer->window_y;
2125 
2126  if (region->region_horizontal_address > subtitle_display_set.page_composition_buffer->display_width)
2127  {
2128  region->region_horizontal_address = subtitle_display_set.page_composition_buffer->display_width;
2129  }
2130 
2131  if (region->region_vertical_address > subtitle_display_set.page_composition_buffer->display_height)
2132  {
2133  region->region_vertical_address = subtitle_display_set.page_composition_buffer->display_height;
2134  }
2135  }
2136  else
2137  {
2138  if (region->region_horizontal_address > subtitle_display_set.page_composition_buffer->display_width)
2139  {
2140  region->region_horizontal_address = subtitle_display_set.page_composition_buffer->display_width;
2141  }
2142 
2143  if (region->region_vertical_address > subtitle_display_set.page_composition_buffer->display_height)
2144  {
2145  region->region_vertical_address = subtitle_display_set.page_composition_buffer->display_height;
2146  }
2147  }
2148 
2149  // Insert at head of link list of composition regions
2150  region->next = subtitle_display_set.page_composition_buffer->region_list;
2151  subtitle_display_set.page_composition_buffer->region_list = region;
2152 
2153  STB_SEGMENT_PRINT((" +r%d @ (%3d, %3d)",
2154  region->region_id,
2155  region->region_horizontal_address, region->region_vertical_address));
2156  }
2157 
2158  // Move data pointer to next region
2159  data += 6;
2160  processed_length += 6;
2161  }
2162 
2163  retval = TRUE;
2164  }
2165  else
2166  {
2167  STB_SEGMENT_PRINT(("\n\nPCS <state %d> Ver v%d ( Comp v%d / Disp v%d ) -- Unchanged version - IGNORING (force_acquisition=%s)",
2168  page_state, page_version_number,
2169  subtitle_display_set.page_composition_buffer->page_version_number,
2170  subtitle_display_set.page_display_buffer->page_version_number,
2171  force_acquisition ? "TRUE" : "FALSE"));
2172 
2173  subtitle_display_set.page_composition_buffer->page_state = page_state;
2174  retval = TRUE;
2175  }
2176 
2177  // Error if we already had an error OR we didn't use all of the expected bytes
2178  retval &= (processed_length == segment_length);
2179  }
2180  else
2181  {
2182  // We have no composition buffer OR received page's state is invalid
2183  STB_SEGMENT_PRINT(("\n\nPCS -- Not processed, illegal state %s@%d", __FILE__, __LINE__));
2184  retval = FALSE;
2185  }
2186 
2187  FUNCTION_FINISH(STB_DSSegmentPCS);
2188 
2189  return(retval);
2190 }
2191 
2204 BOOLEAN STB_DSSegmentRCS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
2205 {
2206  S_REGION_OBJECT *object;
2207  S_REGION_OBJECT *existing_region_object;
2208  S_EPOCH_REGION *region;
2209  U16BIT segment_length;
2210  U16BIT processed_length;
2211  U16BIT region_id;
2212  U8BIT region_version_number;
2213  U16BIT object_id;
2214  U16BIT object_type;
2215 
2216  BOOLEAN retval;
2217 
2218  FUNCTION_START(STB_DSSegmentRCS);
2219 
2220  ASSERT(data != NULL);
2221 
2222  // data[0] - sync_byte
2223  // data[1] - segment_type
2224  // data[2] - page_id MS8Bits
2225  // data[3] - page_id LS8Bits
2226 
2227  segment_length = (data[4] << 8) + data[5];
2228 
2229  if ((processed_bytes + segment_length + 6) > pes_len)
2230  {
2231  STB_SEGMENT_PRINT(("\n\nABORT RCS processing - pes too short"));
2232 
2233  return(FALSE);
2234  }
2235 
2236  region_id = data[6];
2237  region_version_number = (data[7] & 0xf0) >> 4;
2238 
2239  processed_length = 10;
2240 
2241  // search EPOCH's master region list to find region ID
2242  region = subtitle_display_set.region_list;
2243 
2244  while (region != NULL)
2245  {
2246  if (region->region_id == region_id)
2247  {
2248  break;
2249  }
2250  region = region->next;
2251  }
2252 
2253  // NB if we are at Epoch change then we should NEVER find an existing region
2254  if (region != NULL)
2255  {
2256  // Region with this ID was mentioned at last mode_change / Epoch
2257  if (region->region_version_number != region_version_number)
2258  {
2259  // Existing region in epoch's region list, NEW version => reset the object list
2260  S_REGION_OBJECT *object_1;
2261  S_REGION_OBJECT *object_2;
2262 
2263  STB_SEGMENT_PRINT(("RCS Region r%d (existing version %d) new ver %d c%d %s 8_%d 4_%d 2_%d",
2264  region_id, region->region_version_number, region_version_number,
2265  data[13],
2266  ((data[7] & 0x08) >> 3) ? "FILL" : "no fill",
2267  data[14], (data[15] & 0xf0) >> 4, (data[15] & 0x0c) >> 2));
2268 
2269  object_1 = region->region_object_list;
2270  while (object_1 != NULL)
2271  {
2272  // Delete all S_REGION_OBJECT's from each S_EPOCH_REGION
2273  object_2 = object_1->next;
2274  STB_FreeMemory(object_1);
2275  object_1 = object_2;
2276  }
2277  region->region_object_list = NULL;
2278  }
2279  else
2280  {
2281  // Existing region in epoch's region list, NOT NEW version
2282  STB_SEGMENT_PRINT(("RCS Region r%d version number %d unchanged -- IGNORING",
2283  region_id, region->region_version_number, region_version_number));
2284  // No version change => ignore this RCS. Set region = NULL so no further processing
2285  region = NULL;
2286  }
2287  }
2288  // else - no existing Region found, can only create one if we are in MODE_CHANGE state
2289  // (which might have been caused by Acquisition Point being forced to mode change - see PCS)
2290  else if (subtitle_display_set.page_composition_buffer->page_state == MODE_CHANGE)
2291  {
2292  // New region - unknown in master region list
2293  // But we have a suitable page_state => we should create a new region
2294  region = (S_EPOCH_REGION *)STB_GetMemory(sizeof(S_EPOCH_REGION));
2295 
2296  if (region != NULL)
2297  {
2298  // Initialise ourselves
2299  region->region_id = region_id;
2300  region->region_version_number = region_version_number;
2301  region->region_object_list = NULL;
2302 
2303  // The following fields cannot change once set ETS 300 743 5.1.4
2304  region->region_width = (data[8] << 8) + data[9];
2305 
2306  region->region_height = (data[10] << 8) + data[11];
2307  region->region_level_of_compatibilty = (data[12] & 0xe0) >> 5;
2308  region->region_level_of_compatibilty = 1 << region->region_level_of_compatibilty;
2309  region->region_clut_id = data[13];
2310  region->region_colour_depth = (data[12] & 0x1c) >> 2;
2311  region->region_colour_depth = 1 << region->region_colour_depth;
2312 
2313  // These parts of the region can change
2314  region->region_fill_flag = (data[7] & 0x08) >> 3;
2315  region->region_8_bit_pixel_code = data[14];
2316  region->region_4_bit_pixel_code = (data[15] & 0xf0) >> 4;
2317  region->region_2_bit_pixel_code = (data[15] & 0x0c) >> 2;
2318 
2319  STB_SEGMENT_PRINT(("RCS r%d NEW ver %d (%dx%d(x%d)) compat %x c%d %s 8_%d 4_%d 2_%d",
2320  region->region_id,
2321  region->region_version_number,
2322  region->region_width,
2323  region->region_height,
2324  region->region_colour_depth,
2325  region->region_level_of_compatibilty,
2326  data[13],
2327  ((data[7] & 0x08) >> 3) ? "FILL" : "no fill",
2328  data[14], (data[15] & 0xf0) >> 4, (data[15] & 0x0c) >> 2));
2329 
2330  // Insert at head of master link list of regions
2331  region->next = subtitle_display_set.region_list;
2332  subtitle_display_set.region_list = region;
2333 
2334  // Get CLUT for defined ID (may get default CLUT if no matching CLUT found)
2335  STB_DSGetClut(subtitle_display_set.clut_list, region->region_clut_id);
2336 
2337  #ifdef STB_REGION_PRINT_REQUIRED
2338  if (subtitle_display_set.page_composition_buffer->page_state != MODE_CHANGE)
2339  {
2340  CheckRegionFootPrint(region,
2341  region->region_width,
2342  region->region_height,
2343  region->region_level_of_compatibilty,
2344  region->region_colour_depth,
2345  region->region_clut_id);
2346  }
2347  #endif
2348  }
2349  }
2350  else
2351  {
2352  // page_state means that we shouldn't be creating regions !!
2353  STB_SEGMENT_PRINT(("RCS Region r%d (No pre-existing vn) new ver %d - CANNOT CREATE - page state %d",
2354  region_id, region_version_number,
2355  subtitle_display_set.page_composition_buffer->page_state));
2356  // region is still NULL
2357  region = NULL;
2358  }
2359 
2360  // if non-null Region now points to entry in master list of regions (EPOCH's list)
2361  // all internal objects have been deleted
2362  // if NULL then we failed to malloc memory for a new region OR weren't allowed to create
2363  if (region != NULL)
2364  {
2365  region->region_version_number = region_version_number;
2366 
2367  // These parts of the region can change
2368  region->region_fill_flag = (data[7] & 0x08) >> 3;
2369  region->region_8_bit_pixel_code = data[14];
2370  region->region_4_bit_pixel_code = (data[15] & 0xf0) >> 4;
2371  region->region_2_bit_pixel_code = (data[15] & 0x0c) >> 2;
2372 
2373  // Create a new composition region, and attaches to the physical composition list.
2375  subtitle_display_set.page_composition_buffer->page_state);
2376 
2377  data += 16;
2378 
2379  // Add the object references listed in the RCS
2380  while (processed_length < segment_length)
2381  {
2382  object_id = (data[0] << 8) + data[1];
2383  object_type = (data[2] & 0xc0) >> 6;
2384 
2385  existing_region_object = region->region_object_list;
2386  while (existing_region_object != NULL)
2387  {
2388  if (existing_region_object->object_id == object_id)
2389  {
2390  object = existing_region_object;
2391  break;
2392  }
2393  existing_region_object = existing_region_object->next;
2394  }
2395 
2396  if (existing_region_object == NULL)
2397  {
2398  // Region needs to add new object
2399  object = (S_REGION_OBJECT *)STB_GetMemory(sizeof(S_REGION_OBJECT));
2400  }
2401 
2402  if (object != NULL)
2403  {
2404  object->object_id = object_id;
2405  object->object_type = (data[2] & 0xc0) >> 6;
2406  object->object_provider_flag = (data[2] & 0x30) >> 4;
2407  object->object_horizontal_position = ((data[2] & 0x0f) << 8) + data[3];
2408  object->object_vertical_position = ((data[4] & 0x0f) << 8) + data[5];
2409 
2410  if ((object->object_type == 0x01) || (object->object_type == 0x02))
2411  {
2412  object->object_foreground_pixel_code = data[6];
2413  object->object_background_pixel_code = data[7];
2414  }
2415 
2416  if (existing_region_object == NULL)
2417  {
2418  object->next = region->region_object_list;
2419  region->region_object_list = object;
2420  STB_SEGMENT_PRINT((" +o%d @(%d,%d)",
2421  object->object_id,
2422  object->object_horizontal_position,
2423  object->object_vertical_position));
2424  }
2425  else
2426  {
2427  STB_SEGMENT_PRINT((" ~o%d @(%d,%d)",
2428  object->object_id,
2429  object->object_horizontal_position,
2430  object->object_vertical_position));
2431  }
2432  }
2433  else
2434  {
2435  // Object malloc failed, subsequent mallocs are likley to fail for this segment.
2436  // Will cause parse error <= processed length will be wrong
2437  break;
2438  }
2439 
2440  if ((object_type == 0x01) || (object_type == 0x02))
2441  {
2442  // Move data pointer to next object
2443  data += 8;
2444  processed_length += 8;
2445  }
2446  else
2447  {
2448  // Move data pointer to next object
2449  data += 6;
2450  processed_length += 6;
2451  }
2452  }
2453  }
2454 
2455  // Return OK only if we processed the number of bytes we were given
2456  retval = (processed_length == segment_length);
2457 
2458  FUNCTION_FINISH(STB_DSSegmentRCS);
2459 
2460  return(retval);
2461 }
2462 
2475 BOOLEAN STB_DSSegmentCDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
2476 {
2477  S_CLUT *clut;
2478  U32BIT palette_entry;
2479  U16BIT segment_length;
2480  U16BIT processed_length;
2481  U16BIT clut_id;
2482  U8BIT clut_version_number;
2483  U8BIT display_version_number;
2484  U16BIT clut_entries = 0;
2485 
2486  U8BIT clut_entry_id;
2487  U8BIT clut_2_4_8_bit_entry_flags;
2488  U8BIT full_range_flag;
2489 
2490  U8BIT y;
2491  U8BIT cr;
2492  U8BIT cb;
2493  U8BIT t;
2494 
2495  BOOLEAN retval;
2496 
2497 
2498  FUNCTION_START(STB_DSSegmentCDS);
2499 
2500  ASSERT(data != NULL);
2501 
2502  // data[0] - sync_byte
2503  // data[1] - segment_type
2504  // data[2] - page_id MS8Bits
2505  // data[3] - page_id LS8Bits
2506 
2507  segment_length = (data[4] << 8) + data[5];
2508 
2509  if ((processed_bytes + segment_length + 6) > pes_len)
2510  {
2511  return(FALSE);
2512  }
2513 
2514  clut_id = data[6];
2515 
2516  clut_version_number = (data[7] & 0xf0) >> 4;
2517  data += 8;
2518 
2519  processed_length = 2;
2520 
2521  clut = STB_DSGetClut(subtitle_display_set.clut_list, clut_id);
2522 
2523  display_version_number = clut->clut_version_number;
2524 
2525  if (display_version_number == clut_version_number)
2526  {
2527  // ETS 300 743 8.1 Scope of Identifiers
2528  // 'All identifiers (region_id, CLUT_id, object_id) are unique within a
2529  // display built from a composition page and an ancillary page.'
2530 
2531  // DTG - Digital Terrestrial Television Requirements for Interoperability
2532  // Subtitling: 28 August 1998: Version: 3.0 Clause 5.5.5.3
2533  // 'Decoder behaviour is not defined if segments of the same type and id
2534  // value are repeated within a single display set.'
2535  STB_SEGMENT_PRINT(("CDS c%d version number %d unchanged - ignoring",
2536  clut_id, clut_version_number));
2537 
2538  /* Don't need to process the segment.
2539  * Set the processed length to avoid an error being shown */
2540  clut = NULL;
2541  processed_length = segment_length;
2542  }
2543  //else - new version. Now parse entries.
2544 
2545  if (clut != NULL)
2546  {
2547  STB_CLUT_PRINT(("CDS c%d v%d", clut_id, clut_version_number));
2548  while (processed_length < segment_length)
2549  {
2550  clut_entry_id = data[0];
2551  clut_2_4_8_bit_entry_flags = (data[1] & 0xe0) >> 5;
2552  full_range_flag = data[1] & 0x01;
2553 
2554  if (full_range_flag)
2555  {
2556  y = data[2];
2557  cr = data[3];
2558  cb = data[4];
2559  t = data[5];
2560 
2561  processed_length += 6;
2562  data += 6;
2563  }
2564  else
2565  {
2566  /* Reduced range defining the most significant bits of each value */
2567  y = (data[2] & 0xfc);
2568  cr = ((data[2] & 0x03) << 6) + ((data[3] & 0xc0) >> 2);
2569  cb = (data[3] & 0x3c) << 2;
2570  t = (data[3] & 0x03) << 6;
2571 
2572  processed_length += 4;
2573  data += 4;
2574  }
2575 
2576  // ETS 300 743 7.2.3
2577  // Y_value: The Y output value of the CLUT for this entry. A value of zero in the Y_value
2578  // field signals full transparency. In that case the values in the Cr_value, Cb_value and
2579  // T_value fields are irrelevant and shall be set to zero.
2580  // Full transparency is acquired through a value of zero in the Y_value field.
2581  if (y == 0x00)
2582  {
2583  palette_entry = 0xff000000;
2584  }
2585  else
2586  {
2587  palette_entry = (t << 24) + (y << 16) + (cr << 8) + cb;
2588  }
2589 
2590  MakeClutEntry(clut, clut_id, clut_entry_id, clut_2_4_8_bit_entry_flags, palette_entry);
2591  STB_CLUT_PRINT((" %3d> p%08x f%02x ", clut_entry_id, palette_entry, clut_2_4_8_bit_entry_flags));
2592  ++clut_entries;
2593  }
2594 
2595  STB_SEGMENT_PRINT(("CDS c%d v%d -- %d entries", clut_id, clut_version_number, clut_entries));
2596  clut->clut_version_number = clut_version_number;
2597  }
2598 
2599  if (processed_length == segment_length)
2600  {
2601  retval = TRUE;
2602  }
2603  else
2604  {
2605  retval = FALSE;
2606  }
2607 
2608  FUNCTION_FINISH(STB_DSSegmentCDS);
2609 
2610  return(retval);
2611 }
2612 
2625 BOOLEAN STB_DSSegmentODS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
2626 {
2627  S_OBJECT *object;
2628  U16BIT segment_length;
2629  U16BIT object_id;
2630  U8BIT object_version_number;
2631  U8BIT object_coding_method;
2632  U8BIT non_modifying_colour_flag;
2633  BOOLEAN retval;
2634 
2635  FUNCTION_START(STB_DSSegmentODS);
2636 
2637  ASSERT(data != NULL);
2638 
2639  retval = FALSE;
2640 
2641  // data[0] - sync_byte
2642  // data[1] - segment_type
2643  // data[2] - page_id MS8Bits
2644  // data[3] - page_id LS8Bits
2645 
2646  segment_length = (data[4] << 8) + data[5];
2647 
2648  if ((processed_bytes + segment_length + 6) > pes_len)
2649  {
2650  return(FALSE);
2651  }
2652 
2653  object_id = (data[6] << 8) + data[7];
2654 
2655  object_version_number = (data[8] & 0xf0) >> 4;
2656  object_coding_method = (data[8] & 0x0c) >> 2;
2657  non_modifying_colour_flag = (data[8] & 0x02) >> 1;
2658 
2659  object = subtitle_display_set.object_list;
2660 
2661  // search object list to find object ID
2662  while (object != NULL)
2663  {
2664  if (object->object_id == object_id)
2665  {
2666  break;
2667  }
2668  object = object->next;
2669  }
2670 
2671  if (object != NULL)
2672  {
2673  if (object->object_version_number != object_version_number)
2674  {
2675  // new version of existing object
2676  STB_SEGMENT_PRINT(("ODS o%d (existing version v%d) new ver v%d",
2677  object_id,
2678  object->object_version_number,
2679  object_version_number));
2680  }
2681  else
2682  {
2683  STB_SEGMENT_PRINT(("ODS o%d version number v%d unchanged -- IGNORING",
2684  object_id, object_version_number));
2685  /* ETS 300 743 8.1 Scope of Identifiers
2686  * 'All identifiers (region_id, CLUT_id, object_id) are unique within a
2687  * display built from a composition page and an ancillary page.' */
2688 
2689  /* DTG - Digital Terrestrial Television Requirements for Interoperability
2690  * Subtitling: 28 August 1998: Version: 3.0 Clause 5.5.5.3
2691  * 'Decoder behaviour is not defined if segments of the same type and id
2692  * value are repeated within a single display set.' */
2693 
2694  /* The above statement defined the original behaviour with the object being set
2695  * to NULL which meant a parsing error was detected and no subtitles were shown.
2696  * However, it's desirable for subtitles to be shown if at all possible, so this
2697  * is no longer treated as an error. */
2698  /* object = NULL; */
2699  }
2700  }
2701  else
2702  {
2703  // New object
2704  object = (S_OBJECT *)STB_GetMemory(sizeof(S_OBJECT));
2705  if (object != NULL)
2706  {
2707  STB_SEGMENT_PRINT(("ODS o%d ver v%d", object_id, object_version_number));
2708 
2709  memset((void *)object, 0x00, sizeof(S_OBJECT));
2710 
2711  object->next = subtitle_display_set.object_list;
2712  subtitle_display_set.object_list = object;
2713  }
2714  else
2715  {
2716  STB_SEGMENT_PRINT(("ODS o%d ver v%d malloc fail", object_id, object_version_number));
2717  }
2718  }
2719 
2720  if (object != NULL)
2721  {
2722  object->object_id = object_id;
2723  object->object_version_number = object_version_number;
2724  object->object_coding_method = object_coding_method;
2725  object->non_modifying_colour_flag = non_modifying_colour_flag;
2726  object->map_table_2_to_4_bit = default_2_bit_4_bit_map;
2727  object->map_table_2_to_8_bit = default_2_bit_8_bit_map;
2728  object->map_table_4_to_8_bit = default_4_bit_8_bit_map;
2729 
2730  if (ProcessObjectCodingMethod(data + 9, object, object_coding_method, segment_length))
2731  {
2732  // processed_length == segment_length
2733  retval = TRUE;
2734  }
2735  else
2736  {
2737  // processed_length != segment_length
2738  retval = FALSE;
2739  }
2740  }
2741 
2742  FUNCTION_FINISH(STB_DSSegmentODS);
2743 
2744  return(retval);
2745 }
2746 
2760 BOOLEAN STB_DSSegmentEDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
2761 {
2762  U16BIT segment_length;
2763  BOOLEAN retval;
2764 
2765 
2766  FUNCTION_START(STB_DSSegmentEDS);
2767 
2768  ASSERT(data != NULL);
2769 
2770  STB_SEGMENT_PRINT(("EDS - End of Page"));
2771 
2772  // data[0] - sync_byte
2773  // data[1] - segment_type
2774  // data[2] - page_id MS8Bits
2775  // data[3] - page_id LS8Bits
2776 
2777  segment_length = (data[4] << 8) + data[5];
2778 
2779  if ((processed_bytes + segment_length + 6) > pes_len)
2780  {
2781  return(FALSE);
2782  }
2783 
2784  if (segment_length == 0)
2785  {
2786  retval = TRUE;
2787  }
2788  else
2789  {
2790  retval = FALSE;
2791  }
2792 
2793  STB_DSDumpPageState("post-EDS");
2794 
2795  FUNCTION_FINISH(STB_DSSegmentEDS);
2796 
2797  return(retval);
2798 }
2799 
2813 BOOLEAN STB_DSGetPesPts(U8BIT *data, U8BIT *pts)
2814 {
2815  BOOLEAN retval;
2816 
2817 
2818  FUNCTION_START(STB_DSGetPesPts);
2819 
2820  pts[0] = (data[0] & 0x08) >> 3;
2821  pts[1] = ((data[0] & 0x06) << 5) + ((data[1] & 0xfc) >> 2);
2822  pts[2] = ((data[1] & 0x03) << 6) + ((data[2] & 0xfc) >> 2);
2823  pts[3] = ((data[2] & 0x02) << 6) + ((data[3] & 0xfe) >> 1);
2824  pts[4] = ((data[3] & 0x01) << 7) + ((data[4] & 0xfe) >> 1);
2825 
2826  retval = (data[0] & 0x01) & (data[2] & 0x01) & (data[4] & 0x01);
2827 
2828  FUNCTION_FINISH(STB_DSGetPesPts);
2829 
2830  return(retval);
2831 }
2832 
2844 BOOLEAN STB_DSSetDisplaySetPts(U8BIT path, U8BIT *pts)
2845 {
2846  U8BIT stc[5];
2847  U32BIT time_ms;
2848  U32BIT stc_timestamp;
2849  U32BIT pts_timestamp;
2850  U32BIT stc_delay;
2851  U32BIT ms_delay;
2852 
2853 
2854  FUNCTION_START(STB_DSSetDisplaySetPts);
2855 
2856  ASSERT(pts != NULL);
2857 
2858  time_ms = STB_OSGetClockMilliseconds();
2860 
2861  stc_timestamp = ((stc[0] << 24) + (stc[1] << 16) + (stc[2] << 8) + stc[3]);
2862  pts_timestamp = ((pts[0] << 24) + (pts[1] << 16) + (pts[2] << 8) + pts[3]);
2863 
2864  memcpy((void *)subtitle_display_set.page_composition_buffer->pts, (void *)pts, (size_t)5);
2865 
2866  if (pts_timestamp > stc_timestamp)
2867  {
2868  stc_timestamp = ((stc[1] << 24) + (stc[2] << 16) + (stc[3] << 8) + stc[4]);
2869  pts_timestamp = ((pts[1] << 24) + (pts[2] << 16) + (pts[3] << 8) + pts[4]);
2870 
2871  stc_delay = pts_timestamp - stc_timestamp;
2872  ms_delay = stc_delay / 90;
2873 
2874  subtitle_display_set.page_composition_buffer->presentation_time_ms = time_ms + ms_delay;
2875  }
2876  else
2877  {
2878  subtitle_display_set.page_composition_buffer->presentation_time_ms = time_ms;
2879  }
2880 
2881  FUNCTION_FINISH(STB_DSSetDisplaySetPts);
2882 
2883  return(TRUE);
2884 }
2885 
2898 {
2899  FUNCTION_START(STB_DSGetDetails);
2900  FUNCTION_FINISH(STB_DSGetDetails);
2901  return(&subtitle_display_set);
2902 }
2903 
2916 {
2917  FUNCTION_START(STB_DSClearDisplaySetStruct);
2918 
2919  DeletePageCompositionRegions(&subtitle_display_set.page_composition_buffer->region_list);
2920  DeletePageCompositionRegions(&subtitle_display_set.page_display_buffer->region_list);
2921  DeleteEpochRegionList(&subtitle_display_set.region_list);
2922  DeleteObjectList(&subtitle_display_set.object_list);
2923  DeleteClutList(&subtitle_display_set.clut_list);
2924 
2925  memset((void *)&subtitle_display_set, 0x00, sizeof(S_DISPLAY_SET));
2926  memset((void *)&page_1, 0x00, sizeof(S_PAGE_COMPOSITION));
2927  memset((void *)&page_2, 0x00, sizeof(S_PAGE_COMPOSITION));
2928 
2929  /* Initialise the DDS version to an invalid value to ensure the first DDS segment found is used */
2930  page_1.dds_present = FALSE;
2931  page_1.dds_version = 0xff;
2932  page_1.display_width = 719;
2933  page_1.display_height = 575;
2934  page_1.display_window = FALSE;
2935  page_1.page_version_number = 0xff;
2936 
2937  page_2.dds_present = FALSE;
2938  page_2.dds_version = 0xff;
2939  page_2.display_width = 719;
2940  page_2.display_height = 575;
2941  page_2.display_window = FALSE;
2942  page_2.page_version_number = 0xff;
2943 
2944  subtitle_display_set.page_display_buffer = &page_1;
2945  subtitle_display_set.page_composition_buffer = &page_2;
2946 
2947  FUNCTION_FINISH(STB_DSClearDisplaySetStruct);
2948 }
2949 
2962 {
2963  FUNCTION_START(STB_DSClearCompositionPageDetails);
2964 
2965  DeletePageCompositionRegions(&subtitle_display_set.page_composition_buffer->region_list);
2966 
2967  subtitle_display_set.page_composition_buffer->pts[0] = 0x00;
2968  subtitle_display_set.page_composition_buffer->pts[1] = 0x00;
2969  subtitle_display_set.page_composition_buffer->pts[2] = 0x00;
2970  subtitle_display_set.page_composition_buffer->pts[3] = 0x00;
2971  subtitle_display_set.page_composition_buffer->pts[4] = 0x00;
2972 
2973  subtitle_display_set.page_composition_buffer->display_set_shown = FALSE;
2974  subtitle_display_set.page_composition_buffer->display_set_removed = FALSE;
2975  subtitle_display_set.page_composition_buffer->dds_present = FALSE;
2976 
2977  FUNCTION_FINISH(STB_DSClearCompositionPageDetails);
2978 }
2979 
2980 static void STB_DSDumpPageState(const char *label)
2981 {
2982  S_EPOCH_REGION *regione;
2983  S_REGION *region;
2984 #ifdef STB_CLUT_PRINT_REQUIRED
2985  S_CLUT *clut;
2986 #endif
2987 #ifdef STB_OBJECT_PRINT_REQUIRED
2988  S_OBJECT *object;
2990 #endif
2991 
2992 #ifdef STB_SUMMARY_PRINT_REQUIRED
2993  STB_SUMMARY_PRINT(("\nPage state dump \"%s\"\n EPOCH Reg", label));
2994 #else
2995  USE_UNWANTED_PARAM(label);
2996 #endif
2997 
2998  // Dump EPOCH's master region list
2999  {
3000  regione = subtitle_display_set.region_list;
3001 
3002  while (regione != NULL)
3003  {
3004  STB_SUMMARY_PRINT((" r%d (v%d) (w%d, h%d, d%d) c%d",
3005  regione->region_id,
3006  regione->region_version_number,
3007  regione->region_width,
3008  regione->region_height,
3009  regione->region_colour_depth,
3010  regione->region_clut_id));
3011 #ifdef STB_OBJECT_PRINT_REQUIRED
3012  region_object = regione->region_object_list;
3013  while (region_object != NULL)
3014  {
3015  STB_SUMMARY_PRINT((" o%3d @(%d,%d)",
3016  region_object->object_id,
3017  region_object->object_horizontal_position,
3018  region_object->object_vertical_position));
3019  region_object = region_object->next;
3020  }
3021 #endif
3022  regione = regione->next;
3023  }
3024  }
3025  STB_SUMMARY_PRINT((" <END>\n Composition"));
3026  // Dump PCS and its region list
3027  {
3028  region = subtitle_display_set.page_composition_buffer->region_list;
3029 
3030  while (region != NULL)
3031  {
3032  STB_SUMMARY_PRINT((" r%d @ (%dx%d)",
3033  region->region_id,
3034  region->region_horizontal_address,
3035  region->region_vertical_address));
3036  region = region->next;
3037  }
3038  }
3039  STB_SUMMARY_PRINT((" <END>\n Display"));
3040  // Dump PCS and its region list
3041  {
3042  region = subtitle_display_set.page_display_buffer->region_list;
3043 
3044  while (region != NULL)
3045  {
3046  STB_SUMMARY_PRINT((" r%d @ (%dx%d)",
3047  region->region_id,
3048  region->region_horizontal_address,
3049  region->region_vertical_address));
3050 
3051  region = region->next;
3052  }
3053  }
3054 #ifdef STB_OBJECT_PRINT_REQUIRED
3055  // Can cause a lot of print outs in snake subtitles
3056  STB_SUMMARY_PRINT((" <END>\n Objects"));
3057  {
3058  object = subtitle_display_set.object_list;
3059 
3060  while (object != NULL)
3061  {
3062  STB_SUMMARY_PRINT((" o%3d v%2d (%dx%d) coding %d %s",
3063  object->object_id,
3064  object->object_version_number,
3065  object->width, object->height,
3066  object->object_coding_method,
3067  (object->non_modifying_colour_flag) ? "nonmod" : "MODIFY"));
3068  object = object->next;
3069  }
3070  }
3071 #endif
3072 #ifdef STB_CLUT_PRINT_REQUIRED
3073  STB_SUMMARY_PRINT((" <END>\n Clut"));
3074  {
3075  clut = subtitle_display_set.clut_list;
3076 
3077  while (clut != NULL)
3078  {
3079  STB_SUMMARY_PRINT((" c%d v%3d 2-%s 4-%s 8-%s",
3080  clut->clut_id,
3081  clut->clut_version_number,
3082  (clut->default_2_bit) ? "default" : "CHANGED",
3083  (clut->default_4_bit) ? "default" : "CHANGED",
3084  (clut->default_8_bit) ? "default" : "CHANGED"));
3085  clut = clut->next;
3086  }
3087  }
3088 #endif
3089  STB_SUMMARY_PRINT((" <END>"));
3090 }
3091 
3092 //*****************************************************************************
3093 // End of file
3094 //*****************************************************************************
S_CLUT * STB_DSGetClut(S_CLUT *clut_list, U16BIT clut_id)
Finds or malloc&#39;s a new CLUT and assigns the family pointers to the default data. version_id is set t...
Definition: stbdsfn.c:1814
void STB_DSCreateCompositionRegion(S_EPOCH_REGION *region, BOOLEAN page_reset)
By end of call ensures that the specified region has a suitable physical region waiting in the physic...
Definition: stbdsdis.c:1409
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
BOOLEAN STB_DSSegmentPCS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes, BOOLEAN external_force_acquisition)
Processes the Page Composition segment in accordance with ETSI document ETS 300 743.
Definition: stbdsfn.c:1972
BOOLEAN STB_DSSegmentCDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the CLUT Definition segment in accordance with ETSI document ETS 300 743.
Definition: stbdsfn.c:2475
BOOLEAN STB_DSSegmentDDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the Display Definition segment in accordance with ETSI document ETS 300 743...
Definition: stbdsfn.c:1877
Header file - macros and function prototypes for public use.
void STB_DSClearDisplaySetStruct(void)
Clears all information from the display set structure.
Definition: stbdsfn.c:2915
BOOLEAN STB_DSSegmentRCS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the Region Composition segment in accordance with ETSI document ETS 300 743...
Definition: stbdsfn.c:2204
Header file - Function prototypes for OSD control.
void STB_DSClearCompositionPageDetails(void)
Clears all information from the display set composition page.
Definition: stbdsfn.c:2961
void STB_AVGetSTC(U8BIT path, U8BIT stc[5])
Returns the current 33-bit System Time Clock from the PCR PES. On some systems, this information may ...
U8BIT STB_DPGetPathVideoDecoder(U8BIT path)
Returns the video decoder ID acquired by the given decode path.
Definition: stbdpc.c:1757
Header file - Function prototypes for A/V control.
Header file - Function prototypes for DVB subtitles.
Definition: stbds.h:51
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
BOOLEAN STB_DSSegmentEDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
DTG - Digital Terrestrial Television Requirements for Interoperability Subtitling: 28 August 1998: Ve...
Definition: stbdsfn.c:2760
Debug functions header file.
Definition: stbds.h:75
BOOLEAN STB_DSGetPesPts(U8BIT *data, U8BIT *pts)
Extracts the PTS from the PES packet header.
Definition: stbdsfn.c:2813
void STB_DSRenderBitmapToRegion(S_EPOCH_REGION *region_list, S_OBJECT *object, U8BIT *scan_line, U16BIT y, U16BIT w, U16BIT h)
For the passed region list [PCS specified] get region handle, load the region with the correct CLUT...
Definition: stbdsdis.c:1576
BOOLEAN STB_DSSetDisplaySetPts(U8BIT path, U8BIT *pts)
Copies the passed PTS into the display set structure.
Definition: stbdsfn.c:2844
Header file - Function prototypes for operating system.
System Wide Global Technical Data Type Definitions.
S_DISPLAY_SET * STB_DSGetDetails(void)
Gets a pointer to the display set structure.
Definition: stbdsfn.c:2897
BOOLEAN STB_DSInitialiseDVBSubtitlesProcessing(void)
Initilises DVB subtitles, allocates a temporary buffer for use as a scratchpad and zero&#39;s the display...
Definition: stbdsfn.c:1760
void STB_DSResetPhysicalCompositionRegions(void)
Deletes all regions and clears serice_aquired flag.
Definition: stbdsdis.c:1354
Header file - Function prototypes for heap memory.
BOOLEAN STB_DSSegmentODS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the Object Data segment in accordance with ETSI document ETS 300 743.
Definition: stbdsfn.c:2625
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
Definition: stbds.h:126