+ subpicture_region_t *p_region = p_subpic->p_region;
+ int i_scale_width, i_scale_height;
+
+ /* Load the blending module */
+ if( !p_spu->p_blend && p_region )
+ {
+ p_spu->p_blend = vlc_object_create( p_spu, sizeof(filter_t) );
+ vlc_object_attach( p_spu->p_blend, p_spu );
+ p_spu->p_blend->fmt_out.video.i_x_offset =
+ p_spu->p_blend->fmt_out.video.i_y_offset = 0;
+ p_spu->p_blend->fmt_out.video.i_aspect = p_fmt->i_aspect;
+ p_spu->p_blend->fmt_out.video.i_chroma = p_fmt->i_chroma;
+
+ p_spu->p_blend->fmt_in.video.i_chroma = VLC_FOURCC('Y','U','V','P');
+
+ p_spu->p_blend->p_module =
+ module_Need( p_spu->p_blend, "video blending", 0, 0 );
+ }
+
+ /* Load the text rendering module */
+ if( !p_spu->p_text && p_region )
+ {
+ p_spu->p_text = vlc_object_create( p_spu, sizeof(filter_t) );
+ vlc_object_attach( p_spu->p_text, p_spu );
+
+ p_spu->p_text->fmt_out.video.i_width =
+ p_spu->p_text->fmt_out.video.i_visible_width =
+ p_fmt->i_width;
+ p_spu->p_text->fmt_out.video.i_height =
+ p_spu->p_text->fmt_out.video.i_visible_height =
+ p_fmt->i_height;
+
+ p_spu->p_text->pf_sub_buffer_new = spu_new_buffer;
+ p_spu->p_text->pf_sub_buffer_del = spu_del_buffer;
+
+ p_spu->p_text->p_module =
+ module_Need( p_spu->p_text, "text renderer", 0, 0 );
+ }
+
+ i_scale_width = i_scale_width_orig;
+ i_scale_height = i_scale_height_orig;
+
+ if( p_subpic->i_original_picture_width &&
+ p_subpic->i_original_picture_height )
+ {
+ i_scale_width = i_scale_width * p_fmt->i_width /
+ p_subpic->i_original_picture_width;
+ i_scale_height = i_scale_height * p_fmt->i_height /
+ p_subpic->i_original_picture_height;
+ }
+
+ /* Load the scaling module */
+ if( !p_spu->p_scale && (i_scale_width != 1000 ||
+ i_scale_height != 1000) )
+ {
+ p_spu->p_scale = vlc_object_create( p_spu, VLC_OBJECT_FILTER );
+ vlc_object_attach( p_spu->p_scale, p_spu );
+ p_spu->p_scale->fmt_out.video.i_chroma =
+ p_spu->p_scale->fmt_in.video.i_chroma =
+ VLC_FOURCC('Y','U','V','P');
+ p_spu->p_scale->fmt_in.video.i_width =
+ p_spu->p_scale->fmt_in.video.i_height = 32;
+ p_spu->p_scale->fmt_out.video.i_width =
+ p_spu->p_scale->fmt_out.video.i_height = 16;
+
+ p_spu->p_scale->pf_vout_buffer_new = spu_new_video_buffer;
+ p_spu->p_scale->pf_vout_buffer_del = spu_del_video_buffer;
+ p_spu->p_scale->p_module =
+ module_Need( p_spu->p_scale, "video filter2", 0, 0 );
+ }
+
+ if( p_subpic->pf_render )
+ {
+ /* HACK to remove when the ogt subpic decoder is gone */
+ if( p_spu->p_parent &&
+ p_spu->p_parent->i_object_type == VLC_OBJECT_VOUT )
+ {
+ vout_thread_t *p_vout = (vout_thread_t *)p_spu->p_parent;
+ p_subpic->pf_render( p_vout, p_pic_dst, p_subpic );
+ }
+ }
+ else while( p_region && p_spu->p_blend &&
+ p_spu->p_blend->pf_video_blend )
+ {
+ int i_x_offset = p_region->i_x + p_subpic->i_x;
+ int i_y_offset = p_region->i_y + p_subpic->i_y;
+
+ if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )
+ {
+ if( p_spu->p_text && p_spu->p_text->p_module &&
+ p_spu->p_text->pf_render_string )
+ {
+ /* TODO: do it in a less hacky way
+ * (modify text renderer API) */
+ subpicture_t *p_subpic_tmp;
+ subpicture_region_t tmp_region;
+ block_t *p_new_block =
+ block_New( p_spu, strlen(p_region->psz_text) + 1 );
+
+ if( p_new_block )
+ {
+ memcpy( p_new_block->p_buffer, p_region->psz_text,
+ p_new_block->i_buffer );
+ p_new_block->i_pts = p_new_block->i_dts =
+ p_subpic->i_start;
+ p_new_block->i_length =
+ p_subpic->i_start - p_subpic->i_stop;
+ p_subpic_tmp = p_spu->p_text->pf_render_string(
+ p_spu->p_text, p_new_block );
+
+ if( p_subpic_tmp )
+ {
+ tmp_region = *p_region;
+ *p_region = *p_subpic_tmp->p_region;
+ p_region->p_next = tmp_region.p_next;
+ *p_subpic_tmp->p_region = tmp_region;
+ p_spu->p_text->pf_sub_buffer_del( p_spu->p_text,
+ p_subpic_tmp );
+ }
+ }
+ }
+ }
+
+ /* Force palette if requested */
+ if( p_spu->b_force_alpha && VLC_FOURCC('Y','U','V','P') ==
+ p_region->fmt.i_chroma )
+ {
+ p_region->fmt.p_palette->palette[0][3] = p_spu->pi_alpha[0];
+ p_region->fmt.p_palette->palette[1][3] = p_spu->pi_alpha[1];
+ p_region->fmt.p_palette->palette[2][3] = p_spu->pi_alpha[2];
+ p_region->fmt.p_palette->palette[3][3] = p_spu->pi_alpha[3];
+ }
+
+ /* Scale SPU if necessary */
+ if( p_region->p_cache )
+ {
+ if( i_scale_width * p_region->fmt.i_width / 1000 !=
+ p_region->p_cache->fmt.i_width ||
+ i_scale_height * p_region->fmt.i_height / 1000 !=
+ p_region->p_cache->fmt.i_height )
+ {
+ p_subpic->pf_destroy_region( VLC_OBJECT(p_spu),
+ p_region->p_cache );
+ p_region->p_cache = 0;
+ }
+ }
+ if( (i_scale_width != 1000 || i_scale_height != 1000) &&
+ p_spu->p_scale && !p_region->p_cache )
+ {
+ picture_t *p_pic;
+
+ p_spu->p_scale->fmt_in.video = p_region->fmt;
+ p_spu->p_scale->fmt_out.video = p_region->fmt;
+
+ p_region->p_cache =
+ p_subpic->pf_create_region( VLC_OBJECT(p_spu),
+ &p_spu->p_scale->fmt_out.video );
+ if( p_spu->p_scale->fmt_out.video.p_palette )
+ *p_spu->p_scale->fmt_out.video.p_palette =
+ *p_region->fmt.p_palette;
+ p_region->p_cache->p_next = p_region->p_next;
+
+ vout_CopyPicture( p_spu, &p_region->p_cache->picture,
+ &p_region->picture );
+
+ p_spu->p_scale->fmt_out.video.i_width =
+ p_region->fmt.i_width * i_scale_width / 1000;
+ p_spu->p_scale->fmt_out.video.i_visible_width =
+ p_region->fmt.i_visible_width * i_scale_width / 1000;
+ p_spu->p_scale->fmt_out.video.i_height =
+ p_region->fmt.i_height * i_scale_height / 1000;
+ p_spu->p_scale->fmt_out.video.i_visible_height =
+ p_region->fmt.i_visible_height * i_scale_height / 1000;
+ p_region->p_cache->fmt = p_spu->p_scale->fmt_out.video;
+ p_region->p_cache->i_x = p_region->i_x * i_scale_width / 1000;
+ p_region->p_cache->i_y = p_region->i_y * i_scale_height / 1000;
+
+ p_pic = p_spu->p_scale->pf_video_filter(
+ p_spu->p_scale, &p_region->p_cache->picture );
+ if( p_pic )
+ {
+ picture_t p_pic_tmp = p_region->p_cache->picture;
+ p_region->p_cache->picture = *p_pic;
+ *p_pic = p_pic_tmp;
+ free( p_pic );
+ }
+ }
+ if( (i_scale_width != 1000 || i_scale_height != 1000) &&
+ p_spu->p_scale && p_region->p_cache )
+ {
+ p_region = p_region->p_cache;
+ }
+
+ if( p_subpic->i_flags & SUBPICTURE_ALIGN_BOTTOM )
+ {
+ i_y_offset = p_fmt->i_height - p_region->fmt.i_height -
+ p_subpic->i_y;
+ }
+ else if ( !(p_subpic->i_flags & SUBPICTURE_ALIGN_TOP) )
+ {
+ i_y_offset = p_fmt->i_height / 2 - p_region->fmt.i_height / 2;
+ }
+
+ if( p_subpic->i_flags & SUBPICTURE_ALIGN_RIGHT )
+ {
+ i_x_offset = p_fmt->i_width - p_region->fmt.i_width -
+ p_subpic->i_x;
+ }
+ else if ( !(p_subpic->i_flags & SUBPICTURE_ALIGN_LEFT) )
+ {
+ i_x_offset = p_fmt->i_width / 2 - p_region->fmt.i_width / 2;
+ }
+
+ if( p_subpic->b_absolute )
+ {
+ i_x_offset = p_region->i_x +
+ p_subpic->i_x * i_scale_width / 1000;
+ i_y_offset = p_region->i_y +
+ p_subpic->i_y * i_scale_height / 1000;
+
+ if( p_spu->i_margin >= 0 )
+ {
+ if( p_subpic->i_height + (unsigned int)p_spu->i_margin <=
+ p_fmt->i_height )
+ {
+ i_y_offset = p_fmt->i_height -
+ p_spu->i_margin - p_subpic->i_height;
+ }
+ }
+ }
+
+ p_spu->p_blend->fmt_in.video = p_region->fmt;
+
+ /* Force cropping if requested */
+ if( p_spu->b_force_crop )
+ {
+ video_format_t *p_fmt = &p_spu->p_blend->fmt_in.video;
+ int i_crop_x = p_spu->i_crop_x * i_scale_width / 1000;
+ int i_crop_y = p_spu->i_crop_y * i_scale_height / 1000;
+ int i_crop_width = p_spu->i_crop_width * i_scale_width / 1000;
+ int i_crop_height = p_spu->i_crop_height * i_scale_height/1000;
+
+ /* Find the intersection */
+ if( i_crop_x + i_crop_width <= i_x_offset ||
+ i_x_offset + (int)p_fmt->i_visible_width < i_crop_x ||
+ i_crop_y + i_crop_height <= i_y_offset ||
+ i_y_offset + (int)p_fmt->i_visible_height < i_crop_y )
+ {
+ /* No intersection */
+ p_fmt->i_visible_width = p_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)p_fmt->i_visible_width );
+ i_y_end = __MIN( i_crop_y + i_crop_height,
+ i_y_offset + (int)p_fmt->i_visible_height );
+
+ p_fmt->i_x_offset = i_x - i_x_offset;
+ p_fmt->i_y_offset = i_y - i_y_offset;
+ p_fmt->i_visible_width = i_x_end - i_x;
+ p_fmt->i_visible_height = i_y_end - i_y;
+
+ i_x_offset = i_x;
+ i_y_offset = i_y;
+ }
+ }
+
+ /* Update the output picture size */
+ p_spu->p_blend->fmt_out.video.i_width =
+ p_spu->p_blend->fmt_out.video.i_visible_width =
+ p_fmt->i_width;
+ p_spu->p_blend->fmt_out.video.i_height =
+ p_spu->p_blend->fmt_out.video.i_visible_height =
+ p_fmt->i_height;
+
+ p_spu->p_blend->pf_video_blend( p_spu->p_blend, p_pic_dst,
+ p_pic_src, &p_region->picture, i_x_offset, i_y_offset );
+
+ p_region = p_region->p_next;
+ }
+