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 "diracencodeinputpin.h" 00034 00035 DiracEncodeInputPin::DiracEncodeInputPin(AbstractVideoEncodeFilter* inParentFilter, CCritSec* inFilterLock, AbstractVideoEncodeOutputPin* inOutputPin) 00036 : AbstractVideoEncodeInputPin(inParentFilter, inFilterLock, inOutputPin, NAME("DiracEncodeInputPin"), L"YV12 In") 00037 , mXOffset(0) 00038 , mYOffset(0) 00039 00040 00041 { 00042 //debugLog.open("g:\\logs\\theoencfiltinput.log", ios_base::out); 00043 00044 00045 } 00046 00047 DiracEncodeInputPin::~DiracEncodeInputPin(void) 00048 { 00049 //debugLog.close(); 00050 DestroyCodec(); 00051 00052 00053 } 00054 00055 00056 HRESULT DiracEncodeInputPin::deliverData(LONGLONG inStart, LONGLONG inEnd, unsigned char* inBuf, unsigned long inNumBytes) { 00057 //debugLog <<" deliverData : "<<inStart<<" - "<<inEnd<<" :: size = "<<inNumBytes<<endl; 00058 //Get a pointer to a new sample stamped with our time 00059 IMediaSample* locSample; 00060 HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, &inStart, &inEnd, NULL); 00061 00062 if (locHR != S_OK) { 00063 //We get here when the application goes into stop mode usually. 00064 return locHR; 00065 } 00066 00067 BYTE* locBuffer = NULL; 00068 00069 00070 //Make our pointers set to point to the samples buffer 00071 locSample->GetPointer(&locBuffer); 00072 00073 if (locSample->GetSize() >= inNumBytes) { 00074 00075 memcpy((void*)locBuffer, (const void*)inBuf, inNumBytes); 00076 00077 //Set the sample parameters. 00078 SetSampleParams(locSample, inNumBytes, &inStart, &inEnd); 00079 00080 { 00081 CAutoLock locLock(m_pLock); 00082 00083 HRESULT locHR = mOutputPin->mDataQueue->Receive(locSample); //->DownstreamFilter()->Receive(locSample); 00084 if (locHR != S_OK) { 00085 return locHR; 00086 } else { 00087 } 00088 } 00089 //debugLog<<"deliverData : SUCCESS"<<endl; 00090 return S_OK; 00091 } else { 00092 //debugLog<<"Buffer too small !!!! FATALITY !"<<endl; 00093 throw 0; 00094 } 00095 00096 } 00097 00098 long DiracEncodeInputPin::encodeYV12ToYV12(unsigned char* inBuf, long inNumBytes) { 00100 00109 00110 00120 00124 // 00128 00131 00132 00134 //unsigned char* locSourceUptoPtr = inBuf; //View only... don't delete locUptoPtr 00136 // 00140 00142 //char* locDestUptoPtr = mYUV.y; 00144 00146 //if (mYOffset != 0) { 00147 // memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width); //Is it needed to zero this out ? Or just leave junk ? 00148 // locDestUptoPtr += (mYOffset * mYUV.y_width); 00149 //} 00152 00154 //if (mXOffset == 0) { 00155 // //Slight optimisation to keep the inner loop tighter 00156 // for (long line = 0; line < mHeight; line++) { 00157 // memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth); 00158 // locSourceUptoPtr += mWidth; 00159 // locDestUptoPtr += mWidth; 00160 // } 00161 //} else { 00162 // for (long line = 0; line < mHeight; line++) { 00163 // //Pad the start of the line with mXOffset bytes 00164 // memset((void*)locDestUptoPtr, NULL, mXOffset); 00165 // locDestUptoPtr += mXOffset; 00166 00167 // //Fill in the meaty bit 00168 // memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth); 00169 // locSourceUptoPtr += mWidth; 00170 // locDestUptoPtr += mWidth; 00171 00172 // //Pad the end of the line with mXOffset bytes 00173 // memset((void*)locDestUptoPtr, NULL, mXOffset); 00174 // locDestUptoPtr += mXOffset; 00175 // } 00176 00177 //} 00178 00180 //if (mYOffset != 0) { 00181 // memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width); //Is it needed to zero this out ? Or just leave junk ? 00182 // locDestUptoPtr += (mYOffset * mYUV.y_width); 00183 // //Source pointer does not advance 00184 //} 00185 // 00186 00187 00191 00193 //locDestUptoPtr = mYUV.v; 00195 00197 //if (mYOffset != 0) { 00198 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ? 00199 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2); 00200 // //Source pointer does not advance 00201 //} 00203 00205 //if (mXOffset == 0) { 00206 // //Slight optimisation to keep the inner loop tighter 00207 // for (long line = 0; line < mHeight / 2; line++) { 00208 // memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2); 00209 // locSourceUptoPtr += (mWidth / 2); 00210 // locDestUptoPtr += (mWidth / 2); 00211 // } 00212 //} else { 00213 // for (long line = 0; line < mHeight / 2; line++) { 00214 // //Pad the start of the line 00215 // memset((void*)locDestUptoPtr, NULL, mXOffset / 2); 00216 // locDestUptoPtr += (mXOffset / 2); 00217 // //Source pointer does not advance 00218 00219 // //Fill in the meaty bit 00220 // memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2); 00221 // locSourceUptoPtr += (mWidth / 2); 00222 // locDestUptoPtr += (mWidth / 2); 00223 00224 // //Pad the end of the line 00225 // memset((void*)locDestUptoPtr, NULL, mXOffset / 2); 00226 // locDestUptoPtr += (mXOffset / 2); 00227 // //Source pointer does not advance 00228 // } 00229 00230 //} 00231 00233 //if (mYOffset != 0) { 00234 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ? 00235 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2); 00236 // //Source pointer does not advance 00237 //} 00238 // 00239 00240 00241 00242 00246 00248 //locDestUptoPtr = mYUV.u; 00250 00252 //if (mYOffset != 0) { 00253 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ? 00254 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2); 00255 // //Source pointer does not advance 00256 //} 00258 00260 //if (mXOffset == 0) { 00261 // //Slight optimisation to keep the inner loop tighter 00262 // for (long line = 0; line < mHeight / 2; line++) { 00263 // memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2); 00264 // locSourceUptoPtr += (mWidth / 2); 00265 // locDestUptoPtr += (mWidth / 2); 00266 // } 00267 //} else { 00268 // for (long line = 0; line < mHeight / 2; line++) { 00269 // //Pad the start of the line 00270 // memset((void*)locDestUptoPtr, NULL, mXOffset / 2); 00271 // locDestUptoPtr += (mXOffset / 2); 00272 // //Source pointer does not advance 00273 00274 // //Fill in the meaty bit 00275 // memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2); 00276 // locSourceUptoPtr += (mWidth / 2); 00277 // locDestUptoPtr += (mWidth / 2); 00278 00279 // //Pad the end of the line 00280 // memset((void*)locDestUptoPtr, NULL, mXOffset / 2); 00281 // locDestUptoPtr += (mXOffset / 2); 00282 // //Source pointer does not advance 00283 // } 00284 00285 //} 00286 00288 //if (mYOffset != 0) { 00289 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ? 00290 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2); 00291 // //Source pointer does not advance 00292 //} 00293 00295 return 0; 00296 00297 } 00298 00299 //------------------------------------------------------------------------- 00300 00301 00302 00303 00304 00305 //PURE VIRTUALS 00306 long DiracEncodeInputPin::encodeData(unsigned char* inBuf, long inNumBytes) { 00307 00308 //TODO::: Break this function up a bit !! 00309 00310 //Time stamps are granule pos not directshow times 00311 //debugLog<<"Encode data"<<endl; 00312 00313 00314 LONGLONG locFrameStart = mUptoFrame; 00315 LONGLONG locFrameEnd = 0; 00316 HRESULT locHR = S_OK; 00317 if (!mBegun) { 00318 //debugLog<<"encodeData : First time"<<endl; 00319 //mBegun = true; 00320 // 00321 //StampedOggPacket** locHeaders; 00322 //locHeaders = mTheoraEncoder.initCodec(mTheoraInfo); 00323 00324 //for (int i = 0; i < 3; i++) { 00325 // locHR = deliverData(0,0,locHeaders[i]->packetData(), locHeaders[i]->packetSize()); 00326 // if (locHR != S_OK) { 00327 // return locHR; 00328 // } 00329 //} 00330 } 00331 00332 if (mPinInputType.subtype == MEDIASUBTYPE_YV12) { 00333 00334 encodeYV12ToYV12(inBuf, inNumBytes); 00335 00336 00337 00338 00339 //} else if (mPinInputType.subtype == MEDIASUBTYPE_AYUV) { 00340 // encodeAYUVtoYV12(inBuf, inNumBytes); 00341 00342 //} else if (mPinInputType.subtype == MEDIASUBTYPE_RGB32) { 00343 // encodeRGB32toYV12(inBuf, inNumBytes); 00344 00345 //} else if (mPinInputType.subtype == MEDIASUBTYPE_RGB24) { 00346 // encodeRGB24toYV12(inBuf, inNumBytes); 00347 00348 00349 //} else if (mPinInputType.subtype == MEDIASUBTYPE_YV12) { 00350 // //Should be more specifc. 00351 // //debugLog<<"About to encode YV12 to YV12"<<endl; 00352 // encodeYV12ToYV12(inBuf, inNumBytes); 00353 //} else if (mPinInputType.subtype == MEDIASUBTYPE_UYVY) { 00354 // 00355 // 00356 // encodeUYVYToYV12(inBuf, inNumBytes); 00357 00358 //} else if (mPinInputType.subtype == MEDIASUBTYPE_YVYU) { 00359 // 00360 // 00361 // encodeYVYUToYV12(inBuf, inNumBytes); 00362 //} else if (mPinInputType.subtype == MEDIASUBTYPE_IYUV) { 00363 // 00364 // 00365 // encodeIYUVToYV12(inBuf, inNumBytes); 00366 00367 00368 } else { 00369 00370 //FATAL ERROR 00371 throw 0; 00372 } 00373 00374 00375 //StampedOggPacket* locPacket = mTheoraEncoder.encodeTheora(&mYUV); 00376 //if (locPacket == NULL) { 00377 // //debugLog<<"Encode returns NULL"<<endl; 00378 // return S_FALSE; 00379 //} 00380 //locFrameEnd = mUptoFrame 00381 // = locPacket->endTime(); 00382 //debugLog<<"Delivering..."<<endl; 00383 00384 00385 00386 00387 00388 //return deliverData(locFrameStart, locFrameEnd, locPacket->packetData(), locPacket->packetSize()); 00389 00390 } 00391 bool DiracEncodeInputPin::ConstructCodec() { 00392 00393 //debugLog<<"Contructing codec..."<<endl; 00394 // theora_info_init(&mTheoraInfo); 00395 00396 //Round up to multiple of 16 for theora 00397 00398 //--------------------------------------------------------------------------------------------------------------- 00399 //mTheoraInfo values 00400 //================== 00401 //width, height - /16 up rounded values 00402 //frame_width, frame_height - raw video source values 00403 //offset_x - CENTRED - *half* the difference between width and frame_width 00404 //offset_y - CENTRED - *half* the difference between height and frame_heigth 00405 00406 //mYUV values - for YV12 format 00407 //============================= 00408 //y_width, y_stride - Both equal and equal to the /16 up rounded wdith values 00409 //uv_width, uv_stride - Both equal and equal to *half* the /16 up rounded width values 00410 //y_height - Equal to the /16 up rounded height value 00411 //uv_height - Equal to *half* the /16 up rounded height value 00412 //y - Buffer of size y_width*y_height (/16 up rounded values) 00413 //u,v - Buffers each *quarter* the size of the y buffer (/16 up rounded values) 00414 00415 //Member data 00416 //=========== 00417 //mWidth - raw video source values... equal to frame_width 00418 //mHeight - raw video source values... equal to frame_height 00419 //mXOffset - x offset 00420 //mYOffset - y offset 00421 //--------------------------------------------------------------------------------------------------------------- 00422 00424 //mTheoraInfo.width = mYUV.y_width 00425 // = mYUV.y_stride 00426 // = (((mVideoFormat->bmiHeader.biWidth + 15)>>4)<<4); 00427 00428 //mTheoraInfo.frame_width = mWidth 00429 // = mVideoFormat->bmiHeader.biWidth; 00430 00431 //mYUV.uv_width = mYUV.uv_stride 00432 // = mYUV.y_width/2; 00433 00434 // 00436 00438 //mTheoraInfo.height = mYUV.y_height 00439 // = (((mVideoFormat->bmiHeader.biHeight + 15)>>4)<<4); 00440 00441 //mTheoraInfo.frame_height = mHeight 00442 // = mVideoFormat->bmiHeader.biHeight; 00443 00444 //mYUV.uv_height = mYUV.y_height/2; 00445 00446 // 00448 00450 //mTheoraInfo.offset_x = mXOffset 00451 // = (mTheoraInfo.width - mWidth) / 2; 00452 00453 //mTheoraInfo.offset_y = mYOffset 00454 // = (mTheoraInfo.height - mHeight) / 2; 00455 // 00456 //unsigned long locYBuffSize = mYUV.y_height * mYUV.y_width; 00457 //mYUV.y = new char[locYBuffSize]; 00458 //mYUV.u = new char[locYBuffSize/4]; 00459 //mYUV.v = new char[locYBuffSize/4]; 00460 00463 00470 // 00471 00473 //unsigned long locNum = (((double)10000000) / ((double)mVideoFormat->AvgTimePerFrame)) + (double)0.5; 00474 00476 //mTheoraInfo.fps_numerator = locNum; 00477 //mTheoraInfo.fps_denominator = 1; 00478 // 00479 //mTheoraInfo.aspect_numerator=0; 00480 //mTheoraInfo.aspect_denominator=0; 00481 // 00482 //mTheoraInfo.colorspace=OC_CS_UNSPECIFIED; //YV12 00483 //mTheoraInfo.target_bitrate=400000; //mVideoFormat->dwBitRate; 00484 00486 //mTheoraInfo.quality=30; //video_q; 00487 00488 //mTheoraInfo.dropframes_p=0; 00489 //mTheoraInfo.quick_p=1; 00490 //mTheoraInfo.keyframe_auto_p=1; 00491 //mTheoraInfo.keyframe_frequency=64; //If you change this... change the logged value below 00492 //mTheoraInfo.keyframe_frequency_force=64; //ditto 00493 //mTheoraInfo.keyframe_data_target_bitrate=mTheoraInfo.target_bitrate*1.5; 00494 //mTheoraInfo.keyframe_auto_threshold=80; 00495 //mTheoraInfo.keyframe_mindistance=8; 00496 //mTheoraInfo.noise_sensitivity=1; 00497 00498 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateNumerator = locNum; 00499 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateDenominator = 1; 00500 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.maxKeyframeInterval = 6; //log2(keyframe_freq) from above 00501 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameHeight = mHeight; 00502 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameWidth = mWidth; 00503 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.colourSpace = OC_CS_UNSPECIFIED; 00504 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.height = mTheoraInfo.height; 00505 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.width = mTheoraInfo.width; 00506 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.xOffset = mXOffset; 00507 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.yOffset = mYOffset; 00508 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectDenominator = 0; 00509 //((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectNumerator = 0; 00510 00511 return true; 00512 00513 } 00514 void DiracEncodeInputPin::DestroyCodec() { 00515 //fish_sound_delete(mFishSound); 00516 //mFishSound = NULL; 00517 } 00518 00519 00520 00521 HRESULT DiracEncodeInputPin::SetMediaType(const CMediaType* inMediaType) { 00522 AbstractVideoEncodeInputPin::SetMediaType(inMediaType); 00523 00524 ConstructCodec(); 00525 00526 00527 return S_OK; 00528 00529 } 00530