TheoraEncodeInputPin.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2003, 2004 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 "theoraencodeinputpin.h"
00034 
00035 TheoraEncodeInputPin::TheoraEncodeInputPin(AbstractTransformFilter* inParentFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
00036         :       AbstractTransformInputPin(inParentFilter, inFilterLock, inOutputPin, NAME("TheoraEncodeInputPin"), L"YV12 In", inAcceptableMediaTypes)
00037         ,       mXOffset(0)
00038         ,       mYOffset(0)
00039         ,       mHeight(0)
00040         ,       mWidth(0)
00041         ,       mUptoFrame(0)
00042         ,       mBegun(false)
00043         ,       mVideoFormat(NULL)
00044         
00045 
00046 {
00047         //debugLog.open("g:\\logs\\theoencfiltinput.log", ios_base::out);
00048         mYUV.y = NULL;
00049         mYUV.u = NULL;
00050         mYUV.v = NULL;
00051         
00052 }
00053 
00054 TheoraEncodeInputPin::~TheoraEncodeInputPin(void)
00055 {
00056         //debugLog.close();
00057         DestroyCodec();
00058         delete[] mYUV.y;
00059         delete[] mYUV.u;
00060         delete[] mYUV.v;
00061 
00062 }
00063 
00064 
00065 HRESULT TheoraEncodeInputPin::deliverData(LONGLONG inStart, LONGLONG inEnd, unsigned char* inBuf, unsigned long inNumBytes) {
00066         //debugLog <<" deliverData : "<<inStart<<" - "<<inEnd<<"  :: size = "<<inNumBytes<<endl;
00067         //Get a pointer to a new sample stamped with our time
00068         IMediaSample* locSample;
00069         HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, &inStart, &inEnd, NULL);
00070 
00071         if (locHR != S_OK) {
00072                 //We get here when the application goes into stop mode usually.
00073                 return locHR;
00074         }       
00075         
00076         BYTE* locBuffer = NULL;
00077 
00078         
00079         //Make our pointers set to point to the samples buffer
00080         locSample->GetPointer(&locBuffer);
00081 
00082         if (locSample->GetSize() >= inNumBytes) {
00083 
00084                 memcpy((void*)locBuffer, (const void*)inBuf, inNumBytes);
00085                 
00086                 //Set the sample parameters.
00087                 SetSampleParams(locSample, inNumBytes, &inStart, &inEnd);
00088 
00089                 {
00090                         CAutoLock locLock(m_pLock);
00091 
00092                         HRESULT locHR = ((TheoraEncodeOutputPin*)mOutputPin)->mDataQueue->Receive(locSample);                                           //->DownstreamFilter()->Receive(locSample);
00093                         if (locHR != S_OK) {
00094                                 return locHR;   
00095                         } else {
00096                         }
00097                 }
00098                 //debugLog<<"deliverData : SUCCESS"<<endl;
00099                 return S_OK;
00100         } else {
00101                 //debugLog<<"Buffer too small !!!! FATALITY !"<<endl;
00102                 throw 0;
00103         }
00104 
00105 }
00106 
00107 long TheoraEncodeInputPin::encodeYV12ToYV12(unsigned char* inBuf, long inNumBytes) {
00108         //
00109         // Now properly pads on one side only... 20/12/04
00110         //
00111 
00112         //Source Buffer all in one buffer
00113 
00114         //YV12 memory layout for directshow
00115         //=================================
00116         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00117         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00118         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00119         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00120         //VVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVV
00121         //UUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUU
00122 
00123 
00124         //Destination buffer Y, U, V in seperate planes, lowercase are line padding, "." height padding
00125         //.............................. ..............................
00126         //.............................. ..............................
00127         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00128         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00129         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00130         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00131         //.............................. ..............................
00132         //.............................. ..............................
00133 
00134         //.............................. ..............................
00135         //vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv
00136         //.............................. ..............................
00137         
00138         //.............................. ..............................
00139         //uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu
00140         //.............................. ..............................
00141 
00142         //NOTE  : mHeight, mWidth are the actual video sizes and are the sizes of the incoming buffer
00143         //                The yuv width, height parameters are a /16 up rounded size of the output buffer to be sent to libtheora
00144 
00145 
00146         //Setup the source pointer
00147         unsigned char* locSourceUptoPtr = inBuf;  //View only... don't delete locUptoPtr
00148         //
00149         
00150         //========
00151         //Y DATA |
00152         //=========================================================================================================
00153 
00154         //Setup the destination pointer
00155         char* locDestUptoPtr = mYUV.y;
00156         //
00157 
00160         //if (mYOffset != 0) {
00161         //      memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width);                   //Is it needed to zero this out ? Or just leave junk ?
00162         //      locDestUptoPtr += (mYOffset * mYUV.y_width);                                                    //I'm fairly sure it can be junk... but leave for now !
00163         //}
00164         //Source pointer does not advance
00165         //
00166 
00167         //Add mHeight lines of data of width mWidth plus padding of mXOffset at the start of each line
00168         if (mXOffset == 0) {
00169                 //Slight optimisation to keep the inner loop tighter
00170                 //
00171                 //This branch of the condition does exactly the same as the else branch where mXOffset = 0
00172                 for (unsigned long line = 0; line < mHeight; line++) {
00173                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
00174                         locSourceUptoPtr += mWidth;
00175                         locDestUptoPtr += mWidth;
00176                 }
00177         } else {
00178                 for (unsigned long line = 0; line < mHeight; line++) {
00179                         //Pad the start of the line with mXOffset bytes
00180                         memset((void*)locDestUptoPtr, NULL, mXOffset);
00181                         locDestUptoPtr += mXOffset;
00182 
00183                         //Fill in the meaty bit
00184                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
00185                         locSourceUptoPtr += mWidth;
00186                         locDestUptoPtr += mWidth;
00187 
00188                         //
00189                         //This is no longer done... we just pad on one side for efficiency
00190                         //
00191                         //Pad the end of the line with mXOffset bytes
00192                         //memset((void*)locDestUptoPtr, NULL, mXOffset);
00193                         //locDestUptoPtr += mXOffset;
00194                 }
00195 
00196         }
00197 
00198         
00199         //Pad bottom of Y plane buffer with mYOffset lines of width mYUV.y_width
00200         if (mYOffset != 0) {
00201                 memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width);                   //Is it needed to zero this out ? Or just leave junk ?
00202                 locDestUptoPtr += (mYOffset * mYUV.y_width);
00203                 //Source pointer does not advance
00204         }
00205         
00206 
00207 
00208         //========
00209         //V DATA |
00210         //=========================================================================================================
00211 
00212         //Set the destination poitner
00213         locDestUptoPtr = mYUV.v;
00214         //
00215 
00216         //ASSERT (mYOffset is EVEN)
00217         //ASSERT (mHeight is EVEN)
00218         //ASSERT (mWidth is EVEN)
00219         //
00220 
00222         //if (mYOffset != 0) {
00223         //      memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00224         //      locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00225         //      //Source pointer does not advance
00226         //}
00228 
00229         //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
00230         if (mXOffset == 0) {
00231                 //Slight optimisation to keep the inner loop tighter
00232                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00233                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00234                         locSourceUptoPtr += (mWidth / 2);
00235                         locDestUptoPtr += (mWidth / 2);
00236                 }
00237         } else {
00238                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00239                         //Pad the start of the line
00240                         memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00241                         locDestUptoPtr += (mXOffset / 2);
00242                         //Source pointer does not advance
00243 
00244                         //Fill in the meaty bit
00245                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00246                         locSourceUptoPtr += (mWidth / 2);
00247                         locDestUptoPtr += (mWidth / 2);
00248 
00249                         //
00250                         //This is no longer done... we just pad on one side for efficiency
00251                         //
00252 
00254                         //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00255                         //locDestUptoPtr += (mXOffset / 2);
00257                 }
00258 
00259         }
00260 
00261 
00262         //Pad bottom of V plane buffer with mYOffset / 2 lines of width mYUV.uv_width
00263         if (mYOffset != 0) {
00264                 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00265                 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00266                 //Source pointer does not advance
00267         }
00268         
00269 
00270 
00271 
00272 
00273         //========
00274         //U DATA |
00275         //=========================================================================================================
00276 
00277         //Set the destination pointer
00278         locDestUptoPtr = mYUV.u;
00279         //
00280 
00282         //if (mYOffset != 0) {
00283         //      memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00284         //      locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00285         //      //Source pointer does not advance
00286         //}
00288 
00289         //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
00290         if (mXOffset == 0) {
00291                 //Slight optimisation to keep the inner loop tighter
00292                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00293                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00294                         locSourceUptoPtr += (mWidth / 2);
00295                         locDestUptoPtr += (mWidth / 2);
00296                 }
00297         } else {
00298                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00299                         //Pad the start of the line
00300                         memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00301                         locDestUptoPtr += (mXOffset / 2);
00302                         //Source pointer does not advance
00303 
00304                         //Fill in the meaty bit
00305                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00306                         locSourceUptoPtr += (mWidth / 2);
00307                         locDestUptoPtr += (mWidth / 2);
00308 
00309                         //
00310                         //This is no longer done... we just pad on one side for efficiency
00311                         //
00312 
00314                         //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00315                         //locDestUptoPtr += (mXOffset / 2);
00317                 }
00318 
00319         }
00320 
00321         
00322         //Pad bottom of U plane buffer with mYOffset / 2 lines of width mYUV.uv_width
00323         if (mYOffset != 0) {
00324                 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00325                 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00326                 //Source pointer does not advance
00327         }
00328 
00329         //======================================================================================================
00330         return 0;
00331 
00332 }
00333 
00334 //-------------------------------------------------------------------------
00335 
00336 long TheoraEncodeInputPin::encodeIYUVToYV12(unsigned char* inBuf, long inNumBytes) {
00337         //
00338         // Now properly pads on one side only... 20/12/04
00339         //
00340 
00341         //Same as YV12 but planes U and V are reversed.
00342 
00343         //Source Buffer all in one buffer
00344 
00345         //IYUV memory layout for directshow
00346         //=================================
00347         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00348         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00349         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00350         //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
00351         
00352         //UUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUU
00353         
00354         //VVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVV
00355         
00356 
00357 
00358         //Destination buffer Y, U, V in seperate planes, lowercase are line padding, "." height padding
00359         //.............................. ..............................
00360         //.............................. ..............................
00361         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00362         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00363         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00364         //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
00365         //.............................. ..............................
00366         //.............................. ..............................
00367 
00368         //.............................. ..............................
00369         //uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu
00370         //.............................. ..............................
00371         
00372         //.............................. ..............................
00373         //vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv
00374         //.............................. ..............................
00375         
00376 
00377 
00378         //NOTE  : mHeight, mWidth are the actual video sizes and are the sizes of the incoming buffer
00379         //                The yuv width, height parameters are a /16 up rounded size of the output buffer to be sent to libtheora
00380 
00381 
00382         //Setup the source pointer
00383         unsigned char* locSourceUptoPtr = inBuf;  //View only... don't delete locUptoPtr
00384         //
00385         
00386         //========
00387         //Y DATA |
00388         //=========================================================================================================
00389 
00390         //Setup the destination pointer
00391         char* locDestUptoPtr = mYUV.y;
00392         //
00393 
00395         //if (mYOffset != 0) {
00396         //      memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width);                   //Is it needed to zero this out ? Or just leave junk ?
00397         //      locDestUptoPtr += (mYOffset * mYUV.y_width);
00398         //}
00399         //Source pointer does not advance
00400         //
00401 
00402         //Add mHeight lines of data of width mWidth plus padding of mXOffset at each end
00403         if (mXOffset == 0) {
00404                 //Slight optimisation to keep the inner loop tighter
00405                 for (unsigned long line = 0; line < mHeight; line++) {
00406                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
00407                         locSourceUptoPtr += mWidth;
00408                         locDestUptoPtr += mWidth;
00409                 }
00410         } else {
00411                 for (unsigned long line = 0; line < mHeight; line++) {
00412                         //Pad the start of the line with mXOffset bytes
00413                         memset((void*)locDestUptoPtr, NULL, mXOffset);
00414                         locDestUptoPtr += mXOffset;
00415 
00416                         //Fill in the meaty bit
00417                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
00418                         locSourceUptoPtr += mWidth;
00419                         locDestUptoPtr += mWidth;
00420 
00422                         //memset((void*)locDestUptoPtr, NULL, mXOffset);
00423                         //locDestUptoPtr += mXOffset;
00424                 }
00425 
00426         }
00427 
00428         //Pad bottom of Y plane buffer with mYOffset lines of width mYUV.y_width
00429         if (mYOffset != 0) {
00430                 memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width);                   //Is it needed to zero this out ? Or just leave junk ?
00431                 locDestUptoPtr += (mYOffset * mYUV.y_width);
00432                 //Source pointer does not advance
00433         }
00434 
00435         //========
00436         //U DATA |
00437         //=========================================================================================================
00438 
00439         //Set the destination pointer
00440         locDestUptoPtr = mYUV.u;
00441         //
00442 
00444         //if (mYOffset != 0) {
00445         //      memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00446         //      locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00447         //      //Source pointer does not advance
00448         //}
00449         //
00450 
00451         //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
00452         if (mXOffset == 0) {
00453                 //Slight optimisation to keep the inner loop tighter
00454                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00455                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00456                         locSourceUptoPtr += (mWidth / 2);
00457                         locDestUptoPtr += (mWidth / 2);
00458                 }
00459         } else {
00460                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00461                         //Pad the start of the line
00462                         memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00463                         locDestUptoPtr += (mXOffset / 2);
00464                         //Source pointer does not advance
00465 
00466                         //Fill in the meaty bit
00467                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00468                         locSourceUptoPtr += (mWidth / 2);
00469                         locDestUptoPtr += (mWidth / 2);
00470 
00472                         //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00473                         //locDestUptoPtr += (mXOffset / 2);
00475                 }
00476 
00477         }
00478 
00479         //Pad bottom of U plane buffer with mYOffset / 2 lines of width mYUV.uv_width
00480         if (mYOffset != 0) {
00481                 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00482                 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00483                 //Source pointer does not advance
00484         }
00485         
00486 
00487 
00488         //========
00489         //V DATA |
00490         //=========================================================================================================
00491 
00492         //Set the destination poitner
00493         locDestUptoPtr = mYUV.v;
00494         //
00495 
00497         //if (mYOffset != 0) {
00498         //      memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00499         //      locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00500         //      //Source pointer does not advance
00501         //}
00503 
00504         //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
00505         if (mXOffset == 0) {
00506                 //Slight optimisation to keep the inner loop tighter
00507                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00508                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00509                         locSourceUptoPtr += (mWidth / 2);
00510                         locDestUptoPtr += (mWidth / 2);
00511                 }
00512         } else {
00513                 for (unsigned long line = 0; line < mHeight / 2; line++) {
00514                         //Pad the start of the line
00515                         memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00516                         locDestUptoPtr += (mXOffset / 2);
00517                         //Source pointer does not advance
00518 
00519                         //Fill in the meaty bit
00520                         memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
00521                         locSourceUptoPtr += (mWidth / 2);
00522                         locDestUptoPtr += (mWidth / 2);
00523 
00525                         //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
00526                         //locDestUptoPtr += (mXOffset / 2);
00528                 }
00529 
00530         }
00531 
00532         //Pad bottom of V plane buffer with mYOffset / 2 lines of width mYUV.uv_width
00533         if (mYOffset != 0) {
00534                 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2);                    //Is it needed to zero this out ? Or just leave junk ?
00535                 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
00536                 //Source pointer does not advance
00537         }
00538         
00539 
00540 
00541 
00542 
00543 
00544         //======================================================================================================
00545         return 0;
00546 
00547 }
00548 //-------------------------------------------------------------------------
00549 
00550 long TheoraEncodeInputPin::encodeRGB24toYV12(unsigned char* inBuf, long inNumBytes) {
00551         //Blue Green Red Blue Green Red.
00552         unsigned long locNumPixels = (inNumBytes/3);
00553         unsigned char* locAYUVBuf = new unsigned char[locNumPixels<<2];   //4 bytes per pixel
00554 
00555         /*
00556 
00557 
00558 
00559 
00560         Conversion from RGB to YUV is defined by starting with the following:
00561 
00562         L = Kr * R + Kb * B + (1 – Kr – Kb) * G
00563 
00564         The YUV values are then obtained as follows:
00565 
00566         Y =                 floor(2^(M-8) * (219*(L–Z)/S + 16) + 0.5)
00567         U = clip3(0, 2^M-1, floor(2^(M-8) * (112*(B-L) / ((1-Kb)*S) + 128) + 0.5))
00568         V = clip3(0, 2^M-1, floor(2^(M-8) * (112*(R-L) / ((1-Kr)*S) + 128) + 0.5))
00569 
00570         where Z = 16
00571         S = 219
00572         M = 8 bits per sample.
00573 
00574         ==>
00575         Y =                                     floor(L + 0.5)
00576         U =                                     (112*(B-L) / ((1-Kb)*S) + 128)          
00577 
00578 
00579         Kr'                     = Kr * 65536
00580         Kb'                     = Kb * 65536
00581         G_FACTOR        = (1 - Kr - Kb) * 65536
00582 
00583         L'                      = (Kr' * R)  +  (Kb' * B) + (G_FACTOR * G)
00584                                 = 65536 * ( (Kr * R) + (Kb * B) + ((1 - Kr - Kb) * G) )
00585                                 = 65536 * L
00586 
00587         Y                       = round( 219 * (L-Z)/S + 16 )
00588                                 = round ( L-Z + 16 )
00589                                 = round( L )
00590 
00591         Y'                      = L'
00592                                 = 65536 * L
00593                                 
00594         Y                       = L' >> 16
00595 
00596         U_FACTOR        = ( 1 - Kb) * S
00597         U_FACTOR'       = 12716213
00598         
00599                                 = 65536 * U_FACTOR
00600 
00601         V_FACTOR'       = 10061022
00602         
00603         B'                      = 65536 * B
00604         R'                      = 65536 * R
00605 
00606         _U_                     = round( 112 * (B-L) / ( (1-Kb)*S ) + 128 )
00607                                 = round( (112 * (B-L) / U_FACTOR) + 128 )
00608                                 = (112 * (B' - L') / U_FACTOR') + 128
00609                                 = (112 * 65536 * (B - L) / (U_FACTOR * 65536)) + 128
00610                                 = (112 * (B - L) / U_FACTOR) + 128
00611 
00612         Hence integerisation scaling cancels
00613         ==>
00614         _U_                     = (112 * (B' - L') / U_FACTOR') + 128
00615         
00616         _V_                     = (112 * (R' - L') / V_FACTOR') + 128
00617                 
00618         */
00619 
00620         /*
00621         Kr = 0.299
00622         Kb = 0.114
00623 
00624 
00625         */
00626 
00627         //Scaled by factor of 65536 to integerise.
00628         const int KR = 19596;
00629         const int KB = 7472;
00630         
00631         const int ROUNDER = 32768;
00632 
00633         const int G_FACTOR = 38470;
00634         const int U_FACTOR = 12716213;
00635         const int V_FACTOR = 10061022;
00636 
00637         int locL = 0;
00638         int locB = 0;
00639         int locR = 0;
00640 
00641         //unsigned char* locSourcePtr = inBuf;
00642         unsigned char* locDestPtr = locAYUVBuf;
00643 
00644     //SOURCE: Blue Green Red Blue Green Red.
00645         //DEST: v u y a
00646 
00647         unsigned char* locSourceEnds = inBuf + (locNumPixels * 3);
00648 
00649         //Upside down... Upside down !
00650         //for (unsigned char* locSourcePtr = inBuf; locSourcePtr < locSourceEnds; locSourcePtr += 3) {
00651         //      locB = locSourcePtr[0];                                 //Blue
00652         //      locL = KB * (locB);                                             //Blue
00653         //      
00654         //      locL += G_FACTOR * (locSourcePtr[1]);   //Green
00655 
00656         //      locR = locSourcePtr[2];                                 //Red
00657         //      locL += KR * (locR);                                    //Red
00658 
00659         //      
00660         //      *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128);                       //V for Victor
00661         //      *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128);                       //U for ugly
00662         //      *(locDestPtr++) = CLIP3(0, 255, locL >> 16);                                                                                            //Y for yellow
00663         //      *(locDestPtr++) = 255;                                                                                                                                          //A for alpha
00664         //}
00665         
00666 
00667         unsigned char* locColSourcePtr = NULL;
00668         unsigned char* locColEndPtr = NULL;
00669         unsigned long locLineLength = mWidth * 3;
00670         unsigned long col = 0;
00671         for (unsigned char* locSourcePtr = locSourceEnds - locLineLength; locSourcePtr >= inBuf; locSourcePtr -= locLineLength) {
00672                 //
00673                 //for(unsigned char* locColSourcePtr = locSourcePtr, int i = 0; i < mWidth; i++, locColSourcePtr +=4) {
00674                 //
00675                 locColSourcePtr = locSourcePtr;
00676                 locColEndPtr = locColSourcePtr + locLineLength;
00677                 while (locColSourcePtr < locColEndPtr) {
00678                         locB = locColSourcePtr[0];                                      //Blue
00679                         locL = KB * (locB);                                                     //Blue
00680                 
00681                         locL += G_FACTOR * (locColSourcePtr[1]);        //Green
00682 
00683                         locR = locColSourcePtr[2];                                      //Red
00684                         locL += KR * (locR);                                            //Red
00685 
00686                 
00687                         *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128);                       //V for Victor
00688                         *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128);                       //U for ugly
00689                         *(locDestPtr++) = CLIP3(0, 255, locL >> 16);                                                                                            //Y for yellow
00690                         *(locDestPtr++) = 255;                                                                                                                                          //A for alpha
00691 
00692                         //debugCount++;         
00693                         locColSourcePtr+=3;
00694 
00695                 }
00696 
00697 
00698         }
00699 
00700 
00701         //Still need to pass through to the AYUV conversion.
00702         encodeAYUVtoYV12(locAYUVBuf, locNumPixels<<2);
00703         delete[] locAYUVBuf;
00704         locAYUVBuf = NULL;
00705 
00706         return 0;
00707 }
00708 
00709 
00710 
00711 long TheoraEncodeInputPin::encodeRGB32toYV12(unsigned char* inBuf, long inNumBytes) {
00712         //Blue Green Red Alpha Blue Green Red Alpha
00713         //debugLog<<"EncodeRGB32 To YV12 :"<<endl;
00714 
00715         unsigned long locNumPixels = (inNumBytes/4);
00716         
00717         //debugLog<<"EncodeRGB32 To YV12 : Num pixels = "<<locNumPixels<<endl;
00718         //debugLog<<"EncodeRGB32 To YV12 : Num BYtes = "<<inNumBytes<<endl;
00719         unsigned char* locAYUVBuf = new unsigned char[inNumBytes];   //4 bytes per pixel
00720 
00721         //debugLog<<"EncodeRGB32 To YV12 :"<<endl;
00722 
00723         //Scaled by factor of 65536 to integerise.
00724         const int KR = 19596;
00725         const int KB = 7472;
00726         
00727         const int ROUNDER = 32768;
00728 
00729         const int G_FACTOR = 38470;
00730         const int U_FACTOR = 12716213;
00731         const int V_FACTOR = 10061022;
00732 
00733         int locL = 0;
00734         int locB = 0;
00735         int locR = 0;
00736 
00737         //unsigned char* locSourcePtr = inBuf;
00738         unsigned char* locDestPtr = locAYUVBuf;
00739 
00740     //SOURCE: Blue Green Red Blue Green Red.
00741         //DEST: v u y a
00742 
00743         unsigned char* locSourceEnds = inBuf + (inNumBytes);
00744         //debugLog<<"EncodeRGB32 To YV12 : Source Starts = "<<(int)inBuf<<endl;
00745         //debugLog<<"EncodeRGB32 To YV12 : Source Ends = "<<(int)locSourceEnds<<endl;
00746 
00747         //Debugging only... all refs to debugCount remove later
00748         //unsigned long debugCount = 0;
00749         //
00750 
00751         //Upside down !!
00752         //for (unsigned char* locSourcePtr = inBuf; locSourcePtr < locSourceEnds; locSourcePtr += 4) {
00753         //      locB = locSourcePtr[0];                                 //Blue
00754         //      locL = KB * (locB);                                             //Blue
00755         //      
00756         //      locL += G_FACTOR * (locSourcePtr[1]);   //Green
00757 
00758         //      locR = locSourcePtr[2];                                 //Red
00759         //      locL += KR * (locR);                                    //Red
00760 
00761         //      
00762         //      *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128);                       //V for Victor
00763         //      *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128);                       //U for ugly
00764         //      *(locDestPtr++) = CLIP3(0, 255, locL >> 16);                                                                                            //Y for yellow
00765         //      *(locDestPtr++) = locSourcePtr[3];                                                                                                                                              //A for alpha
00766 
00767         //      debugCount++;
00768         //}
00769         unsigned char* locColSourcePtr = NULL;
00770         unsigned char* locColEndPtr = NULL;
00771         unsigned long locLineLength = mWidth * 4;
00772         unsigned long col = 0;
00773         for (unsigned char* locSourcePtr = locSourceEnds - locLineLength; locSourcePtr >= inBuf; locSourcePtr -= locLineLength) {
00774                 //
00775                 //for(unsigned char* locColSourcePtr = locSourcePtr, int i = 0; i < mWidth; i++, locColSourcePtr +=4) {
00776                 //
00777                 locColSourcePtr = locSourcePtr;
00778                 locColEndPtr = locColSourcePtr + locLineLength;
00779                 while (locColSourcePtr < locColEndPtr) {
00780                         locB = locColSourcePtr[0];                                      //Blue
00781                         locL = KB * (locB);                                                     //Blue
00782                 
00783                         locL += G_FACTOR * (locColSourcePtr[1]);        //Green
00784 
00785                         locR = locColSourcePtr[2];                                      //Red
00786                         locL += KR * (locR);                                            //Red
00787 
00788                 
00789                         *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128);                       //V for Victor
00790                         *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128);                       //U for ugly
00791                         *(locDestPtr++) = CLIP3(0, 255, locL >> 16);                                                                                            //Y for yellow
00792                         *(locDestPtr++) = locColSourcePtr[3];                                                                                                           //A for alpha
00793 
00794                         //debugCount++;         
00795                         locColSourcePtr+=4;
00796 
00797                 }
00798 
00799 
00800         }
00801 
00802         //debugLog<<"EncodeRGB32 To YV12 : debugCount = "<<debugCount<<endl;
00803 
00804         //ASSERT(debugCount == locNumPixels);
00805         
00806         ASSERT(locDestPtr == (locAYUVBuf + inNumBytes));
00807 
00808         //debugLog<<"EncodeRGB32 To YV12 : Calling AYUV to YV12 conversion"<<endl;
00809         //Still need to pass through to the AYUV conversion.
00810 
00811         encodeAYUVtoYV12(locAYUVBuf, inNumBytes);
00812         delete[] locAYUVBuf;
00813         locAYUVBuf = NULL;
00814 
00815         return 0;
00816 }
00817 
00818 
00819 
00820 
00821 long TheoraEncodeInputPin::encodeAYUVtoYV12(unsigned char* inBuf, long inNumBytes) {
00822 
00823         //TODO::: This doesn't appear to do offsets.
00824 
00825         //Victor Ugly Yellow Alpha --fonts are fuzzy late at night-- (Yellow is not colour yellow)
00826 
00827         //AYUV is VUYA VUYA VUYA VUYA 4:4:4 sampling
00828         // Twice the vertical and horizontal sampling of YV12 in chrominance
00829 
00830         //Strategy : Process two lines and 2 cols at a time averaging 4 U and V around the position where a
00831         // YV12 chroma sample will be... leave luminance samples... ignore alpha samples
00832 
00833         //debugLog<<"Encode AYUV To YV12 :"<<endl;
00834         
00835         const int PIXEL_BYTE_SIZE = 4;
00836         ASSERT (mHeight % 2 == 0);
00837         ASSERT (mWidth % 2 == 0);
00838 
00839         unsigned char* locSourceUptoPtr = inBuf;                                                //View only... don't delete locUptoPtr
00840         unsigned char* locSourceNextLine = locSourceUptoPtr + (mWidth * PIXEL_BYTE_SIZE);       //View only don't delete
00841         
00842         char* locYUpto = mYUV.y;
00843         char* locUUpto = mYUV.u;
00844         char* locVUpto = mYUV.v;
00845         //Pointer to the same pixel on next line
00846         char* locDestNextLine = locYUpto + (mYUV.y_stride);                             //View only... don't delete
00847 
00848         int temp = 0;
00849 
00850         //Process 2 lines at a time
00851         for (unsigned long line = 0; line < mHeight; line += 2) {
00852                 //debugLog<<"Encode AYUV To YV12 : ++ Line = "<<line<<endl;
00853                 
00854                 //Ensures the current destination buffer skips a line ie points to line 2, 4, 6 etc
00855                 locYUpto = (mYUV.y + (line * mYUV.y_stride));
00856                 //Ensures the nextlinedest skips a
00857                 locDestNextLine = locYUpto + (mYUV.y_stride);
00858 
00859                 //locUUpto = (mYUV.u + ((line/2) * mYUV.uv_stride));
00860                 //locVUpto = (mYUV.v + ((line/2) * mYUV.uv_stride));
00861 
00862                 ASSERT (locSourceUptoPtr == (inBuf + (line * (mWidth * PIXEL_BYTE_SIZE))));
00863                 ASSERT (locSourceNextLine == locSourceUptoPtr + (mWidth * PIXEL_BYTE_SIZE));
00864                 ASSERT (locYUpto == (mYUV.y + (line * mYUV.y_stride)));
00865                 ASSERT (locDestNextLine == locYUpto + (mYUV.y_stride));
00866                 
00867 
00868                 //Pad out the start of the line if needed
00869                 if (mXOffset != 0) {
00870                         memset((void*)locYUpto, 0, mXOffset);
00871                         memset((void*)locDestNextLine, 0, mXOffset);
00872                         memset((void*)locUUpto, 0, mXOffset/2);
00873                         memset((void*)locVUpto, 0, mXOffset/2);
00874                         locYUpto += mXOffset;
00875                         locDestNextLine += mXOffset;
00876                         locUUpto += (mXOffset/2);
00877                         locVUpto += (mXOffset/2);
00878                 }
00879                 //Columns also done 2 at a time
00880                 for (unsigned long col = 0; col < mWidth; col += 2) {
00881                         //debugLog<<"Encode AYUV To YV12 : ++++++ Col = "<<col<<endl;
00882                         
00883 
00884 
00885 
00886 
00887                         //                                              v       u       y       a       v       u       y       a
00888                         //SourceUpto                    ^
00889                         //NextUpto                              ^
00890 
00891                         //====================
00892                         //V for Victor samples
00893                         //====================
00894                         temp =  *(locSourceUptoPtr++);                  //Current pixel
00895 
00896                         //                                              v       u       y       a       v       u       y       a
00897                         //SourceUpto                            ^
00898                         //NextUpto                              ^
00899 
00900                         //This is three as we already advanced one and are pointing to a u not a v
00901                         temp += *(locSourceUptoPtr + 3);                //Pixel to right
00902                         temp += *(locSourceNextLine++);                 //Pixel below
00903 
00904                         //                                              v       u       y       a       v       u       y       a
00905                         //SourceUpto                            ^
00906                         //NextUpto                                      ^
00907 
00908                         temp += *(locSourceNextLine + 3);                       //Pixel below right
00909                         temp >>= 2;                                                             //Divide by 4 to average.
00910                         *(locVUpto++) = (unsigned char)temp;
00911 
00912                         //                                              v       u       y       a       v       u       y       a
00913                         //SourceUpto                            ^
00914                         //NextUpto                                      ^
00915 
00916                         //====================
00917                         //U for Ugly samples
00918                         //====================
00919                         temp =  *(locSourceUptoPtr++);                  //Current pixel
00920 
00921                         //                                              v       u       y       a       v       u       y       a
00922                         //SourceUpto                                    ^
00923                         //NextUpto                                      ^
00924 
00925                         temp += *(locSourceUptoPtr + 3);                        //Pixel to right
00926                         temp += *(locSourceNextLine++);                 //Pixel below
00927 
00928 
00929                         //                                              v       u       y       a       v       u       y       a
00930                         //SourceUpto                                    ^
00931                         //NextUpto                                              ^
00932 
00933                         temp += *(locSourceNextLine + 3);                       //Pixel below right
00934                         temp >>= 2;                                                             //Divide by 4 to average.
00935                         *(locUUpto++) = (unsigned char)temp;
00936 
00937                         //                                              v       u       y       a       v       u       y       a
00938                         //SourceUpto                                    ^
00939                         //NextUpto                                              ^
00940 
00941                         //====================
00942                         //Y for Yellow samples.
00943                         //====================
00944 
00945                         *(locYUpto++) = *(locSourceUptoPtr++);
00946                         *(locDestNextLine++) = *(locSourceNextLine++);
00947 
00948                         //                                              v       u       y       a       v       u       y       a
00949                         //SourceUpto                                            ^
00950                         //NextUpto                                                      ^
00951 
00952                         //Ignore the alpha channel
00953                         //--
00954                         //locSourceUptoPtr++;                   //Optimised away... merged into increment below
00955                         //locSourceNextLine++;                  // "    "       "       "       "       "       "       "       "       "       "
00956 
00957                         //                                              v       u       y       a       v       u       y       a
00958                         //SourceUpto                                                    ^
00959                         //NextUpto                                                              ^
00960 
00961 
00962                         //--
00963                         //Source and next pointer have advanced four bytes so far.
00964                         //Added 2 Y for yellows (one from each line) and one each of U and V, ignore an A on each line
00965                         //--
00966 
00967                         //Current line extra Y for yellows.
00968                         locSourceUptoPtr += 3;                                  //Skip the A and U and V samples
00969                         *(locYUpto++) = *(locSourceUptoPtr);    //get the Y for yellow sample           
00970                         locSourceUptoPtr += 2;                                  //Advance 1 for the Y for yellow and Skip the A sample.
00971 
00972                         //                                              v       u       y       a       v       u       y       a
00973                         //SourceUpto                                                                                    ^
00974                         //NextUpto                                                              ^
00975 
00976 
00977                         //Next line extra Y for yellows.
00978                         locSourceNextLine += 3;                                                 //Skip the A and U and V samples
00979                         *(locDestNextLine++) = *(locSourceNextLine);    //get the Y for yellow sample           
00980                         locSourceNextLine += 2;                                                 //Advance 1 for the Y for yellow and Skip the A sample.
00981 
00982                         //                                              v       u       y       a       v       u       y       a
00983                         //SourceUpto                                                                                    ^
00984                         //NextUpto                                                                                              ^
00985 
00986                         //--
00987                         //In total source and next pointer advanced 8 bytes on each line, and we got 4 Y for yellows (2 each line)
00988                         // and one each U, V, ignored 4 A's (2 each line)
00989                         //--
00990 
00991 
00992                 }
00993                 //Overall this loop will advance :
00994                 //Sourceupto    by              = 8 bytes * (mWidth in pixels / 2 pixels at a time) * 2 lines
00995                 //                                              = 8 * mWidth
00996                 //                                              = 2 lines of 4 byte pixels of pixel width mWidth
00997                 //and the same for sourcenextline
00998                 //--
00999                 //At the end of this loop sourceupto points to the end of the current line (start of next line)
01000                 // and nextupto points to the end of the next line
01001                 //
01002                 //On the next iteration we want the sourceupto to point 2 lines down from where it did on the previous one
01003                 // This is the same place that the sourcenextline points at the end of the iteration.
01004                 //--
01005 
01006                 //Ensures source will point to lines 2, 4, 6 etc.
01007                 locSourceUptoPtr = locSourceNextLine;                   
01008                 //Ensures nextlinesource is one line ahead of the main source.
01009                 locSourceNextLine += (mWidth * PIXEL_BYTE_SIZE);
01010 
01011 
01012 
01013         }
01014         return 0;
01015 }
01016 long TheoraEncodeInputPin::encodeYUY2ToYV12(unsigned char* inBuf, long inNumBytes) {
01017 
01018         //TODO::: This doesn't do offsets properly.
01019         
01020         unsigned char* locSourceUptoPtr = inBuf;  //View only... don't delete locUptoPtr
01021 
01022         //YUY2 is Y0 U0 Y1 V0 Y2 U1 Y3 V1
01023         // it has twice as much sampling height as YV12 so downsample it.
01024 
01025         char* locYUpto = mYUV.y;
01026         char* locUUpto = mYUV.u;
01027         char* locVUpto = mYUV.v;
01028 
01029         
01030 
01031         //After downsampling... from each block of 8, we get 4 y samples and 1 each of u and v
01032 
01033 
01034         for (unsigned long i = 0; i < mHeight / 2; i++) {
01035                 //TO DO: Draw memory layouts.
01036 
01037                 //***Part of the average method... store the pointer to the last of the previous line
01038                 //locLastUUpto = locUUpto;
01039                 //locLastVUpto = locVUpto;
01040                 //***
01041 
01042                 for (unsigned long j = 0; j < mWidth / 2; j++) {
01043                         *(locYUpto++) = *(locSourceUptoPtr++);
01044                         *(locUUpto++) = *(locSourceUptoPtr++);
01045                         *(locYUpto++) = *(locSourceUptoPtr++);
01046                         *(locVUpto++) = *(locSourceUptoPtr++);
01047                 }
01048 
01049                 
01050                 //***Drop line method
01051                 for (unsigned long j = 0; j < mWidth / 2; j++) {
01052                         //Ignore the second line
01053                         *(locYUpto++) = *(locSourceUptoPtr++);
01054                         locSourceUptoPtr++;
01055                         *(locYUpto++) = *(locSourceUptoPtr++);
01056                         locSourceUptoPtr++;
01057                 }
01058                 //***
01059 
01060                 //*** PArt of the Alternate method to average...
01061                 //for (int j = 0; j < mWidth / 2; j++) {
01062                 //      //Ignore the second line
01063                 //      *(locYUpto++) = *(locSourceUptoPtr++);
01064                 //      *(locLastUUpto++) = ((short)(*locLastUUpto) + ((short)(*locUUpto))) / 2;
01065                 //      
01066                 //      *(locYUpto++) = *(locSourceUptoPtr++);
01067                 //      *(locLastVUpto++) = ((short)(*locLastVUpto) + ((short)(*locVUpto))) / 2;
01068                 //      
01069                 //}
01070                 //***
01071 
01072 
01073 
01074         }
01075         return 0;
01076 }
01077 
01078 long TheoraEncodeInputPin::encodeYVYUToYV12(unsigned char* inBuf, long inNumBytes) {
01079         //YVYU  -       Yellow Victor Yellow Ugly
01080         unsigned char* locSourceUptoPtr = inBuf;  //View only... don't delete locUptoPtr
01081 
01082         //YUY2 is Y0 U0 Y1 V0 Y2 U1 Y3 V1
01083         //YVYU is Y0 V0 Y1 U0 Y2 V1 Y3 U1
01084         // it has twice as much sampling height as YV12 so downsample it.
01085 
01086         char* locYUpto = mYUV.y;
01087         char* locUUpto = mYUV.u;
01088         char* locVUpto = mYUV.v;
01089 
01090         
01091 
01092         //After downsampling... from each block of 8, we get 4 y samples and 1 each of u and v
01093 
01094 
01095         for (unsigned long i = 0; i < mHeight / 2; i++) {
01096                 //TO DO: Draw memory layouts.
01097 
01098         
01099 
01100                 for (unsigned long j = 0; j < mWidth / 2; j++) {
01101                         *(locYUpto++) = *(locSourceUptoPtr++);                          //Y for Yellow
01102                         *(locVUpto++) = *(locSourceUptoPtr++);                          //V for victor
01103                         
01104                         *(locYUpto++) = *(locSourceUptoPtr++);                          //Y for Yellow
01105                         *(locUUpto++) = *(locSourceUptoPtr++);                          //U for Ugly
01106                 }
01107 
01108                 
01109                 //***Drop line method
01110                 for (unsigned long j = 0; j < mWidth / 2; j++) {
01111                         //Ignore the second line
01112                         *(locYUpto++) = *(locSourceUptoPtr++);                  //Y for Yellow
01113                         locSourceUptoPtr++;                                                             //V for victor
01114                         *(locYUpto++) = *(locSourceUptoPtr++);                  //Y for yellow
01115                         locSourceUptoPtr++;                                                             //U for ugly.
01116                 }
01117 
01118         }
01119         return 0;
01120 }
01121 
01122 
01123 long TheoraEncodeInputPin::encodeUYVYToYV12(unsigned char* inBuf, long inNumBytes) {
01124         //UYVY :: U0 Y0 V0 Y1   - Ugly Yellow Victor Yello
01125         unsigned char* locSourceUptoPtr = inBuf;  //View only... don't delete locUptoPtr
01126 
01127         //UYVY is U0 Y0 V0 Y1 U0 Y2 V0 Y3
01128         //YUY2 is Y0 U0 Y1 V0 Y2 U1 Y3 V1
01129         // it has twice as much sampling height as YV12 so downsample it.
01130 
01131         char* locYUpto = mYUV.y;
01132         char* locUUpto = mYUV.u;
01133         char* locVUpto = mYUV.v;
01134 
01135         
01136 
01137         //After downsampling... from each block of 8, we get 4 y samples and 1 each of u and v
01138 
01139 
01140         for (unsigned long i = 0; i < mHeight / 2; i++) {
01141                 //TO DO: Draw memory layouts.
01142 
01143         
01144                 for (unsigned long j = 0; j < mWidth / 2; j++) {
01145                         *(locUUpto++) = *(locSourceUptoPtr++);                  //U for Ugly
01146                         *(locYUpto++) = *(locSourceUptoPtr++);                  //Y for Yellow
01147                         
01148                         *(locVUpto++) = *(locSourceUptoPtr++);                  //V for Victor
01149                         *(locYUpto++) = *(locSourceUptoPtr++);                  //Y for Yellow
01150                         
01151                 }
01152 
01153                 
01154                 //***Drop line method
01155                 for (unsigned long j = 0; j < mWidth / 2; j++) {
01156                         //Ignore the second line
01157                         
01158                         locSourceUptoPtr++;                                                             //U for ugly
01159                         *(locYUpto++) = *(locSourceUptoPtr++);                  //Y for yellow
01160 
01161                         locSourceUptoPtr++;                                                             //V for victor
01162                         *(locYUpto++) = *(locSourceUptoPtr++);                  //Y for yellow
01163                         
01164                 }
01165 
01166 
01167         }
01168         return 0;
01169 }
01170 
01171 
01172 
01173 //PURE VIRTUALS
01174 long TheoraEncodeInputPin::TransformData(unsigned char* inBuf, long inNumBytes) {
01175 
01176         //TODO::: Break this function up a bit !!
01177 
01178         //Time stamps are granule pos not directshow times
01179         //debugLog<<"Encode data"<<endl;
01180         LONGLONG locFrameStart = mUptoFrame;
01181         LONGLONG locFrameEnd = 0;
01182         HRESULT locHR = S_OK;
01183         if (!mBegun) {
01184                 //debugLog<<"encodeData : First time"<<endl;
01185                 mBegun = true;
01186                 
01187                 StampedOggPacket** locHeaders;
01188                 locHeaders = mTheoraEncoder.initCodec(mTheoraInfo);
01189 
01190                 for (int i = 0; i < 3; i++) {
01191                         locHR = deliverData(0,0,locHeaders[i]->packetData(), locHeaders[i]->packetSize());
01192                         delete locHeaders[i];
01193                         if (locHR != S_OK) {
01194                                 return locHR;
01195                         }
01196                 }
01197         }
01198 
01199 
01200         //This big if block merely takes the buffer and copies it into the yuv_buffer structure which
01201         // is used below to encode.
01202         if (mPinInputType.subtype == MEDIASUBTYPE_YUY2) {
01203                 //debugLog<<"About to encode YUY2 to YV12"<<endl;
01204                 encodeYUY2ToYV12(inBuf, inNumBytes);
01205         } else if (mPinInputType.subtype == MEDIASUBTYPE_AYUV) {
01206                 encodeAYUVtoYV12(inBuf, inNumBytes);
01207 
01208         } else if (mPinInputType.subtype == MEDIASUBTYPE_RGB32) {
01209                 encodeRGB32toYV12(inBuf, inNumBytes);
01210 
01211         } else if (mPinInputType.subtype == MEDIASUBTYPE_RGB24) {
01212                 encodeRGB24toYV12(inBuf, inNumBytes);
01213 
01214 
01215         } else if (mPinInputType.subtype == MEDIASUBTYPE_YV12) {
01216                 //Should be more specifc.
01217                 //debugLog<<"About to encode YV12 to YV12"<<endl;
01218                 encodeYV12ToYV12(inBuf, inNumBytes);
01219         } else if (mPinInputType.subtype == MEDIASUBTYPE_UYVY) {
01220                 
01221                 
01222                 encodeUYVYToYV12(inBuf, inNumBytes);
01223 
01224         } else if (mPinInputType.subtype == MEDIASUBTYPE_YVYU) {
01225                 
01226                 
01227                 encodeYVYUToYV12(inBuf, inNumBytes);
01228         } else if (mPinInputType.subtype == MEDIASUBTYPE_IYUV) {
01229                 
01230                 
01231                 encodeIYUVToYV12(inBuf, inNumBytes);
01232 
01233                 
01234         } else {
01235 
01236                 //FATAL ERROR
01237                 throw 0;
01238         }
01239         
01240 
01241         StampedOggPacket* locPacket = mTheoraEncoder.encodeTheora(&mYUV);
01242         if (locPacket == NULL) {
01243                 //debugLog<<"Encode returns NULL"<<endl;
01244                 return S_FALSE;
01245         }
01246         locFrameEnd             = mUptoFrame 
01247                                         = locPacket->endTime();
01248         //debugLog<<"Delivering..."<<endl;
01249 
01250         //We still own the packet after this, we have to delete it.
01251         locHR = deliverData(locFrameStart, locFrameEnd, locPacket->packetData(), locPacket->packetSize());
01252         delete locPacket;
01253         return locHR;
01254 
01255 }
01256 bool TheoraEncodeInputPin::ConstructCodec() {
01257 
01258         //debugLog<<"Contructing codec..."<<endl;
01259         theora_info_init(&mTheoraInfo);
01260         
01261         //Round up to multiple of 16 for theora
01262 
01263         //---------------------------------------------------------------------------------------------------------------
01264         //mTheoraInfo values
01265         //==================
01266         //width, height                                 -       /16 up rounded values, size of the outer frame
01267         //frame_width, frame_height             -       size of the inner picture region
01268         //offset_x                                              -       Distance at bottom left from frame to picture  <= width - frame_width
01269         //offset_y                                              -       Distance at bottom left from frame to picture  <= height - frame_height
01270 
01271         //mYUV values - for YV12 format
01272         //=============================
01273         //y_stride                                              -       Equal to the /16 up rounded wdith values
01274         //y_width                                               -       Equal to the /16 up rounded wdith values
01275         //uv_stride                                             -       Equal to *half* the /16 up rounded width values
01276         //uv_width                                              -       Equal to *half* the /16 up rounded wdith values
01277         //y_height                                              -       Equal to the /16 up rounded height value
01278         //uv_height                                             -       Equal to *half* the /16 up rounded height value
01279         //y                                                             -       Buffer of size y_stride*y_height (/16 up rounded values)
01280         //u,v                                                   -       Buffers each *quarter* the size of the y buffer (/16 up rounded values)
01281 
01282         //Member data
01283         //===========
01284         //mWidth                                                -       raw video source values... equal to frame_width
01285         //mHeight                                               -       raw video source values... equal to frame_height
01286         //mXOffset                                              -       x offset
01287         //mYOffset                                              -       y offset
01288         //---------------------------------------------------------------------------------------------------------------
01289 
01290         //Width of the outer frame
01291         mTheoraInfo.width                       =       mYUV.y_width
01292                                                                 =       mYUV.y_stride
01293                                                                 =       (((mVideoFormat->bmiHeader.biWidth + 15)>>4)<<4);
01294 
01295         //Width of the inner picture
01296         mTheoraInfo.frame_width         =       mWidth
01297                                                                 =       mVideoFormat->bmiHeader.biWidth;
01298 
01299         //YUV U&V data
01300         mYUV.uv_width                           =       mYUV.uv_stride
01301                                                                 =       mYUV.y_width/2;
01302 
01303         
01304         //
01305 
01306         //Height data of outer frame
01307         mTheoraInfo.height                      =       mYUV.y_height
01308                                                                 =       (((mVideoFormat->bmiHeader.biHeight + 15)>>4)<<4);
01309 
01310         //Height of the inner picture
01311         mTheoraInfo.frame_height        =       mHeight
01312                                                                 =       mVideoFormat->bmiHeader.biHeight;
01313 
01314         mYUV.uv_height                          =       mYUV.y_height/2;
01315 
01316         
01317         //
01318 
01319         //Set offset values... no longer centred... all the offset is at the bottom left of the image (ie very start of memory image)
01320         //Difference between the outframe dimensions and the inner picture dimensions
01321         mTheoraInfo.offset_x            =       mXOffset
01322                                                                 =       (mTheoraInfo.width - mTheoraInfo.frame_width);
01323 
01324         mTheoraInfo.offset_y            =       mYOffset
01325                                                                 =       (mHeight - mTheoraInfo.frame_height);
01326         
01327         
01328         unsigned long locYBuffSize = mYUV.y_height * mYUV.y_stride;
01329         mYUV.y                          =       new char[locYBuffSize];
01330         mYUV.u                          =       new char[locYBuffSize/4];
01331         mYUV.v                          =       new char[locYBuffSize/4];
01332 
01333         //End YV12 specifics
01334         //
01335 
01336         //HACK:::Bit of a hack to convert dshow nanos to a fps num/denom.
01337         //Now we multiply the numerator and denom by 1000, this gives us 3 d.p. of precision for framerate.
01338         unsigned long locNum = (((double)10000000 * 1000) / ((double)mVideoFormat->AvgTimePerFrame)) + (double)0.5;
01339 
01340         //debugLog<<"FPS = "<<locNum<<endl;
01341         mTheoraInfo.fps_numerator = locNum;
01342         mTheoraInfo.fps_denominator = 1000;
01343         
01344         mTheoraInfo.aspect_numerator=0;
01345         mTheoraInfo.aspect_denominator=0;
01346         
01347         mTheoraInfo.colorspace=OC_CS_UNSPECIFIED;               //YV12
01348         mTheoraInfo.target_bitrate=400000; //mVideoFormat->dwBitRate;
01349 
01350         //Hard code for now
01351         mTheoraInfo.quality=30; //video_q;
01352 
01353         mTheoraInfo.dropframes_p=0;
01354         mTheoraInfo.quick_p=1;
01355         mTheoraInfo.keyframe_auto_p=1;
01356         mTheoraInfo.keyframe_frequency=64;   //If you change this... change the logged value below
01357         mTheoraInfo.keyframe_frequency_force=64;  //ditto
01358         mTheoraInfo.keyframe_data_target_bitrate=mTheoraInfo.target_bitrate*1.5;
01359         mTheoraInfo.keyframe_auto_threshold=80;
01360         mTheoraInfo.keyframe_mindistance=8;
01361         mTheoraInfo.noise_sensitivity=1; 
01362 
01363         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateNumerator = mTheoraInfo.fps_numerator;
01364         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateDenominator = mTheoraInfo.fps_denominator;
01365         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.maxKeyframeInterval = 6;   //log2(keyframe_freq) from above
01366         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.pictureHeight = mHeight;
01367         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.pictureWidth = mWidth;
01368         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.colourSpace = OC_CS_UNSPECIFIED;
01369         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.outerFrameHeight = mTheoraInfo.height;
01370         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.outerFrameWidth = mTheoraInfo.width;
01371         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.xOffset = (unsigned char)mXOffset;
01372         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.yOffset = (unsigned char)mYOffset;
01373 
01374         //TODO ::: DO something about aspect ratios
01375         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectDenominator = 0;
01376         ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectNumerator = 0;
01377 
01378         return true;
01379 
01380 }
01381 void TheoraEncodeInputPin::DestroyCodec() {
01382         //fish_sound_delete(mFishSound);
01383         //mFishSound = NULL;
01384 }
01385 
01386 
01387 
01388 HRESULT TheoraEncodeInputPin::SetMediaType(const CMediaType* inMediaType) {
01389         //AbstractVideoEncodeInputPin::SetMediaType(inMediaType);
01390 
01391         if  (   inMediaType->subtype == MEDIASUBTYPE_YV12 || 
01392                         inMediaType->subtype == MEDIASUBTYPE_IYUV ||
01393                         inMediaType->subtype == MEDIASUBTYPE_YUY2 ||
01394                         inMediaType->subtype == MEDIASUBTYPE_UYVY ||
01395                         inMediaType->subtype == MEDIASUBTYPE_YVYU ||
01396                         inMediaType->subtype == MEDIASUBTYPE_AYUV ||
01397                         inMediaType->subtype == MEDIASUBTYPE_RGB32 ||
01398                         inMediaType->subtype == MEDIASUBTYPE_RGB24
01399         ) {
01400                 mVideoFormat = (VIDEOINFOHEADER*)inMediaType->pbFormat;
01401                 mPinInputType = *inMediaType;
01402                 //mParentFilter->mAudioFormat = AbstractAudioDecodeFilter::VORBIS;
01403         } else {
01404                 //Failed... should never be here !
01405                 throw 0;
01406         }
01407         ConstructCodec();
01408         return CBaseInputPin::SetMediaType(inMediaType);
01409 
01410         
01411 }
01412 
01413 theora_info* TheoraEncodeInputPin::theoraInfo() {
01414         return &mTheoraInfo;
01415 }

Generated on Tue Feb 15 14:54:17 2005 for oggdsf by  doxygen 1.3.9