Updated project files to VS2008 SP1. Removed deprecated features (and warning message...
[xiph/unicode.git] / oggdsf / src / lib / codecs / theora / filters / dsfTheoraEncoder / TheoraEncodeInputPin.cpp
blobb202a3c8c313f922474cf06ef950936b9d0d1d75
1 //===========================================================================
2 //Copyright (C) 2003, 2004 Zentaro Kavanagh
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions
6 //are met:
7 //
8 //- Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
11 //- Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
15 //- Neither the name of Zentaro Kavanagh nor the names of contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
19 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 //PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
23 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 //===========================================================================
32 #include "stdafx.h"
33 #include "theoraencodeinputpin.h"
35 TheoraEncodeInputPin::TheoraEncodeInputPin(AbstractTransformFilter* inParentFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
36 : AbstractTransformInputPin(inParentFilter, inFilterLock, inOutputPin, NAME("TheoraEncodeInputPin"), L"YV12 In", inAcceptableMediaTypes)
37 , mXOffset(0)
38 , mYOffset(0)
39 , mHeight(0)
40 , mWidth(0)
41 , mUptoFrame(0)
42 , mBegun(false)
43 , mVideoFormat(NULL)
47 //debugLog.open("g:\\logs\\theoencfiltinput.log", ios_base::out);
48 mYUV.y = NULL;
49 mYUV.u = NULL;
50 mYUV.v = NULL;
54 TheoraEncodeInputPin::~TheoraEncodeInputPin(void)
56 //debugLog.close();
57 DestroyCodec();
58 delete[] mYUV.y;
59 delete[] mYUV.u;
60 delete[] mYUV.v;
65 HRESULT TheoraEncodeInputPin::deliverData(LONGLONG inStart, LONGLONG inEnd, unsigned char* inBuf, unsigned long inNumBytes) {
66 //debugLog <<" deliverData : "<<inStart<<" - "<<inEnd<<" :: size = "<<inNumBytes<<endl;
67 //Get a pointer to a new sample stamped with our time
68 IMediaSample* locSample;
69 HRESULT locHR = mOutputPin->GetDeliveryBuffer(&locSample, &inStart, &inEnd, NULL);
71 if (locHR != S_OK) {
72 //We get here when the application goes into stop mode usually.
73 return locHR;
76 BYTE* locBuffer = NULL;
79 //Make our pointers set to point to the samples buffer
80 locSample->GetPointer(&locBuffer);
82 if (locSample->GetSize() >= inNumBytes) {
84 memcpy((void*)locBuffer, (const void*)inBuf, inNumBytes);
86 //Set the sample parameters.
87 SetSampleParams(locSample, inNumBytes, &inStart, &inEnd);
90 CAutoLock locLock(m_pLock);
92 HRESULT locHR = ((TheoraEncodeOutputPin*)mOutputPin)->mDataQueue->Receive(locSample); //->DownstreamFilter()->Receive(locSample);
93 if (locHR != S_OK) {
94 return locHR;
95 } else {
98 //debugLog<<"deliverData : SUCCESS"<<endl;
99 return S_OK;
100 } else {
101 //debugLog<<"Buffer too small !!!! FATALITY !"<<endl;
102 throw 0;
107 long TheoraEncodeInputPin::encodeYV12ToYV12(unsigned char* inBuf, long inNumBytes) {
109 // Now properly pads on one side only... 20/12/04
112 //Source Buffer all in one buffer
114 //YV12 memory layout for directshow
115 //=================================
116 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
117 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
118 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
119 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
120 //VVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVV
121 //UUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUU
124 //Destination buffer Y, U, V in seperate planes, lowercase are line padding, "." height padding
125 //.............................. ..............................
126 //.............................. ..............................
127 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
128 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
129 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
130 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
131 //.............................. ..............................
132 //.............................. ..............................
134 //.............................. ..............................
135 //vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv
136 //.............................. ..............................
138 //.............................. ..............................
139 //uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu
140 //.............................. ..............................
142 //NOTE : mHeight, mWidth are the actual video sizes and are the sizes of the incoming buffer
143 // The yuv width, height parameters are a /16 up rounded size of the output buffer to be sent to libtheora
146 //Setup the source pointer
147 unsigned char* locSourceUptoPtr = inBuf; //View only... don't delete locUptoPtr
150 //========
151 //Y DATA |
152 //=========================================================================================================
154 //Setup the destination pointer
155 unsigned char* locDestUptoPtr = mYUV.y;
158 ////Pad top of output Y plane buffer with mYOffset lines of width mYUV.y_width
159 ////y_width is the out frame width.
160 //if (mYOffset != 0) {
161 // memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width); //Is it needed to zero this out ? Or just leave junk ?
162 // locDestUptoPtr += (mYOffset * mYUV.y_width); //I'm fairly sure it can be junk... but leave for now !
164 //Source pointer does not advance
167 //Add mHeight lines of data of width mWidth plus padding of mXOffset at the start of each line
168 if (mXOffset == 0) {
169 //Slight optimisation to keep the inner loop tighter
171 //This branch of the condition does exactly the same as the else branch where mXOffset = 0
172 for (unsigned long line = 0; line < mHeight; line++) {
173 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
174 locSourceUptoPtr += mWidth;
175 locDestUptoPtr += mWidth;
177 } else {
178 for (unsigned long line = 0; line < mHeight; line++) {
179 //Pad the start of the line with mXOffset bytes
180 memset((void*)locDestUptoPtr, NULL, mXOffset);
181 locDestUptoPtr += mXOffset;
183 //Fill in the meaty bit
184 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
185 locSourceUptoPtr += mWidth;
186 locDestUptoPtr += mWidth;
189 //This is no longer done... we just pad on one side for efficiency
191 //Pad the end of the line with mXOffset bytes
192 //memset((void*)locDestUptoPtr, NULL, mXOffset);
193 //locDestUptoPtr += mXOffset;
199 //Pad bottom of Y plane buffer with mYOffset lines of width mYUV.y_width
200 if (mYOffset != 0) {
201 memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width); //Is it needed to zero this out ? Or just leave junk ?
202 locDestUptoPtr += (mYOffset * mYUV.y_width);
203 //Source pointer does not advance
208 //========
209 //V DATA |
210 //=========================================================================================================
212 //Set the destination poitner
213 locDestUptoPtr = mYUV.v;
216 //ASSERT (mYOffset is EVEN)
217 //ASSERT (mHeight is EVEN)
218 //ASSERT (mWidth is EVEN)
221 ////Pad top of V plane buffer with mYOffset/2 lines of width mYUV.uv_width
222 //if (mYOffset != 0) {
223 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
224 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
225 // //Source pointer does not advance
227 ////
229 //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
230 if (mXOffset == 0) {
231 //Slight optimisation to keep the inner loop tighter
232 for (unsigned long line = 0; line < mHeight / 2; line++) {
233 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
234 locSourceUptoPtr += (mWidth / 2);
235 locDestUptoPtr += (mWidth / 2);
237 } else {
238 for (unsigned long line = 0; line < mHeight / 2; line++) {
239 //Pad the start of the line
240 memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
241 locDestUptoPtr += (mXOffset / 2);
242 //Source pointer does not advance
244 //Fill in the meaty bit
245 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
246 locSourceUptoPtr += (mWidth / 2);
247 locDestUptoPtr += (mWidth / 2);
250 //This is no longer done... we just pad on one side for efficiency
253 ////Pad the end of the line
254 //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
255 //locDestUptoPtr += (mXOffset / 2);
256 ////Source pointer does not advance
262 //Pad bottom of V plane buffer with mYOffset / 2 lines of width mYUV.uv_width
263 if (mYOffset != 0) {
264 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
265 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
266 //Source pointer does not advance
273 //========
274 //U DATA |
275 //=========================================================================================================
277 //Set the destination pointer
278 locDestUptoPtr = mYUV.u;
281 ////Pad top of U plane buffer with mYOffset/2 lines of width mYUV.uv_width
282 //if (mYOffset != 0) {
283 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
284 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
285 // //Source pointer does not advance
287 ////
289 //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
290 if (mXOffset == 0) {
291 //Slight optimisation to keep the inner loop tighter
292 for (unsigned long line = 0; line < mHeight / 2; line++) {
293 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
294 locSourceUptoPtr += (mWidth / 2);
295 locDestUptoPtr += (mWidth / 2);
297 } else {
298 for (unsigned long line = 0; line < mHeight / 2; line++) {
299 //Pad the start of the line
300 memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
301 locDestUptoPtr += (mXOffset / 2);
302 //Source pointer does not advance
304 //Fill in the meaty bit
305 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
306 locSourceUptoPtr += (mWidth / 2);
307 locDestUptoPtr += (mWidth / 2);
310 //This is no longer done... we just pad on one side for efficiency
313 ////Pad the end of the line
314 //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
315 //locDestUptoPtr += (mXOffset / 2);
316 ////Source pointer does not advance
322 //Pad bottom of U plane buffer with mYOffset / 2 lines of width mYUV.uv_width
323 if (mYOffset != 0) {
324 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
325 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
326 //Source pointer does not advance
329 //======================================================================================================
330 return 0;
334 //-------------------------------------------------------------------------
336 long TheoraEncodeInputPin::encodeIYUVToYV12(unsigned char* inBuf, long inNumBytes) {
338 // Now properly pads on one side only... 20/12/04
341 //Same as YV12 but planes U and V are reversed.
343 //Source Buffer all in one buffer
345 //IYUV memory layout for directshow
346 //=================================
347 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
348 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
349 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
350 //YYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYY
352 //UUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUU
354 //VVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVV
358 //Destination buffer Y, U, V in seperate planes, lowercase are line padding, "." height padding
359 //.............................. ..............................
360 //.............................. ..............................
361 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
362 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
363 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
364 //yyyyyyYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYyyyyyy
365 //.............................. ..............................
366 //.............................. ..............................
368 //.............................. ..............................
369 //uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu uuuUUUUUUUUUUUUUUUUUUUUUUUUuuu
370 //.............................. ..............................
372 //.............................. ..............................
373 //vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv vvvVVVVVVVVVVVVVVVVVVVVVVVVvvv
374 //.............................. ..............................
378 //NOTE : mHeight, mWidth are the actual video sizes and are the sizes of the incoming buffer
379 // The yuv width, height parameters are a /16 up rounded size of the output buffer to be sent to libtheora
382 //Setup the source pointer
383 unsigned char* locSourceUptoPtr = inBuf; //View only... don't delete locUptoPtr
386 //========
387 //Y DATA |
388 //=========================================================================================================
390 //Setup the destination pointer
391 unsigned char* locDestUptoPtr = mYUV.y;
394 ////Pad top of Y plane buffer with mYOffset lines of width mYUV.y_width
395 //if (mYOffset != 0) {
396 // memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width); //Is it needed to zero this out ? Or just leave junk ?
397 // locDestUptoPtr += (mYOffset * mYUV.y_width);
399 //Source pointer does not advance
402 //Add mHeight lines of data of width mWidth plus padding of mXOffset at each end
403 if (mXOffset == 0) {
404 //Slight optimisation to keep the inner loop tighter
405 for (unsigned long line = 0; line < mHeight; line++) {
406 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
407 locSourceUptoPtr += mWidth;
408 locDestUptoPtr += mWidth;
410 } else {
411 for (unsigned long line = 0; line < mHeight; line++) {
412 //Pad the start of the line with mXOffset bytes
413 memset((void*)locDestUptoPtr, NULL, mXOffset);
414 locDestUptoPtr += mXOffset;
416 //Fill in the meaty bit
417 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth);
418 locSourceUptoPtr += mWidth;
419 locDestUptoPtr += mWidth;
421 ////Pad the end of the line with mXOffset bytes
422 //memset((void*)locDestUptoPtr, NULL, mXOffset);
423 //locDestUptoPtr += mXOffset;
428 //Pad bottom of Y plane buffer with mYOffset lines of width mYUV.y_width
429 if (mYOffset != 0) {
430 memset((void*)locDestUptoPtr, NULL, mYOffset * mYUV.y_width); //Is it needed to zero this out ? Or just leave junk ?
431 locDestUptoPtr += (mYOffset * mYUV.y_width);
432 //Source pointer does not advance
435 //========
436 //U DATA |
437 //=========================================================================================================
439 //Set the destination pointer
440 locDestUptoPtr = mYUV.u;
443 ////Pad top of U plane buffer with mYOffset/2 lines of width mYUV.uv_width
444 //if (mYOffset != 0) {
445 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
446 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
447 // //Source pointer does not advance
451 //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
452 if (mXOffset == 0) {
453 //Slight optimisation to keep the inner loop tighter
454 for (unsigned long line = 0; line < mHeight / 2; line++) {
455 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
456 locSourceUptoPtr += (mWidth / 2);
457 locDestUptoPtr += (mWidth / 2);
459 } else {
460 for (unsigned long line = 0; line < mHeight / 2; line++) {
461 //Pad the start of the line
462 memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
463 locDestUptoPtr += (mXOffset / 2);
464 //Source pointer does not advance
466 //Fill in the meaty bit
467 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
468 locSourceUptoPtr += (mWidth / 2);
469 locDestUptoPtr += (mWidth / 2);
471 ////Pad the end of the line
472 //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
473 //locDestUptoPtr += (mXOffset / 2);
474 ////Source pointer does not advance
479 //Pad bottom of U plane buffer with mYOffset / 2 lines of width mYUV.uv_width
480 if (mYOffset != 0) {
481 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
482 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
483 //Source pointer does not advance
488 //========
489 //V DATA |
490 //=========================================================================================================
492 //Set the destination poitner
493 locDestUptoPtr = mYUV.v;
496 ////Pad top of V plane buffer with mYOffset/2 lines of width mYUV.uv_width
497 //if (mYOffset != 0) {
498 // memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
499 // locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
500 // //Source pointer does not advance
502 ////
504 //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
505 if (mXOffset == 0) {
506 //Slight optimisation to keep the inner loop tighter
507 for (unsigned long line = 0; line < mHeight / 2; line++) {
508 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
509 locSourceUptoPtr += (mWidth / 2);
510 locDestUptoPtr += (mWidth / 2);
512 } else {
513 for (unsigned long line = 0; line < mHeight / 2; line++) {
514 //Pad the start of the line
515 memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
516 locDestUptoPtr += (mXOffset / 2);
517 //Source pointer does not advance
519 //Fill in the meaty bit
520 memcpy((void*)locDestUptoPtr, (const void*)locSourceUptoPtr, mWidth / 2);
521 locSourceUptoPtr += (mWidth / 2);
522 locDestUptoPtr += (mWidth / 2);
524 ////Pad the end of the line
525 //memset((void*)locDestUptoPtr, NULL, mXOffset / 2);
526 //locDestUptoPtr += (mXOffset / 2);
527 ////Source pointer does not advance
532 //Pad bottom of V plane buffer with mYOffset / 2 lines of width mYUV.uv_width
533 if (mYOffset != 0) {
534 memset((void*)locDestUptoPtr, NULL, (mYOffset * mYUV.uv_width) / 2); //Is it needed to zero this out ? Or just leave junk ?
535 locDestUptoPtr += ((mYOffset * mYUV.uv_width) / 2);
536 //Source pointer does not advance
544 //======================================================================================================
545 return 0;
548 //-------------------------------------------------------------------------
550 long TheoraEncodeInputPin::encodeRGB24toYV12(unsigned char* inBuf, long inNumBytes) {
551 //Blue Green Red Blue Green Red.
552 unsigned long locNumPixels = (inNumBytes/3);
553 unsigned char* locAYUVBuf = new unsigned char[locNumPixels<<2]; //4 bytes per pixel
560 Conversion from RGB to YUV is defined by starting with the following:
562 L = Kr * R + Kb * B + (1 – Kr – Kb) * G
564 The YUV values are then obtained as follows:
566 Y = floor(2^(M-8) * (219*(L–Z)/S + 16) + 0.5)
567 U = clip3(0, 2^M-1, floor(2^(M-8) * (112*(B-L) / ((1-Kb)*S) + 128) + 0.5))
568 V = clip3(0, 2^M-1, floor(2^(M-8) * (112*(R-L) / ((1-Kr)*S) + 128) + 0.5))
570 where Z = 16
571 S = 219
572 M = 8 bits per sample.
575 Y = floor(L + 0.5)
576 U = (112*(B-L) / ((1-Kb)*S) + 128)
579 Kr' = Kr * 65536
580 Kb' = Kb * 65536
581 G_FACTOR = (1 - Kr - Kb) * 65536
583 L' = (Kr' * R) + (Kb' * B) + (G_FACTOR * G)
584 = 65536 * ( (Kr * R) + (Kb * B) + ((1 - Kr - Kb) * G) )
585 = 65536 * L
587 Y = round( 219 * (L-Z)/S + 16 )
588 = round ( L-Z + 16 )
589 = round( L )
591 Y' = L'
592 = 65536 * L
594 Y = L' >> 16
596 U_FACTOR = ( 1 - Kb) * S
597 U_FACTOR' = 12716213
599 = 65536 * U_FACTOR
601 V_FACTOR' = 10061022
603 B' = 65536 * B
604 R' = 65536 * R
606 _U_ = round( 112 * (B-L) / ( (1-Kb)*S ) + 128 )
607 = round( (112 * (B-L) / U_FACTOR) + 128 )
608 = (112 * (B' - L') / U_FACTOR') + 128
609 = (112 * 65536 * (B - L) / (U_FACTOR * 65536)) + 128
610 = (112 * (B - L) / U_FACTOR) + 128
612 Hence integerisation scaling cancels
614 _U_ = (112 * (B' - L') / U_FACTOR') + 128
616 _V_ = (112 * (R' - L') / V_FACTOR') + 128
621 Kr = 0.299
622 Kb = 0.114
627 //Scaled by factor of 65536 to integerise.
628 const int KR = 19596;
629 const int KB = 7472;
631 const int ROUNDER = 32768;
633 const int G_FACTOR = 38470;
634 const int U_FACTOR = 12716213;
635 const int V_FACTOR = 10061022;
637 int locL = 0;
638 int locB = 0;
639 int locR = 0;
641 //unsigned char* locSourcePtr = inBuf;
642 unsigned char* locDestPtr = locAYUVBuf;
644 //SOURCE: Blue Green Red Blue Green Red.
645 //DEST: v u y a
647 unsigned char* locSourceEnds = inBuf + (locNumPixels * 3);
649 //Upside down... Upside down !
650 //for (unsigned char* locSourcePtr = inBuf; locSourcePtr < locSourceEnds; locSourcePtr += 3) {
651 // locB = locSourcePtr[0]; //Blue
652 // locL = KB * (locB); //Blue
654 // locL += G_FACTOR * (locSourcePtr[1]); //Green
656 // locR = locSourcePtr[2]; //Red
657 // locL += KR * (locR); //Red
660 // *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128); //V for Victor
661 // *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128); //U for ugly
662 // *(locDestPtr++) = CLIP3(0, 255, locL >> 16); //Y for yellow
663 // *(locDestPtr++) = 255; //A for alpha
667 unsigned char* locColSourcePtr = NULL;
668 unsigned char* locColEndPtr = NULL;
669 unsigned long locLineLength = mWidth * 3;
670 unsigned long col = 0;
671 for (unsigned char* locSourcePtr = locSourceEnds - locLineLength; locSourcePtr >= inBuf; locSourcePtr -= locLineLength) {
673 //for(unsigned char* locColSourcePtr = locSourcePtr, int i = 0; i < mWidth; i++, locColSourcePtr +=4) {
675 locColSourcePtr = locSourcePtr;
676 locColEndPtr = locColSourcePtr + locLineLength;
677 while (locColSourcePtr < locColEndPtr) {
678 locB = locColSourcePtr[0]; //Blue
679 locL = KB * (locB); //Blue
681 locL += G_FACTOR * (locColSourcePtr[1]); //Green
683 locR = locColSourcePtr[2]; //Red
684 locL += KR * (locR); //Red
687 *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128); //V for Victor
688 *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128); //U for ugly
689 *(locDestPtr++) = CLIP3(0, 255, locL >> 16); //Y for yellow
690 *(locDestPtr++) = 255; //A for alpha
692 //debugCount++;
693 locColSourcePtr+=3;
701 //Still need to pass through to the AYUV conversion.
702 encodeAYUVtoYV12(locAYUVBuf, locNumPixels<<2);
703 delete[] locAYUVBuf;
704 locAYUVBuf = NULL;
706 return 0;
711 long TheoraEncodeInputPin::encodeRGB32toYV12(unsigned char* inBuf, long inNumBytes) {
712 //Blue Green Red Alpha Blue Green Red Alpha
713 //debugLog<<"EncodeRGB32 To YV12 :"<<endl;
715 unsigned long locNumPixels = (inNumBytes/4);
717 //debugLog<<"EncodeRGB32 To YV12 : Num pixels = "<<locNumPixels<<endl;
718 //debugLog<<"EncodeRGB32 To YV12 : Num BYtes = "<<inNumBytes<<endl;
719 unsigned char* locAYUVBuf = new unsigned char[inNumBytes]; //4 bytes per pixel
721 //debugLog<<"EncodeRGB32 To YV12 :"<<endl;
723 //Scaled by factor of 65536 to integerise.
724 const int KR = 19596;
725 const int KB = 7472;
727 const int ROUNDER = 32768;
729 const int G_FACTOR = 38470;
730 const int U_FACTOR = 12716213;
731 const int V_FACTOR = 10061022;
733 int locL = 0;
734 int locB = 0;
735 int locR = 0;
737 //unsigned char* locSourcePtr = inBuf;
738 unsigned char* locDestPtr = locAYUVBuf;
740 //SOURCE: Blue Green Red Blue Green Red.
741 //DEST: v u y a
743 unsigned char* locSourceEnds = inBuf + (inNumBytes);
744 //debugLog<<"EncodeRGB32 To YV12 : Source Starts = "<<(int)inBuf<<endl;
745 //debugLog<<"EncodeRGB32 To YV12 : Source Ends = "<<(int)locSourceEnds<<endl;
747 //Debugging only... all refs to debugCount remove later
748 //unsigned long debugCount = 0;
751 //Upside down !!
752 //for (unsigned char* locSourcePtr = inBuf; locSourcePtr < locSourceEnds; locSourcePtr += 4) {
753 // locB = locSourcePtr[0]; //Blue
754 // locL = KB * (locB); //Blue
756 // locL += G_FACTOR * (locSourcePtr[1]); //Green
758 // locR = locSourcePtr[2]; //Red
759 // locL += KR * (locR); //Red
762 // *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128); //V for Victor
763 // *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128); //U for ugly
764 // *(locDestPtr++) = CLIP3(0, 255, locL >> 16); //Y for yellow
765 // *(locDestPtr++) = locSourcePtr[3]; //A for alpha
767 // debugCount++;
769 unsigned char* locColSourcePtr = NULL;
770 unsigned char* locColEndPtr = NULL;
771 unsigned long locLineLength = mWidth * 4;
772 unsigned long col = 0;
773 for (unsigned char* locSourcePtr = locSourceEnds - locLineLength; locSourcePtr >= inBuf; locSourcePtr -= locLineLength) {
775 //for(unsigned char* locColSourcePtr = locSourcePtr, int i = 0; i < mWidth; i++, locColSourcePtr +=4) {
777 locColSourcePtr = locSourcePtr;
778 locColEndPtr = locColSourcePtr + locLineLength;
779 while (locColSourcePtr < locColEndPtr) {
780 locB = locColSourcePtr[0]; //Blue
781 locL = KB * (locB); //Blue
783 locL += G_FACTOR * (locColSourcePtr[1]); //Green
785 locR = locColSourcePtr[2]; //Red
786 locL += KR * (locR); //Red
789 *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locR<<16) - locL)) / V_FACTOR) + 128); //V for Victor
790 *(locDestPtr++) = CLIP3(0, 255, ((112 * ( (locB<<16) - locL)) / U_FACTOR) + 128); //U for ugly
791 *(locDestPtr++) = CLIP3(0, 255, locL >> 16); //Y for yellow
792 *(locDestPtr++) = locColSourcePtr[3]; //A for alpha
794 //debugCount++;
795 locColSourcePtr+=4;
802 //debugLog<<"EncodeRGB32 To YV12 : debugCount = "<<debugCount<<endl;
804 //ASSERT(debugCount == locNumPixels);
806 ASSERT(locDestPtr == (locAYUVBuf + inNumBytes));
808 //debugLog<<"EncodeRGB32 To YV12 : Calling AYUV to YV12 conversion"<<endl;
809 //Still need to pass through to the AYUV conversion.
811 encodeAYUVtoYV12(locAYUVBuf, inNumBytes);
812 delete[] locAYUVBuf;
813 locAYUVBuf = NULL;
815 return 0;
821 long TheoraEncodeInputPin::encodeAYUVtoYV12(unsigned char* inBuf, long inNumBytes) {
823 //TODO::: This doesn't appear to do offsets.
825 //Victor Ugly Yellow Alpha --fonts are fuzzy late at night-- (Yellow is not colour yellow)
827 //AYUV is VUYA VUYA VUYA VUYA 4:4:4 sampling
828 // Twice the vertical and horizontal sampling of YV12 in chrominance
830 //Strategy : Process two lines and 2 cols at a time averaging 4 U and V around the position where a
831 // YV12 chroma sample will be... leave luminance samples... ignore alpha samples
833 //debugLog<<"Encode AYUV To YV12 :"<<endl;
835 const int PIXEL_BYTE_SIZE = 4;
836 ASSERT (mHeight % 2 == 0);
837 ASSERT (mWidth % 2 == 0);
839 unsigned char* locSourceUptoPtr = inBuf; //View only... don't delete locUptoPtr
840 unsigned char* locSourceNextLine = locSourceUptoPtr + (mWidth * PIXEL_BYTE_SIZE); //View only don't delete
842 unsigned char* locYUpto = mYUV.y;
843 unsigned char* locUUpto = mYUV.u;
844 unsigned char* locVUpto = mYUV.v;
845 //Pointer to the same pixel on next line
846 unsigned char* locDestNextLine = locYUpto + (mYUV.y_stride); //View only... don't delete
848 int temp = 0;
850 //Process 2 lines at a time
851 for (unsigned long line = 0; line < mHeight; line += 2) {
852 //debugLog<<"Encode AYUV To YV12 : ++ Line = "<<line<<endl;
854 //Ensures the current destination buffer skips a line ie points to line 2, 4, 6 etc
855 locYUpto = (mYUV.y + (line * mYUV.y_stride));
856 //Ensures the nextlinedest skips a
857 locDestNextLine = locYUpto + (mYUV.y_stride);
859 //locUUpto = (mYUV.u + ((line/2) * mYUV.uv_stride));
860 //locVUpto = (mYUV.v + ((line/2) * mYUV.uv_stride));
862 ASSERT (locSourceUptoPtr == (inBuf + (line * (mWidth * PIXEL_BYTE_SIZE))));
863 ASSERT (locSourceNextLine == locSourceUptoPtr + (mWidth * PIXEL_BYTE_SIZE));
864 ASSERT (locYUpto == (mYUV.y + (line * mYUV.y_stride)));
865 ASSERT (locDestNextLine == locYUpto + (mYUV.y_stride));
868 //Pad out the start of the line if needed
869 if (mXOffset != 0) {
870 memset((void*)locYUpto, 0, mXOffset);
871 memset((void*)locDestNextLine, 0, mXOffset);
872 memset((void*)locUUpto, 0, mXOffset/2);
873 memset((void*)locVUpto, 0, mXOffset/2);
874 locYUpto += mXOffset;
875 locDestNextLine += mXOffset;
876 locUUpto += (mXOffset/2);
877 locVUpto += (mXOffset/2);
879 //Columns also done 2 at a time
880 for (unsigned long col = 0; col < mWidth; col += 2) {
881 //debugLog<<"Encode AYUV To YV12 : ++++++ Col = "<<col<<endl;
887 // v u y a v u y a
888 //SourceUpto ^
889 //NextUpto ^
891 //====================
892 //V for Victor samples
893 //====================
894 temp = *(locSourceUptoPtr++); //Current pixel
896 // v u y a v u y a
897 //SourceUpto ^
898 //NextUpto ^
900 //This is three as we already advanced one and are pointing to a u not a v
901 temp += *(locSourceUptoPtr + 3); //Pixel to right
902 temp += *(locSourceNextLine++); //Pixel below
904 // v u y a v u y a
905 //SourceUpto ^
906 //NextUpto ^
908 temp += *(locSourceNextLine + 3); //Pixel below right
909 temp >>= 2; //Divide by 4 to average.
910 *(locVUpto++) = (unsigned char)temp;
912 // v u y a v u y a
913 //SourceUpto ^
914 //NextUpto ^
916 //====================
917 //U for Ugly samples
918 //====================
919 temp = *(locSourceUptoPtr++); //Current pixel
921 // v u y a v u y a
922 //SourceUpto ^
923 //NextUpto ^
925 temp += *(locSourceUptoPtr + 3); //Pixel to right
926 temp += *(locSourceNextLine++); //Pixel below
929 // v u y a v u y a
930 //SourceUpto ^
931 //NextUpto ^
933 temp += *(locSourceNextLine + 3); //Pixel below right
934 temp >>= 2; //Divide by 4 to average.
935 *(locUUpto++) = (unsigned char)temp;
937 // v u y a v u y a
938 //SourceUpto ^
939 //NextUpto ^
941 //====================
942 //Y for Yellow samples.
943 //====================
945 *(locYUpto++) = *(locSourceUptoPtr++);
946 *(locDestNextLine++) = *(locSourceNextLine++);
948 // v u y a v u y a
949 //SourceUpto ^
950 //NextUpto ^
952 //Ignore the alpha channel
953 //--
954 //locSourceUptoPtr++; //Optimised away... merged into increment below
955 //locSourceNextLine++; // " " " " " " " " " " "
957 // v u y a v u y a
958 //SourceUpto ^
959 //NextUpto ^
962 //--
963 //Source and next pointer have advanced four bytes so far.
964 //Added 2 Y for yellows (one from each line) and one each of U and V, ignore an A on each line
965 //--
967 //Current line extra Y for yellows.
968 locSourceUptoPtr += 3; //Skip the A and U and V samples
969 *(locYUpto++) = *(locSourceUptoPtr); //get the Y for yellow sample
970 locSourceUptoPtr += 2; //Advance 1 for the Y for yellow and Skip the A sample.
972 // v u y a v u y a
973 //SourceUpto ^
974 //NextUpto ^
977 //Next line extra Y for yellows.
978 locSourceNextLine += 3; //Skip the A and U and V samples
979 *(locDestNextLine++) = *(locSourceNextLine); //get the Y for yellow sample
980 locSourceNextLine += 2; //Advance 1 for the Y for yellow and Skip the A sample.
982 // v u y a v u y a
983 //SourceUpto ^
984 //NextUpto ^
986 //--
987 //In total source and next pointer advanced 8 bytes on each line, and we got 4 Y for yellows (2 each line)
988 // and one each U, V, ignored 4 A's (2 each line)
989 //--
993 //Overall this loop will advance :
994 //Sourceupto by = 8 bytes * (mWidth in pixels / 2 pixels at a time) * 2 lines
995 // = 8 * mWidth
996 // = 2 lines of 4 byte pixels of pixel width mWidth
997 //and the same for sourcenextline
998 //--
999 //At the end of this loop sourceupto points to the end of the current line (start of next line)
1000 // and nextupto points to the end of the next line
1002 //On the next iteration we want the sourceupto to point 2 lines down from where it did on the previous one
1003 // This is the same place that the sourcenextline points at the end of the iteration.
1004 //--
1006 //Ensures source will point to lines 2, 4, 6 etc.
1007 locSourceUptoPtr = locSourceNextLine;
1008 //Ensures nextlinesource is one line ahead of the main source.
1009 locSourceNextLine += (mWidth * PIXEL_BYTE_SIZE);
1014 return 0;
1016 long TheoraEncodeInputPin::encodeYUY2ToYV12(unsigned char* inBuf, long inNumBytes) {
1018 //TODO::: This doesn't do offsets properly.
1020 unsigned char* locSourceUptoPtr = inBuf; //View only... don't delete locUptoPtr
1022 //YUY2 is Y0 U0 Y1 V0 Y2 U1 Y3 V1
1023 // it has twice as much sampling height as YV12 so downsample it.
1025 unsigned char* locYUpto = mYUV.y;
1026 unsigned char* locUUpto = mYUV.u;
1027 unsigned char* locVUpto = mYUV.v;
1031 //After downsampling... from each block of 8, we get 4 y samples and 1 each of u and v
1034 for (unsigned long i = 0; i < mHeight / 2; i++) {
1035 //TO DO: Draw memory layouts.
1037 //***Part of the average method... store the pointer to the last of the previous line
1038 //locLastUUpto = locUUpto;
1039 //locLastVUpto = locVUpto;
1040 //***
1042 for (unsigned long j = 0; j < mWidth / 2; j++) {
1043 *(locYUpto++) = *(locSourceUptoPtr++);
1044 *(locUUpto++) = *(locSourceUptoPtr++);
1045 *(locYUpto++) = *(locSourceUptoPtr++);
1046 *(locVUpto++) = *(locSourceUptoPtr++);
1050 //***Drop line method
1051 for (unsigned long j = 0; j < mWidth / 2; j++) {
1052 //Ignore the second line
1053 *(locYUpto++) = *(locSourceUptoPtr++);
1054 locSourceUptoPtr++;
1055 *(locYUpto++) = *(locSourceUptoPtr++);
1056 locSourceUptoPtr++;
1058 //***
1060 //*** PArt of the Alternate method to average...
1061 //for (int j = 0; j < mWidth / 2; j++) {
1062 // //Ignore the second line
1063 // *(locYUpto++) = *(locSourceUptoPtr++);
1064 // *(locLastUUpto++) = ((short)(*locLastUUpto) + ((short)(*locUUpto))) / 2;
1066 // *(locYUpto++) = *(locSourceUptoPtr++);
1067 // *(locLastVUpto++) = ((short)(*locLastVUpto) + ((short)(*locVUpto))) / 2;
1070 //***
1075 return 0;
1078 long TheoraEncodeInputPin::encodeYVYUToYV12(unsigned char* inBuf, long inNumBytes) {
1079 //YVYU - Yellow Victor Yellow Ugly
1080 unsigned char* locSourceUptoPtr = inBuf; //View only... don't delete locUptoPtr
1082 //YUY2 is Y0 U0 Y1 V0 Y2 U1 Y3 V1
1083 //YVYU is Y0 V0 Y1 U0 Y2 V1 Y3 U1
1084 // it has twice as much sampling height as YV12 so downsample it.
1086 unsigned char* locYUpto = mYUV.y;
1087 unsigned char* locUUpto = mYUV.u;
1088 unsigned char* locVUpto = mYUV.v;
1092 //After downsampling... from each block of 8, we get 4 y samples and 1 each of u and v
1095 for (unsigned long i = 0; i < mHeight / 2; i++) {
1096 //TO DO: Draw memory layouts.
1100 for (unsigned long j = 0; j < mWidth / 2; j++) {
1101 *(locYUpto++) = *(locSourceUptoPtr++); //Y for Yellow
1102 *(locVUpto++) = *(locSourceUptoPtr++); //V for victor
1104 *(locYUpto++) = *(locSourceUptoPtr++); //Y for Yellow
1105 *(locUUpto++) = *(locSourceUptoPtr++); //U for Ugly
1109 //***Drop line method
1110 for (unsigned long j = 0; j < mWidth / 2; j++) {
1111 //Ignore the second line
1112 *(locYUpto++) = *(locSourceUptoPtr++); //Y for Yellow
1113 locSourceUptoPtr++; //V for victor
1114 *(locYUpto++) = *(locSourceUptoPtr++); //Y for yellow
1115 locSourceUptoPtr++; //U for ugly.
1119 return 0;
1123 long TheoraEncodeInputPin::encodeUYVYToYV12(unsigned char* inBuf, long inNumBytes) {
1124 //UYVY :: U0 Y0 V0 Y1 - Ugly Yellow Victor Yello
1125 unsigned char* locSourceUptoPtr = inBuf; //View only... don't delete locUptoPtr
1127 //UYVY is U0 Y0 V0 Y1 U0 Y2 V0 Y3
1128 //YUY2 is Y0 U0 Y1 V0 Y2 U1 Y3 V1
1129 // it has twice as much sampling height as YV12 so downsample it.
1131 unsigned char* locYUpto = mYUV.y;
1132 unsigned char* locUUpto = mYUV.u;
1133 unsigned char* locVUpto = mYUV.v;
1137 //After downsampling... from each block of 8, we get 4 y samples and 1 each of u and v
1140 for (unsigned long i = 0; i < mHeight / 2; i++) {
1141 //TO DO: Draw memory layouts.
1144 for (unsigned long j = 0; j < mWidth / 2; j++) {
1145 *(locUUpto++) = *(locSourceUptoPtr++); //U for Ugly
1146 *(locYUpto++) = *(locSourceUptoPtr++); //Y for Yellow
1148 *(locVUpto++) = *(locSourceUptoPtr++); //V for Victor
1149 *(locYUpto++) = *(locSourceUptoPtr++); //Y for Yellow
1154 //***Drop line method
1155 for (unsigned long j = 0; j < mWidth / 2; j++) {
1156 //Ignore the second line
1158 locSourceUptoPtr++; //U for ugly
1159 *(locYUpto++) = *(locSourceUptoPtr++); //Y for yellow
1161 locSourceUptoPtr++; //V for victor
1162 *(locYUpto++) = *(locSourceUptoPtr++); //Y for yellow
1168 return 0;
1173 //PURE VIRTUALS
1174 long TheoraEncodeInputPin::TransformData(unsigned char* inBuf, long inNumBytes) {
1176 //TODO::: Break this function up a bit !!
1178 //Time stamps are granule pos not directshow times
1179 //debugLog<<"Encode data"<<endl;
1180 LONGLONG locFrameStart = mUptoFrame;
1181 LONGLONG locFrameEnd = 0;
1182 HRESULT locHR = S_OK;
1183 if (!mBegun) {
1184 //debugLog<<"encodeData : First time"<<endl;
1185 mBegun = true;
1187 StampedOggPacket** locHeaders;
1188 locHeaders = mTheoraEncoder.initCodec(mTheoraInfo);
1190 for (int i = 0; i < 3; i++) {
1191 locHR = deliverData(0,0,locHeaders[i]->packetData(), locHeaders[i]->packetSize());
1192 delete locHeaders[i];
1193 if (locHR != S_OK) {
1194 return locHR;
1200 //This big if block merely takes the buffer and copies it into the yuv_buffer structure which
1201 // is used below to encode.
1202 if (mPinInputType.subtype == MEDIASUBTYPE_YUY2) {
1203 //debugLog<<"About to encode YUY2 to YV12"<<endl;
1204 encodeYUY2ToYV12(inBuf, inNumBytes);
1205 } else if (mPinInputType.subtype == MEDIASUBTYPE_AYUV) {
1206 encodeAYUVtoYV12(inBuf, inNumBytes);
1208 } else if (mPinInputType.subtype == MEDIASUBTYPE_RGB32) {
1209 encodeRGB32toYV12(inBuf, inNumBytes);
1211 } else if (mPinInputType.subtype == MEDIASUBTYPE_RGB24) {
1212 encodeRGB24toYV12(inBuf, inNumBytes);
1215 } else if (mPinInputType.subtype == MEDIASUBTYPE_YV12) {
1216 //Should be more specifc.
1217 //debugLog<<"About to encode YV12 to YV12"<<endl;
1218 encodeYV12ToYV12(inBuf, inNumBytes);
1219 } else if (mPinInputType.subtype == MEDIASUBTYPE_UYVY) {
1222 encodeUYVYToYV12(inBuf, inNumBytes);
1224 } else if (mPinInputType.subtype == MEDIASUBTYPE_YVYU) {
1227 encodeYVYUToYV12(inBuf, inNumBytes);
1228 } else if (mPinInputType.subtype == MEDIASUBTYPE_IYUV) {
1231 encodeIYUVToYV12(inBuf, inNumBytes);
1234 } else {
1236 //FATAL ERROR
1237 throw 0;
1241 StampedOggPacket* locPacket = mTheoraEncoder.encodeTheora(&mYUV);
1242 if (locPacket == NULL) {
1243 //debugLog<<"Encode returns NULL"<<endl;
1244 return S_FALSE;
1246 locFrameEnd = mUptoFrame
1247 = locPacket->endTime();
1248 //debugLog<<"Delivering..."<<endl;
1250 //We still own the packet after this, we have to delete it.
1251 locHR = deliverData(locFrameStart, locFrameEnd, locPacket->packetData(), locPacket->packetSize());
1252 delete locPacket;
1253 return locHR;
1256 bool TheoraEncodeInputPin::ConstructCodec() {
1258 //debugLog<<"Contructing codec..."<<endl;
1259 theora_info_init(&mTheoraInfo);
1261 //Round up to multiple of 16 for theora
1263 //---------------------------------------------------------------------------------------------------------------
1264 //mTheoraInfo values
1265 //==================
1266 //width, height - /16 up rounded values, size of the outer frame
1267 //frame_width, frame_height - size of the inner picture region
1268 //offset_x - Distance at bottom left from frame to picture <= width - frame_width
1269 //offset_y - Distance at bottom left from frame to picture <= height - frame_height
1271 //mYUV values - for YV12 format
1272 //=============================
1273 //y_stride - Equal to the /16 up rounded wdith values
1274 //y_width - Equal to the /16 up rounded wdith values
1275 //uv_stride - Equal to *half* the /16 up rounded width values
1276 //uv_width - Equal to *half* the /16 up rounded wdith values
1277 //y_height - Equal to the /16 up rounded height value
1278 //uv_height - Equal to *half* the /16 up rounded height value
1279 //y - Buffer of size y_stride*y_height (/16 up rounded values)
1280 //u,v - Buffers each *quarter* the size of the y buffer (/16 up rounded values)
1282 //Member data
1283 //===========
1284 //mWidth - raw video source values... equal to frame_width
1285 //mHeight - raw video source values... equal to frame_height
1286 //mXOffset - x offset
1287 //mYOffset - y offset
1288 //---------------------------------------------------------------------------------------------------------------
1290 //Width of the outer frame
1291 mTheoraInfo.width = mYUV.y_width
1292 = mYUV.y_stride
1293 = (((mVideoFormat->bmiHeader.biWidth + 15)>>4)<<4);
1295 //Width of the inner picture
1296 mTheoraInfo.frame_width = mWidth
1297 = mVideoFormat->bmiHeader.biWidth;
1299 //YUV U&V data
1300 mYUV.uv_width = mYUV.uv_stride
1301 = mYUV.y_width/2;
1306 //Height data of outer frame
1307 mTheoraInfo.height = mYUV.y_height
1308 = (((mVideoFormat->bmiHeader.biHeight + 15)>>4)<<4);
1310 //Height of the inner picture
1311 mTheoraInfo.frame_height = mHeight
1312 = mVideoFormat->bmiHeader.biHeight;
1314 mYUV.uv_height = mYUV.y_height/2;
1319 //Set offset values... no longer centred... all the offset is at the bottom left of the image (ie very start of memory image)
1320 //Difference between the outframe dimensions and the inner picture dimensions
1321 mTheoraInfo.offset_x = mXOffset
1322 = (mTheoraInfo.width - mTheoraInfo.frame_width);
1324 mTheoraInfo.offset_y = mYOffset
1325 = (mHeight - mTheoraInfo.frame_height);
1328 unsigned long locYBuffSize = mYUV.y_height * mYUV.y_stride;
1329 mYUV.y = new unsigned char[locYBuffSize];
1330 mYUV.u = new unsigned char[locYBuffSize/4];
1331 mYUV.v = new unsigned char[locYBuffSize/4];
1333 //End YV12 specifics
1336 //HACK:::Bit of a hack to convert dshow nanos to a fps num/denom.
1337 //Now we multiply the numerator and denom by 1000, this gives us 3 d.p. of precision for framerate.
1338 unsigned long locNum = (((double)10000000 * 1000) / ((double)mVideoFormat->AvgTimePerFrame)) + (double)0.5;
1340 //debugLog<<"FPS = "<<locNum<<endl;
1341 mTheoraInfo.fps_numerator = locNum;
1342 mTheoraInfo.fps_denominator = 1000;
1344 mTheoraInfo.aspect_numerator=0;
1345 mTheoraInfo.aspect_denominator=0;
1347 mTheoraInfo.colorspace=OC_CS_UNSPECIFIED; //YV12
1348 mTheoraInfo.target_bitrate=400000; //mVideoFormat->dwBitRate;
1350 //Hard code for now
1351 mTheoraInfo.quality=30; //video_q;
1353 mTheoraInfo.dropframes_p=0;
1354 mTheoraInfo.quick_p=0;
1355 mTheoraInfo.keyframe_auto_p=1;
1356 mTheoraInfo.keyframe_frequency=64; //If you change this... change the logged value below
1357 mTheoraInfo.keyframe_frequency_force=64; //ditto
1358 mTheoraInfo.keyframe_data_target_bitrate=mTheoraInfo.target_bitrate*1.5;
1359 mTheoraInfo.keyframe_auto_threshold=80;
1360 mTheoraInfo.keyframe_mindistance=8;
1361 mTheoraInfo.noise_sensitivity=1;
1362 mTheoraInfo.pixelformat = OC_PF_420;
1364 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateNumerator = mTheoraInfo.fps_numerator;
1365 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.frameRateDenominator = mTheoraInfo.fps_denominator;
1366 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.maxKeyframeInterval = 6; //log2(keyframe_freq) from above
1367 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.pictureHeight = mHeight;
1368 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.pictureWidth = mWidth;
1369 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.colourSpace = OC_CS_UNSPECIFIED;
1370 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.outerFrameHeight = mTheoraInfo.height;
1371 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.outerFrameWidth = mTheoraInfo.width;
1372 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.xOffset = (unsigned char)mXOffset;
1373 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.yOffset = (unsigned char)mYOffset;
1375 //TODO ::: DO something about aspect ratios
1376 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectDenominator = 0;
1377 ((TheoraEncodeFilter*)mParentFilter)->mTheoraFormatBlock.aspectNumerator = 0;
1379 return true;
1382 void TheoraEncodeInputPin::DestroyCodec() {
1383 //fish_sound_delete(mFishSound);
1384 //mFishSound = NULL;
1389 HRESULT TheoraEncodeInputPin::SetMediaType(const CMediaType* inMediaType)
1393 if ( inMediaType->subtype == MEDIASUBTYPE_YV12 ||
1394 inMediaType->subtype == MEDIASUBTYPE_IYUV ||
1395 inMediaType->subtype == MEDIASUBTYPE_YUY2 ||
1396 inMediaType->subtype == MEDIASUBTYPE_UYVY ||
1397 inMediaType->subtype == MEDIASUBTYPE_YVYU ||
1398 inMediaType->subtype == MEDIASUBTYPE_AYUV ||
1399 inMediaType->subtype == MEDIASUBTYPE_RGB32 ||
1400 inMediaType->subtype == MEDIASUBTYPE_RGB24
1402 mVideoFormat = (VIDEOINFOHEADER*)inMediaType->pbFormat;
1403 mPinInputType = *inMediaType;
1404 } else {
1405 //Failed... should never be here !
1406 throw 0;
1408 ConstructCodec();
1409 return CBaseInputPin::SetMediaType(inMediaType);
1414 theora_info* TheoraEncodeInputPin::theoraInfo() {
1415 return &mTheoraInfo;