bool gst_vlc_set_vout_fmt( GstVideoInfo *p_info, GstVideoAlignment *p_align, GstCaps *p_caps, decoder_t *p_dec ) { es_format_t *p_outfmt = &p_dec->fmt_out; video_format_t *p_voutfmt = &p_dec->fmt_out.video; GstStructure *p_str = gst_caps_get_structure( p_caps, 0 ); vlc_fourcc_t i_chroma; int i_padded_width, i_padded_height; i_chroma = p_outfmt->i_codec = vlc_fourcc_GetCodecFromString( VIDEO_ES, gst_structure_get_string( p_str, "format" ) ); if( !i_chroma ) { msg_Err( p_dec, "video chroma type not supported" ); return false; } i_padded_width = GST_VIDEO_INFO_WIDTH( p_info ) + p_align->padding_left + p_align->padding_right; i_padded_height = GST_VIDEO_INFO_HEIGHT( p_info ) + p_align->padding_top + p_align->padding_bottom; video_format_Setup( p_voutfmt, i_chroma, i_padded_width, i_padded_height, GST_VIDEO_INFO_WIDTH( p_info ), GST_VIDEO_INFO_HEIGHT( p_info ), GST_VIDEO_INFO_PAR_N( p_info ), GST_VIDEO_INFO_PAR_D( p_info )); p_voutfmt->i_x_offset = p_align->padding_left; p_voutfmt->i_y_offset = p_align->padding_top; p_voutfmt->i_frame_rate = GST_VIDEO_INFO_FPS_N( p_info ); p_voutfmt->i_frame_rate_base = GST_VIDEO_INFO_FPS_D( p_info ); return true; }
picture_t *picture_NewFromResource( const video_format_t *p_fmt, const picture_resource_t *p_resource ) { video_format_t fmt = *p_fmt; /* It is needed to be sure all information are filled */ video_format_Setup( &fmt, p_fmt->i_chroma, p_fmt->i_width, p_fmt->i_height, p_fmt->i_visible_width, p_fmt->i_visible_height, p_fmt->i_sar_num, p_fmt->i_sar_den ); if( p_fmt->i_x_offset < p_fmt->i_width && p_fmt->i_y_offset < p_fmt->i_height && p_fmt->i_visible_width > 0 && p_fmt->i_x_offset + p_fmt->i_visible_width <= p_fmt->i_width && p_fmt->i_visible_height > 0 && p_fmt->i_y_offset + p_fmt->i_visible_height <= p_fmt->i_height ) video_format_CopyCrop( &fmt, p_fmt ); /* */ picture_t *p_picture = calloc( 1, sizeof(*p_picture) ); if( !p_picture ) return NULL; /* Make sure the real dimensions are a multiple of 16 */ if( picture_Setup( p_picture, &fmt ) ) { free( p_picture ); return NULL; } if( p_resource ) { p_picture->p_sys = p_resource->p_sys; p_picture->gc.pf_destroy = p_resource->pf_destroy; assert( p_picture->gc.p_sys == NULL ); for( int i = 0; i < p_picture->i_planes; i++ ) { p_picture->p[i].p_pixels = p_resource->p[i].p_pixels; p_picture->p[i].i_lines = p_resource->p[i].i_lines; p_picture->p[i].i_pitch = p_resource->p[i].i_pitch; } } else { if( AllocatePicture( p_picture ) ) { free( p_picture ); return NULL; } } /* */ p_picture->format = fmt; atomic_init( &p_picture->gc.refcount, 1 ); if( p_picture->gc.pf_destroy == NULL ) p_picture->gc.pf_destroy = PictureDestroy; return p_picture; }
picture_t *picture_New( vlc_fourcc_t i_chroma, int i_width, int i_height, int i_sar_num, int i_sar_den ) { video_format_t fmt; memset( &fmt, 0, sizeof(fmt) ); video_format_Setup( &fmt, i_chroma, i_width, i_height, i_width, i_height, i_sar_num, i_sar_den ); return picture_NewFromFormat( &fmt ); }
picture_t *picture_NewFromResource( const video_format_t *p_fmt, const picture_resource_t *p_resource ) { video_format_t fmt = *p_fmt; /* It is needed to be sure all information are filled */ video_format_Setup( &fmt, p_fmt->i_chroma, p_fmt->i_width, p_fmt->i_height, p_fmt->i_sar_num, p_fmt->i_sar_den ); if( p_fmt->i_x_offset < p_fmt->i_width && p_fmt->i_y_offset < p_fmt->i_height && p_fmt->i_visible_width > 0 && p_fmt->i_x_offset + p_fmt->i_visible_width <= p_fmt->i_width && p_fmt->i_visible_height > 0 && p_fmt->i_y_offset + p_fmt->i_visible_height <= p_fmt->i_height ) video_format_CopyCrop( &fmt, p_fmt ); /* */ picture_t *p_picture = calloc( 1, sizeof(*p_picture) ); if( !p_picture ) return NULL; if( p_resource ) { if( picture_Setup( p_picture, fmt.i_chroma, fmt.i_width, fmt.i_height, fmt.i_sar_num, fmt.i_sar_den ) ) { free( p_picture ); return NULL; } p_picture->p_sys = p_resource->p_sys; for( int i = 0; i < p_picture->i_planes; i++ ) { p_picture->p[i].p_pixels = p_resource->p[i].p_pixels; p_picture->p[i].i_lines = p_resource->p[i].i_lines; p_picture->p[i].i_pitch = p_resource->p[i].i_pitch; } } else { if( vout_AllocatePicture( p_picture, fmt.i_chroma, fmt.i_width, fmt.i_height, fmt.i_sar_num, fmt.i_sar_den ) ) { free( p_picture ); return NULL; } } /* */ p_picture->format = fmt; p_picture->i_refcount = 1; p_picture->pf_release = PictureReleaseCallback; return p_picture; }
overlay_t *OverlayCreate( void ) { overlay_t *p_ovl = calloc( 1, sizeof( overlay_t ) ); if( p_ovl == NULL ) return NULL; p_ovl->i_x = p_ovl->i_y = 0; p_ovl->i_alpha = 0xFF; p_ovl->b_active = false; video_format_Setup( &p_ovl->format, VLC_FOURCC( '\0','\0','\0','\0') , 0, 0, 1, 1 ); p_ovl->p_fontstyle = text_style_New(); p_ovl->data.p_text = NULL; return p_ovl; }
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; }
/** * 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; }
int picture_Setup( picture_t *p_picture, video_format_t *fmt ) { /* Store default values */ p_picture->i_planes = 0; for( unsigned i = 0; i < VOUT_MAX_PLANES; i++ ) { plane_t *p = &p_picture->p[i]; p->p_pixels = NULL; p->i_pixel_pitch = 0; } atomic_init( &p_picture->gc.refcount, 0 ); p_picture->gc.pf_destroy = NULL; p_picture->gc.p_sys = NULL; p_picture->i_nb_fields = 2; video_format_Setup( &p_picture->format, fmt->i_chroma, fmt->i_width, fmt->i_height, fmt->i_visible_width, fmt->i_visible_height, fmt->i_sar_num, fmt->i_sar_den ); const vlc_chroma_description_t *p_dsc = vlc_fourcc_GetChromaDescription( p_picture->format.i_chroma ); if( !p_dsc ) return VLC_EGENERIC; /* We want V (width/height) to respect: (V * p_dsc->p[i].w.i_num) % p_dsc->p[i].w.i_den == 0 (V * p_dsc->p[i].w.i_num/p_dsc->p[i].w.i_den * p_dsc->i_pixel_size) % 16 == 0 Which is respected if you have V % lcm( p_dsc->p[0..planes].w.i_den * 16) == 0 */ int i_modulo_w = 1; int i_modulo_h = 1; unsigned int i_ratio_h = 1; for( unsigned i = 0; i < p_dsc->plane_count; i++ ) { i_modulo_w = LCM( i_modulo_w, 16 * p_dsc->p[i].w.den ); i_modulo_h = LCM( i_modulo_h, 16 * p_dsc->p[i].h.den ); if( i_ratio_h < p_dsc->p[i].h.den ) i_ratio_h = p_dsc->p[i].h.den; } i_modulo_h = LCM( i_modulo_h, 32 ); const int i_width_aligned = ( fmt->i_width + i_modulo_w - 1 ) / i_modulo_w * i_modulo_w; const int i_height_aligned = ( fmt->i_height + i_modulo_h - 1 ) / i_modulo_h * i_modulo_h; const int i_height_extra = 2 * i_ratio_h; /* This one is a hack for some ASM functions */ for( unsigned i = 0; i < p_dsc->plane_count; i++ ) { plane_t *p = &p_picture->p[i]; p->i_lines = (i_height_aligned + i_height_extra ) * p_dsc->p[i].h.num / p_dsc->p[i].h.den; p->i_visible_lines = fmt->i_visible_height * p_dsc->p[i].h.num / p_dsc->p[i].h.den; p->i_pitch = i_width_aligned * p_dsc->p[i].w.num / p_dsc->p[i].w.den * p_dsc->pixel_size; p->i_visible_pitch = fmt->i_visible_width * p_dsc->p[i].w.num / p_dsc->p[i].w.den * p_dsc->pixel_size; p->i_pixel_pitch = p_dsc->pixel_size; assert( (p->i_pitch % 16) == 0 ); } p_picture->i_planes = p_dsc->plane_count; return VLC_SUCCESS; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; switch( p_dec->fmt_in.i_codec ) { /* Planar YUV */ case VLC_CODEC_I444: case VLC_CODEC_I422: case VLC_CODEC_I420: case VLC_CODEC_YV12: case VLC_CODEC_I411: case VLC_CODEC_I410: case VLC_CODEC_GREY: case VLC_CODEC_YUVP: /* Packed YUV */ case VLC_CODEC_YUYV: case VLC_CODEC_YVYU: case VLC_CODEC_UYVY: case VLC_CODEC_VYUY: /* RGB */ case VLC_CODEC_RGB32: case VLC_CODEC_RGB24: case VLC_CODEC_RGB16: case VLC_CODEC_RGB15: case VLC_CODEC_RGB8: case VLC_CODEC_RGBP: break; default: return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) return VLC_ENOMEM; /* Misc init */ p_dec->p_sys->b_packetizer = false; p_sys->b_invert = 0; if( (int)p_dec->fmt_in.video.i_height < 0 ) { /* Frames are coded from bottom to top */ p_dec->fmt_in.video.i_height = (unsigned int)(-(int)p_dec->fmt_in.video.i_height); p_sys->b_invert = true; } if( p_dec->fmt_in.video.i_width <= 0 || p_dec->fmt_in.video.i_height <= 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base ); if( p_dec->fmt_out.video.i_frame_rate == 0 || p_dec->fmt_out.video.i_frame_rate_base == 0) { msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead", p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base); date_Init( &p_sys->pts, 25, 1 ); } /* Find out p_vdec->i_raw_size */ video_format_Setup( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height, p_dec->fmt_in.video.i_aspect ); p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel * p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8; if( !p_dec->fmt_in.video.i_aspect ) { p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; } /* Set callbacks */ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; 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; }
/***************************************************************************** * 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; }
/***************************************************************************** * Open: initializes raw DV demux structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; int i_width=-1, i_height=-1; unsigned u_fps_num, u_fps_den; vlc_fourcc_t i_chroma = 0; unsigned int i_sar_num; unsigned int i_sar_den; const struct preset_t *p_preset = NULL; const uint8_t *p_peek; bool b_y4m = false; if( stream_Peek( p_demux->s, &p_peek, 9 ) == 9 ) { /* http://wiki.multimedia.cx/index.php?title=YUV4MPEG2 */ if( !strncmp( (char *)p_peek, "YUV4MPEG2", 9 ) ) { b_y4m = true; goto valid; } } if( !p_demux->b_force ) { /* guess preset based on file extension */ if( !p_demux->psz_file ) return VLC_EGENERIC; const char *psz_ext = strrchr( p_demux->psz_file, '.' ); if( !psz_ext ) return VLC_EGENERIC; psz_ext++; for( unsigned i = 0; p_presets[i].psz_ext ; i++ ) { if( !strcasecmp( psz_ext, p_presets[i].psz_ext ) ) { p_preset = &p_presets[i]; goto valid; } } return VLC_EGENERIC; } valid: p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_sys->b_y4m = b_y4m; /* guess the parameters based on the preset */ if( p_preset ) { i_width = p_preset->i_width; i_height = p_preset->i_height; u_fps_num = p_preset->u_fps_num; u_fps_den = p_preset->u_fps_den; i_sar_num = p_preset->u_ar_num * p_preset->i_height; i_sar_den = p_preset->u_ar_den * p_preset->i_width; i_chroma = p_preset->i_chroma; } /* override presets if yuv4mpeg2 */ if( b_y4m ) { /* The string should start with "YUV4MPEG2" */ char *psz = stream_ReadLine( p_demux->s ); char *psz_buf; int a = 1; int b = 1; if( unlikely(psz == NULL) ) goto error; /* NB, it is not possible to handle interlaced here, since the * interlaced picture flags are in picture_t not block_t */ #define READ_FRAC( key, num, den ) do { \ psz_buf = strstr( psz+9, key );\ if( psz_buf )\ {\ char *end = strchr( psz_buf+1, ' ' );\ char *sep;\ if( end ) *end = '\0';\ sep = strchr( psz_buf+1, ':' );\ if( sep )\ {\ *sep = '\0';\ den = atoi( sep+1 );\ }\ else\ {\ den = 1;\ }\ num = atoi( psz_buf+2 );\ if( sep ) *sep = ':';\ if( end ) *end = ' ';\ } } while(0) READ_FRAC( " W", i_width, a ); READ_FRAC( " H", i_height, a ); READ_FRAC( " F", u_fps_num, u_fps_den ); READ_FRAC( " A", a, b ); #undef READ_FRAC if( b != 0 ) { i_sar_num = a; i_sar_den = b; } psz_buf = strstr( psz+9, " C" ); if( psz_buf ) { static const struct { const char *psz_name; vlc_fourcc_t i_fcc; } formats[] = { { "420jpeg", VLC_CODEC_I420 }, { "420paldv", VLC_CODEC_I420 }, { "420", VLC_CODEC_I420 }, { "422", VLC_CODEC_I422 }, { "444", VLC_CODEC_I444 }, { "mono", VLC_CODEC_GREY }, { NULL, 0 } }; bool b_found = false; char *psz_end = strchr( psz_buf+1, ' ' ); if( psz_end ) *psz_end = '\0'; psz_buf += 2; for( int i = 0; formats[i].psz_name != NULL; i++ ) { if( !strncmp( psz_buf, formats[i].psz_name, strlen(formats[i].psz_name) ) ) { i_chroma = formats[i].i_fcc; b_found = true; break; } } if( !b_found ) msg_Warn( p_demux, "Unknown YUV4MPEG2 chroma type \"%s\"", psz_buf ); if( psz_end ) *psz_end = ' '; } free( psz ); } /* allow the user to override anything guessed from the input */ int i_tmp; i_tmp = var_CreateGetInteger( p_demux, "rawvid-width" ); if( i_tmp ) i_width = i_tmp; i_tmp = var_CreateGetInteger( p_demux, "rawvid-height" ); if( i_tmp ) i_height = i_tmp; char *psz_tmp; psz_tmp = var_CreateGetNonEmptyString( p_demux, "rawvid-chroma" ); if( psz_tmp ) { if( strlen( psz_tmp ) != 4 ) { msg_Err( p_demux, "Invalid fourcc format/chroma specification %s" " expecting four characters eg, UYVY", psz_tmp ); free( psz_tmp ); goto error; } memcpy( &i_chroma, psz_tmp, 4 ); msg_Dbg( p_demux, "Forcing chroma to 0x%.8x (%4.4s)", i_chroma, (char*)&i_chroma ); free( psz_tmp ); } if( var_InheritURational( p_demux, &u_fps_num, &u_fps_den, "rawvid-fps" ) ) { u_fps_num = 0; u_fps_den = 1; } if( var_InheritURational( p_demux, &i_sar_num, &i_sar_den, "rawvid-aspect-ratio" ) ) i_sar_num = i_sar_den = 1; /* moan about anything wrong */ if( i_width <= 0 || i_height <= 0 ) { msg_Err( p_demux, "width and height must be strictly positive." ); goto error; } if( !u_fps_num || !u_fps_den ) { msg_Err( p_demux, "invalid or no framerate specified." ); goto error; } if( i_chroma == 0 ) { msg_Err( p_demux, "invalid or no chroma specified." ); goto error; } /* fixup anything missing with sensible assumptions */ if( i_sar_num <= 0 || i_sar_den <= 0 ) { /* assume 1:1 sar */ i_sar_num = 1; i_sar_den = 1; } es_format_Init( &p_sys->fmt_video, VIDEO_ES, i_chroma ); video_format_Setup( &p_sys->fmt_video.video, i_chroma, i_width, i_height, i_width, i_height, i_sar_num, i_sar_den ); vlc_ureduce( &p_sys->fmt_video.video.i_frame_rate, &p_sys->fmt_video.video.i_frame_rate_base, u_fps_num, u_fps_den, 0); date_Init( &p_sys->pcr, p_sys->fmt_video.video.i_frame_rate, p_sys->fmt_video.video.i_frame_rate_base ); date_Set( &p_sys->pcr, 0 ); if( !p_sys->fmt_video.video.i_bits_per_pixel ) { msg_Err( p_demux, "Unsupported chroma 0x%.8x (%4.4s)", i_chroma, (char*)&i_chroma ); goto error; } p_sys->frame_size = i_width * i_height * p_sys->fmt_video.video.i_bits_per_pixel / 8; p_sys->p_es_video = es_out_Add( p_demux->out, &p_sys->fmt_video ); p_demux->pf_demux = Demux; p_demux->pf_control = Control; return VLC_SUCCESS; error: stream_Seek( p_demux->s, 0 ); // Workaround, but y4m uses stream_ReadLines free( p_sys ); return VLC_EGENERIC; }
static picture_t *Decode (decoder_t *dec, block_t **pp) { picture_t *pic = NULL; if (pp == NULL) return NULL; block_t *block = *pp; if (block == NULL) return NULL; *pp = NULL; if (block->i_pts <= VLC_TS_INVALID) goto drop; /* undated block, should never happen */ if (block->i_buffer < sz_XWDheader) goto drop; /* Skip XWD header */ const XWDFileHeader *hdr = (const void *)block->p_buffer; uint32_t hdrlen = ntohl(hdr->header_size); if (hdrlen < sz_XWDheader || ntohl(hdr->file_version) < XWD_FILE_VERSION || ntohl(hdr->pixmap_format) != 2 /* ZPixmap */) goto drop; hdrlen += ntohl(hdr->ncolors) * sz_XWDColor; if (hdrlen > block->i_buffer) goto drop; block->p_buffer += hdrlen; block->i_buffer -= hdrlen; /* Parse XWD header */ vlc_fourcc_t chroma = 0; switch (ntohl(hdr->pixmap_depth)) { case 8: if (ntohl(hdr->bits_per_pixel) == 8) chroma = VLC_CODEC_RGB8; break; case 15: if (ntohl(hdr->bits_per_pixel) == 16) chroma = VLC_CODEC_RGB15; break; case 16: if (ntohl(hdr->bits_per_pixel) == 16) chroma = VLC_CODEC_RGB16; break; case 24: switch (ntohl(hdr->bits_per_pixel)) { case 32: chroma = VLC_CODEC_RGB32; break; case 24: chroma = VLC_CODEC_RGB24; break; } break; case 32: if (ntohl(hdr->bits_per_pixel) == 32) chroma = VLC_CODEC_ARGB; break; } /* TODO: check image endianess, set RGB mask */ if (!chroma) goto drop; video_format_Setup(&dec->fmt_out.video, chroma, ntohl(hdr->pixmap_width), ntohl(hdr->pixmap_height), ntohl(hdr->pixmap_width), ntohl(hdr->pixmap_height), dec->fmt_in.video.i_sar_num, dec->fmt_in.video.i_sar_den); const size_t copy = dec->fmt_out.video.i_width * (dec->fmt_out.video.i_bits_per_pixel / 8); const uint32_t pitch = ntohl(hdr->bytes_per_line); /* Build picture */ if (pitch < copy || (block->i_buffer / pitch) < dec->fmt_out.video.i_height) goto drop; if (decoder_UpdateVideoFormat(dec)) goto drop; pic = decoder_NewPicture(dec); if (pic == NULL) goto drop; const uint8_t *in = block->p_buffer; uint8_t *out = pic->p->p_pixels; for (unsigned i = 0; i < dec->fmt_out.video.i_height; i++) { memcpy(out, in, copy); in += pitch; out += pic->p->i_pitch; } pic->date = block->i_pts; pic->b_progressive = true; drop: block_Release(block); return pic; }
/** * @brief Read header of y4m stream and make a compatible video_format_t * @return 1 if successful, <=0 on error */ static int readY4mHeader(const filter_t* intf, video_format_t* fmt, int fd) { char header[256] = { 0 }; if (0 >= readLine(header, sizeof(header)-1, fd)) { msg_Err(intf, "readY4mHeader: failed to read header: errno=%d %s", errno, strerror(errno)); return -1; } if (strncmp(header, "YUV4MPEG2", 9) != 0) { msg_Err(intf, "readY4mHeader: input is not a y4m stream"); return -2; } int width, height, fpsNum, fpsDen, sarNum, sarDen; width = height = fpsNum = sarNum = 0; fpsDen = sarDen = 1; char y4mChroma[32] = { 0 }; char* ptr = header; while (*ptr) { if (*ptr++ == ' ') { char field = *ptr++; switch (field) { case 'W': sscanf(ptr, "%d", &width); break; case 'H': sscanf(ptr, "%d", &height); break; case 'F': sscanf(ptr, "%d:%d", &fpsNum, &fpsDen); break; case 'A': sscanf(ptr, "%d:%d", &sarNum, &sarDen); break; case 'C': sscanf(ptr, "%31s", y4mChroma); break; case 'I': break; } } } vlc_fourcc_t chroma = 0; int i = 0; while (sChromaTable[i].name) { if (0 == strcmp(y4mChroma, sChromaTable[i].name)) { chroma = sChromaTable[i].fourcc; break; } i++; } if (chroma == 0) { msg_Err(intf, "readY4mHeader: unsupported Y4M chroma: %s", y4mChroma); return -3; } // vspipe is giving aspect 0:0, (maybe a bug), assume 1:1 // fixme: keep same as the input sar if (sarNum == 0 || sarDen == 0) { msg_Info(intf, "readY4mHeader: assume sar 1:1"); sarNum = 1; sarDen = 1; } msg_Info(intf, "readY4mHeader: %s", header); msg_Info(intf, "readY4mHeader: w=%d h=%d fps=%d:%d sar=%d:%d chroma=%s", width, height, fpsNum, fpsDen, sarNum, sarDen, y4mChroma); video_format_Setup(fmt, chroma, width, height, width, height, sarNum, sarDen); fmt->i_frame_rate = fpsNum; fmt->i_frame_rate_base = fpsDen; return 1; }
static int OpenEncoder( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys; ogg_packet header; int status; if( p_enc->fmt_out.i_codec != VLC_CODEC_DAALA && !p_enc->b_force ) { return VLC_EGENERIC; } /* Allocate the memory needed to store the encoder's structure */ p_sys = malloc( sizeof( encoder_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_enc->p_sys = p_sys; p_enc->pf_encode_video = Encode; p_enc->fmt_in.i_codec = VLC_CODEC_I420; p_enc->fmt_out.i_codec = VLC_CODEC_DAALA; config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg ); char *psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX "chroma-fmt" ); uint32_t i_codec; if( !psz_tmp ) { free(p_sys); return VLC_ENOMEM; } else { if( !strcmp( psz_tmp, "420" ) ) { i_codec = VLC_CODEC_I420; } else if( !strcmp( psz_tmp, "444" ) ) { i_codec = VLC_CODEC_I444; } else { msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp ); free( psz_tmp ); free( p_sys ); return VLC_EGENERIC; } free( psz_tmp ); p_enc->fmt_in.i_codec = i_codec; /* update bits_per_pixel */ video_format_Setup(&p_enc->fmt_in.video, i_codec, p_enc->fmt_in.video.i_width, p_enc->fmt_in.video.i_height, p_enc->fmt_in.video.i_visible_width, p_enc->fmt_in.video.i_visible_height, p_enc->fmt_in.video.i_sar_num, p_enc->fmt_in.video.i_sar_den); } daala_info_init( &p_sys->di ); p_sys->di.pic_width = p_enc->fmt_in.video.i_visible_width; p_sys->di.pic_height = p_enc->fmt_in.video.i_visible_height; p_sys->di.nplanes = 3; for (int i = 0; i < p_sys->di.nplanes; i++) { p_sys->di.plane_info[i].xdec = i > 0 && i_codec != VLC_CODEC_I444; p_sys->di.plane_info[i].ydec = i_codec == VLC_CODEC_I420 ? p_sys->di.plane_info[i].xdec : 0; } p_sys->di.frame_duration = 1; if( !p_enc->fmt_in.video.i_frame_rate || !p_enc->fmt_in.video.i_frame_rate_base ) { p_sys->di.timebase_numerator = 25; p_sys->di.timebase_denominator = 1; } else { p_sys->di.timebase_numerator = p_enc->fmt_in.video.i_frame_rate; p_sys->di.timebase_denominator = p_enc->fmt_in.video.i_frame_rate_base; } if( p_enc->fmt_in.video.i_sar_num > 0 && p_enc->fmt_in.video.i_sar_den > 0 ) { unsigned i_dst_num, i_dst_den; vlc_ureduce( &i_dst_num, &i_dst_den, p_enc->fmt_in.video.i_sar_num, p_enc->fmt_in.video.i_sar_den, 0 ); p_sys->di.pixel_aspect_numerator = i_dst_num; p_sys->di.pixel_aspect_denominator = i_dst_den; } else { p_sys->di.pixel_aspect_numerator = 4; p_sys->di.pixel_aspect_denominator = 3; } p_sys->di.keyframe_rate = var_GetInteger( p_enc, ENC_CFG_PREFIX "keyint" ); daala_enc_ctx *dcx; p_sys->dcx = dcx = daala_encode_create( &p_sys->di ); if( !dcx ) { free( p_sys ); return VLC_ENOMEM; } daala_comment_init( &p_sys->dc ); int i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" ); daala_encode_ctl( dcx, OD_SET_QUANT, &i_quality, sizeof(i_quality) ); /* Create and store headers */ while( ( status = daala_encode_flush_header( dcx, &p_sys->dc, &header ) ) ) { if ( status < 0 ) { CloseEncoder( p_this ); return VLC_EGENERIC; } if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra, &p_enc->fmt_out.p_extra, header.bytes, header.packet ) ) { p_enc->fmt_out.i_extra = 0; p_enc->fmt_out.p_extra = NULL; } } return VLC_SUCCESS; }
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; }
/***************************************************************************** * Command functions *****************************************************************************/ static int exec_DataSharedMem( filter_t *p_filter, const commandparams_t *p_params, commandparams_t *p_results ) { #if defined(HAVE_SYS_SHM_H) filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys; struct shmid_ds shminfo; overlay_t *p_ovl; size_t i_size; VLC_UNUSED(p_results); p_ovl = ListGet( &p_sys->overlays, p_params->i_id ); if( p_ovl == NULL ) { msg_Err( p_filter, "Invalid overlay: %d", p_params->i_id ); return VLC_EGENERIC; } if( shmctl( p_params->i_shmid, IPC_STAT, &shminfo ) == -1 ) { msg_Err( p_filter, "Unable to access shared memory" ); return VLC_EGENERIC; } i_size = shminfo.shm_segsz; if( p_params->fourcc == VLC_CODEC_TEXT ) { char *p_data; if( (p_params->i_height != 1) || (p_params->i_width < 1) ) { msg_Err( p_filter, "Invalid width and/or height. when specifying text height " "must be 1 and width the number of bytes in the string, " "including the null terminator" ); return VLC_EGENERIC; } if( (size_t)p_params->i_width > i_size ) { msg_Err( p_filter, "Insufficient data in shared memory. need %d, got %zu", p_params->i_width, i_size ); return VLC_EGENERIC; } p_ovl->data.p_text = malloc( p_params->i_width ); if( p_ovl->data.p_text == NULL ) { msg_Err( p_filter, "Unable to allocate string storage" ); return VLC_ENOMEM; } video_format_Setup( &p_ovl->format, VLC_CODEC_TEXT, 0, 0, 0, 1 ); p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY ); if( p_data == NULL ) { msg_Err( p_filter, "Unable to attach to shared memory" ); free( p_ovl->data.p_text ); p_ovl->data.p_text = NULL; return VLC_ENOMEM; } memcpy( p_ovl->data.p_text, p_data, p_params->i_width ); shmdt( p_data ); } else { uint8_t *p_data, *p_in; size_t i_neededsize = 0; p_ovl->data.p_pic = picture_New( p_params->fourcc, p_params->i_width, p_params->i_height, 1, 1 ); if( p_ovl->data.p_pic == NULL ) return VLC_ENOMEM; p_ovl->format = p_ovl->data.p_pic->format; for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes; ++i_plane ) { i_neededsize += p_ovl->data.p_pic->p[i_plane].i_visible_lines * p_ovl->data.p_pic->p[i_plane].i_visible_pitch; } if( i_neededsize > i_size ) { msg_Err( p_filter, "Insufficient data in shared memory. need %zu, got %zu", i_neededsize, i_size ); picture_Release( p_ovl->data.p_pic ); p_ovl->data.p_pic = NULL; return VLC_EGENERIC; } p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY ); if( p_data == NULL ) { msg_Err( p_filter, "Unable to attach to shared memory" ); picture_Release( p_ovl->data.p_pic ); p_ovl->data.p_pic = NULL; return VLC_ENOMEM; } p_in = p_data; for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes; ++i_plane ) { uint8_t *p_out = p_ovl->data.p_pic->p[i_plane].p_pixels; for( size_t i_line = 0; i_line < (size_t)p_ovl->data.p_pic->p[i_plane].i_visible_lines; ++i_line ) { memcpy( p_out, p_in, p_ovl->data.p_pic->p[i_plane].i_visible_pitch ); p_out += p_ovl->data.p_pic->p[i_plane].i_pitch; p_in += p_ovl->data.p_pic->p[i_plane].i_visible_pitch; } } shmdt( p_data ); } p_sys->b_updated = p_ovl->b_active; return VLC_SUCCESS; #else VLC_UNUSED(p_params); VLC_UNUSED(p_results); msg_Err( p_filter, "system doesn't support shared memory" ); return VLC_EGENERIC; #endif }
/** * 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; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; switch( p_dec->fmt_in.i_codec ) { /* Planar YUV */ case VLC_CODEC_I444: case VLC_CODEC_J444: case VLC_CODEC_I440: case VLC_CODEC_J440: case VLC_CODEC_I422: case VLC_CODEC_J422: case VLC_CODEC_I420: case VLC_CODEC_J420: case VLC_CODEC_YV12: case VLC_CODEC_YV9: case VLC_CODEC_I411: case VLC_CODEC_I410: case VLC_CODEC_GREY: case VLC_CODEC_YUVP: case VLC_CODEC_NV12: case VLC_CODEC_NV21: case VLC_CODEC_I422_10L: case VLC_CODEC_I422_10B: /* Packed YUV */ case VLC_CODEC_YUYV: case VLC_CODEC_YVYU: case VLC_CODEC_UYVY: case VLC_CODEC_VYUY: /* RGB */ case VLC_CODEC_RGB32: case VLC_CODEC_RGB24: case VLC_CODEC_RGB16: case VLC_CODEC_RGB15: case VLC_CODEC_RGB8: case VLC_CODEC_RGBP: case VLC_CODEC_RGBA: break; default: return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) return VLC_ENOMEM; /* Misc init */ p_dec->p_sys->b_packetizer = false; p_sys->b_invert = false; if( (int)p_dec->fmt_in.video.i_height < 0 ) { /* Frames are coded from bottom to top */ p_dec->fmt_in.video.i_height = (unsigned int)(-(int)p_dec->fmt_in.video.i_height); p_sys->b_invert = true; } if( !p_dec->fmt_in.video.i_visible_width ) p_dec->fmt_in.video.i_visible_width = p_dec->fmt_in.video.i_width; if( !p_dec->fmt_in.video.i_visible_height ) p_dec->fmt_in.video.i_visible_height = p_dec->fmt_in.video.i_height; if( p_dec->fmt_in.video.i_visible_width <= 0 || p_dec->fmt_in.video.i_visible_height <= 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base ); if( p_dec->fmt_out.video.i_frame_rate == 0 || p_dec->fmt_out.video.i_frame_rate_base == 0) { msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead", p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base); date_Init( &p_sys->pts, 25, 1 ); } /* Find out p_vdec->i_raw_size */ video_format_Setup( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, p_dec->fmt_in.video.i_visible_width, p_dec->fmt_in.video.i_visible_height, p_dec->fmt_in.video.i_sar_num, p_dec->fmt_in.video.i_sar_den ); picture_t picture; picture_Setup( &picture, p_dec->fmt_out.i_codec, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height, 0, 1 ); p_sys->i_raw_size = 0; for( int i = 0; i < picture.i_planes; i++ ) { p_sys->i_raw_size += picture.p[i].i_visible_pitch * picture.p[i].i_visible_lines; p_sys->planes[i] = picture.p[i]; } if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den ) { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } /* Set callbacks */ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; return VLC_SUCCESS; }
/** * 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; }