[MPlayer-dev-eng] [PATCH] Support for QNX: QSA audio and Photon GUI.

Mike Gorchak mike.gorchak.qnx at gmail.com
Sun Feb 3 21:23:11 CET 2013


Hi,

Here is a patch (made against latest repository snapshot) to enable
native QNX support in the mplayer. This
patch contains QNX Sound Architecture (QSA) audio driver and Photon GUI
YUV/RGB renderer.

I've posted previous patch a week ago, but it seems ignored. This
patch has many improvements comparing to previous.

Thanks in advance!

diff -u -r -N mplayer-export-2013-02-03-orig/DOCS/man/en/mplayer.1
mplayer-export-2013-02-03/DOCS/man/en/mplayer.1
--- mplayer-export-2013-02-03-orig/DOCS/man/en/mplayer.1	2013-01-31
07:24:25.000000000 +0200
+++ mplayer-export-2013-02-03/DOCS/man/en/mplayer.1	2013-02-03
18:46:04.000000000 +0200
@@ -3575,7 +3575,7 @@
 movie to make it fit a 4:3 display without black bands).
 The range controls how much of the image is cropped.
 Only works with the directx, xv, xmga, mga, gl, gl_tiled, quartz,
-corevideo and xvidix video output drivers.
+corevideo, photon and xvidix video output drivers.
 .br
 .I NOTE:
 Values between \-1 and 0 are allowed as well, but highly experimental
diff -u -r -N mplayer-export-2013-02-03-orig/DOCS/tech/MAINTAINERS
mplayer-export-2013-02-03/DOCS/tech/MAINTAINERS
--- mplayer-export-2013-02-03-orig/DOCS/tech/MAINTAINERS	2013-01-31
07:24:25.000000000 +0200
+++ mplayer-export-2013-02-03/DOCS/tech/MAINTAINERS	2013-02-03
19:01:04.000000000 +0200
@@ -175,6 +175,7 @@
     * vo_mga.c - None
     * vo_mpegpes.c - None
     * vo_null.c - None
+    * vo_photon.c - Mike Gorchak
     * vo_png.c - Felix BГјnemann
     * vo_pnm.c - Ivo van Poorten
     * vo_quartz.c - Nicolas Plourde
@@ -216,6 +217,7 @@
     * ao_pcm.c - None
     * ao_plugin.c - None
     * ao_pulse.c - None
+    * ao_qsa.c - Mike Gorchak
     * ao_sdl.c - None
     * ao_sgi.c - None
     * ao_sun.c - None
diff -u -r -N mplayer-export-2013-02-03-orig/DOCS/xml/en/ports.xml
mplayer-export-2013-02-03/DOCS/xml/en/ports.xml
--- mplayer-export-2013-02-03-orig/DOCS/xml/en/ports.xml	2013-01-31
07:24:21.000000000 +0200
+++ mplayer-export-2013-02-03/DOCS/xml/en/ports.xml	2013-02-03
18:59:41.000000000 +0200
@@ -497,7 +497,19 @@
 <title>QNX</title>

 <para>
-You'll need to download and install SDL for QNX. Then run
+By default configure script will detect Photon GUI and QSA audio interface
+automatically. After successfull build you can run
<application>MPlayer</application>
+with <option>-vo photon</option> and <option>-ao qsa</option> options.
+</para>
+
+<para>
+Photon driver supports three methods of video output: direct layer
access (fastest),
+hardware offscreen blitter (fast), software offscreen blitter (slow,
but works with
+every graphics driver on every platform).
+</para>
+
+<para>
+As alternative, you'll need to download and install SDL for QNX. Then run
 <application>MPlayer</application> with <option>-vo sdl:driver=photon</option>
 and <option>-ao sdl:nto</option> options, it should be fast.
 </para>
diff -u -r -N mplayer-export-2013-02-03-orig/DOCS/xml/it/ports.xml
mplayer-export-2013-02-03/DOCS/xml/it/ports.xml
--- mplayer-export-2013-02-03-orig/DOCS/xml/it/ports.xml	2013-01-31
07:24:21.000000000 +0200
+++ mplayer-export-2013-02-03/DOCS/xml/it/ports.xml	2013-02-03
18:59:41.000000000 +0200
@@ -497,7 +497,19 @@
 <title>QNX</title>

 <para>
-You'll need to download and install SDL for QNX. Then run
+By default configure script will detect Photon GUI and QSA audio interface
+automatically. After successfull build you can run
<application>MPlayer</application>
+with <option>-vo photon</option> and <option>-ao qsa</option> options.
+</para>
+
+<para>
+Photon driver supports three methods of video output: direct layer
access (fastest),
+hardware offscreen blitter (fast), software offscreen blitter (slow,
but works with
+every graphics driver on every platform).
+</para>
+
+<para>
+As alternative, you'll need to download and install SDL for QNX. Then run
 <application>MPlayer</application> with <option>-vo sdl:driver=photon</option>
 and <option>-ao sdl:nto</option> options, it should be fast.
 </para>
diff -u -r -N mplayer-export-2013-02-03-orig/DOCS/xml/zh_CN/ports.xml
mplayer-export-2013-02-03/DOCS/xml/zh_CN/ports.xml
--- mplayer-export-2013-02-03-orig/DOCS/xml/zh_CN/ports.xml	2013-01-31
07:24:21.000000000 +0200
+++ mplayer-export-2013-02-03/DOCS/xml/zh_CN/ports.xml	2013-02-03
18:59:41.000000000 +0200
@@ -497,7 +497,19 @@
 <title>QNX</title>

 <para>
-You'll need to download and install SDL for QNX. Then run
+By default configure script will detect Photon GUI and QSA audio interface
+automatically. After successfull build you can run
<application>MPlayer</application>
+with <option>-vo photon</option> and <option>-ao qsa</option> options.
+</para>
+
+<para>
+Photon driver supports three methods of video output: direct layer
access (fastest),
+hardware offscreen blitter (fast), software offscreen blitter (slow,
but works with
+every graphics driver on every platform).
+</para>
+
+<para>
+As alternative, you'll need to download and install SDL for QNX. Then run
 <application>MPlayer</application> with <option>-vo sdl:driver=photon</option>
 and <option>-ao sdl:nto</option> options, it should be fast.
 </para>
diff -u -r -N mplayer-export-2013-02-03-orig/Makefile
mplayer-export-2013-02-03/Makefile
--- mplayer-export-2013-02-03-orig/Makefile	2013-01-31 07:24:06.000000000 +0200
+++ mplayer-export-2013-02-03/Makefile	2013-02-03 15:53:50.000000000 +0200
@@ -560,6 +560,7 @@
 SRCS_MPLAYER-$(OSS)           += libao2/ao_oss.c
 SRCS_MPLAYER-$(PNM)           += libvo/vo_pnm.c
 SRCS_MPLAYER-$(PULSE)         += libao2/ao_pulse.c
+SRCS_MPLAYER-$(QSA)           += libao2/ao_qsa.c
 SRCS_MPLAYER-$(QUARTZ)        += libvo/vo_quartz.c libvo/osx_common.c
 SRCS_MPLAYER-$(S3FB)          += libvo/vo_s3fb.c
 SRCS_MPLAYER-$(SDL)           += libao2/ao_sdl.c libvo/vo_sdl.c
libvo/sdl_common.c
@@ -573,6 +574,7 @@
 SRCS_MPLAYER-$(V4L2)          += libao2/ao_v4l2.c
 SRCS_MPLAYER-$(VDPAU)         += libvo/vo_vdpau.c
 SRCS_MPLAYER-$(VESA)          += libvo/gtf.c libvo/vo_vesa.c libvo/vesa_lvo.c
+SRCS_MPLAYER-$(PHOTON)        += libvo/vo_photon.c
 SRCS_MPLAYER-$(VIDIX)         += libvo/vo_cvidix.c \
                                  libvo/vosub_vidix.c \
                                  vidix/vidix.c \
diff -u -r -N mplayer-export-2013-02-03-orig/configure
mplayer-export-2013-02-03/configure
--- mplayer-export-2013-02-03-orig/configure	2013-01-31 07:24:20.000000000 +0200
+++ mplayer-export-2013-02-03/configure	2013-02-03 15:37:06.000000000 +0200
@@ -524,6 +524,7 @@
   --enable-bl              enable Blinkenlights video output [disable]
   --enable-tdfxvid         enable tdfx_vid video output [disable]
   --enable-xvr100          enable SUN XVR-100 video output [autodetect]
+  --enable-photon          enable Photon video output [autodetect]
   --disable-tga            disable Targa video output [enable]
   --disable-pnm            disable PNM video output [enable]
   --disable-md5sum         disable md5sum video output [enable]
@@ -546,6 +547,7 @@
   --disable-dart         disable DART audio output [autodetect]
   --disable-win32waveout disable Windows waveout audio output [autodetect]
   --disable-coreaudio    disable CoreAudio audio output [autodetect]
+  --disable-qsa          disable QSA audio output [autodetect]
   --disable-select       disable using select() on the audio device [enable]

 Language options:
@@ -731,6 +733,7 @@
 _caca=auto
 _svga=auto
 _vesa=auto
+_photon=auto
 _fbdev=auto
 _dvb=auto
 _dxr2=auto
@@ -796,6 +799,7 @@
 _sgiaudio=auto
 _sunaudio=auto
 _alsa=auto
+_qsa=auto
 _fastmemcpy=yes
 hardcoded_tables=no
 _unrar_exec=auto
@@ -1098,6 +1102,8 @@
   --disable-svga)       _svga=no        ;;
   --enable-vesa)        _vesa=yes       ;;
   --disable-vesa)       _vesa=no        ;;
+  --enable-photon)      _photon=yes     ;;
+  --disable-photon)     _photon=no      ;;
   --enable-fbdev)       _fbdev=yes      ;;
   --disable-fbdev)      _fbdev=no       ;;
   --enable-dvb)         _dvb=yes        ;;
@@ -1226,6 +1232,8 @@
   --disable-sgiaudio)   _sgiaudio=no    ;;
   --enable-alsa)        _alsa=yes       ;;
   --disable-alsa)       _alsa=no        ;;
+  --enable-qsa)         _qsa=yes        ;;
+  --disable-qsa)        _qsa=no         ;;
   --enable-tv)          _tv=yes         ;;
   --disable-tv)         _tv=no          ;;
   --enable-tv-bsdbt848)  _tv_bsdbt848=yes ;;
@@ -1710,10 +1718,6 @@
   extra_cflags="-DNEWLIB -D__USE_INLINE__ $extra_cflags"
 fi

-if qnx ; then
-  extra_ldflags="$extra_ldflags -lph"
-fi
-
 if os2 ; then
   _exesuf=".exe"
   _getch=getch2-os2.c
@@ -3986,6 +3990,19 @@
 fi #if sunos


+if qnx; then
+echocheck "dcmd_cam.h (QNX)"
+_qnx_cam=no
+header_check sys/dcmd_cam.h && _qnx_cam=yes
+if test "$_qnx_cam" = yes ; then
+  def_qnx_cam='#define QNX_DCMD_CAM_H 1'
+else
+  def_qnx_cam='#undef QNX_DCMD_CAM_H'
+fi
+echores "$_qnx_cam"
+fi #if qnx
+
+
 echocheck "termcap"
 if test "$_termcap" = auto ; then
   _termcap=no
