/***************************************************************************** * SubsdelayFilter: Filter new subpicture *****************************************************************************/ static subpicture_t * SubsdelayFilter( filter_t *p_filter, subpicture_t* p_subpic ) { subsdelay_heap_t *p_heap; subsdelay_heap_entry_t *p_entry; if( !p_subpic->b_subtitle ) { return p_subpic; } if( SubpicIsEmpty( p_subpic ) ) { /* empty subtitles usually helps terminate ephemer subtitles, but this filter calculates the stop value anyway, so this subtitle can be dropped */ subpicture_Delete( p_subpic ); return NULL; } p_heap = &p_filter->p_sys->heap; /* add subpicture to the heap */ SubsdelayHeapLock( p_heap ); p_entry = SubsdelayHeapPush( p_heap, p_subpic, p_filter ); if( !p_entry ) { SubsdelayHeapUnlock( p_heap ); msg_Err(p_filter, "Can't add subpicture to the heap"); return p_subpic; } p_subpic = p_entry->p_subpic; /* get the local subpic */ if( p_subpic->b_ephemer ) { /* set a relativly long delay in hope that the next subtitle will arrive in this time and the real delay could be determined */ p_subpic->i_stop = p_subpic->i_start + 20000000; /* start + 20 sec */ p_subpic->b_ephemer = false; } SubsdelayEnforceDelayRules( p_filter ); SubsdelayHeapUnlock( p_heap ); return p_subpic; }
/***************************************************************************** * SubsdelayCallback: Subsdelay parameters callback *****************************************************************************/ static int SubsdelayCallback( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { filter_sys_t *p_sys = (filter_sys_t *) p_data; VLC_UNUSED( oldval ); SubsdelayHeapLock( &p_sys->heap ); if( !strcmp( psz_var, CFG_MODE ) ) { p_sys->i_mode = newval.i_int; } else if( !strcmp( psz_var, CFG_FACTOR ) ) { p_sys->i_factor = FLOAT_FACTOR_TO_INT_FACTOR( newval.f_float ); } else if( !strcmp( psz_var, CFG_OVERLAP ) ) { p_sys->i_overlap = newval.i_int; } else if( !strcmp( psz_var, CFG_MIN_ALPHA ) ) { p_sys->i_min_alpha = newval.i_int; } else if( !strcmp( psz_var, CFG_MIN_STOPS_INTERVAL ) ) { p_sys->i_min_stops_interval = MILLISEC_TO_MICROSEC( newval.i_int ); } else if( !strcmp( psz_var, CFG_MIN_STOP_START_INTERVAL ) ) { p_sys->i_min_stop_start_interval = MILLISEC_TO_MICROSEC( newval.i_int ); } else if( !strcmp( psz_var, CFG_MIN_START_STOP_INTERVAL ) ) { p_sys->i_min_start_stop_interval = MILLISEC_TO_MICROSEC( newval.i_int ); } else { SubsdelayHeapUnlock( &p_sys->heap ); return VLC_ENOVAR; } SubsdelayRecalculateDelays( (filter_t *) p_this ); SubsdelayHeapUnlock( &p_sys->heap ); return VLC_SUCCESS; }
/***************************************************************************** * SubsdelayHeapDestroy: Destroy the heap and remove its entries *****************************************************************************/ static void SubsdelayHeapDestroy( subsdelay_heap_t *p_heap ) { SubsdelayHeapLock( p_heap ); for( subsdelay_heap_entry_t *p_entry = p_heap->p_head; p_entry != NULL; p_entry = p_entry->p_next ) { p_entry->p_subpic->i_stop = p_entry->p_source->i_stop; p_entry->p_filter = NULL; } SubsdelayHeapUnlock( p_heap ); vlc_mutex_destroy( &p_heap->lock ); }
/***************************************************************************** * SubpicDestroyCallback: Subpicture destroy callback *****************************************************************************/ static void SubpicDestroyWrapper( subpicture_t *p_subpic ) { subsdelay_heap_entry_t *p_entry; subsdelay_heap_t *p_heap; p_entry = p_subpic->updater.p_sys; if( !p_entry ) { return; } if( p_entry->p_filter ) { p_heap = &p_entry->p_filter->p_sys->heap; SubsdelayHeapLock( p_heap ); SubsdelayHeapRemove( p_heap, p_entry ); SubsdelayHeapUnlock( p_heap ); } SubsdelayEntryDestroy( p_entry ); }
/***************************************************************************** * SubpicLocalUpdate: rewrite some of the subpicture parameters *****************************************************************************/ static void SubpicLocalUpdate( subpicture_t* p_subpic, mtime_t i_ts ) { subsdelay_heap_entry_t *p_entry; subsdelay_heap_t *p_heap; filter_t *p_filter; int i_overlapping; p_entry = p_subpic->updater.p_sys; if( !p_entry || !p_entry->p_filter ) { return; } p_filter = p_entry->p_filter; p_heap = &p_filter->p_sys->heap; SubsdelayHeapLock( p_heap ); if( p_entry->b_check_empty && p_subpic->p_region ) { if( SubsdelayIsTextEmpty( p_subpic->p_region->psz_html ) || SubsdelayIsTextEmpty( p_subpic->p_region->psz_text ) ) { /* remove empty subtitle */ p_subpic->b_ephemer = false; p_subpic->i_stop = p_subpic->i_start; SubsdelayHeapRemove( p_heap, p_entry ); SubsdelayHeapUnlock( p_heap ); return; } p_entry->b_check_empty = false; } if( p_entry->b_update_stop && !p_entry->b_update_ephemer ) { p_entry->i_new_stop = p_entry->p_source->i_start + SubsdelayEstimateDelay( p_filter, p_entry ); p_entry->b_update_stop = false; SubsdelayEnforceDelayRules( p_filter ); } i_overlapping = SubsdelayHeapCountOverlap( p_heap, p_entry, i_ts ); p_subpic->i_alpha = SubsdelayCalculateAlpha( p_filter, i_overlapping, p_entry->p_source->i_alpha ); if( p_entry->b_update_position ) { p_subpic->b_absolute = false; if( p_subpic->p_region ) { p_subpic->p_region->i_x = 0; p_subpic->p_region->i_y = 10; p_subpic->p_region->i_align = ( p_subpic->p_region->i_align & ( ~SUBPICTURE_ALIGN_MASK ) ) | SUBPICTURE_ALIGN_BOTTOM; } p_entry->b_update_position = false; } else if( p_entry->b_last_region_saved ) { p_subpic->b_absolute = true; if( p_subpic->p_region ) { p_subpic->p_region->i_x = p_entry->i_last_region_x; p_subpic->p_region->i_y = p_entry->i_last_region_y; p_subpic->p_region->i_align = p_entry->i_last_region_align; } } SubsdelayHeapUnlock( p_heap ); }