[svn] / trunk / xvidextra / src / apps / miniconvert / filters.cpp Repository:
ViewVC logotype

Annotation of /trunk/xvidextra/src/apps/miniconvert/filters.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2045 - (view) (download)

1 : Irhall 2014 /*****************************************************************************
2 :     *
3 :     * Xvid MiniConvert
4 :     * - Helper filters -
5 :     *
6 :     * Copyright(C) 2011 Xvid Solutions GmbH
7 :     *
8 :     * This program is free software ; you can redistribute it and/or modify
9 :     * it under the terms of the GNU General Public License as published by
10 :     * the Free Software Foundation ; either version 2 of the License, or
11 :     * (at your option) any later version.
12 :     *
13 :     * This program is distributed in the hope that it will be useful,
14 :     * but WITHOUT ANY WARRANTY ; without even the implied warranty of
15 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 :     * GNU General Public License for more details.
17 :     *
18 :     * You should have received a copy of the GNU General Public License
19 :     * along with this program ; if not, write to the Free Software
20 :     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 :     *
22 :     * $Id$
23 :     *
24 :     ****************************************************************************/
25 :     /*
26 :     * Author(s): Ireneusz Hallmann
27 :     *
28 :     ****************************************************************************/
29 :    
30 :     #include "stdafx.h"
31 :     #include "filters.h"
32 :     #include "mmreg.h" // WAVE_FORMAT_MPEGLAYER3 format structure
33 :    
34 :     //////////////////////////////////////////////////////////////////////////////////////////////////
35 :    
36 :     CUnknown * WINAPI
37 :     CProgressNotifyFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr, int Type)
38 :     {
39 :     CUnknown *pNewFilter = new CProgressNotifyFilter(pUnk, phr, Type);
40 :    
41 :     if (phr) {
42 :     if (pNewFilter == NULL) *phr = E_OUTOFMEMORY;
43 :     else *phr = S_OK;
44 :     }
45 :    
46 :     return pNewFilter;
47 :     }
48 :    
49 :     CProgressNotifyFilter::CProgressNotifyFilter(LPUNKNOWN pUnk, HRESULT *phr, int Type) :
50 :     CTransInPlaceFilter("ProgressNotify", pUnk, CLSID_ProgressNotifyFilter, phr, false)
51 :     {
52 :     m_MessageWnd = 0;
53 :     m_SampleCnt = 0;
54 :     m_Pass = 1;
55 :     m_Type = Type;
56 :     m_startTime = 0;
57 :     m_stopTime = 0;
58 :     m_Width = 0, m_Height = 0;
59 :     m_AvgTimeForFrame = 0;
60 :    
61 :     if (*phr) *phr = S_OK;
62 :     }
63 :    
64 :    
65 :     CProgressNotifyFilter::~CProgressNotifyFilter(void)
66 :     {
67 :     }
68 :    
69 :     HRESULT
70 :     CProgressNotifyFilter::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
71 :     {
72 :     if (riid == IID_IRecProgressNotify)
73 :     return GetInterface((IRecProgressNotify*)this, ppv);
74 :    
75 :     return CBaseFilter::NonDelegatingQueryInterface (riid, ppv);
76 :     }
77 :    
78 :     HRESULT
79 :     CProgressNotifyFilter::CheckInputType(const CMediaType *mtIn)
80 :     {
81 :     if (mtIn->majortype != MEDIATYPE_Video &&
82 :     mtIn->majortype != MEDIATYPE_Audio) {
83 :    
84 :     return VFW_E_TYPE_NOT_ACCEPTED;
85 :     }
86 :    
87 :     if (mtIn->formattype != FORMAT_None) {
88 :    
89 :     if (mtIn->formattype == FORMAT_VideoInfo ||
90 :     mtIn->formattype == FORMAT_MPEGVideo) {
91 :    
92 :     m_AvgTimeForFrame = ((VIDEOINFOHEADER *)mtIn->pbFormat)->AvgTimePerFrame;
93 :     m_Width = ((VIDEOINFOHEADER *)mtIn->pbFormat)->bmiHeader.biWidth;
94 :     m_Height = ((VIDEOINFOHEADER *)mtIn->pbFormat)->bmiHeader.biHeight;
95 :    
96 :     }
97 :     else if (mtIn->formattype == FORMAT_VideoInfo2 ||
98 :     mtIn->formattype == FORMAT_MPEG2Video) {
99 :    
100 :     m_AvgTimeForFrame = ((VIDEOINFOHEADER2 *)mtIn->pbFormat)->AvgTimePerFrame;
101 :     m_Width = ((VIDEOINFOHEADER2 *)mtIn->pbFormat)->bmiHeader.biWidth;
102 :     m_Height = ((VIDEOINFOHEADER2 *)mtIn->pbFormat)->bmiHeader.biHeight;
103 :    
104 :     }
105 :     else if (mtIn->formattype == FORMAT_WaveFormatEx && m_Type == 2) {
106 :    
107 :     MPEGLAYER3WAVEFORMAT *pMp3 = (MPEGLAYER3WAVEFORMAT *)mtIn->pbFormat;
108 : Isibaar 2045 if (pMp3->wfx.nChannels >= 2 && pMp3->wfx.nAvgBytesPerSec != m_AudioBitrate)
109 : Irhall 2014 return VFW_E_TYPE_NOT_ACCEPTED;
110 :     }
111 :     else if (m_Type == 0) {
112 :     return VFW_E_TYPE_NOT_ACCEPTED;
113 :     }
114 :     }
115 :    
116 :     return S_OK;
117 :     }
118 :    
119 :     HRESULT
120 :     CProgressNotifyFilter::Transform(IMediaSample *pSample)
121 :     {
122 :     LONGLONG osTime, sTime, eTime;
123 :     pSample->GetTime(&osTime, &eTime);
124 :     sTime = osTime;
125 :     int bSetTime = 0;
126 : Isibaar 2045 DWORD SamplesSize = pSample->GetActualDataLength();
127 : Irhall 2014
128 :     if (m_Type == 0) { // Video
129 :    
130 :     #if 0 // emms instruction - for debug
131 :     #ifdef __FUNCTION__
132 :     // Visual Studio
133 :     __asm emms;
134 :     #else
135 :     __asm ("emms");
136 :     #endif
137 :     #endif
138 :    
139 :     m_TotalDataSize += pSample->GetActualDataLength();
140 :     m_SampleCnt++;
141 :    
142 :     int CurPos = (int) (m_TotalFrames ? (((double)(100 * m_SampleCnt/m_TotalFrames) + 0.5)) : 0);
143 :    
144 :     if (m_Pass == 0) {
145 :     CurPos /= 2;
146 :     }
147 :     else if (m_Pass == 2) {
148 :     CurPos = CurPos/2 + 50;
149 :     }
150 :    
151 :     if (m_totalSize > 0) {
152 :     CurPos = ((CurPos*m_curSize) / m_totalSize);
153 :     CurPos += ((100*m_elapsedSize) / m_totalSize);
154 :     }
155 :    
156 :     if (m_MessageWnd)
157 :     PostMessage(m_MessageWnd, PBM_SETPOS, CurPos, 0);
158 :     }
159 :     else { // Audio
160 :     MPEGLAYER3WAVEFORMAT *pMp3 = 0;
161 :    
162 :     if (m_MediaType.subtype == MEDIASUBTYPE_MP3) {
163 :     pMp3 = (MPEGLAYER3WAVEFORMAT *)m_MediaType.pbFormat;
164 :    
165 : Isibaar 2045 DWORD ThisSamples = (pMp3->wfx.nSamplesPerSec >= 32000 ? 1152 : 576) * pMp3->nFramesPerBlock;
166 : Irhall 2014
167 :     LONGLONG sDuration = eTime - sTime;
168 :     if (((m_SampleCnt || sTime) && sTime <= m_stopTime)) {
169 :     sTime = m_stopTime + 1;
170 :     bSetTime = 1;
171 :     }
172 :     if (eTime <= sTime || sDuration != (ThisSamples * 10000000LL * m_FpsDen)/m_FpsNom) {
173 :     sDuration = (ThisSamples * 10000000LL * m_FpsDen)/m_FpsNom - 1;
174 :     eTime = sTime + sDuration;
175 :     bSetTime = 1;
176 :     }
177 :     sTime = osTime; //!!
178 : Isibaar 2045 m_SampleCnt += ThisSamples;
179 : Irhall 2014
180 :     pSample->SetSyncPoint(TRUE);
181 :     }
182 :     }
183 :    
184 :     if (bSetTime)
185 :     pSample->SetTime(&sTime, &eTime);
186 :    
187 :     m_startTime = sTime;
188 :     m_stopTime = eTime;
189 :    
190 :     return S_OK;
191 :     }
192 :    
193 :     HRESULT
194 :     CProgressNotifyFilter::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
195 :     {
196 :     HRESULT hr = pReceivePin->ConnectionMediaType(&m_MediaType);
197 :     m_MinSampleSize = 0;
198 :    
199 :     if (hr == S_OK) {
200 :     if (m_MediaType.formattype == FORMAT_VideoInfo
201 :     || m_MediaType.formattype == FORMAT_MPEGVideo) {
202 :    
203 :     m_AvgTimeForFrame = ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->AvgTimePerFrame;
204 :    
205 :     if (direction == PINDIR_INPUT) {
206 :     if (m_MediaType.bTemporalCompression || m_MediaType.lSampleSize <=1) {
207 :     m_MinSampleSize = ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->bmiHeader.biHeight *
208 :     ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->bmiHeader.biWidth * 4;
209 :     }
210 :     }
211 :     }
212 :     else if (m_MediaType.formattype == FORMAT_VideoInfo2 ||
213 :     m_MediaType.formattype == FORMAT_MPEG2Video) {
214 :     m_AvgTimeForFrame = ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->AvgTimePerFrame;
215 :    
216 :     if (direction == PINDIR_INPUT) {
217 :     if (m_MediaType.bTemporalCompression || m_MediaType.lSampleSize <=1) {
218 :     m_MinSampleSize = ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->bmiHeader.biHeight *
219 :     ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->bmiHeader.biWidth * 4;
220 :     }
221 :     }
222 :     }
223 :     else if (m_Type == 0) {
224 :     hr = VFW_E_TYPE_NOT_ACCEPTED;
225 :     }
226 :    
227 :     if (m_AvgTimeForFrame) {
228 :    
229 :     switch (m_AvgTimeForFrame) {
230 :     case 416666: // 24.0 FPS
231 :     m_FpsNom = 24;
232 :     m_FpsDen = 1;
233 :     break;
234 :    
235 :     case 417083: // 23.97 FPS
236 :     m_FpsNom = 24000;
237 :     m_FpsDen = 1001;
238 :     break;
239 :    
240 :     case 333333: // 30.0 FPS
241 :     m_FpsNom = 30;
242 :     m_FpsDen = 1;
243 :     break;
244 :    
245 :     case 333666: // 29.97 FPS
246 :     m_FpsNom = 30000;
247 :     m_FpsDen = 1001;
248 :     break;
249 :    
250 :     default:
251 :     m_FpsNom = (int) (10000000 / m_AvgTimeForFrame);
252 :     m_FpsDen = 1;
253 :     }
254 :     }
255 :     else if (m_Type == 1 || m_Type == 2) {
256 :     WAVEFORMATEX *pWave = (WAVEFORMATEX *)m_MediaType.pbFormat;
257 :     m_FpsNom = pWave->nSamplesPerSec;
258 :     m_FpsDen = 1;
259 :     }
260 :     }
261 :    
262 :     return hr;
263 :     }
264 :    
265 :     HRESULT
266 :     CProgressNotifyFilter::DecideBufferSize(IMemAllocator *pAlloc,
267 :     ALLOCATOR_PROPERTIES *pProperties)
268 :     {
269 :     ALLOCATOR_PROPERTIES Request, Actual;
270 :     HRESULT hr;
271 :    
272 :     // If we are connected upstream, get his views
273 :     if (m_pInput->IsConnected()) {
274 :     // Get the input pin allocator, and get its size and count.
275 :     // we don't care about his alignment and prefix.
276 :    
277 :     hr = InputPin()->PeekAllocator()->GetProperties(&Request);
278 :    
279 :     if (FAILED(hr)) {
280 :     // Input connected but with a secretive allocator - enough!
281 :     return hr;
282 :     }
283 :    
284 :     if (m_MinSampleSize && (m_Type == 0)) {
285 :     if (Request.cbBuffer < m_MinSampleSize) {
286 :     Request.cbBuffer = m_MinSampleSize;
287 :     }
288 :     }
289 :     }
290 :     else {
291 :     // We're reduced to blind guessing. Let's guess one byte and if
292 :     // this isn't enough then when the other pin does get connected
293 :     // we can revise it.
294 :    
295 :     ZeroMemory(&Request, sizeof(Request));
296 :     Request.cBuffers = 1;
297 :     Request.cbBuffer = 1;
298 :     }
299 :    
300 :     #ifdef _DEBUG
301 :     DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements")));
302 :     DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"), Request.cBuffers, Request.cbBuffer));
303 :     #endif
304 :    
305 :     // Pass the allocator requirements to our output side
306 :     // but do a little sanity checking first or we'll just hit
307 :     // asserts in the allocator.
308 :    
309 :     pProperties->cBuffers = Request.cBuffers;
310 :     pProperties->cbBuffer = Request.cbBuffer;
311 :     pProperties->cbAlign = Request.cbAlign;
312 :    
313 :     if (pProperties->cBuffers<=0) {
314 :     pProperties->cBuffers = 1;
315 :     }
316 :    
317 :     if (pProperties->cbBuffer<=0) {
318 :     pProperties->cbBuffer = 1;
319 :     }
320 :    
321 :     hr = pAlloc->SetProperties(pProperties, &Actual);
322 :     if (FAILED(hr)) {
323 :     return hr;
324 :     }
325 :    
326 :     #ifdef _DEBUG
327 :     DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements")));
328 :     DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"),
329 :     Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign));
330 :     #endif
331 :    
332 :     // Make sure we got the right alignment and at least the minimum required
333 :     if ((Request.cBuffers > Actual.cBuffers) ||
334 :     (Request.cbBuffer > Actual.cbBuffer) ||
335 :     (Request.cbAlign > Actual.cbAlign))
336 :     {
337 :     return E_FAIL;
338 :     }
339 :    
340 :     return NOERROR;
341 :     }
342 :    
343 :     //////////////////////////////////////////////////////////////////////////////////////////
344 :    
345 :     HRESULT
346 :     CIRecProgressNotify::GetDimensions(DWORD &Width, DWORD &Height)
347 :     {
348 :     Width = m_Width;
349 :     Height = m_Height;
350 :    
351 :     return S_OK;
352 :     }
353 :    
354 :     HRESULT
355 :     CIRecProgressNotify::GetBitrate(DWORD &OutFramesCount,
356 :     LONGLONG &OutTotalDataSize)
357 :     {
358 :     OutFramesCount = m_SampleCnt;
359 :     OutTotalDataSize = m_TotalDataSize;
360 :    
361 :     return S_OK;
362 :     }
363 :    
364 :     HRESULT
365 :     CIRecProgressNotify::SetPass(int in_Pass)
366 :     {
367 :     m_Pass = in_Pass;
368 :     m_SampleCnt = 0;
369 :    
370 :     return S_OK;
371 :     }
372 :    
373 :     HRESULT
374 :     CIRecProgressNotify::SetTotalFrames(DWORD in_TotalFrames)
375 :     {
376 :     m_TotalFrames = in_TotalFrames;
377 :    
378 :     return S_OK;
379 :     }
380 :    
381 :     HRESULT
382 :     CIRecProgressNotify::SetNotifyWnd(HWND in_hWnd)
383 :     {
384 :     m_MessageWnd = in_hWnd;
385 :    
386 :     return S_OK;
387 :     }
388 :    
389 :     STDMETHODIMP
390 :     CIRecProgressNotify::SetTotalSize(int nbTotal)
391 :     {
392 :     m_totalSize = nbTotal;
393 :    
394 :     return S_OK;
395 :     }
396 :    
397 :     STDMETHODIMP
398 :     CIRecProgressNotify::SetCurSize(int nbCur)
399 :     {
400 :     m_curSize = nbCur;
401 :    
402 :     return S_OK;
403 :     }
404 :    
405 :     STDMETHODIMP
406 :     CIRecProgressNotify::SetElapsedSize(int nbElapsed)
407 :     {
408 :     m_elapsedSize = nbElapsed;
409 :    
410 :     return S_OK;
411 :     }
412 :    
413 : Isibaar 2045 STDMETHODIMP
414 :     CIRecProgressNotify::GetMeasuredTimes (LONGLONG &outStopTimeMin, LONGLONG &outStopTimeMax, LONGLONG &outStartTimeMin, LONGLONG &outStartTimeMax)
415 :     {
416 :     outStopTimeMin = m_StopTimeMin;
417 :     outStopTimeMax = m_StopTimeMax;
418 :     outStartTimeMin = m_StartTimeMin;
419 :     outStartTimeMax = m_StartTimeMax;
420 :     return S_OK;
421 :     }
422 :    
423 :     STDMETHODIMP
424 :     CIRecProgressNotify::SetForceTimeParams (LONGLONG inStartTimeOffset, LONGLONG inFpsNom, LONGLONG inFpsDen)
425 :     {
426 :     m_StartTimeMin = inStartTimeOffset;
427 :     m_FpsNom = inFpsNom;
428 :     m_FpsDen = inFpsDen;
429 :     m_bForceTimeStamps = 1;
430 :     return S_OK;
431 :     }
432 :    
433 :     STDMETHODIMP
434 :     CIRecProgressNotify::SetAudioBitrate (int Bitrate)
435 :     {
436 :     m_AudioBitrate = Bitrate;
437 :     return S_OK;
438 :     }
439 :    
440 : Irhall 2014 CIRecProgressNotify::CIRecProgressNotify()
441 :     {
442 :     m_Pass = -1;
443 :     m_MessageWnd = 0;
444 :     m_TotalFrames = 0;
445 :     m_SampleCnt = 0;
446 :     m_TotalDataSize = 0;
447 :     m_totalSize = 0;
448 :     m_curSize = 0;
449 :     m_elapsedSize = 0;
450 : Isibaar 2045 m_StopTimeMin = m_StopTimeMax = m_StartTimeMin = m_StartTimeMax = 0;
451 :     m_bForceTimeStamps = 0;
452 :     m_AudioBitrate = 1600;
453 : Irhall 2014 }
454 :    
455 :     //////////////////////////////////////////////////////////////////
456 :    
457 :     CUnknown * WINAPI
458 :     ChangeSubtypeT::CreateInstance(IUnknown *pUnk, HRESULT *phr)
459 :     {
460 :     CUnknown *pNewFilter = new ChangeSubtypeT(pUnk, phr );
461 :    
462 :     if (phr) {
463 :     if (pNewFilter == NULL) *phr = E_OUTOFMEMORY;
464 :     else *phr = S_OK;
465 :     }
466 :    
467 :     return pNewFilter;
468 :     }
469 :    
470 :     ChangeSubtypeT::ChangeSubtypeT(LPUNKNOWN pUnk, HRESULT *phr) :
471 :     CTransformFilter("ChangeSubtypeT", pUnk, CLSID_ChangeSubtypeT)
472 :     {
473 :     m_OutFcc = 'DIVX'; // == FCC('xvid')
474 :     m_SubtypeID = FOURCCMap('divx'); // FCC('XVID')
475 :     m_SampleCnt = 0;
476 :    
477 :     if (*phr) *phr = S_OK;
478 :    
479 :     m_pMpeg4Sequence = 0;
480 :     m_Mpeg4SequenceSize = 0;
481 :     }
482 :    
483 :     ChangeSubtypeT::~ChangeSubtypeT(void)
484 :     {
485 :     }
486 :    
487 :     HRESULT
488 :     ChangeSubtypeT::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
489 :     {
490 :     if (riid == IID_IRecProgressNotify)
491 :     return GetInterface((IRecProgressNotify*)this, ppv);
492 :    
493 :     return CBaseFilter::NonDelegatingQueryInterface (riid, ppv);
494 :     }
495 :    
496 :     HRESULT
497 :     ChangeSubtypeT::CheckInputType(const CMediaType *pmt)
498 :     {
499 :     if (!pmt)
500 :     return E_POINTER;
501 :    
502 :     if (pmt->majortype != MEDIATYPE_Video)
503 :     return S_FALSE;
504 :    
505 :     return S_OK;
506 :     }
507 :    
508 :     HRESULT
509 :     ChangeSubtypeT::CheckTransform (const CMediaType *pmtIn, const CMediaType *pmtOut)
510 :     {
511 :     if (!m_pInput->IsConnected())
512 :     return E_UNEXPECTED;
513 :    
514 :     if (pmtIn->majortype != MEDIATYPE_Video)
515 :     return VFW_E_TYPE_NOT_ACCEPTED;
516 :    
517 :     BITMAPINFOHEADER *pBmp = 0;
518 :    
519 :     if (pmtOut->majortype == MEDIATYPE_Video) {
520 :    
521 :     if (m_SubtypeID != pmtOut->subtype)
522 :     return VFW_E_TYPE_NOT_ACCEPTED;
523 :    
524 :     if (!pmtOut->pbFormat)
525 :     return S_OK;
526 :    
527 :     if (pmtOut->formattype == FORMAT_VideoInfo ||
528 :     pmtOut->formattype == FORMAT_MPEGVideo)
529 :     {
530 :     pBmp = &((VIDEOINFOHEADER *)pmtOut->pbFormat)->bmiHeader;
531 :     }
532 :     else if (pmtOut->formattype == FORMAT_VideoInfo2 ||
533 :     pmtOut->formattype == FORMAT_MPEG2Video)
534 :     {
535 :     pBmp = &((VIDEOINFOHEADER2 *)pmtOut->pbFormat)->bmiHeader;
536 :     }
537 :     else
538 :     return VFW_E_TYPE_NOT_ACCEPTED;
539 :    
540 :     if (m_OutFcc == pBmp->biCompression)
541 :     return S_OK;
542 :     }
543 :    
544 :     return VFW_E_TYPE_NOT_ACCEPTED;
545 :     }
546 :    
547 :     HRESULT
548 :     ChangeSubtypeT::DecideBufferSize(IMemAllocator * pAlloc,
549 :     ALLOCATOR_PROPERTIES * ppropInputRequest)
550 :     {
551 :     if (!m_pInput->IsConnected())
552 :     return E_UNEXPECTED;
553 :    
554 :     HRESULT hr = NOERROR;
555 :     BITMAPINFOHEADER *pBmp = 0;
556 :    
557 :     if (!m_OutMediaType.pbFormat)
558 :     return VFW_E_TYPE_NOT_ACCEPTED;
559 :    
560 :     if (m_OutMediaType.formattype == FORMAT_VideoInfo ||
561 :     m_OutMediaType.formattype == FORMAT_MPEGVideo)
562 :     {
563 :     pBmp = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader;
564 :     }
565 :     else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 ||
566 :     m_OutMediaType.formattype == FORMAT_MPEG2Video)
567 :     {
568 :     pBmp = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader;
569 :     }
570 :     else
571 :     return VFW_E_TYPE_NOT_ACCEPTED;
572 :    
573 :     ppropInputRequest->cBuffers = 1;
574 :     ppropInputRequest->cbBuffer = pBmp->biHeight*pBmp->biWidth * (pBmp->biBitCount+7)/8;
575 :    
576 :     ALLOCATOR_PROPERTIES Actual;
577 :     hr = pAlloc->SetProperties(ppropInputRequest,&Actual);
578 :     if (FAILED(hr))
579 :     return hr;
580 :    
581 :     if (ppropInputRequest->cBuffers > Actual.cBuffers ||
582 :     ppropInputRequest->cbBuffer > Actual.cbBuffer)
583 :     return E_FAIL;
584 :    
585 :     return S_OK;
586 :     }
587 :    
588 :     HRESULT
589 :     ChangeSubtypeT::GetMediaType(int iPosition, CMediaType *pMediaType)
590 :     {
591 :     if (!m_pInput->IsConnected()) {
592 :     return E_UNEXPECTED;
593 :     }
594 :     else if (iPosition < 0) {
595 :     return E_INVALIDARG;
596 :     }
597 :     else if (iPosition > 0) {
598 :     return VFW_S_NO_MORE_ITEMS;
599 :     }
600 :     else { //if (iPosition == 0)
601 :     *pMediaType = m_OutMediaType;
602 :     return S_OK;
603 :     }
604 :     }
605 :    
606 :     HRESULT
607 :     ChangeSubtypeT::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
608 :     {
609 :     CMediaType mt;
610 :     BITMAPINFOHEADER *pBmp = 0;
611 :     pReceivePin->ConnectionMediaType(&mt);
612 :    
613 :     if (mt.majortype == MEDIATYPE_Video) {
614 :     if (direction == PINDIR_INPUT) {
615 :    
616 :     // if (m_pOutput->IsConnected()) {
617 :     // m_pInput->BreakConnection();
618 :     // }
619 :    
620 :     m_InMediaType = mt;
621 :     m_OutMediaType = mt;
622 :     m_OutMediaType.subtype = m_SubtypeID;
623 :    
624 :     int NewSequenceSize = 0;
625 :    
626 :     if (m_InMediaType.formattype == FORMAT_VideoInfo ||
627 :     m_InMediaType.formattype == FORMAT_MPEGVideo)
628 :     {
629 :     pBmp = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader;
630 :     m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->AvgTimePerFrame;
631 :     }
632 :     else {
633 :     if (m_OutMediaType.formattype == FORMAT_VideoInfo2 ||
634 :     m_OutMediaType.formattype == FORMAT_MPEG2Video)
635 :     {
636 :     pBmp = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader;
637 :     m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->AvgTimePerFrame;
638 :     }
639 :     else
640 :     return VFW_E_TYPE_NOT_ACCEPTED;
641 :     }
642 :    
643 :     if (*m_InMediaType.FormatType() == FORMAT_MPEG2Video) {
644 :     MPEG2VIDEOINFO *mpeg2info=(MPEG2VIDEOINFO*)m_InMediaType.Format();
645 :    
646 :     if (mpeg2info->hdr.bmiHeader.biCompression!=0 && mpeg2info->cbSequenceHeader>0) {
647 :    
648 :     if (m_pMpeg4Sequence)
649 :     free(m_pMpeg4Sequence);
650 :    
651 :     m_Mpeg4SequenceSize = mpeg2info->cbSequenceHeader;
652 :    
653 :     if (m_Mpeg4SequenceSize > 0) {
654 :     m_pMpeg4Sequence = (BYTE *)malloc(m_Mpeg4SequenceSize*sizeof(BYTE));
655 :     memcpy(m_pMpeg4Sequence, (const BYTE *)mpeg2info->dwSequenceHeader, m_Mpeg4SequenceSize);
656 :     }
657 :     }
658 :     }
659 :    
660 :     VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)m_OutMediaType.ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
661 :     if (pVih==NULL) {
662 :     return E_OUTOFMEMORY;
663 :     }
664 :    
665 :     ZeroMemory(pVih, sizeof (VIDEOINFOHEADER));
666 :     CopyMemory(&pVih->bmiHeader, pBmp, sizeof(BITMAPINFOHEADER));
667 :    
668 :     /* set output format */
669 :     m_OutMediaType.SetType(&MEDIATYPE_Video);
670 :     m_OutMediaType.SetFormatType(&FORMAT_VideoInfo);
671 :    
672 :     m_OutMediaType.SetSubtype(&m_SubtypeID);
673 :     pVih->bmiHeader.biCompression = m_OutFcc;
674 :    
675 :     pVih->AvgTimePerFrame = m_AvgTimeForFrame;
676 :     pVih->dwBitErrorRate = 0;
677 :     pVih->dwBitRate = 8 * (DWORD)(((float)pVih->bmiHeader.biSizeImage * 10000000) / m_AvgTimeForFrame);
678 :    
679 :     m_OutMediaType.SetTemporalCompression(TRUE);
680 :     m_OutMediaType.SetVariableSize();
681 :    
682 :     if (m_AvgTimeForFrame) {
683 :     switch (m_AvgTimeForFrame) {
684 :    
685 :     case 416666: // 24.0 FPS
686 :     m_FpsNom = 24;
687 :     m_FpsDen = 1;
688 :     break;
689 :    
690 :     case 417083: // 23.97 FPS
691 :     m_FpsNom = 24000;
692 :     m_FpsDen = 1001;
693 :     break;
694 :    
695 :     case 333333: // 30.0 FPS
696 :     m_FpsNom = 30;
697 :     m_FpsDen = 1;
698 :     break;
699 :    
700 :     case 333666: // 29.97 FPS
701 :     m_FpsNom = 30000;
702 :     m_FpsDen = 1001;
703 :     break;
704 :    
705 :     default:
706 :     m_FpsNom = (int) (10000000 / m_AvgTimeForFrame);
707 :     m_FpsDen = 1;
708 :     }
709 :     }
710 :    
711 :     m_SampleCnt = 0;
712 : Isibaar 2045 m_UnitDuration = (10000000LL * m_FpsDen)/m_FpsNom;
713 :     m_UnitTimeDelta = m_UnitDuration / 5;
714 :     if (m_UnitTimeDelta < 1000) m_UnitTimeDelta = m_UnitDuration > 2000 ? 1000 : m_UnitDuration/2;
715 :     m_stopTime = m_startTime = 0;
716 :    
717 :    
718 :     m_MaxStartTime = m_MaxStopTime = 0;
719 :    
720 : Irhall 2014 return S_OK;
721 :     }
722 :     else { // if (direction == PINDIR_OUTPUT) {
723 :     if (!m_pInput->IsConnected())
724 :     return E_UNEXPECTED;
725 :    
726 :     if (m_SubtypeID != mt.subtype)
727 :     return VFW_E_TYPE_NOT_ACCEPTED;
728 :    
729 :     if (!mt.pbFormat)
730 :     return VFW_E_TYPE_NOT_ACCEPTED;
731 :    
732 :     if (mt.formattype == FORMAT_VideoInfo ||
733 :     mt.formattype == FORMAT_MPEGVideo)
734 :     {
735 :     pBmp = &((VIDEOINFOHEADER *)mt.pbFormat)->bmiHeader;
736 :     }
737 :     else if (mt.formattype == FORMAT_VideoInfo2 ||
738 :     mt.formattype == FORMAT_MPEG2Video)
739 :     {
740 :     pBmp = &((VIDEOINFOHEADER2 *)mt.pbFormat)->bmiHeader;
741 :     }
742 :     else
743 :     return VFW_E_TYPE_NOT_ACCEPTED;
744 :    
745 : Isibaar 2045 if (m_bForceTimeStamps) {
746 :     if (m_OutMediaType.formattype == FORMAT_VideoInfo ||
747 :     m_OutMediaType.formattype == FORMAT_MPEGVideo) {
748 :     ((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->AvgTimePerFrame =
749 :     m_AvgTimeForFrame = (DWORD) (m_FpsNom/m_FpsDen);
750 :     } else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 ||
751 :     m_OutMediaType.formattype == FORMAT_MPEG2Video) {
752 :     ((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->AvgTimePerFrame =
753 :     m_AvgTimeForFrame = (DWORD) (m_FpsNom/m_FpsDen);
754 :     }
755 :     }
756 :    
757 : Irhall 2014 if (m_OutFcc == pBmp->biCompression)
758 :     return S_OK;
759 :     }
760 :     }
761 :    
762 :     return VFW_E_TYPE_NOT_ACCEPTED;
763 :     }
764 :    
765 :     HRESULT
766 :     ChangeSubtypeT::Transform(IMediaSample *pIn, IMediaSample *pOut)
767 :     {
768 :     BITMAPINFOHEADER *pBmpIn=0, *pBmpOut=0;
769 :     HRESULT hr = S_FALSE;
770 :    
771 :     if (m_InMediaType.formattype == FORMAT_VideoInfo ||
772 :     m_InMediaType.formattype == FORMAT_MPEGVideo)
773 :     {
774 :     pBmpIn = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader;
775 :     }
776 :     else if (m_InMediaType.formattype == FORMAT_VideoInfo2 ||
777 :     m_InMediaType.formattype == FORMAT_MPEG2Video)
778 :     {
779 :     pBmpIn = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader;
780 :     }
781 :    
782 :     if (m_OutMediaType.formattype == FORMAT_VideoInfo ||
783 :     m_OutMediaType.formattype == FORMAT_MPEGVideo)
784 :     {
785 :     pBmpOut = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader;
786 :     }
787 :     else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 ||
788 :     m_OutMediaType.formattype == FORMAT_MPEG2Video)
789 :     {
790 :     pBmpOut = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader;
791 :     }
792 :    
793 :     if (pBmpIn && pBmpOut && m_InMediaType.lSampleSize == m_OutMediaType.lSampleSize)
794 :     {
795 :     BYTE *pBufIn, *pBufOut;
796 :     pIn->GetPointer(&pBufIn);
797 :     pOut->GetPointer(&pBufOut);
798 :     DWORD lSize = pIn->GetActualDataLength();
799 :    
800 :     DWORD OutOffset = 0;
801 :     if (*((int *)pBufIn) != 0xB0010000 && m_pMpeg4Sequence) {
802 : Isibaar 2045 int FrameType = -1;
803 :     for (int iOffset=0; iOffset < (int) (lSize - 5) && FrameType == -1; iOffset++) {
804 :     if (*((int *)(&(pBufIn[iOffset]))) == 0xB6010000) {
805 :     FrameType = (pBufIn[iOffset + 4] >> 6)& 3;
806 :     }
807 :     }
808 :     pOut->SetSyncPoint(FrameType == 0 ? TRUE : FALSE);
809 :     //if (pIn->IsSyncPoint() == S_OK) { // I-VOP // IsSyncPoint() is not reliable !!
810 :     if (FrameType == 0) {
811 : Irhall 2014 memcpy(pBufOut, m_pMpeg4Sequence, m_Mpeg4SequenceSize);
812 :     OutOffset = m_Mpeg4SequenceSize;
813 :     }
814 :     }
815 :    
816 :     pOut->SetActualDataLength(lSize + OutOffset);
817 :     memcpy(&pBufOut[OutOffset], pBufIn, lSize);
818 : Isibaar 2045 LONGLONG ExpectedStart = m_stopTime;
819 :     LONGLONG ExpectedStop = m_stopTime + m_UnitDuration;
820 : Irhall 2014
821 :     LONGLONG sTime, eTime;
822 :     pOut->GetTime(&sTime, &eTime);
823 :     int bSetTime = 0;
824 :     LONGLONG sDuration = eTime - sTime;
825 :    
826 : Isibaar 2045 if (m_Pass == 1) {
827 :     if (m_SampleCnt == 0) {
828 :     m_StopTimeMin = m_StopTimeMax = eTime;
829 :     m_StartTimeMin = m_StartTimeMax = sTime;
830 :     } else {
831 :     if (m_StopTimeMin > eTime) m_StopTimeMin = eTime;
832 :     if (m_StopTimeMax < eTime) m_StopTimeMax = eTime;
833 :     if (m_StartTimeMin > sTime) m_StartTimeMin = sTime;
834 :     if (m_StartTimeMax < sTime) m_StartTimeMax = sTime;
835 :     }
836 :     } else if (m_SampleCnt == 0 && m_bForceTimeStamps) {
837 :     m_UnitDuration = m_FpsNom/m_FpsDen;
838 :     m_UnitTimeDelta = m_UnitDuration / 5;
839 :     if (m_UnitTimeDelta < 1000) m_UnitTimeDelta = m_UnitDuration > 2000 ? 1000 : m_UnitDuration/2;
840 :     }
841 :    
842 :     int bForceStopTime = 0;
843 :     if (abs((long)((LONGLONG)(ExpectedStop - m_MaxStopTime))) < m_UnitTimeDelta) {
844 :     // re-use of time that had one of previous samples
845 :     // in case when times of samples are reordered
846 :     // to keep exactly in sync with speed of playing of original speed
847 :     // in long distance. Any way of calculation based on
848 :     // number of samples may fail if stream is long enough
849 :     // and frame duration is calculated not with
850 :     // absolute precision (NTSC - family framerates: 23.98, 29.97, etc...)
851 :    
852 :     ExpectedStop = m_MaxStopTime;
853 :     bForceStopTime = 1;
854 :     if (ExpectedStart + m_UnitDuration > ExpectedStop + m_UnitTimeDelta) {
855 :     ExpectedStart = m_MaxStartTime;
856 :     if (ExpectedStart + m_UnitDuration > ExpectedStop)
857 :     ExpectedStart = ExpectedStop - m_UnitDuration;
858 :     }
859 :     }
860 :    
861 :     //LONGLONG eTimeN = eTime * m_FpsNom, Den0 = 10000000LL * m_FpsDen;
862 :     //int SampleEMin = ((eTimeN < 100000) ? 0 : eTimeN - 10000)/Den0, SampleEMax = (eTimeN + 10000)/Den0;
863 :     //int TimeEDiff = eTime - m_stopTime;
864 :     LONGLONG MaxStartTime = max(m_MaxStartTime, sTime),
865 :     MaxStopTime = max(m_MaxStopTime, eTime);
866 :    
867 : Irhall 2014 // simply set correct end time - seems to work here...
868 : Isibaar 2045
869 :     //if (m_Pass ==2 && m_bForceTimeStamps) {
870 :     // sTime = m_SampleCnt * m_FpsNom / m_FpsDen;
871 :     // eTime = (m_SampleCnt +1) * m_FpsNom / m_FpsDen;
872 :     // bSetTime = 1;
873 :     //}
874 :    
875 :     if (eTime + m_UnitTimeDelta < sTime + m_UnitDuration) {
876 :     eTime = sTime + m_UnitDuration;
877 : Irhall 2014 bSetTime = 1;
878 : Isibaar 2045 }
879 : Irhall 2014
880 : Isibaar 2045 if ((bForceStopTime) || (eTime + m_UnitDuration < ExpectedStop)) {
881 :     //if ((bForceStopTime) || (eTime > ExpectedStop + m_UnitTimeDelta) || (eTime + m_UnitTimeDelta < ExpectedStop)) {
882 :     eTime = ExpectedStop;
883 :     sTime = ExpectedStart;
884 :     bSetTime = 1;
885 :     }
886 :     m_MaxStartTime = max(MaxStartTime, sTime);
887 :     m_MaxStopTime = max(MaxStopTime, eTime);
888 :    
889 : Irhall 2014 if (bSetTime) pOut->SetTime(&sTime, &eTime);
890 :    
891 :     m_startTime = sTime;
892 :     m_stopTime = eTime;
893 :     m_SampleCnt ++;
894 :    
895 :     int CurPos = (int) ((double)(100.0 * m_SampleCnt/m_TotalFrames) + 0.5);
896 :     if (m_Pass == 0)
897 :     CurPos /= 2;
898 :     else if (m_Pass == 2)
899 :     CurPos = CurPos /2 + 50;
900 :    
901 :     if (m_MessageWnd)
902 :     PostMessage(m_MessageWnd, PBM_SETPOS, CurPos, 0);
903 :    
904 :     hr = S_OK;
905 :     }
906 :    
907 :     return hr;
908 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4