OGMDecodeInputPin.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2003-2006 Zentaro Kavanagh
00003 //
00004 //Redistribution and use in source and binary forms, with or without
00005 //modification, are permitted provided that the following conditions
00006 //are met:
00007 //
00008 //- Redistributions of source code must retain the above copyright
00009 //  notice, this list of conditions and the following disclaimer.
00010 //
00011 //- Redistributions in binary form must reproduce the above copyright
00012 //  notice, this list of conditions and the following disclaimer in the
00013 //  documentation and/or other materials provided with the distribution.
00014 //
00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 
00016 //  may be used to endorse or promote products derived from this software 
00017 //  without specific prior written permission.
00018 //
00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00022 //PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 //===========================================================================
00031 
00032 #include "stdafx.h"
00033 #include "OGMDecodeInputPin.h"
00034 
00035 OGMDecodeInputPin::OGMDecodeInputPin(OGMDecodeFilter* inParentFilter, HRESULT* outHR)
00036         :       CTransformInputPin(NAME("OGMDecodeInputPin"), inParentFilter, outHR, L"OGM In")
00037         ,       mVideoFormatBlock(NULL)
00038         ,       mAudioFormatBlock(NULL)
00039         ,       mSetupState(VSS_SEEN_NOTHING)
00040         ,       mOGMMediaType(OGM_UNKNOWN_TYPE)
00041         ,       mGranuleRateNumerator(1)
00042         ,       mGranuleRateDenominator(0)
00043 {
00044 
00045 }
00046 
00047 OGMDecodeInputPin::~OGMDecodeInputPin(void)
00048 {
00049 
00050 }
00051 
00052 STDMETHODIMP OGMDecodeInputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00053 {
00054         if (riid == IID_IMediaSeeking) {
00055                 *ppv = (IMediaSeeking*)this;
00056                 ((IUnknown*)*ppv)->AddRef();
00057                 return NOERROR;
00058         } else if (riid == IID_IOggDecoder) {
00059                 *ppv = (IOggDecoder*)this;
00060                 //((IUnknown*)*ppv)->AddRef();
00061                 return NOERROR;
00062 
00063         }
00064 
00065         return CBaseInputPin::NonDelegatingQueryInterface(riid, ppv); 
00066 }
00067 
00068 HRESULT OGMDecodeInputPin::SetMediaType(const CMediaType* inMediaType) 
00069 {
00070         //FIX:::Error checking
00071         //RESOLVED::: Bit better.
00072         if (CheckMediaType(inMediaType) == S_OK) {
00073                 //((OGMDecodeFilter*)m_pFilter)->setOGMFormat(inMediaType->pbFormat);
00074                 
00075         } else {
00076                 throw 0;
00077         }
00078         return CBaseInputPin::SetMediaType(inMediaType);
00079 
00080 }
00081 
00082 HRESULT OGMDecodeInputPin::CheckMediaType(const CMediaType* inMediaType)
00083 {
00084         //VIDSPEC::: Use the audio and text ident fields
00085         if (            (inMediaType->majortype == MEDIATYPE_OggPacketStream)
00086                         &&      (inMediaType->subtype == MEDIASUBTYPE_None)
00087                         &&      (inMediaType->formattype == FORMAT_OggIdentHeader)) {
00088                                 //TODO::: The header size is not fixed. This is just a minimum size.
00089                                 //                      need to look in the size field to determine the actual
00090                                 //                      size of the header as some codecs can include extra data
00091                                 //                      after the ogm headers
00092                                 //PARTIAL RESOLUTION::: Now a minimum size but should still check for
00093                                 //                      validity by checking the size field
00094                 if (inMediaType->cbFormat >= OGM_IDENT_HEADER_SIZE) {
00095                         if (strncmp((char*)inMediaType->pbFormat, "\001video\000\000\000", 9) == 0) {
00096                                 //TODO::: Possibly verify version
00097                                 return S_OK;
00098                         } else if (strncmp((char*)inMediaType->pbFormat, "\001audio\000\000\000", 9) == 0) {
00099                                 return S_OK;
00100                         } else if (strncmp((char*)inMediaType->pbFormat, "\001text\000\000\000\000", 9) == 0) {
00101                                 return S_OK;
00102                         }
00103                 }
00104         }
00105         return S_FALSE;
00106         
00107 }
00108 HRESULT OGMDecodeInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *outRequestedProps)
00109 {
00110         outRequestedProps->cbBuffer = OGM_BUFFER_SIZE;
00111         outRequestedProps->cBuffers = OGM_NUM_BUFFERS;
00112         outRequestedProps->cbAlign = 1;
00113         outRequestedProps->cbPrefix = 0;
00114 
00115         return S_OK;
00116 }
00117 LOOG_INT64 OGMDecodeInputPin::convertGranuleToTime(LOOG_INT64 inGranule)
00118 {
00119         switch (mOGMMediaType) {
00120                 case OGM_VIDEO_TYPE:
00121                         return inGranule * mVideoFormatBlock->AvgTimePerFrame;
00122                 case OGM_AUDIO_TYPE:
00123                         return (inGranule * UNITS) / mAudioFormatBlock->nSamplesPerSec;
00124                 case OGM_TEXT_TYPE:
00125                         return (inGranule * UNITS * mGranuleRateDenominator) / mGranuleRateNumerator;
00126                 default:
00127                         return 0;
00128         };
00129         
00130 }
00131 
00132 LOOG_INT64 OGMDecodeInputPin::mustSeekBefore(LOOG_INT64 inGranule)
00133 {
00134         //TODO::: Get adjustment from block size info... for now, it doesn't matter if no preroll
00135         return inGranule;
00136 }
00137 IOggDecoder::eAcceptHeaderResult OGMDecodeInputPin::showHeaderPacket(OggPacket* inCodecHeaderPacket)
00138 {
00139         switch (mSetupState) {
00140                 case VSS_SEEN_NOTHING:
00141                         //VIDSPEC::: Also accept the audio and text headers
00142                         if (strncmp((char*)inCodecHeaderPacket->packetData(), "\001video\000\000\000", 9) == 0) {
00143                                 mOGMMediaType = OGM_VIDEO_TYPE;
00144                                 handleHeaderPacket(inCodecHeaderPacket);
00145                                 mSetupState = VSS_SEEN_BOS;
00146                                 return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00147                         } else if (strncmp((char*)inCodecHeaderPacket->packetData(), "\001audio\000\000\000", 9) == 0) {
00148                                 //TODO::: Verify that there are secondary comment headers for audio and text
00149                                 mOGMMediaType = OGM_AUDIO_TYPE;
00150                                 handleHeaderPacket(inCodecHeaderPacket);
00151                                 mSetupState = VSS_SEEN_BOS;
00152                                 return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00153                         } else if (strncmp((char*)inCodecHeaderPacket->packetData(), "\001text\000\000\000\000", 9) == 0) {
00154                                 mOGMMediaType = OGM_TEXT_TYPE;
00155                                 handleHeaderPacket(inCodecHeaderPacket);
00156                                 mSetupState = VSS_SEEN_BOS;
00157                                 return IOggDecoder::AHR_MORE_HEADERS_TO_COME;
00158                         } else {
00159                                 mOGMMediaType = OGM_UNKNOWN_TYPE;
00160                         }
00161                         mSetupState = VSS_ERROR;
00162                         return IOggDecoder::AHR_INVALID_HEADER;
00163                         
00164                 case VSS_SEEN_BOS:
00165                         if (inCodecHeaderPacket->packetData()[0] == 0x03) {
00166                                 mSetupState = VSS_ALL_HEADERS_SEEN;
00167                                 return IOggDecoder::AHR_ALL_HEADERS_RECEIVED;
00168                         }
00169                         return IOggDecoder::AHR_INVALID_HEADER;
00170                 
00171         
00172                 case VSS_ALL_HEADERS_SEEN:
00173                 case VSS_ERROR:
00174                 default:
00175                         return IOggDecoder::AHR_UNEXPECTED;
00176         }
00177 }
00178 
00179 bool OGMDecodeInputPin::handleHeaderPacket(OggPacket* inHeaderPack)
00180 {
00181         switch(mOGMMediaType) {
00182                 case OGM_VIDEO_TYPE:
00183                         return handleVideoHeaderPacket(inHeaderPack);
00184                 case OGM_AUDIO_TYPE:
00185                         return handleAudioHeaderPacket(inHeaderPack);
00186 
00187                 case OGM_TEXT_TYPE:
00188                         return handleTextHeaderPacket(inHeaderPack);
00189                 default:
00190                         return false;
00191                 
00192         };
00193 }
00194 
00195 bool OGMDecodeInputPin::handleTextHeaderPacket(OggPacket* inHeaderPack)
00196 {
00197         mGranuleRateNumerator = iLE_Math::CharArrToInt64(inHeaderPack->packetData() + 17);
00198         mGranuleRateDenominator = iLE_Math::CharArrToInt64(inHeaderPack->packetData() + 25);
00199         
00200         //TODO:::
00201         return true;
00202 }
00203 bool OGMDecodeInputPin::handleAudioHeaderPacket(OggPacket* inHeaderPack)
00204 {
00205         delete mAudioFormatBlock;
00206 
00207         //TODO::: This will cause a problem with extra header information appended.
00208         //                      need to change to byte* and cast upon use
00209         mAudioFormatBlock = new WAVEFORMATEX;
00210 
00211         //FORMAT OF AUDIO HEADER IN OGM BOS
00212         //-----------------------------------------
00213 
00214         //0             -               8               =               STRING          Stream Type (char[8] is NULL) \001audio
00215         //9             -               12              =               STRING          Sub Type (format code)
00216         //13    -               16              =               INT32           Size of structure ???
00217         //17    -               24              =               INT64           Time per "unit" in DSHOW UNITS
00218         //25    -               32              =               INT64           Samples per "unit"
00219         //33    -               36              =               INT32           Deefault length ????? in media type ?? WTF ?
00220         //37    -               40              =               INT32           Buffer Size
00221         //41    -               42              =               INT16           Bits per sample
00222         //43    -               44              =               -----           HOLE IN DATA
00223         //45    -               46              =               INT16           Channel count
00224         //47    -               48              =               INT16           Block Align
00225         //49    -               52              =               INT32           Avg Bytes per Second
00226 
00227         mAudioFormatBlock->nAvgBytesPerSec = iLE_Math::charArrToULong(inHeaderPack->packetData() + 49);
00228         mAudioFormatBlock->nChannels = iLE_Math::charArrToUShort(inHeaderPack->packetData() + 45);
00229         mAudioFormatBlock->nBlockAlign = iLE_Math::charArrToUShort(inHeaderPack->packetData() + 47);
00230         
00231         //TODO::: Check if this needs to be div/mul by the time per unit field
00232         mAudioFormatBlock->nSamplesPerSec = iLE_Math::CharArrToInt64(inHeaderPack->packetData() + 25);
00233 
00234         mAudioFormatBlock->wBitsPerSample = iLE_Math::charArrToUShort(inHeaderPack->packetData() + 41);
00235         
00236         //TODO::: Extra header size
00237         mAudioFormatBlock->cbSize = sizeof(WAVEFORMATEX);
00238 
00239         
00240         unsigned short locFormatCode = 0;
00241         unsigned char locHexDigitValue = 0;
00242         for (int i = 0; i < 4; i++) {
00243                 locFormatCode <<= 4;
00244                 locHexDigitValue = inHeaderPack->packetData()[9 + i];
00245 
00246                 if ((locHexDigitValue >= '0') && (locHexDigitValue <= '9')) {
00247                         locHexDigitValue -= '0';
00248                 } else if ((locHexDigitValue >= 'a') && (locHexDigitValue <= 'f')) {
00249                         locHexDigitValue -= 'a';
00250                         locHexDigitValue += 10;
00251                 } else if ((locHexDigitValue >= 'A') && (locHexDigitValue <= 'F')) {
00252                         locHexDigitValue -= 'A';
00253                         locHexDigitValue += 10;
00254                 } else {
00255                         //This is a fatal error.
00256                         throw 0;
00257                 }
00258 
00259                 locFormatCode += locHexDigitValue;
00260         }
00261 
00262         mAudioFormatBlock->wFormatTag = locFormatCode;
00263 
00264         return true;
00265 
00266 }
00267 bool OGMDecodeInputPin::handleVideoHeaderPacket(OggPacket* inHeaderPack)
00268 {
00269         //VIDSPEC::: This whole thing is specific to video
00270         delete mVideoFormatBlock;
00271         mVideoFormatBlock = new VIDEOINFOHEADER;
00272 
00273         //FORMAT OF VIDEO HEADER IN OGM BOS
00274         //-----------------------------------------
00275 
00276         //0             -               8               =               STRING          Stream Type (char[8] is NULL) \001video
00277         //9             -               12              =               STRING          Sub Type (FOURCC)
00278         //13    -               16              =               INT32           Size of structure ???
00279         //17    -               24              =               INT64           Time per "unit" in DSHOW UNITS
00280         //25    -               32              =               INT64           Samples per "unit"
00281         //33    -               36              =               INT32           Deefault length ????? in media type ?? WTF ?
00282         //37    -               40              =               INT32           Buffer Size
00283         //41    -               42              =               INT16           Bits per sample
00284         //43    -               44              =               -----           HOLE IN DATA
00285         //45    -               48              =               INT32           Video Width
00286         //49    -               52              =               INT32           Video Height
00287 
00288 
00289 
00290  
00291 
00292         //------------------------------------------
00293 
00294         
00295         __int64 locTimePerBlock = iLE_Math::CharArrToInt64(inHeaderPack->packetData() + 17);
00296 
00297         
00298         __int64 locSamplesPerBlock = iLE_Math::CharArrToInt64(inHeaderPack->packetData() + 25);
00299 
00300         //debugLog<<"t/block = "<<locTimePerBlock<<"        Sam/block = "<<locSamplesPerBlock<<endl;
00301 
00302         mVideoFormatBlock->AvgTimePerFrame = locTimePerBlock / locSamplesPerBlock;
00303 
00304         //debugLog<<"Time per frame = "<<mVideoFormatBlock->AvgTimePerFrame<<endl;
00305 
00306         __int64 locFPSec = (UNITS / locTimePerBlock) * locSamplesPerBlock;
00307 
00308         //debugLog<<"Rate = "<<locFPSec<<" fps"<<endl;
00309         unsigned short locBPSample = ((unsigned char)(inHeaderPack->packetData()[41])) + (((unsigned short)(inHeaderPack->packetData()[42])) * 256);
00310 
00311         
00312         
00313         mVideoFormatBlock->bmiHeader.biBitCount = locBPSample;
00314         mVideoFormatBlock->bmiHeader.biClrImportant = 0;   //All colours important
00315         mVideoFormatBlock->bmiHeader.biClrUsed = 0;        //Use max colour depth
00316         mVideoFormatBlock->bmiHeader.biCompression = MAKEFOURCC(inHeaderPack->packetData()[9], inHeaderPack->packetData()[10], inHeaderPack->packetData()[11], inHeaderPack->packetData()[12]);;
00317 
00318         unsigned long locHeight = iLE_Math::charArrToULong(inHeaderPack->packetData() + 49);
00319         unsigned long locWidth =  iLE_Math::charArrToULong(inHeaderPack->packetData() + 45);
00320 
00321         mVideoFormatBlock->dwBitRate = 0;
00322 
00323         mVideoFormatBlock->bmiHeader.biHeight = locHeight;
00324         mVideoFormatBlock->bmiHeader.biPlanes = 1;    //Must be 1
00325         mVideoFormatBlock->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);    //????? Size of what ?
00326         mVideoFormatBlock->bmiHeader.biSizeImage = (locHeight * locWidth * locBPSample) / 8;    //Size in bytes of image ??
00327         mVideoFormatBlock->bmiHeader.biWidth = locWidth;
00328         mVideoFormatBlock->bmiHeader.biXPelsPerMeter = 2000;   //Fuck knows
00329         mVideoFormatBlock->bmiHeader.biYPelsPerMeter = 2000;   //" " " " " 
00330         
00331         mVideoFormatBlock->rcSource.top = 0;
00332         mVideoFormatBlock->rcSource.bottom = locHeight;
00333         mVideoFormatBlock->rcSource.left = 0;
00334         mVideoFormatBlock->rcSource.right = locWidth;
00335 
00336         mVideoFormatBlock->rcTarget.top = 0;
00337         mVideoFormatBlock->rcTarget.bottom = locHeight;
00338         mVideoFormatBlock->rcTarget.left = 0;
00339         mVideoFormatBlock->rcTarget.right = locWidth;
00340 
00341         mVideoFormatBlock->dwBitErrorRate=0;
00342         return true;
00343 }
00344 string OGMDecodeInputPin::getCodecShortName()
00345 {
00346         //TODO::: These should also include the information about the fourcc or format code
00347         return "OGM";
00348 }
00349 string OGMDecodeInputPin::getCodecIdentString()
00350 {
00351         //TODO:::
00352         return "OGM";
00353 }
00354 

Generated on Thu Feb 16 23:48:07 2006 for oggdsf by  doxygen 1.3.9