oggTheoraDecoder.h
Engine/source/core/ogg/oggTheoraDecoder.h
Classes:
class
Decodes a Theora substream into frame packets.
class
Descriptor for surface format that this stream should decode into.
class
A single decoded Theora video frame.
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#ifndef _OGGTHEORADECODER_H_ 25#define _OGGTHEORADECODER_H_ 26 27#ifndef _OGGINPUTSTREAM_H_ 28 #include "core/ogg/oggInputStream.h" 29#endif 30#ifndef _TSTREAM_H_ 31 #include "core/stream/tStream.h" 32#endif 33#ifndef _RAWDATA_H_ 34 #include "core/util/rawData.h" 35#endif 36#ifndef _GFXENUMS_H_ 37 #include "gfx/gfxEnums.h" 38#endif 39#ifndef _THREADSAFEDEQUE_H_ 40 #include "platform/threads/threadSafeDeque.h" 41#endif 42#include "theora/theoradec.h" 43 44 45/// A single decoded Theora video frame. 46class OggTheoraFrame : public RawData 47{ 48 public: 49 50 typedef RawData Parent; 51 52 OggTheoraFrame() :mFrameNumber(0), mFrameTime(0), mFrameDuration(0) {} 53 OggTheoraFrame( S8* data, U32 size, bool ownMemory = false ) 54 : Parent( data, size, ownMemory ), mFrameNumber(0), mFrameTime(0), mFrameDuration(0) {} 55 56 /// Serial number of this frame in the stream. 57 U32 mFrameNumber; 58 59 /// Playtime in seconds at which to display this frame. 60 F32 mFrameTime; 61 62 /// Seconds to display this frame. 63 F32 mFrameDuration; 64}; 65 66 67/// Decodes a Theora substream into frame packets. 68/// 69/// Frame packets contain raw pixel data in the set pixel format (default is R8G8B8). 70/// Reading on a thread is safe, but remember to keep a reference to the OggInputStream 71/// master from the worker thread. 72class OggTheoraDecoder : public OggDecoder, 73 public IInputStream< OggTheoraFrame* > 74{ 75 public: 76 77 typedef OggDecoder Parent; 78 79 /// Y'CbCr pixel format of the source video stream. 80 /// For informational purposes only. Packet out is determined 81 /// by PacketFormat. 82 enum EPixelFormat 83 { 84 PIXEL_FORMAT_444, // Full Y, full Cb, full Cr. 85 PIXEL_FORMAT_422, // Full Y, half-width Cb, half-width Cr. 86 PIXEL_FORMAT_420, // Full Y, half-widht+height Cb, half-width+height Cr. 87 PIXEL_FORMAT_Unknown 88 }; 89 90 /// Descriptor for surface format that this stream should 91 /// decode into. This saves an otherwise potentitally necessary 92 /// swizzling step. 93 /// 94 /// @note The output channel ordering will be in device format, i.e. 95 /// least-significant first. 96 struct PacketFormat 97 { 98 /// Pixel format. 99 GFXFormat mFormat; 100 101 /// Bytes per scanline. 102 U32 mPitch; 103 104 /// Default descriptor sets up for RGB. 105 PacketFormat() 106 : mFormat( GFXFormatR8G8B8 ), 107 mPitch( 0 ) {} 108 109 /// 110 PacketFormat( GFXFormat format, U32 pitch ) 111 : mFormat( format ), 112 mPitch( pitch ) {} 113 }; 114 115 /// 116 enum ETranscoder 117 { 118 TRANSCODER_Auto, ///< Auto-detect from current formats and processor capabilities. 119 TRANSCODER_Generic, ///< Generic transcoder that handles all source and target formats; 32bit integer + lookup tables. 120 TRANSCODER_SSE2420RGBA, ///< SSE2 transcoder with fixed 4:2:0 to RGBA conversion; 32bit integer + lookup tables. 121 }; 122 123 protected: 124 125 typedef IPositionable< U32>* TimeSourceRef; 126 127 /// @name libtheora Data 128 /// @{ 129 130 /// 131 th_comment mTheoraComment; 132 133 /// 134 th_info mTheoraInfo; 135 136 /// 137 th_setup_info* mTheoraSetup; 138 139 /// 140 th_dec_ctx* mTheoraDecoder; 141 142 /// @} 143 144 /// 145 PacketFormat mPacketFormat; 146 147 /// 148 F32 mFrameDuration; 149 150 /// 151 F32 mCurrentFrameTime; 152 153 /// 154 U32 mCurrentFrameNumber; 155 156 /// If this is set, the decoder will drop frames that are 157 /// already outdated with respect to the time source. 158 /// 159 /// @note Times are in milliseconds and in video time. 160 TimeSourceRef mTimeSource; 161 162 /// Transcoder to use for color space conversion. If the current 163 /// setting is invalid, will fall back to generic. 164 ETranscoder mTranscoder; 165 166 /// 167 ThreadSafeDeque< OggTheoraFrame*> mFreePackets; 168 169 #ifdef TORQUE_DEBUG 170 U32 mLock; 171 #endif 172 173 /// Generic transcoder going from any of the Y'CbCr pixel formats to 174 /// any RGB format (that is supported by GFXFormatUtils). 175 void _transcode( th_ycbcr_buffer ycbcr, U8* buffer, U32 width, U32 height ); 176#if defined( TORQUE_CPU_X86 ) 177 /// Transcoder with fixed 4:2:0 to RGBA conversion using SSE2 assembly. Unused on 64 bit archetecture. 178 void _transcode420toRGBA_SSE2( th_ycbcr_buffer ycbcr, U8* buffer, U32 width, U32 height, U32 pitch ); 179#endif 180 // OggDecoder. 181 virtual bool _detect( ogg_page* startPage ); 182 virtual bool _init(); 183 virtual bool _packetin( ogg_packet* packet ); 184 185 /// 186 U32 _getPixelOffset( th_ycbcr_buffer buffer, U32 plane, U32 x, U32 y ) const 187 { 188 switch( getDecoderPixelFormat() ) 189 { 190 case PIXEL_FORMAT_444: break; 191 case PIXEL_FORMAT_422: if( plane != 0 ) x >>= 1; break; 192 case PIXEL_FORMAT_420: if( plane != 0 ) { x >>= 1; y >>= 1; } break; 193 194 default: 195 AssertFatal( false, "OggTheoraDecoder::_getPixelOffset() - invalid pixel format" ); 196 } 197 198 return ( y * buffer[ plane ].stride + x ); 199 } 200 201 /// 202 U8* _getPixelPtr( th_ycbcr_buffer buffer, U32 plane, U32 offset, U32 x, U32 y ) const 203 { 204 return ( buffer[ plane ].data + offset + _getPixelOffset( buffer, plane, x, y ) ); 205 } 206 207 /// 208 U32 _getPictureOffset( th_ycbcr_buffer buffer, U32 plane ) 209 { 210 return _getPixelOffset( buffer, plane, mTheoraInfo.pic_x, mTheoraInfo.pic_y ); 211 } 212 213 public: 214 215 /// 216 OggTheoraDecoder( const ThreadSafeRef< OggInputStream>& stream ); 217 218 ~OggTheoraDecoder(); 219 220 /// Return the width of video image frames in pixels. 221 /// @note This returns the actual picture width rather than Theora's internal encoded frame width. 222 U32 getFrameWidth() const { return mTheoraInfo.pic_width; } 223 224 /// Return the height of video image frames in pixels. 225 /// @note This returns the actual picture height rather than Theora's internal encoded frame height. 226 U32 getFrameHeight() const { return mTheoraInfo.pic_height; } 227 228 /// 229 F32 getFramesPerSecond() const { return ( F32( mTheoraInfo.fps_numerator ) / F32( mTheoraInfo.fps_denominator ) ); } 230 231 /// 232 EPixelFormat getDecoderPixelFormat() const 233 { 234 switch( mTheoraInfo.pixel_fmt ) 235 { 236 case TH_PF_444: return PIXEL_FORMAT_444; 237 case TH_PF_422: return PIXEL_FORMAT_422; 238 case TH_PF_420: return PIXEL_FORMAT_420; 239 default: return PIXEL_FORMAT_Unknown; 240 } 241 } 242 243 /// 244 const PacketFormat& getPacketFormat() const { return mPacketFormat; } 245 246 /// 247 void setPacketFormat( const PacketFormat& format ) { mPacketFormat = format; } 248 249 /// Set the reference time source. Frames will be dropped if the decoder 250 /// falls behind the time of this source. 251 /// 252 /// @note The time source must have at least the same lifetime as the decoder. 253 void setTimeSource( const TimeSourceRef& timeSource ) { mTimeSource = timeSource; } 254 255 /// Set the Y'CbCr->RGB transcoder to use. 256 void setTranscoder( ETranscoder transcoder ) { mTranscoder = transcoder; } 257 258 /// 259 void reusePacket( OggTheoraFrame* packet ) { mFreePackets.pushBack( packet ); } 260 261 // OggDecoder. 262 virtual const char* getName() const { return "Theora"; } 263 264 // IInputStream. 265 virtual U32 read( OggTheoraFrame** buffer, U32 num ); 266}; 267 268#endif // !_OGGTHEORADECODER_H_ 269