From: Jean-Paul Saman Date: Mon, 24 May 2004 20:12:27 +0000 (+0000) Subject: HD1000 video output X-Git-Tag: 0.8.0~1349 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=5f50f228482186d0a68b2f6583d6df5ffea8a6d9;p=vlc HD1000 video output --- diff --git a/AUTHORS b/AUTHORS index 1dc72e125d..1108a40f34 100644 --- a/AUTHORS +++ b/AUTHORS @@ -282,6 +282,7 @@ D: Familiar and PDA Linux interface D: Opie PDA Linux interface D: Dutch Translation D: DVB-S/C/T on v4l2 API +D: HD1000 port S: Netherlands N: Arnaud Schauly diff --git a/configure.ac b/configure.ac index d48f5b1185..8ddbb3a902 100644 --- a/configure.ac +++ b/configure.ac @@ -2677,6 +2677,31 @@ dnl LDFLAGS="${LDFLAGS_save}" dnl AX_ADD_CXXFLAGS([qt_video],[-I/usr/include/qt3 -I/usr/include/qt -I${QTDIR}/include]) dnl fi +dnl +dnl Roku HD1000 Video output module +dnl +AC_ARG_ENABLE(hd1000v, + [ --enable-hd1000v HD1000 Video Output module (default enabled on HD1 000)]) +if test "${enable_hd1000v}" != "no" && + (test "${SYS}" != "mingw32" || test "${enable_hd1000v}" = "yes") +then + AC_LANG_PUSH([C++]) + AC_CHECK_HEADERS([cascade/graphics/CascadeScreen.h cascade/graphics/CascadeBitmap.h], + [ + can_build_roku="yes" + ], + [ + can_build_roku="no" + AC_MSG_WARN([Not building Roku HD1000 compatible video output]) + ]) + if test "$can_build_roku" = "yes" + then + AX_ADD_PLUGINS([hd1000v]) + AX_ADD_LDFLAGS([hd1000v],[-lCascade]) + fi + AC_LANG_POP([C++]) +fi + dnl dnl Windows DirectX module dnl diff --git a/modules/LIST b/modules/LIST index b05c4a8bde..62629cbc4c 100644 --- a/modules/LIST +++ b/modules/LIST @@ -187,6 +187,8 @@ $Id$ * hd1000a: audio output module for the Roku HD1000 Set-Top-Box + * hd1000v: video output module for the Roku HD1000 Set-Top-Box + * headphone_channel_mixer: headphone channel mixer with virtual spatialization effect. @@ -338,10 +340,10 @@ $Id$ * qt: interface module using the Qt widget set. + * qt_video: video output module for Qt. + * qte: video output module for Qt Embedded. - * qte_main: QT Embedded wrapper for gte_main - * quicktime: Quicktime decoder that uses the QT library * rawdv: Raw DV demuxer diff --git a/modules/video_output/Modules.am b/modules/video_output/Modules.am index 3e3d203516..11e0166728 100644 --- a/modules/video_output/Modules.am +++ b/modules/video_output/Modules.am @@ -7,3 +7,4 @@ SOURCES_vout_sdl = sdl.c SOURCES_svgalib = svgalib.c SOURCES_wingdi = wingdi.c SOURCES_mga = mga.c +SOURCES_hd1000v = hd1000v.cpp diff --git a/modules/video_output/hd1000v.cpp b/modules/video_output/hd1000v.cpp new file mode 100644 index 0000000000..05a874f56e --- /dev/null +++ b/modules/video_output/hd1000v.cpp @@ -0,0 +1,326 @@ +/***************************************************************************** + * hd1000v.cpp: HD1000 video output display method + ***************************************************************************** + * Copyright (C) 2004 VideoLAN + * $Id: hd1000v.cpp 6961 2004-03-05 17:34:23Z jpsaman $ + * + * Authors: Jean-Paul Saman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +extern "C" { +#include /* ENOMEM */ +#include /* free() */ +#include /* strerror() */ + +#include +#include +#include +} + +#include +#include + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int Create ( vlc_object_t * ); +static void Destroy ( vlc_object_t * ); + +static int Init ( vout_thread_t * ); +static void End ( vout_thread_t * ); +static void Display ( vout_thread_t *, picture_t * ); + +static int NewPicture ( vout_thread_t *, picture_t * ); +static void FreePicture( vout_thread_t *, picture_t * ); + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +vlc_module_begin(); + set_description( _("HD1000 video output") ); + set_capability( "video output", 10 ); + add_shortcut( "hd1000v" ); + set_callbacks( Create, Destroy ); +vlc_module_end(); + +/***************************************************************************** + * vout_sys_t: video output method descriptor + ***************************************************************************** + * This structure is part of the video output thread descriptor. + * It describes the aa specific properties of an output thread. + *****************************************************************************/ +struct vout_sys_t +{ + uint32_t i_width; /* width of main window */ + uint32_t i_height; /* height of main window */ + uint32_t i_screen_depth; + vlc_bool_t b_double_buffered; + + uint32_t u_current; /* Current output resolution. */ + CascadeScreen *p_screen; +}; + +struct picture_sys_t +{ + CascadeSharedMemZone *p_image; +}; + +/***************************************************************************** + * Create: allocates video thread output method + ***************************************************************************** + * This function allocates and initializes a aa vout method. + *****************************************************************************/ +static int Create( vlc_object_t *p_this ) +{ + vout_thread_t *p_vout = (vout_thread_t *)p_this; + bool b_double_buffered = false; + + p_vout->p_sys = (struct vout_sys_t*) malloc( sizeof(struct vout_sys_t) ); + if( p_vout->p_sys == NULL ) + { + msg_Err( p_vout, "out of memory" ); + return VLC_EGENERIC; + } + + /* Allocate a screen for VLC vout. */ + p_vout->p_sys->p_screen = new CascadeScreen(); + if( p_vout->p_sys->p_screen == NULL ) + { + msg_Err( p_vout, "unable to allocate screen" ); + free( p_vout->p_sys ); + return VLC_EGENERIC; + } + + p_vout->pf_init = Init; + p_vout->pf_end = End; + p_vout->pf_manage = NULL; + p_vout->pf_render = NULL; + p_vout->pf_display = Display; + + /* Get current screen resolution */ + msg_Dbg( p_vout, "Number of screen resolutions supported %u", + p_vout->p_sys->p_screen->GetNumScreenResolutionsSupported() ); + + p_vout->p_sys->p_screen->GetCurrentOutputResolution( (u32) p_vout->p_sys->u_current ); + p_vout->p_sys->p_screen->GetSupportedScreenResolutionAt( (u32) p_vout->p_sys->u_current, + (u32) p_vout->p_sys->i_width, + (u32) p_vout->p_sys->i_height, + (u8) p_vout->p_sys->i_screen_depth, + b_double_buffered); + p_vout->p_sys->b_double_buffered = (vlc_bool_t) b_double_buffered; + msg_Dbg( p_vout, "index = %u, width = %u, height = %u, depth = %u, double buffered = %d", + p_vout->p_sys->u_current, + p_vout->p_sys->i_width, + p_vout->p_sys->i_height, + p_vout->p_sys->i_screen_depth, + p_vout->p_sys->b_double_buffered ); + + return VLC_SUCCESS; +} + +static void Destroy( vlc_object_t *p_this ) +{ + vout_thread_t *p_vout = (vout_thread_t *)p_this; + + delete p_vout->p_sys->p_screen; + free( p_vout->p_sys ); +} + +/***************************************************************************** + * Init: initialize video thread output method + *****************************************************************************/ +static int Init( vout_thread_t *p_vout ) +{ + int i_index; + picture_t *p_pic = NULL; + + I_OUTPUTPICTURES = 0; + + p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); + p_vout->output.i_width = p_vout->p_sys->i_width; + p_vout->output.i_height = p_vout->p_sys->i_height; + p_vout->output.i_aspect = p_vout->p_sys->i_width + * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height; + + /* Only RGBA 32bpp is supported by output device. */ + switch( p_vout->p_sys->i_screen_depth ) + { + case 8: /* FIXME: set the palette */ + p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); break; + case 15: + p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break; + case 16: + p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break; + case 24: + p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break; + case 32: + p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break; + default: + msg_Err( p_vout, "unknown screen depth %i", + p_vout->p_sys->i_screen_depth ); + return VLC_SUCCESS; + } + + /* Find an empty picture slot */ + for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) + { + if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) + { + p_pic = p_vout->p_picture + i_index; + break; + } + } + + if( p_pic == NULL || NewPicture( p_vout, p_pic ) ) + { + return -1; + } + + /* Allocate the picture */ + p_pic->p->i_lines = p_vout->p_sys->i_height; + p_pic->p->i_pitch = p_vout->p_sys->i_width; + p_pic->p->i_pixel_pitch = 1; + p_pic->p->i_visible_pitch = p_vout->p_sys->i_width; + p_pic->i_planes = 1; + + p_pic->i_status = DESTROYED_PICTURE; + p_pic->i_type = DIRECT_PICTURE; + + PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; + I_OUTPUTPICTURES++; + + return VLC_SUCCESS; +} + +/***************************************************************************** + * End: terminate video thread output method + *****************************************************************************/ +static void End( vout_thread_t *p_vout ) +{ + int i_index; + + /* Free the direct buffers we allocated */ + for( i_index = I_OUTPUTPICTURES ; i_index ; ) + { + i_index--; + FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] ); + } +} + +/***************************************************************************** + * NewPicture: Allocate shared memory zone for video output + *****************************************************************************/ +static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic ) +{ + CascadeDims p_dims = p_vout->p_sys->p_screen->GetDims(); + + p_pic->p_sys = (picture_sys_t *) malloc( sizeof( picture_sys_t ) ); + if( p_pic->p_sys == NULL ) + { + return -1; + } + + /* Fill in picture_t fields */ + vout_InitPicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma, + p_vout->output.i_width, p_vout->output.i_height, + p_vout->output.i_aspect ); + + p_pic->p_sys->p_image = new CascadeSharedMemZone(); + if( p_pic->p_sys->p_image == NULL ) + { + free( p_pic->p_sys ); + return -1; + } + + if( p_pic->p_sys->p_image->Open( "vlc_hd1000v", p_vout->output.i_width * + p_vout->output.i_height * p_vout->p_sys->i_screen_depth, + true ) ) + { + msg_Err( p_vout, "failed to allocate shared memory" ); + free( p_pic->p_sys ); + return -1; + } + + p_pic->p->i_lines = p_vout->output.i_height; + p_pic->p->p_pixels = (uint8_t*) p_pic->p_sys->p_image->MapLock(); + p_pic->p->i_pitch = p_vout->p_sys->i_screen_depth; + p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch + * p_vout->output.i_width; + + return VLC_SUCCESS; +} + +/***************************************************************************** + * FreePicture: destroy a picture allocated with NewPicture + ***************************************************************************** + * Destroy SharedMemZoned AND associated data. The picture normally will be + * unlocked in the Display() function except when the video output is closed + * before the picture is displayed. + *****************************************************************************/ +static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic ) +{ + if( p_pic->p_sys->p_image->Unlock() ) + { /* Just a test to see the effect described above. REMOVE THIS */ + msg_Err( p_vout, "unlocking shared memory failed, already unlocked" ); + } + + if( p_pic->p_sys->p_image->Close() ) + { + msg_Err( p_vout, "closing shared memory failed. Leaking memory of %ul", + p_pic->p_sys->p_image->GetSize() ); + } + + delete p_pic->p_sys->p_image; + free( p_pic->p_sys ); +} + +/***************************************************************************** + * Display: Map p_image onto the screen + *****************************************************************************/ +static void Display( vout_thread_t *p_vout, picture_t *p_pic ) +{ + uint32_t i_width, i_height, i_x, i_y; + uint32_t i_offset = 0; + + vout_PlacePicture( p_vout, p_vout->p_sys->i_width, + p_vout->p_sys->i_height, + &i_x, &i_y, &i_width, &i_height ); + msg_Dbg( p_vout, "PlacePicture at x_left = %d, y_left = %d, x_bottom = %d, y_bottom = %d", + i_x, i_y, i_width, i_height ); + + /* Currently the only pixel format supported is 32bpp RGBA.*/ + p_vout->p_sys->p_screen->LockScreen(); + + /* Unlock the shared memory region first. */ + if( p_pic->p_sys->p_image->Unlock() ) + { + msg_Err( p_vout, "unlocking shared memory failed. Expect threading problems." ); + } + + p_vout->p_sys->p_screen->Blit( CascadePoint( (u32) i_x, (u32) i_y ), /* Place bitmap at */ + (*p_pic->p_sys->p_image) , /* Image data */ + (u32) i_offset, /* Offset in SharedMemoryZone */ + (u32) i_width, /* Source bitmap width */ + (u32) i_height, /* Source bitmap height */ + (u32) p_vout->p_sys->i_screen_depth, /* Source pixel depth */ + CascadeRect( (u32) i_x, (u32) i_y, (u32) i_width, (u32) i_height ) ); + + p_vout->p_sys->p_screen->UnlockScreen(); +}