/***************************************************************************** * Close: *****************************************************************************/ static void Close( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; int i; for( i = 0; i < PS_TK_COUNT; i++ ) { ps_track_t *tk = &p_sys->tk[i]; if( tk->b_seen ) { es_format_Clean( &tk->fmt ); if( tk->es ) es_out_Del( p_demux->out, tk->es ); } } /* Free the array of titles */ for( int i = 0; i < p_sys->i_titles; i++ ) vlc_input_title_Delete( p_sys->titles[i] ); TAB_CLEAN( p_sys->i_titles, p_sys->titles ); /* Close libdvdread */ if( p_sys->p_title ) DVDCloseFile( p_sys->p_title ); if( p_sys->p_vts_file ) ifoClose( p_sys->p_vts_file ); if( p_sys->p_vmg_file ) ifoClose( p_sys->p_vmg_file ); DVDClose( p_sys->p_dvdread ); free( p_sys ); }
virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDDetectedVideoInputFormatFlags) { demux_sys_t *sys = demux_->p_sys; if( !(events & bmdVideoInputDisplayModeChanged )) return S_OK; const char *mode_name; if (mode->GetName(&mode_name) != S_OK) mode_name = "unknown"; msg_Dbg(demux_, "Video input format changed to %s", mode_name); if (!sys->autodetect) { msg_Err(demux_, "Video format detection disabled"); return S_OK; } es_out_Del(demux_->out, sys->video_es); es_format_t video_fmt = GetModeSettings(demux_, mode); sys->video_es = es_out_Add(demux_->out, &video_fmt); BMDPixelFormat fmt = sys->tenbits ? bmdFormat10BitYUV : bmdFormat8BitYUV; sys->input->PauseStreams(); sys->input->EnableVideoInput( mode->GetDisplayMode(), fmt, bmdVideoInputEnableFormatDetection ); sys->input->FlushStreams(); sys->input->StartStreams(); return S_OK; }
static void ts_pes_es_Clean( demux_t *p_demux, ts_pes_es_t *p_es ) { if( p_es && p_es->id ) { /* Ensure we don't wait for overlap hacks #14257 */ es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, p_es->id, false ); es_out_Del( p_demux->out, p_es->id ); p_demux->p_sys->i_pmt_es--; } es_format_Clean( &p_es->fmt ); }
/***************************************************************************** * Close: *****************************************************************************/ static void Close( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; vlc_cancel( p_sys->thread ); vlc_join( p_sys->thread, NULL ); if ( p_sys->es ) es_out_Del( p_demux->out, p_sys->es ); rfbClientCleanup( p_sys->p_client ); if ( p_sys->p_block ) block_Release( p_sys->p_block ); }
static void desktopResizeHandler( rdpContext *p_context ) { vlcrdp_context_t * p_vlccontext = (vlcrdp_context_t *) p_context; demux_sys_t *p_sys = p_vlccontext->p_demux->p_sys; rdpGdi *p_gdi = p_context->gdi; if ( p_sys->es ) { es_out_Del( p_vlccontext->p_demux->out, p_sys->es ); p_sys->es = NULL; } /* Now init and fill es format */ vlc_fourcc_t i_chroma; switch( p_gdi->bytesPerPixel ) { default: case 16: i_chroma = VLC_CODEC_RGB16; break; case 24: i_chroma = VLC_CODEC_RGB24; break; case 32: i_chroma = VLC_CODEC_RGB32; break; } es_format_t fmt; es_format_Init( &fmt, VIDEO_ES, i_chroma ); fmt.video.i_chroma = i_chroma; fmt.video.i_visible_width = fmt.video.i_width = p_gdi->width; fmt.video.i_visible_height = fmt.video.i_height = p_gdi->height; fmt.video.i_frame_rate_base = 1000; fmt.video.i_frame_rate = 1000 * p_sys->f_fps; p_sys->i_framebuffersize = p_gdi->width * p_gdi->height * p_gdi->bytesPerPixel; if ( p_sys->p_block ) p_sys->p_block = block_Realloc( p_sys->p_block, 0, p_sys->i_framebuffersize ); else p_sys->p_block = block_Alloc( p_sys->i_framebuffersize ); p_sys->es = es_out_Add( p_vlccontext->p_demux->out, &fmt ); }
static void output_mode_cb(void *data, struct wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { demux_t *demux = data; demux_sys_t *sys = demux->p_sys; msg_Dbg(demux, "output mode: 0x%08"PRIX32" %"PRId32"x%"PRId32 " %"PRId32"mHz%s", flags, width, height, refresh, (flags & WL_OUTPUT_MODE_CURRENT) ? " (current)" : ""); if (!(flags & WL_OUTPUT_MODE_CURRENT)) return; if (width <= sys->x || height <= sys->y) return; if (sys->es != NULL) es_out_Del(demux->out, sys->es); es_format_t fmt; es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_RGB32); fmt.video.i_chroma = VLC_CODEC_RGB32; fmt.video.i_bits_per_pixel = 32; fmt.video.i_sar_num = fmt.video.i_sar_den = 1; fmt.video.i_frame_rate = lroundf(1000.f * sys->rate); fmt.video.i_frame_rate_base = 1000; fmt.video.i_width = width; if (sys->w != 0 && width > sys->w + sys->x) fmt.video.i_visible_width = sys->w; else fmt.video.i_visible_width = width - sys->x; if (sys->h != 0 && height > sys->h + sys->y) fmt.video.i_visible_height = sys->h; else fmt.video.i_visible_height = height - sys->y; fmt.video.i_height = fmt.video.i_visible_height; sys->es = es_out_Add(demux->out, &fmt); sys->width = width; sys->height = height; (void) output; }
static void *DemuxThread( void *p_data ) { demux_t *p_demux = (demux_t *) p_data; demux_sys_t *p_sys = p_demux->p_sys; vlc_tick_t i_next_frame_date = vlc_tick_now() + p_sys->i_frame_interval; int i_status; for(;;) { p_sys->i_cancel_state = vlc_savecancel(); i_status = WaitForMessage( p_sys->p_client, p_sys->i_frame_interval ); vlc_restorecancel( p_sys->i_cancel_state ); /* Ensure we're not building frames too fast */ /* as WaitForMessage takes only a maximum wait */ vlc_tick_wait( i_next_frame_date ); i_next_frame_date += p_sys->i_frame_interval; if ( i_status > 0 ) { p_sys->p_client->frameBuffer = p_sys->p_block->p_buffer; p_sys->i_cancel_state = vlc_savecancel(); i_status = HandleRFBServerMessage( p_sys->p_client ); vlc_restorecancel( p_sys->i_cancel_state ); if ( ! i_status ) { msg_Warn( p_demux, "Cannot get announced data. Server closed ?" ); es_out_Del( p_demux->out, p_sys->es ); p_sys->es = NULL; return NULL; } else { block_t *p_block = block_Duplicate( p_sys->p_block ); if ( p_block ) /* drop frame/content if no next block */ { p_sys->p_block->i_dts = p_sys->p_block->i_pts = vlc_tick_now(); es_out_SetPCR( p_demux->out, p_sys->p_block->i_pts ); es_out_Send( p_demux->out, p_sys->es, p_sys->p_block ); p_sys->p_block = p_block; } } } } return NULL; }
void CloseDemux( demux_t* p_demux ) { demux_sys_t* p_sys = p_demux->p_sys; if( p_sys->p_rootnode ) tt_node_RecursiveDelete( p_sys->p_rootnode ); if( p_sys->p_es ) es_out_Del( p_demux->out, p_sys->p_es ); if( p_sys->p_reader ) xml_ReaderDelete( p_sys->p_reader ); if( p_sys->p_xml ) xml_Delete( p_sys->p_xml ); free( p_sys->times.p_array ); free( p_sys ); }
/***************************************************************************** * Close *****************************************************************************/ static void Close( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; int i; for( i = 0; i < PS_TK_COUNT; i++ ) { ps_track_t *tk = &p_sys->tk[i]; if( tk->b_configured ) { es_format_Clean( &tk->fmt ); if( tk->es ) es_out_Del( p_demux->out, tk->es ); } } ps_psm_destroy( &p_sys->psm ); free( p_sys ); }
/***************************************************************************** * Close: *****************************************************************************/ static void Close( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; vlc_cancel( p_sys->thread ); vlc_join( p_sys->thread, NULL ); if ( p_sys->es ) es_out_Del( p_demux->out, p_sys->es ); freerdp_disconnect( p_sys->p_instance ); freerdp_free( p_sys->p_instance ); #if FREERDP_VERSION_MAJOR == 1 && FREERDP_VERSION_MINOR < 2 freerdp_channels_global_uninit(); #endif if ( p_sys->p_block ) block_Release( p_sys->p_block ); free( p_sys->psz_hostname ); }
/***************************************************************************** * Close: *****************************************************************************/ static void Close( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; int i; for( i = 0; i < PS_TK_COUNT; i++ ) { ps_track_t *tk = &p_sys->tk[i]; if( tk->b_seen ) { es_format_Clean( &tk->fmt ); if( tk->es ) es_out_Del( p_demux->out, tk->es ); } } /* Close libdvdread */ if( p_sys->p_title ) DVDCloseFile( p_sys->p_title ); if( p_sys->p_vts_file ) ifoClose( p_sys->p_vts_file ); if( p_sys->p_vmg_file ) ifoClose( p_sys->p_vmg_file ); DVDClose( p_sys->p_dvdread ); free( p_sys ); }
static int Open (vlc_object_t *obj) { demux_t *demux = (demux_t *)obj; demux_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; /* Open the device */ const char *device = demux->psz_location; if (device == NULL || !device[0]) device = "default"; const int mode = SND_PCM_NONBLOCK /*| SND_PCM_NO_AUTO_RESAMPLE*/ | SND_PCM_NO_AUTO_CHANNELS /*| SND_PCM_NO_AUTO_FORMAT*/; snd_pcm_t *pcm; int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_CAPTURE, mode); if (val != 0) { msg_Err (demux, "cannot open ALSA device \"%s\": %s", device, snd_strerror (val)); return VLC_EGENERIC; } sys->pcm = pcm; msg_Dbg (demux, "using ALSA device: %s", device); DumpDevice (VLC_OBJECT(demux), pcm); /* Negotiate capture parameters */ snd_pcm_hw_params_t *hw; es_format_t fmt; unsigned param; int dir; snd_pcm_hw_params_alloca (&hw); snd_pcm_hw_params_any (pcm, hw); Dump (demux, "initial hardware setup:\n", snd_pcm_hw_params_dump, hw); val = snd_pcm_hw_params_set_rate_resample (pcm, hw, 0); if (val) { msg_Err (demux, "cannot disable resampling: %s", snd_strerror (val)); goto error; } val = snd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED); if (val) { msg_Err (demux, "cannot set access mode: %s", snd_strerror (val)); goto error; } snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN; for (size_t i = 0; i < sizeof (choices) / sizeof (choices[0]); i++) if (snd_pcm_hw_params_test_format (pcm, hw, choices[i]) == 0) { val = snd_pcm_hw_params_set_format (pcm, hw, choices[i]); if (val) { msg_Err (demux, "cannot set sample format: %s", snd_strerror (val)); goto error; } format = choices[i]; break; } if (format == SND_PCM_FORMAT_UNKNOWN) { msg_Err (demux, "no supported sample format"); goto error; } assert ((size_t)format < (sizeof (formats) / sizeof (formats[0]))); es_format_Init (&fmt, AUDIO_ES, formats[format]); fmt.audio.i_format = fmt.i_codec; param = 1 + var_InheritBool (demux, "alsa-stereo"); val = snd_pcm_hw_params_set_channels_max (pcm, hw, ¶m); if (val) { msg_Err (demux, "cannot restrict channels count: %s", snd_strerror (val)); goto error; } val = snd_pcm_hw_params_set_channels_last (pcm, hw, ¶m); if (val) { msg_Err (demux, "cannot set channels count: %s", snd_strerror (val)); goto error; } assert (param > 0); assert (param < (sizeof (channel_maps) / sizeof (channel_maps[0]))); fmt.audio.i_channels = param; fmt.audio.i_physical_channels = channel_maps[param - 1]; param = var_InheritInteger (demux, "alsa-samplerate"); val = snd_pcm_hw_params_set_rate_max (pcm, hw, ¶m, NULL); if (val) { msg_Err (demux, "cannot restrict rate to %u Hz or less: %s", 192000, snd_strerror (val)); goto error; } val = snd_pcm_hw_params_set_rate_last (pcm, hw, ¶m, &dir); if (val) { msg_Err (demux, "cannot set sample rate: %s", snd_strerror (val)); goto error; } if (dir) msg_Warn (demux, "sample rate is not integral"); fmt.audio.i_rate = param; sys->rate = param; sys->start = mdate (); sys->caching = INT64_C(1000) * var_InheritInteger (demux, "live-caching"); param = sys->caching; val = snd_pcm_hw_params_set_buffer_time_near (pcm, hw, ¶m, NULL); if (val) { msg_Err (demux, "cannot set buffer duration: %s", snd_strerror (val)); goto error; } param /= 4; val = snd_pcm_hw_params_set_period_time_near (pcm, hw, ¶m, NULL); if (val) { msg_Err (demux, "cannot set period: %s", snd_strerror (val)); goto error; } val = snd_pcm_hw_params_get_period_size (hw, &sys->period_size, &dir); if (val) { msg_Err (demux, "cannot get period size: %s", snd_strerror (val)); goto error; } if (dir > 0) sys->period_size++; /* Commit hardware parameters */ val = snd_pcm_hw_params (pcm, hw); if (val) { msg_Err (demux, "cannot commit hardware parameters: %s", snd_strerror (val)); goto error; } Dump (demux, "final HW setup:\n", snd_pcm_hw_params_dump, hw); /* Kick recording */ aout_FormatPrepare (&fmt.audio); sys->es = es_out_Add (demux->out, &fmt); demux->p_sys = sys; if (vlc_clone (&sys->thread, Thread, demux, VLC_THREAD_PRIORITY_INPUT)) { es_out_Del (demux->out, sys->es); goto error; } demux->pf_demux = NULL; demux->pf_control = Control; return VLC_SUCCESS; error: snd_pcm_close (pcm); return VLC_EGENERIC; }
/***************************************************************************** * Demux: *****************************************************************************/ static void *DemuxThread( void *p_data ) { demux_t *p_demux = (demux_t *) p_data; demux_sys_t *p_sys = p_demux->p_sys; p_sys->i_starttime = vlc_tick_now(); vlc_tick_t i_next_frame_date = vlc_tick_now() + p_sys->i_frame_interval; int i_ret; for(;;) { i_ret = 0; p_sys->i_cancel_state = vlc_savecancel(); if ( freerdp_shall_disconnect( p_sys->p_instance ) ) { vlc_restorecancel( p_sys->i_cancel_state ); msg_Warn( p_demux, "RDP server closed session" ); es_out_Del( p_demux->out, p_sys->es ); p_sys->es = NULL; return NULL; } struct { void* pp_rfds[RDP_MAX_FD]; /* Declared by rdp */ void* pp_wfds[RDP_MAX_FD]; int i_nbr; int i_nbw; struct pollfd ufds[RDP_MAX_FD]; } fds; fds.i_nbr = fds.i_nbw = 0; if ( freerdp_get_fds( p_sys->p_instance, fds.pp_rfds, &fds.i_nbr, fds.pp_wfds, &fds.i_nbw ) != true ) { vlc_restorecancel( p_sys->i_cancel_state ); msg_Err( p_demux, "cannot get FDS" ); } else if ( (fds.i_nbr + fds.i_nbw) > 0 && p_sys->es ) { vlc_restorecancel( p_sys->i_cancel_state ); int i_count = 0; for( int i = 0; i < fds.i_nbr; i++ ) { fds.ufds[ i_count ].fd = (long) fds.pp_rfds[ i ]; fds.ufds[ i_count ].events = POLLIN ; fds.ufds[ i_count++ ].revents = 0; } for( int i = 0; i < fds.i_nbw && i_count < RDP_MAX_FD; i++ ) { /* may be useless */ fds.ufds[ i_count ].fd = (long) fds.pp_wfds[ i ]; fds.ufds[ i_count ].events = POLLOUT; fds.ufds[ i_count++ ].revents = 0; } i_ret = poll( fds.ufds, i_count, p_sys->i_frame_interval * 1000/2 ); } else { vlc_restorecancel( p_sys->i_cancel_state ); } vlc_tick_wait( i_next_frame_date ); i_next_frame_date += p_sys->i_frame_interval; if ( i_ret >= 0 ) { /* Do the rendering */ p_sys->i_cancel_state = vlc_savecancel(); freerdp_check_fds( p_sys->p_instance ); vlc_restorecancel( p_sys->i_cancel_state ); block_t *p_block = block_Duplicate( p_sys->p_block ); if (likely( p_block && p_sys->p_block )) { p_sys->p_block->i_dts = p_sys->p_block->i_pts = vlc_tick_now() - p_sys->i_starttime; es_out_SetPCR( p_demux->out, p_sys->p_block->i_pts ); es_out_Send( p_demux->out, p_sys->es, p_sys->p_block ); p_sys->p_block = p_block; } } } return NULL; }
void codec_destroy (demux_t *demux, void *data) { if (data) es_out_Del (demux->out, (es_out_id_t *)data); }
/** * Processing callback */ static void Demux (void *opaque) { demux_t *demux = opaque; demux_sys_t *sys = demux->p_sys; xcb_connection_t *conn = sys->conn; /* Determine capture region */ xcb_get_geometry_cookie_t gc; xcb_query_pointer_cookie_t qc; gc = xcb_get_geometry (conn, sys->window); if (sys->follow_mouse) qc = xcb_query_pointer (conn, sys->window); xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL); if (geo == NULL) { msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window); discard: if (sys->follow_mouse) xcb_discard_reply (conn, gc.sequence); return; } int w = sys->w; int h = sys->h; int x, y; if (sys->follow_mouse) { xcb_query_pointer_reply_t *ptr = xcb_query_pointer_reply (conn, qc, NULL); if (ptr == NULL) { free (geo); return; } if (w == 0 || w > geo->width) w = geo->width; x = ptr->win_x; if (x < w / 2) x = 0; else if (x >= (int)geo->width - (w / 2)) x = geo->width - w; else x -= w / 2; if (h == 0 || h > geo->height) h = geo->height; y = ptr->win_y; if (y < h / 2) y = 0; else if (y >= (int)geo->height - (h / 2)) y = geo->height - h; else y -= h / 2; } else { int max; x = sys->x; max = (int)geo->width - x; if (max <= 0) goto discard; if (w == 0 || w > max) w = max; y = sys->y; max = (int)geo->height - y; if (max <= 0) goto discard; if (h == 0 || h > max) h = max; } /* Update elementary stream format (if needed) */ if (w != sys->cur_w || h != sys->cur_h) { if (sys->es != NULL) es_out_Del (demux->out, sys->es); /* Update composite pixmap */ if (sys->window != geo->root) { xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */ xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap); xcb_create_pixmap (conn, geo->depth, sys->pixmap, geo->root, geo->width, geo->height); } sys->es = InitES (demux, w, h, geo->depth, &sys->bpp); if (sys->es != NULL) { sys->cur_w = w; sys->cur_h = h; sys->bpp /= 8; /* bits -> bytes */ } } /* Capture screen */ xcb_drawable_t drawable = (sys->window != geo->root) ? sys->pixmap : sys->window; free (geo); block_t *block = NULL; #if HAVE_SYS_SHM_H if (sys->shm) { /* Capture screen through shared memory */ size_t size = w * h * sys->bpp; int id = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777); if (id == -1) /* XXX: fallback */ { msg_Err (demux, "shared memory allocation error: %m"); goto noshm; } /* Attach the segment to X and capture */ xcb_shm_get_image_reply_t *img; xcb_shm_get_image_cookie_t ck; xcb_shm_attach (conn, sys->segment, id, 0 /* read/write */); ck = xcb_shm_get_image (conn, drawable, x, y, w, h, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, sys->segment, 0); xcb_shm_detach (conn, sys->segment); img = xcb_shm_get_image_reply (conn, ck, NULL); xcb_flush (conn); /* ensure eventual detach */ if (img == NULL) { shmctl (id, IPC_RMID, 0); goto noshm; } free (img); /* Attach the segment to VLC */ void *shm = shmat (id, NULL, 0 /* read/write */); shmctl (id, IPC_RMID, 0); if (-1 == (intptr_t)shm) { msg_Err (demux, "shared memory attachment error: %m"); return; } block = block_shm_Alloc (shm, size); if (unlikely(block == NULL)) shmdt (shm); } noshm: #endif if (block == NULL) { /* Capture screen through socket (fallback) */ xcb_get_image_reply_t *img; img = xcb_get_image_reply (conn, xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable, x, y, w, h, ~0), NULL); if (img == NULL) return; uint8_t *data = xcb_get_image_data (img); size_t datalen = xcb_get_image_data_length (img); block = block_heap_Alloc (img, data + datalen - (uint8_t *)img); if (block == NULL) return; block->p_buffer = data; block->i_buffer = datalen; } /* Send block - zero copy */ if (sys->es != NULL) { block->i_pts = block->i_dts = mdate (); es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts); es_out_Send (demux->out, sys->es, block); } }
static rfbBool mallocFrameBufferHandler( rfbClient* p_client ) { vlc_fourcc_t i_chroma; demux_t *p_demux = (demux_t *) rfbClientGetClientData( p_client, DemuxThread ); demux_sys_t *p_sys = p_demux->p_sys; if ( p_sys->es ) /* Source has changed resolution */ { es_out_Del( p_demux->out, p_sys->es ); p_sys->es = NULL; } int i_width = p_client->width; int i_height = p_client->height; int i_depth = p_client->format.bitsPerPixel; switch( i_depth ) { case 8: i_chroma = VLC_CODEC_RGB8; break; default: case 16: i_chroma = VLC_CODEC_RGB16; break; case 24: i_chroma = VLC_CODEC_RGB24; break; case 32: i_chroma = VLC_CODEC_RGB32; break; } switch( i_chroma ) { case VLC_CODEC_RGB16: p_client->format.redShift = 11; p_client->format.greenShift = 5; p_client->format.blueShift = 0; p_client->format.redMax = 0x1f; p_client->format.greenMax = 0x3f; p_client->format.blueMax = 0x1f; break; case VLC_CODEC_RGB24: case VLC_CODEC_RGB32: p_client->format.redShift = 16; p_client->format.greenShift = 8; p_client->format.blueShift = 0; p_client->format.redMax = 0xff; p_client->format.greenMax = 0xff; p_client->format.blueMax = 0xff; break; } /* Set up framebuffer */ p_sys->i_framebuffersize = i_width * i_height * i_depth / 8; /* Reuse unsent block */ if ( p_sys->p_block ) p_sys->p_block = block_Realloc( p_sys->p_block, 0, p_sys->i_framebuffersize ); else p_sys->p_block = block_Alloc( p_sys->i_framebuffersize ); if ( p_sys->p_block ) p_sys->p_block->i_buffer = p_sys->i_framebuffersize; else return FALSE; /* Push our VNC config */ SetFormatAndEncodings( p_client ); /* Now init and fill es format */ es_format_t fmt; es_format_Init( &fmt, VIDEO_ES, i_chroma ); /* Fill input format */ fmt.video.i_chroma = i_chroma; fmt.video.i_visible_width = fmt.video.i_width = i_width; fmt.video.i_visible_height = fmt.video.i_height = i_height; fmt.video.i_frame_rate_base = 1000; fmt.video.i_frame_rate = 1000 * p_sys->f_fps; fmt.video.i_bits_per_pixel = i_depth; fmt.video.i_rmask = p_client->format.redMax << p_client->format.redShift; fmt.video.i_gmask = p_client->format.greenMax << p_client->format.greenShift; fmt.video.i_bmask = p_client->format.blueMax << p_client->format.blueShift; fmt.video.i_sar_num = fmt.video.i_sar_den = 1; /* declare the new es */ p_sys->es = es_out_Add( p_demux->out, &fmt ); return TRUE; }
/** * Processing callback */ static void Demux (void *data) { demux_t *demux = data; demux_sys_t *sys = demux->p_sys; xcb_connection_t *conn = sys->conn; /* Determine capture region */ xcb_get_geometry_cookie_t gc; xcb_query_pointer_cookie_t qc; gc = xcb_get_geometry (conn, sys->window); if (sys->follow_mouse) qc = xcb_query_pointer (conn, sys->window); xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL); if (geo == NULL) { msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window); discard: if (sys->follow_mouse) xcb_discard_reply (conn, gc.sequence); return; } int w = sys->w; int h = sys->h; int x, y; if (sys->follow_mouse) { xcb_query_pointer_reply_t *ptr = xcb_query_pointer_reply (conn, qc, NULL); if (ptr == NULL) { free (geo); return; } if (w == 0 || w > geo->width) w = geo->width; x = ptr->win_x; if (x < w / 2) x = 0; else if (x >= (int)geo->width - (w / 2)) x = geo->width - w; else x -= w / 2; if (h == 0 || h > geo->height) h = geo->height; y = ptr->win_y; if (y < h / 2) y = 0; else if (y >= (int)geo->height - (h / 2)) y = geo->height - h; else y -= h / 2; } else { int max; x = sys->x; max = (int)geo->width - x; if (max <= 0) goto discard; if (w == 0 || w > max) w = max; y = sys->y; max = (int)geo->height - y; if (max <= 0) goto discard; if (h == 0 || h > max) h = max; } /* Update elementary stream format (if needed) */ if (w != sys->cur_w || h != sys->cur_h) { if (sys->es != NULL) es_out_Del (demux->out, sys->es); /* Update composite pixmap */ if (sys->window != geo->root) { xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */ xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap); xcb_create_pixmap (conn, geo->depth, sys->pixmap, geo->root, geo->width, geo->height); } sys->es = InitES (demux, w, h, geo->depth); if (sys->es != NULL) { sys->cur_w = w; sys->cur_h = h; } } /* Capture screen */ xcb_drawable_t drawable = (sys->window != geo->root) ? sys->pixmap : sys->window; free (geo); xcb_get_image_reply_t *img; img = xcb_get_image_reply (conn, xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable, x, y, w, h, ~0), NULL); if (img == NULL) return; block_t *block = block_heap_Alloc (img, xcb_get_image_data (img), xcb_get_image_data_length (img)); if (block == NULL) return; /* Send block - zero copy */ if (sys->es != NULL) { if (sys->pts == VLC_TS_INVALID) sys->pts = mdate (); block->i_pts = block->i_dts = sys->pts; es_out_Control (demux->out, ES_OUT_SET_PCR, sys->pts); es_out_Send (demux->out, sys->es, block); sys->pts += sys->interval; } }
/** * Processing callback */ static void Demux (void *data) { demux_t *demux = data; demux_sys_t *p_sys = demux->p_sys; xcb_connection_t *conn = p_sys->conn; /* Update capture region (if needed) */ xcb_get_geometry_cookie_t gc = xcb_get_geometry (conn, p_sys->window); int16_t x = p_sys->x, y = p_sys->y; xcb_translate_coordinates_cookie_t tc; if (p_sys->window != p_sys->root) tc = xcb_translate_coordinates (conn, p_sys->window, p_sys->root, x, y); xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL); if (geo == NULL) { msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, p_sys->window); return; } uint16_t w = geo->width - x; uint16_t h = geo->height - y; free (geo); if (p_sys->w > 0 && p_sys->w < w) w = p_sys->w; if (p_sys->h > 0 && p_sys->h < h) h = p_sys->h; if (p_sys->window != p_sys->root) { xcb_translate_coordinates_reply_t *coords = xcb_translate_coordinates_reply (conn, tc, NULL); if (coords == NULL) return; x = coords->dst_x; y = coords->dst_y; free (coords); } xcb_get_image_reply_t *img; img = xcb_get_image_reply (conn, xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, p_sys->root, x, y, w, h, ~0), NULL); if (img == NULL) return; /* Send block - zero copy */ block_t *block = block_heap_Alloc (img, xcb_get_image_data (img), xcb_get_image_data_length (img)); if (block == NULL) return; vlc_mutex_lock (&p_sys->lock); if (w != p_sys->fmt.video.i_visible_width || h != p_sys->fmt.video.i_visible_height) { if (p_sys->es != NULL) es_out_Del (demux->out, p_sys->es); p_sys->fmt.video.i_visible_width = p_sys->fmt.video.i_width = w; p_sys->fmt.video.i_visible_height = p_sys->fmt.video.i_height = h; p_sys->es = es_out_Add (demux->out, &p_sys->fmt); } /* Capture screen */ if (p_sys->es != NULL) { if (p_sys->pts == VLC_TS_INVALID) p_sys->pts = mdate (); block->i_pts = block->i_dts = p_sys->pts; es_out_Control (demux->out, ES_OUT_SET_PCR, p_sys->pts); es_out_Send (demux->out, p_sys->es, block); p_sys->pts += p_sys->interval; } vlc_mutex_unlock (&p_sys->lock); }