MHEG5  18.9.0
MHEG5 Documentation
mh5display.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  * Copyright © 2000 Koninklijke Philips Electronics N.V
5  *
6  * This file is part of a DTVKit Software Component
7  * You are permitted to copy, modify or distribute this file subject to the terms
8  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
9  *
10  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
11  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * If you or your organisation is not a member of DTVKit then you have access
15  * to this source code outside of the terms of the licence agreement
16  * and you are expected to delete this and any associated files immediately.
17  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
18  *******************************************************************************/
29 /*---includes for this file--------------------------------------------------*/
30 #include <string.h>
31 
32 #include "mh5application.h"
33 #include "mh5base.h"
34 #include "mh5display.h"
35 #include "mh5classes.h"
36 #include "mh5queue.h"
37 #include "mh5object.h"
38 #include "mh5final.h"
39 #include "mh5drawtext.h"
40 
41 #include "mg_api.h"
42 #include "mg_video.h"
43 #include "dvb_audio.h"
44 #include "dvb_video.h"
45 
46 #include "mh5memory.h"
47 #include "mh5profile.h"
48 #include "mh5streamevent.h"
49 #include "mh5debug.h"
50 #include "tmcolor.h"
51 
52 #include "mh5dispBttnRT.h"
53 #ifdef TRACING
54 #include "mg_osd.h"
55 #endif
56 #ifdef INCLUDE_ICS
57 #include "dvb_ics.h"
58 #include "mh5streamer.h"
59 #endif
60 #include "mh5control.h" // for MHEG5NotifyServiceInfoChanged
61 #ifdef SURFACE_THRESHOLD
62 #include "glue_queue.h"
63 #endif
64 
65 /*---constant definitions for this file--------------------------------------*/
66 #define MAX_RECTS 32
67 #define DELTA_X 5
68 #define DELTA_Y 4
69 #define SIGNF_X 20
70 #define SIGNF_Y 16
71 #define IRATIO 32
72 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
73 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
74 
75 /* Check whether a multiplex reference is valid. The only value that can be
76  * checked is service_id.
77  */
78 #define MHEG5_MULTIPLEX_REF_VALID(mux) \
79  ((mux).service_id != 0 && (mux).service_id != 0xffff)
80 
81 
82 const char *stream_states[] = {
83  "STOPPED",
84  "STOPPING",
85  "STARTING",
86  "PLAYING",
87  "PLAYING_CLIP",
88  "NEW_REF",
89  "FROZEN",
90  "Error"
91 };
92 
93 /*---local typedef structs for this file-------------------------------------*/
94 
95 typedef enum
96 {
102 
103 /*---local (static) variable declarations for this file----------------------*/
104 
105 /* Flag to indicate whether there is video currently playing */
106 static MHEG5Bool videoPlaying = MHEG5FALSE;
107 
108 /* Flag to indicate whether the current video is frozen */
109 static MHEG5Bool videoFreeze = MHEG5FALSE;
110 
111 /* Flags to indicate whether there is iframe currently playing */
112 static MHEG5Bool iframePlaying = MHEG5FALSE;
113 static MHEG5Bool iframeDecoded = MHEG5FALSE;
114 
115 #ifdef INCLUDE_FREESAT
116 /* Flags to indicate whether there is iframe currently playing */
117 static MHEG5Bool imagePlanePlaying = MHEG5FALSE;
118 static MHEG5Bool imagePlaneDecoded = MHEG5FALSE;
119 
120 #endif
121 /* Multiplex reference for the currently playing Video object, and a flag to
122  * indicate that this has been updated.
123  */
124 static S_DvbComponent video_stream_ref;
125 static MHEG5Bool video_stream_changed;
126 static MHEG5Bool video_pause_changed;
127 static MHEG5Bool videoPositionChanged;
128 
129 
130 /* Indicate whether there is audio currently playing - and which type */
131 static E_AudioPlayState audioPlaying = AUDIO_PLAY_DEFAULT;
132 
133 /* Flag to indicate whether the current audio is frozen */
134 static MHEG5Bool audioFreeze = MHEG5FALSE;
135 
136 /* Multiplex reference for the currently playing Audio object, and a flag to
137  * indicate that this has been updated.
138  */
139 static S_DvbComponent audio_stream_ref;
140 static MHEG5Bool audio_stream_changed;
141 static MHEG5Bool audio_pause_changed;
142 
143 /* Current audio volume level */
144 static MHEG5Int audioVolume = 0;
145 
146 
147 static MHEG5Bool lastTerminating = MHEG5TRUE;
148 static MHEG5Bool lastVideoPlaying = MHEG5TRUE;
149 static MHEG5Bool lastVideoFreeze = MHEG5FALSE;
150 static E_AudioPlayState lastAudioPlaying = AUDIO_PLAY_STREAM;
151 static MHEG5Bool lastAudioFreeze = MHEG5FALSE;
152 
153 /* Boolean flag to indicate when any of the audio, video or rtgraphics stream
154  * settings have changed. This is used to update the media decoders only when
155  * necessary.
156  */
157 static MHEG5Bool streamSettingsChanged = MHEG5FALSE;
158 
159 
160 /* Boolean that is set to true to indicate that streams are locked and
161  * updates are disabled.
162  */
163 static MHEG5Bool displayStreamsAreLocked = MHEG5FALSE;
164 
165 /* Rectangle which describes the area of the screen that requires updating in
166  * the display.
167  */
168 static S_REGION dirtyRects[32];
169 static int numDirtyRects = 0;
170 
171 /* Hold the current video,iframe or audio object */
172 static MHEG5Bitmap *activeIframeObject = NULL;
173 #ifdef INCLUDE_FREESAT
174 static MHEG5Bitmap *activeImagePlaneObject = NULL;
175 #endif
176 static MHEG5Video *activeVideoObject = NULL;
177 static MHEG5Audio *activeAudioObject = NULL;
178 
179 #ifdef SURFACE_THRESHOLD
180 /* surface threshold */
181 static S32BIT surfaceThreshold = SURFACE_THRESHOLD;
182 #endif
183 
184 /*---local function definitions----------------------------------------------*/
185 
186 static void MHEG5displayUpdateStreamDecoders(MHEG5Bool terminating);
187 
188 /*---global function definitions---------------------------------------------*/
189 
190 #ifdef TRACING
191 static const char* SS( MHEG5Stream *stm );
192 #endif
193 
194 #ifdef TRACING
195 static const char* SS( MHEG5Stream *stm )
196 {
197  if (stm->streamState <= SS_FROZEN)
198  {
199  return stream_states[(int)stm->streamState];
200  }
201  return stream_states[(int)SS_FROZEN + 1];
202 }
203 
204 #endif
205 
211 /*
212  Generic Display Part
213  */
214 
215 
221 {
222  MHEG5Application *application;
223  MHEG5Scene *scene;
224  OSDColor desktopColour;
225  S_REGION rgn = { 0, 0, 720, 576 };
226 
227  application = MHEG5getCurrentApplication();
228  scene = MHEG5getCurrentScene();
229 
230  if ((application) && (application->group.root.runningStatus) &&
231  (scene) && (scene->group.root.runningStatus))
232  {
233  /* There is an application and a scene currently running. Clear to the
234  * MHEG-5 desktop colour
235  */
236  desktopColour = MHEG5displayColour(&application->desktopColour);
237  MG_OSDerase( rgn, desktopColour );
238  /* Update the on screen display now */
239  MG_OSDUpdate();
240  }
241  else
242  {
243  /* There is no scene running. Clear to transparent to show moving video below OSD */
244  MG_OSDclear();
245  }
246 }
247 
257 {
258  assert(colour);
259 
260  if (colour->type == MHEG5INT)
261  {
262  return (OSDColor)colour->value.i;
263  }
264 
265  /* If we have an octet string, do the conversion to an int once and cache
266  * the converted value in the MHEG5Colour variable
267  */
268  if (colour->type == MHEG5OCTETSTRING)
269  {
270  OSDColor value;
271 
272  /* Convert from string to OSDColor type */
273  value = OSDgetColour((char *)colour->value.s.data, colour->value.s.len);
274 
275  /* Destroy the string holding the colour information */
276  MHEG5stringDestruct(&colour->value.s);
277 
278  /* Cache the colour information as an integer type */
279  colour->type = MHEG5INT;
280  colour->value.i = (MHEG5Int)value;
281 
282  return value;
283  }
284 
285  /* Could get application default colour, but we don't know which one -
286  * that knowledge is with the calling function */
287  ERROR_PRINT(("ERROR: unknown colour type detected\n"));
288 
290 }
291 
298 static void MHEG5displaySlider(MHEG5Slider *slider, S_REGION *overlap)
299 {
300  OSDColor markerColour; /* Colour of the slider marker */
301  int boxX1, boxY1, boxX2, boxY2; /* Bounding box */
302  int width, height; /* Width and height of the bounding box */
303  /* in pixels */
304  int sliderPos; /* Position of slider in steps */
305  int screenPos; /* Position of slider in pixels from */
306  /* start */
307  int sliderRange; /* Distance slider moves in steps */
308  int screenRange; /* Distance slider moves in pixels */
309  int screenPortion; /* Size of proportional slider in pixels */
310  int screenMarkerSize; /* Normal Size of normal slider marker in pixels */
311 
312  assert(slider);
313 
314  /* Extract the slider dimensions (in pixels) */
315  width = slider->visible.boxSize[0];
316  height = slider->visible.boxSize[1];
317 
318  /* Calculate the bounding box for the slider */
319  boxX1 = slider->visible.position[0];
320  boxY1 = slider->visible.position[1];
321  boxX2 = boxX1 + width - 1;
322  boxY2 = boxY1 + height - 1;
323 
324  /* Fetch the thumb colour, depending on source and highlight status */
325  if (slider->interactible.highlightStatus && slider->interactible.engineResp)
326  {
327  if (slider->sliderRefColour.type == MHEG5NONE)
328  {
329  markerColour = MHEG5displayColour(&(MHEG5getCurrentApplication()->highlightRefColour));
330  }
331  else
332  {
333  markerColour = MHEG5displayColour(&slider->interactible.highlightRefColour);
334  }
335  }
336  else
337  {
338  if (slider->sliderRefColour.type == MHEG5NONE)
339  {
340  markerColour = MHEG5displayColour(&(MHEG5getCurrentApplication()->sliderRefColour));
341  }
342  else
343  {
344  markerColour = MHEG5displayColour(&slider->sliderRefColour);
345  }
346  }
347 
348  /* Calculate the range of the slider. */
349  sliderRange = slider->maxValue - slider->minValue;
350  if (sliderRange <= 0)
351  {
352  return;
353  }
354 
355  /* Check the slider position (distance from minimum) against the minimum and
356  * maximum.
357  */
358  if (slider->sliderValue < slider->minValue)
359  {
360  sliderPos = 0;
361  }
362  else if (slider->sliderValue > slider->maxValue)
363  {
364  sliderPos = sliderRange;
365  }
366  else
367  {
368  sliderPos = slider->sliderValue - slider->minValue;
369  }
370 
371  /* Determine the range (in pixels) of the slider movement */
372  switch (slider->orientation)
373  {
374  default:
375  ERROR_PRINT(("ERROR: Illegal slider orientation\n"));
376  /* fallthrough */
377 
378  case MHEG5RIGHT:
379  case MHEG5LEFT:
380  screenRange = width;
381  break;
382  case MHEG5DOWN:
383  case MHEG5UP:
384  screenRange = height;
385  break;
386  }
387 
388  /* Calculate the position of the slider (in pixels) */
389  screenPos = (sliderPos * screenRange) / sliderRange;
390 
391  switch (slider->sliderStyle)
392  {
393  /* Normal style has a position marker. This is defined as a percentage
394  * of the sliderRange.
395  */
396  case MHEG5NORMAL:
397  /* The size of the marker is given in the profile (9 pixels) */
398  screenMarkerSize = 9;
399  screenPos = (sliderPos * (screenRange - screenMarkerSize)) / sliderRange + screenMarkerSize / 2;
400 
401  switch (slider->orientation)
402  {
403  /* Draw the slider marker */
404  case MHEG5LEFT:
405  MG_OSDdisplayRectangle( overlap, boxX2 - screenPos - screenMarkerSize / 2, boxY1, screenMarkerSize,
406  height, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour );
407  break;
408  case MHEG5RIGHT:
409  MG_OSDdisplayRectangle( overlap, boxX1 + screenPos - screenMarkerSize / 2, boxY1, screenMarkerSize,
410  height, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
411  break;
412  case MHEG5DOWN:
413  MG_OSDdisplayRectangle( overlap, boxX1, boxY1 + screenPos - screenMarkerSize / 2, width,
414  screenMarkerSize, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
415  break;
416  case MHEG5UP:
417  MG_OSDdisplayRectangle( overlap, boxX1, boxY2 - screenPos - screenMarkerSize / 2, width,
418  screenMarkerSize, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour );
419  break;
420  }
421  break;
422 
423  case MHEG5THERMOMETER:
424  switch (slider->orientation)
425  {
426  /* Draw the thermometer bar (from start of slider to current
427  * value)
428  */
429  case MHEG5LEFT:
430  MG_OSDdisplayRectangle( overlap, boxX2 - screenPos + 1, boxY1, screenPos, height, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
431  break;
432  case MHEG5RIGHT:
433  MG_OSDdisplayRectangle( overlap, boxX1, boxY1, screenPos, height, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
434  break;
435  case MHEG5DOWN:
436  MG_OSDdisplayRectangle( overlap, boxX1, boxY1, width, screenPos, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
437  break;
438  case MHEG5UP:
439  MG_OSDdisplayRectangle( overlap, boxX1, boxY2 - screenPos + 1, width, screenPos, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
440  break;
441  }
442  break;
443  case MHEG5PROPORTIONAL:
444  /* Calculate the size of the portion to draw */
445  screenPortion = (slider->portion * screenRange) / sliderRange;
446  switch (slider->orientation)
447  {
448  /* Draw the portion, starting at the slider value, with the size
449  * just calculated
450  */
451  case MHEG5LEFT:
452  MG_OSDdisplayRectangle( overlap, boxX2 - screenPos - screenPortion + 1, boxY1, screenPortion, height, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
453  break;
454  case MHEG5RIGHT:
455  MG_OSDdisplayRectangle( overlap, boxX1 + screenPos, boxY1, screenPortion, height, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
456  break;
457  case MHEG5DOWN:
458  MG_OSDdisplayRectangle( overlap, boxX1, boxY1 + screenPos, width, screenPortion, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
459  break;
460  case MHEG5UP:
461  MG_OSDdisplayRectangle( overlap, boxX1, boxY2 - screenPos - screenPortion + 1, width, screenPortion, 0, /*MHEG_LINE_STYLE_SOLID,*/ markerColour, markerColour);
462  break;
463  }
464  break;
465  default:
466  ERROR_PRINT(("ERROR: Illegal slider style\n"));
467  assert(0);
468  }
469 }
470 
471 #ifdef INCLUDE_FREESAT
472 
482 static void MHEG5displayDrawImagePlane( MHEG5Visible *visible, S_REGION *overlap )
483 {
484  if (visible->ingredient.data != 0 &&
485  visible->ingredient.dataLen > 0)
486  {
487  /* This is an I-frame bitmap for which we have bitmap data.
488  * Start displaying the I-Frame data
489  */
490  if (imagePlaneDecoded == MHEG5TRUE)
491  {
492  MG_OSDdisplayVideo( *overlap );
493  }
494  else if (DVB_MhegDecodeImagePlaneIFrame( visible->ingredient.data,
495  visible->ingredient.dataLen,
497  {
498  TRACE(TSTRM, ("decoded Iframe(d=0x%p, l=%ld) OK", visible->ingredient.data, visible->ingredient.dataLen));
499  /* Display video only if updated the I-Frame successfully, or not
500  * updated at all.
501  */
502  imagePlaneDecoded = MHEG5TRUE;
503  MG_OSDdisplayVideo( *overlap );
504  }
505  else
506  {
507  TRACE(TERROR, ("(d=0x%p, l=%ld)", visible->ingredient.data, visible->ingredient.dataLen))
508  }
509  }
510 }
511 
512 #endif
513 
524 static void MHEG5displayDraw( MHEG5Visible *visible, S_REGION *overlap )
525 {
526  MHEG5Video *video;
527 
528  assert(visible);
529 
530  TRACE(TGRAPHICS, ("box=(%d,%d,%d,%d) id=%ld clz=%d gd=%p", overlap->left, overlap->top, overlap->right, overlap->bottom,
531  ((MHEG5Root *)visible)->id, ((MHEG5Root *) visible)->clazz, visible->graphic_data))
532  switch (((MHEG5Root *) visible)->clazz)
533  {
534  case MHEG5BITMAP:
535  {
536  E_VideoEncoding encoding = VIDEO_ENC_MPEG2;
537  switch (visible->ingredient.contentHook)
538  {
539  case CHOOK_BITMAP_PNG:
540  if (visible->graphic_data == NULL)
541  {
542  MG_DrawPng( visible->ingredient.data, visible->ingredient.dataLen, visible );
543  }
544  if (visible->graphic_data != NULL)
545  {
546  MG_OSDdisplayBitmap( visible, overlap );
547  }
548  break;
549 
550  case CHOOK_BITMAP_JPG:
551  if (visible->graphic_data == NULL)
552  {
553  MG_DrawJpg( visible->ingredient.data, visible->ingredient.dataLen, visible );
554  }
555  if (visible->graphic_data != NULL)
556  {
557  MG_OSDdisplayBitmap( visible, overlap );
558  }
559  break;
560 
562  encoding = VIDEO_ENC_H_264;
563  /* fallthrough */
564 
566  /* Display I-frame format */
567  if (visible->ingredient.data != 0 &&
568  visible->ingredient.dataLen > 0)
569  {
570  /* This is an I-frame bitmap for which we have bitmap data.
571  * Start displaying the I-Frame data
572  */
573  if (iframeDecoded == MHEG5TRUE)
574  {
575  MG_OSDdisplayVideo( *overlap );
576  }
577  else if (visible->ingredient.data && visible->ingredient.dataLen)
578  {
580  visible->ingredient.dataLen,
581  encoding ) == MHERR_OK)
582  {
583  TRACE(TSTRM, ("decoded Iframe(d=0x%p, l=%ld enc=%d) OK", visible->ingredient.data, visible->ingredient.dataLen, encoding))
584  /* Display video only if updated the I-Frame successfully, or not
585  * updated at all.
586  */
587  iframeDecoded = MHEG5TRUE;
588  MG_OSDdisplayVideo( *overlap );
589  }
590  else
591  {
592  TRACE(TERROR, ("(d=0x%p, l=%ld enc=%d)", visible->ingredient.data, visible->ingredient.dataLen, encoding))
593  }
594  }
595  }
596  default:;
597  }
598  }
599  break;
600 
601  case MHEG5TEXT:
602  {
603  if (visible->graphic_data == NULL)
604  {
605  MHEG5drawText((MHEG5Text *)visible );
606  }
607  MH5_DisplayText((MHEG5Text *)visible, overlap);
608  #ifdef SURFACE_THRESHOLD
609  MG_ApplySurfaceThreshold(&visible->graphic_data, surfaceThreshold);
610  #endif
611  }
612  break;
613 
614  case MHEG5HYPERTEXT:
615  {
616  if (visible->graphic_data == NULL)
617  {
618  MHEG5drawHypertext((MHEG5Hypertext *)visible );
619  }
620  MH5_DisplayText((MHEG5Text *)visible, overlap);
621  #ifdef SURFACE_THRESHOLD
622  MG_ApplySurfaceThreshold(&visible->graphic_data, surfaceThreshold);
623  #endif
624  }
625  break;
626 
627  case MHEG5ENTRYFIELD:
628  {
629  if (visible->graphic_data == NULL)
630  {
632  }
633  MH5_DisplayEntry((MHEG5Entryfield *)visible, overlap);
634  #ifdef SURFACE_THRESHOLD
635  MG_ApplySurfaceThreshold(&visible->graphic_data, surfaceThreshold);
636  #endif
637  }
638  break;
639 
640  case MHEG5RECTANGLE:
641  MG_OSDdisplayRectangle( overlap, visible->rect.left, visible->rect.top,
642  visible->rect.right - visible->rect.left, visible->rect.bottom - visible->rect.top,
643  ((MHEG5Lineart *) visible)->lineWidth, /*((MHEG5Lineart *) visible)->lineStyle,*/
644  MHEG5displayColour(&((MHEG5Lineart *) visible)->refLineColour),
645  MHEG5displayColour(&((MHEG5Lineart *) visible)->refFillColour));
646  break;
647 
648  case MHEG5SLIDER:
649  MHEG5displaySlider((MHEG5Slider *)visible, overlap );
650  break;
651 
652  case MHEG5DYNAMICLINEART:
653  MG_OSDdisplayDynamicLineart( visible->graphic_data, overlap, visible->position[0], visible->position[1] );
654  break;
655 
656  case MHEG5VIDEO:
657  video = (MHEG5Video *)visible;
658  if (((MHEG5Root *)video->parent)->runningStatus)
659  {
660  MG_OSDdisplayVideo( *overlap );
661  }
662  break;
663 
664 #ifndef MHEG5PROFILE_UK1_06
665  case MHEG5LINEART:
666  MHEG5displayLineart(visible->position[0], visible->position[1], left, top, right, bottom,
667  ((MHEG5Lineart *) visible)->borderedBoundingBox,
668  ((MHEG5Lineart *) visible)->originalLineWidth,
669  ((MHEG5Lineart *) visible)->originalLineStyle,
670  &((MHEG5Lineart *) visible)->originalRefLineColour,
671  &((MHEG5Lineart *) visible)->originalRefFillColour);
672  break;
673  case MHEG5HOTSPOT:
674  MHEG5displayHotspot(visible, left, top, right, bottom);
675  break;
676  case MHEG5SWITCHBUTTON:
677  MHEG5displaySwitchbutton(visible, left, top, right, bottom);
678  break;
679  case MHEG5PUSHBUTTON:
680  MHEG5displayPushbutton(visible, left, top, right, bottom);
681  break;
682  case MHEG5RTGRAPHICS:
683  MHEG5displayRTGraphics((MHEG5RTGraphics *)visible, left, top, right, bottom);
684  break;
685 #endif
686 
687  default:
688  break;
689  }
690 
691 }
692 
693 static void AddExtraRect( S_REGION rect, int cur )
694 {
695  int i;
696  for (i = 0; i != cur; i++)
697  {
698  if (dirtyRects[i].right == 0)
699  {
700  /* free slot */
701  TRACE(TGRAPHICS, ("changed box[%d]=(%d,%d,%d,%d)", i, rect.left, rect.top, rect.right, rect.bottom))
702  dirtyRects[i] = rect;
703  if (numDirtyRects <= i)
704  {
705  numDirtyRects = i+1;
706  }
707  break;
708  }
709  }
710  while (numDirtyRects != 0 && dirtyRects[numDirtyRects - 1].right == 0)
711  {
712  numDirtyRects--;
713  }
714  if (i == cur)
715  {
716  if (numDirtyRects == MAX_RECTS)
717  {
718  /* Oh dear - too many ! */
719  MHEG5Scene *scene = MHEG5getCurrentScene();
720  dirtyRects[0].left = 0;
721  dirtyRects[0].top = 0;
722  dirtyRects[0].right = (S16BIT)scene->sceneCoordinateSystem[0];
723  dirtyRects[0].bottom = (S16BIT)scene->sceneCoordinateSystem[1];
724  numDirtyRects = 1;
725  }
726  else
727  {
728  TRACE(TGRAPHICS, ("added new box[%d]=(%d,%d,%d,%d)", numDirtyRects, rect.left, rect.top, rect.right, rect.bottom))
729  assert( rect.right > rect.left && rect.bottom > rect.top );
730  dirtyRects[numDirtyRects] = rect;
731  numDirtyRects++;
732  }
733  }
734 }
735 
737 {
738  MHEG5Scene *scene = MHEG5getCurrentScene();
739  S_REGION rect;
740 
741  assert(visible);
742 
743  rect.left = (S16BIT)visible->position[0];
744  rect.top = (S16BIT)visible->position[1];
745  rect.right = rect.left + (S16BIT)visible->boxSize[0];
746  rect.bottom = rect.top + (S16BIT)visible->boxSize[1];
747  if (rect.right < 0)
748  rect.right = 0;
749  if (rect.bottom < 0)
750  rect.bottom = 0;
751  if (rect.left < 0)
752  rect.left = 0;
753  if (rect.top < 0)
754  rect.top = 0;
755 
756  /* Should only be drawing items which are running, or starting to run,
757  * or still running but about to be hidden */
758  if (!((MHEG5Root *)visible)->runningStatus)
759  {
760  TRACE(TERROR, ("Item is not visible! upd=%d, clz=%d id=%ld", upd, ((MHEG5Root *)visible)->clazz, ((MHEG5Root *)visible)->id))
761  }
762 
763  if (!scene)
764  {
765  /* use standard coordinates */
766  if (rect.right > SD_WIDTH)
767  rect.right = SD_WIDTH;
768  if (rect.bottom > SD_HEIGHT)
769  rect.bottom = SD_HEIGHT;
770  if (!upd)
771  {
772  /* save the rect */
773  visible->rect = rect;
774  }
775  numDirtyRects = 0;
776  return;
777  }
778 
779  if (rect.right > scene->sceneCoordinateSystem[0])
780  rect.right = (S16BIT)scene->sceneCoordinateSystem[0];
781  if (rect.bottom > scene->sceneCoordinateSystem[1])
782  rect.bottom = (S16BIT)scene->sceneCoordinateSystem[1];
783  if (!upd)
784  {
785  /* save the rect */
786  visible->rect = rect;
787  }
788 
789  if ((rect.top == 0 && rect.left == 0 &&
790  rect.right == (S16BIT)scene->sceneCoordinateSystem[0] &&
791  rect.bottom == (S16BIT)scene->sceneCoordinateSystem[1]) ||
792  numDirtyRects == MAX_RECTS)
793  {
794  /* set first rectangle to cover the entire screen */
795  dirtyRects[0].left = 0;
796  dirtyRects[0].top = 0;
797  dirtyRects[0].right = (S16BIT)scene->sceneCoordinateSystem[0];
798  dirtyRects[0].bottom = (S16BIT)scene->sceneCoordinateSystem[1];
799  numDirtyRects = 1;
800 
801  TRACE(TGRAPHICS, ("screen box=(%d,%d,%d,%d)",
802  dirtyRects[0].left, dirtyRects[0].top, dirtyRects[0].right, dirtyRects[0].bottom))
803  }
804  else if ((rect.left < rect.right) && (rect.top < rect.bottom))
805  {
806  S_REGION *pRect;
807  int i, d_rects, sav, expanded;
808 
809  d_rects = numDirtyRects;
810  do
811  {
812  pRect = dirtyRects;
813  expanded = 0;
814  for (i = 0; i != d_rects; i++, pRect++)
815  {
816  assert( pRect->right == 0 || (pRect->right > pRect->left && pRect->bottom > pRect->top));
817  if (pRect->right > rect.left && rect.right > pRect->left &&
818  pRect->bottom > rect.top && rect.bottom > pRect->top)
819  {
820  /* there is an intersection */
821  if (rect.right <= pRect->right)
822  {
823  if (rect.left >= pRect->left)
824  {
825  /*new one is within old one in x-directn*/
826  if (rect.bottom <= pRect->bottom)
827  {
828  if (rect.top >= pRect->top)
829  {
830  /* new is Completely inside - no need to add this one */
831  return;
832  }
833  else /* new only intersects on top edge of old */
834  if (rect.top + SIGNF_Y > pRect->top ||
835  (rect.right - rect.left) * 2 > (pRect->right - pRect->left))
836  {
837  /* Expand to engulf old */
838  rect.right = pRect->right;
839  rect.left = pRect->left;
840  rect.bottom = pRect->bottom;
841  pRect->right = 0;
842  expanded = 1;
843  }
844  else
845  {
846  rect.bottom = pRect->top; /* reduce to bit outside old */
847  }
848  }
849  else /* rect.bottom > pRect->bottom */
850  {
851  if (rect.top < pRect->top)
852  {
853  /* new stradles top and bottom edges of old */
854  if ((rect.top + SIGNF_Y > pRect->top && rect.bottom < pRect->bottom + SIGNF_Y) ||
855  (rect.right - rect.left) * 2 > (pRect->right - pRect->left))
856  {
857  /* Expand to engulf old */
858  rect.right = pRect->right;
859  rect.left = pRect->left;
860  pRect->right = 0;
861  expanded = 1;
862  }
863  else
864  {
865  /* create extra box from dividing up old */
866  sav = pRect->right;
867  if (rect.right != sav)
868  {
869  if (rect.left != pRect->left)
870  {
871  pRect->right = rect.left;
872  AddExtraRect( *pRect, i );
873  pRect->right = sav;
874  pRect->left = rect.right;
875  }
876  else
877  {
878  pRect->left = rect.right;
879  }
880  }
881  else
882  {
883  if (rect.left != pRect->left)
884  {
885  pRect->right = rect.left;
886  }
887  else
888  {
889  /* new completely surrounds old - need to remove old one */
890  pRect->right = 0;
891  }
892  }
893  }
894  }
895  else /* rect.bottom > pRect->bottom && rect.top >= pRect->top */
896  {
897  /* new only intersects on bottom edge of old */
898  if (rect.bottom < pRect->bottom + SIGNF_Y ||
899  (rect.right - rect.left) * 2 > (pRect->right - pRect->left))
900  {
901  /* Expand to engulf old */
902  rect.right = pRect->right;
903  rect.left = pRect->left;
904  rect.top = pRect->top;
905  pRect->right = 0;
906  expanded = 1;
907  }
908  else
909  {
910  rect.top = pRect->bottom; /* reduce to bit outside old */
911  }
912  }
913  }
914  }
915  else /* rect.right <= pRect->right && rect.left < pRect->left */
916  {
917  /* new intersects left edge of old one */
918  if (rect.bottom <= pRect->bottom)
919  {
920  if (rect.top >= pRect->top)
921  {
922  /* new only intersects on left edge of old */
923  if (rect.left + SIGNF_X > pRect->left ||
924  (rect.bottom - rect.top) * 2 > (pRect->bottom - pRect->top))
925  {
926  /* Expand to engulf old */
927  rect.right = pRect->right;
928  rect.bottom = pRect->bottom;
929  rect.top = pRect->top;
930  pRect->right = 0;
931  expanded = 1;
932  }
933  else
934  {
935  rect.right = pRect->left; /* reduce to bit outside old */
936  }
937  }
938  else /* rect.bottom <= pRect->bottom && rect.top < pRect->top */
939  {
940  /* new bottom-right intersect old top-left */
941  if ((rect.left + SIGNF_X > pRect->left && rect.right + SIGNF_X > pRect->right) ||
942  (rect.top + SIGNF_Y > pRect->top && rect.bottom + SIGNF_Y > pRect->bottom) ||
943  (rect.right - pRect->left) * 2 > (pRect->right - rect.left) ||
944  (rect.bottom - pRect->top) * 2 > (pRect->bottom - rect.top))
945  {
946  /* Expand to engulf old */
947  rect.right = pRect->right;
948  rect.bottom = pRect->bottom;
949  pRect->right = 0;
950  expanded = 1;
951  }
952  else
953  {
954  /* create extra box from dividing up old */
955  if (rect.bottom != pRect->bottom)
956  {
957  if (rect.right != pRect->right)
958  {
959  sav = pRect->top;
960  pRect->top = rect.bottom;
961  AddExtraRect( *pRect, i );
962  pRect->bottom = pRect->top;
963  pRect->top = sav;
964  pRect->left = rect.right;
965  }
966  else
967  {
968  pRect->top = rect.bottom;
969  }
970  }
971  else
972  {
973  if (rect.right != pRect->right)
974  {
975  pRect->left = rect.right;
976  }
977  else
978  {
979  /* new completely surrounds old - need to remove old one */
980  pRect->right = 0;
981  }
982  }
983  }
984  }
985  }
986  else /* rect.bottom > pRect->bottom */
987  {
988  if (rect.top < pRect->top)
989  {
990  if (rect.right != pRect->right)
991  {
992  /* old only intersects on right edge of new */
993  if (rect.right + SIGNF_X > pRect->right ||
994  (rect.bottom - rect.top) < (pRect->bottom - pRect->top) * 2)
995  {
996  /* Expand to engulf old */
997  rect.right = pRect->right;
998  pRect->right = 0;
999  expanded = 1;
1000  }
1001  else
1002  {
1003  pRect->left = rect.right;
1004  }
1005  }
1006  else
1007  {
1008  /* new completely surrounds old - need to remove old one */
1009  pRect->right = 0;
1010  }
1011  }
1012  else /* rect.bottom > pRect->bottom && rect.top >= pRect->top */
1013  {
1014  /* new top-right intersect old bottom-left corners */
1015  if ((rect.left + SIGNF_X > pRect->left && rect.right + SIGNF_X > pRect->right) ||
1016  (rect.top < pRect->top + SIGNF_Y && rect.bottom < pRect->bottom + SIGNF_Y) ||
1017  (rect.right - pRect->left) * 2 > (pRect->right - rect.left) ||
1018  (pRect->bottom - rect.top) * 2 > (rect.bottom - pRect->top))
1019  {
1020  /* Expand to engulf old */
1021  rect.right = pRect->right;
1022  rect.top = pRect->top;
1023  pRect->right = 0;
1024  expanded = 1;
1025  }
1026  else
1027  {
1028  /* create extra box from dividing up old */
1029  if (rect.top != pRect->top)
1030  {
1031  if (rect.right != pRect->right)
1032  {
1033  sav = pRect->bottom;
1034  pRect->bottom = rect.top;
1035  AddExtraRect( *pRect, i );
1036  pRect->top = pRect->bottom;
1037  pRect->bottom = sav;
1038  pRect->left = rect.right;
1039  }
1040  else
1041  {
1042  pRect->bottom = rect.top;
1043  }
1044  }
1045  else
1046  {
1047  if (rect.right != pRect->right)
1048  {
1049  pRect->left = rect.right;
1050  }
1051  else
1052  {
1053  /* new completely surrounds old - need to remove old one */
1054  pRect->right = 0;
1055  }
1056  }
1057  }
1058  }
1059  }
1060  }
1061  }
1062  else /* rect.right > pRect->right */
1063  {
1064  if (pRect->left >= rect.left)
1065  {
1066  /*old is within new in x-directn*/
1067  if (pRect->bottom <= rect.bottom)
1068  {
1069  if (pRect->top >= rect.top)
1070  {
1071  /* new completely surrounds old - need to remove old one */
1072  pRect->right = 0;
1073  }
1074  else /* pRect->bottom <= rect.bottom && pRect->top < rect.top */
1075  {
1076  /* old only intersects on top edge of new */
1077  if (rect.top < pRect->top + SIGNF_Y ||
1078  (rect.right - rect.left) < (pRect->right - pRect->left) * 2)
1079  {
1080  /* Expand to engulf old */
1081  rect.top = pRect->top;
1082  pRect->right = 0;
1083  expanded = 1;
1084  }
1085  else
1086  {
1087  pRect->bottom = rect.top; /* reduce old to bit outside new */
1088  }
1089  }
1090  }
1091  else /* pRect->bottom > rect.bottom */
1092  {
1093  if (pRect->top < rect.top)
1094  {
1095  /* old stradles top and bottom edges of new, or...
1096  * new stradles left and right edges of old */
1097  if ((rect.left + SIGNF_X > pRect->left && rect.right < pRect->right + SIGNF_X) ||
1098  (rect.bottom - rect.top) * 2 > (pRect->bottom - pRect->top))
1099  {
1100  /* Expand to engulf old */
1101  rect.bottom = pRect->bottom;
1102  rect.top = pRect->top;
1103  pRect->right = 0;
1104  expanded = 1;
1105  }
1106  else
1107  {
1108  /* create extra box by dividing up old */
1109  sav = pRect->bottom;
1110  pRect->bottom = rect.top;
1111  AddExtraRect( *pRect, i );
1112  pRect->bottom = sav;
1113  pRect->top = rect.bottom;
1114  }
1115  }
1116  else
1117  {
1118  /* old only intersects on bottom edge of new one */
1119  if (rect.bottom + SIGNF_Y > pRect->bottom ||
1120  (rect.right - rect.left) < (pRect->right - pRect->left) * 2)
1121  {
1122  /* Expand to engulf old */
1123  rect.bottom = pRect->bottom;
1124  pRect->right = 0;
1125  expanded = 1;
1126  }
1127  else
1128  {
1129  pRect->top = rect.bottom; /* reduce old to bit outside new */
1130  }
1131  }
1132  }
1133  }
1134  else /* rect.right > pRect->right && pRect->left < rect.left */
1135  {
1136  /* new intersects right edge of old */
1137  if (pRect->bottom <= rect.bottom)
1138  {
1139  if (pRect->top >= rect.top)
1140  {
1141  /* old only intersects on left edge of new */
1142  if (rect.left < pRect->left + SIGNF_X ||
1143  (rect.bottom - rect.top) < (pRect->bottom - pRect->top) * 2)
1144  {
1145  /* Expand to engulf old */
1146  rect.left = pRect->left;
1147  pRect->right = 0;
1148  expanded = 1;
1149  }
1150  else
1151  {
1152  pRect->right = rect.left; /* reduce old to bit outside new */
1153  }
1154  }
1155  else /* pRect->bottom <= rect.bottom && pRect->top < rect.top */
1156  {
1157  /* old bottom-right interects new top-left */
1158  if ((rect.left < pRect->left + SIGNF_X && rect.right < pRect->right + SIGNF_X) ||
1159  (rect.top < pRect->top + SIGNF_Y && rect.bottom < pRect->bottom + SIGNF_Y) ||
1160  (pRect->right - rect.left) * 2 > (rect.right - pRect->left) ||
1161  (pRect->bottom - rect.top) * 2 > (rect.bottom - pRect->top))
1162  {
1163  /* Expand to engulf old */
1164  rect.left = pRect->left;
1165  rect.top = pRect->top;
1166  pRect->right = 0;
1167  expanded = 1;
1168  }
1169  else
1170  {
1171  /* create extra box by dividing up old */
1172  sav = pRect->bottom;
1173  pRect->bottom = rect.top;
1174  AddExtraRect( *pRect, i );
1175  pRect->top = pRect->bottom;
1176  pRect->bottom = sav;
1177  pRect->right = rect.left;
1178  }
1179  }
1180  }
1181  else /* pRect->bottom > rect.bottom */
1182  {
1183  if (pRect->top > rect.top)
1184  {
1185  /* old top-right interects new bottom-left */
1186  if ((rect.left < pRect->left + SIGNF_X && rect.right < pRect->right + SIGNF_X) ||
1187  (pRect->top < rect.top + SIGNF_Y && pRect->bottom < rect.bottom + SIGNF_Y) ||
1188  (pRect->right - rect.left) * 2 > (rect.right - pRect->left) ||
1189  (rect.bottom - pRect->top) * 2 > (pRect->bottom - rect.top))
1190  {
1191  /* Expand to engulf old */
1192  rect.left = pRect->left;
1193  rect.bottom = pRect->bottom;
1194  pRect->right = 0;
1195  expanded = 1;
1196  }
1197  else
1198  {
1199  /* create extra box by dividing up old */
1200  sav = pRect->top;
1201  pRect->top = rect.bottom;
1202  AddExtraRect( *pRect, i );
1203  pRect->bottom = pRect->top;
1204  pRect->top = sav;
1205  pRect->right = rect.left;
1206  }
1207  }
1208  else /* pRect->bottom > rect.bottom && pRect->top <= rect.top */
1209  {
1210  /* new only intersects on right edge of old */
1211  if (rect.right < pRect->right + SIGNF_X ||
1212  (rect.bottom - rect.top) * 2 > (pRect->bottom - pRect->top))
1213  {
1214  /* Expand to engulf old */
1215  rect.left = pRect->left;
1216  rect.bottom = pRect->bottom;
1217  rect.top = pRect->top;
1218  pRect->right = 0;
1219  expanded = 1;
1220  }
1221  else
1222  {
1223  rect.left = pRect->right; /* reduce new to bit outside old */
1224  }
1225  }
1226  }
1227  }
1228  }
1229  }
1230  else if (pRect->right != 0)
1231  {
1232  /* Not intersecting, but may be close ... */
1233  int cnt = 0, diff, most;
1234 
1235  if (pRect->top < rect.top + DELTA_Y && pRect->top + DELTA_Y > rect.top &&
1236  pRect->bottom < rect.bottom + DELTA_Y && pRect->bottom + DELTA_Y > rect.bottom)
1237  {
1238  if ((pRect->right < rect.left && pRect->right + 90 > rect.left) ||
1239  (rect.right < pRect->left && rect.right + 90 > pRect->left))
1240  {
1241  cnt++;
1242  }
1243  }
1244  if (pRect->left < rect.left + DELTA_X && pRect->left + DELTA_X > rect.left &&
1245  pRect->right < rect.right + DELTA_X && pRect->right + DELTA_X > rect.right)
1246  {
1247  if ((pRect->bottom < rect.top && pRect->bottom + 72 > rect.top) ||
1248  (rect.bottom < pRect->top && rect.bottom + 72 > pRect->top))
1249  {
1250  cnt++;
1251  }
1252  }
1253  if (pRect->right > rect.left && rect.right > pRect->left)
1254  {
1255  if ((pRect->top < rect.bottom + DELTA_Y && pRect->top + DELTA_Y > rect.bottom) ||
1256  (rect.top < pRect->bottom + DELTA_Y && rect.top + DELTA_Y > pRect->bottom))
1257  {
1258  if (pRect->right > rect.right)
1259  {
1260  most = pRect->right;
1261  diff = pRect->right - rect.right;
1262  }
1263  else
1264  {
1265  most = rect.right;
1266  diff = rect.right - pRect->right;
1267  }
1268  if (rect.left > pRect->left)
1269  {
1270  most -= pRect->left;
1271  diff += rect.left - pRect->left;
1272  }
1273  else
1274  {
1275  most -= rect.left;
1276  diff += pRect->left - rect.left;
1277  }
1278  if (diff * 2 < most)
1279  {
1280  cnt++;
1281  }
1282  }
1283  }
1284  if (pRect->bottom > rect.top && rect.bottom > pRect->top)
1285  {
1286  if ((pRect->left < rect.right + DELTA_X && pRect->left + DELTA_X > rect.right) ||
1287  (rect.left < pRect->right + DELTA_X && rect.left + DELTA_X > pRect->right))
1288  {
1289  if (pRect->bottom > rect.bottom)
1290  {
1291  most = pRect->bottom;
1292  diff = pRect->bottom - rect.bottom;
1293  }
1294  else
1295  {
1296  most = rect.bottom;
1297  diff = rect.bottom - pRect->bottom;
1298  }
1299  if (rect.top > pRect->top)
1300  {
1301  most -= pRect->top;
1302  diff += rect.top - pRect->top;
1303  }
1304  else
1305  {
1306  most -= rect.top;
1307  diff += pRect->top - rect.top;
1308  }
1309  if (diff * 2 < most)
1310  {
1311  cnt++;
1312  }
1313  }
1314  }
1315  if (cnt)
1316  {
1317  /* an existing rect has borders close in position to this new one,
1318  * make this new one engulf existing rect */
1319  TRACE(TGRAPHICS, ("b[%d](%d,%d,%d,%d)", i, pRect->left, pRect->top, pRect->right, pRect->bottom))
1320  TRACE(TGRAPHICS, ("new (%d,%d,%d,%d)", rect.left, rect.top, rect.right, rect.bottom))
1321  if (rect.left > pRect->left)
1322  {
1323  rect.left = pRect->left;
1324  expanded = 1;
1325  }
1326  if (rect.right < pRect->right)
1327  {
1328  rect.right = pRect->right;
1329  expanded = 1;
1330  }
1331  if (rect.top > pRect->top)
1332  {
1333  rect.top = pRect->top;
1334  expanded = 1;
1335  }
1336  if (rect.bottom < pRect->bottom)
1337  {
1338  rect.bottom = pRect->bottom;
1339  expanded = 1;
1340  }
1341  pRect->right = 0;
1342  }
1343  }
1344  assert( pRect->right == 0 || (pRect->right > pRect->left && pRect->bottom > pRect->top));
1345  }
1346  }
1347  while (expanded != 0);
1348 
1349  /* add the new rectangle that was occupied by this visible as requiring a redraw */
1350  AddExtraRect( rect, d_rects );
1351 
1352  TRACE(TGRAPHICS, ("finished id=%ld, box=(%d,%d,%d,%d) num:was=%d,now=%d", visible->ingredient.root.id,
1353  rect.left, rect.top, rect.right, rect.bottom, i, numDirtyRects))
1354  }
1355 }
1356 
1363 {
1364  MHEG5Scene *scene = MHEG5getCurrentScene();
1365  if (!scene)
1366  {
1367  numDirtyRects = 0;
1368  }
1369  else
1370  {
1371  /* Set a rectangle to cover the entire screen area */
1372  dirtyRects[0].left = 0;
1373  dirtyRects[0].top = 0;
1374  dirtyRects[0].right = (S16BIT)scene->sceneCoordinateSystem[0];
1375  dirtyRects[0].bottom = (S16BIT)scene->sceneCoordinateSystem[1];
1376  numDirtyRects = 1;
1377 
1378  TRACE(TGRAPHICS, ("box=(%d,%d,%d,%d)",
1379  dirtyRects[0].left, dirtyRects[0].top, dirtyRects[0].right, dirtyRects[0].bottom))
1380  }
1381 }
1382 
1383 static void RestartAudioClip(MHEG5Stream *stream)
1384 {
1385  if (stream->streamState == SS_PLAYING_CLIP)
1386  {
1387  if (DVB_MhegAudioPlayClip( stream->ingredient.data, stream->ingredient.dataLen,
1388  stream->looping, AUDIO_ENC_MPEG2 ) != MHERR_OK)
1389  {
1390  TRACE(TERROR, ("DVB_MhegAudioPlayClip failed"));
1391  }
1392  }
1393 }
1394 
1396 {
1397  if (iframePlaying)
1398  {
1399  /* On activation, an iframe will need to be redisplayed correctly */
1400  iframeDecoded = MHEG5FALSE;
1401  }
1402  else
1403  {
1404  video_stream_changed = MHEG5TRUE;
1405  if (videoFreeze)
1406  {
1407  video_pause_changed = MHEG5TRUE;
1408  }
1409  }
1410  audio_stream_changed = MHEG5TRUE;
1411  streamSettingsChanged = MHEG5TRUE;
1412  videoPositionChanged = MHEG5TRUE;
1413  MHEG5displayUpdateStreamDecoders(MHEG5FALSE);
1415  if (audioPlaying == AUDIO_PLAY_MEMORY && activeAudioObject != NULL)
1416  {
1417  RestartAudioClip( activeAudioObject->parent );
1418  }
1419  audio_pause_changed = audioFreeze;
1420 }
1421 
1423 {
1424  MG_OSDclear();
1425  DVB_MhegSetVideoScaling( NULL );
1426  if (lastAudioPlaying == AUDIO_PLAY_MEMORY)
1427  {
1428  (void)DVB_MhegAudioStopClip();
1429  }
1430  if (iframeDecoded)
1431  {
1433  iframeDecoded = MHEG5FALSE;
1434  }
1435 #ifdef INCLUDE_FREESAT
1436  if (imagePlaneDecoded)
1437  {
1438  DVB_MhegImagePlaneIFrameStop();
1439  imagePlaneDecoded = MHEG5FALSE;
1440  }
1441 #endif
1442  (void)DVB_MhegVideoPlayDefault();
1443  (void)DVB_MhegAudioPlayDefault();
1444  lastVideoPlaying = MHEG5TRUE;
1445  lastVideoFreeze = MHEG5FALSE;
1446  lastAudioPlaying = AUDIO_PLAY_STREAM;
1447  lastAudioFreeze = MHEG5FALSE;
1448  lastTerminating = MHEG5TRUE;
1449 }
1450 
1452 {
1453  MHEG5Ingredient *item = ((MHEG5Group *)group)->itemHead;
1454  while (item)
1455  {
1456  switch (item->root.clazz)
1457  {
1458  case MHEG5BITMAP:
1459  case MHEG5ENTRYFIELD:
1460  case MHEG5HYPERTEXT:
1461  case MHEG5TEXT:
1462  if (((MHEG5Visible *)item)->graphic_data != NULL)
1463  {
1464  MG_FreeData(((MHEG5Visible *)item)->graphic_data );
1465  ((MHEG5Visible *)item)->graphic_data = NULL;
1466  }
1467  break;
1468 
1469  case MHEG5DYNAMICLINEART:
1471  break;
1472 
1473  case MHEG5LINEART:
1474  case MHEG5RECTANGLE:
1475  break;
1476 
1477  default:
1478  /* NON visible */
1479  break;
1480  }
1481  item = item->next;
1482  }
1483 }
1484 
1486 {
1487  MHEG5Ingredient *item = ((MHEG5Group *)group)->itemHead;
1488  while (item)
1489  {
1490  switch (item->root.clazz)
1491  {
1492  case MHEG5BITMAP:
1493  {
1494  MHEG5Visible *visible = (MHEG5Visible *)item;
1495  if (visible->ingredient.data != NULL)
1496  {
1497  switch (item->contentHook)
1498  {
1499  case CHOOK_BITMAP_PNG:
1500  MG_DrawPng( visible->ingredient.data, visible->ingredient.dataLen, visible );
1501  break;
1502  case CHOOK_BITMAP_JPG:
1503  MG_DrawJpg( visible->ingredient.data, visible->ingredient.dataLen, visible );
1504  break;
1505  default:;
1506  }
1507  }
1508  }
1509  break;
1510 
1511  case MHEG5TEXT:
1512  MHEG5drawText((MHEG5Text *)item );
1513  break;
1514 
1515  case MHEG5LINEART:
1516  case MHEG5RECTANGLE:
1517  break;
1518 
1519  case MHEG5DYNAMICLINEART:
1521  break;
1522 
1523  case MHEG5ENTRYFIELD:
1525  break;
1526 
1527  case MHEG5HYPERTEXT:
1529  break;
1530 
1531  default:
1532  /* NON visible */
1533  break;
1534  }
1535  item = item->next;
1536  }
1537 }
1538 
1539 static void VideoStop( MHEG5Bool terminating )
1540 {
1541  if (terminating)
1542  {
1543  /* Set the displayed video stream to the user selected preference */
1544  (void)DVB_MhegVideoPlayDefault();
1545  }
1546  else
1547  {
1548  /* Stop the video decoder */
1549  (void)DVB_MhegVideoStopStream();
1550  }
1551 }
1552 
1553 static void AudioStop( MHEG5Bool terminating )
1554 {
1555  if (terminating)
1556  {
1557  /* Set the presented audio stream to the user selected preference */
1558  (void)DVB_MhegAudioPlayDefault();
1559  }
1560  else
1561  {
1562  /* Stop the audio decoder */
1563  (void)DVB_MhegAudioStopStream();
1564  }
1565 }
1566 
1575 static void MHEG5displayUpdateStreamDecoders(MHEG5Bool terminating)
1576 {
1577  static MHEG5Int lastAudioVolume = 0;
1578 #ifdef INCLUDE_ICS
1579  static MHEG5Stream *lastIcStream = NULL;
1580  MHEG5Stream *icStream = NULL;
1581 #endif
1582  MHEG5Stream *stream;
1583  E_MhegErr err;
1584 
1585 
1586  /* Video playing state and selected video stream */
1587  if ((lastVideoPlaying != videoPlaying) || (video_stream_changed) ||
1588  (lastTerminating != terminating))
1589  {
1590  TRACE(TSTRM, ("VP=%d ifrmPly=%d", videoPlaying, iframePlaying));
1591  if (videoPlaying)
1592  {
1593  assert( activeVideoObject );
1594  assert( activeVideoObject->visible.ingredient.root.clazz == MHEG5VIDEO );
1595 
1596  stream = activeVideoObject->parent;
1597 
1598  /* This is only relevant to streams from broadcast */
1600  {
1601  TRACE(TSTRM, ("V_srv_id=%d V_cmpt_id=%d",
1602  video_stream_ref.service_id,
1603  video_stream_ref.ComponentTag));
1604 
1605  if (MHEG5_MULTIPLEX_REF_VALID(video_stream_ref))
1606  {
1607  /* The following call may return MHERR_OTHER
1608  * if the service is present, but no video in PMT
1609  */
1610  err = DVB_MhegVideoPlayStream(&video_stream_ref);
1611  }
1612  else
1613  {
1614  err = MHERR_BAD_PARAMETER;
1615  }
1616 
1617  switch (err)
1618  {
1619  case MHERR_OK:
1620  TRACE(TSTRM, ("Video Play success, SS=%s", SS(stream)));
1621  if (stream->streamState <= SS_STOPPING)
1622  {
1623  stream->streamState = SS_STARTING;
1624  /* next wait for the 'stream started' callback */
1625  }
1626  else if (stream->streamState == SS_PLAYING)
1627  {
1628  stream->streamState = SS_NEW_REF;
1629  }
1630  break;
1631 
1632  case MHERR_BAD_PARAMETER:
1633  TRACE(TSTRM, ("SS=%s", SS(stream)));
1634  if (stream->streamState > SS_STOPPING)
1635  {
1636  stream->streamState = SS_STOPPING;
1637  }
1638 
1639  /* The multiplex reference is invalid, so stop
1640  * playing the video
1641  */
1642  VideoStop(terminating);
1643  break;
1644 
1645  default:
1646  case MHERR_OTHER:
1647  TRACE(TSTRM, ("SS=%s service_id=%x", SS(stream),video_stream_ref.service_id));
1648  /* Stream state is set to stopped, so that it won't
1649  * generate stream stopped event
1650  */
1651  stream->streamState = SS_STOPPED;
1652  break;
1653  }
1654  }
1655  #ifdef INCLUDE_ICS
1656  else if (stream->ingredient.contentHook == CHOOK_STREAM_IC)
1657  {
1658  /* Stream is from IC */
1659  if (MHEG5StreamerIsRunable(stream))
1660  {
1661  if (lastIcStream == NULL)
1662  {
1663  TRACE(TSTRM, ("SS=%s service_id=%x", SS(stream),video_stream_ref.service_id));
1665  memset(&video_stream_ref, 0, sizeof(video_stream_ref));
1666  }
1667  icStream = stream;
1668  }
1669  }
1670  #endif
1671  }
1672  else if (!iframeDecoded)
1673  {
1674  /* Video is not playing and I-frame is not decoded */
1675  if (activeVideoObject != NULL)
1676  {
1677  stream = activeVideoObject->parent;
1678 
1679  /* This is only relevant to streams from broadcast */
1681  {
1682  TRACE(TSTRM, ("AVO=%d AAO=%p STM=%p", activeVideoObject,
1683  activeAudioObject, stream));
1684  TRACE(TSTRM, ("Stop Video, SS=%s", SS(stream)));
1685  switch (stream->streamState)
1686  {
1687  case SS_STOPPING:
1688  /* DTG test 6.10A expects Stream Stopped event
1689  * and Stream Playing event to occur because
1690  * of two consecutive elementry actions:
1691  * - Stop(stream)
1692  * - Run(stream)
1693  * This means we cannot wait for the notify
1694  * A/V stopped callback, because we will be in
1695  * the starting state by then.
1696  */
1698  stream->streamState = SS_STOPPED;
1699  break;
1700 
1701  default:
1702  stream->streamState = SS_STOPPING;
1703 
1704  case SS_STOPPED:
1705  /* ignore */
1706  ;
1707  }
1708  }
1709  else
1710  {
1711  TRACE(TSTRM, ("No Video object (assume destroyed)"));
1712  }
1713  }
1714  VideoStop(terminating);
1715  }
1716 
1717  lastVideoPlaying = videoPlaying;
1718  video_stream_changed = MHEG5FALSE;
1719  }
1720  else
1721  {
1722  TRACE(TSTRM, ("IGNORE: VP=%d ifrmPly=%d", videoPlaying, iframePlaying));
1723  }
1724 
1725  /* Video freeze state */
1726  if (lastVideoFreeze != videoFreeze || video_pause_changed)
1727  {
1728  TRACE(TSTRM, ("VF=%d", videoFreeze));
1729  if (videoFreeze)
1730  {
1732  }
1733  else
1734  {
1736  }
1737  lastVideoFreeze = videoFreeze;
1738  video_pause_changed = MHEG5FALSE;
1739  }
1740 
1741  /******************/
1742  /* Audio Settings */
1743  /******************/
1744 
1745  /* Volume */
1746  if (lastAudioVolume != audioVolume)
1747  {
1748  #ifdef INCLUDE_ICS
1749  if (activeAudioObject != NULL)
1750  {
1751  stream = activeAudioObject->parent;
1752  if (stream->ingredient.contentHook == CHOOK_STREAM_IC)
1753  {
1754  err = DVB_MhegICStreamAudioSetVolume(audioVolume);
1755  }
1756  else
1757  {
1758  err = DVB_MhegAudioSetVolume(audioVolume);
1759  }
1760  }
1761  else
1762  {
1763  err = DVB_MhegAudioSetVolume(audioVolume);
1764  }
1765  #else
1766  err = DVB_MhegAudioSetVolume(audioVolume);
1767  #endif
1768  if (err != MHERR_OK)
1769  {
1770  ERROR_PRINT(("ERROR: OSDaudioSetVolume() - Failed to adjust audio volume\n"));
1771  }
1772  lastAudioVolume = audioVolume;
1773  }
1774 
1775  /* Audio freeze state */
1776  if (lastAudioFreeze != audioFreeze || audio_pause_changed)
1777  {
1778  if (audioPlaying == AUDIO_PLAY_MEMORY)
1779  {
1780  if (audioFreeze)
1781  {
1783  }
1784  else
1785  {
1787  }
1788  }
1789  else
1790  {
1791  audio_stream_changed = MHEG5TRUE;
1792  }
1793  lastAudioFreeze = audioFreeze;
1794  audio_pause_changed = MHEG5FALSE;
1795  }
1796 
1797  /* Audio playing state, audio freeze state, and selected audio stream */
1798  if ((lastAudioPlaying != audioPlaying) || (audio_stream_changed) ||
1799  (lastTerminating != terminating))
1800  {
1801  TRACE(TSTRM, ("AP=%d ", audioPlaying))
1802  if (lastAudioPlaying == AUDIO_PLAY_MEMORY)
1803  {
1805  {
1806  TRACE(TERROR, ("Failed to stop audio"));
1807  }
1808  }
1809  if (audioPlaying == AUDIO_PLAY_STREAM && !audioFreeze)
1810  {
1811  assert( activeAudioObject );
1812  stream = activeAudioObject->parent;
1813 
1814  /* This is only relevant to streams from broadcast */
1816  {
1817  TRACE(TSTRM, ("A_srv_id=%d A_cmpt_id=%d",
1818  audio_stream_ref.service_id,
1819  audio_stream_ref.ComponentTag));
1820 
1821  if (MHEG5_MULTIPLEX_REF_VALID(audio_stream_ref))
1822  {
1823  /* The following call may return
1824  * MHERR_OTHER if the service is present,
1825  * but no Audio in PMT
1826  */
1827  err = DVB_MhegAudioPlayStream(&audio_stream_ref);
1828  }
1829  else
1830  {
1831  err = MHERR_BAD_PARAMETER;
1832  }
1833 
1834  switch (err)
1835  {
1836  case MHERR_OK:
1837  TRACE(TSTRM, ("SetAudioStream/Mode OK, SS=%s", SS(stream)));
1838  if (stream->streamState <= SS_STOPPING)
1839  {
1840  stream->streamState = SS_STARTING;
1841  /* next, wait for the 'stream started' callback */
1842  }
1843  else if (stream->streamState == SS_PLAYING)
1844  {
1845  stream->streamState = SS_NEW_REF;
1846  }
1847  break;
1848 
1849  case MHERR_BAD_PARAMETER:
1850  TRACE(TSTRM, ("SS=%s", SS(stream)));
1851  if (stream->streamState > SS_STOPPING)
1852  {
1853  stream->streamState = SS_STOPPING;
1854  }
1855 
1856  /* The multiplex reference is invalid, so stop
1857  * playing the audio
1858  */
1859  AudioStop(terminating);
1860  break;
1861 
1862  default:
1863  case MHERR_OTHER:
1864  TRACE(TSTRM, ("SS=%s", SS(stream)));
1865  /* Stream state is set to stopped, so that it
1866  * won't generate stream stopped event
1867  */
1868  stream->streamState = SS_STOPPED;
1869  }
1870  }
1871  #ifdef INCLUDE_ICS
1872  else if (stream->ingredient.contentHook == CHOOK_STREAM_IC)
1873  {
1874  /* Stream is from IC */
1875  if (MHEG5StreamerIsRunable(stream))
1876  {
1877  if (lastIcStream == NULL)
1878  {
1880  memset(&audio_stream_ref, 0, sizeof(audio_stream_ref));
1881  }
1882  icStream = stream;
1883  }
1884  }
1885  #endif
1886  }
1887  else if (audioPlaying == AUDIO_PLAY_MEMORY)
1888  {
1889  if (lastAudioPlaying == AUDIO_PLAY_STREAM || lastTerminating)
1890  {
1892  {
1893  TRACE(TERROR, ("DVB_MhegAudioStopStream failed"))
1894  }
1895  }
1896  }
1897  else
1898  {
1899  if (activeAudioObject != NULL)
1900  {
1901  stream = activeAudioObject->parent;
1902  TRACE(TSTRM, ("AVO=%d AAO=%p STM=%p", activeVideoObject,
1903  activeAudioObject, stream));
1904  TRACE(TSTRM, ("Stop Audio, SS=%s", SS(stream)));
1905 
1906  /* This is only relevant to streams from broadcast or memory */
1907  if (stream->ingredient.contentHook == CHOOK_STREAM_NORMAL ||
1909  {
1910  switch (stream->streamState)
1911  {
1912  case SS_STOPPING:
1913  /* DTG test 6.10A expects Stream Stopped event and Stream Playing event
1914  * to occur because of two consecutive elementry actions:
1915  * Stop(stream)
1916  * Run(stream)
1917  * This means we cannot wait for the notify A/V stopped callback,
1918  * because we will be in the starting state by then.
1919  */
1921  stream->streamState = SS_STOPPED;
1922  break;
1923 
1924  default:
1925  stream->streamState = SS_STOPPING;
1926 
1927  case SS_STOPPED: /*ignor*/;
1928  }
1929  }
1930  else
1931  {
1932  TRACE(TSTRM, ("No Audio object (assume destroyed), %d", audioPlaying));
1933  }
1934  }
1935  AudioStop( terminating );
1936  }
1937 
1938  lastAudioPlaying = audioPlaying;
1939  audio_stream_changed = MHEG5FALSE;
1940  }
1941 
1942 #ifndef MHEG5PROFILE_UK1_06
1943  /***********************/
1944  /* RTGraphics Settings */
1945  /***********************/
1946  MHEG5displayRtGraphicsUpdate( terminating, (videoXscale == 720 && videoYscale == 576) ? MHEG5TRUE : MHEG5FALSE );
1947 #endif
1948 
1949  /* Update the lastTerminating flag */
1950  lastTerminating = terminating;
1951 
1952  /* Reset the changed flag since we have just reprogrammed the media
1953  * decoders.
1954  */
1955  streamSettingsChanged = MHEG5FALSE;
1956 
1957 #ifdef INCLUDE_ICS
1958  if (icStream != NULL)
1959  {
1960  lastIcStream = icStream;
1961  /* Start playing IC stream */
1962  MHEG5StreamerRun(icStream);
1963  }
1964  else
1965  {
1966  lastIcStream = NULL;
1967  }
1968 #endif
1969 }
1970 
1971 static void SetScaling(void *dummy)
1972 {
1973  TRACE(TSTRM, ("AVO=%p, AIO=%p", activeVideoObject, activeIframeObject))
1974 #ifdef INCLUDE_FREESAT
1975  if (activeImagePlaneObject != NULL)
1976  {
1977  MG_SetVideoPosition((MHEG5Video *)activeImagePlaneObject,
1978  activeImagePlaneObject->visible.ingredient.contentHook );
1979  }
1980 #endif
1981  if (activeIframeObject != NULL)
1982  {
1983  MG_SetVideoPosition((MHEG5Video *)activeIframeObject,
1984  activeIframeObject->visible.ingredient.contentHook );
1985  }
1986  else if (activeVideoObject != NULL)
1987  {
1988  MHEG5Stream *stream = activeVideoObject->parent;
1989  MG_SetVideoPosition( activeVideoObject, stream->ingredient.contentHook );
1990  }
1991  else
1992  {
1994  }
1995 }
1996 
1998 {
1999  /* Check whether stream settings (audio, video, rtgraphics objects) have
2000  * changed, and reprogram the stream decoders if necessary.
2001  */
2002  if (!displayStreamsAreLocked)
2003  {
2004  if (videoPositionChanged && application && application->lockCount == 0)
2005  {
2006  MHEG5eventMessage_t event_msg;
2007  TRACE(TSTRM, (""))
2008  /* put on low priority queue to schedule positioning of video/iframe */
2009  event_msg.proc_msg_func = SetScaling;
2010  event_msg.data_type = DT_NONE;
2011  if (VQ_PutMsg(&event_msg, PRTY_LOW) == MHERR_OK)
2012  {
2013  videoPositionChanged = MHEG5FALSE;
2014  }
2015  }
2016 #ifdef NO_STREAM_UPDATE_WHEN_LOCKED
2017  if (application && application->lockCount == 0))
2018 #endif
2019  {
2020  if (streamSettingsChanged)
2021  {
2022  TRACE(TSTRM, (""))
2023  MHEG5displayUpdateStreamDecoders(MHEG5FALSE);
2024  }
2025  }
2026  }
2027 }
2028 
2036 {
2037  int i;
2038  TRACER(int itemCount = 0;)
2039  S_REGION *pRect;
2040  MHEG5Visible *visible;
2041  MHEG5DisplayStackItem *prevItem;
2042  MHEG5Application *application;
2043  OSDColor desktopColour;
2044 
2045  application = MHEG5getCurrentApplication();
2046  if ((application) && (application->lockCount == 0))
2047  {
2048  TRACE(TGRAPHICS, ("*************** numDirtyRects=%d *************",numDirtyRects))
2049  /* Screen is not locked. So can redraw it. */
2050  //assert( MH5GlueActiveState() == TRUE );
2051  if (numDirtyRects)
2052  {
2053  pRect = dirtyRects;
2054  for (i = 0; i != numDirtyRects; i++, pRect++)
2055  {
2056  if (pRect->right != 0)
2057  {
2058  assert( pRect->right > pRect->left && pRect->bottom > pRect->top );
2059  desktopColour = MHEG5displayColour(&application->desktopColour);
2060  MG_OSDerase( *pRect, desktopColour );
2061  }
2062  }
2063 
2064  /* To do object blending, we must erase the background and redraw all
2065  * objects in the display stack.
2066  */
2067 
2068 #ifdef INCLUDE_FREESAT
2069  if (activeImagePlaneObject)
2070  {
2071  S_REGION rect, overlap, *pRect;
2072 
2073  rect = ((MHEG5Visible *)activeImagePlaneObject)->rect;
2074 
2075  pRect = dirtyRects;
2076  for (i = 0; i != numDirtyRects; i++, pRect++)
2077  {
2078  if (pRect->right > rect.left && rect.right > pRect->left &&
2079  pRect->bottom > rect.top && rect.bottom > pRect->top)
2080  {
2081  /* Overlap */
2082  overlap.left = MAX(pRect->left, rect.left);
2083  overlap.top = MAX(pRect->top, rect.top);
2084  overlap.right = MIN(pRect->right, rect.right);
2085  overlap.bottom = MIN(pRect->bottom, rect.bottom);
2086 
2087  /* Update part of display with visible object */
2088  MHEG5displayDrawImagePlane((MHEG5Visible *)activeImagePlaneObject, &overlap);
2089  }
2090  }
2091  }
2092 #endif /* INCLUDE_FREESAT */
2093 
2094  prevItem = application->displayStackBottom; /* start at Bottom of Stack */
2095 
2096  while (prevItem)
2097  {
2098  visible = (MHEG5Visible *)prevItem->item;
2099  TRACER(itemCount++;)
2100  if (!visible->ingredient.root.runningStatus)
2101  {
2102  if (visible->graphic_data || visible->ingredient.cloned)
2103  {
2104  TRACE(TGRAPHICS, ("id=%d clzz=%d %p", visible->ingredient.root.id,
2105  visible->ingredient.root.clazz, visible->graphic_data))
2106  }
2107  }
2108  else
2109  {
2110  S_REGION rect, overlap;
2111 
2112  rect = visible->rect;
2113  pRect = dirtyRects;
2114  for (i = 0; i != numDirtyRects; i++, pRect++)
2115  {
2116  if (pRect->right > rect.left && rect.right > pRect->left &&
2117  pRect->bottom > rect.top && rect.bottom > pRect->top)
2118  {
2119  /* Overlap */
2120  overlap.left = MAX(pRect->left, rect.left);
2121  overlap.top = MAX(pRect->top, rect.top);
2122  overlap.right = MIN(pRect->right, rect.right);
2123  overlap.bottom = MIN(pRect->bottom, rect.bottom);
2124 
2125  /* Update part of display with visible object */
2126  MHEG5displayDraw( visible, &overlap );
2127  }
2128  }
2129  }
2130  prevItem = prevItem->prev;
2131  }
2132 
2133  MG_OSDUpdate();
2134  numDirtyRects = 0;
2135  }
2136  TRACE(TGRAPHICS, ("*************** itemCount=%d *************",itemCount))
2137  }
2138  MHEG5displayStreamUpdate( application );
2139 }
2140 
2141 /*
2142  Stream Functions
2143  */
2144 
2151 {
2152  MHEG5Stream *stream;
2153  assert(audio);
2154 
2155  stream = audio->parent;
2156 
2157  /* AMS_TODO: not sure that this is where we should set the active stream object */
2158  activeAudioObject = audio;
2159 
2160  /* Adjust the audio volume */
2161  audioVolume = audio->volume;
2162 
2163  TRACE(TSTRM, ("(%p)", audio))
2164 
2165  /* Note that stream settings have changed so that the media decoders can be
2166  * reprogrammed.
2167  */
2168  streamSettingsChanged = MHEG5TRUE;
2169 
2170  if (stream->speed[0] == 0)
2171  {
2172  /* Note that the audio stream is frozen */
2173  audioFreeze = MHEG5TRUE;
2174  }
2175  else if (audioFreeze && audioPlaying != AUDIO_PLAY_NONE)
2176  {
2177  /* Audio stream is not frozen, but don't play from the start */
2178  audioFreeze = MHEG5FALSE;
2179  }
2180  else
2181  {
2182  /* Audio stream is not frozen, and play from the start */
2183  audioFreeze = MHEG5FALSE;
2184 
2185  /* Audio stream is now playing - even if waiting for data in the memory case */
2186  if (stream->storageMemory)
2187  {
2188  /* This clip is playing from memory */
2189  audioPlaying = AUDIO_PLAY_MEMORY;
2190  TRACE(TSTRM, ("aud play %ld", audio->parent->ingredient.dataLen))
2191 
2192  if (stream->ingredient.data != 0 &&
2193  stream->ingredient.dataLen != 0)
2194  {
2195  E_MhegErr err;
2196  TRACE(TSTRM, ("AP=%d", audioPlaying))
2197 
2198  /* Start playing the audio sample immediately */
2199  audio_stream_changed = MHEG5TRUE;
2200  MHEG5displayUpdateStreamDecoders(MHEG5FALSE);
2201  err = DVB_MhegAudioPlayClip( stream->ingredient.data,
2202  stream->ingredient.dataLen,
2203  stream->looping, AUDIO_ENC_MPEG2 );
2204  if (err != MHERR_OK)
2205  {
2206  TRACE(TERROR, ("DVB_MhegAudioPlayClip returned %d", err))
2207  }
2208  else
2209  {
2210  TRACE(TSTRM, ("Audio Play Memory success, SS=%s", SS(stream)))
2211  if (stream->streamState <= SS_STOPPING)
2212  {
2213  /* for Audio Clip, don't wait for the 'stream started' callback to do event */
2215  stream->streamState = SS_PLAYING_CLIP;
2216  }
2217  }
2218  }
2219  }
2220  else if (stream->ingredient.contentHook == CHOOK_STREAM_NORMAL)
2221  {
2222  MHEG5Int componentTag = MHEG5streamGetComponentTag((MHEG5Ingredient *)audio);
2223 
2224  TRACE(TSTRM, ("AP=%d", audioPlaying))
2225 
2226  /* This audio is playing from a stream */
2227  audioPlaying = AUDIO_PLAY_STREAM;
2228 
2229  /* Extract the multiplex reference from the stream. The componentTag
2230  * is extracted from the audio object to reference a specific
2231  * component within the multiplex.
2232  */
2233  if ((audio_stream_ref.service_id != stream->dvbLocator.service_id) ||
2234  (audio_stream_ref.original_network_id != stream->dvbLocator.original_network_id) ||
2235  (audio_stream_ref.transport_stream_id != stream->dvbLocator.transport_stream_id) ||
2236  (audio_stream_ref.ComponentTag != componentTag))
2237  {
2238  audio_stream_ref.original_network_id = stream->dvbLocator.original_network_id;
2239  audio_stream_ref.transport_stream_id = stream->dvbLocator.transport_stream_id;
2240  audio_stream_ref.service_id = stream->dvbLocator.service_id;
2241  audio_stream_ref.ComponentTag = (S16BIT)componentTag;
2242 
2243  /* Indicate that we have updated the audio multiplex reference */
2244  MHEG5streamSetCurrentService((MHEG5Ingredient *)audio, &audio_stream_ref );
2245  audio_stream_changed = MHEG5TRUE;
2246  TRACE(TSTRM, (" new Audio ref, SS=%s", SS(stream)))
2247  }
2248  }
2249  #ifdef INCLUDE_ICS
2250  else if (stream->ingredient.contentHook == CHOOK_STREAM_IC)
2251  {
2252  /* This audio is playing from a stream */
2253  audioPlaying = AUDIO_PLAY_STREAM;
2254  audio_stream_changed = MHEG5TRUE;
2255  }
2256  #endif
2257  }
2258 
2259  #ifdef INCLUDE_ICS
2260  if (stream->ingredient.contentHook == CHOOK_STREAM_IC)
2261  {
2262  /* Pause/resume is handled by the streamer */
2263  audioFreeze = MHEG5FALSE;
2264  }
2265  #endif
2266 }
2267 
2274 {
2275  MHEG5Stream *stream;
2276  assert(video);
2277 
2278  stream = video->parent;
2279 
2280  TRACE(TSTRM, ("(%p) VP=%d", video, videoPlaying))
2281 
2282  if (activeVideoObject != NULL)
2283  {
2284  TRACE((TSTRM | TPERFORM), ("AVO_clss=%d", activeVideoObject->visible.ingredient.root.clazz))
2285  }
2286 
2287  /* AMS_TODO: not sure that this is where we should set the active stream object */
2288  activeVideoObject = video;
2289 
2290  videoPlaying = MHEG5TRUE;
2291 
2292  if (stream->speed[0] == 0)
2293  {
2294  /* Video is frozen */
2295  videoFreeze = MHEG5TRUE;
2296  TRACE(TSTRM, ("FROZEN"))
2297  }
2298  else
2299  {
2300  TRACE(TSTRM, ("chook=%d vsr.sid=%x dvb.sid=%x",stream->ingredient.contentHook,
2301  video_stream_ref.service_id, stream->dvbLocator.service_id))
2303  {
2304  S16BIT componentTag = (S16BIT)MHEG5streamGetComponentTag((MHEG5Ingredient *)video);
2305 
2306  /* Video is not frozen */
2307  videoFreeze = MHEG5FALSE;
2308 
2309  /* Extract the multiplex reference from the stream. The componentTag
2310  * is extracted from the video object to reference a specific
2311  * component within the multiplex.
2312  */
2313  if ((video_stream_ref.service_id != stream->dvbLocator.service_id) ||
2314  (video_stream_ref.original_network_id != stream->dvbLocator.original_network_id) ||
2315  (video_stream_ref.transport_stream_id != stream->dvbLocator.transport_stream_id) ||
2316  (video_stream_ref.ComponentTag != componentTag))
2317  {
2318  video_stream_ref.original_network_id = stream->dvbLocator.original_network_id;
2319  video_stream_ref.transport_stream_id = stream->dvbLocator.transport_stream_id;
2320  video_stream_ref.service_id = stream->dvbLocator.service_id;
2321  video_stream_ref.ComponentTag = componentTag;
2322 
2323  /* Indicate that we have updated the video multiplex reference */
2324  MHEG5streamSetCurrentService((MHEG5Ingredient *)video, &video_stream_ref );
2325  video_stream_changed = MHEG5TRUE;
2326  TRACE(TSTRM, (" new Video ref, SS=%s", SS(stream)));
2327  }
2328  }
2329  #ifdef INCLUDE_ICS
2330  else if (stream->ingredient.contentHook == CHOOK_STREAM_IC)
2331  {
2332  video_stream_changed = MHEG5TRUE;
2333  }
2334  #endif
2335  }
2336 
2337  #ifdef INCLUDE_ICS
2338  if (stream->ingredient.contentHook == CHOOK_STREAM_IC)
2339  {
2340  /* Pause/resume is handled by the streamer */
2341  videoFreeze = MHEG5FALSE;
2342  }
2343  #endif
2344 
2345  /* Note that stream settings have changed so that the media decoders can be
2346  * reprogrammed.
2347  */
2348  streamSettingsChanged = MHEG5TRUE;
2349  videoPositionChanged = MHEG5TRUE;
2350 }
2351 
2353 {
2354  return video_stream_ref.service_id;
2355 }
2356 
2358 {
2359  return audio_stream_ref.service_id;
2360 }
2361 
2363 {
2364  if (videoPlaying && video_stream_ref.service_id == service_id)
2365  {
2366  /* Notify platform that video PID may need refreshing */
2367  DVB_MhegVideoPlayStream( &video_stream_ref );
2368  }
2369  if (audioPlaying == AUDIO_PLAY_STREAM && audio_stream_ref.service_id == service_id)
2370  {
2371  /* Notify platform that audio PID may need refreshing */
2372  DVB_MhegAudioPlayStream( &audio_stream_ref );
2373  }
2374 }
2375 
2377 {
2378  DBGTRACE(TSTRM,"audioPlaying %u service_ids %u,%u",audioPlaying,audio_stream_ref.service_id,service_id)
2379  if (audioPlaying == AUDIO_PLAY_STREAM &&
2380  audio_stream_ref.service_id == service_id &&
2381  audio_stream_ref.ComponentTag == -1)
2382  {
2383  /* Notify platform that audio may need refreshing */
2384  DVB_MhegAudioPlayStream( &audio_stream_ref );
2385  }
2386 #ifdef INCLUDE_ICS
2387  else
2388  {
2389  MHEG5StreamerRefresh(); /* Check if refresh is needed in IC Streamer */
2390  }
2391 #endif
2392 }
2393 
2400 {
2401  MHEG5Ingredient **item;
2402 
2403  assert(stream);
2404 
2405  TRACE(TSTRM, ("strm{id=%d} play %ld, SS=%s", stream->ingredient.root.id, stream->ingredient.dataLen, SS(stream)))
2406 
2407  item = stream->multiplex;
2408  while (*item)
2409  {
2410  if ((*item)->root.runningStatus)
2411  {
2412  switch ((*item)->root.clazz)
2413  {
2414  case MHEG5AUDIO:
2416  break;
2417 
2418  case MHEG5VIDEO:
2420  MHEG5displayShow((MHEG5Visible *)*item);
2421  break;
2422 
2423 #ifndef MHEG5PROFILE_UK1_06
2424  case MHEG5RTGRAPHICS:
2426  /* Note that stream settings have changed so that the media decoders can be
2427  * reprogrammed.
2428  */
2429  streamSettingsChanged = MHEG5TRUE;
2430  break;
2431 #endif
2432 
2433  default:
2434  ERROR_PRINT(("ERROR: MHEG5displayStreamPlay: Illegal item class in stream multiplex\n"));
2435  break;
2436  }
2437  }
2438  item++;
2439  }
2440 
2442 }
2443 
2451 {
2452  TRACE(TSTRM, ("AP=%d", audioPlaying))
2453 
2454  audioPlaying = AUDIO_PLAY_NONE;
2455 
2456  /* Note that stream settings have changed so that the media decoders can be
2457  * reprogrammed.
2458  */
2459  streamSettingsChanged = MHEG5TRUE;
2460 }
2461 
2469 {
2470  TRACE(TSTRM, ("VP=%d", videoPlaying))
2471 
2472  videoPlaying = MHEG5FALSE;
2473 
2474  /* Note that stream settings have changed so that the media decoders can be
2475  * reprogrammed.
2476  */
2477  streamSettingsChanged = MHEG5TRUE;
2478 }
2479 
2488 {
2489  MHEG5Ingredient **item;
2490 
2491  assert(stream);
2492 
2493  TRACE(TSTRM, ("SS=%s", SS(stream)))
2494 
2495  item = stream->multiplex;
2496  while (*item)
2497  {
2498  switch ((*item)->root.clazz)
2499  {
2500  case MHEG5AUDIO:
2501  /* if (activeAudioObject == NULL) */
2502  TRACE(TSTRM, ("AP=%d", audioPlaying))
2503  if (audioPlaying == AUDIO_PLAY_NONE)
2504  {
2505  /* Can get here, for example, when audio clip stopped naturally
2506  * and the mheg app does 'stop' on stream as result of StreamStopped event
2507  * - as in case of test 3.5.3.
2508  */
2509  TRACE(TSTRM, (" NO active Audio"))
2510  }
2511  else
2512  {
2513  streamSettingsChanged = MHEG5TRUE;
2514  audioPlaying = AUDIO_PLAY_NONE;
2515  audio_stream_changed = MHEG5TRUE;
2516  }
2517  break;
2518 
2519  case MHEG5VIDEO:
2520  /* if (activeVideoObject == NULL) */
2521  if (videoPlaying == MHEG5FALSE)
2522  {
2523  TRACE(TSTRM, (" NO active Video"))
2524  }
2525  else
2526  {
2527  streamSettingsChanged = MHEG5TRUE;
2528  videoPositionChanged = MHEG5TRUE;
2529  videoPlaying = MHEG5FALSE;
2530  }
2531  /* Fix for scene 3 of DTG test 6.6.1) -
2532  * need to hide video plane (to show grey behind) */
2533  MHEG5displayHide((MHEG5Visible *)*item );
2534  break;
2535 
2536 #ifndef MHEG5PROFILE_UK1_06
2537  case MHEG5RTGRAPHICS:
2538  /* Note that stream settings have changed so that the media decoders can be
2539  * reprogrammed.
2540  */
2541  streamSettingsChanged = MHEG5TRUE;
2543  break;
2544 #endif
2545 
2546  default:
2547  ERROR_PRINT(("ERROR: MHEG5displayStreamStop: Illegal item class in stream multiplex\n"));
2548  break;
2549  }
2550  item++;
2551  }
2552 
2553  switch (stream->streamState)
2554  {
2555  case SS_PLAYING:
2556  case SS_PLAYING_CLIP:
2557  case SS_NEW_REF:
2558  case SS_FROZEN:
2559  case SS_STOPPING:
2560  TRACE(TSTRM, ("AVO=%d AAO=%p STM=%p", activeVideoObject, activeAudioObject, stream))
2561  TRACE(TSTRM, ("STOPPING AP=%d SS=%s", audioPlaying, SS(stream)))
2562  stream->streamState = SS_STOPPING;
2563  break;
2564 
2565  case SS_STARTING:
2566  default:
2567  TRACE(TSTRM, ("AVO=%d AAO=%p STM=%p", activeVideoObject, activeAudioObject, stream))
2568  TRACE(TSTRM, ("STOPPED AP=%d SS=%s", audioPlaying, SS(stream)))
2569  stream->streamState = SS_STOPPED;
2570  if (activeVideoObject && activeVideoObject->parent == stream)
2571  {
2572  activeVideoObject = NULL;
2573  }
2574  if (activeAudioObject && activeAudioObject->parent == stream)
2575  {
2576  activeAudioObject = NULL;
2577  }
2578  }
2579 }
2580 
2582 {
2583  if (activeAudioObject == audio)
2584  {
2585  TRACE(TSTRM, ("audio destroy %x SS=%s", audio, SS(audio->parent)))
2586  activeAudioObject = NULL;
2587  }
2588 }
2589 
2591 {
2592  if (activeVideoObject == video)
2593  {
2594  assert(video->visible.ingredient.root.clazz == MHEG5VIDEO);
2595  TRACE(TSTRM, (" video destroyed %x, SS=%s", video, SS(video->parent)))
2596  activeVideoObject = NULL;
2597  }
2598 }
2599 
2601 {
2602  TRACE(TSTRM, ("iframe destroyed, bmp=%p, AIO=%p", iframe, activeIframeObject))
2603  if (activeIframeObject == iframe)
2604  {
2605  activeIframeObject = NULL;
2606  }
2607 }
2608 
2615 {
2616  TRACE(TSTRM, ("bmp=%x, AIO=%x, ifrmPly=%d ch=%d", bitmap, activeIframeObject, iframePlaying,
2617  bitmap->visible.ingredient.contentHook))
2618 #ifndef INCLUDE_FREESAT
2621 #else
2624  bitmap->visible.ingredient.contentHook == CHOOK_BITMAP_IMAGE_PLANE_IFRAME );
2625  if (bitmap->visible.ingredient.contentHook == CHOOK_BITMAP_IMAGE_PLANE_IFRAME)
2626  {
2627  if (imagePlanePlaying)
2628  {
2629  E_VideoEncoding encoding;
2630  /* have had setData while iframe already showing */
2631  encoding = VIDEO_ENC_MPEG2;
2632 
2633  if (DVB_MhegDecodeImagePlaneIFrame( bitmap->visible.ingredient.data,
2634  bitmap->visible.ingredient.dataLen, encoding ) == MHERR_OK)
2635  {
2636  imagePlaneDecoded = MHEG5TRUE;
2637  }
2638  else
2639  {
2640  imagePlanePlaying = MHEG5FALSE;
2641  imagePlaneDecoded = MHEG5FALSE;
2642  }
2643  }
2644  else
2645  {
2646  imagePlanePlaying = MHEG5TRUE;
2647  }
2648  activeImagePlaneObject = bitmap;
2649  }
2650  else
2651 #endif
2652  {
2653  if (iframePlaying)
2654  {
2655  E_VideoEncoding encoding;
2656  /* have had setData while iframe already showing */
2658  encoding = VIDEO_ENC_H_264;
2659  else
2660  encoding = VIDEO_ENC_MPEG2;
2661 
2662  if (bitmap->visible.ingredient.data && bitmap->visible.ingredient.dataLen &&
2664  bitmap->visible.ingredient.dataLen, encoding ) == MHERR_OK)
2665  {
2666  iframeDecoded = MHEG5TRUE;
2667  }
2668  else
2669  {
2670  iframePlaying = MHEG5FALSE;
2671  iframeDecoded = MHEG5FALSE;
2672  }
2673  }
2674  else
2675  {
2676  if (videoPlaying)
2677  {
2678  /* stop playing video */
2679  videoPlaying = MHEG5FALSE;
2680  streamSettingsChanged = MHEG5TRUE;
2681  }
2682  if (streamSettingsChanged)
2683  {
2684  MHEG5displayUpdateStreamDecoders(MHEG5FALSE);
2685  }
2686  iframePlaying = MHEG5TRUE;
2687  }
2688  activeIframeObject = bitmap;
2689  }
2690  videoPositionChanged = MHEG5TRUE; /* set position of iframe in displayUpdate */
2691 }
2692 
2693 #ifdef INCLUDE_FREESAT
2694 
2698 void MHEG5displayImagePlaneStop(void)
2699 {
2700  TRACE(TSTRM, ("AIO=%x", activeIframeObject))
2701  if (DVB_MhegImagePlaneIFrameStop() != MHERR_OK)
2702  {
2703  ERROR_PRINT(("ERROR: OSDIFrameDisplayStop() - Failed to stop decoding IFrame\n"));
2704  }
2705  imagePlanePlaying = MHEG5FALSE;
2706  imagePlaneDecoded = MHEG5FALSE;
2707 #ifdef INCLUDE_FREESAT
2708  activeImagePlaneObject = NULL;
2709 #endif
2710 }
2711 
2712 #endif
2713 
2718 {
2719  TRACE(TSTRM, ("AIO=%x", activeIframeObject))
2721  {
2722  TRACE(TERROR, ("Failed to stop decoding IFrame %d", iframeDecoded));
2723  }
2724  iframePlaying = MHEG5FALSE;
2725  iframeDecoded = MHEG5FALSE;
2726  activeIframeObject = NULL;
2727 }
2728 
2730 {
2731  videoPositionChanged = MHEG5TRUE;
2732 }
2733 
2735 {
2736  /* check active video object and that it is not iframe */
2737  if (activeVideoObject != NULL)
2738  {
2739  MHEG5Stream *stream = activeVideoObject->parent;
2740 
2741  switch (stream->ingredient.contentHook)
2742  {
2743  case CHOOK_STREAM_NORMAL:
2744  TRACE(TSTRM, ("VP=%d SS=%s", videoPlaying, SS(stream)));
2745  if (stream->streamState > SS_STOPPING)
2746  {
2747  if (stream->streamState == SS_STARTING)
2748  {
2749  /* send stream playing event */
2751  }
2752  /* else SS_NEW_REF or SS_FROZEN,
2753  * now set to SS_PLAYING */
2754  stream->streamState = SS_PLAYING;
2755  }
2756  break;
2757  #ifdef INCLUDE_ICS
2758  case CHOOK_STREAM_IC:
2759  /*MHEG5StreamerNotifyStreamStarted(stream);*/
2760  break;
2761  #endif
2762  default:
2763  ;
2764  }
2765  }
2766  else
2767  {
2768  TRACE(TERROR, ("SS callback, NO video object"))
2769  }
2770 }
2771 
2773 {
2774  /* check active video object and that it is not iframe */
2775  if (activeVideoObject != NULL)
2776  {
2777  MHEG5Stream *stream = activeVideoObject->parent;
2778  switch (stream->ingredient.contentHook)
2779  {
2780  case CHOOK_STREAM_NORMAL:
2781  TRACE(TSTRM, ("AVO=%p STM=%p", activeVideoObject, stream));
2782  TRACE(TSTRM, ("VP=%d SS=%s", videoPlaying, SS(stream)));
2783  if (stream->streamState == SS_STOPPING)
2784  {
2785  /* send stream stopping event */
2787  stream->streamState = SS_STOPPED;
2788 
2789  /* Can have situation where action to start playing video has happened
2790  * (e.g. MHEG5displayVideoPlay),
2791  * but streams not yet updated due to lockScreen (i.e. app->lockCount != 0),
2792  * so check streamSettingsChanged is false
2793  */
2794  if (!streamSettingsChanged)
2795  {
2796  activeVideoObject = NULL;
2797  videoPlaying = MHEG5FALSE;
2798  }
2799  }
2800  else if (stream->streamState > SS_STOPPING)
2801  {
2802  TRACE(TERROR, ("SS=%s", SS(stream)));
2803  }
2804  break;
2805  #ifdef INCLUDE_ICS
2806  case CHOOK_STREAM_IC:
2807  /*MHEG5StreamerNotifyStreamStopped(stream);*/
2808  break;
2809  #endif
2810  default:
2811  ;
2812  }
2813  }
2814  else
2815  {
2816  TRACE(TSTRM, ("SS callback, but NO video object %x", activeVideoObject))
2817  }
2818 }
2819 
2821 {
2822  if (activeAudioObject != NULL)
2823  {
2824  MHEG5Stream *stream = activeAudioObject->parent;
2825  switch (stream->ingredient.contentHook)
2826  {
2827  case CHOOK_STREAM_NORMAL:
2828  case CHOOK_STREAM_MEMORY:
2829  TRACE(TSTRM, ("AAO=%p STM=%p", activeAudioObject, stream));
2830  TRACE(TSTRM, ("AP=%d isClp=%d SS=%s", audioPlaying, isClip, SS(stream)));
2831  if (stream->ingredient.root.runningStatus)
2832  {
2833  switch (stream->streamState)
2834  {
2835  case SS_STOPPED:
2836  case SS_STARTING:
2837  /* send stream playing event */
2839  /* fallthrough */
2840 
2841  case SS_NEW_REF:
2842  case SS_FROZEN:
2843  /* now set to SS_PLAYING */
2844  stream->streamState = isClip ? SS_PLAYING_CLIP : SS_PLAYING;
2845  default:;
2846  }
2847  }
2848  break;
2849  #ifdef INCLUDE_ICS
2850  case CHOOK_STREAM_IC:
2851  /*MHEG5StreamerNotifyStreamStarted(stream);*/
2852  break;
2853  #endif
2854  default:
2855  ;
2856  }
2857  }
2858  else
2859  {
2860  TRACE(TERROR, ("SS callback, but NO audio object AP=%d", audioPlaying))
2861  }
2862 }
2863 
2865 {
2866  if (activeAudioObject != NULL)
2867  {
2868  MHEG5Stream *stream = activeAudioObject->parent;
2869  switch (stream->ingredient.contentHook)
2870  {
2871  case CHOOK_STREAM_NORMAL:
2872  case CHOOK_STREAM_MEMORY:
2873  TRACE(TSTRM, ("AAO=%p STM=%p", activeAudioObject, stream));
2874  TRACE(TSTRM, ("AP=%d isClp=%d SS=%s", audioPlaying, isClip, SS(stream)));
2875  if (stream->ingredient.root.runningStatus)
2876  {
2877  if ((stream->streamState == SS_STOPPING) ||
2878  (isClip && (stream->streamState == SS_PLAYING_CLIP)))
2879  {
2880  TRACE(TSTRM, ("AP=%d", audioPlaying))
2881  /* send stream stopped event */
2883  stream->streamState = SS_STOPPED;
2884  activeAudioObject = NULL;
2885  audioPlaying = AUDIO_PLAY_NONE;
2886  }
2887  }
2888  break;
2889  #ifdef INCLUDE_ICS
2890  case CHOOK_STREAM_IC:
2891  /*MHEG5StreamerNotifyStreamStopped(stream);*/
2892  break;
2893  #endif
2894  default:
2895  ;
2896  }
2897  }
2898  else
2899  {
2900  TRACE(TSTRM, ("SS callback, but NO audio object AP=%d", audioPlaying))
2901  }
2902 }
2903 
2910 {
2911  TRACE(TSTRM, ("AVO=%x, AAO=%x", activeVideoObject, activeAudioObject))
2912  TRACE(TSTRM, ("AP=%d, VP=%d", audioPlaying, videoPlaying))
2913 
2914  /* Reset the stream decoders to their defaults when MHEG-5 is not running */
2915  activeVideoObject = NULL;
2916  activeIframeObject = NULL;
2917 
2918  videoPlaying = MHEG5FALSE;
2919  videoFreeze = MHEG5FALSE;
2920 
2921  audioPlaying = AUDIO_PLAY_DEFAULT;
2922  audioFreeze = MHEG5FALSE;
2923  audioVolume = 0;
2924 
2925  /* Clear the multiplex references to prevent old streams being displayed */
2926  memset(&audio_stream_ref, 0, sizeof(audio_stream_ref));
2927  memset(&video_stream_ref, 0, sizeof(video_stream_ref));
2928 
2929 #ifndef MHEG5PROFILE_UK1_06
2931 #endif
2932 
2933  /* Perform the update immediately */
2934  if (update)
2935  {
2937 
2938  MHEG5displayUpdateStreamDecoders(MHEG5TRUE);
2939  }
2940  else
2941  {
2942  /* Set the displayed video stream to the user selected preference */
2943  (void)DVB_MhegVideoPlayDefault();
2944  /* Set the presented audio stream to the user selected preference */
2945  (void)DVB_MhegAudioPlayDefault();
2946  lastTerminating = MHEG5TRUE;
2947  }
2948 }
2949 
2955 {
2956  displayStreamsAreLocked = MHEG5TRUE;
2957 }
2958 
2964 {
2965  displayStreamsAreLocked = MHEG5FALSE;
2966 }
2967 
2975 {
2976  audioVolume = volume;
2977 
2978  /* Note that stream settings have changed so that the media decoders can be
2979  * reprogrammed.
2980  */
2981  streamSettingsChanged = MHEG5TRUE;
2982 }
2983 
2984 #ifdef SURFACE_THRESHOLD
2985 
2993 void MHEG5displaySetSurfaceThreshold(S32BIT pixels)
2994 {
2995  surfaceThreshold = pixels;
2996 }
2997 
3010 static void SetSurfaceThreshold( MHEG5SurfaceThresholdEventParams_t *surfThresh )
3011 {
3012  MHEG5displaySetSurfaceThreshold(surfThresh->pixels);
3013  MHEG5groupDestroySurfaces(surfThresh->pixels);
3014 }
3015 
3030 {
3031  E_MhegErr result;
3032  MHEG5eventMessage_t event_msg;
3033 
3034  event_msg.proc_msg_func = SetSurfaceThreshold;
3035  event_msg.data_type = DT_NONE;
3036  event_msg.data.surfaceThreshold.pixels = pixels;
3037 
3038  result = VQ_PutMsg(&event_msg, PRTY_HIGH);
3039  if (result != MHERR_OK)
3040  {
3041  TRACE(TERROR, ("VQ_PutMsg Failed"));
3042  }
3043  return result;
3044 }
3045 
3046 #endif /* SURFACE_THRESHOLD */
MHEG5Visible visible
Definition: mh5slider.h:46
MHEG5Stream * parent
Definition: mh5audio.h:58
Implement MHEG5 engine control functions (i.e. start/stop etc)
Basis MHEG5 data types.
E_MhegErr VQ_PutMsg(S_MhegMessage *pMsg, E_PRIORITY priority)
Post event or section message on queue. Copies data into queue.
Definition: glue_queue.c:248
MHEG5Byte * data
Definition: mh5ingredient.h:80
#define DELTA_X
Definition: mh5display.c:67
E_VideoEncoding
Definition: dvb_video.h:95
void MHEG5displayRefreshStreams(U16BIT service_id)
Definition: mh5display.c:2362
void MHEG5displayAudioStop(void)
Stops playback of the audio media decoder.
Definition: mh5display.c:2450
void MHEG5displayRefreshDefaultAudio(U16BIT service_id)
Definition: mh5display.c:2376
MHEG5Int boxSize[2]
Definition: mh5visible.h:58
F_MSG_PROCESS proc_msg_func
Definition: glue_queue.h:198
#define TRANSPARENTCOLOR
Definition: tmcolor.h:37
Distributor for Prepare, Destruct, Activate, Deactivate and Clone calls. Distribute the +Prepare +Des...
MHEG5Int sliderValue
Definition: mh5slider.h:60
void MHEG5displayStreamUpdate(MHEG5Application *application)
Definition: mh5display.c:1997
E_MhegErr DVB_MhegAudioPlayDefault(void)
MHEG5 engine gives control of Audio to external application. Set decoding and presentation of Audio a...
#define SIGNF_X
Definition: mh5display.c:69
MHEG5Ingredient ingredient
Definition: mh5stream.h:65
MHEG5Int volume
Definition: mh5audio.h:55
struct sMHEG5Ingredient * next
Definition: mh5ingredient.h:83
#define DBGTRACE(...)
Definition: glue_debug.h:126
const char * stream_states[]
Definition: mh5display.c:82
void MHEG5displayHotspot(MHEG5Visible *visible, int x1, int y1, int x2, int y2)
Draw a Hotspot.
U16BIT original_network_id
Definition: dvblocator.h:39
void MHEG5drawHypertext(MHEG5Hypertext *hypertxt)
Definition: mh5drawtext.c:578
void MHEG5displayStreamStop(MHEG5Stream *stream)
Stops playback of all active component of the specified stream object.
Definition: mh5display.c:2487
MHEG5Int i
Definition: mh5base.h:154
void MHEG5displayLockStreams(void)
Lock streams, disallow any stream updates.
Definition: mh5display.c:2954
void MHEG5notifyAudioStopped(BOOLEAN isClip)
Definition: mh5display.c:2864
S_DVB_LOCATOR dvbLocator
Definition: mh5stream.h:82
MHEG5String s
Definition: mh5base.h:156
U16BIT transport_stream_id
Definition: dvblocator.h:40
void MHEG5displayPause(void)
Definition: mh5display.c:1422
U16BIT type
Definition: mh5base.h:151
MHEG5String value
Definition: mh5cookies.c:52
#define CHOOK_STREAM_NORMAL
Definition: mh5profile.h:107
MHEG5 queue.
MHEG5Colour desktopColour
#define MHEG5_MULTIPLEX_REF_VALID(mux)
Definition: mh5display.c:78
void MHEG5displayStreamPlay(MHEG5Stream *stream)
Begin playback of all active components in the specifed stream object.
Definition: mh5display.c:2399
#define CHOOK_UNSPECIFIED
Definition: mh5profile.h:91
MHEG5Int looping
Definition: mh5stream.h:71
U32BIT OSDColor
Definition: osdtypes.h:41
void MG_OSDdisplayDynamicLineart(void *data, S_REGION *overlap, int x, int y)
Display dynamic lineart.
Definition: mg_dla.c:1050
#define CHOOK_BITMAP_NORMAL_IFRAME
Definition: mh5profile.h:94
void MG_DrawJpg(void *data, int len, MHEG5Visible *visible)
Definition: mg_bmp.c:236
MHEG5Final clazz
Definition: mh5root.h:55
#define SD_HEIGHT
Definition: osdtype.h:30
MHEG5Int maxValue
Definition: mh5slider.h:63
MHEG5Colour sliderRefColour
Definition: mh5slider.h:57
Stream event subscription management.
MHEG5Bool highlightStatus
void MHEG5displayRTGraphics(MHEG5RTGraphics *rtgraphics, int x1, int y1, int x2, int y2)
void MG_FreeData(void *data)
free surface buffer
Definition: mg_osd.c:1536
void DVB_MhegSetVideoScaling(S_RECTANGLE *scaling)
Set Mheg video scaling.
S16BIT top
Definition: osdtypes.h:46
void MHEG5displaySwitchbutton(MHEG5Visible *visible, int x1, int y1, int x2, int y2)
Draw a Switchbutton.
void MHEG5groupRedraw(MHEG5Root *group)
Definition: mh5display.c:1485
void MHEG5drawEntry(MHEG5Entryfield *entry, entryfieldCursor_t cursor)
Definition: mh5drawtext.c:502
union MHEG5Generic::@6 value
int16_t S16BIT
Definition: techtype.h:85
void MHEG5streamFindCurrentService(void)
Find the current service (i.e. the service corresponding to the currently running Video...
Definition: mh5stream.c:1129
#define MG_OSDUpdate
Definition: mg_api.h:34
U16BIT transport_stream_id
Definition: dvblocator.h:33
void MG_OSDclear(void)
Clear the screen, making it the specified colour.
Definition: mg_osd.c:888
E_MhegErr
Definition: mherrors.h:28
void MHEG5displayIFrameStart(MHEG5Bitmap *bitmap)
Start displaying an I-Frame.
Definition: mh5display.c:2614
void MG_DrawPng(void *data, int len, MHEG5Visible *visible)
Definition: mg_bmp.c:161
void MHEG5displayIframeDestroy(MHEG5Bitmap *iframe)
Definition: mh5display.c:2600
void MG_SetVideoPosition(MHEG5Video *video, MHEG5Int contentHook)
Definition: mg_video.c:105
E_MhegErr DVB_MhegVideoStopStream(void)
MHEG5 engine takes control of Video - and specifies that decoding and presentation of any Video strea...
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
Definition: mh5base.c:686
void * graphic_data
Definition: mh5visible.h:64
void MHEG5displayVisUpd(MHEG5Visible *visible, U8BIT upd)
Definition: mh5display.c:736
U16BIT original_network_id
Definition: dvblocator.h:32
void MHEG5displayVideoDestroy(MHEG5Video *video)
Definition: mh5display.c:2590
uint8_t U8BIT
Definition: techtype.h:82
#define CHOOK_BITMAP_JPG
Definition: mh5profile.h:99
void MHEG5notifyAudioStarted(BOOLEAN isClip)
Definition: mh5display.c:2820
long MHEG5Int
Definition: mh5base.h:73
OSDColor OSDgetColour(const char *colour, int len)
Converts an MHEG5 colour value to an OSDColor type.
Definition: tmcolor.c:53
MHEG5Int speed[2]
Definition: mh5stream.h:74
#define CHOOK_BITMAP_H264_IFRAME
Definition: mh5profile.h:100
void MHEG5displayUpdate(void)
Update the display, redrawing any visible objects that are in the dirty rectangle.
Definition: mh5display.c:2035
DVB Video functions are required by MHEG5 engine. All required functions should be non-blocking...
void MHEG5displayResetStreamDecoders(BOOLEAN update)
Reset all media decoders to default values. This is used when the MHEG-5 engine is terminated...
Definition: mh5display.c:2909
E_MhegErr DVB_MhegVideoPlayStream(S_DvbComponent *pDvbComponent)
MHEG5 engine takes control of Video - and informs that Video must be switched to the specified Video ...
void MH5_DisplayEntry(MHEG5Entryfield *entry, S_REGION *overlap)
Definition: mh5drawtext.c:671
API for IC streamer.
MHEG5Group group
This file defines the profile for the MHEG engine.
void MHEG5displayRtgraphicsPlay(MHEG5RTGraphics *rtgraphics)
Begin playback of the specified RTGraphics object.
E_MhegErr DVB_MhegVideoSetUpdating(E_VideoState displayState)
Switch between frozen or unfrozen video display (reacting on either the current or subsequent frame)...
#define MAX_RECTS
Definition: mh5display.c:66
U16BIT MHEG5GetVideoSid(void)
Definition: mh5display.c:2352
void MHEG5displayResume(void)
Definition: mh5display.c:1395
void MHEG5displayVideoPlay(MHEG5Video *video)
Begin playback of the specified video object.
Definition: mh5display.c:2273
short MHEG5Bool
Definition: mh5base.h:71
E_StreamState streamState
Definition: mh5stream.h:81
#define MHEG5displayHide(v)
Definition: mh5display.h:46
MHEG5Bool storageMemory
Definition: mh5stream.h:69
MHEG5Int portion
Definition: mh5slider.h:61
Interface to OSD.
#define SIGNF_Y
Definition: mh5display.c:70
MHEG5Int minValue
Definition: mh5slider.h:62
S16BIT right
Definition: osdtypes.h:47
MHEG5Stream * parent
Definition: mh5video.h:65
Event handling. Implementation of a combined queue for events and actions. This is the eventsystem wh...
#define CHOOK_STREAM_MEMORY
Definition: mh5profile.h:108
MHEG5Byte * data
Definition: mh5base.h:85
MHEG5DisplayStackItem * displayStackBottom
BOOLEAN MHEG5StreamerIsRunable(MHEG5Stream *stream)
Check that stream is runable (i.e. MHEG5StreamerPrepare has been called for it)
void MHEG5displayShowAll(void)
Redisplay all active visible objects. AKD: Optimised 12/5/99.
Definition: mh5display.c:1362
int32_t S32BIT
Definition: techtype.h:87
#define MHEG5TRUE
Definition: mh5base.h:49
S16BIT bottom
Definition: osdtypes.h:48
E_DATA_TYPE data_type
Definition: glue_queue.h:199
#define MIN(a, b)
Definition: mh5display.c:73
#define MHEG5displayShow(v)
Definition: mh5display.h:45
MHEG5Group group
Definition: mh5scene.h:46
uint16_t U16BIT
Definition: techtype.h:84
Implement functions to retrieve MHEG5objects by GroupID and ID.
MHEG5Int sceneCoordinateSystem[2]
Definition: mh5scene.h:50
MHEG5Ingredient * multiplex[MAX_MLTPLX]
Definition: mh5stream.h:68
Implementation of the MHEG5 Application Class Defines a set of Ingredient objects, which are shared within an application scope. Base class: Group Subclasses: None Status: Concrete class.
void MG_OSDdisplayVideo(S_REGION rgn)
Display video window.
Definition: mg_osd.c:729
#define TRACER(x)
Definition: glue_debug.h:123
Mheg5 logging and debug printing.
void MHEG5initDynamicLineart(MHEG5DynamicLineart *dynamicLineart)
Create the canvas for a dynamic lineart object.
void MG_VideoPositionReset(void)
Definition: mg_video.c:374
void MG_OSDdisplayRectangle(S_REGION *overlap, int x, int y, int width, int height, int lineWidth, OSDColor lineColour, OSDColor fillColour)
Draw rectangle.
Definition: mg_osd.c:566
U16BIT service_id
Definition: dvblocator.h:34
MHEG class interface to graphics text render.
MHEG5Bool runningStatus
Definition: mh5root.h:51
MHEG5Ingredient ingredient
Definition: mh5visible.h:49
MHEG5Visible visible
Definition: mh5video.h:49
void MHEG5StreamerRefresh(void)
Refresh any running IC streams - called when user preferences have changed.
E_MhegErr DVB_MhegAudioStopClip(void)
Instruct the controlling application that playback of the previously supplied audio clip should be st...
MHEG5Orientation orientation
Definition: mh5slider.h:50
DVB Audio functions are required by MHEG5 engine. All required functions should be non-blocking...
MHEG5Root root
Definition: mh5group.h:50
void MHEG5displayIFrameStop(void)
Stop displaying an I-Frame.
Definition: mh5display.c:2717
#define MAX(a, b)
Definition: mh5display.c:72
U16BIT MHEG5GetAudioSid(void)
Definition: mh5display.c:2357
redirection include
MHEG5Int id
Definition: mh5root.h:48
void MHEG5displayClear(void)
<Function description>="">
Definition: mh5display.c:220
E_MhegErr DVB_MhegAudioPlayStream(S_DvbComponent *pDvbComponent)
MHEG5 engine takes control of Audio - and informs that Audio must be switched to the specified Audio ...
OSDColor MHEG5displayColour(MHEG5Colour *colour)
Convert Generic Colour value to OSD specific value. If the generic colour is encoded as a string it i...
Definition: mh5display.c:256
S16BIT left
Definition: osdtypes.h:45
MHEG5Interactible interactible
Definition: mh5slider.h:47
U16BIT service_id
Definition: dvblocator.h:41
#define ERROR_PRINT(x)
Definition: mh5debug.h:76
MHEG5Scene * MHEG5getCurrentScene(void)
<Function description>="">
Definition: mh5scene.c:207
void MHEG5sendEvent(MHEG5Root *source, MHEG5EventType event, MHEG5Int data)
Store an event in the asynchronous event queue.
Definition: mh5queue.c:1540
void MHEG5displayAudioPlay(MHEG5Audio *audio)
Begin playback of the specified audio object.
Definition: mh5display.c:2150
void MHEG5streamSetCurrentService(MHEG5Ingredient *item, S_DvbComponent *service)
Set the current service.
Definition: mh5stream.c:1233
#define SD_WIDTH
Definition: osdtype.h:31
MHEG5Int MHEG5streamGetComponentTag(MHEG5Ingredient *item)
Get component tag for ingredient. This depends on the stream&#39;s content and the component tag of the i...
Definition: mh5stream.c:1293
S16BIT ComponentTag
Definition: dvblocator.h:42
MHEG5Int len
Definition: mh5base.h:84
#define DELTA_Y
Definition: mh5display.c:68
void MG_OSDerase(S_REGION rgn, OSDColor colour)
Erase an area of the OSD to the desktop colour.
Definition: mg_osd.c:808
void MHEG5displayRtGraphicsReset(void)
Reset all media decoders to default values. This is used when the MHEG-5 engine is terminated...
Interaction Channel Streaming functions required by MHEG5 engine References: [1] UK1 Profile - Digita...
void MH5_DisplayText(MHEG5Text *txt, S_REGION *overlap)
Definition: mh5drawtext.c:646
Definition of colour type for MHEG5 - settings and conversions.
U8BIT BOOLEAN
Definition: techtype.h:99
void MHEG5StreamerRun(MHEG5Stream *stream)
Start streaming IP content for a prepared request.
E_MhegErr DVB_MhegAudioPlayClip(U8BIT *pAudioData, U32BIT dataLength, U32BIT repeatCount, E_AudioEncoding encoding)
Instruct the controlling application that the provided audio sound clip should be played...
Include all classes.
void MHEG5freeDynamicLineart(MHEG5DynamicLineart *dynamicLineart)
Create the canvas for a dynamic lineart object.
E_MhegErr DVB_MhegVideoPlayDefault(void)
MHEG5 engine gives control of Video to external application. Set decoding and presentation of Video a...
E_MhegErr MHEG5_SetSurfaceThreshold(S32BIT pixels)
Set the minimum number of pixels that force the MHEG-5 engine to release a surface immediately after ...
E_MhegErr DVB_MhegAudioSetVolume(S32BIT volumeAdjust)
Adjust sound level for any external application sourced audio. A setting of 0 dB means leave the audi...
Implement generic MHEG5-display functions - independent from the OSD These are generic functions used...
void MHEG5displayRtgraphicsStop(void)
Stops playback of the RTGraphics (subtitle) media decoder.
E_MhegErr DVB_MhegICStreamAudioSetVolume(S32BIT volumeAdjust)
Set volume for audio component of the currently playing IC stream This function is equivalent to DVB_...
void MHEG5displayPushbutton(MHEG5Visible *visible, int x1, int y1, int x2, int y2)
Draw a Pushbutton.
Video Scaling / Positioning functionality.
#define CHOOK_BITMAP_PNG
Definition: mh5profile.h:95
E_AudioPlayState
Definition: mh5display.c:95
MHEG5Int contentHook
Definition: mh5ingredient.h:69
#define CHOOK_STREAM_IC
Definition: mh5profile.h:111
union s_mhg_message::@13 data
E_MhegErr DVB_MhegAudioSetSpeed(E_AudioSpeed speed)
Instruct the controlling application that playback of the previously supplied audio clip should be pa...
void MHEG5notifyVideoStopped(void)
Definition: mh5display.c:2772
S_REGION rect
Definition: mh5visible.h:65
MHEG5Int position[2]
Definition: mh5visible.h:59
void MG_OSDdisplayBitmap(MHEG5Visible *visible, S_REGION *overlap)
Definition: mg_bmp.c:298
MHEG5SliderStyle sliderStyle
Definition: mh5slider.h:56
#define MHEG5FALSE
Definition: mh5base.h:48
void MHEG5drawText(MHEG5Text *txt)
Definition: mh5drawtext.c:485
void MHEG5displayVideoPositionUpdate(void)
Definition: mh5display.c:2729
void MHEG5groupClearImages(MHEG5Root *group)
Definition: mh5display.c:1451
E_MhegErr DVB_MhegAudioStopStream(void)
MHEG5 engine takes control of Audio - and specifies that decoding and presentation of any Audio strea...
void MHEG5displaySetVolume(MHEG5Int volume)
Volume Control.
Definition: mh5display.c:2974
MHEG5Colour highlightRefColour
struct sMHEG5DisplayStackItem * prev
MHEG5Visible visible
Definition: mh5bitmap.h:45
void MHEG5displayLineart(int x1, int y1, int boxX1, int boxY1, int boxX2, int boxY2, MHEG5Bool bbbox, MHEG5Int lineWidth, MHEG5Int lineStyle, MHEG5Colour *refLineColour, MHEG5Colour *refFillColour)
Draw a Lineart Object.
E_MhegErr DVB_MhegVideoPlayIFrame(U8BIT *pVideoData, U32BIT dataLength, E_VideoEncoding encoding)
Instruct the controlling application to decode supplied video data. The I-Frame is displayed in the v...
void MHEG5displayUnlockStreams(void)
Unlock streams, allow stream updates.
Definition: mh5display.c:2963
E_MhegErr DVB_MhegVideoStopIFrame(void)
Instruct the controlling application to stop displaying the previously supplied video data in DVB_Mhe...
void MHEG5displayRtGraphicsUpdate(MHEG5Bool terminating, MHEG5Bool fullScreen)
void MHEG5displayVideoStop(void)
Stops playback of the video media decoder.
Definition: mh5display.c:2468
MHEG5Application * MHEG5getCurrentApplication(void)
<Function description>="">
void MHEG5notifyVideoStarted(void)
Definition: mh5display.c:2734
void MHEG5displayAudioDestroy(MHEG5Audio *audio)
Definition: mh5display.c:2581
#define TRACE(t, x)
Definition: glue_debug.h:118