1 /* 2 * vconvert.h 3 * 4 * Classes to support streaming video input (grabbing) and output. 5 * 6 * Portable Windows Library 7 * 8 * Copyright (c) 1993-2000 Equivalence Pty. Ltd. 9 * 10 * The contents of this file are subject to the Mozilla Public License 11 * Version 1.0 (the "License"); you may not use this file except in 12 * compliance with the License. You may obtain a copy of the License at 13 * http://www.mozilla.org/MPL/ 14 * 15 * Software distributed under the License is distributed on an "AS IS" 16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 17 * the License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * The Original Code is Portable Windows Library. 21 * 22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd. 23 * 24 * Contributor(s): Derek Smithies (derek@indranet.co.nz) 25 * Thorsten Westheider (thorsten.westheider@teleos-web.de) 26 * Mark Cooke (mpc@star.sr.bham.ac.uk) 27 * 28 * $Revision: 26686 $ 29 * $Author: rjongbloed $ 30 * $Date: 2011-11-23 20:22:20 -0600 (Wed, 23 Nov 2011) $ 31 */ 32 33 #ifndef PTLIB_CONVERT_H 34 #define PTLIB_CONVERT_H 35 36 #ifdef P_USE_PRAGMA 37 #ifndef P_MACOSX 38 #pragma interface 39 #endif 40 #endif 41 42 #include <ptbuildopts.h> 43 44 #if P_VIDEO 45 46 #include <ptlib/videoio.h> 47 48 struct jdec_private; 49 50 51 /**This class registers a colour conversion class. 52 There should be one and one only instance of this class for each pair of 53 srcColurFormat and dstColourFormat strings. Use the 54 PCOLOUR_CONVERTER_REGISTRATION macro to do this. 55 */ 56 class PColourConverterRegistration : public PCaselessString 57 { 58 PCLASSINFO(PColourConverterRegistration, PCaselessString); 59 public: 60 PColourConverterRegistration( 61 const PString & srcColourFormat, ///< Name of source colour format 62 const PString & destColourFormat ///< Name of destination colour format 63 ); 64 65 protected: 66 virtual PColourConverter * Create( 67 const PVideoFrameInfo & src, ///< Source frame info (colour formet, size etc) 68 const PVideoFrameInfo & dst ///< Destination frame info 69 ) const = 0; 70 71 PColourConverterRegistration * link; 72 73 friend class PColourConverter; 74 }; 75 76 77 /**This class defines a means to convert an image from one colour format to another. 78 It is an ancestor class for the individual formatting functions. 79 */ 80 class PColourConverter : public PObject 81 { 82 PCLASSINFO(PColourConverter, PObject); 83 public: 84 /**Create a new converter. 85 */ 86 PColourConverter( 87 const PString & srcColourFormat, ///< Name of source colour format 88 const PString & dstColourFormat, ///< Name of destination colour format 89 unsigned width, ///< Width of frame 90 unsigned height ///< Height of frame 91 ); 92 PColourConverter( 93 const PVideoFrameInfo & src, ///< Source frame info (colour formet, size etc) 94 const PVideoFrameInfo & dst ///< Destination frame info 95 ); 96 97 /// Print description of converter 98 virtual void PrintOn( 99 ostream & strm 100 ) const; 101 102 /**Get the video conversion vertical flip state 103 */ GetVFlipState()104 PBoolean GetVFlipState() 105 { return verticalFlip; } 106 107 /**Set the video conversion vertical flip state 108 */ SetVFlipState(PBoolean vFlipState)109 void SetVFlipState( 110 PBoolean vFlipState ///< New state for flipping images 111 ) { verticalFlip = vFlipState; } 112 113 /**Set the frame size to be used. 114 115 Default behaviour calls SetSrcFrameSize() and SetDstFrameSize(). 116 */ 117 virtual PBoolean SetFrameSize( 118 unsigned width, ///< New width of frame 119 unsigned height ///< New height of frame 120 ); 121 122 /**Set the source frame info to be used. 123 124 Default behaviour sets the srcFrameWidth and srcFrameHeight variables and 125 recalculates the frame buffer size in bytes then returns true if the size 126 was calculated correctly. 127 128 Returns false if the colour formats do not agree. 129 */ 130 virtual PBoolean SetSrcFrameInfo( 131 const PVideoFrameInfo & info ///< New info for frame 132 ); 133 134 /**Set the destination frame info to be used. 135 136 Default behaviour sets the dstFrameWidth and dstFrameHeight variables, 137 and the scale / crop preference. It then recalculates the frame buffer 138 size in bytes then returns true if the size was calculated correctly. 139 140 Returns false if the colour formats do not agree. 141 */ 142 virtual PBoolean SetDstFrameInfo( 143 const PVideoFrameInfo & info ///< New info for frame 144 ); 145 146 /**Get the source frame info to be used. 147 */ 148 virtual void GetSrcFrameInfo( 149 PVideoFrameInfo & info ///< New info for frame 150 ); 151 152 /**Get the destination frame info to be used. 153 */ 154 virtual void GetDstFrameInfo( 155 PVideoFrameInfo & info ///< New info for frame 156 ); 157 158 /**Set the source frame size to be used. 159 160 Default behaviour sets the srcFrameWidth and srcFrameHeight variables and 161 recalculates the frame buffer size in bytes then returns true if the size 162 was calculated correctly. 163 */ 164 virtual PBoolean SetSrcFrameSize( 165 unsigned width, ///< New width of frame 166 unsigned height ///< New height of frame 167 ); 168 169 /**Set the destination frame size to be used. 170 171 Default behaviour sets the dstFrameWidth and dstFrameHeight variables, 172 and the scale / crop preference. It then recalculates the frame buffer 173 size in bytes then returns true if the size was calculated correctly. 174 */ 175 virtual PBoolean SetDstFrameSize( 176 unsigned width, ///< New width of target frame 177 unsigned height ///< New height of target frame 178 ); 179 virtual PBoolean SetDstFrameSize( 180 unsigned width, ///< New width of target frame 181 unsigned height, ///< New height of target frame 182 PBoolean bScale ///< Indicate if scaling or cropping is to be used 183 ); 184 185 /**Get the source colour format. 186 */ GetSrcColourFormat()187 const PString & GetSrcColourFormat() { return srcColourFormat; } 188 189 /**Get the destination colour format. 190 */ GetDstColourFormat()191 const PString & GetDstColourFormat() { return dstColourFormat; } 192 193 /**Get the maximum frame size in bytes for source frames. 194 195 Note a particular device may be able to provide variable length 196 frames (eg motion JPEG) so will be the maximum size of all frames. 197 */ GetMaxSrcFrameBytes()198 PINDEX GetMaxSrcFrameBytes() { return srcFrameBytes; } 199 200 /**Get the maximum frame size in bytes for destination frames. 201 202 Note a particular device may be able to provide variable length 203 frames (eg motion JPEG) so will be the maximum size of all frames. 204 */ GetMaxDstFrameBytes()205 PINDEX GetMaxDstFrameBytes() { return dstFrameBytes; } 206 207 208 /**Convert from one colour format to another. 209 This version will copy the data from one frame buffer to another. 210 An implementation of this function should allow for the case of 211 where srcFrameBuffer and dstFrameBuffer are the same, if the conversion 212 algorithm allows for that to occur without an intermediate frame store. 213 214 The function should return false if srcFrameBuffer and dstFrameBuffer 215 are the same and that form pf conversion is not allowed 216 */ 217 virtual PBoolean Convert( 218 const BYTE * srcFrameBuffer, ///< Frame store for source pixels 219 BYTE * dstFrameBuffer, ///< Frame store for destination pixels 220 PINDEX * bytesReturned = NULL ///< Bytes written to dstFrameBuffer 221 ) = 0; 222 223 virtual PBoolean Convert( 224 const BYTE * srcFrameBuffer, ///< Frame store for source pixels 225 BYTE * dstFrameBuffer, ///< Frame store for destination pixels 226 unsigned int srcFrameBytes, ///< Bytes used in source frame buffer 227 PINDEX * bytesReturned = NULL ///< Bytes written to dstFrameBuffer 228 ) = 0; 229 230 /**Convert from one colour format to another. 231 This version will copy the data from one frame buffer to the same frame 232 buffer. Not all conversions can do this so an intermediate store and 233 copy may be required. If the noIntermediateFrame parameter is true 234 and the conversion cannot be done in place then the function returns 235 false. If the in place conversion can be done then that parameter is 236 ignored. 237 238 Note that the frame should be large enough to take the destination 239 pixels. 240 241 Default behaviour calls Convert() from the frameBuffer to itself, and 242 if that returns false then calls it again (provided noIntermediateFrame 243 is false) using an intermediate store, copying the intermediate store 244 back to the original frame store. 245 */ 246 virtual PBoolean ConvertInPlace( 247 BYTE * frameBuffer, ///< Frame buffer to translate data 248 PINDEX * bytesReturned = NULL, ///< Bytes written to frameBuffer 249 PBoolean noIntermediateFrame = false ///< Flag to use intermediate store 250 ); 251 252 253 /**Create an instance of a colour conversion function. 254 Returns NULL if there is no registered colour converter between the two 255 named formats. 256 */ 257 static PColourConverter * Create( 258 const PVideoFrameInfo & src, ///< Source frame info (colour formet, size etc) 259 const PVideoFrameInfo & dst ///< Destination frame info 260 ); 261 static PColourConverter * Create( 262 const PString & srcColourFormat, 263 const PString & destColourFormat, 264 unsigned width, 265 unsigned height 266 ); 267 268 /**Get the output frame size. 269 */ 270 PBoolean GetDstFrameSize( 271 unsigned & width, ///< Width of destination frame 272 unsigned & height ///< Height of destination frame 273 ) const; 274 275 /**Get the input frame size. 276 */ 277 PBoolean GetSrcFrameSize( 278 unsigned & width, ///< Width of source frame 279 unsigned & height ///< Height of source frame 280 ) const; 281 GetSrcFrameWidth()282 unsigned GetSrcFrameWidth() const { return srcFrameWidth; } GetSrcFrameHeight()283 unsigned GetSrcFrameHeight() const { return srcFrameHeight; } GetDstFrameWidth()284 unsigned GetDstFrameWidth() const { return dstFrameWidth; } GetDstFrameHeight()285 unsigned GetDstFrameHeight() const { return dstFrameHeight; } 286 287 /**Set the resize mode to be used. 288 */ SetResizeMode(PVideoFrameInfo::ResizeMode mode)289 void SetResizeMode( 290 PVideoFrameInfo::ResizeMode mode 291 ) { if (mode < PVideoFrameInfo::eMaxResizeMode) resizeMode = mode; } 292 293 /**Get the resize mode to be used. 294 */ GetResizeMode()295 PVideoFrameInfo::ResizeMode GetResizeMode() const { return resizeMode; } 296 297 /**Convert RGB to YUV. 298 */ 299 static void RGBtoYUV( 300 unsigned r, unsigned g, unsigned b, 301 unsigned & y, unsigned & u, unsigned & v 302 ); 303 static void RGBtoYUV( 304 unsigned r, unsigned g, unsigned b, 305 BYTE & y, BYTE & u, BYTE & v 306 ); 307 308 /**Copy a section of the source frame to a section of the destination 309 frame with scaling/cropping as required. 310 */ 311 static bool CopyYUV420P( 312 unsigned srcX, unsigned srcY, unsigned srcWidth, unsigned srcHeight, 313 unsigned srcFrameWidth, unsigned srcFrameHeight, const BYTE * srcYUV, 314 unsigned dstX, unsigned dstY, unsigned dstWidth, unsigned dstHeight, 315 unsigned dstFrameWidth, unsigned dstFrameHeight, BYTE * dstYUV, 316 PVideoFrameInfo::ResizeMode resizeMode 317 ); 318 319 static bool FillYUV420P( 320 unsigned x, unsigned y, int width, int height, 321 unsigned frameWidth, unsigned frameHeight, BYTE * yuv, 322 unsigned r, unsigned g, unsigned b 323 ); 324 325 protected: 326 void Construct( 327 const PVideoFrameInfo & src, ///< Source frame info (colour formet, size etc) 328 const PVideoFrameInfo & dst ///< Destination frame info 329 ); 330 331 PString srcColourFormat; 332 PString dstColourFormat; 333 unsigned srcFrameWidth; 334 unsigned srcFrameHeight; 335 unsigned srcFrameBytes; 336 337 // Needed for resizing 338 unsigned dstFrameWidth; 339 unsigned dstFrameHeight; 340 unsigned dstFrameBytes; 341 342 PVideoFrameInfo::ResizeMode resizeMode; 343 344 PBoolean verticalFlip; 345 346 PBYTEArray intermediateFrameStore; 347 348 #ifndef P_MACOSX 349 /* Use by the jpeg decompressor */ 350 struct jdec_private *jdec; 351 #endif 352 353 friend class PColourConverterRegistration; 354 }; 355 356 357 /**Declare a colour converter class with Convert() function. 358 This should only be used once and at the global scope level for each 359 converter. It declares everything needs so only the body of the Convert() 360 function need be added. 361 */ 362 #define PCOLOUR_CONVERTER2(cls,ancestor,srcFmt,dstFmt) \ 363 class cls : public ancestor { \ 364 public: \ 365 cls(const PVideoFrameInfo & src, const PVideoFrameInfo & dst) \ 366 : ancestor(src, dst) { } \ 367 virtual PBoolean Convert(const BYTE *, BYTE *, PINDEX * = NULL); \ 368 virtual PBoolean Convert(const BYTE *, BYTE *, unsigned int , PINDEX * = NULL); \ 369 }; \ 370 static class cls##_Registration : public PColourConverterRegistration { \ 371 public: cls##_Registration() \ 372 : PColourConverterRegistration(srcFmt,dstFmt) { } \ 373 protected: virtual PColourConverter * Create(const PVideoFrameInfo & src, const PVideoFrameInfo & dst) const; \ 374 } p_##cls##_registration_instance; \ 375 PColourConverter * cls##_Registration::Create(const PVideoFrameInfo & src, const PVideoFrameInfo & dst) const \ 376 { return new cls(src, dst); } \ 377 PBoolean cls::Convert(const BYTE *srcFrameBuffer, BYTE *dstFrameBuffer, unsigned int p_srcFrameBytes, PINDEX * bytesReturned) \ 378 { srcFrameBytes = p_srcFrameBytes;return Convert(srcFrameBuffer, dstFrameBuffer, bytesReturned); } \ 379 PBoolean cls::Convert(const BYTE *srcFrameBuffer, BYTE *dstFrameBuffer, PINDEX * bytesReturned) 380 381 382 /**Declare a colour converter class with Convert() function. 383 This should only be used once and at the global scope level for each 384 converter. It declares everything needs so only the body of the Convert() 385 function need be added. 386 */ 387 #define PCOLOUR_CONVERTER(cls,src,dst) \ 388 PCOLOUR_CONVERTER2(cls,PColourConverter,src,dst) 389 390 391 392 /**Define synonym colour format converter. 393 This is a class that defines for which no conversion is required between 394 the specified colour format names. 395 */ 396 class PSynonymColour : public PColourConverter { 397 public: PSynonymColour(const PVideoFrameInfo & src,const PVideoFrameInfo & dst)398 PSynonymColour( 399 const PVideoFrameInfo & src, 400 const PVideoFrameInfo & dst 401 ) : PColourConverter(src, dst) { } 402 virtual PBoolean Convert(const BYTE *, BYTE *, PINDEX * = NULL); 403 virtual PBoolean Convert(const BYTE *, BYTE *, unsigned int , PINDEX * = NULL); 404 }; 405 406 407 /**Define synonym colour format registration. 408 This is a class that defines for which no conversion is required between 409 the specified colour format names. 410 */ 411 class PSynonymColourRegistration : public PColourConverterRegistration { 412 public: 413 PSynonymColourRegistration( 414 const char * srcFmt, 415 const char * dstFmt 416 ); 417 418 protected: 419 virtual PColourConverter * Create(const PVideoFrameInfo & src, const PVideoFrameInfo & dst) const; 420 }; 421 422 423 /**Define synonym colour format. 424 This is a class that defines for which no conversion is required between 425 the specified colour format names. 426 */ 427 #define PSYNONYM_COLOUR_CONVERTER(from,to) \ 428 static PSynonymColourRegistration p_##from##_##to##_registration_instance(#from,#to) 429 430 431 #endif // P_VIDEO 432 433 #endif // PTLIB_CONVERT_H 434 435 436 // End of file /////////////////////////////////////////////////////////////// 437