- * It will render the provided region onto p_pic_dst.
- */
-
-static void SpuRenderRegion( spu_t *p_spu,
- picture_t *p_pic_dst, spu_area_t *p_area,
- subpicture_t *p_subpic, subpicture_region_t *p_region,
- const spu_scale_t scale_size,
- const video_format_t *p_fmt,
- const spu_area_t *p_subtitle_area, int i_subtitle_area )
-{
- spu_private_t *p_sys = p_spu->p;
-
- video_format_t fmt_original = p_region->fmt;
- bool b_rerender_text = false;
- bool b_restore_format = false;
- int i_x_offset;
- int i_y_offset;
-
- video_format_t region_fmt;
- picture_t *p_region_picture;
-
- /* Invalidate area by default */
- *p_area = spu_area_create( 0,0, 0,0, scale_size );
-
- /* Render text region */
- if( p_region->fmt.i_chroma == VLC_CODEC_TEXT )
- {
- const int i_min_scale_ratio = SCALE_UNIT; /* FIXME what is the right value? (scale_size is not) */
- SpuRenderText( p_spu, &b_rerender_text, p_subpic, p_region, i_min_scale_ratio );
- b_restore_format = b_rerender_text;
-
- /* Check if the rendering has failed ... */
- if( p_region->fmt.i_chroma == VLC_CODEC_TEXT )
- goto exit;
- }
-
- /* Force palette if requested
- * FIXME b_force_palette and b_force_crop are applied to all subpictures using palette
- * instead of only the right one (being the dvd spu).
- */
- const bool b_using_palette = p_region->fmt.i_chroma == VLC_CODEC_YUVP;
- const bool b_force_palette = b_using_palette && p_sys->b_force_palette;
- const bool b_force_crop = b_force_palette && p_sys->b_force_crop;
- bool b_changed_palette = false;
-
-
- /* Compute the margin which is expressed in destination pixel unit
- * The margin is applied only to subtitle and when no forced crop is
- * requested (dvd menu) */
- int i_margin_y = 0;
- if( !b_force_crop && p_subpic->b_subtitle )
- i_margin_y = spu_invscale_h( p_sys->i_margin, scale_size );
-
- /* Place the picture
- * We compute the position in the rendered size */
- SpuRegionPlace( &i_x_offset, &i_y_offset,
- p_subpic, p_region, i_margin_y );
-
- /* Save this position for subtitle overlap support
- * it is really important that there are given without scale_size applied */
- *p_area = spu_area_create( i_x_offset, i_y_offset,
- p_region->fmt.i_width, p_region->fmt.i_height,
- scale_size );
-
- /* Handle overlapping subtitles when possible */
- if( p_subpic->b_subtitle && !p_subpic->b_absolute )
- {
- spu_area_t display = spu_area_create( 0, 0, p_fmt->i_width, p_fmt->i_height,
- spu_scale_unit() );
-
- SpuAreaFixOverlap( p_area, &display, p_subtitle_area, i_subtitle_area,
- p_region->i_align );
- }
-
- /* Fix the position for the current scale_size */
- i_x_offset = spu_scale_w( p_area->i_x, p_area->scale );
- i_y_offset = spu_scale_h( p_area->i_y, p_area->scale );
-
- /* */
- if( b_force_palette )
- {
- video_palette_t *p_palette = p_region->fmt.p_palette;
- video_palette_t palette;
-
- /* We suppose DVD palette here */
- palette.i_entries = 4;
- for( int i = 0; i < 4; i++ )
- for( int j = 0; j < 4; j++ )
- palette.palette[i][j] = p_sys->palette[i][j];
-
- if( p_palette->i_entries == palette.i_entries )
- {
- for( int i = 0; i < p_palette->i_entries; i++ )
- for( int j = 0; j < 4; j++ )
- b_changed_palette |= p_palette->palette[i][j] != palette.palette[i][j];
- }
- else
- {
- b_changed_palette = true;
- }
- *p_palette = palette;
- }
-
- /* */
- region_fmt = p_region->fmt;
- p_region_picture = p_region->p_picture;
-
-
- /* Scale from rendered size to destination size */
- if( p_sys->p_scale && p_sys->p_scale->p_module &&
- ( !b_using_palette || ( p_sys->p_scale_yuvp && p_sys->p_scale_yuvp->p_module ) ) &&
- ( scale_size.w != SCALE_UNIT || scale_size.h != SCALE_UNIT || b_using_palette ) )
- {
- const unsigned i_dst_width = spu_scale_w( p_region->fmt.i_width, scale_size );
- const unsigned i_dst_height = spu_scale_h( p_region->fmt.i_height, scale_size );
-
- /* Destroy the cache if unusable */
- if( p_region->p_private )
- {
- subpicture_region_private_t *p_private = p_region->p_private;
- bool b_changed = false;
-
- /* Check resize changes */
- if( i_dst_width != p_private->fmt.i_width ||
- i_dst_height != p_private->fmt.i_height )
- b_changed = true;
-
- /* Check forced palette changes */
- if( b_changed_palette )
- b_changed = true;
-
- if( b_changed )
- {
- SpuRegionPrivateDelete( p_private );
- p_region->p_private = NULL;
- }
- }
-
- /* Scale if needed into cache */
- if( !p_region->p_private && i_dst_width > 0 && i_dst_height > 0 )
- {
- filter_t *p_scale = p_sys->p_scale;
-
- picture_t *p_picture = p_region->p_picture;
- picture_Hold( p_picture );
-
- /* Convert YUVP to YUVA/RGBA first for better scaling quality */
- if( b_using_palette )
- {
- filter_t *p_scale_yuvp = p_sys->p_scale_yuvp;
-
- p_scale_yuvp->fmt_in.video = p_region->fmt;
-
- /* TODO converting to RGBA for RGB video output is better */
- p_scale_yuvp->fmt_out.video = p_region->fmt;
- p_scale_yuvp->fmt_out.video.i_chroma = VLC_CODEC_YUVA;
-
- p_picture = p_scale_yuvp->pf_video_filter( p_scale_yuvp, p_picture );
- if( !p_picture )
- {
- /* Well we will try conversion+scaling */
- msg_Warn( p_spu, "%4.4s to %4.4s conversion failed",
- (const char*)&p_scale_yuvp->fmt_in.video.i_chroma,
- (const char*)&p_scale_yuvp->fmt_out.video.i_chroma );
- }
- }
-
- /* Conversion(except from YUVP)/Scaling */
- if( p_picture &&
- ( p_picture->format.i_width != i_dst_width ||
- p_picture->format.i_height != i_dst_height ) )
- {
- p_scale->fmt_in.video = p_picture->format;
- p_scale->fmt_out.video = p_picture->format;
-
- p_scale->fmt_out.video.i_width = i_dst_width;
- p_scale->fmt_out.video.i_height = i_dst_height;
-
- p_scale->fmt_out.video.i_visible_width =
- spu_scale_w( p_region->fmt.i_visible_width, scale_size );
- p_scale->fmt_out.video.i_visible_height =
- spu_scale_h( p_region->fmt.i_visible_height, scale_size );
-
- p_picture = p_scale->pf_video_filter( p_scale, p_picture );
- if( !p_picture )
- msg_Err( p_spu, "scaling failed" );
- }
-
- /* */
- if( p_picture )
- {
- p_region->p_private = SpuRegionPrivateNew( &p_picture->format );
- if( p_region->p_private )
- {
- p_region->p_private->p_picture = p_picture;
- if( !p_region->p_private->p_picture )
- {
- SpuRegionPrivateDelete( p_region->p_private );
- p_region->p_private = NULL;
- }
- }
- else
- {
- picture_Release( p_picture );
- }
- }
- }
-
- /* And use the scaled picture */
- if( p_region->p_private )
- {
- region_fmt = p_region->p_private->fmt;
- p_region_picture = p_region->p_private->p_picture;
- }
- }
-
- /* Force cropping if requested */
- if( b_force_crop )
- {
- int i_crop_x = spu_scale_w( p_sys->i_crop_x, scale_size );
- int i_crop_y = spu_scale_h( p_sys->i_crop_y, scale_size );
- int i_crop_width = spu_scale_w( p_sys->i_crop_width, scale_size );
- int i_crop_height= spu_scale_h( p_sys->i_crop_height,scale_size );
-
- /* Find the intersection */
- if( i_crop_x + i_crop_width <= i_x_offset ||
- i_x_offset + (int)region_fmt.i_visible_width < i_crop_x ||
- i_crop_y + i_crop_height <= i_y_offset ||
- i_y_offset + (int)region_fmt.i_visible_height < i_crop_y )
- {
- /* No intersection */
- region_fmt.i_visible_width =
- region_fmt.i_visible_height = 0;
- }
- else
- {
- int i_x, i_y, i_x_end, i_y_end;
- i_x = __MAX( i_crop_x, i_x_offset );
- i_y = __MAX( i_crop_y, i_y_offset );
- i_x_end = __MIN( i_crop_x + i_crop_width,
- i_x_offset + (int)region_fmt.i_visible_width );
- i_y_end = __MIN( i_crop_y + i_crop_height,
- i_y_offset + (int)region_fmt.i_visible_height );