MHEG-5  19.3.0
MHEG-5 Documentation
mg_video.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2008 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include <string.h>
27 #include "dvb_video.h"
28 #include "mg_video.h"
29 #include "mg_api.h"
30 #include "mg_osd.h"
31 
32 #include "mh5profile.h"
33 #include "mh5debug.h"
34 
35 #include "glue_main.h"
36 
37 #ifdef INCLUDE_ICS
38 #include "dvb_ics.h"
39 #endif
40 
41 
42 typedef struct _S_Region
43 {
44  S32BIT left;
45  S32BIT top;
46  S32BIT right;
47  S32BIT bottom;
48 } S_Region;
49 
50 
51 /*---local (static) variable declarations for this file----------------------*/
52 
53 /* Initial values are unlikely to be used in a real application */
54 static MHEG5Bool mg_subtitle_on = MHEG5TRUE;
55 static MHEG5Bool mg_full_screen = MHEG5TRUE;
56 static S_RECTANGLE mg_video_scaling = { -1000, -1000, 1000, 1000 };
57 #ifdef INCLUDE_FREESAT
58 static S_RECTANGLE mg_image_scaling = { -1000, -1000, 1000, 1000 };
59 #endif
60 
61 static void Mheg5ToScalingCoordinates( S_RECTANGLE *rect )
62 {
63  S32BIT tmp;
64  /* Translate according to MHEG5 HD rules */
65  DBGTRACE(TGRAPHICS, " RatioX (%d/%d)", mg_ctxt.vid_x.mlt, mg_ctxt.vid_x.div);
66  tmp = rect->left + rect->width;
67  rect->left = (rect->left * mg_ctxt.vid_x.mlt) / mg_ctxt.vid_x.div;
68  tmp = (tmp * mg_ctxt.vid_x.mlt) / mg_ctxt.vid_x.div;
69  rect->width = tmp - rect->left;
70  DBGTRACE(TGRAPHICS, " RatioY (%d/%d)", mg_ctxt.vid_y.mlt, mg_ctxt.vid_y.div);
71  tmp = rect->top + rect->height;
72  rect->top = (rect->top * mg_ctxt.vid_y.mlt) / mg_ctxt.vid_y.div;
73  tmp = (tmp * mg_ctxt.vid_y.mlt) / mg_ctxt.vid_y.div;
74  rect->height = tmp - rect->top;
75  DBGTRACE(TGRAPHICS,"%ux%u", rect->width, rect->height);
76 }
77 
78 
79 /*---global function definitions---------------------------------------------*/
80 
89 void MG_SetSubtitleMode(MHEG5Bool subtitleOn)
90 {
91  if (mg_subtitle_on != subtitleOn)
92  {
93  mg_subtitle_on = subtitleOn;
94  if (subtitleOn && mg_full_screen)
95  {
96  DVB_MhegSubtitleSetVisibility(MHEG5_DVB_SUBTITLE_SHOW);
97  }
98  else
99  {
100  DVB_MhegSubtitleSetVisibility(MHEG5_DVB_SUBTITLE_HIDE);
101  }
102  }
103 }
104 
105 void MG_SetVideoPosition( MHEG5Video *video, MHEG5Int contentHook )
106 {
107  S_Region rgn;
108  S32BIT xOffset, yOffset;
109  S_RECTANGLE new_video_scaling;
110  MHEG5Bool fullscreen = MHEG5FALSE;
111 
112  if (video && video->visible.ingredient.root.runningStatus)
113  {
114  rgn.left = video->visible.position[0];
115  rgn.top = video->visible.position[1];
116  rgn.right = video->visible.position[0] + video->visible.boxSize[0];
117  rgn.bottom = video->visible.position[1] + video->visible.boxSize[1];
118 
119  xOffset = video->visible.position[0] + video->xOffset;
120  yOffset = video->visible.position[1] + video->yOffset;
121  new_video_scaling.left = xOffset;
122  new_video_scaling.top = yOffset;
123  TRACE(TGRAPHICS | TSTRM | TSTATE, ("rgn=(%d,%d,%d,%d) offset=(%d,%d)", rgn.left, rgn.top, rgn.right, rgn.bottom, xOffset, yOffset))
124 
125  /*clip to SD coordinate screen*/
126  if (rgn.left < 0)
127  rgn.left = 0;
128  else if (rgn.left > mg_ctxt.input_width)
129  rgn.left = mg_ctxt.input_width;
130 
131  if (rgn.top < 0)
132  rgn.top = 0;
133  else if (rgn.top > mg_ctxt.input_height)
134  rgn.top = mg_ctxt.input_height;
135 
136  if (rgn.right > mg_ctxt.input_width)
137  rgn.right = mg_ctxt.input_width;
138  else if (rgn.right < 0)
139  rgn.right = 0;
140 
141  if (rgn.bottom > mg_ctxt.input_height)
142  rgn.bottom = mg_ctxt.input_height;
143  else if (rgn.bottom < 0)
144  rgn.bottom = 0;
145  TRACE(TGRAPHICS | TSTRM | TSTATE, ("rgn=(%d,%d,%d,%d) offset=(%d,%d)", rgn.left, rgn.top, rgn.right, rgn.bottom, xOffset, yOffset))
146 
147  /* Check for sensible width/height */
148  if (rgn.right < rgn.left) rgn.right = rgn.left;
149  if (rgn.bottom < rgn.top) rgn.bottom = rgn.top;
150 
151  /* Check whether offset clips output */
152  if (video->scaleSet)
153  {
154  if (xOffset + video->xScale < rgn.right)
155  {
156  rgn.right = video->xScale + xOffset;
157  }
158  if (yOffset + video->yScale < rgn.bottom)
159  {
160  rgn.bottom = video->yScale + yOffset;
161  }
162  }
163  else
164  {
165  if (xOffset + mg_ctxt.input_width < rgn.right)
166  {
167  rgn.right = mg_ctxt.input_width + xOffset;
168  }
169  if (yOffset + mg_ctxt.input_height < rgn.bottom)
170  {
171  rgn.bottom = mg_ctxt.input_height + yOffset;
172  }
173  }
174  if (rgn.left < xOffset)
175  {
176  rgn.left = xOffset;
177  xOffset = 0;
178  }
179  else
180  {
181  xOffset = rgn.left - xOffset;
182  }
183  if (rgn.top < yOffset)
184  {
185  rgn.top = yOffset;
186  yOffset = 0;
187  }
188  else
189  {
190  yOffset = rgn.top - yOffset;
191  }
192  TRACE(TGRAPHICS | TSTRM | TSTATE, ("rgn=(%d,%d,%d,%d) offset=(%d,%d)", rgn.left, rgn.top, rgn.right, rgn.bottom, xOffset, yOffset));
193 
194  if (!video->scaleSet)
195  {
196  TRACE(TGRAPHICS | TSTRM | TSTATE, ("No SCALE rgn=(%d,%d,%d,%d) offset=(%d,%d)", rgn.left, rgn.top, rgn.right, rgn.bottom, xOffset, yOffset))
197  new_video_scaling.width = (U16BIT)SD_WIDTH;
198  new_video_scaling.height = (U16BIT)SD_HEIGHT;
199  if (new_video_scaling.left == 0 && new_video_scaling.top == 0)
200  {
201  fullscreen = MHEG5TRUE;
202  }
203  }
204  else
205  {
206  TRACE(TGRAPHICS | TSTRM | TSTATE, ("SCALE(%d,%d) rgn=(%d,%d,%d,%d) offset=(%d,%d)", (int)video->xScale, (int)video->yScale,
207  rgn.left, rgn.top, rgn.right, rgn.bottom, xOffset, yOffset))
208  new_video_scaling.width = (U16BIT)video->xScale;
209  new_video_scaling.height = (U16BIT)video->yScale;
210  if (new_video_scaling.left == 0 && new_video_scaling.top == 0 &&
211  new_video_scaling.width == SD_WIDTH && new_video_scaling.height == SD_HEIGHT)
212  {
213  fullscreen = MHEG5TRUE;
214  }
215  }
216  }
217  else
218  {
219  TRACE(TGRAPHICS | TSTRM | TSTATE, ("default video position"))
220  new_video_scaling.top = 0;
221  new_video_scaling.left = 0;
222  new_video_scaling.width = SD_WIDTH;
223  new_video_scaling.height = SD_HEIGHT;
224  fullscreen = MHEG5TRUE;
225  }
226  #ifdef INCLUDE_FREESAT
227  if (contentHook == CHOOK_BITMAP_IMAGE_PLANE_IFRAME)
228  {
229  if (new_video_scaling.height != mg_image_scaling.height ||
230  new_video_scaling.width != mg_image_scaling.width ||
231  new_video_scaling.left != mg_image_scaling.left ||
232  new_video_scaling.top != mg_image_scaling.top
233  )
234  {
235  mg_image_scaling = new_video_scaling;
236  if (fullscreen)
237  {
238  DVB_MhegSetImageScaling( NULL );
239  }
240  else
241  {
242  /* only after assigning values to global can we translate to final
243  * coordinates. Otherwise VideoToGraphics will be wrong */
244  Mheg5ToScalingCoordinates( &new_video_scaling );
245  DVB_MhegSetImageScaling( &new_video_scaling );
246  }
247  }
248  }
249  else
250  #endif
251  if (new_video_scaling.height != mg_video_scaling.height ||
252  new_video_scaling.width != mg_video_scaling.width ||
253  new_video_scaling.left != mg_video_scaling.left ||
254  new_video_scaling.top != mg_video_scaling.top
255  )
256  {
257  mg_video_scaling = new_video_scaling;
258  if (fullscreen)
259  {
260  DVB_MhegSetVideoScaling( NULL );
261  }
262  else
263  {
264  /* only after assigning values to global can we translate to final
265  * coordinates. Otherwise VideoToGraphics will be wrong */
266  Mheg5ToScalingCoordinates( &new_video_scaling );
267  DVB_MhegSetVideoScaling( &new_video_scaling );
268  }
269  }
270  if (mg_full_screen != fullscreen)
271  {
272  mg_full_screen = fullscreen;
273  if (fullscreen && mg_subtitle_on)
274  {
275  DVB_MhegSubtitleSetVisibility(MHEG5_DVB_SUBTITLE_SHOW);
276  }
277  else
278  {
279  DVB_MhegSubtitleSetVisibility(MHEG5_DVB_SUBTITLE_HIDE);
280  }
281  }
282 }
283 
294 void MG_DisplayVideoToGraphics( MHEG5Int videoXval, MHEG5Int videoYval,
295  MHEG5Int *graphicsXVal, MHEG5Int *graphicsYVal )
296 {
297  E_FORMAT_CONVERSION formatConversion;
298  BOOLEAN scaled;
299  S32BIT width = (S32BIT)mg_video_scaling.width;
300  S32BIT height = (S32BIT)mg_video_scaling.height;
301 #ifdef INCLUDE_USER_DEFINED_VTG
302  S32BIT xVal, yVal;
303 #endif /* INCLUDE_USER_DEFINED_VTG */
304 
305  scaled = TRUE;
306  formatConversion = DVB_MhegGetDecoderFormatConversion();
307  switch (formatConversion)
308  {
309  case FORMAT_CONVERSION_UNKNOWN:
310  case FORMAT_CONVERSION_IGNORE:
311  *graphicsXVal = width * videoXval;
312  *graphicsYVal = height * videoYval;
313  break;
314  case FORMAT_CONVERSION_PANSCAN:
315  *graphicsXVal = width * (8 * videoXval - SD_WIDTH) / 6;
316  *graphicsYVal = height * videoYval;
317  break;
318  case FORMAT_CONVERSION_LETTERBOX:
319  *graphicsXVal = width * videoXval;
320  *graphicsYVal = height * (6 * videoYval + SD_HEIGHT) / 8;
321  break;
322  case FORMAT_CONVERSION_LETTERBOX_14_9:
323  *graphicsXVal = width * (16 * videoXval - SD_WIDTH) / 14;
324  *graphicsYVal = height * (12 * videoYval + SD_HEIGHT) / 14;
325  break;
326  case FORMAT_CONVERSION_PILLAR_BOX:
327  *graphicsXVal = width * (6 * videoXval + SD_WIDTH) / 8;
328  *graphicsYVal = height * videoYval;
329  break;
330  case FORMAT_CONVERSION_ZOOM_4_3:
331  *graphicsXVal = width * videoXval;
332  *graphicsYVal = height * (8 * videoYval - SD_HEIGHT) / 6;
333  break;
334  case FORMAT_CONVERSION_CENTRE_4_3:
335  *graphicsXVal = width * (8 * videoXval - SD_WIDTH) / 6;
336  *graphicsYVal = height * (8 * videoYval - SD_HEIGHT) / 6;
337  break;
338  case FORMAT_CONVERSION_ZOOM_14_9:
339  *graphicsXVal = width * (14 * videoXval + SD_WIDTH) / 16;
340  *graphicsYVal = height * (14 * videoYval - SD_HEIGHT) / 12;
341  break;
342  case FORMAT_CONVERSION_PANSCAN_14_9:
343  *graphicsXVal = width * (14 * videoXval - SD_WIDTH) / 12;
344  *graphicsYVal = height * (14 * videoYval - SD_HEIGHT) / 12;
345  break;
346  case FORMAT_CONVERSION_CENTRE_14_9:
347  *graphicsXVal = width * (16 * videoXval - SD_WIDTH) / 14;
348  *graphicsYVal = height * (16 * videoYval - SD_HEIGHT) / 14;
349  break;
350 #ifdef INCLUDE_USER_DEFINED_VTG
351  case FORMAT_CONVERSION_USER_DEFINED:
352  tmMHEG5VideoToGraphics(videoXval, videoYval, &xVal, &yVal);
353  *graphicsXVal = ((xVal * mg_ctxt.vid_x.div + mg_ctxt.vid_x.mlt / 2) /
354  mg_ctxt.vid_x.mlt);
355  *graphicsYVal = ((yVal * mg_ctxt.vid_y.div + mg_ctxt.vid_y.mlt / 2) /
356  mg_ctxt.vid_y.mlt);
357  scaled = FALSE;
358  break;
359 #endif /* INCLUDE_USER_DEFINED_VTG */
360  default:
361  *graphicsXVal = width * videoXval;
362  *graphicsYVal = height * videoYval;
363  }
364 
365  if (scaled)
366  {
367  *graphicsXVal = ((*graphicsXVal + SD_WIDTH / 2) / SD_WIDTH +
368  mg_video_scaling.left);
369  *graphicsYVal = ((*graphicsYVal + SD_HEIGHT / 2) / SD_HEIGHT +
370  mg_video_scaling.top);
371  }
372 }
373 
374 void MG_VideoPositionReset(void)
375 {
376  memset(&mg_video_scaling, 0, sizeof(S_RECTANGLE));
377  /* do not set mg_full_screen to either MHEG5TRUE or MHEG5FALSE,
378  * so that MG_SetVideoPosition() will be forced to call DVB_MhegSubtitleSetVisibility() */
379  mg_full_screen = TRUE;
380 }
381 
void MG_SetSubtitleMode(MHEG5Bool subtitleOn)
Set the current subtitle display mode to be either On or Off, Should only have an impact if subtitles...
Definition: mg_video.c:89
void DVB_MhegSetVideoScaling(S_RECTANGLE *scaling)
Set Mheg video scaling.
E_MhegErr DVB_MhegSubtitleSetVisibility(E_DvbSubtitleShowState showState)
Show or hide DVB subtitles. This operation remains in force until set again by another call to this f...
DVB Video functions are required by MHEG5 engine. All required functions should be non-blocking...
This file defines the profile for the MHEG engine.
Interface to OSD.
Mheg5 logging and debug printing.
void MG_DisplayVideoToGraphics(MHEG5Int videoXval, MHEG5Int videoYval, MHEG5Int *graphicsXVal, MHEG5Int *graphicsYVal)
Calculate the graphical co-ordinate from a given video coordinate (should take into account the curre...
Definition: mg_video.c:294
Interaction Channel Streaming functions required by MHEG5 engine References: [1] UK1 Profile - Digita...
Video Scaling / Positioning functionality.
#define TRACE(t, x)
Definition: glue_debug.h:118