summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/lib.cpp15
-rw-r--r--noncore/multimedia/opieplayer2/nullvideo.c359
-rw-r--r--noncore/multimedia/opieplayer2/opieplayer2.pro2
-rw-r--r--noncore/multimedia/opieplayer2/xinevideowidget.cpp1
4 files changed, 236 insertions, 141 deletions
diff --git a/noncore/multimedia/opieplayer2/lib.cpp b/noncore/multimedia/opieplayer2/lib.cpp
index 1ab5c96..248221b 100644
--- a/noncore/multimedia/opieplayer2/lib.cpp
+++ b/noncore/multimedia/opieplayer2/lib.cpp
@@ -1,434 +1,435 @@
/*
                This file is part of the Opie Project
              Copyright (c) 2002 Max Reiss <harlekin@handhelds.org>
Copyright (c) 2002 LJP <>
Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "xinevideowidget.h"
#include "frame.h"
#include "lib.h"
/* OPIE */
#include <opie2/odebug.h>
using namespace Opie::Core;
/* QT */
#include <qtextstream.h>
#include <qdir.h>
#include <qgfx_qws.h>
/* STD */
#include <assert.h>
+#include <unistd.h>
typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
int width, int height,int bytes );
extern "C" {
xine_vo_driver_t* init_video_out_plugin( xine_t *xine, void* video, display_xine_frame_t, void * );
int null_is_showing_video( const xine_vo_driver_t* self );
void null_set_show_video( const xine_vo_driver_t* self, int show );
int null_is_fullscreen( const xine_vo_driver_t* self );
void null_set_fullscreen( const xine_vo_driver_t* self, int screen );
int null_is_scaling( const xine_vo_driver_t* self );
void null_set_scaling( const xine_vo_driver_t* self, int scale );
void null_set_gui_width( const xine_vo_driver_t* self, int width );
void null_set_gui_height( const xine_vo_driver_t* self, int height );
void null_set_mode( const xine_vo_driver_t* self, int depth, int rgb );
void null_set_videoGamma( const xine_vo_driver_t* self , int value );
void null_display_handler( const xine_vo_driver_t* self, display_xine_frame_t t, void* user_data );
void null_preload_decoders( xine_stream_t *stream );
}
using namespace XINE;
Lib::Lib( InitializationMode initMode, XineVideoWidget* widget )
{
m_initialized = false;
m_duringInitialization = false;
m_video = false;
m_wid = widget;
printf("Lib");
QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
// get the configuration
// not really OO, should be an extra class, later
if ( !QFile::exists(configPath) ) {
QFile f(configPath);
f.open(IO_WriteOnly);
QTextStream ts( &f );
ts << "misc.memcpy_method:glibc\n";
ts << "# uncomment if you experience double speed audio \n #audio.oss_sync_method:softsync\n";
ts << "codec.ffmpeg_pp_quality:3\n";
ts << "audio.num_buffers:50\n";
ts << "audio.size_buffers:4096\n";
ts << "video.num_buffers:20\n";
ts << "video.size_buffers:4096\n";
ts << "audio.out_num_audio_buf:16\n";
ts << "audio.out_size_audio_buf:8096\n";
ts << "audio.out_size_zero_buf:1024\n";
ts << "audio.passthrough_offset:0\n";
f.close();
}
if ( initMode == InitializeImmediately ) {
initialize();
m_initialized = true;
}
else
start();
}
void Lib::run()
{
- odebug << "Lib::run() started" << oendl;
+ odebug << "Lib::run() started" << oendl;
initialize();
m_initialized = true;
- odebug << "Lib::run() finished" << oendl;
+ odebug << "Lib::run() finished" << oendl;
}
void Lib::initialize()
{
m_duringInitialization = true;
m_xine = xine_new( );
QString configPath = QDir::homeDirPath() + "/Settings/opiexine.cf";
xine_config_load( m_xine, QFile::encodeName( configPath ) );
xine_init( m_xine );
// allocate oss for sound
// and fb for framebuffer
m_audioOutput = xine_open_audio_driver( m_xine, "oss", NULL );
m_videoOutput = ::init_video_out_plugin( m_xine, NULL, xine_display_frame, this );
//xine_open_video_driver( m_xine, NULL, XINE_VISUAL_TYPE_FB, NULL);
// null_display_handler( m_videoOutput, xine_display_frame, this );
m_stream = xine_stream_new (m_xine, m_audioOutput, m_videoOutput );
if (m_wid != 0 ) {
printf( "!0\n" );
setWidget( m_wid );
}
m_queue = xine_event_new_queue (m_stream);
xine_event_create_listener_thread (m_queue, xine_event_handler, this);
- ::null_preload_decoders( m_stream );
+ ::null_preload_decoders( m_stream );
m_duringInitialization = false;
}
Lib::~Lib() {
assert( isRunning() == false );
assert( m_initialized );
// free( m_config );
xine_close( m_stream );
xine_event_dispose_queue( m_queue );
xine_dispose( m_stream );
xine_exit( m_xine );
/* FIXME either free or delete but valgrind bitches against both */
//free( m_videoOutput );
//delete m_audioOutput;
}
void Lib::resize ( const QSize &s ) {
assert( m_initialized || m_duringInitialization );
if ( s. width ( ) && s. height ( ) ) {
::null_set_gui_width( m_videoOutput, s. width() );
::null_set_gui_height( m_videoOutput, s. height() );
}
}
int Lib::majorVersion() {
int major, minor, sub;
xine_get_version ( &major, &minor, &sub );
return major;
}
int Lib::minorVersion() {
int major, minor, sub;
xine_get_version ( &major, &minor, &sub );
return minor;
}
int Lib::subVersion() {
int major, minor, sub;
xine_get_version ( &major, &minor, &sub );
return sub;
}
int Lib::play( const QString& fileName, int startPos, int start_time ) {
assert( m_initialized );
// FIXME actually a hack imho. Should not be needed to dispose the whole stream
// but without we get wrong media length reads from libxine for the second media
//xine_dispose ( m_stream );
QString str = fileName.stripWhiteSpace();
//m_stream = xine_stream_new (m_xine, m_audioOutput, m_videoOutput );
//m_queue = xine_event_new_queue (m_stream);
//xine_event_create_listener_thread (m_queue, xine_event_handler, this);
if ( !xine_open( m_stream, str.utf8().data() ) ) {
return 0;
}
return xine_play( m_stream, startPos, start_time);
}
void Lib::stop() {
assert( m_initialized );
- odebug << "<<<<<<<< STOP IN LIB TRIGGERED >>>>>>>" << oendl;
+ odebug << "<<<<<<<< STOP IN LIB TRIGGERED >>>>>>>" << oendl;
xine_stop( m_stream );
}
void Lib::pause( bool toggle ) {
assert( m_initialized );
xine_set_param( m_stream, XINE_PARAM_SPEED, toggle ? XINE_SPEED_PAUSE : XINE_SPEED_NORMAL );
}
int Lib::speed() const {
assert( m_initialized );
return xine_get_param ( m_stream, XINE_PARAM_SPEED );
}
void Lib::setSpeed( int speed ) {
assert( m_initialized );
xine_set_param ( m_stream, XINE_PARAM_SPEED, speed );
}
int Lib::status() const {
assert( m_initialized );
return xine_get_status( m_stream );
}
int Lib::currentPosition() const {
assert( m_initialized );
int pos, time, length;
xine_get_pos_length( m_stream, &pos, &time, &length );
return pos;
}
int Lib::currentTime() const {
assert( m_initialized );
int pos, time, length;
xine_get_pos_length( m_stream, &pos, &time, &length );
if ( time > 0 ) {
return time/1000;
} else {
return 0;
}
}
int Lib::length() const {
assert( m_initialized );
int pos, time, length;
/* dilb: patch to solve the wrong stream length reported to the GUI*/
int iRetVal=0, iTestLoop=0;
do
{
iRetVal = xine_get_pos_length( m_stream, &pos, &time, &length );
if (iRetVal)
{/* if the function didn't return 0, then pos, time and length are valid.*/
return length/1000;
}
/*don't poll too much*/
usleep(100000);
iTestLoop++;
}
while ( iTestLoop < 10 ); /* if after 1s, we still don't have any
valid stream, then return -1 (this value could be used to make the stream
unseekable, but it should never occur!! Mr. Murphy ? :) ) */
return -1;
}
bool Lib::isSeekable() const {
assert( m_initialized );
return xine_get_stream_info( m_stream, XINE_STREAM_INFO_SEEKABLE );
}
void Lib::seekTo( int time ) {
assert( m_initialized );
//xine_trick_mode ( m_stream, XINE_TRICK_MODE_SEEK_TO_TIME, time ); NOT IMPLEMENTED YET IN XINE :_(
// since its now milliseconds we need *1000
xine_play( m_stream, 0, time*1000 );
}
Frame Lib::currentFrame() const {
assert( m_initialized );
Frame frame;
return frame;
};
QString Lib::metaInfo( int number) const {
assert( m_initialized );
return xine_get_meta_info( m_stream, number );
}
int Lib::error() const {
assert( m_initialized );
return xine_get_error( m_stream );
};
void Lib::ensureInitialized()
{
if ( m_initialized )
return;
- odebug << "waiting for initialization thread to finish" << oendl;
+ odebug << "waiting for initialization thread to finish" << oendl;
wait();
- odebug << "initialization thread finished!" << oendl;
+ odebug << "initialization thread finished!" << oendl;
}
void Lib::setWidget( XineVideoWidget *widget )
{
m_wid = widget;
resize ( m_wid-> size ( ) );
::null_set_mode( m_videoOutput, qt_screen->depth(), qt_screen->pixelType() );
m_wid->repaint();
}
void Lib::receiveMessage( ThreadUtil::ChannelMessage *msg, SendType sendType )
{
assert( sendType == ThreadUtil::Channel::OneWay );
handleXineEvent( msg->type() );
delete msg;
}
void Lib::handleXineEvent( const xine_event_t* t ) {
send( new ThreadUtil::ChannelMessage( t->type ), OneWay );
}
void Lib::handleXineEvent( int type ) {
assert( m_initialized );
if ( type == XINE_EVENT_UI_PLAYBACK_FINISHED ) {
emit stopped();
}
}
void Lib::setShowVideo( bool video ) {
assert( m_initialized );
m_video = video;
::null_set_show_video( m_videoOutput, video );
}
bool Lib::isShowingVideo() const {
assert( m_initialized );
return ::null_is_showing_video( m_videoOutput );
}
bool Lib::hasVideo() const {
assert( m_initialized );
return xine_get_stream_info( m_stream, 18 );
}
void Lib::showVideoFullScreen( bool fullScreen ) {
assert( m_initialized );
::null_set_fullscreen( m_videoOutput, fullScreen );
}
bool Lib::isVideoFullScreen() const {
assert( m_initialized );
return ::null_is_fullscreen( m_videoOutput );
}
void Lib::setScaling( bool scale ) {
assert( m_initialized );
::null_set_scaling( m_videoOutput, scale );
}
void Lib::setGamma( int value ) {
assert( m_initialized );
::null_set_videoGamma( m_videoOutput, value );
}
bool Lib::isScaling() const {
assert( m_initialized );
return ::null_is_scaling( m_videoOutput );
}
void Lib::xine_event_handler( void* user_data, const xine_event_t* t ) {
( (Lib*)user_data)->handleXineEvent( t );
}
void Lib::xine_display_frame( void* user_data, uint8_t *frame,
int width, int height, int bytes ) {
( (Lib*)user_data)->drawFrame( frame, width, height, bytes );
}
void Lib::drawFrame( uint8_t* frame, int width, int height, int bytes ) {
assert( m_initialized );
if ( !m_video ) {
- owarn << "not showing video now" << oendl;
+ owarn << "not showing video now" << oendl;
return;
}
assert( m_wid );
m_wid-> setVideoFrame ( frame, width, height, bytes );
}
diff --git a/noncore/multimedia/opieplayer2/nullvideo.c b/noncore/multimedia/opieplayer2/nullvideo.c
index 378bbd4..6769a37 100644
--- a/noncore/multimedia/opieplayer2/nullvideo.c
+++ b/noncore/multimedia/opieplayer2/nullvideo.c
@@ -1,642 +1,735 @@
/*
                This file is part of the Opie Project
              Copyright (c) 2002 Max Reiss <harlekin@handhelds.org>
Copyright (c) 2002 LJP <>
Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
+ Copyright (c) 2002-2003 Miguel Freitas of xine
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <xine.h>
#include <xine/video_out.h>
#include <xine/xine_internal.h>
//#include <xine/xineutils.h>
#include <xine/vo_scale.h>
#include <xine/buffer.h>
#include <pthread.h>
#include "alphablend.h"
#include "yuv2rgb.h"
#define printf(x,...)
/*
#define LOG
*/
/* the caller for our event draw handler */
typedef void (*display_xine_frame_t) (void *user_data, uint8_t* frame,
int width, int height,int bytes );
typedef struct null_driver_s null_driver_t;
struct null_driver_s {
vo_driver_t vo_driver;
uint32_t m_capabilities;
int m_show_video;
int m_video_fullscreen;
int m_is_scaling;
int depth, bpp, bytes_per_pixel;
int yuv2rgb_mode;
int yuv2rgb_swap;
int yuv2rgb_gamma;
uint8_t *yuv2rgb_cmap;
yuv2rgb_factory_t *yuv2rgb_factory;
vo_overlay_t *overlay;
vo_scale_t sc;
int gui_width;
int gui_height;
int gui_changed;
double display_ratio;
void* caller;
display_xine_frame_t frameDis;
};
typedef struct opie_frame_s opie_frame_t;
struct opie_frame_s {
vo_frame_t frame;
int format;
int flags;
vo_scale_t sc;
uint8_t *chunk[3];
uint8_t *data; /* rgb */
int bytes_per_line;
yuv2rgb_t *yuv2rgb;
uint8_t *rgb_dst;
int yuv_stride;
int stripe_height, stripe_inc;
null_driver_t *output;
};
static uint32_t null_get_capabilities( vo_driver_t *self ){
null_driver_t* this = (null_driver_t*)self;
return this->m_capabilities;
}
-static void null_frame_copy (vo_frame_t *vo_img, uint8_t **src) {
+static void null_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) {
opie_frame_t *frame = (opie_frame_t *) vo_img ;
vo_img->proc_called = 1;
if (!frame->output->m_show_video) {
/* printf("nullvideo: no video\n"); */
return;
}
if (frame->format == XINE_IMGFMT_YV12) {
frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst,
src[0], src[1], src[2]);
} else {
frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst,
src[0]);
}
frame->rgb_dst += frame->stripe_inc;
}
static void null_frame_field (vo_frame_t *vo_img, int which_field) {
opie_frame_t *frame = (opie_frame_t *) vo_img ;
switch (which_field) {
case VO_TOP_FIELD:
frame->rgb_dst = (uint8_t *)frame->data;
frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line;
break;
case VO_BOTTOM_FIELD:
frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ;
frame->stripe_inc = 2*frame->stripe_height * frame->bytes_per_line;
break;
case VO_BOTH_FIELDS:
frame->rgb_dst = (uint8_t *)frame->data;
break;
}
}
/* take care of the frame*/
static void null_frame_dispose( vo_frame_t* vo_img){
opie_frame_t* frame = (opie_frame_t*)vo_img;
if (frame->data)
free( frame->data );
free (frame);
}
/* end take care of frames*/
static vo_frame_t* null_alloc_frame( vo_driver_t* self ){
null_driver_t* this = (null_driver_t*)self;
opie_frame_t* frame;
#ifdef LOG
fprintf (stderr, "nullvideo: alloc_frame\n");
#endif
- frame = (opie_frame_t*)malloc ( sizeof(opie_frame_t) );
+ frame = (opie_frame_t*)xine_xmalloc ( sizeof(opie_frame_t) );
- memset( frame, 0, sizeof( opie_frame_t) );
memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t));
pthread_mutex_init (&frame->frame.mutex, NULL);
frame->output = this;
/* initialize the frame*/
frame->frame.driver = self;
- frame->frame.proc_slice = null_frame_copy;
+ frame->frame.proc_slice = null_frame_proc_slice;
frame->frame.field = null_frame_field;
frame->frame.dispose = null_frame_dispose;
/*
* colorspace converter for this frame
*/
frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory);
return (vo_frame_t*) frame;
}
-static void null_update_frame_format( vo_driver_t* self, vo_frame_t* img,
- uint32_t width, uint32_t height,
- double ratio_code, int format,
- int flags ){
- null_driver_t* this = (null_driver_t*) self;
- opie_frame_t* frame = (opie_frame_t*)img;
- /* not needed now */
-#ifdef LOG
- fprintf (stderr, "nullvideo: update_frame_format\n");
-#endif
+static void null_frame_compute_ideal_size( null_driver_t *this,
+ opie_frame_t *frame ) {
+ this = this;
- flags &= VO_BOTH_FIELDS;
+ _x_vo_scale_compute_ideal_size(&frame->sc);
+}
- /* find out if we need to adapt this frame */
+static void null_frame_compute_rgb_size( null_driver_t *this,
+ opie_frame_t *frame ){
+ this = this;
- if ((width != frame->sc.delivered_width)
- || (height != frame->sc.delivered_height)
- || (ratio_code != frame->sc.delivered_ratio)
- || (flags != frame->flags)
- || (format != frame->format)
- || (this->sc.user_ratio != frame->sc.user_ratio)
- || (this->gui_width != frame->sc.gui_width)
- || (this->gui_height != frame->sc.gui_height)) {
+ _x_vo_scale_compute_output_size(&frame->sc);
- frame->sc.delivered_width = width;
- frame->sc.delivered_height = height;
- frame->sc.delivered_ratio = ratio_code;
- frame->flags = flags;
- frame->format = format;
- frame->sc.user_ratio = this->sc.user_ratio;
- frame->sc.gui_width = this->gui_width;
- frame->sc.gui_height = this->gui_height;
- frame->sc.gui_pixel_aspect = 1.0;
+ /* avoid problems in yuv2rgb */
+ if(frame->sc.output_height < (frame->sc.delivered_height+15) >> 4)
+ frame->sc.output_height = (frame->sc.delivered_height+15) >> 4;
- vo_scale_compute_ideal_size ( &frame->sc );
- vo_scale_compute_output_size( &frame->sc );
+ if (frame->sc.output_width < 8)
+ frame->sc.output_width = 8;
-#ifdef LOG
- fprintf (stderr, "nullvideo: gui %dx%d delivered %dx%d output %dx%d\n",
- frame->sc.gui_width, frame->sc.gui_height,
- frame->sc.delivered_width, frame->sc.delivered_height,
- frame->sc.output_width, frame->sc.output_height);
-#endif
+ /* yuv2rgb_mlib needs an even YUV2 width */
+ if (frame->sc.output_width & 1)
+ frame->sc.output_width++;
+}
+static void null_frame_reallocate( null_driver_t *this, opie_frame_t *frame,
+ uint32_t width, uint32_t height, int format){
/*
* (re-) allocate
*/
if( frame->data ) {
if( frame->chunk[0] ){
free( frame->chunk[0] );
frame->chunk[0] = NULL;
}
if( frame->chunk[1] ){
free ( frame->chunk[1] );
frame->chunk[1] = NULL;
}
if( frame->chunk[2] ){
free ( frame->chunk[2] );
frame->chunk[2] = NULL;
}
free ( frame->data );
}
- frame->data = xine_xmalloc (frame->sc.output_width
+ frame->data = xine_xmalloc (frame->sc.output_width
* frame->sc.output_height
* this->bytes_per_pixel );
if( format == XINE_IMGFMT_YV12 ) {
frame->frame.pitches[0] = 8*((width + 7) / 8);
frame->frame.pitches[1] = 8*((width + 15) / 16);
frame->frame.pitches[2] = 8*((width + 15) / 16);
frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height,(void **)&frame->chunk[0]);
frame->frame.base[1] = xine_xmalloc_aligned (16, frame->frame.pitches[1] * ((height+ 1)/2), (void **)&frame->chunk[1]);
frame->frame.base[2] = xine_xmalloc_aligned (16, frame->frame.pitches[2] * ((height+ 1)/2), (void **)&frame->chunk[2]);
}else{
frame->frame.pitches[0] = 8*((width + 3) / 4);
frame->frame.base[0] = xine_xmalloc_aligned (16, frame->frame.pitches[0] * height,
(void **)&frame->chunk[0]);
frame->chunk[1] = NULL;
frame->chunk[2] = NULL;
}
+}
+
+static void null_setup_colorspace_converter(opie_frame_t *frame, int flags ) {
+ switch (flags) {
+ case VO_TOP_FIELD:
+ case VO_BOTTOM_FIELD:
+ frame->yuv2rgb->configure (frame->yuv2rgb,
+ frame->sc.delivered_width,
+ 16,
+ 2*frame->frame.pitches[0],
+ 2*frame->frame.pitches[1],
+ frame->sc.output_width,
+ frame->stripe_height,
+ frame->bytes_per_line*2);
+ frame->yuv_stride = frame->bytes_per_line*2;
+ break;
+ case VO_BOTH_FIELDS:
+ frame->yuv2rgb->configure (frame->yuv2rgb,
+ frame->sc.delivered_width,
+ 16,
+ frame->frame.pitches[0],
+ frame->frame.pitches[1],
+ frame->sc.output_width,
+ frame->stripe_height,
+ frame->bytes_per_line);
+ frame->yuv_stride = frame->bytes_per_line;
+ break;
+ }
+#ifdef LOG
+ fprintf (stderr, "nullvideo: colorspace converter configured.\n");
+#endif
+}
+
+static void null_update_frame_format( vo_driver_t* self, vo_frame_t* img,
+ uint32_t width, uint32_t height,
+ double ratio_code, int format,
+ int flags ){
+ null_driver_t* this = (null_driver_t*) self;
+ opie_frame_t* frame = (opie_frame_t*)img;
+
+#ifdef LOG
+ fprintf (stderr, "nullvideo: update_frame_format\n");
+#endif
+
+ flags &= VO_BOTH_FIELDS;
+
+ /* find out if we need to adapt this frame */
+
+ if ((width != frame->sc.delivered_width)
+ || (height != frame->sc.delivered_height)
+ || (ratio_code != frame->sc.delivered_ratio)
+ || (flags != frame->flags)
+ || (format != frame->format)
+ || (this->sc.user_ratio != frame->sc.user_ratio)
+ || (this->gui_width != frame->sc.gui_width)
+ || (this->gui_height != frame->sc.gui_height)) {
+
+ frame->sc.delivered_width = width;
+ frame->sc.delivered_height = height;
+ frame->sc.delivered_ratio = ratio_code;
+ frame->flags = flags;
+ frame->format = format;
+ frame->sc.user_ratio = this->sc.user_ratio;
+ frame->sc.gui_width = this->gui_width;
+ frame->sc.gui_height = this->gui_height;
+ frame->sc.gui_pixel_aspect = 1.0;
+
+
+ null_frame_compute_ideal_size(this, frame);
+ null_frame_compute_rgb_size(this, frame);
+ null_frame_reallocate(this, frame, width, height, format);
+
+#ifdef LOG
+ fprintf (stderr, "nullvideo: gui %dx%d delivered %dx%d output %dx%d\n",
+ frame->sc.gui_width, frame->sc.gui_height,
+ frame->sc.delivered_width, frame->sc.delivered_height,
+ frame->sc.output_width, frame->sc.output_height);
+#endif
+
+
+
frame->stripe_height = 16 * frame->sc.output_height / frame->sc.delivered_height;
frame->bytes_per_line = frame->sc.output_width * this->bytes_per_pixel;
/*
* set up colorspace converter
*/
+ null_setup_colorspace_converter(frame, flags);
- switch (flags) {
- case VO_TOP_FIELD:
- case VO_BOTTOM_FIELD:
- frame->yuv2rgb->configure (frame->yuv2rgb,
- frame->sc.delivered_width,
- 16,
- 2*frame->frame.pitches[0],
- 2*frame->frame.pitches[1],
- frame->sc.output_width,
- frame->stripe_height,
- frame->bytes_per_line*2);
- frame->yuv_stride = frame->bytes_per_line*2;
- break;
- case VO_BOTH_FIELDS:
- frame->yuv2rgb->configure (frame->yuv2rgb,
- frame->sc.delivered_width,
- 16,
- frame->frame.pitches[0],
- frame->frame.pitches[1],
- frame->sc.output_width,
- frame->stripe_height,
- frame->bytes_per_line);
- frame->yuv_stride = frame->bytes_per_line;
- break;
- }
-#ifdef LOG
- fprintf (stderr, "nullvideo: colorspace converter configured.\n");
-#endif
}
-
/*
* reset dest pointers
*/
- if (frame->data) {
- switch (flags) {
- case VO_TOP_FIELD:
- frame->rgb_dst = (uint8_t *)frame->data;
- frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
- break;
- case VO_BOTTOM_FIELD:
- frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ;
- frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
- break;
- case VO_BOTH_FIELDS:
- frame->rgb_dst = (uint8_t *)frame->data;
- frame->stripe_inc = frame->stripe_height * frame->bytes_per_line;
- break;
+ if (frame->data) {
+ switch (flags) {
+ case VO_TOP_FIELD:
+ frame->rgb_dst = (uint8_t *)frame->data;
+ frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
+ break;
+ case VO_BOTTOM_FIELD:
+ frame->rgb_dst = (uint8_t *)frame->data + frame->bytes_per_line ;
+ frame->stripe_inc = 2 * frame->stripe_height * frame->bytes_per_line;
+ break;
+ case VO_BOTH_FIELDS:
+ frame->rgb_dst = (uint8_t *)frame->data;
+ frame->stripe_inc = frame->stripe_height * frame->bytes_per_line;
+ break;
+ }
}
- }
}
static void null_display_frame( vo_driver_t* self, vo_frame_t *frame_gen ){
null_driver_t* this = (null_driver_t*) self;
opie_frame_t* frame = (opie_frame_t*)frame_gen;
display_xine_frame_t display = this->frameDis;
if (!this->m_show_video)
return;
if( display != NULL ) {
(*display)(this->caller, frame->data,
frame->sc.output_width, frame->sc.output_height,
frame->bytes_per_line );
}
frame->frame.free(&frame->frame);
}
/* blending related */
static void null_overlay_clut_yuv2rgb (null_driver_t *this,
vo_overlay_t *overlay,
opie_frame_t *frame) {
+ this = this;
+
+
int i;
clut_t* clut = (clut_t*) overlay->color;
if (!overlay->rgb_clut) {
for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
*((uint32_t *)&clut[i]) =
- frame->yuv2rgb->yuv2rgb_single_pixel_fun (frame->yuv2rgb,
- clut[i].y, clut[i].cb,
- clut[i].cr);
+ frame->yuv2rgb->
+ yuv2rgb_single_pixel_fun (frame->yuv2rgb,
+ clut[i].y, clut[i].cb,
+ clut[i].cr);
}
overlay->rgb_clut++;
}
if (!overlay->clip_rgb_clut) {
clut = (clut_t*) overlay->clip_color;
for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
*((uint32_t *)&clut[i]) =
frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb,
clut[i].y, clut[i].cb, clut[i].cr);
}
overlay->clip_rgb_clut++;
}
}
static void null_overlay_blend ( vo_driver_t *this_gen, vo_frame_t *frame_gen,
vo_overlay_t *overlay) {
null_driver_t *this = (null_driver_t *) this_gen;
opie_frame_t *frame = (opie_frame_t *) frame_gen;
if(!this->m_show_video || frame->sc.output_width == 0
|| frame->sc.output_height== 0)
return;
/* Alpha Blend here */
if (overlay->rle) {
if( !overlay->rgb_clut || !overlay->clip_rgb_clut)
null_overlay_clut_yuv2rgb(this,overlay,frame);
switch(this->bpp) {
- case 16:
- blend_rgb16( (uint8_t *)frame->data, overlay,
- frame->sc.output_width, frame->sc.output_height,
- frame->sc.delivered_width, frame->sc.delivered_height);
- break;
- case 24:
- blend_rgb24( (uint8_t *)frame->data, overlay,
- frame->sc.output_width, frame->sc.output_height,
- frame->sc.delivered_width, frame->sc.delivered_height);
- break;
- case 32:
- blend_rgb32( (uint8_t *)frame->data, overlay,
- frame->sc.output_width, frame->sc.output_height,
- frame->sc.delivered_width, frame->sc.delivered_height);
- break;
- default:
- /* It should never get here */
- break;
+ case 16:
+ blend_rgb16((uint8_t *)frame->data,
+ overlay,
+ frame->sc.output_width,
+ frame->sc.output_height,
+ frame->sc.delivered_width,
+ frame->sc.delivered_height);
+ break;
+ case 24:
+ blend_rgb24((uint8_t *)frame->data,
+ overlay,
+ frame->sc.output_width,
+ frame->sc.output_height,
+ frame->sc.delivered_width,
+ frame->sc.delivered_height);
+ break;
+ case 32:
+ blend_rgb32((uint8_t *)frame->data,
+ overlay,
+ frame->sc.output_width,
+ frame->sc.output_height,
+ frame->sc.delivered_width,
+ frame->sc.delivered_height);
+ break;
+ default:
+ /* It should never get here */
+ break;
}
}
}
-static int null_get_property( vo_driver_t* self,
- int property ){
+static int null_get_property( vo_driver_t* self, int property ){
+#if 0
+ null_driver_t *this = (null_driver_t *)self;
+
+ switch(property)
+ {
+ case VO_PROP_ASPECT_RATIO:
+ return this->sc.user_ratio;
+ case VO_PROP_BRIGHTNESS:
+ return this->yuv2rgb_brightness;
+ case VO_PROP_WINDOW_WIDTH:
+ return this->sc.gui_width;
+ case VO_PROP_WINDOW_HEIGHT:
+ return this->sc.gui_height;
+ default:
+ break;
+ }
+#else
+ property = property;
+ self = self;
+#endif
+
return 0;
}
-static int null_set_property( vo_driver_t* self,
- int property,
+static int null_set_property( vo_driver_t* self, int property,
int value ){
+#if 0
+ null_driver_t *this = (null_driver_t *)self;
+
+ switch(property)
+ {
+ case VO_PROP_ASPECT_RATIO:
+ if(value>=XINE_VO_ASPECT_NUM_RATIOS)
+ value = XINE_VO_ASPECT_AUTO;
+ this->sc.user_ratio = value;
+ break;
+ case VO_PROP_BRIGHTNESS:
+ this->yuv2rgb_brightness = value;
+ this->yuv2rgb_factory->
+ set_csc_levels(this->yuv2rgb_factory, value, 128, 128);
+ break;
+ default:
+ break;
+ }
+#else
+ self = self;
+ property = property;
+#endif
+
return value;
}
static void null_get_property_min_max( vo_driver_t* self,
int property, int *min,
int *max ){
+ self = self;
+ property = property;
+
*max = 0;
*min = 0;
}
static int null_gui_data_exchange( vo_driver_t* self,
int data_type,
void *data ){
+ self = self;
+ data_type = data_type;
+ data = data;
+
return 0;
}
static void null_dispose ( vo_driver_t* self ){
null_driver_t* this = (null_driver_t*)self;
free ( this );
}
static int null_redraw_needed( vo_driver_t* self ){
- return 0;
+ self = self;
+
+ return 0;
}
-xine_vo_driver_t* init_video_out_plugin( xine_t *xine,
+xine_video_port_t* init_video_out_plugin( xine_t *xine,
void* video,
display_xine_frame_t frameDisplayFunc,
void *userData ){
+ video = video;
+
+
null_driver_t *vo;
vo = (null_driver_t*)malloc( sizeof(null_driver_t ) );
/* memset? */
memset(vo,0, sizeof(null_driver_t ) );
- vo_scale_init (&vo->sc, 0, 0, xine->config);
+ _x_vo_scale_init (&vo->sc, 0, 0, xine->config);
vo->sc.gui_pixel_aspect = 1.0;
vo->m_show_video = 0; // false
vo->m_video_fullscreen = 0;
vo->m_is_scaling = 0;
vo->display_ratio = 1.0;
vo->gui_width = 16;
vo->gui_height = 8;
vo->frameDis = NULL;
/* install callback handlers*/
vo->vo_driver.get_capabilities = null_get_capabilities;
vo->vo_driver.alloc_frame = null_alloc_frame;
vo->vo_driver.update_frame_format = null_update_frame_format;
vo->vo_driver.display_frame = null_display_frame;
vo->vo_driver.overlay_blend = null_overlay_blend;
vo->vo_driver.get_property = null_get_property;
vo->vo_driver.set_property = null_set_property;
vo->vo_driver.get_property_min_max = null_get_property_min_max;
vo->vo_driver.gui_data_exchange = null_gui_data_exchange;
vo->vo_driver.dispose = null_dispose;
vo->vo_driver.redraw_needed = null_redraw_needed;
/* capabilities */
- vo->m_capabilities = /* VO_CAP_COPIES_IMAGE | */ VO_CAP_YUY2 | VO_CAP_YV12;
+ vo->m_capabilities = VO_CAP_YUY2 | VO_CAP_YV12;
vo->yuv2rgb_factory = yuv2rgb_factory_init (MODE_16_RGB, vo->yuv2rgb_swap,
vo->yuv2rgb_cmap);
vo->caller = userData;
vo->frameDis = frameDisplayFunc;
- /* return ( vo_driver_t*) vo; */
- return vo_new_port( xine, ( vo_driver_t* )vo, 0 );
+ return _x_vo_new_port(xine, &vo->vo_driver, 0);
}
-#if 0
-static vo_info_t vo_info_null = {
- 5,
- XINE_VISUAL_TYPE_FB
-};
-
-vo_info_t *get_video_out_plugin_info(){
- vo_info_null.description = ("xine video output plugin using null device");
- return &vo_info_null;
-}
-
-#endif
/* this is special for this device */
/**
* We know that we will be controled by the XINE LIB++
*/
/**
*
*/
int null_is_showing_video( xine_vo_driver_t* self ){
null_driver_t* this = (null_driver_t*)self->driver;
return this->m_show_video;
}
void null_set_show_video( xine_vo_driver_t* self, int show ) {
((null_driver_t*)self->driver)->m_show_video = show;
}
int null_is_fullscreen( xine_vo_driver_t* self ){
return ((null_driver_t*)self->driver)->m_video_fullscreen;
}
void null_set_fullscreen( xine_vo_driver_t* self, int screen ){
((null_driver_t*)self->driver)->m_video_fullscreen = screen;
}
int null_is_scaling( xine_vo_driver_t* self ){
return ((null_driver_t*)self->driver)->m_is_scaling;
}
void null_set_videoGamma( xine_vo_driver_t* self , int value ) {
((null_driver_t*) self->driver) ->yuv2rgb_gamma = value;
((null_driver_t*) self->driver) ->yuv2rgb_factory->set_gamma( ((null_driver_t*) self->driver) ->yuv2rgb_factory, value );
}
void null_set_scaling( xine_vo_driver_t* self, int scale ) {
((null_driver_t*)self->driver)->m_is_scaling = scale;
}
void null_set_gui_width( xine_vo_driver_t* self, int width ) {
((null_driver_t*)self->driver)->gui_width = width;
}
void null_set_gui_height( xine_vo_driver_t* self, int height ) {
((null_driver_t*)self->driver)->gui_height = height;
}
void null_set_mode( xine_vo_driver_t* self, int depth, int rgb ) {
null_driver_t* this = (null_driver_t*)self->driver;
this->bytes_per_pixel = (depth + 7 ) / 8;
this->bpp = this->bytes_per_pixel * 8;
this->depth = depth;
- printf("depth %d %d\n", depth, this->bpp);
- printf("pixeltype %d\n", rgb );
+
switch ( this->depth ) {
case 32:
if( rgb == 0 )
this->yuv2rgb_mode = MODE_32_RGB;
else
this->yuv2rgb_mode = MODE_32_BGR;
case 24:
if( this->bpp == 32 ) {
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_32_RGB;
} else {
this->yuv2rgb_mode = MODE_32_BGR;
}
}else{
if( rgb == 0 )
this->yuv2rgb_mode = MODE_24_RGB;
else
this->yuv2rgb_mode = MODE_24_BGR;
};
break;
case 16:
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_16_RGB;
} else {
this->yuv2rgb_mode = MODE_16_BGR;
}
break;
case 15:
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_15_RGB;
} else {
this->yuv2rgb_mode = MODE_15_BGR;
}
break;
case 8:
if( rgb == 0 ) {
this->yuv2rgb_mode = MODE_8_RGB;
} else {
this->yuv2rgb_mode = MODE_8_BGR;
}
break;
};
//free(this->yuv2rgb_factory );
// this->yuv2rgb_factory = yuv2rgb_factory_init (this->yuv2rgb_mode, this->yuv2rgb_swap,
// this->yuv2rgb_cmap);
};
void null_display_handler( xine_vo_driver_t* self, display_xine_frame_t t,
void* user_data ) {
null_driver_t* this = (null_driver_t*) self->driver;
this->caller = user_data;
this->frameDis = t;
}
void null_preload_decoders( xine_stream_t *stream )
{
static const uint32_t preloadedAudioDecoders[] = { BUF_AUDIO_MPEG, BUF_AUDIO_VORBIS };
static const uint8_t preloadedAudioDecoderCount = sizeof( preloadedAudioDecoders ) / sizeof( preloadedAudioDecoders[ 0 ] );
static const uint32_t preloadedVideoDecoders[] = { BUF_VIDEO_MPEG, BUF_VIDEO_MPEG4, BUF_VIDEO_DIVX5 };
static const uint8_t preloadedVideoDecoderCount = sizeof( preloadedVideoDecoders ) / sizeof( preloadedVideoDecoders[ 0 ] );
uint8_t i;
+#if 0
for ( i = 0; i < preloadedAudioDecoderCount; ++i ) {
- audio_decoder_t *decoder = get_audio_decoder( stream, ( preloadedAudioDecoders[ i ] >> 16 ) & 0xff );
+ audio_decoder_t *decoder = get_audio_decoder( stream, ( preloadedAudioDecoders[ i ] >> 16 ) & 0xff );
+ decoder = decoder;
/* free_audio_decoder( stream, decoder ); */
}
for ( i = 0; i < preloadedVideoDecoderCount; ++i ) {
- video_decoder_t *decoder = get_video_decoder( stream, ( preloadedVideoDecoders[ i ] >> 16 ) & 0xff );
+ video_decoder_t *decoder = get_video_decoder( stream, ( preloadedVideoDecoders[ i ] >> 16 ) & 0xff );
+ decoder = decoder;
/* free_video_decoder( stream, decoder ); */
}
+#endif
}
diff --git a/noncore/multimedia/opieplayer2/opieplayer2.pro b/noncore/multimedia/opieplayer2/opieplayer2.pro
index b9a8d6d..8166658 100644
--- a/noncore/multimedia/opieplayer2/opieplayer2.pro
+++ b/noncore/multimedia/opieplayer2/opieplayer2.pro
@@ -1,29 +1,29 @@
CONFIG = qt warn_on quick-app
HEADERS = playlistselection.h mediaplayerstate.h xinecontrol.h \
videowidget.h audiowidget.h playlistwidget.h om3u.h mediaplayer.h inputDialog.h \
frame.h lib.h xinevideowidget.h volumecontrol.h playlistwidgetgui.h\
alphablend.h yuv2rgb.h threadutil.h mediawidget.h playlistview.h playlistfileview.h \
skin.h
SOURCES = main.cpp \
playlistselection.cpp mediaplayerstate.cpp xinecontrol.cpp \
videowidget.cpp audiowidget.cpp playlistwidget.cpp om3u.cpp mediaplayer.cpp inputDialog.cpp \
frame.cpp lib.cpp nullvideo.c xinevideowidget.cpp volumecontrol.cpp \
playlistwidgetgui.cpp\
alphablend.c yuv2rgb.c yuv2rgb_arm2.c yuv2rgb_arm4l.S \
threadutil.cpp mediawidget.cpp playlistview.cpp playlistfileview.cpp \
skin.cpp
TARGET = opieplayer2
INCLUDEPATH += $(OPIEDIR)/include
DEPENDPATH += $(OPIEDIR)/include
-LIBS += -lqpe -lpthread -lopiecore2 -lopieui2 -lxine -lstdc++
+LIBS += -lqpe -lpthread -lopiecore2 -lopieui2 -lqtaux2 -lxine
MOC_DIR = qpeobj
OBJECTS_DIR = qpeobj
include ( $(OPIEDIR)/include.pro )
!isEmpty( LIBXINE_INC_DIR ) {
INCLUDEPATH = $$LIBXINE_INC_DIR $$INCLUDEPATH
}
!isEmpty( LIBXINE_LIB_DIR ) {
LIBS = -L$$LIBXINE_LIB_DIR $$LIBS
}
diff --git a/noncore/multimedia/opieplayer2/xinevideowidget.cpp b/noncore/multimedia/opieplayer2/xinevideowidget.cpp
index 15c611f..1ac9277 100644
--- a/noncore/multimedia/opieplayer2/xinevideowidget.cpp
+++ b/noncore/multimedia/opieplayer2/xinevideowidget.cpp
@@ -1,245 +1,246 @@
/*
                This file is part of the Opie Project
Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. 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
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <qimage.h>
#include <qdirectpainter_qws.h>
#include <qgfx_qws.h>
#include <qsize.h>
#include <qapplication.h>
#include <qpe/resource.h>
#include "xinevideowidget.h"
// 0 deg rot: copy a line from src to dst (use libc memcpy)
// 180 deg rot: copy a line from src to dst reversed
/*
* This code relies the len be a multiply of 16bit
*/
static inline void memcpy_rev ( void *_dst, void *_src, size_t len )
{
+
/*
* move the source to the end
*/
char *src_c = static_cast<char*>(_src) + len;
/*
* as we copy by 16bit and not 8bit
* devide the length by two
*/
len >>= 1;
short int* dst = static_cast<short int*>( _dst );
short int* src = reinterpret_cast<short int*>( src_c );
/*
* Increment dst after assigning
* Decrement src before assigning becase we move backwards
*/
while ( len-- )
*dst++ = *--src;
}
// 90 deg rot: copy a column from src to dst
static inline void memcpy_step ( void *_dst, void *_src, size_t len, size_t step )
{
short int *dst = static_cast<short int*>( _dst );
short int *src = static_cast<short int*>( _src );
len >>= 1;
/*
* Copy 16bit from src to dst and move to the next address
*/
while ( len-- ) {
*dst++ = *src;
src = reinterpret_cast<short int*>(reinterpret_cast<char*>(src)+step);
}
}
// 270 deg rot: copy a column from src to dst reversed
static inline void memcpy_step_rev ( void *_dst, void *_src, size_t len, size_t step )
{
len >>= 1;
char *src_c = static_cast<char*>( _src ) + (len*step);
short int* dst = static_cast<short int*>( _dst );
short int* src = reinterpret_cast<short int*>( src_c );
while ( len-- ) {
src_c -= step;
src = reinterpret_cast<short int*>( src_c );
*dst++ = *src;
}
}
XineVideoWidget::XineVideoWidget ( QWidget* parent, const char* name )
: QWidget ( parent, name, WRepaintNoErase | WResizeNoErase )
{
setBackgroundMode ( NoBackground );
m_logo = 0;
m_buff = 0;
m_bytes_per_line_fb = qt_screen-> linestep ( );
m_bytes_per_pixel = ( qt_screen->depth() + 7 ) / 8;
m_rotation = 0;
}
XineVideoWidget::~XineVideoWidget ( )
{
delete m_logo;
}
void XineVideoWidget::clear ( )
{
m_buff = 0;
repaint ( false );
}
QSize XineVideoWidget::videoSize() const
{
QSize s = size();
bool fs = ( s == qApp->desktop()->size() );
// if we are in fullscreen mode, do not rotate the video
// (!! the paint routine uses m_rotation + qt_screen-> transformOrientation() !!)
m_rotation = fs ? - qt_screen->transformOrientation() : 0;
if ( fs && qt_screen->isTransformed() )
s = qt_screen->mapToDevice( s );
return s;
}
void XineVideoWidget::paintEvent ( QPaintEvent * )
{
if ( m_buff == 0 ) {
QPainter p ( this );
p. fillRect ( rect ( ), black );
if ( m_logo )
p. drawImage ( 0, 0, *m_logo );
}
else {
// Qt needs to be notified which areas were really updated .. strange
QArray <QRect> qt_bug_workaround_clip_rects;
{
QDirectPainter dp ( this );
int rot = dp. transformOrientation ( ) + m_rotation; // device rotation + custom rotation
uchar *fb = dp. frameBuffer ( );
uchar *frame = m_buff;
// where is the video frame in fb coordinates
QRect framerect = qt_screen-> mapToDevice ( QRect ( mapToGlobal ( m_thisframe. topLeft ( )), m_thisframe. size ( )), QSize ( qt_screen-> width ( ), qt_screen-> height ( )));
qt_bug_workaround_clip_rects. resize ( dp. numRects ( ));
for ( int i = dp. numRects ( ) - 1; i >= 0; i-- ) {
const QRect &clip = dp. rect ( i );
qt_bug_workaround_clip_rects [ i ] = qt_screen-> mapFromDevice ( clip, QSize ( qt_screen-> width ( ), qt_screen-> height ( )));
uchar *dst = fb + ( clip. x ( ) * m_bytes_per_pixel ) + ( clip. y ( ) * m_bytes_per_line_fb ); // clip x/y in the fb
uchar *src = frame;
// Adjust the start the source data based on the rotation (xine frame)
switch ( rot ) {
case 0: src += ((( clip. x ( ) - framerect. x ( )) * m_bytes_per_pixel ) + (( clip. y ( ) - framerect. y ( )) * m_bytes_per_line_frame )); break;
case 1: src += ((( clip. y ( ) - framerect. y ( )) * m_bytes_per_pixel ) + (( clip. x ( ) - framerect. x ( )) * m_bytes_per_line_frame ) + (( framerect. height ( ) - 1 ) * m_bytes_per_pixel )); break;
case 2: src += ((( clip. x ( ) - framerect. x ( )) * m_bytes_per_pixel ) + (( clip. y ( ) - framerect. y ( )) * m_bytes_per_line_frame ) + (( framerect. height ( ) - 1 ) * m_bytes_per_line_frame )); break;
case 3: src += ((( clip. y ( ) - framerect. y ( )) * m_bytes_per_pixel ) + (( clip. x ( ) - framerect. x ( )) * m_bytes_per_line_frame )); break;
default: break;
}
// all of the following widths/heights are fb relative (0deg rotation)
uint leftfill = 0; // black border on the "left" side of the video frame
uint framefill = 0; // "width" of the video frame
uint rightfill = 0; // black border on the "right" side of the video frame
uint clipwidth = clip. width ( ) * m_bytes_per_pixel; // "width" of the current clip rect
if ( clip. left ( ) < framerect. left ( ))
leftfill = (( framerect. left ( ) - clip. left ( )) * m_bytes_per_pixel ) <? clipwidth;
if ( clip. right ( ) > framerect. right ( ))
rightfill = (( clip. right ( ) - framerect. right ( )) * m_bytes_per_pixel ) <? clipwidth;
framefill = clipwidth - ( leftfill + rightfill );
for ( int y = clip. top ( ); y <= clip. bottom ( ); y++ ) {
if (( y < framerect. top ( )) || ( y > framerect. bottom ( ))) {
// "above" or "below" the video -> black
memset ( dst, 0, clipwidth );
}
else {
if ( leftfill )
memset ( dst, 0, leftfill ); // "left" border -> black
if ( framefill ) { // blit in the video frame
// see above for an explanation of the different memcpys
switch ( rot ) {
case 0: memcpy ( dst + leftfill, src, framefill & ~1 ); break;
case 1: memcpy_step ( dst + leftfill, src, framefill, m_bytes_per_line_frame ); break;
case 2: memcpy_rev ( dst + leftfill, src, framefill ); break;
case 3: memcpy_step_rev ( dst + leftfill, src, framefill, m_bytes_per_line_frame ); break;
default: break;
}
}
if ( rightfill )
memset ( dst + leftfill + framefill, 0, rightfill ); // "right" border -> black
}
dst += m_bytes_per_line_fb; // advance one line in the framebuffer
// advance one "line" in the xine frame data
switch ( rot ) {
case 0: src += m_bytes_per_line_frame; break;
case 1: src -= m_bytes_per_pixel; break;
case 2: src -= m_bytes_per_line_frame; break;
case 3: src += m_bytes_per_pixel; break;
default: break;
}
}
}
}