mirror of
https://github.com/videolan/vlc.git
synced 2024-12-11 10:44:38 +08:00
* QNX RTOS plug-in by Jon Lech Johansen.
This commit is contained in:
parent
9727b87f36
commit
61cd2b0a26
1
AUTHORS
1
AUTHORS
@ -127,6 +127,7 @@ N: Jon Lech Johansen
|
||||
E: jon-vl@nanocrew.net
|
||||
D: PS input fixes
|
||||
D: Win32 DVD input port
|
||||
D: QNX RTOS plug-in
|
||||
|
||||
N: Michel Kaempf
|
||||
E: maxx@via.ecp.fr
|
||||
|
@ -63,6 +63,7 @@ HEAD
|
||||
* Kludged so that times displayed in the scrollbar are finally correct
|
||||
for MPEG-2 streams.
|
||||
* FreeBSD compilation fix by Øyvind Kolbu.
|
||||
* QNX RTOS plug-in by Jon Lech Johansen.
|
||||
|
||||
0.2.80
|
||||
Tue, 5 Jun 2001 04:41:06 +0200
|
||||
|
@ -74,6 +74,7 @@ LIB_GTK = @LIB_GTK@
|
||||
LIB_IDCTALTIVEC = @LIB_IDCTALTIVEC@
|
||||
LIB_KDE = @LIB_KDE@
|
||||
LIB_MACOSX = @LIB_MACOSX@
|
||||
LIB_QNX = @LIB_QNX@
|
||||
LIB_NCURSES = @LIB_NCURSES@
|
||||
LIB_QT = @LIB_QT@
|
||||
LIB_TS = @LIB_TS@
|
||||
|
13
configure.in
13
configure.in
@ -412,6 +412,18 @@ AC_ARG_ENABLE(macosx,
|
||||
LIB_SDL="${LIB_SDL} -framework AGL -framework Carbon"
|
||||
)])
|
||||
|
||||
dnl
|
||||
dnl QNX RTOS module
|
||||
dnl
|
||||
AC_ARG_ENABLE(qnx,
|
||||
[ --disable-qnx QNX RTOS support (default enabled)])
|
||||
if test x$enable_qnx != xno; then
|
||||
AC_CHECK_HEADERS(Ph.h, [
|
||||
PLUGINS="${PLUGINS} qnx"
|
||||
LIB_QNX="-lasound -lph"
|
||||
])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Linux framebuffer module
|
||||
dnl
|
||||
@ -656,6 +668,7 @@ AC_SUBST(LIB_GTK)
|
||||
AC_SUBST(LIB_IDCTALTIVEC)
|
||||
AC_SUBST(LIB_KDE)
|
||||
AC_SUBST(LIB_MACOSX)
|
||||
AC_SUBST(LIB_QNX)
|
||||
AC_SUBST(LIB_NCURSES)
|
||||
AC_SUBST(LIB_QT)
|
||||
AC_SUBST(LIB_TS)
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ioctl.c: DVD ioctl replacement function
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: ioctl.c,v 1.3 2001/06/25 11:34:08 sam Exp $
|
||||
* $Id: ioctl.c,v 1.4 2001/07/19 11:50:50 massiot Exp $
|
||||
*
|
||||
* Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
@ -168,6 +168,16 @@ int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
|
||||
*pi_copyright = p_buffer[ 4 ];
|
||||
}
|
||||
|
||||
#elif defined( __QNXNTO__ )
|
||||
/*
|
||||
QNX RTOS currently doesn't have a CAM
|
||||
interface (they're working on it though).
|
||||
Assume DVD is not encrypted.
|
||||
*/
|
||||
|
||||
*pi_copyright = 0;
|
||||
i_ret = 0;
|
||||
|
||||
#else
|
||||
/* DVD ioctls unavailable - do as if the ioctl failed */
|
||||
i_ret = -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* include/defs.h.in. Generated automatically from configure.in by autoheader 2.13. */
|
||||
/* include/defs.h.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
#undef const
|
||||
@ -61,6 +61,9 @@
|
||||
/* Define if you have the <Carbon/Carbon.h> header file. */
|
||||
#undef HAVE_CARBON_CARBON_H
|
||||
|
||||
/* Define if you have the <Ph.h> header file. */
|
||||
#undef HAVE_PH_H
|
||||
|
||||
/* Define if you have the <SDL/SDL.h> header file. */
|
||||
#undef HAVE_SDL_SDL_H
|
||||
|
||||
|
29
plugins/qnx/Makefile
Normal file
29
plugins/qnx/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
###############################################################################
|
||||
# vlc (VideoLAN Client) QNX RTOS module Makefile
|
||||
# (c)2001 VideoLAN
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# Objects
|
||||
#
|
||||
|
||||
PLUGIN_C = qnx.o aout_qnx.o vout_qnx.o
|
||||
BUILTIN_C = $(PLUGIN_C:%.o=BUILTIN_%.o)
|
||||
|
||||
ALL_OBJ = $(PLUGIN_C) $(BUILTIN_C)
|
||||
|
||||
#
|
||||
# Virtual targets
|
||||
#
|
||||
|
||||
include ../../Makefile.modules
|
||||
|
||||
#
|
||||
# Real targets
|
||||
#
|
||||
|
||||
../../plugins/qnx.so: $(PLUGIN_C)
|
||||
$(CC) $(PCFLAGS) -o $@ $^ $(PLCFLAGS) $(LIB_QNX)
|
||||
|
||||
../../plugins/qnx.a: $(BUILTIN_C)
|
||||
ar r $@ $^
|
367
plugins/qnx/aout_qnx.c
Normal file
367
plugins/qnx/aout_qnx.c
Normal file
@ -0,0 +1,367 @@
|
||||
/*****************************************************************************
|
||||
* aout_qnx.c : Alsa functions library
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000 VideoLAN
|
||||
*
|
||||
* Authors: Henri Fallon <henri@videolan.org>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#define MODULE_NAME qnx
|
||||
#include "modules_inner.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <string.h> /* strerror() */
|
||||
#include <stdio.h> /* "intf_msg.h" */
|
||||
#include <stdlib.h> /* calloc(), malloc(), free() */
|
||||
|
||||
#include <sys/asoundlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h" /* boolean_t, byte_t */
|
||||
#include "threads.h"
|
||||
#include "mtime.h"
|
||||
#include "tests.h"
|
||||
|
||||
#include "audio_output.h" /* aout_thread_t */
|
||||
|
||||
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
|
||||
#include "main.h"
|
||||
|
||||
#include "modules.h"
|
||||
#include "modules_export.h"
|
||||
|
||||
typedef struct alsa_device_s
|
||||
{
|
||||
int i_num;
|
||||
} alsa_device_t;
|
||||
|
||||
typedef struct alsa_card_s
|
||||
{
|
||||
int i_num;
|
||||
} alsa_card_t;
|
||||
|
||||
/* here we store plugin dependant informations */
|
||||
|
||||
typedef struct aout_sys_s
|
||||
{
|
||||
snd_pcm_t * p_alsa_handle;
|
||||
alsa_device_t s_alsa_device;
|
||||
alsa_card_t s_alsa_card;
|
||||
snd_pcm_channel_params_t s_alsa_channel_params;
|
||||
snd_pcm_format_t s_alsa_format;
|
||||
} aout_sys_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int aout_Probe ( probedata_t *p_data );
|
||||
static int aout_Open ( aout_thread_t *p_aout );
|
||||
static int aout_SetFormat ( aout_thread_t *p_aout );
|
||||
static long aout_GetBufInfo ( aout_thread_t *p_aout, long l_buffer_info );
|
||||
static void aout_Play ( aout_thread_t *p_aout,
|
||||
byte_t *buffer, int i_size );
|
||||
static void aout_Close ( aout_thread_t *p_aout );
|
||||
|
||||
/*****************************************************************************
|
||||
* Functions exported as capabilities. They are declared as static so that
|
||||
* we don't pollute the namespace too much.
|
||||
*****************************************************************************/
|
||||
void _M( aout_getfunctions )( function_list_t * p_function_list )
|
||||
{
|
||||
p_function_list->pf_probe = aout_Probe;
|
||||
p_function_list->functions.aout.pf_open = aout_Open;
|
||||
p_function_list->functions.aout.pf_setformat = aout_SetFormat;
|
||||
p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
|
||||
p_function_list->functions.aout.pf_play = aout_Play;
|
||||
p_function_list->functions.aout.pf_close = aout_Close;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_Probe: probes the audio device and return a score
|
||||
*****************************************************************************
|
||||
* This function tries to open the dps and returns a score to the plugin
|
||||
* manager so that it can make its choice.
|
||||
*****************************************************************************/
|
||||
static int aout_Probe( probedata_t *p_data )
|
||||
{
|
||||
int i_open_return, i_close_return;
|
||||
aout_sys_t local_sys;
|
||||
/* This is the same as the beginning of the aout_Open */
|
||||
|
||||
/* Initialize */
|
||||
local_sys.s_alsa_device.i_num = 0;
|
||||
local_sys.s_alsa_card.i_num = 0;
|
||||
|
||||
/* Open device */
|
||||
i_open_return = snd_pcm_open( &(local_sys.p_alsa_handle),
|
||||
local_sys.s_alsa_card.i_num,
|
||||
local_sys.s_alsa_device.i_num,
|
||||
SND_PCM_OPEN_PLAYBACK );
|
||||
if( i_open_return )
|
||||
{
|
||||
intf_WarnMsg( 2, "aout info: could not probe ALSA device (%s)",
|
||||
snd_strerror( i_open_return ) );
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
/* Close it */
|
||||
i_close_return = snd_pcm_close( local_sys.p_alsa_handle );
|
||||
|
||||
if( i_close_return )
|
||||
{
|
||||
intf_ErrMsg( "aout error: could not close ALSA device (%s)",
|
||||
snd_strerror( i_close_return ) );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( TestMethod( AOUT_METHOD_VAR, "qnx" ) )
|
||||
{
|
||||
return( 999 );
|
||||
}
|
||||
|
||||
/* And return score */
|
||||
return( 50 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_Open : creates a handle and opens an alsa device
|
||||
*****************************************************************************
|
||||
* This function opens an alsa device, through the alsa API
|
||||
*****************************************************************************/
|
||||
static int aout_Open( aout_thread_t *p_aout )
|
||||
{
|
||||
int i_open_returns;
|
||||
|
||||
/* Allocate structures */
|
||||
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
|
||||
if( p_aout->p_sys == NULL )
|
||||
{
|
||||
intf_ErrMsg( "aout error: failed allocating memory for ALSA (%s)",
|
||||
strerror(ENOMEM) );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* Initialize */
|
||||
p_aout->p_sys->s_alsa_device.i_num = 0;
|
||||
p_aout->p_sys->s_alsa_card.i_num = 0;
|
||||
/* FIXME : why not other format ? */
|
||||
p_aout->i_format = AOUT_FMT_S16_LE;
|
||||
/* FIXME : why always 2 channels ?*/
|
||||
p_aout->i_channels = 2;
|
||||
p_aout->l_rate = main_GetIntVariable( AOUT_RATE_VAR, AOUT_RATE_DEFAULT );
|
||||
|
||||
/* Open device */
|
||||
if( ( i_open_returns = snd_pcm_open( &(p_aout->p_sys->p_alsa_handle),
|
||||
p_aout->p_sys->s_alsa_card.i_num,
|
||||
p_aout->p_sys->s_alsa_device.i_num,
|
||||
SND_PCM_OPEN_PLAYBACK ) ) )
|
||||
{
|
||||
intf_ErrMsg( "aout error: could not open ALSA device (%s)",
|
||||
snd_strerror(i_open_returns) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
intf_DbgMsg( "aout info: ALSA device successfully opened" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_SetFormat : sets the alsa output format
|
||||
*****************************************************************************
|
||||
* This function prepares the device, sets the rate, format, the mode
|
||||
* ("play as soon as you have data"), and buffer information.
|
||||
*****************************************************************************/
|
||||
static int aout_SetFormat( aout_thread_t *p_aout )
|
||||
{
|
||||
|
||||
int i_set_param_returns;
|
||||
int i_prepare_playback_returns;
|
||||
int i_playback_go_returns;
|
||||
|
||||
/* Fill with zeros */
|
||||
memset( &p_aout->p_sys->s_alsa_channel_params, 0,
|
||||
sizeof( p_aout->p_sys->s_alsa_channel_params ) );
|
||||
|
||||
/* Fill the s_alsa_channel_params structure */
|
||||
|
||||
/* Tranfer mode and direction*/
|
||||
p_aout->p_sys->s_alsa_channel_params.channel = SND_PCM_CHANNEL_PLAYBACK ;
|
||||
p_aout->p_sys->s_alsa_channel_params.mode = SND_PCM_MODE_STREAM;
|
||||
|
||||
/* Format and rate */
|
||||
p_aout->p_sys->s_alsa_channel_params.format.interleave = 1;
|
||||
if( p_aout->i_format == AOUT_FMT_S16_LE )
|
||||
{
|
||||
p_aout->p_sys->s_alsa_channel_params.format.format =
|
||||
SND_PCM_SFMT_S16_LE;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_aout->p_sys->s_alsa_channel_params.format.format =
|
||||
SND_PCM_SFMT_S16_BE;
|
||||
}
|
||||
p_aout->p_sys->s_alsa_channel_params.format.rate = p_aout->l_rate;
|
||||
p_aout->p_sys->s_alsa_channel_params.format.voices = p_aout->i_channels ;
|
||||
|
||||
/* When to start playing and when to stop */
|
||||
p_aout->p_sys->s_alsa_channel_params.start_mode = SND_PCM_START_DATA;
|
||||
p_aout->p_sys->s_alsa_channel_params.stop_mode = SND_PCM_STOP_STOP;
|
||||
|
||||
/* Buffer information . I have chosen the stream mode here
|
||||
* instead of the block mode. I don't know whether i'm wrong
|
||||
* but it seemed more logical */
|
||||
/* TODO : find the best value to put here. Probably depending
|
||||
* on many parameters */
|
||||
p_aout->p_sys->s_alsa_channel_params.buf.stream.queue_size = 131072;
|
||||
|
||||
p_aout->p_sys->s_alsa_channel_params.buf.stream.fill = SND_PCM_FILL_NONE ;
|
||||
p_aout->p_sys->s_alsa_channel_params.buf.stream.max_fill = 0 ;
|
||||
|
||||
/* Now we pass this to the driver */
|
||||
i_set_param_returns = snd_pcm_channel_params(
|
||||
p_aout->p_sys->p_alsa_handle,
|
||||
&(p_aout->p_sys->s_alsa_channel_params) );
|
||||
|
||||
if( i_set_param_returns )
|
||||
{
|
||||
intf_ErrMsg( "aout error: unable to set parameters (%s)",
|
||||
snd_strerror( i_set_param_returns ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* we shall now prepare the channel */
|
||||
i_prepare_playback_returns =
|
||||
snd_pcm_playback_prepare( p_aout->p_sys->p_alsa_handle );
|
||||
|
||||
if( i_prepare_playback_returns )
|
||||
{
|
||||
intf_ErrMsg( "aout error: unable to prepare channel (%s)",
|
||||
snd_strerror( i_set_param_returns ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* then we may go */
|
||||
i_playback_go_returns =
|
||||
snd_pcm_playback_go( p_aout->p_sys->p_alsa_handle );
|
||||
if( i_playback_go_returns )
|
||||
{
|
||||
intf_ErrMsg( "aout error: unable to prepare channel (bis) (%s)",
|
||||
snd_strerror( i_set_param_returns ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
p_aout->i_latency = 0;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_BufInfo: buffer status query
|
||||
*****************************************************************************
|
||||
* This function returns the number of used byte in the queue.
|
||||
* It also deals with errors : indeed if the device comes to run out
|
||||
* of data to play, it switches to the "underrun" status. It has to
|
||||
* be flushed and re-prepared
|
||||
*****************************************************************************/
|
||||
static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
|
||||
{
|
||||
snd_pcm_channel_status_t alsa_channel_status;
|
||||
int i_alsa_get_status_returns;
|
||||
|
||||
memset( &alsa_channel_status, 0, sizeof( alsa_channel_status ) );
|
||||
|
||||
i_alsa_get_status_returns = snd_pcm_channel_status(
|
||||
p_aout->p_sys->p_alsa_handle, &alsa_channel_status );
|
||||
|
||||
if( i_alsa_get_status_returns )
|
||||
{
|
||||
intf_ErrMsg( "aout error: failed getting alsa buffer info (%s)",
|
||||
snd_strerror ( i_alsa_get_status_returns ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
switch( alsa_channel_status.status )
|
||||
{
|
||||
case SND_PCM_STATUS_NOTREADY:
|
||||
{
|
||||
intf_ErrMsg( "aout error: status NOT READY" );
|
||||
break;
|
||||
}
|
||||
|
||||
case SND_PCM_STATUS_UNDERRUN:
|
||||
{
|
||||
int i_prepare_returns;
|
||||
intf_ErrMsg( "aout error: status UNDERRUN ... resetting queue ");
|
||||
i_prepare_returns = snd_pcm_playback_prepare(
|
||||
p_aout->p_sys->p_alsa_handle );
|
||||
if ( i_prepare_returns )
|
||||
{
|
||||
intf_ErrMsg( "aout error: could not flush (%s)",
|
||||
snd_strerror(i_prepare_returns) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return( alsa_channel_status.count );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_Play : plays a sample
|
||||
*****************************************************************************
|
||||
* Plays a sample using the snd_pcm_write function from the alsa API
|
||||
*****************************************************************************/
|
||||
static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
|
||||
{
|
||||
int i_write_returns;
|
||||
|
||||
i_write_returns = (int) snd_pcm_write (
|
||||
p_aout->p_sys->p_alsa_handle, (void *) buffer, (size_t) i_size );
|
||||
|
||||
if( i_write_returns <= 0 )
|
||||
{
|
||||
intf_ErrMsg( "aout error: writing blocks failed (%s)",
|
||||
snd_strerror( i_write_returns ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* aout_Close : close the Alsa device
|
||||
*****************************************************************************/
|
||||
static void aout_Close( aout_thread_t *p_aout )
|
||||
{
|
||||
int i_close_returns;
|
||||
|
||||
i_close_returns = snd_pcm_close( p_aout->p_sys->p_alsa_handle );
|
||||
|
||||
if( i_close_returns )
|
||||
{
|
||||
intf_ErrMsg( "aout error: failed closing ALSA device (%s)",
|
||||
snd_strerror( i_close_returns ) );
|
||||
}
|
||||
free( p_aout->p_sys );
|
||||
|
||||
intf_DbgMsg( "aout: ALSA device closed" );
|
||||
}
|
||||
|
71
plugins/qnx/qnx.c
Normal file
71
plugins/qnx/qnx.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*****************************************************************************
|
||||
* qnx.c : QNX RTOS plugin for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2000, 2001 VideoLAN
|
||||
*
|
||||
* Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#define MODULE_NAME qnx
|
||||
#include "modules_inner.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include "defs.h"
|
||||
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h" /* boolean_t, byte_t */
|
||||
#include "threads.h"
|
||||
#include "mtime.h"
|
||||
|
||||
#include "video.h"
|
||||
#include "video_output.h"
|
||||
|
||||
#include "modules.h"
|
||||
#include "modules_export.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Capabilities defined in the other files.
|
||||
******************************************************************************/
|
||||
void _M( aout_getfunctions )( function_list_t * p_function_list );
|
||||
void _M( vout_getfunctions )( function_list_t * p_function_list );
|
||||
|
||||
/*****************************************************************************
|
||||
* Building configuration tree
|
||||
*****************************************************************************/
|
||||
MODULE_CONFIG_START
|
||||
ADD_WINDOW( "Configuration for QNX RTOS module" )
|
||||
ADD_COMMENT( "For now, the QNX RTOS module cannot be configured" )
|
||||
MODULE_CONFIG_STOP
|
||||
|
||||
MODULE_INIT_START
|
||||
p_module->psz_longname = "QNX RTOS module";
|
||||
p_module->i_capabilities = MODULE_CAPABILITY_NULL
|
||||
| MODULE_CAPABILITY_AOUT
|
||||
| MODULE_CAPABILITY_VOUT;
|
||||
MODULE_INIT_STOP
|
||||
|
||||
MODULE_ACTIVATE_START
|
||||
_M( aout_getfunctions )( &p_module->p_functions->aout );
|
||||
_M( vout_getfunctions )( &p_module->p_functions->vout );
|
||||
MODULE_ACTIVATE_STOP
|
||||
|
||||
MODULE_DEACTIVATE_START
|
||||
MODULE_DEACTIVATE_STOP
|
845
plugins/qnx/vout_qnx.c
Normal file
845
plugins/qnx/vout_qnx.c
Normal file
@ -0,0 +1,845 @@
|
||||
/*****************************************************************************
|
||||
* vout_qnx.c: QNX RTOS video output display method
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
*
|
||||
* Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
|
||||
*
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#define MODULE_NAME qnx
|
||||
#include "modules_inner.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Preamble
|
||||
*****************************************************************************/
|
||||
#include "defs.h"
|
||||
|
||||
#include <errno.h> /* ENOMEM */
|
||||
#include <stdlib.h> /* free() */
|
||||
#include <string.h> /* strerror() */
|
||||
|
||||
#include <photon/PtWidget.h>
|
||||
#include <photon/PtWindow.h>
|
||||
#include <photon/PtLabel.h>
|
||||
#include <photon/PdDirect.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "threads.h"
|
||||
#include "mtime.h"
|
||||
#include "tests.h"
|
||||
|
||||
#include "video.h"
|
||||
#include "video_output.h"
|
||||
|
||||
#include "interface.h"
|
||||
#include "intf_msg.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "modules.h"
|
||||
#include "modules_export.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_sys_t: video output QNX method descriptor
|
||||
*****************************************************************************
|
||||
* This structure is part of the video output thread descriptor.
|
||||
* It describes the QNX specific properties of an output thread. QNX video
|
||||
* output is performed through regular resizable windows. Windows can be
|
||||
* dynamically resized to adapt to the size of the streams.
|
||||
*****************************************************************************/
|
||||
|
||||
#define MODE_NORMAL_MEM 0
|
||||
#define MODE_SHARED_MEM 1
|
||||
#define MODE_VIDEO_MEM 2
|
||||
#define MODE_VIDEO_OVERLAY 3
|
||||
|
||||
typedef struct vout_sys_s
|
||||
{
|
||||
/* video mode */
|
||||
int i_mode;
|
||||
|
||||
/* internal stuff */
|
||||
PtWidget_t * p_window;
|
||||
|
||||
/* [shared] memory blit */
|
||||
PhImage_t * p_image[2];
|
||||
int i_img_type;
|
||||
|
||||
/* video memory blit */
|
||||
PdOffscreenContext_t * p_ctx[2];
|
||||
char * p_buf[2];
|
||||
|
||||
/* video overlay */
|
||||
PgVideoChannel_t * p_channel;
|
||||
void * p_vc_y[2];
|
||||
void * p_vc_u[2];
|
||||
void * p_vc_v[2];
|
||||
int i_vc_flags;
|
||||
int i_vc_format;
|
||||
|
||||
/* position & dimensions */
|
||||
PhPoint_t pos;
|
||||
PhDim_t dim;
|
||||
PhDim_t old_dim;
|
||||
PhDim_t screen_dim;
|
||||
} vout_sys_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int vout_Probe ( probedata_t *p_data );
|
||||
static int vout_Create ( struct vout_thread_s * );
|
||||
static int vout_Init ( struct vout_thread_s * );
|
||||
static void vout_End ( struct vout_thread_s * );
|
||||
static void vout_Destroy ( struct vout_thread_s * );
|
||||
static int vout_Manage ( struct vout_thread_s * );
|
||||
static void vout_Display ( struct vout_thread_s * );
|
||||
|
||||
static int QNXCreateWnd ( struct vout_thread_s * );
|
||||
static int QNXDestroyWnd ( struct vout_thread_s * );
|
||||
static int QNXInitDisplay ( struct vout_thread_s * );
|
||||
|
||||
/*****************************************************************************
|
||||
* Functions exported as capabilities. They are declared as static so that
|
||||
* we don't pollute the namespace too much.
|
||||
*****************************************************************************/
|
||||
void _M( vout_getfunctions )( function_list_t * p_function_list )
|
||||
{
|
||||
p_function_list->pf_probe = vout_Probe;
|
||||
p_function_list->functions.vout.pf_create = vout_Create;
|
||||
p_function_list->functions.vout.pf_init = vout_Init;
|
||||
p_function_list->functions.vout.pf_end = vout_End;
|
||||
p_function_list->functions.vout.pf_destroy = vout_Destroy;
|
||||
p_function_list->functions.vout.pf_manage = vout_Manage;
|
||||
p_function_list->functions.vout.pf_display = vout_Display;
|
||||
p_function_list->functions.vout.pf_setpalette = NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_Probe: probe the video driver and return a score
|
||||
*****************************************************************************
|
||||
* This function tries to initialize SDL and returns a score to the
|
||||
* plugin manager so that it can select the best plugin.
|
||||
*****************************************************************************/
|
||||
static int vout_Probe( probedata_t *p_data )
|
||||
{
|
||||
if( TestMethod( VOUT_METHOD_VAR, "qnx" ) )
|
||||
{
|
||||
return( 999 );
|
||||
}
|
||||
|
||||
return( 100 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_Create: allocate QNX video thread output method
|
||||
*****************************************************************************
|
||||
* This function allocate and initialize a QNX vout method. It uses some of the
|
||||
* vout properties to choose the window size, and change them according to the
|
||||
* actual properties of the display.
|
||||
*****************************************************************************/
|
||||
static int vout_Create( vout_thread_t *p_vout )
|
||||
{
|
||||
/* init connection to photon */
|
||||
if( PtInit( "/dev/photon" ) != 0 )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to connect to photon" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* allocate structure */
|
||||
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
|
||||
if( p_vout->p_sys == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: %s", strerror( ENOMEM ) );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
|
||||
|
||||
p_vout->b_fullscreen =
|
||||
main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT );
|
||||
p_vout->p_sys->i_mode =
|
||||
main_GetIntVariable( VOUT_OVERLAY_VAR, VOUT_OVERLAY_DEFAULT ) ?
|
||||
MODE_VIDEO_OVERLAY : MODE_NORMAL_MEM;
|
||||
p_vout->p_sys->dim.w =
|
||||
main_GetIntVariable( VOUT_WIDTH_VAR, VOUT_WIDTH_DEFAULT );
|
||||
p_vout->p_sys->dim.h =
|
||||
main_GetIntVariable( VOUT_HEIGHT_VAR, VOUT_HEIGHT_DEFAULT );
|
||||
|
||||
/* init display and create window */
|
||||
if( QNXInitDisplay( p_vout ) || QNXCreateWnd( p_vout ) )
|
||||
{
|
||||
free( p_vout->p_sys );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_Init: initialize QNX video thread output method
|
||||
*****************************************************************************
|
||||
* This function create the buffers needed by the output thread. It is called
|
||||
* at the beginning of the thread, but also each time the window is resized.
|
||||
*****************************************************************************/
|
||||
static int vout_Init( vout_thread_t *p_vout )
|
||||
{
|
||||
if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
|
||||
p_vout->p_sys->i_mode == MODE_SHARED_MEM )
|
||||
{
|
||||
/* create images for [shared] memory blit */
|
||||
|
||||
if( !( p_vout->p_sys->p_image[0] = PhCreateImage( NULL,
|
||||
p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
|
||||
p_vout->p_sys->i_img_type, NULL, 0,
|
||||
p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
|
||||
intf_ErrMsg( "vout error: cannot create image" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( !( p_vout->p_sys->p_image[1] = PhCreateImage( NULL,
|
||||
p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
|
||||
p_vout->p_sys->i_img_type, NULL, 0,
|
||||
p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
|
||||
intf_ErrMsg( "vout error: cannot create image" );
|
||||
PhReleaseImage( p_vout->p_sys->p_image[0] );
|
||||
free( p_vout->p_sys->p_image[0] );
|
||||
p_vout->p_sys->p_image[0] = NULL;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* set bytes per line, set buffers */
|
||||
p_vout->i_bytes_per_line = p_vout->p_sys->p_image[0]->bpl;
|
||||
p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_image[0]->image,
|
||||
p_vout->p_sys->p_image[1]->image );
|
||||
}
|
||||
else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
|
||||
{
|
||||
/* create offscreen contexts for video memory blit */
|
||||
|
||||
if( ( p_vout->p_sys->p_ctx[0] = PdCreateOffscreenContext( 0,
|
||||
p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
|
||||
Pg_OSC_MEM_PAGE_ALIGN ) ) == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to create offscreen context" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( ( p_vout->p_sys->p_ctx[1] = PdCreateOffscreenContext( 0,
|
||||
p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
|
||||
Pg_OSC_MEM_PAGE_ALIGN ) ) == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to create offscreen context" );
|
||||
PhDCRelease ( p_vout->p_sys->p_ctx[0] );
|
||||
p_vout->p_sys->p_ctx[0] = NULL;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* get context pointers */
|
||||
if( ( ( p_vout->p_sys->p_buf[0] =
|
||||
PdGetOffscreenContextPtr ( p_vout->p_sys->p_ctx[0] ) ) == NULL ) ||
|
||||
( p_vout->p_sys->p_buf[1] =
|
||||
PdGetOffscreenContextPtr ( p_vout->p_sys->p_ctx[1] ) ) == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to get offscreen context ptr" );
|
||||
PhDCRelease ( p_vout->p_sys->p_ctx[0] );
|
||||
PhDCRelease ( p_vout->p_sys->p_ctx[1] );
|
||||
p_vout->p_sys->p_ctx[0] = NULL;
|
||||
p_vout->p_sys->p_ctx[1] = NULL;
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* set bytes per line, clear buffers, set buffers */
|
||||
p_vout->i_bytes_per_line =
|
||||
p_vout->i_bytes_per_pixel * p_vout->p_sys->dim.w;
|
||||
memset( p_vout->p_sys->p_buf[0], 0,
|
||||
p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
|
||||
memset( p_vout->p_sys->p_buf[1], 0,
|
||||
p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
|
||||
p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_buf[0],
|
||||
p_vout->p_sys->p_buf[1] );
|
||||
}
|
||||
else if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
|
||||
{
|
||||
PgScalerProps_t props;
|
||||
|
||||
props.size = sizeof( props );
|
||||
props.format = p_vout->p_sys->i_vc_format;
|
||||
props.viewport.ul.x = p_vout->p_sys->pos.x + 4;
|
||||
props.viewport.ul.y = p_vout->p_sys->pos.y + 20;
|
||||
props.viewport.lr.x = p_vout->p_sys->dim.w + props.viewport.ul.x;
|
||||
props.viewport.lr.y = p_vout->p_sys->dim.h + props.viewport.ul.y;
|
||||
props.src_dim.w = p_vout->p_sys->dim.w;
|
||||
props.src_dim.h = p_vout->p_sys->dim.h;
|
||||
props.flags = Pg_SCALER_PROP_SCALER_ENABLE |
|
||||
Pg_SCALER_PROP_DOUBLE_BUFFER;
|
||||
|
||||
if( PgConfigScalerChannel( p_vout->p_sys->p_channel, &props ) == -1 )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to configure video channel" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
p_vout->p_sys->p_vc_y[0] =
|
||||
PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->yplane1 );
|
||||
p_vout->p_sys->p_vc_y[1] =
|
||||
PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->yplane2 );
|
||||
|
||||
if( p_vout->p_sys->p_vc_y[0] == NULL ||
|
||||
p_vout->p_sys->p_vc_y[1] == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to get video channel ctx ptr" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_YV12 )
|
||||
{
|
||||
p_vout->b_need_render = 0;
|
||||
|
||||
p_vout->p_sys->p_vc_u[0] =
|
||||
PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->uplane1 );
|
||||
p_vout->p_sys->p_vc_u[1] =
|
||||
PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->uplane2 );
|
||||
p_vout->p_sys->p_vc_v[0] =
|
||||
PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->vplane1 );
|
||||
p_vout->p_sys->p_vc_v[1] =
|
||||
PdGetOffscreenContextPtr( p_vout->p_sys->p_channel->vplane2 );
|
||||
|
||||
if( p_vout->p_sys->p_vc_u[0] == NULL ||
|
||||
p_vout->p_sys->p_vc_u[1] == NULL ||
|
||||
p_vout->p_sys->p_vc_v[0] == NULL ||
|
||||
p_vout->p_sys->p_vc_v[1] == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to get video channel ctx ptr" );
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
else if( p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_RGB8888 )
|
||||
{
|
||||
/* set bytes per line, clear buffers, set buffers */
|
||||
p_vout->i_bytes_per_line =
|
||||
p_vout->i_bytes_per_pixel * p_vout->p_sys->dim.w;
|
||||
memset( p_vout->p_sys->p_vc_y[0], 0,
|
||||
p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
|
||||
memset( p_vout->p_sys->p_vc_y[1], 0,
|
||||
p_vout->i_bytes_per_line * p_vout->p_sys->dim.h );
|
||||
p_vout->pf_setbuffers( p_vout,
|
||||
p_vout->p_sys->p_vc_y[0], p_vout->p_sys->p_vc_y[1] );
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_End: terminate QNX video thread output method
|
||||
*****************************************************************************
|
||||
* Destroy the buffers created by vout_Init. It is called at the end of
|
||||
* the thread, but also each time the window is resized.
|
||||
*****************************************************************************/
|
||||
static void vout_End( vout_thread_t *p_vout )
|
||||
{
|
||||
if( ( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
|
||||
p_vout->p_sys->i_mode == MODE_SHARED_MEM ) &&
|
||||
p_vout->p_sys->p_image[0] )
|
||||
{
|
||||
PhReleaseImage( p_vout->p_sys->p_image[0] );
|
||||
PhReleaseImage( p_vout->p_sys->p_image[1] );
|
||||
free( p_vout->p_sys->p_image[0] );
|
||||
free( p_vout->p_sys->p_image[1] );
|
||||
}
|
||||
else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM &&
|
||||
p_vout->p_sys->p_ctx[0] )
|
||||
{
|
||||
PhDCRelease( p_vout->p_sys->p_ctx[0] );
|
||||
PhDCRelease( p_vout->p_sys->p_ctx[1] );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_Destroy: destroy QNX video thread output method
|
||||
*****************************************************************************
|
||||
* Terminate an output method created by vout_CreateOutputMethod
|
||||
*****************************************************************************/
|
||||
static void vout_Destroy( vout_thread_t *p_vout )
|
||||
{
|
||||
/* destroy the window */
|
||||
QNXDestroyWnd( p_vout );
|
||||
|
||||
/* destroy structure */
|
||||
free( p_vout->p_sys );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_Manage: handle QNX events
|
||||
*****************************************************************************
|
||||
* This function should be called regularly by video output thread. It allows
|
||||
* window resizing. It returns a non null value on error.
|
||||
*****************************************************************************/
|
||||
static int vout_Manage( vout_thread_t *p_vout )
|
||||
{
|
||||
int i_ev, i_buflen;
|
||||
PhEvent_t *p_event;
|
||||
boolean_t b_repos = 0;
|
||||
|
||||
/* allocate buffer for event */
|
||||
i_buflen = sizeof( PhEvent_t ) * 4;
|
||||
if( ( p_event = malloc( i_buflen ) ) == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: %s", strerror( ENOMEM ) );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* event loop */
|
||||
do
|
||||
{
|
||||
memset( p_event, 0, i_buflen );
|
||||
i_ev = PhEventPeek( p_event, i_buflen );
|
||||
|
||||
if( i_ev == Ph_RESIZE_MSG )
|
||||
{
|
||||
i_buflen = PhGetMsgSize( p_event );
|
||||
if( ( p_event = realloc( p_event, i_buflen ) ) == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: %s", strerror( ENOMEM ) );
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
else if( i_ev == Ph_EVENT_MSG )
|
||||
{
|
||||
PtEventHandler( p_event );
|
||||
|
||||
if( p_event->type == Ph_EV_WM )
|
||||
{
|
||||
PhWindowEvent_t *p_ev = PhGetData( p_event );
|
||||
|
||||
switch( p_ev->event_f )
|
||||
{
|
||||
case Ph_WM_CLOSE:
|
||||
p_main->p_intf->b_die = 1;
|
||||
break;
|
||||
|
||||
case Ph_WM_MOVE:
|
||||
b_repos = 1;
|
||||
p_vout->p_sys->pos.x = p_ev->pos.x;
|
||||
p_vout->p_sys->pos.y = p_ev->pos.y;
|
||||
break;
|
||||
|
||||
case Ph_WM_RESIZE:
|
||||
p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
|
||||
p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
|
||||
p_vout->p_sys->dim.w = p_vout->i_width = p_ev->size.w;
|
||||
p_vout->p_sys->dim.h = p_vout->i_height = p_ev->size.h;
|
||||
p_vout->i_changes |= VOUT_SIZE_CHANGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( p_event->type == Ph_EV_KEY )
|
||||
{
|
||||
PhKeyEvent_t *p_ev = PhGetData( p_event );
|
||||
long i_key = p_ev->key_sym;
|
||||
|
||||
if( ( p_ev->key_flags & Pk_KF_Key_Down ) &&
|
||||
( p_ev->key_flags & Pk_KF_Sym_Valid ) )
|
||||
{
|
||||
switch( i_key )
|
||||
{
|
||||
case Pk_q:
|
||||
case Pk_Q:
|
||||
p_main->p_intf->b_die = 1;
|
||||
break;
|
||||
|
||||
case Pk_f:
|
||||
case Pk_F:
|
||||
p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
|
||||
break;
|
||||
|
||||
case Pk_c:
|
||||
case Pk_C:
|
||||
p_vout->b_grayscale = ! p_vout->b_grayscale;
|
||||
p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( i_key >= Pk_0 && i_key <= Pk_9 )
|
||||
{
|
||||
network_ChannelJoin( i_key );
|
||||
}
|
||||
else if( intf_ProcessKey( p_main->p_intf,
|
||||
(char) i_key ) )
|
||||
{
|
||||
intf_DbgMsg( "vout: unhandled key '%c' (%i)",
|
||||
(char) i_key, i_key );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while( i_ev != -1 && i_ev != 0 );
|
||||
|
||||
free( p_event );
|
||||
|
||||
/*
|
||||
* fullscreen
|
||||
*/
|
||||
if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
|
||||
{
|
||||
PhDim_t dim;
|
||||
PhPoint_t pos;
|
||||
|
||||
intf_DbgMsg( "vout: changing full-screen status" );
|
||||
|
||||
p_vout->b_fullscreen = !p_vout->b_fullscreen;
|
||||
p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
|
||||
|
||||
if( p_vout->b_fullscreen )
|
||||
{
|
||||
pos.x = pos.y = 0;
|
||||
dim.w = p_vout->p_sys->screen_dim.w + 1;
|
||||
dim.h = p_vout->p_sys->screen_dim.h + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.x = p_vout->p_sys->pos.x;
|
||||
pos.y = p_vout->p_sys->pos.y;
|
||||
dim.w = p_vout->p_sys->old_dim.w + 1;
|
||||
dim.h = p_vout->p_sys->old_dim.h + 1;
|
||||
}
|
||||
|
||||
PtSetResource( p_vout->p_sys->p_window,
|
||||
Pt_ARG_WINDOW_RENDER_FLAGS,
|
||||
p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
|
||||
Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
|
||||
PtSetResource( p_vout->p_sys->p_window,
|
||||
Pt_ARG_POS, &pos, 0 );
|
||||
PtSetResource( p_vout->p_sys->p_window,
|
||||
Pt_ARG_DIM, &dim, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* vout window resizing
|
||||
*/
|
||||
if( ( p_vout->i_width != p_vout->p_sys->dim.w ) ||
|
||||
( p_vout->i_height != p_vout->p_sys->dim.h ) )
|
||||
{
|
||||
intf_DbgMsg( "vout: resizing output window" );
|
||||
|
||||
p_vout->p_sys->dim.w = p_vout->i_width;
|
||||
p_vout->p_sys->dim.h = p_vout->i_height;
|
||||
|
||||
/* set new dimension */
|
||||
PtSetResource( p_vout->p_sys->p_window,
|
||||
Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* size change
|
||||
*/
|
||||
if( p_vout->i_changes & VOUT_SIZE_CHANGE )
|
||||
{
|
||||
intf_DbgMsg( "vout: resizing window" );
|
||||
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
|
||||
|
||||
vout_End( p_vout );
|
||||
if( vout_Init( p_vout ) )
|
||||
{
|
||||
intf_ErrMsg( "vout error: cannot resize display" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
p_vout->i_changes |= VOUT_YUV_CHANGE;
|
||||
intf_Msg( "vout: video display resized (%dx%d)",
|
||||
p_vout->i_width, p_vout->i_height );
|
||||
}
|
||||
|
||||
/*
|
||||
* position change, move video channel
|
||||
*/
|
||||
if( b_repos && p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
|
||||
{
|
||||
intf_DbgMsg( "vout: moving video channel" );
|
||||
|
||||
vout_End( p_vout );
|
||||
if( vout_Init( p_vout ) )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to move video channel" );
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
return( i_ev == -1 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* vout_Display: displays previously rendered output
|
||||
*****************************************************************************
|
||||
* This function send the currently rendered image to QNX server, wait until
|
||||
* it is displayed and switch the two rendering buffer, preparing next frame.
|
||||
*****************************************************************************/
|
||||
static void vout_Display( vout_thread_t *p_vout )
|
||||
{
|
||||
if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
|
||||
p_vout->p_sys->i_mode == MODE_SHARED_MEM )
|
||||
{
|
||||
PhPoint_t pos = { 0, 0 };
|
||||
|
||||
PgSetRegion( PtWidgetRid( p_vout->p_sys->p_window ) );
|
||||
PgDrawPhImagemx( &pos, p_vout->p_sys->p_image[p_vout->i_buffer_index], 0 );
|
||||
PgFlush();
|
||||
}
|
||||
else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
|
||||
{
|
||||
PhRect_t rc = { { 0, 0 }, {
|
||||
p_vout->p_sys->dim.w,
|
||||
p_vout->p_sys->dim.h
|
||||
} };
|
||||
|
||||
PgSetRegion( PtWidgetRid ( p_vout->p_sys->p_window ) );
|
||||
PgContextBlit( p_vout->p_sys->p_ctx[p_vout->i_buffer_index], &rc, NULL, &rc );
|
||||
PgFlush();
|
||||
}
|
||||
else if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY &&
|
||||
p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_YV12 )
|
||||
{
|
||||
int i_size, i_index;
|
||||
|
||||
/* this code has NOT been tested */
|
||||
|
||||
i_size = p_vout->p_rendered_pic->i_width *
|
||||
p_vout->p_rendered_pic->i_height;
|
||||
i_index = PgNextVideoFrame( p_vout->p_sys->p_channel );
|
||||
|
||||
memcpy( p_vout->p_sys->p_vc_y[i_index],
|
||||
p_vout->p_rendered_pic->p_y, i_size );
|
||||
memcpy( p_vout->p_sys->p_vc_v[i_index],
|
||||
p_vout->p_rendered_pic->p_v, i_size / 4 );
|
||||
memcpy( p_vout->p_sys->p_vc_u[i_index],
|
||||
p_vout->p_rendered_pic->p_u, i_size / 4 );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* QNXInitDisplay: check screen resolution, depth, amount of video ram, etc
|
||||
*****************************************************************************/
|
||||
static int QNXInitDisplay( p_vout_thread_t p_vout )
|
||||
{
|
||||
PgHWCaps_t hwcaps;
|
||||
PgDisplaySettings_t cfg;
|
||||
PgVideoModeInfo_t minfo;
|
||||
|
||||
/* get graphics card hw capabilities */
|
||||
if( PgGetGraphicsHWCaps( &hwcaps ) != 0 )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to get gfx card capabilities" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* get current video mode */
|
||||
if( PgGetVideoMode( &cfg ) != 0 )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to get current video mode" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* get video mode info */
|
||||
if( PgGetVideoModeInfo( cfg.mode, &minfo ) != 0 )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to get info for video mode" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* use video ram if we have enough available */
|
||||
if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM &&
|
||||
hwcaps.currently_available_video_ram >=
|
||||
( ( minfo.width * minfo.height * minfo.bits_per_pixel ) / 8 ) )
|
||||
{
|
||||
intf_DbgMsg( "vout: using video ram" );
|
||||
p_vout->p_sys->i_mode = MODE_VIDEO_MEM;
|
||||
}
|
||||
|
||||
p_vout->p_sys->i_img_type = minfo.type;
|
||||
p_vout->p_sys->screen_dim.w = minfo.width;
|
||||
p_vout->p_sys->screen_dim.h = minfo.height;
|
||||
p_vout->i_screen_depth = minfo.bits_per_pixel;
|
||||
|
||||
switch( minfo.type )
|
||||
{
|
||||
case Pg_IMAGE_PALETTE_BYTE:
|
||||
p_vout->i_bytes_per_pixel = 1;
|
||||
break;
|
||||
|
||||
case Pg_IMAGE_DIRECT_555:
|
||||
case Pg_IMAGE_DIRECT_565:
|
||||
p_vout->i_bytes_per_pixel = 2;
|
||||
break;
|
||||
|
||||
case Pg_IMAGE_DIRECT_8888:
|
||||
p_vout->i_bytes_per_pixel = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
switch( p_vout->i_screen_depth )
|
||||
{
|
||||
case 15:
|
||||
p_vout->i_red_mask = 0x7c00;
|
||||
p_vout->i_green_mask = 0x03e0;
|
||||
p_vout->i_blue_mask = 0x001f;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
p_vout->i_red_mask = 0xf800;
|
||||
p_vout->i_green_mask = 0x07e0;
|
||||
p_vout->i_blue_mask = 0x001f;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
case 32:
|
||||
default:
|
||||
p_vout->i_red_mask = 0xff0000;
|
||||
p_vout->i_green_mask = 0x00ff00;
|
||||
p_vout->i_blue_mask = 0x0000ff;
|
||||
break;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* QNXCreateWnd: create and realize the main window
|
||||
*****************************************************************************/
|
||||
static int QNXCreateWnd( p_vout_thread_t p_vout )
|
||||
{
|
||||
PtArg_t args[8];
|
||||
PhPoint_t pos = { 0, 0 };
|
||||
PgColor_t color = Pg_BLACK;
|
||||
|
||||
/* correct way to check for overlay support:
|
||||
|
||||
1. call PgGetGraphicsHWCaps and check
|
||||
the results for Pg_VIDEO_OVERLAY
|
||||
2. check if the current graphics mode
|
||||
has PgVM_MODE_CAP1_VIDEO_OVERLAY set
|
||||
3. call PgGetScalerCapabilities for info
|
||||
|
||||
problems:
|
||||
|
||||
1. Pg_VIDEO_OVERLAY is not defined in any
|
||||
header files :)
|
||||
2. PgVM_MODE_CAP1_VIDEO_OVERLAY is not set
|
||||
even if the current mode supports overlay
|
||||
3. the flags (chroma, etc) do not reflect
|
||||
the actual capabilities
|
||||
*/
|
||||
|
||||
if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
|
||||
{
|
||||
if( ( p_vout->p_sys->p_channel =
|
||||
PgCreateVideoChannel( Pg_VIDEO_CHANNEL_SCALER, 0 ) ) == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to create video channel" );
|
||||
return( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
PgScalerCaps_t vcaps;
|
||||
|
||||
vcaps.size = sizeof( vcaps );
|
||||
while( PgGetScalerCapabilities( p_vout->p_sys->p_channel,
|
||||
i++, &vcaps ) == 0 )
|
||||
{
|
||||
if( vcaps.format == Pg_VIDEO_FORMAT_YV12 ||
|
||||
vcaps.format == Pg_VIDEO_FORMAT_RGB8888 )
|
||||
{
|
||||
p_vout->p_sys->i_vc_flags = vcaps.flags;
|
||||
p_vout->p_sys->i_vc_format = vcaps.format;
|
||||
}
|
||||
|
||||
vcaps.size = sizeof( vcaps );
|
||||
}
|
||||
|
||||
if( p_vout->p_sys->i_vc_format == 0 )
|
||||
{
|
||||
intf_ErrMsg( "vout error: need YV12 or RGB8888 overlay" );
|
||||
return( 1 );
|
||||
}
|
||||
else if( vcaps.flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
|
||||
{
|
||||
color = PgGetOverlayChromaColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fullscreen, set dimension */
|
||||
if( p_vout->b_fullscreen )
|
||||
{
|
||||
p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
|
||||
p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
|
||||
p_vout->i_width = p_vout->p_sys->dim.w = p_vout->p_sys->screen_dim.w;
|
||||
p_vout->i_height = p_vout->p_sys->dim.h = p_vout->p_sys->screen_dim.h;
|
||||
}
|
||||
|
||||
/* set window parameters */
|
||||
PtSetArg( &args[0], Pt_ARG_POS, &pos, 0 );
|
||||
PtSetArg( &args[1], Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
|
||||
PtSetArg( &args[2], Pt_ARG_FILL_COLOR, color, 0 );
|
||||
PtSetArg( &args[3], Pt_ARG_WINDOW_TITLE, "VideoLan Client", 0 );
|
||||
PtSetArg( &args[4], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE );
|
||||
PtSetArg( &args[5], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
|
||||
Ph_WM_MOVE | Ph_WM_RESIZE | Ph_WM_CLOSE );
|
||||
PtSetArg( &args[6], Pt_ARG_WINDOW_RENDER_FLAGS,
|
||||
p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
|
||||
Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
|
||||
|
||||
/* create window */
|
||||
p_vout->p_sys->p_window = PtCreateWidget( PtWindow, Pt_NO_PARENT, 7, args);
|
||||
if( p_vout->p_sys->p_window == NULL )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to create window" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* realize the window widget */
|
||||
if( PtRealizeWidget( p_vout->p_sys->p_window ) != 0 )
|
||||
{
|
||||
intf_ErrMsg( "vout error: unable to realize window widget" );
|
||||
PtDestroyWidget( p_vout->p_sys->p_window );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* QNXDestroyWnd: unrealize and destroy the main window
|
||||
*****************************************************************************/
|
||||
static int QNXDestroyWnd( p_vout_thread_t p_vout )
|
||||
{
|
||||
/* destroy the window widget */
|
||||
PtUnrealizeWidget( p_vout->p_sys->p_window );
|
||||
PtDestroyWidget( p_vout->p_sys->p_window );
|
||||
|
||||
/* destroy video channel */
|
||||
if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
|
||||
{
|
||||
PgDestroyVideoChannel( p_vout->p_sys->p_channel );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
Loading…
Reference in New Issue
Block a user