@@ -5184,6 +5201,23 @@
 fi
 echores "$_vesa"

+
+echocheck "Photon support"
+if test "$_photon" = auto ; then
+  _photon=no
+  statement_check Pt.h 'PtInit(NULL)' -lph && _photon=yes
+fi
+if test "$_photon" = yes ; then
+  def_photon='#define CONFIG_PHOTON 1'
+  libs_mplayer="$libs_mplayer -lph"
+  vomodules="photon $vomodules"
+else
+  def_photon='#undef CONFIG_PHOTON'
+  novomodules="photon $novomodules"
+fi
+echores "$_photon"
+
+
 #################
 # VIDEO + AUDIO #
 #################
@@ -5747,6 +5781,22 @@
 echores "$_alsa"


+echocheck "QSA audio"
+if test "$_qsa" = auto ; then
+  _qsa=no
+  header_check sys/asoundlib.h -lasound $ld_dl $ld_pthread && _qsa=yes
+fi
+if test "$_qsa" = yes ; then
+  aomodules="qsa $aomodules"
+  def_alsa='#define CONFIG_QSA 1'
+  extra_ldflags="$extra_ldflags -lasound"
+else
+  noaomodules="qsa $noaomodules"
+  def_alsa='#undef CONFIG_QSA'
+fi
+echores "$_qsa"
+
+
 echocheck "Sun audio"
 if test "$_sunaudio" = auto ; then
   cat > $TMPC << EOF
@@ -5861,6 +5911,8 @@
   default_cdrom_device="/dev/disk1"
 elif dragonfly ; then
   default_cdrom_device="/dev/cd0"
+elif qnx ; then
+  default_cdrom_device="/dev/cd0"
 elif freebsd ; then
   default_cdrom_device="/dev/acd0"
 elif openbsd ; then
@@ -5875,7 +5927,7 @@
   default_cdrom_device="/dev/cdrom"
 fi

-if win32 || os2 || dragonfly || freebsd || openbsd || sunos || amigaos ; then
+if win32 || os2 || dragonfly || freebsd || openbsd || sunos ||
amigaos || qnx ; then
   default_dvd_device=$default_cdrom_device
 elif darwin ; then
   default_dvd_device="/dev/rdiskN"
@@ -5924,9 +5976,9 @@
 if test "$_dvdread_internal" = auto ; then
   _dvdread_internal=no
   _dvdread=no
-  if (linux || freebsd || netbsd || openbsd || dragonfly || sunos || hpux) &&
+  if (linux || freebsd || netbsd || openbsd || dragonfly || sunos ||
hpux || qnx) &&
      (test "$_dvd" = yes || test "$_cdrom" = yes || test "$_cdio" = yes ||
-      test "$_dvdio" = yes || test "$_bsdi_dvd" = yes) ||
+      test "$_dvdio" = yes || test "$_bsdi_dvd" = yes || test
"$_qnx_cam" = yes) ||
      darwin || win32 || os2; then
     _dvdread_internal=yes
     _dvdread=yes
@@ -8335,12 +8387,14 @@
 OPENAL = $_openal
 OSS = $_ossaudio
 PE_EXECUTABLE = $_pe_executable
+PHOTON = $_photon
 PNG = $_png
 PNM = $_pnm
 POSTPROC = $postproc
 PRIORITY = $_priority
 PULSE = $_pulse
 PVR = $_pvr
+QSA = $_qsa
 QTX_CODECS = $_qtx
 QTX_CODECS_WIN32 = $_qtx_codecs_win32
 QTX_EMULATION = $_qtx_emulation
@@ -8771,6 +8825,7 @@
 $def_ossaudio_devdsp
 $def_ossaudio_devmixer
 $def_pulse
+$def_qsa
 $def_sgiaudio
 $def_sunaudio
 $def_win32waveout
@@ -8867,6 +8922,7 @@
 $def_mga
 $def_mlib
 $def_mng
+$def_photon
 $def_postproc
 $def_png
 $def_pnm
diff -u -r -N mplayer-export-2013-02-03-orig/cpudetect.c
mplayer-export-2013-02-03/cpudetect.c
--- mplayer-export-2013-02-03-orig/cpudetect.c	2013-01-31
07:24:14.000000000 +0200
+++ mplayer-export-2013-02-03/cpudetect.c	2013-01-24 14:04:50.000000000 +0200
@@ -46,6 +46,9 @@
 #include <os2.h>
 #elif defined(__AMIGAOS4__)
 #include <proto/exec.h>
+#elif defined(__QNXNTO__) && defined(__X86__)
+#include <x86/cpuinline.h>
+#include <sys/syspage.h>
 #endif

 /* Thanks to the FreeBSD project for some of this cpuid code, and
@@ -216,6 +219,19 @@
     mp_msg(MSGT_CPUDETECT,MSGL_WARN, "Cannot test OS support for SSE,
disabling to be safe.\n" );
     gCpuCaps.hasSSE=0;
 #endif /* _POSIX_SOURCE */
+#elif defined(__QNXNTO__) && defined(__X86__)
+    mp_msg(MSGT_CPUDETECT,MSGL_V, "Testing OS support for SSE... " );
+    if ((__cpu_flags & X86_CPU_SIMD)==X86_CPU_SIMD)
+    {
+        gCpuCaps.hasSSE=1;
+    }
+    mp_msg(MSGT_CPUDETECT,MSGL_V, gCpuCaps.hasSSE ? "yes.\n" : "no!\n" );
+    mp_msg(MSGT_CPUDETECT,MSGL_V, "Testing OS support for SSE2... " );
+    if ((__cpu_flags & X86_CPU_SSE2)==X86_CPU_SSE2)
+    {
+        gCpuCaps.hasSSE2=1;
+    }
+    mp_msg(MSGT_CPUDETECT,MSGL_V, gCpuCaps.hasSSE2 ? "yes.\n" : "no!\n" );
 #else
     /* Do nothing on other platforms for now.
      */
diff -u -r -N mplayer-export-2013-02-03-orig/libao2/ao_qsa.c
mplayer-export-2013-02-03/libao2/ao_qsa.c
--- mplayer-export-2013-02-03-orig/libao2/ao_qsa.c	1970-01-01
02:00:00.000000000 +0200
+++ mplayer-export-2013-02-03/libao2/ao_qsa.c	2013-01-26
19:28:55.000000000 +0200
@@ -0,0 +1,415 @@
+/*
+ * QSA (QNX Sound Architecture) audio output driver
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <sys/neutrino.h>
+#include <sys/asoundlib.h>
+
+#include "mp_msg.h"
+#include "config.h"
+#include "libaf/af_format.h"
+#include "audio_out.h"
+#include "audio_out_internal.h"
+
+static const ao_info_t info =
+{
+    "QSA audio output",
+    "qsa",
+    "Mike Gorchak <mike.gorchak.qnx at gmail.com>",
+    ""
+};
+
+LIBAO_EXTERN(qsa)
+
+snd_pcm_channel_params_t cpars;
+snd_pcm_channel_setup_t  csetup;
+snd_pcm_t* audio_handle=NULL;
+int audio_fd;
+
+static int control(int cmd, void* arg)
+{
+    switch(cmd)
+    {
+        case AOCONTROL_QUERY_FORMAT:
+             return CONTROL_TRUE;
+        case AOCONTROL_SET_DEVICE:
+        case AOCONTROL_GET_DEVICE:
+        case AOCONTROL_GET_VOLUME:
+        case AOCONTROL_SET_VOLUME:
+        case AOCONTROL_SET_PLUGIN_DRIVER:
+        case AOCONTROL_SET_PLUGIN_LIST:
+        default:
+             return CONTROL_UNKNOWN;
+    }
+
+    return CONTROL_UNKNOWN;
+}
+
+static int init(int rate, int channels, int format, int flags)
+{
+    int qsa_format=SND_PCM_SFMT_S16_LE;
+    int frag_multiplier=1;
+    int status;
+    int cardno;
+    int deviceno;
+    int try_again=0;
+
+    mp_msg(MSGT_AO, MSGL_V, "qsa-init: requested format: %d Hz, %d
channels, %x\n",
+        rate, channels, format);
+    mp_msg(MSGT_AO, MSGL_V, "qsa-init: compiled for QSA %s\n",
SND_LIB_VERSION_STR);
+
+    switch(format)
+    {
+        case AF_FORMAT_U8:
+             qsa_format=SND_PCM_SFMT_U8;
+             break;
+        case AF_FORMAT_S8:
+             qsa_format=SND_PCM_SFMT_S8;
+             break;
+        case AF_FORMAT_U16_LE:
+             qsa_format=SND_PCM_SFMT_U16_LE;
+             frag_multiplier=2;
+             break;
+        case AF_FORMAT_U16_BE:
+             qsa_format=SND_PCM_SFMT_U16_BE;
+             frag_multiplier=2;
+             break;
+        case AF_FORMAT_S16_LE:
+             qsa_format=SND_PCM_SFMT_S16_LE;
+             frag_multiplier=2;
+             break;
+        case AF_FORMAT_S16_BE:
+             qsa_format=SND_PCM_SFMT_S16_BE;
+             frag_multiplier=2;
+             break;
+        case AF_FORMAT_U24_LE:
+             qsa_format=SND_PCM_SFMT_U24_LE;
+             frag_multiplier=3;
+             break;
+        case AF_FORMAT_U24_BE:
+             qsa_format=SND_PCM_SFMT_U24_BE;
+             frag_multiplier=3;
+             break;
+        case AF_FORMAT_S24_LE:
+             qsa_format=SND_PCM_SFMT_S24_LE;
+             frag_multiplier=3;
+             break;
+        case AF_FORMAT_S24_BE:
+             qsa_format=SND_PCM_SFMT_S24_BE;
+             frag_multiplier=3;
+             break;
+        case AF_FORMAT_U32_LE:
+             qsa_format=SND_PCM_SFMT_U32_LE;
+             frag_multiplier=4;
+             break;
+        case AF_FORMAT_U32_BE:
+             qsa_format=SND_PCM_SFMT_U32_BE;
+             frag_multiplier=4;
+             break;
+        case AF_FORMAT_S32_LE:
+             qsa_format=SND_PCM_SFMT_S32_LE;
+             frag_multiplier=4;
+             break;
+        case AF_FORMAT_S32_BE:
+             qsa_format=SND_PCM_SFMT_S32_BE;
+             frag_multiplier=4;
+             break;
+        case AF_FORMAT_FLOAT_LE:
+             qsa_format=SND_PCM_SFMT_FLOAT_LE;
+             frag_multiplier=4;
+             break;
+        case AF_FORMAT_FLOAT_BE:
+             qsa_format=SND_PCM_SFMT_FLOAT_BE;
+             frag_multiplier=4;
+             break;
+        case AF_FORMAT_AC3_LE:
+             qsa_format=SND_PCM_SFMT_IEC958_SUBFRAME_LE;
+             frag_multiplier=2;
+             break;
+        case AF_FORMAT_AC3_BE:
+             qsa_format=SND_PCM_SFMT_IEC958_SUBFRAME_BE;
+             frag_multiplier=2;
+             break;
+        case AF_FORMAT_IEC61937_LE:
+             qsa_format=SND_PCM_SFMT_IEC958_SUBFRAME_LE;
+             frag_multiplier=2;
+             break;
+        case AF_FORMAT_IEC61937_BE:
+             qsa_format=SND_PCM_SFMT_IEC958_SUBFRAME_BE;
+             frag_multiplier=2;
+             break;
+        default:
+             qsa_format=SND_PCM_SFMT_S16_LE;
+             frag_multiplier=2;
+             break;
+    }
+
+    memset(&cpars, 0, sizeof(cpars));
+
+    cpars.channel=SND_PCM_CHANNEL_PLAYBACK;
+    cpars.mode=SND_PCM_MODE_BLOCK;
+    cpars.start_mode=SND_PCM_START_DATA;
+    cpars.stop_mode=SND_PCM_STOP_ROLLOVER;
+    cpars.format.format=qsa_format;
+    cpars.format.interleave=1;
+    cpars.format.rate=rate;
+    cpars.format.voices=channels;
+    cpars.buf.block.frag_size=2048*frag_multiplier*channels;
+    cpars.buf.block.frags_min=16;
+    cpars.buf.block.frags_max=32;
+
+    status=snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno,
SND_PCM_OPEN_PLAYBACK);
+
+    /* Check if requested device is opened */
+    if (status<0)
+    {
+        mp_msg(MSGT_AO, MSGL_ERR, "qsa-init: can't open preferred device\n");
+        return 0;
+    }
+
+    /* Disable mmap to control data transfer to the audio device */
+    snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP);
+
+    /* Check if QSA and underlying driver can accept requested parameters */
+    status=snd_pcm_plugin_params(audio_handle, &cpars);
+    if (status<0)
+    {
+        do {
+            if ((format==AF_FORMAT_FLOAT_LE) && (try_again==0))
+            {
+                format=AF_FORMAT_S32_LE;
+                qsa_format=SND_PCM_SFMT_S32_LE;
+                cpars.buf.block.frag_size=8192*4;
+                try_again=1;
+            }
+            if ((format==AF_FORMAT_FLOAT_BE) && (try_again==0))
+            {
+                format=AF_FORMAT_S32_BE;
+                qsa_format=SND_PCM_SFMT_S32_BE;
+                cpars.buf.block.frag_size=8192*4;
+                try_again=1;
+            }
+            if ((format==AF_FORMAT_S32_LE) && (try_again==0))
+            {
+                format=AF_FORMAT_S16_LE;
+                qsa_format=SND_PCM_SFMT_S16_LE;
+                cpars.buf.block.frag_size=8192*2;
+                try_again=1;
+            }
+            if ((format==AF_FORMAT_S32_BE) && (try_again==0))
+            {
+                format=AF_FORMAT_S16_BE;
+                qsa_format=SND_PCM_SFMT_S16_BE;
+                cpars.buf.block.frag_size=8192*2;
+                try_again=1;
+            }
+            if ((channels>=6) && (try_again==0))
+            {
+                channels=4;
+                try_again=1;
+            }
+            if ((channels>=4) && (try_again==0))
+            {
+                channels=2;
+                try_again=1;
+            }
+            if ((channels>=2) && (try_again==0))
+            {
+                channels=1;
+                try_again=1;
+            }
+            if ((rate>=192000) && (try_again==0))
+            {
+                rate=96000;
+                try_again=1;
+            }
+            if ((rate>=96000) && (try_again==0))
+            {
+                rate=48000;
+                try_again=1;
+            }
+            if ((rate>=48000) && (try_again==0))
+            {
+                rate=44100;
+                try_again=1;
+            }
+            if (try_again)
+            {
+                cpars.format.format=qsa_format;
+                cpars.format.voices=channels;
+                cpars.format.rate=rate;
+                status=snd_pcm_plugin_params(audio_handle, &cpars);
+                if (status<0)
+                {
+                    continue;
+                }
+                else
+                {
+                    break;
+                }
+            }
+            else
+            {
+                mp_msg(MSGT_AO, MSGL_ERR, "qsa-init: can't find
compatible sample format\n");
+                return 0;
+            }
+        } while(1);
+    }
+
+    memset(&csetup, 0x00, sizeof(csetup));
+    csetup.channel=SND_PCM_CHANNEL_PLAYBACK;
+
+    status=snd_pcm_plugin_setup(audio_handle, &csetup);
+    if (status<0)
+    {
+        mp_msg(MSGT_AO, MSGL_ERR, "qsa-init: can't setup playback channel\n");
+        return 0;
+    }
+
+    ao_data.samplerate=rate;
+    ao_data.format=format;
+    ao_data.channels=channels;
+    ao_data.bps=(af_fmt2bits(ao_data.format)/8)*ao_data.channels*ao_data.samplerate;
+    ao_data.buffersize=csetup.buf.block.frag_size*csetup.buf.block.frags;
+
+    audio_fd=snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK);
+    if (audio_fd<0)
+    {
+        mp_msg(MSGT_AO, MSGL_ERR, "qsa-init: can't get handle of
playback channel\n");
+        return 0;
+    }
+
+    status=snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK);
+    if (status<0)
+    {
+        mp_msg(MSGT_AO, MSGL_ERR, "qsa-init: can't get prepare
playback channel\n");
+        return 0;
+    }
+
+    mp_msg(MSGT_AO, MSGL_V, "qsa-init: used format: %d Hz, %d channels, %x\n",
+        rate, channels, format);
+
+    return 1;
+}
+
+static void uninit(int immed)
+{
+    snd_pcm_playback_flush(audio_handle);
+    snd_pcm_close(audio_handle);
+}
+
+static void drain(void)
+{
+    snd_pcm_plugin_playback_drain(audio_handle);
+}
+
+static void reset(void)
+{
+    snd_pcm_plugin_playback_drain(audio_handle);
+    snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK);
+}
+
+static void audio_pause(void)
+{
+    snd_pcm_playback_pause(audio_handle);
+}
+
+static void audio_resume(void)
+{
+    snd_pcm_playback_resume(audio_handle);
+}
+
+static int get_space(void)
+{
+    int status;
+    snd_pcm_channel_status_t cstatus;
+
+    memset(&cstatus, 0, sizeof(cstatus));
+    cstatus.channel=SND_PCM_CHANNEL_PLAYBACK;
+
+    status=snd_pcm_plugin_status(audio_handle, &cstatus);
+    if (status<0)
+    {
+        return 0;
+    }
+
+    return cstatus.free;
+}
+
+static int play(void* data, int len, int flags)
+{
+    int written;
+    int status;
+    snd_pcm_channel_status_t cstatus;
+
+    written=snd_pcm_plugin_write(audio_handle, data, len);
+    if (written!=len)
+    {
+        /* Check if samples playback got stuck somewhere in hardware or in */
+        /* the audio device driver */
+        if ((errno==EAGAIN) && (written==0))
+        {
+            return 0;
+        }
+        if ((errno==EINVAL) || (errno==EIO))
+        {
+            memset(&cstatus, 0, sizeof(cstatus));
+            cstatus.channel=SND_PCM_CHANNEL_PLAYBACK;
+            status=snd_pcm_plugin_status(audio_handle, &cstatus);
+            if (status>0)
+            {
+                return 0;
+            }
+            if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
+                (cstatus.status == SND_PCM_STATUS_READY))
+            {
+                status=snd_pcm_plugin_prepare(audio_handle,
SND_PCM_CHANNEL_PLAYBACK);
+                if (status<0)
+                {
+                    return 0;
+                }
+            }
+        }
+    }
+
+    return written;
+}
+
+static float get_delay(void)
+{
+    int status;
+    snd_pcm_channel_status_t cstatus;
+
+    memset(&cstatus, 0, sizeof(cstatus));
+    cstatus.channel=SND_PCM_CHANNEL_PLAYBACK;
+
+    status=snd_pcm_plugin_status(audio_handle, &cstatus);
+    if (status<0)
+    {
+        return (float)ao_data.buffersize/(float)ao_data.bps;
+    }
+
+    return (float)cstatus.count/(float)ao_data.bps;
+}
diff -u -r -N mplayer-export-2013-02-03-orig/libao2/audio_out.c
mplayer-export-2013-02-03/libao2/audio_out.c
--- mplayer-export-2013-02-03-orig/libao2/audio_out.c	2013-01-31
07:24:06.000000000 +0200
+++ mplayer-export-2013-02-03/libao2/audio_out.c	2013-02-03
15:01:58.000000000 +0200
@@ -40,6 +40,7 @@
 extern const ao_functions_t audio_out_openal;
 extern const ao_functions_t audio_out_null;
 extern const ao_functions_t audio_out_alsa;
+extern const ao_functions_t audio_out_qsa;
 extern const ao_functions_t audio_out_nas;
 extern const ao_functions_t audio_out_sdl;
 extern const ao_functions_t audio_out_sun;
@@ -85,6 +86,9 @@
 #ifdef CONFIG_SUN_AUDIO
         &audio_out_sun,
 #endif
+#ifdef CONFIG_QSA
+        &audio_out_qsa,
+#endif
 // wrappers:
 #ifdef CONFIG_ARTS
         &audio_out_arts,
diff -u -r -N mplayer-export-2013-02-03-orig/libdvdread4/bswap.h
mplayer-export-2013-02-03/libdvdread4/bswap.h
--- mplayer-export-2013-02-03-orig/libdvdread4/bswap.h	2013-01-31
07:24:56.000000000 +0200
+++ mplayer-export-2013-02-03/libdvdread4/bswap.h	2013-02-03
15:03:30.000000000 +0200
@@ -92,6 +92,12 @@
       (((x) & 0x000000000000ff00ULL) << 40) | \
       (((x) & 0x00000000000000ffULL) << 56))

+#elif defined(__QNXNTO__)
+#include <gulliver.h>
+#define B2N_16(x) x = ENDIAN_SWAP16(x)
+#define B2N_32(x) x = ENDIAN_SWAP32(x)
+#define B2N_64(x) x = ENDIAN_SWAP64(x)
+
 #else

 /* If there isn't a header provided with your system with this functionality
diff -u -r -N mplayer-export-2013-02-03-orig/libmpcodecs/vf_pp7.c
mplayer-export-2013-02-03/libmpcodecs/vf_pp7.c
--- mplayer-export-2013-02-03-orig/libmpcodecs/vf_pp7.c	2013-01-31
07:24:01.000000000 +0200
+++ mplayer-export-2013-02-03/libmpcodecs/vf_pp7.c	2013-02-03
15:13:00.000000000 +0200
@@ -44,7 +44,9 @@
 #define XMIN(a,b) ((a) < (b) ? (a) : (b))
 #define XMAX(a,b) ((a) > (b) ? (a) : (b))

+#if !defined(__QNXNTO__)
 typedef short int16_t;
+#endif /* __QNXNTO__ */

 //===========================================================================//
 static const uint8_t  __attribute__((aligned(8))) dither[8][8]={
diff -u -r -N mplayer-export-2013-02-03-orig/libvo/video_out.c
mplayer-export-2013-02-03/libvo/video_out.c
--- mplayer-export-2013-02-03-orig/libvo/video_out.c	2013-01-31
07:24:16.000000000 +0200
+++ mplayer-export-2013-02-03/libvo/video_out.c	2013-02-03
15:04:44.000000000 +0200
@@ -136,6 +136,7 @@
 extern const vo_functions_t video_out_pnm;
 extern const vo_functions_t video_out_md5sum;
 extern const vo_functions_t video_out_mng;
+extern const vo_functions_t video_out_photon;

 /* The following declarations are _not_ const because functions pointers
  * get overloaded during (re)initialization. */
@@ -254,6 +255,9 @@
 #ifdef CONFIG_VESA
         &video_out_vesa,
 #endif
+#ifdef CONFIG_PHOTON
+        &video_out_photon,
+#endif
 #ifdef CONFIG_DIRECTFB
         &video_out_directfb,
         &video_out_dfbmga,
diff -u -r -N mplayer-export-2013-02-03-orig/libvo/vo_photon.c
mplayer-export-2013-02-03/libvo/vo_photon.c
--- mplayer-export-2013-02-03-orig/libvo/vo_photon.c	1970-01-01
02:00:00.000000000 +0200
+++ mplayer-export-2013-02-03/libvo/vo_photon.c	2013-02-03
18:44:25.000000000 +0200
@@ -0,0 +1,1460 @@
+/*
+ * Copyright (C) 2013 Mike Gorchak <mike.gorchak.qnx at gmail.com>
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer 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.
+ *
+ * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <Ph.h>
+#include <Pt.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "mp_fifo.h"
+#include "help_mp.h"
+#include "aspect.h"
+#include "sub/sub.h"
+#include "fastmemcpy.h"
+#include "osdep/keycodes.h"
+#include "input/input.h"
+#include "input/mouse.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+
+static const vo_info_t info =
+{
+	"Photon YUV/BGR renderer",
+	"photon",
+	"Mike Gorchak <mike.gorchak.qnx at gmail.com>",
+	""
+};
+
+const LIBVO_EXTERN(photon)
+
+int phwindow_ontop=VO_FALSE;
+int phwindow_fullscreen=VO_FALSE;
+int phwindow_fullscreen_set=VO_TRUE;
+
+int         phinited=0;
+PtWidget_t* phwindow=NULL;
+PtWidget_t* phoscontainer=NULL;
+PtWidget_t* phrawcontainer=NULL;
+
+#define PHW_WINDOW_CHANGE_POSITION    0x00000001
+#define PHW_WINDOW_CHANGE_SIZE        0x00000002
+#define PHW_WINDOW_EXIT_REQUESTED     0x00000004
+#define PHW_WINDOW_MAXIMIZE_EVENT     0x00000008
+
+unsigned int phwindow_event_flags;
+PhDim_t      phwindow_dimension;
+PhDim_t      phwindow_old_dimension;
+PhPoint_t    phwindow_position;
+PhPoint_t    phwindow_old_position;
+PhDim_t      phwindow_fs_dimension;
+PhPoint_t    phwindow_fs_position;
+
+unsigned long photon_display_format;
+int photon_mplayer_format;
+int photon_format_idx=0;
+int photon_screen_width;
+int photon_screen_height;
+int photon_video_width;
+int photon_video_height;
+int photon_target_video_pos_x;
+int photon_target_video_pos_y;
+int photon_target_video_width;
+int photon_target_video_height;
+int photon_source_video_pos_x;
+int photon_source_video_pos_y;
+int photon_source_video_width;
+int photon_source_video_height;
+
+#define PHRENDER_USE_NONE        -1
+#define PHRENDER_USE_LAYER        0
+#define PHRENDER_USE_OFFSCREEN    1
+#define PHRENDER_USE_SWOFFSCREEN  2
+
+int                   phrender_type=PHRENDER_USE_NONE;
+int                   ph_image_current=0;
+PdOffscreenContext_t* ph_image_off=NULL;
+PdOffscreenContext_t* ph_image_off2=NULL;
+void*                 ph_surface_data=NULL;
+void*                 ph_surface_data2=NULL;
+int                   ph_surface_width;
+int                   ph_surface_height;
+int                   ph_surface_pitch;
+PhPoint_t             ph_position;
+PhRect_t              ph_src_rect;
+PhRect_t              ph_dst_rect;
+unsigned long         ph_chroma_color;
+
+static void photon_configure_layer(void);
+
+static int draw_slice(uint8_t *image[], int stride[], int w, int h,
int x, int y)
+{
+    /* YV12 interface is not supported */
+    return -1;
+}
+
+static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
+                       unsigned char *srca, int stride)
+{
+    switch (photon_mplayer_format)
+    {
+        case IMGFMT_YUY2:
+        case IMGFMT_YVYU:
+             if (ph_image_current==0)
+             {
+                 vo_draw_alpha_yuy2(w, h, src, srca, stride,
((uint8_t *)ph_surface_data) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             else
+             {
+                 vo_draw_alpha_yuy2(w, h, src, srca, stride,
((uint8_t *)ph_surface_data2) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             break;
+        case IMGFMT_UYVY:
+        case IMGFMT_V422:
+             if (ph_image_current==0)
+             {
+                 vo_draw_alpha_uyvy(w, h, src, srca, stride,
((uint8_t *)ph_surface_data) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             else
+             {
+                 vo_draw_alpha_uyvy(w, h, src, srca, stride,
((uint8_t *)ph_surface_data2) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             break;
+        case IMGFMT_BGR15:
+             if (ph_image_current==0)
+             {
+                 vo_draw_alpha_rgb15(w, h, src, srca, stride,
((uint8_t *)ph_surface_data) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             else
+             {
+                 vo_draw_alpha_rgb15(w, h, src, srca, stride,
((uint8_t *)ph_surface_data2) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             break;
+        case IMGFMT_BGR16:
+             if (ph_image_current==0)
+             {
+                 vo_draw_alpha_rgb16(w, h, src, srca, stride,
((uint8_t *)ph_surface_data) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             else
+             {
+                 vo_draw_alpha_rgb16(w, h, src, srca, stride,
((uint8_t *)ph_surface_data2) +
+                     ph_surface_pitch * y0 + 2 * x0, ph_surface_pitch);
+             }
+             break;
+        case IMGFMT_BGR24:
+             if (ph_image_current==0)
+             {
+                 vo_draw_alpha_rgb24(w, h, src, srca, stride,
((uint8_t *)ph_surface_data) +
+                     ph_surface_pitch * y0 + 4 * x0, ph_surface_pitch);
+             }
+             else
+             {
+                 vo_draw_alpha_rgb24(w, h, src, srca, stride,
((uint8_t *)ph_surface_data2) +
+                     ph_surface_pitch * y0 + 4 * x0, ph_surface_pitch);
+             }
+             break;
+        case IMGFMT_BGR32:
+             if (ph_image_current==0)
+             {
+                 vo_draw_alpha_rgb32(w, h, src, srca, stride,
((uint8_t *)ph_surface_data) +
+                     ph_surface_pitch * y0 + 4 * x0, ph_surface_pitch);
+             }
+             else
+             {
+                 vo_draw_alpha_rgb32(w, h, src, srca, stride,
((uint8_t *)ph_surface_data2) +
+                     ph_surface_pitch * y0 + 4 * x0, ph_surface_pitch);
+             }
+             break;
+    }
+}
+
+static void draw_osd(void)
+{
+    vo_draw_text(photon_video_width, photon_video_height, draw_alpha);
+}
+
+static void ph_raw_draw_image(PtWidget_t* widget, PhTile_t* damage)
+{
+    PhRect_t ph_window_rect;
+
+    ph_window_rect.ul.x=0;
+    ph_window_rect.ul.y=0;
+    ph_window_rect.lr.x=vo_dwidth-1;
+    ph_window_rect.lr.y=vo_dheight-1;
+    if (phrender_type==PHRENDER_USE_LAYER)
+    {
+        PgSetFillColor(ph_chroma_color);
+    }
+    else
+    {
+        PgSetFillColor(PgRGB(0x00, 0x00, 0x00));
+    }
+    PgDrawRect(&ph_window_rect, Pg_DRAW_FILL);
+
+    if (phrender_type!=PHRENDER_USE_LAYER)
+    {
+        PgContextBlit(ph_image_off, &ph_src_rect, PhDCGetCurrent(),
&ph_dst_rect);
+        if (vo_vsync)
+        {
+            PgWaitVSync();
+        }
+        PgFlush();
+    }
+}
+
+static void flip_page(void)
+{
+    switch (phrender_type)
+    {
+        case PHRENDER_USE_OFFSCREEN:
+        case PHRENDER_USE_SWOFFSCREEN:
+             {
+                 PtDamageWidget(phrawcontainer);
+                 PtFlush();
+             }
+             break;
+        case PHRENDER_USE_LAYER:
+             {
+                 ph_image_current=!ph_image_current;
+                 photon_configure_layer();
+                 PtDamageWidget(phrawcontainer);
+                 PtFlush();
+                 PgWaitVSync();
+             }
+             break;
+    }
+}
+
+static int draw_frame(uint8_t *src[])
+{
+    /* Old interface is not supported */
+    return -1;
+}
+
+typedef struct _layer_mp_map
+{
+    unsigned int layer_id;
+    unsigned int mp_id;
+    unsigned int format_idx;
+    unsigned int found;
+} layer_mp_map_t;
+
+layer_mp_map_t photon_layer_map[]=
+{
+    {Pg_LAYER_FORMAT_ARGB1555, IMGFMT_BGR15, 0, 0},
+    {Pg_LAYER_FORMAT_RGB565,   IMGFMT_BGR16, 0, 0},
+    {Pg_LAYER_FORMAT_RGB888,   IMGFMT_BGR24, 0, 0},
+    {Pg_LAYER_FORMAT_ARGB8888, IMGFMT_BGR32, 0, 0},
+    {Pg_LAYER_FORMAT_YUY2,     IMGFMT_YUY2,  0, 0},
+    {Pg_LAYER_FORMAT_YUY2,     IMGFMT_YUNV,  0, 0},
+    {Pg_LAYER_FORMAT_UYVY,     IMGFMT_UYVY,  0, 0},
+    {Pg_LAYER_FORMAT_UYVY,     IMGFMT_UYNV,  0, 0},
+    {Pg_LAYER_FORMAT_YVYU,     IMGFMT_YVYU,  0, 0},
+    {Pg_LAYER_FORMAT_V422,     IMGFMT_V422,  0, 0},
+    {0,                        0,            0, 0},
+};
+
+static int query_format(uint32_t format)
+{
+    if (phrender_type==PHRENDER_USE_LAYER)
+    {
+        int it=0;
+
+        do {
+            if ((photon_layer_map[it].layer_id==0) &&
(photon_layer_map[it].mp_id==0))
+            {
+                return 0;
+            }
+            if ((photon_layer_map[it].mp_id==format) &&
(photon_layer_map[it].found))
+            {
+                return VFCAP_CSP_SUPPORTED |
VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD |
+                       VFCAP_ACCEPT_STRIDE | VFCAP_FLIP | VFCAP_HWSCALE_UP |
+                       VFCAP_HWSCALE_DOWN | VOCAP_NOSLICES |
VFCAP_EOSD | VFCAP_EOSD_UNSCALED;
+            }
+            it++;
+        } while(1);
+    }
+    else
+    {
+        switch(format)
+        {
+            case IMGFMT_BGR15:
+            case IMGFMT_BGR16:
+            case IMGFMT_BGR24:
+            case IMGFMT_BGR32:
+                 if (((photon_display_format==Pg_IMAGE_DIRECT_565) &&
(format==IMGFMT_BGR16)) ||
+                     ((photon_display_format==Pg_IMAGE_DIRECT_1555)
&& (format==IMGFMT_BGR15)) ||
+                     ((photon_display_format==Pg_IMAGE_DIRECT_888) &&
(format==IMGFMT_BGR24)) ||
+                     ((photon_display_format==Pg_IMAGE_DIRECT_8888)
&& (format==IMGFMT_BGR32)))
+                 {
+                     return VFCAP_CSP_SUPPORTED |
VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD |
+                            VFCAP_ACCEPT_STRIDE | VFCAP_FLIP |
VFCAP_SWSCALE | VFCAP_HWSCALE_UP |
+                            VFCAP_HWSCALE_DOWN | VOCAP_NOSLICES |
VFCAP_EOSD | VFCAP_EOSD_UNSCALED;
+                 }
+                 else
+                 {
+                     return VFCAP_CSP_SUPPORTED | VFCAP_OSD |
VFCAP_ACCEPT_STRIDE | VFCAP_FLIP |
+                            VFCAP_SWSCALE | VOCAP_NOSLICES |
VFCAP_EOSD | VFCAP_EOSD_UNSCALED;
+
+                 }
+        }
+
+        return 0;
+    }
+}
+
+typedef struct _photon_mp_keydef
+{
+    int photon_key;
+    int mp_key;
+} photon_mp_keydef_t;
+
+photon_mp_keydef_t photon_keymap[]=
+{
+    {Pk_Tab,       KEY_TAB      },
+    {Pk_Return,    KEY_ENTER    },
+    {Pk_BackSpace, KEY_BACKSPACE},
+    {Pk_Delete,    KEY_DELETE   },
+    {Pk_Insert,    KEY_INSERT   },
+    {Pk_Home,      KEY_HOME     },
+    {Pk_End,       KEY_END      },
+    {Pk_Pg_Up,     KEY_PAGE_UP  },
+    {Pk_Pg_Down,   KEY_PAGE_DOWN},
+    {Pk_Escape,    KEY_ESC      },
+    {Pk_Right,     KEY_RIGHT    },
+    {Pk_Left,      KEY_LEFT     },
+    {Pk_Down,      KEY_DOWN     },
+    {Pk_Up,        KEY_UP       },
+    {Pk_Control_L, KEY_CTRL     },
+    {Pk_Control_R, KEY_CTRL     },
+    {Pk_F1,        KEY_F+1      },
+    {Pk_F2,        KEY_F+2      },
+    {Pk_F3,        KEY_F+3      },
+    {Pk_F4,        KEY_F+4      },
+    {Pk_F5,        KEY_F+5      },
+    {Pk_F6,        KEY_F+6      },
+    {Pk_F7,        KEY_F+7      },
+    {Pk_F8,        KEY_F+8      },
+    {Pk_F9,        KEY_F+9      },
+    {Pk_F10,       KEY_F+10     },
+    {Pk_F11,       KEY_F+11     },
+    {Pk_F12,       KEY_F+12     },
+    {Pk_KP_0,      KEY_KP0      },
+    {Pk_KP_1,      KEY_KP1      },
+    {Pk_KP_2,      KEY_KP2      },
+    {Pk_KP_3,      KEY_KP3      },
+    {Pk_KP_4,      KEY_KP4      },
+    {Pk_KP_5,      KEY_KP5      },
+    {Pk_KP_6,      KEY_KP6      },
+    {Pk_KP_7,      KEY_KP7      },
+    {Pk_KP_8,      KEY_KP8      },
+    {Pk_KP_9,      KEY_KP9      },
+    {Pk_KP_Enter,  KEY_KPENTER  },
+    {0,            0            },
+};
+
+static int phwindow_callback(PtWidget_t* widget, void* data,
PtCallbackInfo_t* info)
+{
+    switch (info->event->type)
+    {
+        case Ph_EV_KEY:
+             {
+                  PhKeyEvent_t* keyevent=NULL;
+
+                  keyevent=PhGetData(info->event);
+                  if (keyevent==NULL)
+                  {
+                      break;
+                  }
+
+                  /* Check if key has been translated to the symbol */
+                  if ((keyevent->key_flags & Pk_KF_Sym_Valid)==Pk_KF_Sym_Valid)
+                  {
+                      int it=0;
+                      int found=0;
+
+                      do {
+                          if ((photon_keymap[it].photon_key==0) &&
(photon_keymap[it].mp_key==0))
+                          {
+                              break;
+                          }
+                          if (photon_keymap[it].photon_key==keyevent->key_sym)
+                          {
+                              mplayer_put_key(photon_keymap[it].mp_key);
+                              found=1;
+                              break;
+                          }
+                          it++;
+                      } while(1);
+                      if (!found)
+                      {
+                          if (keyevent->key_sym<0x0100)
+                          {
+                              mplayer_put_key(keyevent->key_sym);
+                          }
+                      }
+                  }
+              }
+              break;
+         case Ph_EV_BUT_PRESS:
+              {
+                  PhPointerEvent_t* ptrevent=NULL;
+
+                  ptrevent=PhGetData(info->event);
+                  if (ptrevent==NULL)
+                  {
+                      break;
+                  }
+
+                  if (ptrevent->buttons & Ph_BUTTON_SELECT)
+                  {
+                      mplayer_put_key(MOUSE_BTN0 | MP_KEY_DOWN);
+                  }
+
+                  if (ptrevent->buttons & Ph_BUTTON_MENU)
+                  {
+                      mplayer_put_key(MOUSE_BTN1 | MP_KEY_DOWN);
+                  }
+
+                  if (ptrevent->buttons & Ph_BUTTON_ADJUST)
+                  {
+                      mplayer_put_key(MOUSE_BTN2 | MP_KEY_DOWN);
+                  }
+              }
+              break;
+         case Ph_EV_BUT_RELEASE:
+              {
+                  PhPointerEvent_t* ptrevent=NULL;
+
+                  ptrevent=PhGetData(info->event);
+                  if (ptrevent==NULL)
+                  {
+                      break;
+                  }
+
+                  if (ptrevent->buttons & Ph_BUTTON_SELECT)
+                  {
+                      mplayer_put_key(MOUSE_BTN0);
+                  }
+
+                  if (ptrevent->buttons & Ph_BUTTON_MENU)
+                  {
+                      mplayer_put_key(MOUSE_BTN1);
+                  }
+
+                  if (ptrevent->buttons & Ph_BUTTON_ADJUST)
+                  {
+                      mplayer_put_key(MOUSE_BTN2);
+                  }
+              }
+              break;
+         case Ph_EV_PTR_MOTION_BUTTON:
+         case Ph_EV_PTR_MOTION_NOBUTTON:
+              {
+                  PhPointerEvent_t* ptrevent=NULL;
+                  short x;
+                  short y;
+
+                  ptrevent=PhGetData(info->event);
+                  if (ptrevent==NULL)
+                  {
+                      break;
+                  }
+
+                  PtGetAbsPosition(phrawcontainer, &x, &y);
+                  x=ptrevent->pos.x-x;
+                  y=ptrevent->pos.y-y;
+
+                  vo_mouse_movement(x, y);
+              }
+              break;
+    }
+
+    return Pt_CONTINUE;
+}
+
+static void photon_configure_layer(void)
+{
+    PhArea_t source_viewport;
+    PhArea_t destination_viewport;
+    PgChroma_t chroma_key;
+    short x;
+    short y;
+    int active=1;
+    unsigned int filter=Pg_LAYER_FILTER;
+    PhRect_t workspace_rect;
+
+    PhWindowQueryVisible(Ph_QUERY_WORKSPACE, 0, PhInputGroup(NULL),
&workspace_rect);
+    PtGetAbsPosition(phrawcontainer, &x , &y);
+    x-=workspace_rect.ul.x;
+    y-=workspace_rect.ul.y;
+
+    PgSetLayerArg(1, Pg_LAYER_ARG_LIST_BEGIN, 0, 0);
+    PgSetLayerArg(1, Pg_LAYER_ARG_FORMAT_INDEX, &photon_format_idx,
sizeof(int));
+    if (ph_image_current==0)
+    {
+        PgSetLayerSurface(1, 0, ph_image_off2);
+    }
+    else
+    {
+        PgSetLayerSurface(1, 0, ph_image_off);
+    }
+    chroma_key.op=Pg_CHROMA_DEST_MATCH | Pg_CHROMA_DRAW | Pg_ENABLE_CHROMA;
+    chroma_key.color=ph_chroma_color;
+    PgSetLayerArg(1, Pg_LAYER_ARG_CHROMA, &chroma_key, sizeof(chroma_key));
+    PgSetLayerArg(1, Pg_LAYER_ARG_FILTER_MODE, &filter, sizeof(filter));
+    PgSetLayerArg(1, Pg_LAYER_ARG_ACTIVE, &active, sizeof(active));
+    source_viewport.pos.x=ph_src_rect.ul.x;
+    source_viewport.pos.y=ph_src_rect.ul.y;
+    source_viewport.size.w=(ph_src_rect.lr.x-ph_src_rect.ul.x+1);
+    source_viewport.size.h=(ph_src_rect.lr.y-ph_src_rect.ul.y+1);
+    PgSetLayerArg(1, Pg_LAYER_ARG_SRC_VIEWPORT, &source_viewport,
sizeof(source_viewport));
+    destination_viewport.pos.x=ph_dst_rect.ul.x+x;
+    destination_viewport.pos.y=ph_dst_rect.ul.y+y;
+    destination_viewport.size.w=ph_dst_rect.lr.x-ph_dst_rect.ul.x+1;
+    destination_viewport.size.h=ph_dst_rect.lr.y-ph_dst_rect.ul.y+1;
+    PgSetLayerArg(1, Pg_LAYER_ARG_DST_VIEWPORT,
&destination_viewport, sizeof(destination_viewport));
+    PgSetLayerArg(1, Pg_LAYER_ARG_LIST_END, 0, 0);
+}
+
+static int create_window(char* title, int width, int height)
+{
+    PtArg_t         winargs[64];
+    uint32_t        winargc=0;
+    int32_t         status;
+    PhDim_t         temp_dim={width, height};
+    PhDim_t         temp_dim2={128, 64};
+    PhPoint_t       temp_pos={vo_dx, vo_dy};
+    PtRawCallback_t raw_cb;
+
+    PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_TITLE, title, strlen(title));
+    PtSetArg(&winargs[winargc++], Pt_ARG_BASIC_FLAGS, Pt_TRUE,
Pt_BASIC_PREVENT_FILL);
+    PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE,
+             Ph_WM_APP_DEF_MANAGED | Ph_WM_RESIZE | Ph_WM_CLOSE);
+    PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE,
+             Ph_WM_BACKDROP | Ph_WM_TOFRONT | Ph_WM_COLLAPSE | Ph_WM_FFRONT |
+             Ph_WM_HELP | Ph_WM_HIDE |  Ph_WM_MOVE |
+             Ph_WM_MENU | Ph_WM_RESTORE | Ph_WM_TASKBAR |
+             Ph_WM_TOBACK | Ph_WM_MAX | Ph_WM_FOCUS);
+    PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_FALSE,
+             Ph_WM_HELP);
+    PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
+             Ph_WM_COLLAPSE | Ph_WM_FOCUS | Ph_WM_MAX | Ph_WM_CLOSE |
+             Ph_WM_MOVE | Ph_WM_RESIZE | Ph_WM_RESTORE | Ph_WM_HIDE);
+    if (vo_border)
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE,
+                 Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_MENU | Ph_WM_RENDER_MIN |
+                 Ph_WM_RENDER_TITLE | Ph_WM_RENDER_MOVE | Ph_WM_RENDER_ASAPP |
+                 Ph_WM_RENDER_MAX | Ph_WM_RENDER_BORDER);
+    }
+    else
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE,
+                 Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_MENU | Ph_WM_RENDER_MIN |
+                 Ph_WM_RENDER_TITLE | Ph_WM_RENDER_MOVE | Ph_WM_RENDER_ASAPP |
+                 Ph_WM_RENDER_MAX);
+        PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE,
+                 Ph_WM_RENDER_BORDER);
+    }
+    if ((vo_dx!=INT_MAX) && (vo_dy!=INT_MAX))
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_POS, &temp_pos, 0);
+    }
+    PtSetArg(&winargs[winargc++], Pt_ARG_DIM, &temp_dim, 0);
+    PtSetArg(&winargs[winargc++], Pt_ARG_MINIMUM_DIM, &temp_dim2, 0);
+
+    raw_cb.event_mask=Ph_EV_KEY;
+    raw_cb.event_f=phwindow_callback;
+    raw_cb.data=(void*)NULL;
+    PtSetArg(&winargs[winargc++], Pt_CB_RAW, &raw_cb, 0);
+
+    if (vo_ontop)
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_STATE, Pt_TRUE,
Ph_WM_STATE_ISFRONT);
+    }
+    else
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_STATE, Pt_FALSE,
Ph_WM_STATE_ISFRONT);
+    }
+
+    /* Finally create the window */
+    phwindow=PtCreateWidget(PtWindow, Pt_NO_PARENT, winargc, winargs);
+    if (phwindow==NULL)
+    {
+        return -1;
+    }
+
+    /* Create PtOSContainer widget for flicker-free updating */
+    winargc=0;
+    PtSetArg(&winargs[winargc++], Pt_ARG_DIM, &temp_dim, 0);
+    if (phrender_type==PHRENDER_USE_LAYER)
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_FILL_COLOR, ph_chroma_color, 0);
+    }
+    else
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_FILL_COLOR, PgRGB(0x00,
0x00, 0x00), 0);
+    }
+
+    /* Create the PtOSContainer widget */
+    phoscontainer=PtCreateWidget(PtOSContainer, phwindow, winargc, winargs);
+    if (phoscontainer==NULL)
+    {
+        return -1;
+    }
+
+    /* Create PtRaw widget as main container */
+    winargc=0;
+    PtSetArg(&winargs[winargc++], Pt_ARG_DIM, &temp_dim, 0);
+    if (phrender_type==PHRENDER_USE_LAYER)
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_FILL_COLOR, ph_chroma_color, 0);
+    }
+    else
+    {
+        PtSetArg(&winargs[winargc++], Pt_ARG_FILL_COLOR, PgRGB(0x00,
0x00, 0x00), 0);
+    }
+    PtSetArg(&winargs[winargc++], Pt_ARG_RAW_DRAW_F, ph_raw_draw_image, 0);
+
+    /* Create the PtRaw widget */
+    phrawcontainer=PtCreateWidget(PtRaw, phoscontainer, winargc, winargs);
+    if (phrawcontainer==NULL)
+    {
+        return -1;
+    }
+
+    /* Show widget */
+    status=PtRealizeWidget(phwindow);
+    if (status!=0)
+    {
+        PtDestroyWidget(phwindow);
+    }
+
+    /* Flush all widget operations */
+    PtFlush();
+}
+
+static int config(uint32_t width, uint32_t height, uint32_t d_width,
uint32_t d_height, uint32_t flags, char* title, uint32_t format)
+{
+    PhRect_t workspace_rect;
+
+    panscan_init();
+
+    /* Update window size */
+    phwindow_event_flags|=PHW_WINDOW_CHANGE_SIZE;
+
+    vo_dwidth=d_width;
+    vo_dheight=d_height;
+    phwindow_dimension.w=d_width;
+    phwindow_dimension.h=d_height;
+    phwindow_position.x=vo_dx;
+    phwindow_position.y=vo_dy;
+    photon_video_width=width;
+    photon_video_height=height;
+    photon_mplayer_format=format;
+
+    aspect_save_orig(width, height);
+    aspect_save_prescale(d_width, d_height);
+    aspect_save_screenres(vo_screenwidth, vo_screenheight);
+    geometry(&vo_dx, &vo_dy, &vo_dwidth, &vo_dheight, vo_screenwidth,
vo_screenheight);
+
+    /* Make sure our window will not be larger than a desktop resolution */
+    PhWindowQueryVisible(Ph_QUERY_WORKSPACE, 0, PhInputGroup(NULL),
&workspace_rect);
+    if (vo_dwidth>(workspace_rect.lr.x-workspace_rect.ul.x))
+    {
+        vo_dx=workspace_rect.ul.x;
+        vo_dy=workspace_rect.ul.y;
+        vo_dwidth=(workspace_rect.lr.x-workspace_rect.ul.x)-12;
+    }
+    if (vo_dheight>(workspace_rect.lr.y-workspace_rect.ul.y))
+    {
+        vo_dx=workspace_rect.ul.x;
+        vo_dy=workspace_rect.ul.y;
+        vo_dheight=(workspace_rect.lr.y-workspace_rect.ul.y)-12;
+    }
+
+    phwindow_dimension.w=vo_dwidth;
+    phwindow_dimension.h=vo_dheight;
+    phwindow_position.x=vo_dx;
+    phwindow_position.y=vo_dy;
+
+    if (vo_wintitle)
+    {
+        title=vo_wintitle;
+    }
+
+    create_window(title, vo_dwidth, vo_dheight);
+
+    photon_target_video_pos_x=0;
+    photon_target_video_pos_y=0;
+    photon_target_video_width=vo_dwidth;
+    photon_target_video_height=vo_dheight;
+
+    if ((flags & VOFLAG_FULLSCREEN)==VOFLAG_FULLSCREEN)
+    {
+         if (phwindow_fullscreen==VO_TRUE)
+         {
+             phwindow_fullscreen=VO_FALSE;
+         }
+         else
+         {
+             phwindow_fullscreen=VO_TRUE;
+         }
+         phwindow_fullscreen_set=VO_FALSE;
+    }
+
+    /* Try to use a direct layer renderer */
+    if (phrender_type==PHRENDER_USE_LAYER)
+    {
+        int it;
+
+        it=0;
+        do {
+            if ((photon_layer_map[it].layer_id==0) &&
(photon_layer_map[it].mp_id==0))
+            {
+                return 0;
+            }
+            if ((photon_layer_map[it].mp_id==format) &&
(photon_layer_map[it].found))
+            {
+                photon_format_idx=photon_layer_map[it].format_idx;
+                break;
+            }
+            it++;
+        } while(1);
+
+        ph_image_off=PgCreateLayerSurface(1, 0, photon_format_idx,
width, height, Pg_OSC_MEM_PAGE_ALIGN);
+        if (ph_image_off!=NULL)
+        {
+            ph_surface_data=PdGetOffscreenContextPtr(ph_image_off);
+            ph_surface_width=ph_image_off->dim.w;
+            ph_surface_height=ph_image_off->dim.h;
+            ph_surface_pitch=ph_image_off->pitch;
+        }
+        else
+        {
+            phrender_type=PHRENDER_USE_NONE;
+        }
+
+        ph_image_off2=PgCreateLayerSurface(1, 0, photon_format_idx,
width, height, Pg_OSC_MEM_PAGE_ALIGN);
+        if (ph_image_off!=NULL)
+        {
+            ph_surface_data2=PdGetOffscreenContextPtr(ph_image_off2);
+        }
+
+        /* Lock layer modifications by other applications */
+        PgLockLayer(1);
+    }
+
+    /* Try to use an offscreen renderer */
+    if (phrender_type==PHRENDER_USE_NONE)
+    {
+        ph_image_off=PdCreateOffscreenContext(photon_display_format,
width, height,
+            Pg_OSC_MEM_2D_WRITABLE | Pg_OSC_MEM_2D_READABLE |
Pg_OSC_MEM_PAGE_ALIGN);
+        if (ph_image_off!=NULL)
+        {
+            phrender_type=PHRENDER_USE_OFFSCREEN;
+            ph_surface_data=PdGetOffscreenContextPtr(ph_image_off);
+            ph_surface_width=ph_image_off->dim.w;
+            ph_surface_height=ph_image_off->dim.h;
+            ph_surface_pitch=ph_image_off->pitch;
+        }
+    }
+
+    /* Try to use an software offscren renderer */
+    if (phrender_type==PHRENDER_USE_NONE)
+    {
+        ph_image_off=PdCreateOffscreenContext(photon_display_format,
width, height,
+            Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_MEM_SYS_ONLY |
+            Pg_OSC_MEM_HINT_CPU_READ | Pg_OSC_MEM_HINT_CPU_WRITE);
+        if (ph_image_off!=NULL)
+        {
+            phrender_type=PHRENDER_USE_SWOFFSCREEN;
+            ph_surface_data=PdGetOffscreenContextPtr(ph_image_off);
+            ph_surface_width=ph_image_off->dim.w;
+            ph_surface_height=ph_image_off->dim.h;
+            ph_surface_pitch=ph_image_off->pitch;
+        }
+    }
+
+    /* Check if none of three renderers have been created */
+    if (phrender_type==PHRENDER_USE_NONE)
+    {
+        mp_msg(MSGT_VO, MSGL_ERR, "Can't create photon renderer!\n");
+        return -1;
+    }
+
+    if (phrender_type==PHRENDER_USE_LAYER)
+    {
+        photon_configure_layer();
+    }
+
+    switch (phrender_type)
+    {
+        case PHRENDER_USE_OFFSCREEN:
+             mp_msg(MSGT_VO, MSGL_INFO, "vo_photon: using hardware
offscreen (fast)\n");
+             break;
+        case PHRENDER_USE_SWOFFSCREEN:
+             mp_msg(MSGT_VO, MSGL_INFO, "vo_photon: using software
offscreen (slow)\n");
+             break;
+        case PHRENDER_USE_LAYER:
+             mp_msg(MSGT_VO, MSGL_INFO, "vo_photon: using direct
layer access (fastest)\n");
+             break;
+    }
+
+    return 0;
+}
+
+static void uninit(void)
+{
+    int active=0;
+
+    /* Unlock layer modifications */
+    PgUnlockLayer(1);
+
+    /* Disable layer on exit */
+    if (phrender_type==PHRENDER_USE_LAYER)
+    {
+        PgSetLayerArg(1, Pg_LAYER_ARG_LIST_BEGIN, 0, 0);
+        PgSetLayerArg(1, Pg_LAYER_ARG_ACTIVE, &active, sizeof(int));
+        PgSetLayerArg(1, Pg_LAYER_ARG_LIST_END, 0, 0);
+    }
+
+    if (ph_image_off2!=NULL)
+    {
+        PhDCRelease(ph_image_off2);
+        ph_image_off2=NULL;
+    }
+
+    if (ph_image_off!=NULL)
+    {
+        PhDCRelease(ph_image_off);
+        ph_image_off=NULL;
+    }
+
+    PtDestroyWidget(phwindow);
+}
+
+static void handle_phwindow_event(void)
+{
+    uint8_t    eventbuffer[8192];
+    PhEvent_t* event=(PhEvent_t*)eventbuffer;
+    int32_t    status;
+    uint32_t   finish=0;
+
+    do {
+        status=PhEventPeek(event, 8192);
+        switch (status)
+        {
+            case Ph_RESIZE_MSG:
+                 {
+                     mp_msg(MSGT_VO, MSGL_ERR, "Can't get window event\n");
+                     return;
+                 }
+                 break;
+            case Ph_EVENT_MSG:
+                 {
+                     /* Pass event to Widgets Toolkit */
+                     PtEventHandler(event);
+
+                     /* Event is ready */
+                     switch (event->type)
+                     {
+                         case Ph_EV_WM:
+                              {
+                                  PhWindowEvent_t* wmevent=NULL;
+
+                                  /* Get associated event data */
+                                  wmevent=PhGetData(event);
+                                  if (wmevent==NULL)
+                                  {
+                                      break;
+                                  }
+
+                                  switch (wmevent->event_f)
+                                  {
+                                      case Ph_WM_RESIZE:
+                                           {
+
phwindow_event_flags|=PHW_WINDOW_CHANGE_SIZE;
+
phwindow_event_flags|=PHW_WINDOW_CHANGE_POSITION;
+
phwindow_event_flags&=~(PHW_WINDOW_MAXIMIZE_EVENT);
+
phwindow_dimension=wmevent->size;
+                                               phwindow_position=wmevent->pos;
+                                           }
+                                           break;
+                                      case Ph_WM_MAX:
+                                           {
+                                               /* Avoid double
maximize events */
+                                               if
((phwindow_event_flags & PHW_WINDOW_MAXIMIZE_EVENT)==0)
+                                               {
+                                                   PhDim_t* current_size;
+
+                                                   PtFlush();
+
PtGetResource(phwindow, Pt_ARG_DIM, &current_size, 0);
+
+
phwindow_event_flags|=PHW_WINDOW_CHANGE_SIZE;
+
phwindow_event_flags|=PHW_WINDOW_CHANGE_POSITION;
+
phwindow_event_flags|=PHW_WINDOW_MAXIMIZE_EVENT;
+
phwindow_old_dimension=phwindow_dimension;
+
phwindow_old_position=phwindow_position;
+
phwindow_dimension=*current_size;
+                                                   phwindow_position.x=0;
+                                                   phwindow_position.y=0;
+
+
PtSetResource(phwindow, Pt_ARG_WINDOW_STATE, Pt_TRUE,
+                                                       Ph_WM_STATE_ISMAX);
+                                                   PtFlush();
+                                               }
+                                           }
+                                           break;
+                                      case Ph_WM_RESTORE:
+                                           {
+
phwindow_event_flags|=PHW_WINDOW_CHANGE_SIZE;
+
phwindow_event_flags|=PHW_WINDOW_CHANGE_POSITION;
+
phwindow_event_flags&=~(PHW_WINDOW_MAXIMIZE_EVENT);
+
+
phwindow_dimension=phwindow_old_dimension;
+
phwindow_position=phwindow_old_position;
+
+
PtSetResource(phwindow, Pt_ARG_WINDOW_STATE, Pt_FALSE,
+                                                   Ph_WM_STATE_ISMAX);
+                                               PtFlush();
+                                           }
+                                           break;
+                                      case Ph_WM_MOVE:
+                                           {
+                                               PhPoint_t* current_position;
+
+                                               PtFlush();
+
PtGetResource(phwindow, Pt_ARG_POS, &current_position, 0);
+
phwindow_position=*current_position;
+
phwindow_event_flags|=PHW_WINDOW_CHANGE_POSITION;
+
phwindow_event_flags&=~(PHW_WINDOW_MAXIMIZE_EVENT);
+                                           }
+                                           break;
+                                      case Ph_WM_CLOSE:
+                                           {
+
phwindow_event_flags|=PHW_WINDOW_EXIT_REQUESTED;
+                                           }
+                                           break;
+                                  }
+                              }
+                              break;
+                     }
+                 }
+                 break;
+            case 0:
+                 {
+                     /* All events are read */
+                     finish=1;
+                 }
+                 break;
+            case -1:
+                 {
+                     /* Error occured in event reading */
+                     mp_msg(MSGT_VO, MSGL_ERR, "Can't read window event\n");
+                     return;
+                 }
+                 break;
+        }
+
+        if (finish!=0)
+        {
+            break;
+        }
+    } while (1);
+}
+
+static void check_events(void)
+{
+    if ((phwindow_fullscreen) && (!phwindow_fullscreen_set))
+    {
+        struct vo_rect src_rect;
+        struct vo_rect dst_rect;
+        struct vo_rect borders;
+        PhRect_t workspace_rect;
+
+        PhWindowQueryVisible(Ph_QUERY_WORKSPACE, 0,
PhInputGroup(NULL), &workspace_rect);
+        phwindow_fs_dimension.w=photon_screen_width;
+        phwindow_fs_dimension.h=photon_screen_height;
+        phwindow_fs_position.x=workspace_rect.ul.x-5;
+        phwindow_fs_position.y=workspace_rect.ul.y-23;
+        PtSetResource(phwindow, Pt_ARG_POS, &phwindow_fs_position, 0);
+        PtSetResource(phwindow, Pt_ARG_DIM, &phwindow_fs_dimension, 0);
+        PtSetResource(phoscontainer, Pt_ARG_DIM, &phwindow_fs_dimension, 0);
+        PtSetResource(phrawcontainer, Pt_ARG_DIM, &phwindow_fs_dimension, 0);
+        PtSetResource(phoscontainer, Pt_ARG_DIM, &phwindow_fs_dimension, 0);
+        PtSetResource(phwindow, Pt_ARG_DIM, &phwindow_fs_dimension, 0);
+        PtSetResource(phrawcontainer, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0);
+        phwindow_fullscreen_set=VO_TRUE;
+        vo_dwidth=photon_screen_width;
+        vo_dheight=photon_screen_height;
+
+        calc_src_dst_rects(photon_video_width, photon_video_height,
&src_rect, &dst_rect, &borders, NULL);
+
+        photon_source_video_pos_x=src_rect.left;
+        photon_source_video_pos_y=src_rect.top;
+        photon_source_video_width=src_rect.width;
+        photon_source_video_height=src_rect.height;
+
+        photon_target_video_pos_x=dst_rect.left;
+        photon_target_video_pos_y=dst_rect.top;
+        photon_target_video_width=dst_rect.width;
+        photon_target_video_height=dst_rect.height;
+
+        PtDamageWidget(phrawcontainer);
+        PtFlush();
+
+        if (phrender_type==PHRENDER_USE_LAYER)
+        {
+            photon_configure_layer();
+        }
+    }
+
+    if ((!phwindow_fullscreen) && (!phwindow_fullscreen_set))
+    {
+        struct vo_rect src_rect;
+        struct vo_rect dst_rect;
+        struct vo_rect borders;
+
+        PtSetResource(phwindow, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phoscontainer, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phrawcontainer, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phoscontainer, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phwindow, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phwindow, Pt_ARG_POS, &phwindow_position, 0);
+        PtSetResource(phrawcontainer, Pt_ARG_CURSOR_TYPE,
Ph_CURSOR_POINTER, 0);
+        phwindow_fullscreen_set=VO_TRUE;
+        vo_dwidth=phwindow_dimension.w;
+        vo_dheight=phwindow_dimension.h;
+
+        calc_src_dst_rects(photon_video_width, photon_video_height,
&src_rect, &dst_rect, &borders, NULL);
+
+        photon_source_video_pos_x=src_rect.left;
+        photon_source_video_pos_y=src_rect.top;
+        photon_source_video_width=src_rect.width;
+        photon_source_video_height=src_rect.height;
+
+        photon_target_video_pos_x=dst_rect.left;
+        photon_target_video_pos_y=dst_rect.top;
+        photon_target_video_width=dst_rect.width;
+        photon_target_video_height=dst_rect.height;
+
+        PtDamageWidget(phrawcontainer);
+        PtFlush();
+
+        if (phrender_type==PHRENDER_USE_LAYER)
+        {
+            photon_configure_layer();
+        }
+    }
+
+    handle_phwindow_event();
+    if (phwindow_event_flags & PHW_WINDOW_EXIT_REQUESTED)
+    {
+        phwindow_event_flags&=~(PHW_WINDOW_EXIT_REQUESTED);
+        mplayer_put_key(KEY_ESC);
+    }
+    if (phwindow_event_flags & PHW_WINDOW_CHANGE_POSITION)
+    {
+        vo_dx=phwindow_position.x;
+        vo_dy=phwindow_position.y;
+        PtSetResource(phwindow, Pt_ARG_POS, &phwindow_position, 0);
+        PtFlush();
+
+        phwindow_event_flags&=~(PHW_WINDOW_CHANGE_POSITION);
+
+        if (phrender_type==PHRENDER_USE_LAYER)
+        {
+            photon_configure_layer();
+        }
+    }
+    if (phwindow_event_flags & PHW_WINDOW_CHANGE_SIZE)
+    {
+        struct vo_rect src_rect;
+        struct vo_rect dst_rect;
+        struct vo_rect borders;
+
+        vo_dwidth=phwindow_dimension.w;
+        vo_dheight=phwindow_dimension.h;
+
+        calc_src_dst_rects(photon_video_width, photon_video_height,
&src_rect, &dst_rect, &borders, NULL);
+
+        photon_source_video_pos_x=src_rect.left;
+        photon_source_video_pos_y=src_rect.top;
+        photon_source_video_width=src_rect.width;
+        photon_source_video_height=src_rect.height;
+
+        photon_target_video_pos_x=dst_rect.left;
+        photon_target_video_pos_y=dst_rect.top;
+        photon_target_video_width=dst_rect.width;
+        photon_target_video_height=dst_rect.height;
+
+        PtSetResource(phwindow, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phoscontainer, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phrawcontainer, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phoscontainer, Pt_ARG_DIM, &phwindow_dimension, 0);
+        PtSetResource(phwindow, Pt_ARG_DIM, &phwindow_dimension, 0);
+
+        phwindow_event_flags&=~(PHW_WINDOW_CHANGE_SIZE);
+
+        PtDamageWidget(phrawcontainer);
+        PtFlush();
+
+        if (phrender_type==PHRENDER_USE_LAYER)
+        {
+            photon_configure_layer();
+        }
+    }
+}
+
+static int preinit(const char *arg)
+{
+    PdOffscreenContext_t* main_display_ctx=NULL;
+    PhRect_t workspace_rect;
+    int jt;
+
+    /* Initialize Photon */
+    if (!phinited)
+    {
+        if (PtInit(NULL)==-1)
+        {
+            mp_msg(MSGT_VO, MSGL_ERR, "Can't connect to Photon\n");
+            return -1;
+        }
+        phinited=1;
+    }
+
+    /* Clear layer list */
+    jt=0;
+    do {
+        if ((photon_layer_map[jt].layer_id==0) &&
(photon_layer_map[jt].mp_id==0))
+        {
+            break;
+        }
+        photon_layer_map[jt].found=0;
+        photon_layer_map[jt].format_idx=0;
+        jt++;
+    } while(1);
+
+    phrender_type=PHRENDER_USE_NONE;
+
+    /* Get display pixel format for a conversion routines */
+    photon_display_format=Pg_IMAGE_DIRECT_565;
+
+    /* Try to make duplicate of display context */
+    main_display_ctx=PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY);
+    /* Check if underlying driver has full support of layer */
+    if (main_display_ctx!=NULL)
+    {
+        photon_display_format=main_display_ctx->format;
+        photon_screen_width=main_display_ctx->dim.w;
+        photon_screen_height=main_display_ctx->dim.h;
+        PhDCRelease(main_display_ctx);
+    }
+    else
+    {
+        PgDisplaySettings_t mode_settings;
+        PgVideoModeInfo_t   mode_info;
+
+        /* In very rare cases we have to check display format in the video  */
+        /* mode settings. If video mode is not generic, this function fails */
+        if (PgGetVideoMode(&mode_settings)==0)
+        {
+            if (PgGetVideoModeInfo(mode_settings.mode, &mode_info)==0)
+            {
+                photon_display_format=mode_info.type;
+                photon_screen_width=mode_info.width;
+                photon_screen_height=mode_info.height;
+            }
+            else
+            {
+                mp_msg(MSGT_VO, MSGL_ERR, "Can't get display pixel format\n");
+                return -1;
+            }
+        }
+        else
+        {
+            mp_msg(MSGT_VO, MSGL_ERR, "Can't get display pixel format\n");
+            return -1;
+        }
+    }
+
+    /* Query virtual desktop settings */
+    PhWindowQueryVisible(Ph_QUERY_WORKSPACE, 0, PhInputGroup(NULL),
&workspace_rect);
+    xinerama_x=workspace_rect.ul.x;
+    xinerama_y=workspace_rect.ul.y;
+
+    /* Try to use a direct layer renderer */
+    if (phrender_type==PHRENDER_USE_NONE)
+    {
+        PgLayerCaps_t lcaps;
+        int layer_formats=0;
+        int status;
+        int it;
+
+        for (it=0; it<256; it++)
+        {
+            status=PgGetLayerCaps(1, it, &lcaps);
+            if (status==-1)
+            {
+                if (errno==EOPNOTSUPP)
+                {
+                    layer_formats=0;
+                    break;
+                }
+                if (errno==ENXIO)
+                {
+                    layer_formats=0;
+                    break;
+                }
+                if (errno==EINVAL)
+                {
+                    break;
+                }
+            }
+
+            jt=0;
+            do {
+                if ((photon_layer_map[jt].layer_id==0) &&
(photon_layer_map[jt].mp_id==0))
+                {
+                    break;
+                }
+                if (photon_layer_map[jt].layer_id==lcaps.format)
+                {
+                    photon_layer_map[jt].found=1;
+                    photon_layer_map[jt].format_idx=it;
+                    layer_formats++;
+                }
+                jt++;
+            } while(1);
+        }
+
+        if (layer_formats!=0)
+        {
+            int layer_active=0;
+            int status;
+
+            status=PgSetLayerArg(1, Pg_LAYER_ARG_LIST_BEGIN, 0, 0);
+            if (status==0)
+            {
+                status=PgSetLayerArg(1, Pg_LAYER_ARG_ACTIVE,
&layer_active, sizeof(int));
+                if (status==0)
+                {
+                    status=PgSetLayerArg(1, Pg_LAYER_ARG_LIST_END, 0, 0);
+                    if (status==0)
+                    {
+                        phrender_type=PHRENDER_USE_LAYER;
+                    }
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static uint32_t get_image(mp_image_t* mpi)
+{
+    /* Check if it is already has direct rendering flag */
+    if ((mpi->flags & MP_IMGFLAG_DIRECT)==MP_IMGFLAG_DIRECT)
+    {
+        return VO_TRUE;
+    }
+
+    /* video memory reading is very slow operation */
+    if ((mpi->flags & MP_IMGFLAG_READABLE)==MP_IMGFLAG_READABLE)
+    {
+        return VO_FALSE;
+    }
+
+    /* Codec must accept video driver's stride */
+    if ((mpi->flags & MP_IMGFLAG_ACCEPT_STRIDE)!=MP_IMGFLAG_ACCEPT_STRIDE)
+    {
+        return VO_FALSE;
+    }
+
+    if ((mpi->type!=MP_IMGTYPE_STATIC) && (mpi->type!=MP_IMGTYPE_TEMP))
+    {
+        return VO_FALSE;
+    }
+
+    /* Check image size and image pixel format */
+    if ((mpi->imgfmt!=photon_mplayer_format) ||
(photon_video_width!=mpi->width) ||
+        (photon_video_height!=mpi->height))
+    {
+        return VO_FALSE;
+    }
+
+    mpi->flags|=MP_IMGFLAG_DIRECT;
+    if (ph_image_current==0)
+    {
+        mpi->planes[0]=ph_surface_data;
+        mpi->stride[0]=ph_surface_pitch;
+    }
+    else
+    {
+        mpi->planes[0]=ph_surface_data2;
+        mpi->stride[0]=ph_surface_pitch;
+    }
+
+    return VO_TRUE;
+}
+
+static uint32_t put_image(mp_image_t* mpi)
+{
+    switch (phrender_type)
+    {
+        case PHRENDER_USE_LAYER:
+        case PHRENDER_USE_OFFSCREEN:
+        case PHRENDER_USE_SWOFFSCREEN:
+             {
+                 ph_src_rect.ul.x=photon_source_video_pos_x;
+                 ph_src_rect.ul.y=photon_source_video_pos_y;
+
ph_src_rect.lr.x=photon_source_video_pos_x+photon_source_video_width-1;
+
ph_src_rect.lr.y=photon_source_video_pos_y+photon_source_video_height-1;
+
+                 ph_dst_rect.ul.x=photon_target_video_pos_x;
+                 ph_dst_rect.ul.y=photon_target_video_pos_y;
+
ph_dst_rect.lr.x=photon_target_video_pos_x+photon_target_video_width-1;
+
ph_dst_rect.lr.y=photon_target_video_pos_y+photon_target_video_height-1;
+             }
+             break;
+    }
+
+    /* Check if it direct rendering flag, we have nothing todo then */
+    if ((mpi->flags & MP_IMGFLAG_DIRECT)==MP_IMGFLAG_DIRECT)
+    {
+        return VO_TRUE;
+    }
+
+    if (mpi->stride[0]==ph_surface_pitch)
+    {
+        if (ph_image_current==0)
+        {
+            fast_memcpy(ph_surface_data, mpi->planes[0],
+                ph_surface_pitch < mpi->stride[0] ? ph_surface_pitch
: mpi->stride[0]*mpi->height);
+        }
+        else
+        {
+            fast_memcpy(ph_surface_data2, mpi->planes[0],
+                ph_surface_pitch < mpi->stride[0] ? ph_surface_pitch
: mpi->stride[0]*mpi->height);
+        }
+    }
+    else
+    {
+        int it;
+        int pitch=ph_surface_pitch < mpi->stride[0] ?
ph_surface_pitch : mpi->stride[0];
+
+        for (it=0; it<mpi->height; it++)
+        {
+            if (ph_image_current==0)
+            {
+                fast_memcpy(ph_surface_data+it*ph_surface_pitch,
mpi->planes[0]+it*mpi->stride[0], pitch);
+            }
+            else
+            {
+                fast_memcpy(ph_surface_data2+it*ph_surface_pitch,
mpi->planes[0]+it*mpi->stride[0], pitch);
+            }
+        }
+    }
+
+    return VO_TRUE;
+}
+
+static int control(uint32_t request, void* data)
+{
+    switch (request)
+    {
+        case VOCTRL_QUERY_FORMAT:
+             return query_format(*((uint32_t*)data));
+        case VOCTRL_GUI_NOWINDOW:
+             return VO_FALSE;
+        case VOCTRL_GUISUPPORT:
+             return VO_TRUE;
+        case VOCTRL_GET_PANSCAN:
+             return VO_TRUE;
+        case VOCTRL_SET_PANSCAN:
+             phwindow_event_flags|=PHW_WINDOW_CHANGE_SIZE;
+             return VO_TRUE;
+        case VOCTRL_FULLSCREEN:
+             if (phwindow_fullscreen==VO_TRUE)
+             {
+                 phwindow_fullscreen=VO_FALSE;
+             }
+             else
+             {
+                 phwindow_fullscreen=VO_TRUE;
+             }
+             phwindow_fullscreen_set=VO_FALSE;
+             return VO_TRUE;
+        case VOCTRL_GET_IMAGE:
+             return get_image(data);
+        case VOCTRL_DRAW_IMAGE:
+             return put_image(data);
+        case VOCTRL_ONTOP:
+             if (phwindow_ontop==VO_TRUE)
+             {
+                 phwindow_ontop=VO_FALSE;
+             }
+             else
+             {
+                 phwindow_ontop=VO_TRUE;
+             }
+             return VO_TRUE;
+        case VOCTRL_UPDATE_SCREENINFO:
+             vo_screenwidth=photon_screen_width;
+             vo_screenheight=photon_screen_height;
+             switch (photon_display_format)
+             {
+                 case Pg_IMAGE_DIRECT_1555:
+                      vo_depthonscreen=15;
+                      ph_chroma_color=PgRGBA(0x0F, 0x1F, 0x0F, 0x80);
+                      break;
+                 case Pg_IMAGE_DIRECT_565:
+                      vo_depthonscreen=16;
+                      ph_chroma_color=PgRGBA(0x0F, 0x0F, 0x0F, 0x80);
+                      break;
+                 case Pg_IMAGE_DIRECT_888:
+                      vo_depthonscreen=24;
+                      ph_chroma_color=PgRGBA(0x01, 0x02, 0x03, 0x00);
+                      break;
+                 case Pg_IMAGE_DIRECT_8888:
+                      vo_depthonscreen=32;
+                      ph_chroma_color=PgRGBA(0x01, 0x02, 0x03, 0x80);
+                      break;
+             }
+             aspect_save_screenres(vo_screenwidth, vo_screenheight);
+             return VO_TRUE;
+    }
+
+    return VO_NOTIMPL;
+}


More information about the MPlayer-dev-eng mailing list