VideoRenderer Class Reference

This I/O class renders a gray-scale or RGB stream (via a QFrameBuffer) onto a QLabel widget. Don't forget to set the appropriate VideoFrameBuffer! More...

#include <VideoRenderer.hpp>

Inheritance diagram for VideoRenderer:

IO VThread QLabelRenderer SDLRenderer X11Renderer List of all members.

Public Member Functions

 VideoRenderer (const VideoESInfo *es, UncompressedVideoFrame::ColorSpace colorSpace, int width, int height, bool isLabelResizable=true, bool fixAspectRatio=true, bool allowUpscaleX=false)
 Constructor.
virtual ~VideoRenderer ()
 Destructor.
virtual FramegetFrame ()
 Returns NULL, as this class is intended to be an output class only.
void setOutputDepth (int depth)
void setDirectBitBlt (bool direct)
void setVideoFrameBuffer (VideoFrameBuffer *vfb)
virtual int writeFrame (Frame *frm, ESInfo *out_es=NULL)
 Renders a frame to the destination QLabel widget.
virtual bool open ()
 Creates internal frame buffers and checks whether the stream to be rendered matches the widget dimensions.
virtual bool close (bool immediate=false)
 Does nothing but setting the object state to CLOSED.
virtual bool destroy ()
 Not applicable to this class.
virtual int getBufferFillLevel () const
 Not applicable to this class.
virtual const char * getURL () const
 Returns the fixed string VideoRenderer:.
virtual void setESInfo (ESInfo *es)
 Not implemented.
virtual ESInfogetESInfo ()
 Not implemented.

Protected Member Functions

bool updateDisplayRegion ()
 Update frame_info (except size) and display_region.

Protected Attributes

char url [MAX_STR_LEN]
const VideoESInfo * es
 Elementary video stream information.
VideoFrameBufferframeBuffer
 The frame buffer.
UncompressedVideoFrame::ColorSpace colorSpace
 The color space of the frames to be rendered.
VideoRect frame_info
 Dimension, storage size (in bytes), and scaling factors of a decoded video frame.
VideoRect out_label_info
VideoRect display_region
 apect-ratio adjusted region of qlabel where frames will be displayed.
int outputDepth
bool directBitBlt

Detailed Description

This I/O class renders a gray-scale or RGB stream (via a QFrameBuffer) onto a QLabel widget. Don't forget to set the appropriate VideoFrameBuffer!

It is intended to be used as a DataSink connected to a DataChannel.

Video frames will be (down or up) scaled to fit into the QLabel widget by preserving the aspect ratio given in VideoESInfo.

The expected format of the gray-scale stream is: 1 byte per pixel.

The expected format of the RGB24 stream is: 3 bytes per pixel, in the order RGB (red, green, blue).

The expected format of the RGB32 stream is: 4 bytes per pixel, in the order BGRA (blue, green, red, alpha). This conforms to the PIX_FMT_RGBA32 format defined in ffmpeg/libavcodec/avcodec.h on little endian architectures.

Author:
Mario Taschwer and Michael Kropfberger
Version:
Id
VideoRenderer.hpp,v 1.15 2006/01/26 11:42:00 mkropfbe Exp

Definition at line 78 of file VideoRenderer.hpp.


Constructor & Destructor Documentation

VideoRenderer::VideoRenderer const VideoESInfo *  es,
UncompressedVideoFrame::ColorSpace  colorSpace,
int  width,
int  height,
bool  isLabelResizable = true,
bool  fixAspectRatio = true,
bool  allowUpscaleX = false
 

Constructor.

If the parameters are invalid, the open() method will fail.

