/** * Create a region with a white transparent picture. */ static subpicture_region_t *OSDRegion(int x, int y, int width, int height) { video_palette_t palette = { // sunqueen modify start /*.i_entries =*/ 2, /*.palette =*/ { /*[0] =*/ { 0xff, 0x80, 0x80, 0x00 }, /*[1] =*/ { 0xff, 0x80, 0x80, 0xff }, }, // sunqueen modify end }; video_format_t fmt; video_format_Init(&fmt, VLC_CODEC_YUVP); fmt.i_width = fmt.i_visible_width = width; fmt.i_height = fmt.i_visible_height = height; fmt.i_sar_num = 1; fmt.i_sar_den = 1; fmt.p_palette = &palette; subpicture_region_t *r = subpicture_region_New(&fmt); if (!r) return NULL; r->i_x = x; r->i_y = y; memset(r->p_picture->p->p_pixels, 0, r->p_picture->p->i_pitch * height); return r; }
static subpicture_region_t * vout_OSDBackground(int x, int y, int width, int height, uint32_t i_argb) { /* Create a new subpicture region */ video_palette_t palette; spuregion_CreateVGradientPalette( &palette, GRADIENT_COLORS, i_argb, 0xFF000000 ); video_format_t fmt; video_format_Init(&fmt, VLC_CODEC_YUVP); fmt.i_width = fmt.i_visible_width = width; fmt.i_height = fmt.i_visible_height = height; fmt.i_sar_num = 1; fmt.i_sar_den = 1; fmt.p_palette = &palette; subpicture_region_t *region = subpicture_region_New(&fmt); if (!region) return NULL; region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP; region->i_x = x; region->i_y = y; spuregion_CreateVGradientFill( region->p_picture->p, palette.i_entries ); return region; }
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; }
/** * Create a region with a white transparent picture. */ static subpicture_region_t *OSDRegion(int x, int y, int width, int height) { video_format_t fmt; video_format_Init(&fmt, VLC_CODEC_YUVA); fmt.i_width = fmt.i_visible_width = width; fmt.i_height = fmt.i_visible_height = height; fmt.i_sar_num = 0; fmt.i_sar_den = 1; subpicture_region_t *r = subpicture_region_New(&fmt); if (!r) return NULL; r->i_x = x; r->i_y = y; for (int i = 0; i < r->p_picture->i_planes; i++) { plane_t *p = &r->p_picture->p[i]; int colors[PICTURE_PLANE_MAX] = { 0xff, 0x80, 0x80, 0x00 }; memset(p->p_pixels, colors[i], p->i_pitch * height); } return r; }
static subpicture_region_t * vout_OSDEpgText(const char *text, int x, int y, int size, uint32_t color) { video_format_t fmt; subpicture_region_t *region; if (!text) return NULL; /* Create a new subpicture region */ video_format_Init(&fmt, VLC_CODEC_TEXT); fmt.i_sar_num = 0; fmt.i_sar_den = 1; region = subpicture_region_New(&fmt); if (!region) return NULL; /* Set subpicture parameters */ region->psz_text = strdup(text); region->i_align = 0; region->i_x = x; region->i_y = y; /* Set text style */ region->p_style = text_style_New(); if (region->p_style) { region->p_style->i_font_size = size; region->p_style->i_font_color = color; region->p_style->i_font_alpha = 0; } return region; }
static subpicture_t *Subpicture( decoder_t *p_dec, video_format_t *p_fmt, bool b_text, int i_columns, int i_rows, int i_align, mtime_t i_pts ) { video_format_t fmt; subpicture_t *p_spu=NULL; /* If there is a page or sub to render, then we do that here */ /* Create the subpicture unit */ if( b_text ) p_spu = decoder_NewSubpictureText( p_dec ); else p_spu = decoder_NewSubpicture( p_dec, NULL ); if( !p_spu ) { msg_Warn( p_dec, "can't get spu buffer" ); return NULL; } video_format_Init(&fmt, b_text ? VLC_CODEC_TEXT : VLC_CODEC_RGBA); if( b_text ) { fmt.i_bits_per_pixel = 0; } else { fmt.i_width = fmt.i_visible_width = i_columns * 12; fmt.i_height = fmt.i_visible_height = i_rows * 10; fmt.i_bits_per_pixel = 32; fmt.i_sar_num = fmt.i_sar_den = 0; /* let the vout set the correct AR */ } fmt.i_x_offset = fmt.i_y_offset = 0; p_spu->p_region = subpicture_region_New( &fmt ); if( p_spu->p_region == NULL ) { msg_Err( p_dec, "cannot allocate SPU region" ); subpicture_Delete( p_spu ); return NULL; } p_spu->p_region->i_x = 0; p_spu->p_region->i_y = 0; p_spu->i_start = i_pts; p_spu->i_stop = b_text ? i_pts + (10*CLOCK_FREQ): 0; p_spu->b_ephemer = true; p_spu->b_absolute = b_text ? false : true; if( !b_text ) p_spu->p_region->i_align = i_align; p_spu->i_original_picture_width = fmt.i_width; p_spu->i_original_picture_height = fmt.i_height; /* */ *p_fmt = fmt; return p_spu; }
/* 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 ); }
static subpicture_region_t * vout_OSDEpgSlider(int x, int y, int width, int height, float ratio) { /* Create a new subpicture region */ video_palette_t palette = { // sunqueen modify start /*.i_entries =*/ 4, /*.palette =*/ { /*[0] =*/ { 0xff, 0x80, 0x80, 0x00 }, /*[1] =*/ { 0x00, 0x80, 0x80, 0x00 }, /*[2] =*/ { 0xff, 0x80, 0x80, 0xff }, /*[3] =*/ { 0x00, 0x80, 0x80, 0xff }, }, // sunqueen modify end }; video_format_t fmt; video_format_Init(&fmt, VLC_CODEC_YUVP); fmt.i_width = fmt.i_visible_width = width; fmt.i_height = fmt.i_visible_height = height; fmt.i_sar_num = 1; fmt.i_sar_den = 1; fmt.p_palette = &palette; subpicture_region_t *region = subpicture_region_New(&fmt); if (!region) return NULL; region->i_x = x; region->i_y = y; picture_t *picture = region->p_picture; ratio = VLC_CLIP(ratio, 0, 1); int filled_part_width = ratio * width; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { /* Slider border. */ bool is_outline = j == 0 || j == height - 1 || i == 0 || i == width - 1; /* We can see the video through the part of the slider which corresponds to the leaving time. */ bool is_border = j < 3 || j > height - 4 || i < 3 || i > width - 4 || i < filled_part_width; picture->p->p_pixels[picture->p->i_pitch * j + i] = 2 * is_border + is_outline; } } return region; }
static subpicture_region_t * vout_OSDEpgSlider( int i_x, int i_y, int i_width, int i_height, float f_ratio ) { video_format_t fmt; subpicture_region_t *p_region; /* Create a new subpicture region */ video_format_Init( &fmt, VLC_CODEC_YUVA ); fmt.i_width = fmt.i_visible_width = i_width; fmt.i_height = fmt.i_visible_height = i_height; fmt.i_sar_num = 0; fmt.i_sar_den = 1; p_region = subpicture_region_New( &fmt ); if( !p_region ) return NULL; p_region->i_x = i_x; p_region->i_y = i_y; picture_t *p_picture = p_region->p_picture; f_ratio = __MIN( __MAX( f_ratio, 0 ), 1 ); int i_filled_part_width = f_ratio * i_width; for( int j = 0; j < i_height; j++ ) { for( int i = 0; i < i_width; i++ ) { #define WRITE_COMP( plane, value ) \ p_picture->p[plane].p_pixels[p_picture->p[plane].i_pitch * j + i] = value /* Draw the slider. */ bool is_outline = j == 0 || j == i_height - 1 || i == 0 || i == i_width - 1; WRITE_COMP( 0, is_outline ? 0x00 : 0xff ); WRITE_COMP( 1, 0x80 ); WRITE_COMP( 2, 0x80 ); /* We can see the video through the part of the slider which corresponds to the leaving time. */ bool is_border = j < 3 || j > i_height - 4 || i < 3 || i > i_width - 4 || i < i_filled_part_width; WRITE_COMP( 3, is_border ? 0xff : 0x00 ); #undef WRITE_COMP } } return p_region; }
/** * It loads the logo image into memory. */ static picture_t *LoadImage( vlc_object_t *p_this, const char *psz_filename ) { if( !psz_filename ) return NULL; video_format_t fmt_in; video_format_Init( &fmt_in, 0 ); video_format_t fmt_out; video_format_Init( &fmt_out, VLC_CODEC_YUVA ); image_handler_t *p_image = image_HandlerCreate( p_this ); if( !p_image ) return NULL; char *psz_url = make_URI( psz_filename, NULL ); picture_t *p_pic = image_ReadUrl( p_image, psz_url, &fmt_in, &fmt_out ); free( psz_url ); image_HandlerDelete( p_image ); return p_pic; }
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; }
subpicture_t *subpicture_New( const subpicture_updater_t *p_upd ) { subpicture_t *p_subpic = calloc( 1, sizeof(*p_subpic) ); if( !p_subpic ) return NULL; p_subpic->i_order = 0; p_subpic->b_absolute = true; p_subpic->b_fade = false; p_subpic->b_subtitle = false; p_subpic->i_alpha = 0xFF; p_subpic->p_region = NULL; if( p_upd ) { subpicture_private_t *p_private = malloc( sizeof(*p_private) ); if( !p_private ) { free( p_subpic ); return NULL; } video_format_Init( &p_private->src, 0 ); video_format_Init( &p_private->dst, 0 ); p_subpic->updater = *p_upd; p_subpic->p_private = p_private; } else { p_subpic->p_private = NULL; p_subpic->updater.pf_validate = NULL; p_subpic->updater.pf_update = NULL; p_subpic->updater.pf_destroy = NULL; p_subpic->updater.p_sys = NULL; } return p_subpic; }
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; }
/** * @brief Thread reading frames from the subprocess */ static void* outputThread(void* userData) { filter_t* intf = (filter_t*)userData; filter_sys_t* sys = intf->p_sys; msg_Info(intf, "outputThread: enter"); bool gotHeader = false; while (true) { if (!gotHeader) { video_format_Init(&sys->outFormat, VLC_CODEC_I420); if (1 != readY4mHeader(intf, &sys->outFormat, sys->stdout)) break; gotHeader = true; } picture_t* outPic = picture_NewFromFormat(&sys->outFormat); if(1 != readY4mFrame(intf, outPic, sys->stdout)) { picture_Release(outPic); break; } //msg_Info(intf, "outputThread: read picture"); // fixme: deinterlace filter does this, not sure if we need to; // y4m header contains this information outPic->b_progressive = true; outPic->i_nb_fields = 2; picture_fifo_Push(sys->outputFifo, outPic); vlc_cond_signal(&sys->outputCond); } msg_Info(intf, "outputThread: exit"); sys->threadExit = true; vlc_cond_signal(&sys->outputCond); return userData; }
int transcode_osd_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id, block_t *in, block_t **out ) { sout_stream_sys_t *p_sys = p_stream->p_sys; subpicture_t *p_subpic = NULL; /* Check if we have a subpicture to send */ if( p_sys->p_spu && in->i_dts > VLC_TS_INVALID ) { video_format_t fmt; video_format_Init( &fmt, 0 ); video_format_Setup( &fmt, 0, 720, 576, 720, 576, 1, 1 ); p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt, in->i_dts, in->i_dts, false ); } else { msg_Warn( p_stream, "spu channel not initialized, doing it now" ); if( !p_sys->p_spu ) p_sys->p_spu = spu_Create( p_stream ); } if( p_subpic ) { block_t *p_block = NULL; if( p_sys->b_master_sync && p_sys->i_master_drift ) { p_subpic->i_start -= p_sys->i_master_drift; if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift; } p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic ); subpicture_Delete( p_subpic ); if( p_block ) { p_block->i_dts = p_block->i_pts = in->i_dts; block_ChainAppend( out, p_block ); return VLC_SUCCESS; } } return VLC_EGENERIC; }
static subpicture_region_t * vout_OSDEpgText( const char *psz_string, int i_x, int i_y, int i_size, uint32_t i_color ) { video_format_t fmt; subpicture_region_t *p_region; if( !psz_string ) return NULL; /* Create a new subpicture region */ video_format_Init( &fmt, VLC_CODEC_TEXT ); fmt.i_sar_num = 0; fmt.i_sar_den = 1; p_region = subpicture_region_New( &fmt ); if( !p_region ) return NULL; /* Set subpicture parameters */ p_region->psz_text = strdup( psz_string ); p_region->i_align = 0; p_region->i_x = i_x; p_region->i_y = i_y; /* Set text style */ p_region->p_style = text_style_New(); if( p_region->p_style ) { p_region->p_style->i_font_size = i_size; p_region->p_style->i_font_color = i_color; p_region->p_style->i_font_alpha = 0; } return p_region; }
/** * ProjectM update thread which do the rendering * @param p_this: the p_thread object */ static void *Thread( void *p_data ) { filter_t *p_filter = (filter_t*)p_data; filter_sys_t *p_sys = p_filter->p_sys; video_format_t fmt; vlc_gl_t *gl; unsigned int i_last_width = 0; unsigned int i_last_height = 0; locale_t loc; locale_t oldloc; projectM *p_projectm; #ifndef HAVE_PROJECTM2 char *psz_config; #else char *psz_preset_path; char *psz_title_font; char *psz_menu_font; projectM::Settings settings; #endif vlc_savecancel(); /* Create the openGL provider */ p_sys->p_vout = (vout_thread_t *)vlc_object_create( p_filter, sizeof(vout_thread_t) ); if( !p_sys->p_vout ) goto error; /* */ video_format_Init( &fmt, 0 ); video_format_Setup( &fmt, VLC_CODEC_RGB32, p_sys->i_width, p_sys->i_height, 0, 1 ); fmt.i_sar_num = 1; fmt.i_sar_den = 1; vout_display_state_t state; memset( &state, 0, sizeof(state) ); state.cfg.display.sar.num = 1; state.cfg.display.sar.den = 1; state.cfg.is_display_filled = true; state.cfg.zoom.num = 1; state.cfg.zoom.den = 1; state.sar.num = 1; state.sar.den = 1; p_sys->p_vd = vout_NewDisplay( p_sys->p_vout, &fmt, &state, "opengl", 300000, 1000000 ); if( !p_sys->p_vd ) { vlc_object_release( p_sys->p_vout ); goto error; } var_Create( p_sys->p_vout, "fullscreen", VLC_VAR_BOOL ); var_AddCallback( p_sys->p_vout, "fullscreen", VoutCallback, p_sys->p_vd ); gl = vout_GetDisplayOpengl( p_sys->p_vd ); if( !gl ) { vout_DeleteDisplay( p_sys->p_vd, NULL ); vlc_object_release( p_sys->p_vout ); goto error; } /* Work-around the projectM locale bug */ loc = newlocale (LC_NUMERIC_MASK, "C", NULL); oldloc = uselocale (loc); /* Create the projectM object */ #ifndef HAVE_PROJECTM2 psz_config = var_InheritString( p_filter, "projectm-config" ); p_projectm = new projectM( psz_config ); free( psz_config ); #else psz_preset_path = var_InheritString( p_filter, "projectm-preset-path" ); #ifdef WIN32 if ( psz_preset_path == NULL ) { char *psz_data_path = config_GetDataDir( p_filter ); asprintf( &psz_preset_path, "%s" DIR_SEP "visualization", psz_data_path ); free( psz_data_path ); } #endif psz_title_font = var_InheritString( p_filter, "projectm-title-font" ); psz_menu_font = var_InheritString( p_filter, "projectm-menu-font" ); settings.meshX = var_InheritInteger( p_filter, "projectm-meshx" ); settings.meshY = var_InheritInteger( p_filter, "projectm-meshy" ); settings.fps = 35; settings.textureSize = var_InheritInteger( p_filter, "projectm-texture-size" ); settings.windowWidth = p_sys->i_width; settings.windowHeight = p_sys->i_height; settings.presetURL = psz_preset_path; settings.titleFontURL = psz_title_font; settings.menuFontURL = psz_menu_font; settings.smoothPresetDuration = 5; settings.presetDuration = 30; settings.beatSensitivity = 10; settings.aspectCorrection = 1; settings.easterEgg = 1; settings.shuffleEnabled = 1; p_projectm = new projectM( settings ); free( psz_menu_font ); free( psz_title_font ); free( psz_preset_path ); #endif /* HAVE_PROJECTM2 */ p_sys->i_buffer_size = p_projectm->pcm()->maxsamples; p_sys->p_buffer = (float*)calloc( p_sys->i_buffer_size, sizeof( float ) ); vlc_sem_post( &p_sys->ready ); /* Choose a preset randomly or projectM will always show the first one */ if ( p_projectm->getPlaylistSize() > 0 ) p_projectm->selectPreset( (unsigned)vlc_mrand48() % p_projectm->getPlaylistSize() ); /* */ for( ;; ) { const mtime_t i_deadline = mdate() + CLOCK_FREQ / 50; /* 50 fps max */ /* Manage the events */ vout_ManageDisplay( p_sys->p_vd, true ); if( p_sys->p_vd->cfg->display.width != i_last_width || p_sys->p_vd->cfg->display.height != i_last_height ) { /* FIXME it is not perfect as we will have black bands */ vout_display_place_t place; vout_display_PlacePicture( &place, &p_sys->p_vd->source, p_sys->p_vd->cfg, false ); p_projectm->projectM_resetGL( place.width, place.height ); i_last_width = p_sys->p_vd->cfg->display.width; i_last_height = p_sys->p_vd->cfg->display.height; } /* Render the image and swap the buffers */ vlc_mutex_lock( &p_sys->lock ); if( p_sys->i_nb_samples > 0 ) { p_projectm->pcm()->addPCMfloat( p_sys->p_buffer, p_sys->i_nb_samples ); p_sys->i_nb_samples = 0; } if( p_sys->b_quit ) { vlc_mutex_unlock( &p_sys->lock ); delete p_projectm; vout_DeleteDisplay( p_sys->p_vd, NULL ); vlc_object_release( p_sys->p_vout ); if (loc != (locale_t)0) { uselocale (oldloc); freelocale (loc); } return NULL; } vlc_mutex_unlock( &p_sys->lock ); p_projectm->renderFrame(); /* */ mwait( i_deadline ); if( !vlc_gl_Lock(gl) ) { vlc_gl_Swap( gl ); vlc_gl_Unlock( gl ); } } abort(); error: p_sys->b_error = true; vlc_sem_post( &p_sys->ready ); return NULL; }
/** * ProjectM update thread which do the rendering * @param p_this: the p_thread object */ static void *Thread( void *p_data ) { filter_t *p_filter = (filter_t*)p_data; filter_sys_t *p_sys = p_filter->p_sys; int cancel = vlc_savecancel(); video_format_t fmt; vout_opengl_t *gl; int i_last_width = 0; int i_last_height = 0; #ifdef HAVE_PROJECTM2 projectM::Settings settings; #endif /* Create the openGL provider */ p_sys->p_vout = (vout_thread_t *)vlc_object_create( p_filter, sizeof(vout_thread_t) ); if( !p_sys->p_vout ) goto error; vlc_object_attach( p_sys->p_vout, p_filter ); /* */ video_format_Init( &fmt, 0 ); video_format_Setup( &fmt, VLC_CODEC_RGB32, p_sys->i_width, p_sys->i_height, 0, 1 ); fmt.i_sar_num = 1; fmt.i_sar_den = 1; vout_display_state_t state; memset( &state, 0, sizeof(state) ); state.cfg.display.sar.num = 1; state.cfg.display.sar.den = 1; state.cfg.is_display_filled = true; state.cfg.zoom.num = 1; state.cfg.zoom.den = 1; state.sar.num = 1; state.sar.den = 1; p_sys->p_vd = vout_NewDisplay( p_sys->p_vout, &fmt, &state, "opengl", 300000, 1000000 ); if( !p_sys->p_vd ) { vlc_object_release( p_sys->p_vout ); goto error; } var_Create( p_sys->p_vout, "fullscreen", VLC_VAR_BOOL ); var_AddCallback( p_sys->p_vout, "fullscreen", VoutCallback, p_sys->p_vd ); gl = vout_GetDisplayOpengl( p_sys->p_vd ); if( !gl ) { vout_DeleteDisplay( p_sys->p_vd, NULL ); vlc_object_release( p_sys->p_vout ); goto error; } /* Create the projectM object */ #ifndef HAVE_PROJECTM2 p_sys->p_projectm = new projectM( p_sys->psz_config ); #else settings.meshX = 32; settings.meshY = 24; settings.fps = 35; settings.textureSize = 1024; settings.windowWidth = p_sys->i_width; settings.windowHeight = p_sys->i_height; settings.presetURL = p_sys->psz_preset_path; settings.titleFontURL = p_sys->psz_title_font; settings.menuFontURL = p_sys->psz_menu_font; settings.smoothPresetDuration = 5; settings.presetDuration = 30; settings.beatSensitivity = 10; settings.aspectCorrection = 1; settings.easterEgg = 1; settings.shuffleEnabled = 1; p_sys->p_projectm = new projectM( settings ); #endif p_sys->i_buffer_size = p_sys->p_projectm->pcm()->maxsamples; p_sys->p_buffer = (float*)calloc( p_sys->i_buffer_size, sizeof( float ) ); vlc_sem_post( &p_sys->ready ); /* TODO: Give to projectm the name of the input p_sys->p_projectm->projectM_setTitle( "" ); */ /* */ for( ;; ) { const mtime_t i_deadline = mdate() + CLOCK_FREQ / 50; /* 50 fps max */ /* Manage the events */ vout_ManageDisplay( p_sys->p_vd, true ); if( p_sys->p_vd->cfg->display.width != i_last_width || p_sys->p_vd->cfg->display.height != i_last_height ) { /* FIXME it is not perfect as we will have black bands */ vout_display_place_t place; vout_display_PlacePicture( &place, &p_sys->p_vd->source, p_sys->p_vd->cfg, false ); p_sys->p_projectm->projectM_resetGL( place.width, place.height ); i_last_width = p_sys->p_vd->cfg->display.width; i_last_height = p_sys->p_vd->cfg->display.height; } /* Render the image and swap the buffers */ vlc_mutex_lock( &p_sys->lock ); if( p_sys->i_nb_samples > 0 ) { p_sys->p_projectm->pcm()->addPCMfloat( p_sys->p_buffer, p_sys->i_nb_samples ); p_sys->i_nb_samples = 0; } if( p_sys->b_quit ) { vlc_mutex_unlock( &p_sys->lock ); delete p_sys->p_projectm; vout_DeleteDisplay( p_sys->p_vd, NULL ); vlc_object_release( p_sys->p_vout ); return NULL; } vlc_mutex_unlock( &p_sys->lock ); p_sys->p_projectm->renderFrame(); /* */ mwait( i_deadline ); if( !vout_opengl_Lock(gl) ) { vout_opengl_Swap( gl ); vout_opengl_Unlock( gl ); } } abort(); error: p_sys->b_error = true; vlc_sem_post( &p_sys->ready ); return NULL; }
static int OpenVideo(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t *)p_this; vout_display_sys_t *sys; struct decklink_sys_t *decklink_sys; vd->sys = sys = (vout_display_sys_t*)malloc(sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->tenbits = var_InheritBool(p_this, VIDEO_CFG_PREFIX "tenbits"); sys->nosignal_delay = var_InheritInteger(p_this, VIDEO_CFG_PREFIX "nosignal-delay"); sys->pic_nosignal = NULL; decklink_sys = OpenDecklink(vd); if (!decklink_sys) { if (sys->pic_nosignal) picture_Release(sys->pic_nosignal); free(sys); return VLC_EGENERIC; } sys->pool = NULL; vd->fmt.i_chroma = sys->tenbits ? VLC_CODEC_I422_10L /* we will convert to v210 */ : VLC_CODEC_UYVY; //video_format_FixRgb(&(vd->fmt)); vd->fmt.i_width = decklink_sys->i_width; vd->fmt.i_height = decklink_sys->i_height; char *pic_file = var_InheritString(p_this, VIDEO_CFG_PREFIX "nosignal-image"); if (pic_file) { image_handler_t *img = image_HandlerCreate(p_this); if (!img) { msg_Err(p_this, "Could not create image converter"); } else { video_format_t in, dummy; video_format_Init(&in, 0); video_format_Setup(&in, 0, vd->fmt.i_width, vd->fmt.i_height, vd->fmt.i_width, vd->fmt.i_height, 1, 1); video_format_Init(&dummy, 0); picture_t *png = image_ReadUrl(img, pic_file, &dummy, &in); if (png) { msg_Err(p_this, "Converting"); sys->pic_nosignal = image_Convert(img, png, &in, &vd->fmt); picture_Release(png); } image_HandlerDelete(img); } free(pic_file); if (!sys->pic_nosignal) { CloseVideo(p_this); msg_Err(p_this, "Could not create no signal picture"); return VLC_EGENERIC; } } vd->info.has_hide_mouse = true; vd->pool = PoolVideo; vd->prepare = NULL; vd->display = DisplayVideo; vd->control = ControlVideo; vd->manage = NULL; vout_display_SendEventFullscreen(vd, false); return VLC_SUCCESS; }
/** * Update thread which do the rendering * @param p_this: the p_thread object */ static void *Thread( void *p_data ) { filter_t *p_filter = (filter_t*)p_data; filter_sys_t *p_sys = p_filter->p_sys; video_format_t fmt; vlc_gl_t *gl; unsigned int i_last_width = 0; unsigned int i_last_height = 0; /* Create the openGL provider */ p_sys->p_vout = (vout_thread_t *)vlc_object_create(p_filter, sizeof(vout_thread_t)); if (!p_sys->p_vout) goto error; /* Configure the video format for the opengl provider. */ video_format_Init(&fmt, 0); video_format_Setup(&fmt, VLC_CODEC_RGB32, p_sys->i_width, p_sys->i_height, 0, 1 ); fmt.i_sar_num = 1; fmt.i_sar_den = 1; /* Init vout state. */ vout_display_state_t state; memset(&state, 0, sizeof(state)); state.cfg.display.sar.num = 1; state.cfg.display.sar.den = 1; state.cfg.is_display_filled = true; state.cfg.zoom.num = 1; state.cfg.zoom.den = 1; state.sar.num = 1; state.sar.den = 1; p_sys->p_vd = vout_NewDisplay(p_sys->p_vout, &fmt, &state, "opengl", 1000000, 1000000); if (!p_sys->p_vd) { vlc_object_release(p_sys->p_vout); goto error; } gl = vout_GetDisplayOpengl(p_sys->p_vd); if (!gl) { vout_DeleteDisplay(p_sys->p_vd, NULL); vlc_object_release(p_sys->p_vout); goto error; } vlc_sem_post(&p_sys->ready); initOpenGLScene(); float height[NB_BANDS] = {0}; while (1) { block_t *block = block_FifoGet(p_sys->fifo); int canc = vlc_savecancel(); /* Manage the events */ vout_ManageDisplay(p_sys->p_vd, true); if (p_sys->p_vd->cfg->display.width != i_last_width || p_sys->p_vd->cfg->display.height != i_last_height) { /* FIXME it is not perfect as we will have black bands */ vout_display_place_t place; vout_display_PlacePicture(&place, &p_sys->p_vd->source, p_sys->p_vd->cfg, false); i_last_width = p_sys->p_vd->cfg->display.width; i_last_height = p_sys->p_vd->cfg->display.height; } /* Horizontal scale for 20-band equalizer */ const unsigned xscale[] = {0,1,2,3,4,5,6,7,8,11,15,20,27, 36,47,62,82,107,141,184,255}; fft_state *p_state; /* internal FFT data */ unsigned i, j; float p_output[FFT_BUFFER_SIZE]; /* Raw FFT Result */ int16_t p_buffer1[FFT_BUFFER_SIZE]; /* Buffer on which we perform the FFT (first channel) */ int16_t p_dest[FFT_BUFFER_SIZE]; /* Adapted FFT result */ float *p_buffl = (float*)block->p_buffer; /* Original buffer */ int16_t *p_buffs; /* int16_t converted buffer */ int16_t *p_s16_buff; /* int16_t converted buffer */ /* Allocate the buffer only if the number of samples change */ if (block->i_nb_samples != p_sys->i_prev_nb_samples) { free(p_sys->p_prev_s16_buff); p_sys->p_prev_s16_buff = malloc(block->i_nb_samples * p_sys->i_channels * sizeof(int16_t)); if (!p_sys->p_prev_s16_buff) goto release; p_sys->i_prev_nb_samples = block->i_nb_samples; } p_buffs = p_s16_buff = p_sys->p_prev_s16_buff; /* Convert the buffer to int16_t Pasted from float32tos16.c */ for (i = block->i_nb_samples * p_sys->i_channels; i--;) { union {float f; int32_t i;} u; u.f = *p_buffl + 384.0; if (u.i > 0x43c07fff) *p_buffs = 32767; else if (u.i < 0x43bf8000) *p_buffs = -32768; else *p_buffs = u.i - 0x43c00000; p_buffl++; p_buffs++; } p_state = visual_fft_init(); if (!p_state) { msg_Err(p_filter,"unable to initialize FFT transform"); goto release; } p_buffs = p_s16_buff; for (i = 0 ; i < FFT_BUFFER_SIZE; i++) { p_output[i] = 0; p_buffer1[i] = *p_buffs; p_buffs += p_sys->i_channels; if (p_buffs >= &p_s16_buff[block->i_nb_samples * p_sys->i_channels]) p_buffs = p_s16_buff; } fft_perform (p_buffer1, p_output, p_state); for (i = 0; i< FFT_BUFFER_SIZE; ++i) p_dest[i] = p_output[i] * (2 ^ 16) / ((FFT_BUFFER_SIZE / 2 * 32768) ^ 2); for (i = 0 ; i < NB_BANDS; i++) { /* Decrease the previous size of the bar. */ height[i] -= BAR_DECREMENT; if (height[i] < 0) height[i] = 0; int y = 0; /* We search the maximum on one scale to determine the current size of the bar. */ for (j = xscale[i]; j < xscale[i + 1]; j++) { if (p_dest[j] > y) y = p_dest[j]; } /* Calculate the height of the bar */ float new_height = y != 0 ? log(y) * 0.4 : 0; height[i] = new_height > height[i] ? new_height : height[i]; } /* Determine the camera rotation angle. */ p_sys->f_rotationAngle += p_sys->f_rotationIncrement; if (p_sys->f_rotationAngle <= -ROTATION_MAX) p_sys->f_rotationIncrement = ROTATION_INCREMENT; else if (p_sys->f_rotationAngle >= ROTATION_MAX) p_sys->f_rotationIncrement = -ROTATION_INCREMENT; /* Render the frame. */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(p_sys->f_rotationAngle, 0, 1, 0); drawBars(height); glPopMatrix(); /* Wait to swapp the frame on time. */ mwait(block->i_pts + (block->i_length / 2)); if (!vlc_gl_Lock(gl)) { vlc_gl_Swap(gl); vlc_gl_Unlock(gl); } release: block_Release(block); vlc_restorecancel(canc); } assert(0); error: p_sys->b_error = true; vlc_sem_post(&p_sys->ready); return NULL; }
/***************************************************************************** * 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; }
/** * VSXu update thread which do the rendering * @param p_this: the p_thread object */ static void *Thread( void *p_data ) { filter_t *p_filter = (filter_t*)p_data; filter_sys_t *p_sys = p_filter->p_sys; // our abstract manager holder vsx_manager_abs* manager = 0; // temp audio buffer for sending to vsxu through manager float f_sample_buf[512]; // vsxu logo intro vsx_logo_intro* intro = 0; vout_display_t *p_vd; video_format_t fmt; vlc_gl_t *gl; unsigned int i_last_width = 0; unsigned int i_last_height = 0; bool first = true; bool run = true; /* Create the openGL provider */ vout_thread_t *p_vout; p_vout = (vout_thread_t *)vlc_object_create( p_filter, sizeof(vout_thread_t) ); if( !p_vout ) goto error; video_format_Init( &fmt, 0 ); video_format_Setup( &fmt, VLC_CODEC_RGB32, p_sys->i_width, p_sys->i_height, 0, 1 ); fmt.i_sar_num = 1; fmt.i_sar_den = 1; vout_display_state_t state; memset( &state, 0, sizeof(state) ); state.cfg.display.sar.num = 1; state.cfg.display.sar.den = 1; state.cfg.is_display_filled = true; state.cfg.zoom.num = 1; state.cfg.zoom.den = 1; state.sar.num = 1; state.sar.den = 1; p_vd = vout_NewDisplay( p_vout, &fmt, &state, "opengl", 300000, 1000000 ); if( !p_vd ) { vlc_object_release( p_vout ); goto error; } var_Create( p_vout, "fullscreen", VLC_VAR_BOOL ); var_AddCallback( p_vout, "fullscreen", VoutCallback, p_vd ); gl = vout_GetDisplayOpengl( p_vd ); if( !gl ) { var_DelCallback( p_vout, "fullscreen", VoutCallback, p_vd ); vout_DeleteDisplay( p_vd, NULL ); vlc_object_release( p_vout ); goto error; } // tell main thread we are ready vlc_sem_post( &p_sys->ready ); while ( run ) { /* Manage the events */ vout_ManageDisplay( p_vd, true ); if( p_vd->cfg->display.width != i_last_width || p_vd->cfg->display.height != i_last_height ) { /* FIXME it is not perfect as we will have black bands */ vout_display_place_t place; vout_display_PlacePicture( &place, &p_vd->source, p_vd->cfg, false ); i_last_width = p_vd->cfg->display.width; i_last_height = p_vd->cfg->display.height; } // look for control commands from outside the thread vlc_mutex_lock( &p_sys->lock ); if( p_sys->b_quit ) { run = false; } vlc_mutex_unlock( &p_sys->lock ); if (first) { // only run this once first = false; // create a new manager manager = manager_factory(); // init manager with the shared path and sound input type. manager->init( 0, "media_player" ); // only show logo once // keep track of iterations static int i_iterations = 0; if ( i_iterations++ < 1 ) { intro = new vsx_logo_intro(); intro->set_destroy_textures( false ); } } // lock cyclic buffer mutex and copy floats vlc_mutex_lock( &p_sys->cyclic_block_mutex ); block_holder* bh = p_sys->vsxu_cyclic_buffer->consume(); memcpy( &f_sample_buf[0], (void*)(&bh->data[0]), sizeof(float) * 512 ); vlc_mutex_unlock( &p_sys->cyclic_block_mutex ); // send sound pointer to vsxu manager->set_sound_wave( &f_sample_buf[0] ); // render vsxu engine if (manager) manager->render(); // render intro if (intro) intro->draw(); // swap buffers etc. if( !vlc_gl_Lock(gl) ) { vlc_gl_Swap( gl ); vlc_gl_Unlock( gl ); } } // stop vsxu nicely (unloads textures and frees memory) if (manager) manager->stop(); // call manager factory to destruct our manager object if (manager) manager_destroy( manager ); // delete the intro (if ever allocated) if (intro) delete intro; var_DelCallback( p_vout, "fullscreen", VoutCallback, p_vd ); // clean out vlc opengl stuff vout_DeleteDisplay( p_vd, NULL ); vlc_object_release( p_vout ); // clean up the cyclic buffer vlc_mutex_lock( &p_sys->cyclic_block_mutex ); p_sys->vsxu_cyclic_buffer->reset(); vlc_mutex_unlock( &p_sys->cyclic_block_mutex ); // die return NULL; error: p_sys->b_error = true; vlc_sem_post( &p_sys->ready ); return NULL; }
/** * Sub source */ static subpicture_t *FilterSub(filter_t *p_filter, vlc_tick_t date) { filter_sys_t *p_sys = p_filter->p_sys; BarGraph_t *p_BarGraph = &(p_sys->p_BarGraph); subpicture_t *p_spu; subpicture_region_t *p_region; video_format_t fmt; picture_t *p_pic; vlc_mutex_lock(&p_sys->lock); /* Basic test: b_spu_update occurs on a dynamic change */ if (!p_sys->b_spu_update) { vlc_mutex_unlock(&p_sys->lock); return NULL; } p_pic = p_BarGraph->p_pic; /* Allocate the subpicture internal data. */ p_spu = filter_NewSubpicture(p_filter); if (!p_spu) goto exit; p_spu->b_absolute = p_sys->b_absolute; p_spu->i_start = date; p_spu->i_stop = 0; p_spu->b_ephemer = true; /* Send an empty subpicture to clear the display when needed */ if (!p_pic || !p_BarGraph->i_alpha) goto exit; /* Create new SPU region */ video_format_Init(&fmt, VLC_CODEC_YUVA); fmt.i_sar_num = fmt.i_sar_den = 1; fmt.i_width = fmt.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch; fmt.i_height = fmt.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines; fmt.i_x_offset = fmt.i_y_offset = 0; p_region = subpicture_region_New(&fmt); if (!p_region) { msg_Err(p_filter, "cannot allocate SPU region"); subpicture_Delete(p_spu); p_spu = NULL; goto exit; } /* */ picture_Copy(p_region->p_picture, p_pic); /* where to locate the bar graph: */ if (p_sys->i_pos < 0) { /* set to an absolute xy */ p_region->i_align = SUBPICTURE_ALIGN_RIGHT | SUBPICTURE_ALIGN_TOP; p_spu->b_absolute = true; } else { /* set to one of the 9 relative locations */ p_region->i_align = p_sys->i_pos; p_spu->b_absolute = false; } p_region->i_x = p_sys->i_pos_x; p_region->i_y = p_sys->i_pos_y; p_spu->p_region = p_region; p_spu->i_alpha = p_BarGraph->i_alpha ; exit: 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; }
/***************************************************************************** * Init: initialize the OpenGL video thread output method *****************************************************************************/ static int Init( vout_thread_t *p_vout ) { vout_sys_t *p_sys = p_vout->p_sys; p_sys->p_vout->pf_init( p_sys->p_vout ); p_sys->gl.lock = OpenglLock; p_sys->gl.unlock = OpenglUnlock; p_sys->gl.swap = OpenglSwap; p_sys->gl.sys = p_sys->p_vout; video_format_t fmt; video_format_Init( &fmt, 0 ); video_format_Setup( &fmt, p_vout->render.i_chroma, p_vout->render.i_width, p_vout->render.i_height, p_vout->render.i_aspect * p_vout->render.i_height, VOUT_ASPECT_FACTOR * p_vout->render.i_width ); if( vout_display_opengl_Init( &p_sys->vgl, &fmt, &p_sys->gl ) ) { I_OUTPUTPICTURES = 0; return VLC_EGENERIC; } p_sys->p_pool = vout_display_opengl_GetPool( &p_sys->vgl ); if( !p_sys->p_pool ) { vout_display_opengl_Clean( &p_sys->vgl ); I_OUTPUTPICTURES = 0; return VLC_EGENERIC; } /* */ p_vout->output.i_chroma = fmt.i_chroma; p_vout->output.i_rmask = fmt.i_rmask; p_vout->output.i_gmask = fmt.i_gmask; p_vout->output.i_bmask = fmt.i_bmask; /* Since OpenGL can do rescaling for us, stick to the default * coordinates and aspect. */ p_vout->output.i_width = p_vout->render.i_width; p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_aspect = p_vout->render.i_aspect; p_vout->fmt_out = p_vout->fmt_in; p_vout->fmt_out.i_chroma = p_vout->output.i_chroma; /* */ p_sys->p_current = picture_pool_Get( p_sys->p_pool ); p_vout->p_picture[0] = *p_sys->p_current; p_vout->p_picture[0].i_status = DESTROYED_PICTURE; p_vout->p_picture[0].i_type = DIRECT_PICTURE; p_vout->p_picture[0].i_refcount = 0; p_vout->p_picture[0].p_sys = NULL; PP_OUTPUTPICTURE[0] = &p_vout->p_picture[0]; I_OUTPUTPICTURES = 1; return VLC_SUCCESS; }