summaryrefslogtreecommitdiff
path: root/noncore/multimedia/opieplayer2/xinevideowidget.cpp
authorsandman <sandman>2002-09-24 18:55:16 (UTC)
committer sandman <sandman>2002-09-24 18:55:16 (UTC)
commit844325085130e79ec503a0ab5b8eeafa25a7bdb1 (patch) (unidiff)
treeaa1c45bf90036f9a5077f63b478e77069e64b5f1 /noncore/multimedia/opieplayer2/xinevideowidget.cpp
parent262dfbf10d031ab8a80948cd1485d747ad2c931b (diff)
downloadopie-844325085130e79ec503a0ab5b8eeafa25a7bdb1.zip
opie-844325085130e79ec503a0ab5b8eeafa25a7bdb1.tar.gz
opie-844325085130e79ec503a0ab5b8eeafa25a7bdb1.tar.bz2
Documentation for the video magic (for Holger ;)
Small interface changes (better method names)
Diffstat (limited to 'noncore/multimedia/opieplayer2/xinevideowidget.cpp') (more/less context) (show whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/xinevideowidget.cpp126
1 files changed, 58 insertions, 68 deletions
diff --git a/noncore/multimedia/opieplayer2/xinevideowidget.cpp b/noncore/multimedia/opieplayer2/xinevideowidget.cpp
index d06d62a..9b26d41 100644
--- a/noncore/multimedia/opieplayer2/xinevideowidget.cpp
+++ b/noncore/multimedia/opieplayer2/xinevideowidget.cpp
@@ -2,8 +2,7 @@
2/* 2/*
3                This file is part of the Opie Project 3                This file is part of the Opie Project
4 4
5              Copyright (c) 2002 Max Reiss <harlekin@handhelds.org> 5 Copyright (c) 2002 Robert Griebl <sandman@handhelds.org>
6 Copyright (c) 2002 LJP <>
7 Copyright (c) 2002 Holger Freyther <zecke@handhelds.org> 6 Copyright (c) 2002 Holger Freyther <zecke@handhelds.org>
8 =. 7 =.
9 .=l. 8 .=l.
@@ -45,6 +44,9 @@
45 44
46#include "xinevideowidget.h" 45#include "xinevideowidget.h"
47 46
47// 0 deg rot: copy a line from src to dst (use libc memcpy)
48
49// 180 deg rot: copy a line from src to dst reversed
48 50
49static inline void memcpy_rev ( void *dst, void *src, size_t len ) 51static inline void memcpy_rev ( void *dst, void *src, size_t len )
50{ 52{
@@ -55,23 +57,27 @@ static inline void memcpy_rev ( void *dst, void *src, size_t len )
55 *((short int *) dst )++ = *--((short int *) src ); 57 *((short int *) dst )++ = *--((short int *) src );
56} 58}
57 59
58static inline void memcpy_step ( void *dst, void *src, size_t len, size_t step ) 60// 90 deg rot: copy a column from src to dst
61
62static inline void memcpy_step ( void *dst, void *src, size_t len, size_t linestep )
59{ 63{
60 len >>= 1; 64 len >>= 1;
61 while ( len-- ) { 65 while ( len-- ) {
62 *((short int *) dst )++ = *((short int *) src ); 66 *((short int *) dst )++ = *((short int *) src );
63 ((char *) src ) += step; 67 ((char * ) src) += linestep;
64 } 68 }
65} 69}
66 70
67static inline void memcpy_step_rev ( void *dst, void *src, size_t len, size_t step ) 71// 270 deg rot: copy a column from src to dst reversed
72
73static inline void memcpy_step_rev ( void *dst, void *src, size_t len, size_t linestep )
68{ 74{
69 len >>= 1; 75 len >>= 1;
70 76
71 ((char *) src ) += ( len * step ); 77 ((char *) src) += ( len * linestep );
72 78
73 while ( len-- ) { 79 while ( len-- ) {
74 ((char *) src ) -= step; 80 ((char *) src) -= linestep;
75 *((short int *) dst )++ = *((short int *) src ); 81 *((short int *) dst )++ = *((short int *) src );
76 } 82 }
77} 83}
@@ -82,7 +88,7 @@ XineVideoWidget::XineVideoWidget ( QWidget* parent, const char* name )
82{ 88{
83 setBackgroundMode ( NoBackground ); 89 setBackgroundMode ( NoBackground );
84 90
85 m_image = 0; 91 m_logo = 0;
86 m_buff = 0; 92 m_buff = 0;
87 m_bytes_per_line_fb = qt_screen-> linestep ( ); 93 m_bytes_per_line_fb = qt_screen-> linestep ( );
88 m_bytes_per_pixel = ( qt_screen->depth() + 7 ) / 8; 94 m_bytes_per_pixel = ( qt_screen->depth() + 7 ) / 8;
@@ -92,7 +98,7 @@ XineVideoWidget::XineVideoWidget ( QWidget* parent, const char* name )
92 98
93XineVideoWidget::~XineVideoWidget ( ) 99XineVideoWidget::~XineVideoWidget ( )
94{ 100{
95 delete m_image; 101 delete m_logo;
96} 102}
97 103
98void XineVideoWidget::clear ( ) 104void XineVideoWidget::clear ( )
@@ -103,27 +109,25 @@ void XineVideoWidget::clear ( )
103 109
104void XineVideoWidget::paintEvent ( QPaintEvent * ) 110void XineVideoWidget::paintEvent ( QPaintEvent * )
105{ 111{
106 //qWarning( "painting <<<" );
107 if ( m_buff == 0 ) { 112 if ( m_buff == 0 ) {
108 QPainter p ( this ); 113 QPainter p ( this );
109 p. fillRect ( rect ( ), black ); 114 p. fillRect ( rect ( ), black );
110 if ( m_image ) 115 if ( m_logo )
111 p. drawImage ( 0, 0, *m_image ); 116 p. drawImage ( 0, 0, *m_logo );
112 //qWarning ( "logo\n" );
113 } 117 }
114 else { 118 else {
115// qWarning ( "paintevent\n" ); 119 // Qt needs to be notified which areas were really updated .. strange
116
117 QArray <QRect> qt_bug_workaround_clip_rects; 120 QArray <QRect> qt_bug_workaround_clip_rects;
118 121
119 { 122 {
120 QDirectPainter dp ( this ); 123 QDirectPainter dp ( this );
121 124
122 int rot = dp. transformOrientation ( ) + m_rotation; 125 int rot = dp. transformOrientation ( ) + m_rotation; // device rotation + custom rotation
123 126
124 uchar *fb = dp. frameBuffer ( ); 127 uchar *fb = dp. frameBuffer ( );
125 uchar *frame = m_buff; // rot == 0 ? m_buff : m_buff + ( m_thisframe. height ( ) - 1 ) * m_bytes_per_line_frame; 128 uchar *frame = m_buff;
126 129
130 // where is the video frame in fb coordinates
127 QRect framerect = qt_screen-> mapToDevice ( QRect ( mapToGlobal ( m_thisframe. topLeft ( )), m_thisframe. size ( )), QSize ( qt_screen-> width ( ), qt_screen-> height ( ))); 131 QRect framerect = qt_screen-> mapToDevice ( QRect ( mapToGlobal ( m_thisframe. topLeft ( )), m_thisframe. size ( )), QSize ( qt_screen-> width ( ), qt_screen-> height ( )));
128 132
129 qt_bug_workaround_clip_rects. resize ( dp. numRects ( )); 133 qt_bug_workaround_clip_rects. resize ( dp. numRects ( ));
@@ -133,9 +137,10 @@ void XineVideoWidget::paintEvent ( QPaintEvent * )
133 137
134 qt_bug_workaround_clip_rects [i] = qt_screen-> mapFromDevice ( clip, QSize ( qt_screen-> width ( ), qt_screen-> height ( ))); 138 qt_bug_workaround_clip_rects [i] = qt_screen-> mapFromDevice ( clip, QSize ( qt_screen-> width ( ), qt_screen-> height ( )));
135 139
136 uchar *dst = fb + ( clip. x ( ) * m_bytes_per_pixel ) + ( clip. y ( ) * m_bytes_per_line_fb ); 140 uchar *dst = fb + ( clip. x ( ) * m_bytes_per_pixel ) + ( clip. y ( ) * m_bytes_per_line_fb ); // clip x/y in the fb
137 uchar *src = frame; 141 uchar *src = frame;
138 142
143 // Adjust the start the source data based on the rotation (xine frame)
139 switch ( rot ) { 144 switch ( rot ) {
140 case 0: src += ( (( clip. x ( ) - framerect. x ( )) * m_bytes_per_pixel ) + (( clip. y ( ) - framerect. y ( )) * m_bytes_per_line_frame ) ); break; 145 case 0: src += ( (( clip. x ( ) - framerect. x ( )) * m_bytes_per_pixel ) + (( clip. y ( ) - framerect. y ( )) * m_bytes_per_line_frame ) ); break;
141 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; 146 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;
@@ -144,10 +149,12 @@ void XineVideoWidget::paintEvent ( QPaintEvent * )
144 default: break; 149 default: break;
145 } 150 }
146 151
147 uint leftfill = 0; 152 // all of the following widths/heights are fb relative (0deg rotation)
148 uint framefill = 0; 153
149 uint rightfill = 0; 154 uint leftfill = 0; // black border on the "left" side of the video frame
150 uint clipwidth = clip. width ( ) * m_bytes_per_pixel; 155 uint framefill = 0; // "width" of the video frame
156 uint rightfill = 0; // black border on the "right" side of the video frame
157 uint clipwidth = clip. width ( ) * m_bytes_per_pixel; // "width" of the current clip rect
151 158
152 if ( clip. left ( ) < framerect. left ( )) 159 if ( clip. left ( ) < framerect. left ( ))
153 leftfill = (( framerect. left ( ) - clip. left ( )) * m_bytes_per_pixel ) <? clipwidth; 160 leftfill = (( framerect. left ( ) - clip. left ( )) * m_bytes_per_pixel ) <? clipwidth;
@@ -158,13 +165,16 @@ void XineVideoWidget::paintEvent ( QPaintEvent * )
158 165
159 for ( int y = clip. top ( ); y <= clip. bottom ( ); y++ ) { 166 for ( int y = clip. top ( ); y <= clip. bottom ( ); y++ ) {
160 if (( y < framerect. top ( )) || ( y > framerect. bottom ( ))) { 167 if (( y < framerect. top ( )) || ( y > framerect. bottom ( ))) {
168 // "above" or "below" the video -> black
161 memset ( dst, 0, clipwidth ); 169 memset ( dst, 0, clipwidth );
162 } 170 }
163 else { 171 else {
164 if ( leftfill ) 172 if ( leftfill )
165 memset ( dst, 0, leftfill ); 173 memset ( dst, 0, leftfill ); // "left" border -> black
174
175 if ( framefill ) { // blit in the video frame
176 // see above for an explanation of the different memcpys
166 177
167 if ( framefill ) {
168 switch ( rot ) { 178 switch ( rot ) {
169 case 0: memcpy ( dst + leftfill, src, framefill ); break; 179 case 0: memcpy ( dst + leftfill, src, framefill ); break;
170 case 1: memcpy_step ( dst + leftfill, src, framefill, m_bytes_per_line_frame ); break; 180 case 1: memcpy_step ( dst + leftfill, src, framefill, m_bytes_per_line_frame ); break;
@@ -172,13 +182,13 @@ void XineVideoWidget::paintEvent ( QPaintEvent * )
172 case 3: memcpy_step_rev ( dst + leftfill, src, framefill, m_bytes_per_line_frame ); break; 182 case 3: memcpy_step_rev ( dst + leftfill, src, framefill, m_bytes_per_line_frame ); break;
173 default: break; 183 default: break;
174 } 184 }
175 }
176 if ( rightfill ) 185 if ( rightfill )
177 memset ( dst + leftfill + framefill, 0, rightfill ); 186 memset ( dst + leftfill + framefill, 0, rightfill ); // "right" border -> black
178 } 187 }
179 188
180 dst += m_bytes_per_line_fb; 189 dst += m_bytes_per_line_fb; // advance one line in the framebuffer
181 190
191 // advance one "line" in the xine frame data
182 switch ( rot ) { 192 switch ( rot ) {
183 case 0: src += m_bytes_per_line_frame; break; 193 case 0: src += m_bytes_per_line_frame; break;
184 case 1: src -= m_bytes_per_pixel; break; 194 case 1: src -= m_bytes_per_pixel; break;
@@ -188,10 +198,11 @@ void XineVideoWidget::paintEvent ( QPaintEvent * )
188 } 198 }
189 } 199 }
190 } 200 }
191 } 201
192 //qWarning ( " ||| painting |||" );
193 { 202 {
194 // QVFB hack by MArtin Jones 203 // QVFB hack by Martin Jones
204 // We need to "touch" all affected clip rects with a normal QPainter in addition to the QDirectPainter
205
195 QPainter p ( this ); 206 QPainter p ( this );
196 207
197 for ( int i = qt_bug_workaround_clip_rects. size ( ) - 1; i >= 0; i-- ) { 208 for ( int i = qt_bug_workaround_clip_rects. size ( ) - 1; i >= 0; i-- ) {
@@ -199,21 +210,21 @@ void XineVideoWidget::paintEvent ( QPaintEvent * )
199 } 210 }
200 } 211 }
201 } 212 }
202 //qWarning( "painting >>>" );
203} 213}
204 214
215 QImage *XineVideoWidget::logo ( ) const {
216 return m_logo;
217 }
205 218
206void XineVideoWidget::setImage ( QImage* image ) 219 void XineVideoWidget::setLogo ( QImage * image ) {
207{ 220 delete m_logo;
208 delete m_image; 221 m_logo = image;
209 m_image = image;
210} 222}
211 223
212void XineVideoWidget::setImage ( uchar* img, int w, int h, int bpl ) 224 void XineVideoWidget::setVideoFrame ( uchar * img, int w, int h, int bpl ) {
213{
214 bool rot90 = (( -m_rotation ) & 1 ); 225 bool rot90 = (( -m_rotation ) & 1 );
215 226
216 if ( rot90 ) { 227 if ( rot90 ) { // if the rotation is 90 or 270 we have to swap width / height
217 int d = w; 228 int d = w;
218 w = h; 229 w = h;
219 h = d; 230 h = d;
@@ -222,52 +233,31 @@ void XineVideoWidget::setImage ( uchar* img, int w, int h, int bpl )
222 m_lastframe = m_thisframe; 233 m_lastframe = m_thisframe;
223 m_thisframe. setRect (( width ( ) - w ) / 2, ( height ( ) - h ) / 2, w , h ); 234 m_thisframe. setRect (( width ( ) - w ) / 2, ( height ( ) - h ) / 2, w , h );
224 235
225// qDebug ( "Frame: %d,%d - %dx%d", ( width ( ) - w ) / 2, ( height ( ) - h ) / 2, w , h );
226
227 m_buff = img; 236 m_buff = img;
228 m_bytes_per_line_frame = bpl; 237 m_bytes_per_line_frame = bpl;
229 238
230 repaint ((( m_thisframe & m_lastframe ) != m_lastframe ) ? m_lastframe : m_thisframe, false ); 239 // only repaint the area that *really* needs to be repainted
240
241 repaint ((
231} 242}
232 243
233void XineVideoWidget::resizeEvent ( QResizeEvent * ) 244 void XineVideoWidget::resizeEvent ( QResizeEvent * ) {
234{
235 QSize s = size ( ); 245 QSize s = size ( );
236 bool fs = ( s == qApp-> desktop ( )-> size ( )); 246 bool fs = ( s == qApp-> desktop ( )-> size ( ));
237 247
248 // if we are in fullscreen mode, do not rotate the video
249 // (!! the paint routine uses m_rotation + qt_screen-> transformOrientation() !!)
250
238 m_rotation = fs ? -qt_screen-> transformOrientation ( ) : 0; 251 m_rotation = fs ? -qt_screen-> transformOrientation ( ) : 0;
239 252
240 if ( fs && qt_screen-> isTransformed ( )) { 253 if ( fs && qt_screen-> isTransformed ( ))
241 s = qt_screen-> mapToDevice ( s ); 254 s = qt_screen-> mapToDevice ( s );
242 }
243
244// qDebug ( "\n\nResize: %dx%d, Rot: %d", s.width(),s.height(),m_rotation );
245 255
246 emit videoResized ( s ); 256 emit videoResized ( s );
247} 257}
248 258
249 259
250void XineVideoWidget::mousePressEvent ( QMouseEvent * /*me*/ ) 260 void XineVideoWidget::mouseReleaseEvent ( QMouseEvent * ) {
251{
252 QWidget *p = parentWidget ( );
253
254 if ( p ) {
255 // QMouseEvent pme ( QEvent::MouseButtonPress, mapToParent ( me-> pos ( )), me-> globalPos ( ), me-> button ( ), me-> state ( ));
256
257 // QApplication::sendEvent ( p, &pme );
258 // emit clicked();
259 }
260}
261
262void XineVideoWidget::mouseReleaseEvent ( QMouseEvent * /*me*/ )
263{
264 QWidget *p = parentWidget ( );
265
266 if ( p ) {
267 // QMouseEvent pme ( QEvent::MouseButtonRelease, mapToParent ( me-> pos ( )), me-> globalPos ( ), me-> button ( ), me-> state ( ));
268
269 // QApplication::sendEvent ( p, &pme );
270 emit clicked(); 261 emit clicked();
271 } 262 }
272}
273 263