📄 vout_subpictures.c
字号:
}/** * Allocate a subpicture in the spu heap. * * This function create a reserved subpicture in the spu heap. * A null pointer is returned if the function fails. This method provides an * already allocated zone of memory in the spu data fields. It needs locking * since several pictures can be created by several producers threads. * \param p_spu the subpicture unit in which to create the subpicture * \return NULL on error, a reserved subpicture otherwise */subpicture_t *spu_CreateSubpicture( spu_t *p_spu ){ int i_subpic; /* subpicture index */ subpicture_t * p_subpic = NULL; /* first free subpicture */ /* Get lock */ vlc_mutex_lock( &p_spu->subpicture_lock ); /* * Look for an empty place */ p_subpic = NULL; for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ ) { if( p_spu->p_subpicture[i_subpic].i_status == FREE_SUBPICTURE ) { /* Subpicture is empty and ready for allocation */ p_subpic = &p_spu->p_subpicture[i_subpic]; p_spu->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE; break; } } /* If no free subpicture could be found */ if( p_subpic == NULL ) { msg_Err( p_spu, "subpicture heap is full" ); vlc_mutex_unlock( &p_spu->subpicture_lock ); return NULL; } /* Copy subpicture information, set some default values */ memset( p_subpic, 0, sizeof(subpicture_t) ); p_subpic->i_status = RESERVED_SUBPICTURE; p_subpic->b_absolute = VLC_TRUE; p_subpic->b_fade = VLC_FALSE; p_subpic->i_alpha = 0xFF; p_subpic->p_region = 0; p_subpic->pf_render = 0; p_subpic->pf_destroy = 0; p_subpic->p_sys = 0; vlc_mutex_unlock( &p_spu->subpicture_lock ); p_subpic->pf_create_region = __spu_CreateRegion; p_subpic->pf_make_region = __spu_MakeRegion; p_subpic->pf_destroy_region = __spu_DestroyRegion; return p_subpic;}/** * Remove a subpicture from the heap * * This function frees a previously reserved subpicture. * It is meant to be used when the construction of a picture aborted. * This function does not need locking since reserved subpictures are ignored * by the spu. */void spu_DestroySubpicture( spu_t *p_spu, subpicture_t *p_subpic ){ /* Get lock */ vlc_mutex_lock( &p_spu->subpicture_lock ); /* There can be race conditions so we need to check the status */ if( p_subpic->i_status == FREE_SUBPICTURE ) { vlc_mutex_unlock( &p_spu->subpicture_lock ); return; } /* Check if status is valid */ if( ( p_subpic->i_status != RESERVED_SUBPICTURE ) && ( p_subpic->i_status != READY_SUBPICTURE ) ) { msg_Err( p_spu, "subpicture %p has invalid status %d", p_subpic, p_subpic->i_status ); } while( p_subpic->p_region ) { subpicture_region_t *p_region = p_subpic->p_region; p_subpic->p_region = p_region->p_next; spu_DestroyRegion( p_spu, p_region ); } if( p_subpic->pf_destroy ) { p_subpic->pf_destroy( p_subpic ); } p_subpic->i_status = FREE_SUBPICTURE; vlc_mutex_unlock( &p_spu->subpicture_lock );}/***************************************************************************** * spu_RenderSubpictures: render a subpicture list ***************************************************************************** * This function renders all sub picture units in the list. *****************************************************************************/void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt, picture_t *p_pic_dst, picture_t *p_pic_src, subpicture_t *p_subpic, int i_scale_width_orig, int i_scale_height_orig ){ /* Get lock */ vlc_mutex_lock( &p_spu->subpicture_lock ); /* Check i_status again to make sure spudec hasn't destroyed the subpic */ while( p_subpic != NULL && p_subpic->i_status != FREE_SUBPICTURE ) { subpicture_region_t *p_region = p_subpic->p_region; int i_scale_width, i_scale_height; int i_subpic_x = p_subpic->i_x; /* Load the blending module */ if( !p_spu->p_blend && p_region ) { p_spu->p_blend = vlc_object_create( p_spu, VLC_OBJECT_FILTER ); 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, VLC_OBJECT_FILTER ); 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 ); } else if( p_region ) { 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; } 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; } /* Set default subpicture aspect ratio */ if( p_region && p_region->fmt.i_aspect && (!p_region->fmt.i_sar_num || !p_region->fmt.i_sar_den) ) { p_region->fmt.i_sar_den = p_region->fmt.i_aspect; p_region->fmt.i_sar_num = VOUT_ASPECT_FACTOR; } if( p_region && (!p_region->fmt.i_sar_num || !p_region->fmt.i_sar_den) ) { p_region->fmt.i_sar_den = p_fmt->i_sar_den; p_region->fmt.i_sar_num = p_fmt->i_sar_num; } /* Take care of the aspect ratio */ if( p_region && p_region->fmt.i_sar_num * p_fmt->i_sar_den != p_region->fmt.i_sar_den * p_fmt->i_sar_num ) { i_scale_width = i_scale_width * (int64_t)p_region->fmt.i_sar_num * p_fmt->i_sar_den / p_region->fmt.i_sar_den / p_fmt->i_sar_num; i_subpic_x = p_subpic->i_x * i_scale_width / 1000; } /* 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 ); } while( p_region && p_spu->p_blend && p_spu->p_blend->pf_video_blend ) { int i_fade_alpha = 255; int i_x_offset = p_region->i_x + i_subpic_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_text ) { p_region->i_text_align = p_subpic->i_flags & 0x3; p_spu->p_text->pf_render_text( p_spu->p_text, p_region, p_region ); } } /* Force palette if requested */ if( p_spu->b_force_palette && VLC_FOURCC('Y','U','V','P') == p_region->fmt.i_chroma ) { memcpy( p_region->fmt.p_palette->palette, p_spu->palette, 16 ); } /* 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 - i_subpic_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 + i_subpic_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -