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