Parameters:
es elementary stream information about the video stream to be rendered.
colorSpace the color space of the video stream to be rendered; must be one of: MP4Decoder::ColorSpaceGRAY8, MP4Decoder::ColorSpaceRGB24, MP4Decoder::ColorSpaceRGB32.
width the width of the output label/window
height the height of the output label/window
isLabelResizable if true, the given width/height is assumed to be flexible, so it will be tried to keep the original video size (plus adhering #fixAspectRatio) setting this to true, width&height may be zero, only the video is used to determine the resolution
fixAspectRatio if true, video frames may be resized according to their ESInfo aspectRatio, which means upscaling in the y-dimension
allowUpscaleX if true, video frames may be upscaled in x-dimension to fit the label, which may result in significant quality loss, since a very simple upscaling algorithm is used (assumes isLabelResizable==false).
Definition at line 49 of file VideoRenderer.cpp.

References UncompressedVideoFrame::ColorSpace, es, frame_info, and frameBuffer.

00053 : IO() { 00054 strcpy(this->url,"VideoRenderer"); 00055 this->es = _es; 00056 this->colorSpace = colorSpace; 00057 this->outputDepth = 24; //default value assumes modern display 00058 this->directBitBlt = false; 00059 frameBuffer = NULL; 00060 00061 dprintf_full("VideoRenderer Construct (colorSpace %s, depth %i bit, resolution %ix%i, allowUpscaleX: %s)\n", 00062 colorSpace==UncompressedVideoFrame::ColorSpaceGRAY8?"RGB8gray": 00063 colorSpace==UncompressedVideoFrame::ColorSpaceRGB24?"RGB24": 00064 colorSpace==UncompressedVideoFrame::ColorSpaceRGB32?"RGB32": 00065 colorSpace==UncompressedVideoFrame::ColorSpaceRGB565?"RGB565": 00066 colorSpace==UncompressedVideoFrame::ColorSpaceI420?"I420": 00067 colorSpace==UncompressedVideoFrame::ColorSpaceYV12?"YV12": 00068 "UNKNOWN", 00069 UncompressedVideoFrame::mapColorSpaceToBitDepth(colorSpace), 00070 width, height, allowUpscaleX?"yes":"no"); 00071 frame_info.width = 0; 00072 frame_info.height = 0; 00073 frame_info.size = 0; 00074 frame_info.scaleX = INT2FIXED(1); 00075 frame_info.scaleY = INT2FIXED(1); 00076 frame_info.fixAspectRatio = fixAspectRatio; 00077 frame_info.allowUpscaleX = allowUpscaleX; 00078 out_label_info.isLabelResizable = isLabelResizable; 00079 out_label_info.left=0; 00080 out_label_info.top=0; 00081 00082 if (isLabelResizable) { 00083 //get first hint from ES, aspectRatio may be calc'd later 00084 out_label_info.width=es->getWidth(); 00085 out_label_info.height=es->getHeight(); 00086 } else { 00087 out_label_info.width=width; 00088 out_label_info.height=height; 00089 } 00090 state = CLOSED; 00091 }


Member Function Documentation

virtual bool VideoRenderer::close bool  immediate = false  )  [inline, virtual]
 

Does nothing but setting the object state to CLOSED.

Parameters:
immediate ignored.
Returns:
true
See also:
IO::close(bool)

Implements IO.

Definition at line 169 of file VideoRenderer.hpp.

00169 { 00170 state=CLOSED; 00171 return true; 00172 };

virtual bool VideoRenderer::destroy  )  [inline, virtual]
 

Not applicable to this class.

Returns:
true
See also:
IO::destroy()

Implements IO.

Definition at line 178 of file VideoRenderer.hpp.

00178 { 00179 return true; 00180 };

virtual int VideoRenderer::getBufferFillLevel  )  const [inline, virtual]
 

Not applicable to this class.

Returns:
50
See also:
IO::getBufferFillLevel()

Implements IO.

Definition at line 186 of file VideoRenderer.hpp.

00186 { 00187 return 50; 00188 };

virtual ESInfo* VideoRenderer::getESInfo  )  [inline, virtual]
 

Not implemented.

Returns:
NULL

Implements IO.

Definition at line 201 of file VideoRenderer.hpp.

00201 { return NULL;};

bool VideoRenderer::open  )  [virtual]
 

Creates internal frame buffers and checks whether the stream to be rendered matches the widget dimensions.

Returns:
true on success, false on error.
See also:
IO::open()

Implements IO.

Reimplemented in QLabelRenderer, SDLRenderer, and X11Renderer.

Definition at line 214 of file VideoRenderer.cpp.

Referenced by Visualizer::adapt().

00214 { 00215 /* implement in subclass! */ 00216 return true; 00217 }

bool VideoRenderer::updateDisplayRegion  )  [protected]
 

Update frame_info (except size) and display_region.

This function is not thread-safe, and is internally called by the open() method.

Reimplemented in QLabelRenderer, SDLRenderer, and X11Renderer.

Definition at line 111 of file VideoRenderer.cpp.

References display_region, es, and frame_info.

Referenced by X11Renderer::updateDisplayRegion(), SDLRenderer::updateDisplayRegion(), and QLabelRenderer::updateDisplayRegion().

00111 { 00112 int width, height; 00113 double scalex, scaley; 00114 double aspect; 00115 00116 if (!es || !es->isVisualStream()) { 00117 dprintf_err("VideoRenderer::updateDisplayRegion(): invalid member: es = %p\n", es); 00118 return false; 00119 } 00120 /* update frame_info */ 00121 frame_info.width = (int) es->getWidth(); 00122 frame_info.height = (int) es->getHeight(); 00123 /* compute frame display region with correct aspect ratio */ 00124 display_region.top = 0; 00125 display_region.left = 0; 00126 display_region.width = frame_info.width; 00127 display_region.height = frame_info.height; 00128 00129 aspect = (double) frame_info.width / (double) frame_info.height; 00130 if (es->getAspectRatio() > 0.0 && es->getAspectRatio() < 10.0) 00131 aspect = es->getAspectRatio(); 00132 width=display_region.width; 00133 height = (int) ((double) display_region.width / aspect); 00134 if (height < display_region.height) { //always scale up, not down! 00135 height= display_region.height; 00136 width = (int) ((double) display_region.height * aspect); 00137 } 00138 00139 // adjust to even value 00140 height += height % 2; 00141 if (height == 242 || height == 642) //quick hack, but works 00142 height -= 2; 00143 display_region.height = height; 00144 display_region.width = width; 00145 dprintf_full("VideoRenderer::updateDisplayRegion() aspect-correct frame size (%d x %d)\n" 00146 " aspect ratio = %5.3f (using: %5.3f)\n", 00147 display_region.width, display_region.height, 00148 es->getAspectRatio(), aspect); 00149 00150 /* if label/widget is resizeable, adjust out_label_info to display_region */ 00151 if (out_label_info.isLabelResizable) { 00152 out_label_info.width = display_region.width; 00153 out_label_info.height = display_region.height; 00154 scalex = scaley = 1.0; 00155 } else { 00156 /* otherwise, fit display_region into label */ 00157 width = out_label_info.width; 00158 height = out_label_info.height; 00159 if (display_region.width < width && !frame_info.allowUpscaleX) { 00160 width = display_region.width; 00161 } 00162 scalex = (double) width / (double) display_region.width; 00163 scaley = (double) height / (double) display_region.height; 00164 if ((scalex >= scaley && scaley >= 1.0) 00165 || (scaley <= scalex && scaley < 1.0)) { 00166 /* scale to height */ 00167 if (height == display_region.height) 00168 width = display_region.width; 00169 else 00170 width = (int) (display_region.width * scaley); 00171 } else if ((scaley >= scalex && scalex >= 1.0) 00172 || (scalex <= scaley && scalex < 1.0)) { 00173 /* scale to width */ 00174 if (width == display_region.width) 00175 height = display_region.height; 00176 else 00177 height = (int) (display_region.height * scalex); 00178 } 00179 // adjust width and height to even values 00180 width += width % 2; 00181 height += height % 2; 00182 display_region.width = width; 00183 display_region.height = height; 00184 } 00185 00186 dprintf_full("VideoRenderer::updateDisplayRegion() set display_region to (%d x %d)\n" 00187 " scalex = %5.3f, scaley = %5.3f, label/widget (%d x %d)\n", 00188 display_region.width, display_region.height, 00189 scalex, scaley, out_label_info.width, out_label_info.height); 00190 00191 if (display_region.width > out_label_info.width 00192 || display_region.height > out_label_info.height 00193 || display_region.width <= 0 00194 || display_region.height <= 0) { 00195 dprintf_err("VideoRenderer::updateDisplayRegion(): invalid size:\n" 00196 " video (%d x %d), qlabel (%d x %d)\n", 00197 display_region.width, display_region.height, 00198 out_label_info.width, out_label_info.height); 00199 return false; 00200 } 00201 /* center displayed region within label/widget */ 00202 display_region.left += (out_label_info.width - display_region.width) / 2; 00203 display_region.top += (out_label_info.height - display_region.height) / 2; 00204 /* update frame_info.scale{X,Y} */ 00205 frame_info.scaleX = DIV_FIXED(frame_info.width, display_region.width); 00206 frame_info.scaleY = DIV_FIXED(frame_info.height, display_region.height); 00207 00208 display_region.right = display_region.left + display_region.width; 00209 display_region.bottom = display_region.top + display_region.height; 00210 return true; 00211 }

int VideoRenderer::writeFrame Frame frm,
ESInfo out_es = NULL
[virtual]
 

Renders a frame to the destination QLabel widget.

Returns:
1 on success, 0 on error.

Implements IO.

Reimplemented in QLabelRenderer, SDLRenderer, and X11Renderer.

Definition at line 220 of file VideoRenderer.cpp.

References colorSpace, frame_info, frameBuffer, Frame::getAU(), VideoFrameBuffer::lock(), VideoFrameBuffer::postPaintEvent(), and VideoFrameBuffer::unlock().

Referenced by Visualizer::adapt(), X11Renderer::writeFrame(), SDLRenderer::writeFrame(), and QLabelRenderer::writeFrame().

00220 { 00221 struct AU *au; 00222 register int x, x0, y, y0; 00223 register u8 *pix, *pixline; 00224 register u32 yframe; 00225 register u32 one = INT2FIXED(1); 00226 00227 if (!frm || !frm->getAU()) { 00228 dprintf_err("VideoRenderer::writeFrame(): invalid parameter: frm = %p, au = %p\n", 00229 frm, frm ? (void *) frm->getAU() : NULL); 00230 state = STREAMERR; 00231 return 0; 00232 } 00233 if (state != OPEN) 00234 return 1; 00235 framesSeen++; 00236 /* we don't set currentFrameNumber, as we have no way to determine it! */ 00237 00238 au = frm->getAU(); 00239 if (au->size != (u32) frame_info.size) { 00240 dprintf_err("VideoRenderer::writeFrame(): frame size mismatch: expected %d bytes, " 00241 "got %u bytes\n", frame_info.size, au->size); 00242 state = STREAMERR; 00243 return 0; 00244 } 00245 00246 /* convert frame to frameBuffer, 00247 * scaling the frame according to frame_info.scaleX and frame_info.scaleY 00248 */ 00249 frameBuffer->lock(); 00250 switch (colorSpace) { 00251 case UncompressedVideoFrame::ColorSpaceGRAY8: 00252 CHOOSE_SCALE_FRAME(1, *pix) 00253 break; 00254 case UncompressedVideoFrame::ColorSpaceRGB24: 00255 if (outputDepth >= 24) { 00256 //note: it is BGR! 00257 CHOOSE_SCALE_FRAME(3, (pix[0] << 16) | (pix[1] << 8) | pix[2]) 00258 } else { 00259 CHOOSE_SCALE_FRAME(3, ((pix[0] >> 3) << 11) + ((pix[1] >> 2) << 5) + (pix[2] >> 3)) 00260 // CHOOSE_SCALE_FRAME(3, ((pix[2] >> 11) << 11) + ((pix[1] >> 10) << 5) + (pix[0] >> 11)) 00261 } 00262 break; 00263 case UncompressedVideoFrame::ColorSpaceRGB32: 00264 /* Qt expected input format: BGRA */ 00265 // CHOOSE_SCALE_FRAME(4, qRgba(pix[2], pix[1], pix[0], pix[3])) 00266 /* SDL expected input format: ARGB */ 00267 // CHOOSE_SCALE_FRAME(4, (pix[3] << 24) | (pix[2] << 16) | (pix[1] << 8) | pix[0]) 00268 /* X11 expected input format: ARGB */ 00269 00270 00271 //note: it is RGB! 00272 if (outputDepth >= 24) 00273 CHOOSE_SCALE_FRAME(4, (pix[3] << 24) | (pix[2] << 16) | (pix[1] << 8) | pix[0]) 00274 else 00275 CHOOSE_SCALE_FRAME(4, ((pix[2] >> 3) << 11) + ((pix[1] >> 2) << 5) + (pix[0] >> 3)) 00276 00277 break; 00278 case UncompressedVideoFrame::ColorSpaceRGB565: 00279 /* How Do I Convert RGB5XX into a 16-bit number? 00280 * #define RGB565(r, g, b) ((r >> 3) << 11)| ((g >> 2) << 5)| ((b >> 3) << 0) 00281 * #define RGB555(r, g, b) ((r >> 3) << 10)| ((g >> 3) << 5)| ((b >> 3) << 0) 00282 */ 00283 00284 if (outputDepth >= 24) { 00285 //FIXME: the RGB green-part is fucked up, and I don't find the problem :( 00286 00287 //scale up from 16 to 24 bit 00288 // CHOOSE_SCALE_FRAME(2, ((pix[0] << 3) <<0) | (pix[0] >>5 | pix[1] >>5 <<3)<<8 | ((pix[1] << 3)>>3)<<16 ) 00289 CHOOSE_SCALE_FRAME(2, ((pix[0] << 3)) /*blue*/ | ((pix[1] << 3)>>3<<16) /*red*/ 00290 | pix[0] >>5<<10 | pix[1] >>5 <<13 /*green*/ ) 00291 00292 } else { 00293 CHOOSE_SCALE_FRAME(2, (pix[1]<<8) | pix[0]) 00294 } 00295 break; 00296 default: 00297 /* make compiler happy */ 00298 break; 00299 } 00300 frameBuffer->unlock(); 00301 dprintf_full("VideoRenderer::writeFrame() posting paint event to frame buffer\n"); 00302 frameBuffer->postPaintEvent(); 00303 00304 00305 00306 #ifdef _POSIX_PRIORITY_SCHEDULING 00307 sched_yield(); //this is necessary to give parallel getFrames a chance 00308 #endif 00309 00310 return 1; 00311 }


Member Data Documentation

VideoRect VideoRenderer::display_region [protected]
 

apect-ratio adjusted region of qlabel where frames will be displayed.

Frame dimensions may be smaller than display_region and out_label_info dimensions. Definition at line 247 of file VideoRenderer.hpp.

Referenced by updateDisplayRegion().

VideoRect VideoRenderer::frame_info [protected]
 

Dimension, storage size (in bytes), and scaling factors of a decoded video frame.

The scaling factors are defined as
sx = frame_info.width / display_region.width
sy = frame_info.height / display_region.height

We use fixed point arithmetic with FIXED_DIGITS binary precision, so
scaleX = (int) (sx * 2^FIXED_DIGITS)

The product x * sx for an integer x is then computed as the scaled integer product
(x * scaleX) >> FIXED_DIGITS
which should be considerably faster than floating point multiplication. Definition at line 240 of file VideoRenderer.hpp.

Referenced by updateDisplayRegion(), VideoRenderer(), and writeFrame().


The documentation for this class was generated from the following files: