+/*****************************************************************************
+ * RenderSubPicture: render a subpicture
+ *****************************************************************************
+ * This function render a sub picture unit.
+ *****************************************************************************/
+static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
+{
+ p_vout_font_t p_font; /* text font */
+ int i_width, i_height; /* subpicture dimensions */
+
+ while( p_subpic != NULL )
+ {
+ switch( p_subpic->i_type )
+ {
+ case DVD_SUBPICTURE: /* DVD subpicture unit */
+ /* test if the picture really has to be displayed */
+ if( mdate() < p_subpic->begin_date )
+ {
+ /* not yet, see you later */
+ break;
+ }
+ if( mdate() > p_subpic->end_date )
+ {
+ /* too late, destroying the subpic */
+ vout_DestroySubPicture( p_vout, p_subpic );
+ break;
+ }
+ vout_RenderSPU( &p_vout->p_buffer[ p_vout->i_buffer_index ],
+ p_subpic, p_vout->i_bytes_per_pixel,
+ p_vout->i_bytes_per_line );
+ break;
+ case TEXT_SUBPICTURE: /* single line text */
+ /* Select default font if not specified */
+ p_font = p_subpic->type.text.p_font;
+ if( p_font == NULL )
+ {
+ p_font = p_vout->p_default_font;
+ }
+
+ /* Compute text size (width and height fields are ignored)
+ * and print it */
+ vout_TextSize( p_font, p_subpic->type.text.i_style,
+ p_subpic->p_data, &i_width, &i_height );
+ if( !Align( p_vout, &p_subpic->i_x, &p_subpic->i_y,
+ i_width, i_height, p_subpic->i_horizontal_align,
+ p_subpic->i_vertical_align ) )
+ {
+ vout_Print( p_font,
+ p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
+ p_subpic->i_x * p_vout->i_bytes_per_pixel +
+ p_subpic->i_y * p_vout->i_bytes_per_line,
+ p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
+ p_subpic->type.text.i_char_color,
+ p_subpic->type.text.i_border_color,
+ p_subpic->type.text.i_bg_color,
+ p_subpic->type.text.i_style, p_subpic->p_data );
+ SetBufferArea( p_vout, p_subpic->i_x, p_subpic->i_y,
+ i_width, i_height );
+ }
+ break;
+
+#ifdef DEBUG
+ default:
+ intf_DbgMsg( "error: unknown subpicture %p type %d\n",
+ p_subpic, p_subpic->i_type );
+#endif
+ }
+
+ p_subpic = p_subpic->p_next;
+ }
+}
+
+/*****************************************************************************
+ * RenderInterface: render the interface
+ *****************************************************************************
+ * This function render the interface, if any.
+ *****************************************************************************/
+static void RenderInterface( vout_thread_t *p_vout )
+{
+ int i_height, i_text_height; /* total and text height */
+ int i_width_1, i_width_2; /* text width */
+ int i_byte; /* byte index */
+ const char *psz_text_1 = "[1-9] Channel [i]nfo [c]olor [g/G]amma";
+ const char *psz_text_2 = "[+/-] Volume [m]ute [s]caling [Q]uit";
+
+ /* Get text size */
+ vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_1, &i_width_1, &i_height );
+ vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_2, &i_width_2, &i_text_height );
+ i_height += i_text_height;
+
+ /* Render background */
+ for( i_byte = (p_vout->i_height - i_height) * p_vout->i_bytes_per_line;
+ i_byte < p_vout->i_height * p_vout->i_bytes_per_line;
+ i_byte++ )
+ {
+ /* XXX?? noooo ! */
+ p_vout->p_buffer[ p_vout->i_buffer_index ].p_data[ i_byte ] = p_vout->i_blue_pixel;
+ }
+
+ /* Render text, if not larger than screen */
+ if( i_width_1 < p_vout->i_width )
+ {
+ vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
+ (p_vout->i_height - i_height) * p_vout->i_bytes_per_line,
+ p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
+ p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
+ OUTLINED_TEXT, psz_text_1 );
+ }
+ if( i_width_2 < p_vout->i_width )
+ {
+ vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
+ (p_vout->i_height - i_height + i_text_height) * p_vout->i_bytes_per_line,
+ p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
+ p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
+ OUTLINED_TEXT, psz_text_2 );
+ }
+
+ /* Activate modified area */
+ SetBufferArea( p_vout, 0, p_vout->i_height - i_height, p_vout->i_width, i_height );
+}
+
+/*****************************************************************************
+ * Synchronize: update synchro level depending of heap state
+ *****************************************************************************
+ * This function is called during the main vout loop.
+ *****************************************************************************/
+static void Synchronize( vout_thread_t *p_vout, s64 i_delay )
+{
+ int i_synchro_inc = 0;
+ /* XXX?? gore following */
+ static int i_panic_count = 0;
+ static int i_last_synchro_inc = 0;
+ static float r_synchro_level = VOUT_SYNCHRO_LEVEL_START;
+ static int i_truc = 10;
+
+ if( i_delay < 0 )
+ {
+ //fprintf( stderr, "PANIC %d\n", i_panic_count );
+ i_panic_count++;
+ }
+
+ i_truc *= 2;
+
+ if( p_vout->i_pictures > VOUT_SYNCHRO_HEAP_IDEAL_SIZE+1 )
+ {
+ i_truc = 40;
+ i_synchro_inc += p_vout->i_pictures - VOUT_SYNCHRO_HEAP_IDEAL_SIZE - 1;
+
+ }
+ else
+ {
+ if( p_vout->i_pictures < VOUT_SYNCHRO_HEAP_IDEAL_SIZE )
+ {
+ i_truc = 32;
+ i_synchro_inc += p_vout->i_pictures - VOUT_SYNCHRO_HEAP_IDEAL_SIZE;
+ }
+ }
+
+ if( i_truc > VOUT_SYNCHRO_LEVEL_MAX*2*2*2*2*2 ||
+ i_synchro_inc*i_last_synchro_inc < 0 )
+ {
+ i_truc = 32;
+ }
+
+ if( i_delay < 6000 )
+ {
+ i_truc = 16;
+ i_synchro_inc -= 2;
+ }
+ else if( i_delay < 70000 )
+ {
+ i_truc = 24+(24*i_delay)/70000;
+ if( i_truc < 16 )
+ i_truc = 16;
+ i_synchro_inc -= 1+(5*(70000-i_delay))/70000;
+ }
+ else if( i_delay > 100000 )
+ {
+ r_synchro_level += 1;
+ if( i_delay > 130000 )
+ r_synchro_level += 1;
+ }
+
+ r_synchro_level += (float)i_synchro_inc / i_truc;
+ p_vout->i_synchro_level = (int)(r_synchro_level+0.5);
+
+ if( r_synchro_level > VOUT_SYNCHRO_LEVEL_MAX )
+ {
+ r_synchro_level = VOUT_SYNCHRO_LEVEL_MAX;
+ }
+
+ //fprintf( stderr, "synchro level : %d, heap : %d (%d, %d) (%d, %f) - %Ld\n", p_vout->i_synchro_level,
+ // p_vout->i_pictures, i_last_synchro_inc, i_synchro_inc, i_truc, r_synchro_level, i_delay );
+ i_last_synchro_inc = i_synchro_inc;
+}
+
+/*****************************************************************************