DVBCore  20.3.0
DVBCore Documentation
stbdsdis.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  *******************************************************************************/
24 /* #define STB_ERROR_PRINT_REQUIRED*/
25 /* #define TIMINGS */
26 /* #define STB_TIMING_PRINT_REQUIRED */
27 /* #define STB_DISPLAY_PRINT_REQUIRED */
28 /* #define STB_PIXEL_PRINT_REQUIRED */
29 
30 //---includes for this file----------------------------------------------------
31 // compiler library header files
32 
33 #include <string.h>
34 #include <stdlib.h>
35 
36 // third party header files
37 
38 // Ocean Blue Software header files
39 
40 #include <techtype.h>
41 #include <dbgfuncs.h>
42 
43 #include "stbhwos.h"
44 #include "stbhwosd.h"
45 #include "stbheap.h"
46 #include "stbds.h"
47 #include "stbhwosd.h"
48 #include "stbhwav.h"
49 #include "stbdpc.h"
50 
51 //---constant definitions for this file----------------------------------------
52 
53 // System Time Clock frequency - 90kHz
54 #define STC_FREQ 90000
55 #define QUARTER_SEC_STC_FREQ (STC_FREQ / 4)
56 // But for the PTS's, of the 5 bytes the 4MSB only are used.
57 #define QUARTER_SEC_STC_FREQ_MSB (QUARTER_SEC_STC_FREQ >> 8)
58 
59 #ifdef STB_DEBUG_PRINT_REQUIRED
60  #ifdef STB_DEBUG_CHANNEL_DEBUG_REQUIRED
61  #define STB_DBG_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
62  #else
63  #define STB_DBG_PRINT(x) STB_SPDebugWrite x
64  #endif
65 #else
66  #define STB_DBG_PRINT(x)
67 #endif
68 
69 #ifdef STB_ERROR_PRINT_REQUIRED
70  #ifdef STB_ERROR_CHANNEL_DEBUG_REQUIRED
71  #define STB_ERROR_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
72  #else
73  #define STB_ERROR_PRINT(x) STB_SPDebugWrite x
74  #endif
75 #else
76  #define STB_ERROR_PRINT(x)
77 #endif
78 
79 #ifdef STB_TIMING_PRINT_REQUIRED
80  #ifdef STB_TIMING_CHANNEL_DEBUG_REQUIRED
81  #define STB_TIMING_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
82  #else
83  #define STB_TIMING_PRINT(x) STB_SPDebugWrite x
84  #endif
85 #else
86  #define STB_TIMING_PRINT(x)
87 #endif
88 
89 #ifdef STB_DISPLAY_PRINT_REQUIRED
90  #ifdef STB_DISPLAY_MOVE_CHANNEL_DEBUG_REQUIRED
91  #define STB_DISPLAY_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
92  #else
93  #define STB_DISPLAY_PRINT(x) STB_SPDebugWrite x
94  #endif
95 #else
96  #define STB_DISPLAY_PRINT(x)
97 #endif
98 
99 #ifdef STB_PIXEL_PRINT_REQUIRED
100  #ifdef STB_PIXEL_MOVE_CHANNEL_DEBUG_REQUIRED
101  #define STB_PIXEL_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x
102  #else
103  #define STB_PIXEL_PRINT(x) STB_SPDebugWrite x
104  #endif
105 #else
106  #define STB_PIXEL_PRINT(x)
107 #endif
108 
109 #ifdef DS_HEAP_USAGE
110  #define STB_GetMemory(x) STB_DSGetMemory(x)
111  #define STB_FreeMemory(x) STB_DSFreeMemory(x)
112 #endif
113 
114 //---local typedef structs for this file---------------------------------------
115 
116 typedef struct physical_region
117 {
118  struct physical_region *next;
119  void *handle;
120  U8BIT region_id;
121  U8BIT region_version_number;
122 
123  // These are varibles for physical control/settings
124  U16BIT current_x;
125  U16BIT current_y;
126  U16BIT region_width;
127  U16BIT region_height;
128  U16BIT region_colour_depth;
129 
130  BOOLEAN visible;
132 
133 
134 //---local (static) variable declarations for this file------------------------
135 // (internal variables declared static to make them local)
136 
137 static BOOLEAN terminate_subtitles;
138 static BOOLEAN show_subtitles;
139 
140 static BOOLEAN time_diff_set = FALSE;
141 static U32BIT time_diff_value;
142 
143 static S_PHYSICAL_REGION *physical_display_region_list;
144 static S_PHYSICAL_REGION *physical_composition_region_list;
145 
146 // Callback function for the stb_ui library to use font fusion to render a string of characters
147 // into a provided area of memory.
148 static void (*CreateBitmapCallback)(U8BIT *bitmap, U16BIT width, U16BIT height, U8BIT *char_array,
149  U8BIT *tycrcb_palette, U8BIT fgnd_col, U8BIT bkgnd_col);
150 
151 // Display set timimg variables
152 #ifdef TIMINGS
153 static U32BIT shown_time;
154 static U32BIT diff_ms;
155 static S32BIT delay;
156 static BOOLEAN do_timing;
157 #endif
158 
159 //---local function prototypes for this file-----------------------------------
160 // (internal functions declared static to make them local)
161 
162 static BOOLEAN DetectPcrDiscontinuity(U8BIT path);
163 static BOOLEAN WaitToDisplay(U8BIT path, S_PAGE_COMPOSITION *pg_disp_buff, S_PAGE_COMPOSITION *pg_comp_buff);
164 static void HideAllShownRegions(S_REGION *region_list);
165 static void SwapDisplayAndCompositionBuffers(S_PAGE_COMPOSITION **buff_1,
166  S_PAGE_COMPOSITION **buff_2);
167 static void CheckToHideCopiedRegion(S_PHYSICAL_REGION *physical_region, S_REGION *region_list);
168 static void CompleteCompositionList(S_DISPLAY_SET *subtitle_display_set);
169 static void MoveRegions(S_REGION *region_list);
170 static void UpdateDisplaySet(U8BIT path, S_DISPLAY_SET *subtitle_display_set);
171 static void ColourDepthAdjustTo2Bits(U8BIT **region_adjusted_bitmap, U8BIT *bitmap,
172  U16BIT width, U16BIT height);
173 static void ColourDepthAdjustTo4Bits(U8BIT **region_adjusted_bitmap, U8BIT *bitmap,
174  U16BIT width, U16BIT height);
175 static void LoadPalettesIntoRegions(S_EPOCH_REGION *region_list, S_CLUT *clut_list);
176 static void ShowDisplaySet(S_REGION *region_list);
177 static void remove_entry_from_list(S_PHYSICAL_REGION *entry, S_PHYSICAL_REGION **list);
178 #ifdef STB_DISPLAY_PRINT_REQUIRED
179 void dump_physical_regions(const char *label);
180 #endif
181 
182 //---local function definitions------------------------------------------------
183 
195 static BOOLEAN DetectPcrDiscontinuity(U8BIT path)
196 {
197  static U32BIT last_time;
198  static U8BIT last_stc[5];
199 
200  U32BIT stc_timestamp;
201  U32BIT diff_stc_ms;
202  U32BIT stc_err;
203  U32BIT projected_stc;
204  U32BIT new_time;
205  U32BIT diff_last_time;
206  U8BIT new_stc[5];
207 
208  BOOLEAN retval;
209 
210 
211  FUNCTION_START(DetectPcrDiscontinuity);
212 
213  diff_last_time = STB_OSGetClockDiff(last_time);
214 
215  // System Time Clock frequency - 90kHz
216  diff_stc_ms = ((diff_last_time * 90) >> 8);
217 
218  new_time = STB_OSGetClockMilliseconds();
219  STB_AVGetSTC(STB_DPGetPathVideoDecoder(path), new_stc);
220 
221  stc_timestamp = ((last_stc[0] << 24) + (last_stc[1] << 16) + (last_stc[2] << 8) + last_stc[3]);
222  projected_stc = stc_timestamp + diff_stc_ms;
223  stc_timestamp = ((new_stc[0] << 24) + (new_stc[1] << 16) + (new_stc[2] << 8) + new_stc[3]);
224  stc_err = abs(projected_stc - stc_timestamp);
225 
226  /* Allow STC to be out by 1 minute before signalling a discontinuity */
227  if (stc_err > ((STC_FREQ >> 8) * 60))
228  {
229  STB_TIMING_PRINT(("DetectPcrDiscontinuity"));
230  retval = TRUE;
231  }
232  else
233  {
234  retval = FALSE;
235  }
236 
237  memcpy((void *)last_stc, (void *)new_stc, (size_t)5);
238  last_time = new_time;
239 
240  FUNCTION_FINISH(DetectPcrDiscontinuity);
241 
242  return(retval);
243 }
244 
259 static BOOLEAN WaitToDisplay(U8BIT path, S_PAGE_COMPOSITION *pg_disp_buff, S_PAGE_COMPOSITION *pg_comp_buff)
260 {
261  U32BIT time_ms;
262  U32BIT pg_timestamp;
263  U32BIT stc_timestamp;
264  U32BIT difference_seconds;
265  U32BIT waitdelay;
266  U8BIT stc[5];
267  BOOLEAN display;
268 
269  FUNCTION_START(WaitToDisplay);
270 
271  ASSERT(pg_disp_buff != NULL);
272  ASSERT(pg_comp_buff != NULL);
273 
274  display = TRUE;
275 
276  // PTS values are used discounting the least signifiant byte, leaving 4 bytes using
277  // 25 bits not the full 33 bits.
278  pg_timestamp = ((pg_comp_buff->pts[0] << 24) +
279  (pg_comp_buff->pts[1] << 16) +
280  (pg_comp_buff->pts[2] << 8) +
281  (pg_comp_buff->pts[3]));
282 
284  stc_timestamp = ((stc[0] << 24) + (stc[1] << 16) + (stc[2] << 8) + stc[3]);
285 
286  if (!time_diff_set && (stc_timestamp != 0) && (pg_timestamp != 0))
287  {
288  if ((stc[0] == 0) && (pg_comp_buff->pts[0] == 1))
289  {
290  /* Top bit of STC isn't present so make sure PTS doesn't have it set either */
291  pg_timestamp &= 0x00ffffff;
292  }
293  else if ((stc[0] == 1) && (pg_comp_buff->pts[0] == 0))
294  {
295  /* Top bit of STC is present so make sure PTS hae it set too */
296  pg_timestamp |= 0x01000000;
297  }
298 
299  time_diff_value = 0;
300 
301  if (pg_timestamp > stc_timestamp)
302  {
303  if ((pg_timestamp - stc_timestamp) > 0x10000)
304  {
305  time_diff_value = (pg_timestamp & 0xffffff00) - (stc_timestamp & 0xffffff00);
306  }
307  }
308  else
309  {
310  if ((stc_timestamp - pg_timestamp) > 0x10000)
311  {
312  time_diff_value = (stc_timestamp & 0xffffff00) - (pg_timestamp & 0xffffff00);
313  }
314  }
315 
316  time_diff_set = TRUE;
317  }
318 
319  if (time_diff_set)
320  {
321  if (stc[0] == 0)
322  {
323  /* Top bit of STC isn't present so make sure PTS doesn't have it set either */
324  pg_timestamp &= 0x00ffffff;
325  }
326 
327  if (pg_timestamp > stc_timestamp)
328  {
329  if ((pg_timestamp - stc_timestamp) > 0x10000)
330  {
331  pg_timestamp -= time_diff_value;
332  }
333  }
334  else
335  {
336  if ((stc_timestamp - pg_timestamp) > 0x10000)
337  {
338  pg_timestamp += time_diff_value;
339  }
340  }
341  }
342 
343  while (1)
344  {
345  time_ms = STB_OSGetClockMilliseconds();
346 
347  if (terminate_subtitles)
348  {
349  terminate_subtitles = FALSE;
350  break;
351  }
352 
353  if (DetectPcrDiscontinuity(path))
354  {
355  break;
356  }
357 
358  // Check timeout of the displayed display set, in seconds. Rounds up to the next second.
359  difference_seconds = (STB_OSGetClockDiff(pg_disp_buff->timeout_start) / 1000) + 1;
360 
361  if ((pg_disp_buff->display_set_shown) && (!pg_disp_buff->display_set_removed))
362  {
363  if (pg_disp_buff->page_time_out <= difference_seconds)
364  {
365  // Clear display set
366  STB_TIMING_PRINT(("$ WaitToDisplay @ %d, expired clear OSD", __LINE__));
367  HideAllShownRegions(pg_disp_buff->region_list);
369  pg_disp_buff->display_set_removed = TRUE;
370  #ifdef TIMINGS
371  diff_ms = STB_OSGetClockDiff(shown_time);
372  do_timing = FALSE;
373  #endif
374  }
375  else
376  {
377  STB_TIMING_PRINT(("$ WaitToDisplay @ %d, %d > %d",
378  __LINE__, pg_disp_buff->page_time_out, difference_seconds));
379  }
380  }
381  else
382  {
383  STB_TIMING_PRINT(("$ WaitToDisplay @ %d, !shown || removed", __LINE__));
384  }
385 
387  stc_timestamp = ((stc[0] << 24) + (stc[1] << 16) + (stc[2] << 8) + stc[3]);
388 
389 #if 0
390  STB_TIMING_PRINT(("Time=%lu, pres_time=%lu, PTS=0x%lx, STC=0x%lx, PTS-STC=%ld\n", time_ms,
391  pg_comp_buff->presentation_time_ms, pg_timestamp, stc_timestamp,
392  (S32BIT)(pg_timestamp - stc_timestamp)));
393 #endif
394 
395  // As page PTS is some time in the future, if the current AV PTS is greater
396  // than or equal to; then its time to display page
397  STB_TIMING_PRINT(("%d >? %d ~%d || %d >?= %d ~%d",
398  stc_timestamp, pg_timestamp, (stc_timestamp >= pg_timestamp),
399  time_ms, pg_comp_buff->presentation_time_ms,
400  (time_ms >= pg_comp_buff->presentation_time_ms)));
401 
402  if (stc_timestamp == 0)
403  {
404  display = FALSE;
405  break;
406  }
407 
408  if ((stc_timestamp >= pg_timestamp) || (time_ms >= pg_comp_buff->presentation_time_ms))
409  {
410  STB_TIMING_PRINT(("$ WaitToDisplay, PTS now"));
411  break;
412  }
413 
414  /* Make sure the delay isn't too long */
415  if ((waitdelay = pg_comp_buff->presentation_time_ms - time_ms) > 250)
416  {
417  waitdelay = 250;
418  }
419 
420  STB_OSTaskDelay(waitdelay);
421  }
422 
423  FUNCTION_FINISH(WaitToDisplay);
424 
425  return(display);
426 }
427 
440 static void HideAllShownRegions(S_REGION *region_list)
441 {
442  S_PHYSICAL_REGION *physical_region;
443  S_REGION *region;
444 
445  FUNCTION_START(HideAllShownRegions);
446 
447  if ((region_list != NULL) && (physical_display_region_list != NULL))
448  {
449  region = region_list;
450  while (region != NULL)
451  {
452  physical_region = physical_display_region_list;
453  while (physical_region != NULL)
454  {
455  ASSERT(region != NULL);
456 
457  if ((physical_region->region_id == region->region_id) && physical_region->visible)
458  {
459  STB_DISPLAY_PRINT(("%s: Hide region pr%d, %x", __FUNCTION__, physical_region->region_id,
460  physical_region->handle));
461 
462  STB_OSDHideRegion(physical_region->handle);
463  physical_region->visible = FALSE;
464  break;
465  }
466  physical_region = physical_region->next;
467  }
468  region = region->next;
469  }
470  }
471 
472  FUNCTION_FINISH(HideAllShownRegions);
473 }
474 
487 static void SwapDisplayAndCompositionBuffers(S_PAGE_COMPOSITION **buff_1, S_PAGE_COMPOSITION **buff_2)
488 {
489  S_PAGE_COMPOSITION *tmp_pg;
490  S_PHYSICAL_REGION *temp;
491 
492  FUNCTION_START(SwapDisplayAndCompositionBuffers);
493 
494  ASSERT(*buff_1 != NULL);
495  ASSERT(*buff_2 != NULL);
496 
497  //STB_DISPLAY_PRINT(("Display & comp buffers swapped"));
498 
499  if ((*buff_1)->dds_present && ((*buff_1)->dds_version != (*buff_2)->dds_version))
500  {
501  (*buff_2)->dds_present = (*buff_1)->dds_present;
502  (*buff_2)->dds_version = (*buff_1)->dds_version;
503  (*buff_2)->display_width = (*buff_1)->display_width;
504  (*buff_2)->display_height = (*buff_1)->display_height;
505  (*buff_2)->display_window = (*buff_1)->display_window;
506  if ((*buff_1)->display_window)
507  {
508  (*buff_2)->window_x = (*buff_1)->window_x;
509  (*buff_2)->window_y = (*buff_1)->window_y;
510  (*buff_2)->window_width = (*buff_1)->window_width;
511  (*buff_2)->window_height = (*buff_1)->window_height;
512  }
513  }
514 
515  tmp_pg = *buff_1;
516  *buff_1 = *buff_2;
517  *buff_2 = tmp_pg;
518 
519  // Now swap the physical buffers to match
520  temp = physical_display_region_list;
521  physical_display_region_list = physical_composition_region_list;
522  physical_composition_region_list = temp;
523 
524  FUNCTION_FINISH(SwapDisplayAndCompositionBuffers);
525 }
526 
540 static void CheckToHideCopiedRegion(S_PHYSICAL_REGION *physical_region, S_REGION *region_list)
541 {
542  S_REGION *region = region_list;
543 
544  while ((region != NULL) && (region->region_id != physical_region->region_id))
545  {
546  region = region->next;
547  }
548  //either we found a match, or we ran out of regions
549 
550  if (region == NULL)
551  {
552  //We didn't find a matching region in the PCS list => we should not be showning this region
553  STB_DISPLAY_PRINT(("%s: Hide region pr%d, %x", __FUNCTION__, physical_region->region_id,
554  physical_region->handle));
555 
556  STB_OSDHideRegion(physical_region->handle);
557  physical_region->visible = FALSE;
558  }
559 }
560 
574 static void CompleteCompositionList(S_DISPLAY_SET *subtitle_display_set)
575 {
576  S_PHYSICAL_REGION *display_region;
577  S_PHYSICAL_REGION *prev_display_region;
578  S_PHYSICAL_REGION *composition_region;
579  S_EPOCH_REGION *legal_region;
580 
581  FUNCTION_START(CompleteCompositionList);
582 
583  // dump_physical_regions("PRE-MOVE");
584 
585  // Iterate over EPOCH's master region list
586  legal_region = subtitle_display_set->region_list;
587 
588  while (legal_region != NULL)
589  {
590  composition_region = physical_composition_region_list;
591 
592  while (composition_region != NULL)
593  {
594  if (legal_region->region_id == composition_region->region_id)
595  {
596  break;
597  }
598  composition_region = composition_region->next;
599  }
600 
601  if (composition_region == NULL)
602  {
603  // We don't currently have this region in the compose list - see if we can grab it
604  // from the displayed list
605  display_region = physical_display_region_list;
606  prev_display_region = NULL;
607 
608  while (display_region != NULL)
609  {
610  // Remember who pointed to the display region
611  if (legal_region->region_id == display_region->region_id)
612  {
613  // Move it across!
614  if (prev_display_region == NULL)
615  {
616  // display region is first in display list, amend list
617  physical_display_region_list = display_region->next;
618  }
619  else
620  {
621  prev_display_region->next = display_region->next;
622  }
623  display_region->next = physical_composition_region_list;
624  physical_composition_region_list = display_region;
625 
626  // We may want to retain the region, but should it be visible?
627  if (display_region->visible)
628  {
629  CheckToHideCopiedRegion(display_region,
630  subtitle_display_set->page_composition_buffer->region_list);
631  }
632  break;
633  }
634  prev_display_region = display_region;
635  display_region = display_region->next;
636  }
637  }
638  // else - Use new region
639 
640  legal_region = legal_region->next;
641  }
642 
643  // dump_physical_regions("POST-MOVE");
644 
645  FUNCTION_FINISH(CompleteCompositionList);
646 }
647 
659 static void MoveRegions(S_REGION *region_list)
660 {
661  S_REGION *region;
662  S_PHYSICAL_REGION *physical_composition_region;
663 
664  U16BIT region_id;
665 
666 
667  FUNCTION_START(MoveRegions);
668 
669  if (region_list != NULL)
670  {
671  if (physical_composition_region_list != NULL)
672  {
673  // For each region listed in the PCS...
674  region = region_list;
675  while (region != NULL)
676  {
677  region_id = region->region_id;
678 
679  // Find PCS regions' physical composition region from list...
680  physical_composition_region = physical_composition_region_list;
681  while (physical_composition_region != NULL)
682  {
683  if (physical_composition_region->region_id == region_id)
684  {
685  if ((physical_composition_region->current_x != region->region_horizontal_address) ||
686  (physical_composition_region->current_y != region->region_vertical_address))
687  {
688  STB_OSDMoveRegion(physical_composition_region->handle,
689  region->region_horizontal_address,
690  region->region_vertical_address);
691  physical_composition_region->current_x = region->region_horizontal_address;
692  physical_composition_region->current_y = region->region_vertical_address;
693  STB_DISPLAY_PRINT(("Move region %d (%x)",
694  region->region_id, physical_composition_region->handle));
695  }
696  break;
697  }
698  physical_composition_region = physical_composition_region->next;
699  }
700  region = region->next;
701  } //while(region != NULL)
702  }
703  else if (physical_display_region_list != NULL)
704  {
705  // For each region listed in the PCS...
706  region = region_list;
707  while (region != NULL)
708  {
709  region_id = region->region_id;
710 
711  // Find PCS regions' physical composition region from list...
712  physical_composition_region = physical_display_region_list;
713  while (physical_composition_region != NULL)
714  {
715  if (physical_composition_region->region_id == region_id)
716  {
717  if ((physical_composition_region->current_x != region->region_horizontal_address) ||
718  (physical_composition_region->current_y != region->region_vertical_address))
719  {
720  STB_OSDMoveRegion(physical_composition_region->handle,
721  region->region_horizontal_address,
722  region->region_vertical_address);
723  physical_composition_region->current_x = region->region_horizontal_address;
724  physical_composition_region->current_y = region->region_vertical_address;
725  STB_DISPLAY_PRINT(("Move region %d (%x)",
726  region->region_id, physical_composition_region->handle));
727  }
728  break;
729  }
730  physical_composition_region = physical_composition_region->next;
731  }
732  region = region->next;
733  } //while(region != NULL)
734  }
735  }
736 
737  FUNCTION_FINISH(MoveRegions);
738 }
739 
752 static void UpdateDisplaySet(U8BIT path, S_DISPLAY_SET *subtitle_display_set)
753 {
754  FUNCTION_START(UpdateDisplaySet);
755 
756  ASSERT(subtitle_display_set != NULL);
757 
758  USE_UNWANTED_PARAM(path);
759 
760 // dump_physical_regions("Pre update display");
761 
762 #ifdef TIMINGS
763  if (do_timing)
764  {
765  diff_ms = STB_OSGetClockDiff(shown_time);
766  do_timing = FALSE;
767  }
768 
769  if (subtitle_display_set->page_display_buffer->region_list != NULL)
770  {
771  STB_TIMING_PRINT(("# pg.ver %02d shown for %04dms %04dms late ms_clk 0x%08x",
772  subtitle_display_set->page_display_buffer->page_version_number,
773  diff_ms, delay, STB_OSGetClockMilliseconds()));
774  }
775  else
776  {
777  STB_TIMING_PRINT((" pg.ver %02d shown for %04dms %04dms late ms_clk 0x%08x",
778  subtitle_display_set->page_display_buffer->page_version_number,
779  diff_ms, delay, STB_OSGetClockMilliseconds()));
780  }
781 
782  do_timing = TRUE;
783 #endif
784 
785  //If this is to be treated as a normal page...
786  //Note dsfn.c code may force an acquisition point to be a mode change (by overriding page_state)
787  if (subtitle_display_set->page_composition_buffer->page_state != MODE_CHANGE)
788  {
789  // Composition list contains all regions which we have built for this page
790  // We need to grab older regions for this Page's epoch list from the now
791  // undisplayed displayed list
792  CompleteCompositionList(subtitle_display_set);
793  }
794  // else - we have been told to ignore history
795 
796  // Hide all regions remaining in display list - if they were needed and legal they'd already
797  // have been moved into the composition list
798  HideAllShownRegions(subtitle_display_set->page_display_buffer->region_list);
799  subtitle_display_set->page_display_buffer->display_set_removed = TRUE;
800 
801  SwapDisplayAndCompositionBuffers(&subtitle_display_set->page_composition_buffer,
802  &subtitle_display_set->page_display_buffer);
803 
804  ShowDisplaySet(subtitle_display_set->page_display_buffer->region_list);
805 
806  subtitle_display_set->page_display_buffer->display_set_shown = TRUE;
807  subtitle_display_set->page_display_buffer->timeout_start = STB_OSGetClockMilliseconds();
808 
809  // All regions remaining in the old display list (now the composition list) can be freed
811 
813 
814 #ifdef TIMINGS
815  {
816  U8BIT stc[5];
817  U32BIT stc_timestamp;
818  U32BIT pg_timestamp;
819 
820  pg_timestamp = ((subtitle_display_set->page_display_buffer->pts[0] << 24) +
821  (subtitle_display_set->page_display_buffer->pts[1] << 16) +
822  (subtitle_display_set->page_display_buffer->pts[2] << 8) +
823  (subtitle_display_set->page_display_buffer->pts[3]));
824 
825  shown_time = STB_OSGetClockMilliseconds();
827  stc_timestamp = ((stc[0] << 24) + (stc[1] << 16) + (stc[2] << 8) + stc[3]);
828  delay = ((((S32BIT)stc_timestamp - (S32BIT)pg_timestamp) << 8) / 90);
829  do_timing = TRUE;
830  }
831 #endif
832 // dump_physical_regions("Post update display");
833 
834  FUNCTION_FINISH(UpdateDisplaySet);
835 }
836 
852 static void ColourDepthAdjustTo2Bits(U8BIT **region_adjusted_bitmap, U8BIT *bitmap,
853  U16BIT width, U16BIT height)
854 {
855  U32BIT size;
856  U32BIT i;
857  U32BIT j;
858  U8BIT tmp_byte;
859 
860  U8BIT *p2;
861  U8BIT *p8;
862 
863 
864  FUNCTION_START(ColourDepthAdjustTo2Bits);
865 
866  ASSERT(*region_adjusted_bitmap != NULL);
867  ASSERT(bitmap != NULL);
868 
869  // ETS 300 743 9.2 8 to 2-bit reduction
870  // Let the input value be represented by an 8-bit field, the individual
871  // bits of which are called bi1, bi2, bi3, bi4, bi5, bi6, bi7 and bi8
872  // where bi1 is received first and bi8 is received last. Let the output
873  // value be represented by a 2-bit field bo1, bo2.
874  // The relation between output and input bits is:
875  // bo1 = bi1 : bo2 = bi2 | bi3 | bi4
876  p2 = *region_adjusted_bitmap;
877  p8 = bitmap;
878 
879  if (*region_adjusted_bitmap != NULL)
880  {
881  if (width % 4 == 0)
882  {
883  STB_PIXEL_PRINT(("To2 No padding (%dx%d) @ %d", width, height, __LINE__));
884  // No padding
885  size = height * width;
886  for (i = 0; i < size; i += 4)
887  {
888  static U8BIT lastcolin = 0xff;
889 
890  if (lastcolin != *p8)
891  {
892  STB_PIXEL_PRINT((" in %02x -cda2-> %02x",
893  *p8, (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0))));
894  lastcolin = *p8;
895  }
896 
897  tmp_byte = (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 6;
898  p8++;
899  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 4;
900  p8++;
901  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 2;
902  p8++;
903  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0));
904  p8++;
905  *p2 = tmp_byte;
906  p2++;
907  }
908  }
909  else
910  {
911  STB_PIXEL_PRINT(("To2 Padding (%dx%d) @ %d", width, height, __LINE__));
912  for (i = 0; i < height; i++)
913  {
914  for (j = 0; j <= width; j += 4)
915  {
916  if ((j + 3) <= width)
917  {
918  tmp_byte = (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 6;
919  p8++;
920  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 4;
921  p8++;
922  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 2;
923  p8++;
924  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0));
925  p8++;
926  }
927  else
928  {
929  tmp_byte = (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 6;
930  p8++;
931 
932  if ((j + 1) < width)
933  {
934  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 4;
935  p8++;
936 
937  if ((j + 2) < width)
938  {
939  tmp_byte |= (((*p8 & 0x80) >> 6) | ((*p8 & 0x70) != 0)) << 2;
940  p8++;
941  }
942  }
943  }
944  *p2 = tmp_byte;
945  p2++;
946  }
947  }
948  }
949  }
950 
951  FUNCTION_FINISH(ColourDepthAdjustTo2Bits);
952 }
953 
969 static void ColourDepthAdjustTo4Bits(U8BIT **region_adjusted_bitmap, U8BIT *bitmap,
970  U16BIT width, U16BIT height)
971 {
972  U32BIT size;
973  U32BIT i;
974  U32BIT j;
975  U8BIT tmp_byte;
976 
977  U8BIT *p4;
978  U8BIT *p8;
979 
980 
981  FUNCTION_START(ColourDepthAdjustTo4Bits);
982 
983  ASSERT(*region_adjusted_bitmap != NULL);
984  ASSERT(bitmap != NULL);
985 
986  // ETS 300 743 9.3 8 to 4-bit reduction
987  // Let the input value be represented by a 8-bit field, the individual bits of which are called
988  // bi1, bi2, bi3, bi4, bi5, bi6, bi7 and bi8 where bi1 is received first and bi8 is received
989  // last. Let the output value be represented by a 4-bit field bo1 to bo4. The relation between
990  // output and input bits is: bo1 = bi1 : bo2 = bi2 : bo3 = bi3 : bo4 = bi4
991  if (*region_adjusted_bitmap != NULL)
992  {
993  p4 = *region_adjusted_bitmap;
994  p8 = bitmap;
995 
996  // Reduce 8 bit to 4 bit bitmap
997  if (width % 2 == 0)
998  {
999  STB_PIXEL_PRINT(("To4 No Padding (%dx%d) @ %d", width, height, __LINE__));
1000  // No padding
1001  size = height * width;
1002  for (i = 0; i < size; i += 2)
1003  {
1004  STB_PIXEL_PRINT((" in %02x + %02x -cda4-> %02x @ %x",
1005  *p8, *(p8 + 1), ((*p8 & 0xf0) | (((*(p8 + 1) & 0xf0)) >> 4)), p4));
1006 
1007  tmp_byte = (*p8 & 0xf0);
1008  p8++;
1009  tmp_byte |= ((*p8 & 0xf0) >> 4);
1010  p8++;
1011  *p4 = tmp_byte;
1012  p4++;
1013  }
1014  }
1015  else
1016  {
1017  STB_PIXEL_PRINT(("To4 Padding (%dx%d) @ %d", width, height, __LINE__));
1018  for (i = 0; i < height; i++)
1019  {
1020  for (j = 0; j <= width; j += 2)
1021  {
1022  STB_PIXEL_PRINT((" in %02x + %02x -cda4-> %02x @ %x",
1023  *p8, *(p8 + 1), ((*p8 & 0xf0) | (((*(p8 + 1) & 0xf0)) >> 4)), p4));
1024 
1025  if ((j + 1) < width)
1026  {
1027  tmp_byte = (*p8 & 0xf0);
1028  p8++;
1029  tmp_byte |= ((*p8 & 0xf0) >> 4);
1030  p8++;
1031  }
1032  else
1033  {
1034  tmp_byte = (*p8 & 0xf0);
1035  p8++;
1036  }
1037  *p4 = tmp_byte;
1038  p4++;
1039  }
1040  }
1041  }
1042  }
1043 
1044  FUNCTION_FINISH(ColourDepthAdjustTo4Bits);
1045 }
1046 
1059 static void LoadPalettesIntoRegions(S_EPOCH_REGION *region_list, S_CLUT *clut_list)
1060 {
1061  S_PHYSICAL_REGION *physical_region;
1063  S_CLUT *clut;
1064 
1065 
1066  FUNCTION_START(LoadPalettesIntoRegions);
1067 
1068  physical_region = physical_composition_region_list;
1069  while (physical_region != NULL)
1070  {
1071  region = region_list;
1072 
1073  while (region)
1074  {
1075  ASSERT(region_list != NULL);
1076 
1077  if (physical_region->region_id == region->region_id)
1078  {
1079  clut = STB_DSGetClut(clut_list, region->region_clut_id);
1080 
1081  ASSERT(clut_list != NULL);
1082 
1083  switch (physical_region->region_colour_depth)
1084  {
1085  case 2:
1086  {
1087  STB_OSDSetYCrCbPalette(physical_region->handle, clut->clut_2_bit);
1088  break;
1089  }
1090 
1091  case 4:
1092  {
1093  STB_OSDSetYCrCbPalette(physical_region->handle, clut->clut_4_bit);
1094  break;
1095  }
1096 
1097  case 8:
1098  {
1099  STB_OSDSetYCrCbPalette(physical_region->handle, clut->clut_8_bit);
1100  break;
1101  }
1102  }
1103  break;
1104  }
1105  region = region->next;
1106  }
1107  physical_region = physical_region->next;
1108  }
1109 
1110  FUNCTION_FINISH(LoadPalettesIntoRegions);
1111 }
1112 
1124 static void ShowDisplaySet(S_REGION *region_list)
1125 {
1126  S_REGION *region;
1127  S_PHYSICAL_REGION *physical_display_region;
1128  U16BIT region_id;
1129 
1130  FUNCTION_START(ShowDisplaySet);
1131 
1132  if ((region_list != NULL) && (physical_display_region_list != NULL))
1133  {
1134  // For each region listed in the PCS...
1135  region = region_list;
1136  while (region != NULL)
1137  {
1138  region_id = region->region_id;
1139 
1140  // Find PCS regions' physical region from list...
1141  physical_display_region = physical_display_region_list;
1142  while (physical_display_region != NULL)
1143  {
1144  if (physical_display_region->region_id == region_id)
1145  {
1146  if (show_subtitles && !physical_display_region->visible)
1147  {
1148  STB_OSDShowRegion(physical_display_region->handle);
1149  STB_DISPLAY_PRINT((" Show region %d, %x", physical_display_region->region_id,
1150  physical_display_region->handle));
1151  physical_display_region->visible = TRUE;
1152  }
1153  break;
1154  }
1155  physical_display_region = physical_display_region->next;
1156  }
1157  region = region->next;
1158  } //while(region != NULL)
1159  }
1160 
1161  FUNCTION_FINISH(ShowDisplaySet);
1162 }
1163 
1164 //---global function definitions-----------------------------------------------
1165 
1177 void STB_DSCheckDisplaySetTimeout(S_DISPLAY_SET *subtitle_display_set, BOOLEAN timeout_override)
1178 {
1179  U32BIT difference_seconds;
1180 
1181  FUNCTION_START(STB_DSCheckDisplaySetTimeout);
1182 
1183  ASSERT(subtitle_display_set != NULL);
1184 
1185  if ((subtitle_display_set->page_display_buffer->region_list != NULL) &&
1186  (subtitle_display_set->page_display_buffer->display_set_shown) &&
1187  (!subtitle_display_set->page_display_buffer->display_set_removed))
1188  {
1189  difference_seconds = (STB_OSGetClockDiff(subtitle_display_set->page_display_buffer->timeout_start) / 1000) + 1;
1190 
1191  if ((subtitle_display_set->page_display_buffer->page_time_out <= difference_seconds) || timeout_override)
1192  {
1193  // Clear display set
1194  STB_TIMING_PRINT((" CheckDisplay, cleared OSD"));
1195  HideAllShownRegions(subtitle_display_set->page_display_buffer->region_list);
1196  subtitle_display_set->page_display_buffer->display_set_removed = TRUE;
1198  }
1199  }
1200 
1201  FUNCTION_FINISH(STB_DSCheckDisplaySetTimeout);
1202 }
1203 
1216 void STB_DSDisplay(U8BIT path, S_DISPLAY_SET *subtitle_display_set )
1217 {
1218  FUNCTION_START(STB_DSDisplay);
1219 
1220  ASSERT(subtitle_display_set != NULL);
1221 
1222  if (!subtitle_display_set->page_composition_buffer->display_set_shown)
1223  {
1224  /* Set display size so that subtitle regions can be scaled correctly */
1225  STB_OSDSetRegionDisplaySize(subtitle_display_set->page_composition_buffer->display_width + 1,
1226  subtitle_display_set->page_composition_buffer->display_height + 1);
1227 
1228  LoadPalettesIntoRegions(subtitle_display_set->region_list, subtitle_display_set->clut_list);
1229 
1230  MoveRegions(subtitle_display_set->page_composition_buffer->region_list);
1231 
1232  if (WaitToDisplay(path, subtitle_display_set->page_display_buffer,
1233  subtitle_display_set->page_composition_buffer))
1234  {
1235  UpdateDisplaySet(path, subtitle_display_set);
1236  }
1237  }
1238 
1239  FUNCTION_FINISH(STB_DSDisplay);
1240 }
1241 
1254 void STB_DSRegisterCharRenderFunction(void (*DSCreateBitmap)(U8BIT *bitmap, U16BIT width, U16BIT height, U8BIT *char_array,
1255  U8BIT *tycrcb_palette, U8BIT fgnd_col, U8BIT bkgnd_col))
1256 {
1257  FUNCTION_START(STB_DSRegisterCharRenderFunction);
1258 
1259  ASSERT(DSCreateBitmap != NULL);
1260 
1261  CreateBitmapCallback = DSCreateBitmap;
1262 
1263  FUNCTION_FINISH(STB_DSRegisterCharRenderFunction);
1264 }
1265 
1277 void STB_DSShow(void)
1278 {
1279  FUNCTION_START(STB_DSShow);
1280 
1281  show_subtitles = TRUE;
1282  time_diff_set = FALSE;
1284 
1285  FUNCTION_FINISH(STB_DSShow);
1286 }
1287 
1299 void STB_DSHide(void)
1300 {
1301  FUNCTION_START(STB_DSHide);
1302 
1303  show_subtitles = FALSE;
1304  time_diff_set = FALSE;
1306 
1307  FUNCTION_FINISH(STB_DSHide);
1308 }
1309 
1322 {
1323  S_PHYSICAL_REGION *physical_region;
1324  S_PHYSICAL_REGION *temp;
1325 
1326  FUNCTION_START(STB_DSResetPhysicalDisplayRegions);
1327 
1328  physical_region = physical_display_region_list;
1329  while (physical_region != NULL)
1330  {
1331  STB_DISPLAY_PRINT((" STB_DSResetPhysicalDisplayRegions pr%d %x", physical_region->region_id,
1332  physical_region->handle));
1333  STB_OSDDestroyRegion(physical_region->handle);
1334  temp = physical_region->next;
1335  STB_FreeMemory(physical_region);
1336  physical_region = temp;
1337  }
1338  physical_display_region_list = NULL;
1339 
1340  FUNCTION_FINISH(STB_DSResetPhysicalDisplayRegions);
1341 }
1342 
1355 {
1356  S_PHYSICAL_REGION *physical_region;
1357  S_PHYSICAL_REGION *temp;
1358 
1359  FUNCTION_START(STB_DSResetPhysicalCompositionRegions);
1360 
1361  physical_region = physical_composition_region_list;
1362  while (physical_region != NULL)
1363  {
1364  STB_DISPLAY_PRINT((" STB_DSResetPhysicalCompositionRegions pr%d %x", physical_region->region_id,
1365  physical_region->handle));
1366  STB_OSDDestroyRegion(physical_region->handle);
1367  temp = physical_region->next;
1368  STB_FreeMemory(physical_region);
1369  physical_region = temp;
1370  }
1371  physical_composition_region_list = NULL;
1372 
1373  FUNCTION_FINISH(STB_DSResetPhysicalCompositionRegions);
1374 }
1375 
1388 {
1389  FUNCTION_START(STB_DSTerminateDisplayCycle);
1390 
1391  terminate_subtitles = TRUE;
1392 
1393  FUNCTION_FINISH(STB_DSTerminateDisplayCycle);
1394 }
1395 
1410 {
1411  //The physical region to be used for the specified epoch region
1412  S_PHYSICAL_REGION *physical_region = NULL;
1413  //Pointer to existing, older, region if one exists
1414  S_PHYSICAL_REGION *reference_region = NULL;
1415 
1416 
1417  FUNCTION_START(STB_DSCreateCompositionRegion);
1418 
1419  ASSERT(region != NULL);
1420 
1421  if (page_reset)
1422  {
1423  //Not using anything old!
1424  physical_region = NULL;
1425  }
1426  else
1427  {
1428  //Look in what's currently being displayed
1429  physical_region = physical_display_region_list;
1430  }
1431 
1432  while (physical_region != NULL)
1433  {
1434  if (physical_region->region_id == region->region_id)
1435  {
1436  reference_region = physical_region;
1437  break;
1438  }
1439  physical_region = physical_region->next;
1440  }
1441 
1442  if ((physical_region != NULL) &&
1443  ((physical_region->region_width != region->region_width) ||
1444  (physical_region->region_height != region->region_height) ||
1445  (physical_region->region_colour_depth != region->region_colour_depth)))
1446  {
1447  //We found an old region that has incompatible parameters
1448  //This is a sign that we've missed a mode change / acquisition point that we needed
1449  //Or the stream didn't supply one...
1450  STB_ERROR_PRINT(("!! STB_DSCreateCompositionRegion - SIZE MISMATCH %s @ %d !!",
1451  __FILE__, __LINE__));
1452  //Make a new one!
1453  physical_region = NULL;
1454  //Don't copy from the old one
1455  reference_region = NULL;
1456  }
1457 
1458  if ((physical_region == NULL) ||
1459  (physical_region->region_version_number != region->region_version_number))
1460  {
1461  // We're going to need a new region, either because no previous one existed,
1462  // OR we're going to need a new region due to a new version
1463  // OR old (illegal) one was the wrong size
1464 
1465  physical_region = (S_PHYSICAL_REGION *)STB_GetMemory(sizeof(S_PHYSICAL_REGION));
1466 
1467  if (physical_region != NULL)
1468  {
1469  physical_region->handle = STB_OSDCreateRegion(region->region_width,
1470  region->region_height,
1471  region->region_colour_depth);
1472 
1473  if (physical_region->handle != 0)
1474  {
1475  physical_region->next = physical_composition_region_list;
1476  physical_composition_region_list = physical_region;
1477 
1478  physical_region->region_id = region->region_id;
1479  physical_region->region_version_number = region->region_version_number;
1480  physical_region->region_width = region->region_width;
1481  physical_region->region_height = region->region_height;
1482  physical_region->region_colour_depth = region->region_colour_depth;
1483 
1484  physical_region->current_x = 0;
1485  physical_region->current_y = 0;
1486 
1487  physical_region->visible = FALSE;
1488 
1489  if (region->region_fill_flag)
1490  {
1491  //We're using a fresh region, which we need to fill
1492  STB_DISPLAY_PRINT((" STB_DSCreateCompositionRegion pr%d (%dx%d) NEW %x - FILL",
1493  region->region_id, region->region_width, region->region_height,
1494  physical_region->handle));
1495  switch (region->region_colour_depth)
1496  {
1497  case 2:
1498  STB_DSFillRegion(region->region_id, region->region_2_bit_pixel_code);
1499  break;
1500  case 4:
1501  STB_DSFillRegion(region->region_id, region->region_4_bit_pixel_code);
1502  break;
1503  case 8:
1504  STB_DSFillRegion(region->region_id, region->region_8_bit_pixel_code);
1505  break;
1506  }
1507  // Don't fill again
1508  region->region_fill_flag = FALSE;
1509  }
1510  //Now did we have an original region (whose data we need to copy over)?
1511  else if (reference_region != NULL)
1512  {
1513  STB_DISPLAY_PRINT((" STB_DSCreateCompositionRegion r%d (%dx%d) Copy %x <- %x",
1514  region->region_id, region->region_width, region->region_height,
1515  physical_region->handle, reference_region->handle));
1516  STB_OSDRegionToRegionCopy(physical_region->handle, reference_region->handle);
1517  }
1518  else
1519  {
1520  STB_DISPLAY_PRINT((" STB_DSCreateCompositionRegion pr%d (%dx%d) NEW %x - no fill",
1521  region->region_id, region->region_width, region->region_height,
1522  physical_region->handle));
1523  }
1524  //else - We didn't need to fill the new region
1525  }
1526  else
1527  {
1528  // Couldn't get OSD resource
1529  STB_FreeMemory(physical_region);
1530  physical_region = NULL;
1531  STB_ERROR_PRINT(("!! STB_DSCreateCompositionRegion - STB_OSDCreateRegion failed %s @ %d !!",
1532  __FILE__, __LINE__));
1533  }
1534  }
1535  else
1536  {
1537  // Couldn't get OSD resource
1538  STB_ERROR_PRINT(("!! STB_DSCreateCompositionRegion - STB_GetMemory failed %s @ %d !!",
1539  __FILE__, __LINE__));
1540  }
1541  }
1542  else
1543  {
1544  physical_region->region_version_number = region->region_version_number;
1545 
1546  STB_DISPLAY_PRINT((" STB_DSCreateCompositionRegion pr%d (%dx%d) Reuse",
1547  region->region_id, region->region_width, region->region_height));
1548 
1549  //Move region over to the composition list
1550  remove_entry_from_list(physical_region, &physical_display_region_list);
1551  physical_region->next = physical_composition_region_list;
1552  physical_composition_region_list = physical_region;
1553  }
1554 
1555  FUNCTION_FINISH(STB_DSCreateCompositionRegion);
1556 }
1557 
1576 void STB_DSRenderBitmapToRegion(S_EPOCH_REGION *region_list, S_OBJECT *object, U8BIT *bitmap,
1577  U16BIT y, U16BIT w, U16BIT h)
1578 {
1579  S_PHYSICAL_REGION *physical_composition_region;
1582  U32BIT size;
1583  U8BIT *region_adjusted_bitmap;
1584 
1585  FUNCTION_START(STB_DSRenderBitmapToRegion);
1586 
1587  ASSERT(object != NULL);
1588  ASSERT(bitmap != NULL);
1589 
1590  region_adjusted_bitmap = NULL;
1591 
1592  region = region_list;
1593  while (region)
1594  {
1595  region_object = region->region_object_list;
1596  while (region_object)
1597  {
1598  if (region_object->object_id == object->object_id)
1599  {
1600  physical_composition_region = physical_composition_region_list;
1601  while (physical_composition_region != NULL)
1602  {
1603  if (physical_composition_region->region_id == region->region_id)
1604  {
1605  switch (physical_composition_region->region_colour_depth)
1606  {
1607  case 2:
1608  {
1609  size = (h * (w + 4)) / 4;
1610  region_adjusted_bitmap = STB_GetMemory(size);
1611 
1612  ColourDepthAdjustTo2Bits(&region_adjusted_bitmap, bitmap, w, h);
1613  break;
1614  }
1615 
1616  case 4:
1617  {
1618  size = (h * (w + 2)) / 2;
1619  region_adjusted_bitmap = STB_GetMemory(size);
1620 
1621  ColourDepthAdjustTo4Bits(&region_adjusted_bitmap, bitmap, w, h);
1622  break;
1623  }
1624 
1625  case 8:
1626  {
1627  region_adjusted_bitmap = bitmap;
1628  break;
1629  }
1630  }
1631 
1632  if ((region_object->object_horizontal_position < physical_composition_region->region_width) &&
1633  (region_object->object_vertical_position + y < physical_composition_region->region_height))
1634  {
1635  if ((region_object->object_horizontal_position + w) > physical_composition_region->region_width)
1636  {
1637  STB_DISPLAY_PRINT((" o%d Truncate w - %d + %d > %d ==> %d",
1638  object->object_id,
1639  region_object->object_horizontal_position,
1640  w,
1641  physical_composition_region->region_width,
1642  physical_composition_region->region_width - region_object->object_horizontal_position));
1643 
1644  w = physical_composition_region->region_width - region_object->object_horizontal_position;
1645  }
1646 
1647  if ((region_object->object_vertical_position + h) > physical_composition_region->region_height)
1648  {
1649  STB_DISPLAY_PRINT((" o%d Truncate h - %d + %d > %d ==> %d",
1650  object->object_id,
1651  region_object->object_vertical_position,
1652  h,
1653  physical_composition_region->region_height,
1654  physical_composition_region->region_height - region_object->object_vertical_position));
1655 
1656  h = physical_composition_region->region_height - region_object->object_vertical_position;
1657  }
1658 
1659  if ((y < physical_composition_region->region_height) &&
1660  ((region_object->object_vertical_position + y) < physical_composition_region->region_height))
1661  {
1662  if ((region_object->object_vertical_position + y + h) >
1663  physical_composition_region->region_height)
1664  {
1665  h = (region_object->object_vertical_position + y + h) -
1666  physical_composition_region->region_height;
1667  }
1668 
1669  if (h > 0)
1670  {
1671  physical_composition_region->region_version_number = region->region_version_number;
1672 
1673  STB_OSDDrawBitmapInRegion(physical_composition_region->handle,
1674  region_object->object_horizontal_position,
1675  region_object->object_vertical_position + y,
1676  w,
1677  h,
1678  region_adjusted_bitmap,
1679  object->non_modifying_colour_flag);
1680  }
1681  }
1682  else
1683  {
1684  STB_DISPLAY_PRINT((" o%d Out of region's height", object->object_id));
1685  }
1686  }
1687  else
1688  {
1689  STB_DISPLAY_PRINT((" o%d Outside of region", object->object_id));
1690  }
1691 
1692  if ((physical_composition_region->region_colour_depth == 2) ||
1693  (physical_composition_region->region_colour_depth == 4))
1694  {
1695  STB_FreeMemory(region_adjusted_bitmap);
1696  }
1697  break;
1698  }
1699  physical_composition_region = physical_composition_region->next;
1700  }
1701  }
1702  region_object = region_object->next;
1703  }
1704  region = region->next;
1705  }
1706 
1707  FUNCTION_FINISH(STB_DSRenderBitmapToRegion);
1708 }
1709 
1722 void STB_DSFillRegion(U16BIT region_id, U8BIT fillcode)
1723 {
1724  S_PHYSICAL_REGION *physical_composition_region;
1725 
1726 
1727  FUNCTION_START(STB_DSFillRegion);
1728 
1729  physical_composition_region = physical_composition_region_list;
1730  while (physical_composition_region != NULL)
1731  {
1732  if (physical_composition_region->region_id == region_id)
1733  {
1734  STB_DISPLAY_PRINT((" STB_DSFillRegion r%d (%x) with %d",
1735  region_id, physical_composition_region->handle, fillcode));
1736  STB_OSDFillRegion(physical_composition_region->handle, fillcode);
1737  break;
1738  }
1739  physical_composition_region = physical_composition_region->next;
1740  }
1741 
1742  FUNCTION_FINISH(STB_DSFillRegion);
1743 }
1744 
1756 U32BIT STB_DSNumPixelOperations(S_DISPLAY_SET *subtitle_display_set)
1757 {
1758  S_EPOCH_REGION *temp;
1759  S_REGION *tmp;
1760  U32BIT pixel_operations;
1761 
1762 
1763  FUNCTION_START(STB_DSNumPixelOperations);
1764 
1765  pixel_operations = 0;
1766 
1767  // removal of existing display set
1768  tmp = subtitle_display_set->page_display_buffer->region_list;
1769  while (tmp != NULL)
1770  {
1771  temp = subtitle_display_set->region_list;
1772  while (temp != NULL)
1773  {
1774  if (tmp->region_id == temp->region_id)
1775  {
1776  pixel_operations += temp->region_width * temp->region_height * temp->region_colour_depth;
1777  break;
1778  }
1779  temp = temp->next;
1780  }
1781  tmp = tmp->next;
1782  }
1783 
1784  // displaying of new display set
1785  tmp = subtitle_display_set->page_composition_buffer->region_list;
1786  while (tmp != NULL)
1787  {
1788  temp = subtitle_display_set->region_list;
1789  while (temp != NULL)
1790  {
1791  if (tmp->region_id == temp->region_id)
1792  {
1793  pixel_operations += temp->region_width * temp->region_height * temp->region_colour_depth;
1794  break;
1795  }
1796  temp = temp->next;
1797  }
1798  tmp = tmp->next;
1799  }
1800 
1801  FUNCTION_FINISH(STB_DSNumPixelOperations);
1802 
1803  return(pixel_operations);
1804 }
1805 
1806 static void remove_entry_from_list(S_PHYSICAL_REGION *entry, S_PHYSICAL_REGION **list)
1807 {
1808  S_PHYSICAL_REGION *itor;
1809 
1810  if (*list == entry)
1811  {
1812  *list = entry->next;
1813  }
1814  else
1815  {
1816  itor = *list;
1817 
1818  while ((itor != NULL) && (itor->next != entry))
1819  {
1820  itor = itor->next;
1821  }
1822 
1823  if (itor != NULL)
1824  {
1825  itor->next = entry->next;
1826  }
1827  else
1828  {
1829  STB_ERROR_PRINT(("Couldn't find entry %d in list %s @ %d",
1830  entry->region_id, __FILE__, __LINE__));
1831  }
1832  }
1833 }
1834 
1835 #ifdef STB_DISPLAY_PRINT_REQUIRED
1836 void dump_physical_regions(const char *label)
1837 {
1839 
1840  FUNCTION_START(dump_physical_regions);
1841 
1842  STB_DISPLAY_PRINT(("%s - Dump OSD resources\n Display", label));
1843  region = physical_display_region_list;
1844  while (region != NULL)
1845  {
1846  STB_DISPLAY_PRINT((" r%d (v%d) (w%d h%d d%d) @ (%d %d) %c",
1847  (int) region->region_id,
1848  (int) region->region_version_number,
1849  (int) region->region_width,
1850  (int) region->region_height,
1851  (int) region->region_colour_depth,
1852  (int) region->current_x,
1853  (int) region->current_y,
1854  (region->visible ? 'V' : '.')));
1855  region = region->next;
1856  }
1857  STB_DISPLAY_PRINT((" <END>\n Composition"));
1858  region = physical_composition_region_list;
1859  while (region != NULL)
1860  {
1861  STB_DISPLAY_PRINT((" r%d (v%d) (w%d h%d d%d) @ (%d %d) %c",
1862  (int) region->region_id,
1863  (int) region->region_version_number,
1864  (int) region->region_width,
1865  (int) region->region_height,
1866  (int) region->region_colour_depth,
1867  (int) region->current_x,
1868  (int) region->current_y,
1869  (region->visible ? 'v' : '.')));
1870  region = region->next;
1871  }
1872  STB_DISPLAY_PRINT((" <END>"));
1873 
1874  FUNCTION_FINISH(dump_physical_regions);
1875 }
1876 
1877 #endif
1878 
1879 //*****************************************************************************
1880 // End of file
1881 //*****************************************************************************
1882 
1883 
void STB_DSResetPhysicalCompositionRegions(void)
Deletes all regions and clears serice_aquired flag.
Definition: stbdsdis.c:1354
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
void STB_DSRenderBitmapToRegion(S_EPOCH_REGION *region_list, S_OBJECT *object, U8BIT *bitmap, 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
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
U32BIT STB_OSGetClockDiff(U32BIT timestamp)
Get Difference between Given Time and Current Time.
Header file - macros and function prototypes for public use.
void STB_OSDUpdateRegions(void)
Updates the display of all subtitle regions.
Header file - Function prototypes for OSD control.
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
void STB_OSDFillRegion(void *handle, U8BIT colour)
Fill a region with a colour.
Header file - Function prototypes for A/V control.
BOOLEAN STB_OSDDisableUIRegion(void)
Disables (makes invisible) the OSD. This function needs to be implemented on platforms that cannot di...
void STB_DSTerminateDisplayCycle(void)
Sets flag to exit display wait while loop.
Definition: stbdsdis.c:1387
void STB_DSShow(void)
Allows subtitles to display what it has decoded.
Definition: stbdsdis.c:1277
void STB_DSHide(void)
Prevents subtitles to display what it has decoded.
Definition: stbdsdis.c:1299
Header file - Function prototypes for DVB subtitles.
void STB_DSCheckDisplaySetTimeout(S_DISPLAY_SET *subtitle_display_set, BOOLEAN timeout_override)
It checks the timeout of the current display set, and removes if/when necessary.
Definition: stbdsdis.c:1177
Definition: stbds.h:51
void STB_OSDShowRegion(void *handle)
Makes a region visible.
void STB_OSDSetYCrCbPalette(void *region_handle, U32BIT *tycrcb)
Sets a regions entire palette to a T,Y,CR,CB clut.
void STB_OSDDrawBitmapInRegion(void *handle, U16BIT x, U16BIT y, U16BIT w, U16BIT h, U8BIT *bitmap, BOOLEAN non_modifying_colour)
Draw a bitmap in a specified region.
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
Debug functions header file.
void STB_DSFillRegion(U16BIT region_id, U8BIT fillcode)
Flood fills the identified region, with the specified colour index.
Definition: stbdsdis.c:1722
Definition: stbds.h:75
U32BIT STB_DSNumPixelOperations(S_DISPLAY_SET *subtitle_display_set)
Calculates the number of individual pixels in volved in the next display set.
Definition: stbdsdis.c:1756
void STB_DSResetPhysicalDisplayRegions(void)
Deletes all regions and clears serice_aquired flag.
Definition: stbdsdis.c:1321
void STB_DSDisplay(U8BIT path, S_DISPLAY_SET *subtitle_display_set)
The subtitle display function. Provides timing of display and clean up when necessary.
Definition: stbdsdis.c:1216
void STB_OSDMoveRegion(void *handle, U16BIT x, U16BIT y)
Move a region to new coordinates.
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
Header file - Function prototypes for operating system.
System Wide Global Technical Data Type Definitions.
void * STB_OSDCreateRegion(U16BIT width, U16BIT height, U8BIT depth)
Creates a new OSD region (for subtitling)
void STB_OSDSetRegionDisplaySize(U16BIT width, U16BIT height)
Should be called to set the size of the display so that SD subtitles can be scaled correctly for an H...
Header file - Function prototypes for heap memory.
void STB_OSDHideRegion(void *handle)
Makes a region invisible.
void STB_OSDDestroyRegion(void *handle)
Destroys (free the resources used by) a region.
void STB_OSTaskDelay(U16BIT timeout)
Delay Task for Specifed Time Period.
BOOLEAN STB_OSDEnableUIRegion(void)
Disables (makes invisible) the OSD. This function needs to be implemented on platforms that cannot di...
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
void STB_DSRegisterCharRenderFunction(void(*DSCreateBitmap)(U8BIT *bitmap, U16BIT width, U16BIT height, U8BIT *char_array, U8BIT *tycrcb_palette, U8BIT fgnd_col, U8BIT bkgnd_col))
Registers a STBUI function to use whatever font tool is present [if any] for the creation of a bitmap...
Definition: stbdsdis.c:1254
Definition: stbds.h:126
void STB_OSDRegionToRegionCopy(void *handle_new, void *handle_orig)
Copy a region to another region, including palette.