void subpicture_Update( subpicture_t *p_subpicture, const video_format_t *p_fmt_src, const video_format_t *p_fmt_dst, mtime_t i_ts ) { subpicture_updater_t *p_upd = &p_subpicture->updater; subpicture_private_t *p_private = p_subpicture->p_private; if( !p_upd->pf_validate ) return; if( !p_upd->pf_validate( p_subpicture, !video_format_IsSimilar( p_fmt_src, &p_private->src ), p_fmt_src, !video_format_IsSimilar( p_fmt_dst, &p_private->dst ), p_fmt_dst, i_ts ) ) return; subpicture_region_ChainDelete( p_subpicture->p_region ); p_subpicture->p_region = NULL; p_upd->pf_update( p_subpicture, p_fmt_src, p_fmt_dst, i_ts ); video_format_Clean( &p_private->src ); video_format_Clean( &p_private->dst ); video_format_Copy( &p_private->src, p_fmt_src ); video_format_Copy( &p_private->dst, p_fmt_dst ); }
static void vlc_vidsplit_Close(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; int n = sys->splitter.i_output; for (int i = 0; i < n; i++) { struct vlc_vidsplit_part *part = &sys->parts[i]; vout_display_t *display; vlc_sem_wait(&part->lock); display = part->display; part->display = NULL; vlc_sem_post(&part->lock); if (display != NULL) vout_display_Delete(display); vout_window_Disable(part->window); vout_window_Delete(part->window); vlc_sem_destroy(&part->lock); } module_unneed(&sys->splitter, sys->splitter.p_module); video_format_Clean(&sys->splitter.fmt); vlc_mutex_destroy(&sys->lock); vlc_object_release(&sys->splitter); }
static int blendbench_LoadImage( vlc_object_t *p_this, picture_t **pp_pic, vlc_fourcc_t i_chroma, char *psz_file, const char *psz_name ) { image_handler_t *p_image; video_format_t fmt_out; video_format_Init( &fmt_out, i_chroma ); p_image = image_HandlerCreate( p_this ); *pp_pic = image_ReadUrl( p_image, psz_file, &fmt_out ); video_format_Clean( &fmt_out ); image_HandlerDelete( p_image ); if( *pp_pic == NULL ) { msg_Err( p_this, "Unable to load %s image", psz_name ); return VLC_EGENERIC; } msg_Dbg( p_this, "%s image has dim %d x %d (Y plane)", psz_name, (*pp_pic)->p[Y_PLANE].i_visible_pitch, (*pp_pic)->p[Y_PLANE].i_visible_lines ); return VLC_SUCCESS; }
void subpicture_region_private_Delete( subpicture_region_private_t *p_private ) { if( p_private->p_picture ) picture_Release( p_private->p_picture ); video_format_Clean( &p_private->fmt ); free( p_private ); }
void subpicture_Delete( subpicture_t *p_subpic ) { subpicture_region_ChainDelete( p_subpic->p_region ); p_subpic->p_region = NULL; if( p_subpic->updater.pf_destroy ) p_subpic->updater.pf_destroy( p_subpic ); if( p_subpic->p_private ) { video_format_Clean( &p_subpic->p_private->src ); video_format_Clean( &p_subpic->p_private->dst ); } free( p_subpic->p_private ); free( p_subpic ); }
void video_splitter_Delete( video_splitter_t *p_splitter ) { if( p_splitter->p_module ) module_unneed( p_splitter, p_splitter->p_module ); video_format_Clean( &p_splitter->fmt ); vlc_object_delete(p_splitter); }
/* copied from video_filters/erase.c . Gruik ? */ static void LoadMask( filter_t *p_filter, const char *psz_filename ) { image_handler_t *p_image; video_format_t fmt_in, fmt_out; video_format_Init( &fmt_in, 0 ); video_format_Init( &fmt_out, VLC_CODEC_YUVA ); if( p_filter->p_sys->p_mask ) picture_Release( p_filter->p_sys->p_mask ); p_image = image_HandlerCreate( p_filter ); char *psz_url = vlc_path2uri( psz_filename, NULL ); p_filter->p_sys->p_mask = image_ReadUrl( p_image, psz_url, &fmt_in, &fmt_out ); free( psz_url ); video_format_Clean( &fmt_in ); video_format_Clean( &fmt_out ); image_HandlerDelete( p_image ); }
/** * This function closes a clone video splitter module */ static void Close( vlc_object_t *p_this ) { video_splitter_t *p_splitter = (video_splitter_t*)p_this; for( int i = 0; i < p_splitter->i_output; i++ ) { video_splitter_output_t *p_cfg = &p_splitter->p_output[i]; free( p_cfg->psz_module ); video_format_Clean( &p_cfg->fmt ); } free( p_splitter->p_output ); }
static subpicture_t *Decode(decoder_t *dec, block_t **block) { if (block == NULL || *block == NULL) return NULL; subpicture_t *sub = NULL; block_t *b = *block; *block = NULL; if (b->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) goto exit; if (b->i_buffer < 128) goto exit; int payload_size = (b->i_buffer / 128) * 112; uint8_t *payload = malloc(payload_size); if (!payload) goto exit; for (unsigned i = 0; i < b->i_buffer / 128; i++) memcpy(&payload[112 * i], &b->p_buffer[128 * i + 16], 112); sub = decoder_NewSubpicture(dec, NULL); if (!sub) { free(payload); goto exit; } sub->i_start = b->i_pts; sub->i_stop = b->i_pts + b->i_length; sub->b_ephemer = b->i_length == 0; sub->b_absolute = false; //sub->i_original_picture_width = 0; //sub->i_original_picture_height = 0; video_format_t fmt; video_format_Init(&fmt, VLC_CODEC_TEXT); sub->p_region = subpicture_region_New(&fmt); video_format_Clean(&fmt); if (sub->p_region) { sub->p_region->psz_text = ParseText(payload, payload_size, cct_nums[dec->p_sys->cct - CCT_BEGIN].str); sub->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM; sub->p_region->psz_html = NULL; } free(payload); exit: block_Release(b); return sub; }
void subpicture_region_Delete( subpicture_region_t *p_region ) { if( !p_region ) return; if( p_region->p_private ) subpicture_region_private_Delete( p_region->p_private ); if( p_region->p_picture ) picture_Release( p_region->p_picture ); text_segment_ChainDelete( p_region->p_text ); video_format_Clean( &p_region->fmt ); free( p_region ); }
static block_t *Decode(demux_t *demux, video_format_t *fmt, vlc_fourcc_t chroma, block_t *data) { image_handler_t *handler = image_HandlerCreate(demux); if (!handler) { block_Release(data); return NULL; } video_format_t decoded; video_format_Init(&decoded, chroma); picture_t *image = image_Read(handler, data, fmt, &decoded); image_HandlerDelete(handler); if (!image) return NULL; video_format_Clean(fmt); *fmt = decoded; size_t size = 0; for (int i = 0; i < image->i_planes; i++) size += image->p[i].i_pitch * image->p[i].i_lines; data = block_Alloc(size); if (!data) { picture_Release(image); return NULL; } size_t offset = 0; for (int i = 0; i < image->i_planes; i++) { const plane_t *src = &image->p[i]; for (int y = 0; y < src->i_visible_lines; y++) { memcpy(&data->p_buffer[offset], &src->p_pixels[y * src->i_pitch], src->i_visible_pitch); offset += src->i_visible_pitch; } } picture_Release(image); return data; }
subpicture_region_t *subpicture_region_New( const video_format_t *p_fmt ) { subpicture_region_t *p_region = calloc( 1, sizeof(*p_region ) ); if( !p_region ) return NULL; if ( p_fmt->i_chroma == VLC_CODEC_YUVP ) { video_format_Copy( &p_region->fmt, p_fmt ); /* YUVP should have a palette */ if( p_region->fmt.p_palette == NULL ) { p_region->fmt.p_palette = calloc( 1, sizeof(*p_region->fmt.p_palette) ); if( p_region->fmt.p_palette == NULL ) { free( p_region ); return NULL; } } } else { p_region->fmt = *p_fmt; p_region->fmt.p_palette = NULL; } p_region->i_alpha = 0xff; if( p_fmt->i_chroma == VLC_CODEC_TEXT ) return p_region; p_region->p_picture = picture_NewFromFormat( p_fmt ); if( !p_region->p_picture ) { video_format_Clean( &p_region->fmt ); free( p_region ); return NULL; } return p_region; }
/** This function allocates and initialize the DirectX vout display. */ static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; /* Allocate structure */ vd->sys = sys = calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; /* Load direct draw DLL */ sys->hddraw_dll = LoadLibrary(_T("DDRAW.DLL")); if (!sys->hddraw_dll) { msg_Warn(vd, "DirectXInitDDraw failed loading ddraw.dll"); free(sys); return VLC_EGENERIC; } /* */ sys->use_wallpaper = var_CreateGetBool(vd, "video-wallpaper"); /* FIXME */ sys->use_overlay = false;//var_CreateGetBool(vd, "overlay"); /* FIXME */ sys->restore_overlay = false; var_Create(vd, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT); /* Initialisation */ if (CommonInit(vd)) goto error; /* */ video_format_t fmt = vd->fmt; if (DirectXOpen(vd, &fmt)) goto error; /* */ vout_display_info_t info = vd->info; info.is_slow = true; info.has_double_click = true; info.has_hide_mouse = false; info.has_pictures_invalid = true; info.has_event_thread = true; /* Interaction TODO support starting with wallpaper mode */ vlc_mutex_init(&sys->lock); sys->ch_wallpaper = sys->use_wallpaper; sys->wallpaper_requested = sys->use_wallpaper; sys->use_wallpaper = false; vlc_value_t val; val.psz_string = _("Wallpaper"); var_Change(vd, "video-wallpaper", VLC_VAR_SETTEXT, &val, NULL); var_AddCallback(vd, "video-wallpaper", WallpaperCallback, NULL); /* Setup vout_display now that everything is fine */ video_format_Clean(&vd->fmt); video_format_Copy(&vd->fmt, &fmt); vd->info = info; vd->pool = Pool; vd->prepare = NULL; vd->display = Display; vd->control = Control; vd->manage = Manage; return VLC_SUCCESS; error: DirectXClose(vd); CommonClean(vd); if (sys->hddraw_dll) FreeLibrary(sys->hddraw_dll); free(sys); return VLC_EGENERIC; }
static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block, const video_format_t *p_fmt_in, video_format_t *p_fmt_out ) { picture_t *p_pic = NULL; /* Check if we can reuse the current decoder */ if( p_image->p_dec && p_image->p_dec->fmt_in.i_codec != p_fmt_in->i_chroma ) { DeleteDecoder( p_image->p_dec ); p_image->p_dec = 0; } /* Start a decoder */ if( !p_image->p_dec ) { p_image->p_dec = CreateDecoder( p_image->p_parent, p_fmt_in ); if( !p_image->p_dec ) { block_Release(p_block); return NULL; } if( p_image->p_dec->fmt_out.i_cat != VIDEO_ES ) { DeleteDecoder( p_image->p_dec ); p_image->p_dec = NULL; block_Release(p_block); return NULL; } p_image->p_dec->pf_queue_video = ImageQueueVideo; p_image->p_dec->p_queue_ctx = p_image; } p_block->i_pts = p_block->i_dts = mdate(); int ret = p_image->p_dec->pf_decode( p_image->p_dec, p_block ); if( ret == VLCDEC_SUCCESS ) { /* Drain */ p_image->p_dec->pf_decode( p_image->p_dec, NULL ); p_pic = picture_fifo_Pop( p_image->outfifo ); unsigned lostcount = 0; picture_t *lostpic; while( ( lostpic = picture_fifo_Pop( p_image->outfifo ) ) != NULL ) { picture_Release( lostpic ); lostcount++; } if( lostcount > 0 ) msg_Warn( p_image->p_parent, "Image decoder output more than one " "picture (%d)", lostcount ); } if( p_pic == NULL ) { msg_Warn( p_image->p_parent, "no image decoded" ); return 0; } if( !p_fmt_out->i_chroma ) p_fmt_out->i_chroma = p_image->p_dec->fmt_out.video.i_chroma; if( !p_fmt_out->i_width && p_fmt_out->i_height ) p_fmt_out->i_width = (int64_t)p_image->p_dec->fmt_out.video.i_width * p_image->p_dec->fmt_out.video.i_sar_num * p_fmt_out->i_height / p_image->p_dec->fmt_out.video.i_height / p_image->p_dec->fmt_out.video.i_sar_den; if( !p_fmt_out->i_height && p_fmt_out->i_width ) p_fmt_out->i_height = (int64_t)p_image->p_dec->fmt_out.video.i_height * p_image->p_dec->fmt_out.video.i_sar_den * p_fmt_out->i_width / p_image->p_dec->fmt_out.video.i_width / p_image->p_dec->fmt_out.video.i_sar_num; if( !p_fmt_out->i_width ) p_fmt_out->i_width = p_image->p_dec->fmt_out.video.i_width; if( !p_fmt_out->i_height ) p_fmt_out->i_height = p_image->p_dec->fmt_out.video.i_height; if( !p_fmt_out->i_visible_width ) p_fmt_out->i_visible_width = p_fmt_out->i_width; if( !p_fmt_out->i_visible_height ) p_fmt_out->i_visible_height = p_fmt_out->i_height; /* Check if we need chroma conversion or resizing */ if( p_image->p_dec->fmt_out.video.i_chroma != p_fmt_out->i_chroma || p_image->p_dec->fmt_out.video.i_width != p_fmt_out->i_width || p_image->p_dec->fmt_out.video.i_height != p_fmt_out->i_height ) { if( p_image->p_filter ) if( p_image->p_filter->fmt_in.video.i_chroma != p_image->p_dec->fmt_out.video.i_chroma || p_image->p_filter->fmt_out.video.i_chroma != p_fmt_out->i_chroma ) { /* We need to restart a new filter */ DeleteFilter( p_image->p_filter ); p_image->p_filter = 0; } /* Start a filter */ if( !p_image->p_filter ) { p_image->p_filter = CreateFilter( p_image->p_parent, &p_image->p_dec->fmt_out, p_fmt_out ); if( !p_image->p_filter ) { picture_Release( p_pic ); return NULL; } } else { /* Filters should handle on-the-fly size changes */ p_image->p_filter->fmt_in = p_image->p_dec->fmt_out; p_image->p_filter->fmt_out = p_image->p_dec->fmt_out; p_image->p_filter->fmt_out.i_codec = p_fmt_out->i_chroma; p_image->p_filter->fmt_out.video = *p_fmt_out; } p_pic = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic ); video_format_Clean( p_fmt_out ); video_format_Copy( p_fmt_out, &p_image->p_filter->fmt_out.video ); } else { video_format_Clean( p_fmt_out ); video_format_Copy( p_fmt_out, &p_image->p_dec->fmt_out.video ); } return p_pic; }
/***************************************************************************** * Filter *****************************************************************************/ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) { filter_sys_t *p_sys = p_filter->p_sys; bridge_t *p_bridge; int i_real_index, i_row, i_col; int i_greatest_real_index_used = p_sys->i_order_length - 1; unsigned int col_inner_width, row_inner_height; subpicture_region_t *p_region; subpicture_region_t *p_region_prev = NULL; /* Allocate the subpicture internal data. */ subpicture_t *p_spu = filter_NewSubpicture( p_filter ); if( !p_spu ) return NULL; /* Initialize subpicture */ p_spu->i_channel = 0; p_spu->i_start = date; p_spu->i_stop = 0; p_spu->b_ephemer = true; p_spu->i_alpha = p_sys->i_alpha; p_spu->b_absolute = false; p_spu->i_original_picture_width = p_sys->i_width; p_spu->i_original_picture_height = p_sys->i_height; vlc_mutex_lock( &p_sys->lock ); vlc_global_lock( VLC_MOSAIC_MUTEX ); p_bridge = GetBridge( p_filter ); if ( p_bridge == NULL ) { vlc_global_unlock( VLC_MOSAIC_MUTEX ); vlc_mutex_unlock( &p_sys->lock ); return p_spu; } if ( p_sys->i_position == position_offsets ) { /* If we have either too much or not enough offsets, fall-back * to automatic positioning. */ if ( p_sys->i_offsets_length != p_sys->i_order_length ) { msg_Err( p_filter, "Number of specified offsets (%d) does not match number " "of input substreams in mosaic-order (%d), falling back " "to mosaic-position=0", p_sys->i_offsets_length, p_sys->i_order_length ); p_sys->i_position = position_auto; } } if ( p_sys->i_position == position_auto ) { int i_numpics = p_sys->i_order_length; /* keep slots and all */ for( int i_index = 0; i_index < p_bridge->i_es_num; i_index++ ) { bridged_es_t *p_es = p_bridge->pp_es[i_index]; if ( !p_es->b_empty ) { i_numpics ++; if( p_sys->i_order_length && p_es->psz_id != NULL ) { /* We also want to leave slots for images given in * mosaic-order that are not available in p_vout_picture */ for( int i = 0; i < p_sys->i_order_length ; i++ ) { if( !strcmp( p_sys->ppsz_order[i], p_es->psz_id ) ) { i_numpics--; break; } } } } } p_sys->i_rows = ceil(sqrt( (double)i_numpics )); p_sys->i_cols = ( i_numpics % p_sys->i_rows == 0 ? i_numpics / p_sys->i_rows : i_numpics / p_sys->i_rows + 1 ); } col_inner_width = ( ( p_sys->i_width - ( p_sys->i_cols - 1 ) * p_sys->i_borderw ) / p_sys->i_cols ); row_inner_height = ( ( p_sys->i_height - ( p_sys->i_rows - 1 ) * p_sys->i_borderh ) / p_sys->i_rows ); i_real_index = 0; for( int i_index = 0; i_index < p_bridge->i_es_num; i_index++ ) { bridged_es_t *p_es = p_bridge->pp_es[i_index]; video_format_t fmt_in, fmt_out; picture_t *p_converted; if ( p_es->b_empty ) continue; while ( p_es->p_picture != NULL && p_es->p_picture->date + p_sys->i_delay < date ) { if ( p_es->p_picture->p_next != NULL ) { picture_t *p_next = p_es->p_picture->p_next; picture_Release( p_es->p_picture ); p_es->p_picture = p_next; } else if ( p_es->p_picture->date + p_sys->i_delay + BLANK_DELAY < date ) { /* Display blank */ picture_Release( p_es->p_picture ); p_es->p_picture = NULL; p_es->pp_last = &p_es->p_picture; break; } else { msg_Dbg( p_filter, "too late picture for %s (%"PRId64 ")", p_es->psz_id, date - p_es->p_picture->date - p_sys->i_delay ); break; } } if ( p_es->p_picture == NULL ) continue; if ( p_sys->i_order_length == 0 ) { i_real_index++; } else { int i; for ( i = 0; i <= p_sys->i_order_length; i++ ) { if ( i == p_sys->i_order_length ) break; if ( strcmp( p_es->psz_id, p_sys->ppsz_order[i] ) == 0 ) { i_real_index = i; break; } } if ( i == p_sys->i_order_length ) i_real_index = ++i_greatest_real_index_used; } i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows; i_col = i_real_index % p_sys->i_cols ; video_format_Init( &fmt_in, 0 ); video_format_Init( &fmt_out, 0 ); if ( !p_sys->b_keep ) { /* Convert the images */ fmt_in.i_chroma = p_es->p_picture->format.i_chroma; fmt_in.i_height = p_es->p_picture->format.i_height; fmt_in.i_width = p_es->p_picture->format.i_width; if( fmt_in.i_chroma == VLC_CODEC_YUVA || fmt_in.i_chroma == VLC_CODEC_RGBA ) fmt_out.i_chroma = VLC_CODEC_YUVA; else fmt_out.i_chroma = VLC_CODEC_I420; fmt_out.i_width = col_inner_width; fmt_out.i_height = row_inner_height; if( p_sys->b_ar ) /* keep aspect ratio */ { if( (float)fmt_out.i_width / (float)fmt_out.i_height > (float)fmt_in.i_width / (float)fmt_in.i_height ) { fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width ) / fmt_in.i_height; } else { fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height ) / fmt_in.i_width; } } fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; p_converted = image_Convert( p_sys->p_image, p_es->p_picture, &fmt_in, &fmt_out ); if( !p_converted ) { msg_Warn( p_filter, "image resizing and chroma conversion failed" ); video_format_Clean( &fmt_in ); video_format_Clean( &fmt_out ); continue; } } else { p_converted = p_es->p_picture; fmt_in.i_width = fmt_out.i_width = p_converted->format.i_width; fmt_in.i_height = fmt_out.i_height = p_converted->format.i_height; fmt_in.i_chroma = fmt_out.i_chroma = p_converted->format.i_chroma; fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; } p_region = subpicture_region_New( &fmt_out ); /* FIXME the copy is probably not needed anymore */ if( p_region ) picture_Copy( p_region->p_picture, p_converted ); if( !p_sys->b_keep ) picture_Release( p_converted ); if( !p_region ) { video_format_Clean( &fmt_in ); video_format_Clean( &fmt_out ); msg_Err( p_filter, "cannot allocate SPU region" ); subpicture_Delete( p_spu ); vlc_global_unlock( VLC_MOSAIC_MUTEX ); vlc_mutex_unlock( &p_sys->lock ); return NULL; } if( p_es->i_x >= 0 && p_es->i_y >= 0 ) { p_region->i_x = p_es->i_x; p_region->i_y = p_es->i_y; } else if( p_sys->i_position == position_offsets ) { p_region->i_x = p_sys->pi_x_offsets[i_real_index]; p_region->i_y = p_sys->pi_y_offsets[i_real_index]; } else { if( fmt_out.i_width > col_inner_width || p_sys->b_ar || p_sys->b_keep ) { /* we don't have to center the video since it takes the whole rectangle area or it's larger than the rectangle */ p_region->i_x = p_sys->i_xoffset + i_col * ( p_sys->i_width / p_sys->i_cols ) + ( i_col * p_sys->i_borderw ) / p_sys->i_cols; } else { /* center the video in the dedicated rectangle */ p_region->i_x = p_sys->i_xoffset + i_col * ( p_sys->i_width / p_sys->i_cols ) + ( i_col * p_sys->i_borderw ) / p_sys->i_cols + ( col_inner_width - fmt_out.i_width ) / 2; } if( fmt_out.i_height > row_inner_height || p_sys->b_ar || p_sys->b_keep ) { /* we don't have to center the video since it takes the whole rectangle area or it's taller than the rectangle */ p_region->i_y = p_sys->i_yoffset + i_row * ( p_sys->i_height / p_sys->i_rows ) + ( i_row * p_sys->i_borderh ) / p_sys->i_rows; } else { /* center the video in the dedicated rectangle */ p_region->i_y = p_sys->i_yoffset + i_row * ( p_sys->i_height / p_sys->i_rows ) + ( i_row * p_sys->i_borderh ) / p_sys->i_rows + ( row_inner_height - fmt_out.i_height ) / 2; } } p_region->i_align = p_sys->i_align; p_region->i_alpha = p_es->i_alpha; if( p_region_prev == NULL ) { p_spu->p_region = p_region; } else { p_region_prev->p_next = p_region; } video_format_Clean( &fmt_in ); video_format_Clean( &fmt_out ); p_region_prev = p_region; } vlc_global_unlock( VLC_MOSAIC_MUTEX ); vlc_mutex_unlock( &p_sys->lock ); return p_spu; }
static subpicture_region_t *CreateTextRegion( decoder_t *p_dec, char *psz_subtitle, int i_sys_align ) { decoder_sys_t *p_sys = p_dec->p_sys; subpicture_region_t *p_text_region; video_format_t fmt; /* Create a new subpicture region */ video_format_Init( &fmt, VLC_CODEC_TEXT ); fmt.i_width = fmt.i_height = 0; fmt.i_x_offset = fmt.i_y_offset = 0; p_text_region = subpicture_region_New( &fmt ); video_format_Clean( &fmt ); if( p_text_region != NULL ) { ssa_style_t *p_ssa_style = NULL; p_ssa_style = ParseStyle( p_sys, psz_subtitle ); if( !p_ssa_style ) { for( int i = 0; i < p_sys->i_ssa_styles; i++ ) { if( !strcasecmp( p_sys->pp_ssa_styles[i]->psz_stylename, "Default" ) ) p_ssa_style = p_sys->pp_ssa_styles[i]; } } /* Set default or user align/magin. * Style overriden if no user value. */ p_text_region->i_x = i_sys_align > 0 ? 20 : 0; p_text_region->i_y = 10; p_text_region->i_align = SUBPICTURE_ALIGN_BOTTOM | ((i_sys_align > 0) ? i_sys_align : 0); if( p_ssa_style ) { msg_Dbg( p_dec, "style is: %s", p_ssa_style->psz_stylename ); /* TODO: Setup % based offsets properly, without adversely affecting * everything else in vlc. Will address with separate patch, * to prevent this one being any more complicated. * p_ssa_style->i_margin_percent_h; * p_ssa_style->i_margin_percent_v; */ if( i_sys_align == -1 ) { p_text_region->i_align = p_ssa_style->i_align; p_text_region->i_x = p_ssa_style->i_margin_h; p_text_region->i_y = p_ssa_style->i_margin_v; } p_text_region->p_text = text_segment_NewInheritStyle( p_ssa_style->p_style ); } else { p_text_region->p_text = text_segment_New( NULL ); } /* Look for position arguments which may override the style-based * defaults. */ SetupPositions( p_text_region, psz_subtitle ); p_text_region->p_next = NULL; } return p_text_region; }