1 //===========================================================================
2 //Copyright (C) 2003, 2004 Zentaro Kavanagh
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions
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 //===========================================================================
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
)
47 //debugLog.open("g:\\logs\\theoencfiltinput.log", ios_base::out);
54 TheoraEncodeInputPin::~TheoraEncodeInputPin(void)
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
);
72 //We get here when the application goes into stop mode usually.
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);
98 //debugLog<<"deliverData : SUCCESS"<<endl;
101 //debugLog<<"Buffer too small !!!! FATALITY !"<<endl;
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
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
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
;
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
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
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
229 //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
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);
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
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
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
289 //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
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);
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
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 //======================================================================================================
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
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
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
;
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
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
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
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);
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
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
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
504 //Add mHeight/2 lines of data of length mWidth/2 plus padded by mXOffset/2 at each end
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);
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
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 //======================================================================================================
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))
572 M = 8 bits per sample.
576 U = (112*(B-L) / ((1-Kb)*S) + 128)
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) )
587 Y = round( 219 * (L-Z)/S + 16 )
596 U_FACTOR = ( 1 - Kb) * S
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
627 //Scaled by factor of 65536 to integerise.
628 const int KR
= 19596;
631 const int ROUNDER
= 32768;
633 const int G_FACTOR
= 38470;
634 const int U_FACTOR
= 12716213;
635 const int V_FACTOR
= 10061022;
641 //unsigned char* locSourcePtr = inBuf;
642 unsigned char* locDestPtr
= locAYUVBuf
;
644 //SOURCE: Blue Green Red Blue Green Red.
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
701 //Still need to pass through to the AYUV conversion.
702 encodeAYUVtoYV12(locAYUVBuf
, locNumPixels
<<2);
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;
727 const int ROUNDER
= 32768;
729 const int G_FACTOR
= 38470;
730 const int U_FACTOR
= 12716213;
731 const int V_FACTOR
= 10061022;
737 //unsigned char* locSourcePtr = inBuf;
738 unsigned char* locDestPtr
= locAYUVBuf
;
740 //SOURCE: Blue Green Red Blue Green Red.
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;
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
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
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
);
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
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
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;
891 //====================
892 //V for Victor samples
893 //====================
894 temp
= *(locSourceUptoPtr
++); //Current pixel
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
908 temp
+= *(locSourceNextLine
+ 3); //Pixel below right
909 temp
>>= 2; //Divide by 4 to average.
910 *(locVUpto
++) = (unsigned char)temp
;
916 //====================
918 //====================
919 temp
= *(locSourceUptoPtr
++); //Current pixel
925 temp
+= *(locSourceUptoPtr
+ 3); //Pixel to right
926 temp
+= *(locSourceNextLine
++); //Pixel below
933 temp
+= *(locSourceNextLine
+ 3); //Pixel below right
934 temp
>>= 2; //Divide by 4 to average.
935 *(locUUpto
++) = (unsigned char)temp
;
941 //====================
942 //Y for Yellow samples.
943 //====================
945 *(locYUpto
++) = *(locSourceUptoPtr
++);
946 *(locDestNextLine
++) = *(locSourceNextLine
++);
952 //Ignore the alpha channel
954 //locSourceUptoPtr++; //Optimised away... merged into increment below
955 //locSourceNextLine++; // " " " " " " " " " " "
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
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.
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.
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)
993 //Overall this loop will advance :
994 //Sourceupto by = 8 bytes * (mWidth in pixels / 2 pixels at a time) * 2 lines
996 // = 2 lines of 4 byte pixels of pixel width mWidth
997 //and the same for sourcenextline
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.
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
);
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;
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
++);
1055 *(locYUpto
++) = *(locSourceUptoPtr
++);
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;
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.
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
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
;
1184 //debugLog<<"encodeData : First time"<<endl;
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
) {
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
);
1241 StampedOggPacket
* locPacket
= mTheoraEncoder
.encodeTheora(&mYUV
);
1242 if (locPacket
== NULL
) {
1243 //debugLog<<"Encode returns NULL"<<endl;
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());
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)
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
1293 = (((mVideoFormat
->bmiHeader
.biWidth
+ 15)>>4)<<4);
1295 //Width of the inner picture
1296 mTheoraInfo
.frame_width
= mWidth
1297 = mVideoFormat
->bmiHeader
.biWidth
;
1300 mYUV
.uv_width
= mYUV
.uv_stride
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;
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;
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
;
1405 //Failed... should never be here !
1409 return CBaseInputPin::SetMediaType(inMediaType
);
1414 theora_info
* TheoraEncodeInputPin::theoraInfo() {
1415 return &mTheoraInfo
;