Parent Directory | Revision Log
Revision 2014 - (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 : | if (pMp3->wfx.nAvgBytesPerSec != 16000) | ||
109 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
110 : | |||
111 : | // WAVEFORMATEX *pWaveFormat = (WAVEFORMATEX *)mtIn->pbFormat; | ||
112 : | // if (pWaveFormat->nChannels > 2) | ||
113 : | // return VFW_E_TYPE_NOT_ACCEPTED; | ||
114 : | |||
115 : | } | ||
116 : | else if (m_Type == 0) { | ||
117 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
118 : | } | ||
119 : | } | ||
120 : | |||
121 : | return S_OK; | ||
122 : | } | ||
123 : | |||
124 : | HRESULT | ||
125 : | CProgressNotifyFilter::Transform(IMediaSample *pSample) | ||
126 : | { | ||
127 : | LONGLONG osTime, sTime, eTime; | ||
128 : | pSample->GetTime(&osTime, &eTime); | ||
129 : | sTime = osTime; | ||
130 : | int bSetTime = 0; | ||
131 : | |||
132 : | if (m_Type == 0) { // Video | ||
133 : | |||
134 : | #if 0 // emms instruction - for debug | ||
135 : | #ifdef __FUNCTION__ | ||
136 : | // Visual Studio | ||
137 : | __asm emms; | ||
138 : | #else | ||
139 : | __asm ("emms"); | ||
140 : | #endif | ||
141 : | #endif | ||
142 : | |||
143 : | m_TotalDataSize += pSample->GetActualDataLength(); | ||
144 : | m_SampleCnt++; | ||
145 : | |||
146 : | int CurPos = (int) (m_TotalFrames ? (((double)(100 * m_SampleCnt/m_TotalFrames) + 0.5)) : 0); | ||
147 : | |||
148 : | if (m_Pass == 0) { | ||
149 : | CurPos /= 2; | ||
150 : | } | ||
151 : | else if (m_Pass == 2) { | ||
152 : | CurPos = CurPos/2 + 50; | ||
153 : | } | ||
154 : | |||
155 : | if (m_totalSize > 0) { | ||
156 : | CurPos = ((CurPos*m_curSize) / m_totalSize); | ||
157 : | CurPos += ((100*m_elapsedSize) / m_totalSize); | ||
158 : | } | ||
159 : | |||
160 : | if (m_MessageWnd) | ||
161 : | PostMessage(m_MessageWnd, PBM_SETPOS, CurPos, 0); | ||
162 : | } | ||
163 : | else { // Audio | ||
164 : | MPEGLAYER3WAVEFORMAT *pMp3 = 0; | ||
165 : | |||
166 : | if (m_MediaType.subtype == MEDIASUBTYPE_MP3) { | ||
167 : | pMp3 = (MPEGLAYER3WAVEFORMAT *)m_MediaType.pbFormat; | ||
168 : | |||
169 : | DWORD ThisSamples = (pMp3->wfx.nSamplesPerSec >= 32000 ? 576 : 1152) * pMp3->nFramesPerBlock; | ||
170 : | m_SampleCnt += ThisSamples; | ||
171 : | |||
172 : | LONGLONG sDuration = eTime - sTime; | ||
173 : | if (((m_SampleCnt || sTime) && sTime <= m_stopTime)) { | ||
174 : | sTime = m_stopTime + 1; | ||
175 : | bSetTime = 1; | ||
176 : | } | ||
177 : | if (eTime <= sTime || sDuration != (ThisSamples * 10000000LL * m_FpsDen)/m_FpsNom) { | ||
178 : | sDuration = (ThisSamples * 10000000LL * m_FpsDen)/m_FpsNom - 1; | ||
179 : | eTime = sTime + sDuration; | ||
180 : | bSetTime = 1; | ||
181 : | } | ||
182 : | sTime = osTime; //!! | ||
183 : | |||
184 : | pSample->SetSyncPoint(TRUE); | ||
185 : | } | ||
186 : | } | ||
187 : | |||
188 : | if (bSetTime) | ||
189 : | pSample->SetTime(&sTime, &eTime); | ||
190 : | |||
191 : | m_startTime = sTime; | ||
192 : | m_stopTime = eTime; | ||
193 : | |||
194 : | return S_OK; | ||
195 : | } | ||
196 : | |||
197 : | HRESULT | ||
198 : | CProgressNotifyFilter::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin) | ||
199 : | { | ||
200 : | HRESULT hr = pReceivePin->ConnectionMediaType(&m_MediaType); | ||
201 : | m_MinSampleSize = 0; | ||
202 : | |||
203 : | if (hr == S_OK) { | ||
204 : | if (m_MediaType.formattype == FORMAT_VideoInfo | ||
205 : | || m_MediaType.formattype == FORMAT_MPEGVideo) { | ||
206 : | |||
207 : | m_AvgTimeForFrame = ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->AvgTimePerFrame; | ||
208 : | |||
209 : | if (direction == PINDIR_INPUT) { | ||
210 : | if (m_MediaType.bTemporalCompression || m_MediaType.lSampleSize <=1) { | ||
211 : | m_MinSampleSize = ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->bmiHeader.biHeight * | ||
212 : | ((VIDEOINFOHEADER *)m_MediaType.pbFormat)->bmiHeader.biWidth * 4; | ||
213 : | } | ||
214 : | } | ||
215 : | } | ||
216 : | else if (m_MediaType.formattype == FORMAT_VideoInfo2 || | ||
217 : | m_MediaType.formattype == FORMAT_MPEG2Video) { | ||
218 : | m_AvgTimeForFrame = ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->AvgTimePerFrame; | ||
219 : | |||
220 : | if (direction == PINDIR_INPUT) { | ||
221 : | if (m_MediaType.bTemporalCompression || m_MediaType.lSampleSize <=1) { | ||
222 : | m_MinSampleSize = ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->bmiHeader.biHeight * | ||
223 : | ((VIDEOINFOHEADER2 *)m_MediaType.pbFormat)->bmiHeader.biWidth * 4; | ||
224 : | } | ||
225 : | } | ||
226 : | } | ||
227 : | else if (m_Type == 0) { | ||
228 : | hr = VFW_E_TYPE_NOT_ACCEPTED; | ||
229 : | } | ||
230 : | |||
231 : | if (m_AvgTimeForFrame) { | ||
232 : | |||
233 : | switch (m_AvgTimeForFrame) { | ||
234 : | case 416666: // 24.0 FPS | ||
235 : | m_FpsNom = 24; | ||
236 : | m_FpsDen = 1; | ||
237 : | break; | ||
238 : | |||
239 : | case 417083: // 23.97 FPS | ||
240 : | m_FpsNom = 24000; | ||
241 : | m_FpsDen = 1001; | ||
242 : | break; | ||
243 : | |||
244 : | case 333333: // 30.0 FPS | ||
245 : | m_FpsNom = 30; | ||
246 : | m_FpsDen = 1; | ||
247 : | break; | ||
248 : | |||
249 : | case 333666: // 29.97 FPS | ||
250 : | m_FpsNom = 30000; | ||
251 : | m_FpsDen = 1001; | ||
252 : | break; | ||
253 : | |||
254 : | default: | ||
255 : | m_FpsNom = (int) (10000000 / m_AvgTimeForFrame); | ||
256 : | m_FpsDen = 1; | ||
257 : | } | ||
258 : | } | ||
259 : | else if (m_Type == 1 || m_Type == 2) { | ||
260 : | WAVEFORMATEX *pWave = (WAVEFORMATEX *)m_MediaType.pbFormat; | ||
261 : | m_FpsNom = pWave->nSamplesPerSec; | ||
262 : | m_FpsDen = 1; | ||
263 : | } | ||
264 : | } | ||
265 : | |||
266 : | return hr; | ||
267 : | } | ||
268 : | |||
269 : | HRESULT | ||
270 : | CProgressNotifyFilter::DecideBufferSize(IMemAllocator *pAlloc, | ||
271 : | ALLOCATOR_PROPERTIES *pProperties) | ||
272 : | { | ||
273 : | ALLOCATOR_PROPERTIES Request, Actual; | ||
274 : | HRESULT hr; | ||
275 : | |||
276 : | // If we are connected upstream, get his views | ||
277 : | if (m_pInput->IsConnected()) { | ||
278 : | // Get the input pin allocator, and get its size and count. | ||
279 : | // we don't care about his alignment and prefix. | ||
280 : | |||
281 : | hr = InputPin()->PeekAllocator()->GetProperties(&Request); | ||
282 : | |||
283 : | if (FAILED(hr)) { | ||
284 : | // Input connected but with a secretive allocator - enough! | ||
285 : | return hr; | ||
286 : | } | ||
287 : | |||
288 : | if (m_MinSampleSize && (m_Type == 0)) { | ||
289 : | if (Request.cbBuffer < m_MinSampleSize) { | ||
290 : | Request.cbBuffer = m_MinSampleSize; | ||
291 : | } | ||
292 : | } | ||
293 : | } | ||
294 : | else { | ||
295 : | // We're reduced to blind guessing. Let's guess one byte and if | ||
296 : | // this isn't enough then when the other pin does get connected | ||
297 : | // we can revise it. | ||
298 : | |||
299 : | ZeroMemory(&Request, sizeof(Request)); | ||
300 : | Request.cBuffers = 1; | ||
301 : | Request.cbBuffer = 1; | ||
302 : | } | ||
303 : | |||
304 : | #ifdef _DEBUG | ||
305 : | DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements"))); | ||
306 : | DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"), Request.cBuffers, Request.cbBuffer)); | ||
307 : | #endif | ||
308 : | |||
309 : | // Pass the allocator requirements to our output side | ||
310 : | // but do a little sanity checking first or we'll just hit | ||
311 : | // asserts in the allocator. | ||
312 : | |||
313 : | pProperties->cBuffers = Request.cBuffers; | ||
314 : | pProperties->cbBuffer = Request.cbBuffer; | ||
315 : | pProperties->cbAlign = Request.cbAlign; | ||
316 : | |||
317 : | if (pProperties->cBuffers<=0) { | ||
318 : | pProperties->cBuffers = 1; | ||
319 : | } | ||
320 : | |||
321 : | if (pProperties->cbBuffer<=0) { | ||
322 : | pProperties->cbBuffer = 1; | ||
323 : | } | ||
324 : | |||
325 : | hr = pAlloc->SetProperties(pProperties, &Actual); | ||
326 : | if (FAILED(hr)) { | ||
327 : | return hr; | ||
328 : | } | ||
329 : | |||
330 : | #ifdef _DEBUG | ||
331 : | DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements"))); | ||
332 : | DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"), | ||
333 : | Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign)); | ||
334 : | #endif | ||
335 : | |||
336 : | // Make sure we got the right alignment and at least the minimum required | ||
337 : | if ((Request.cBuffers > Actual.cBuffers) || | ||
338 : | (Request.cbBuffer > Actual.cbBuffer) || | ||
339 : | (Request.cbAlign > Actual.cbAlign)) | ||
340 : | { | ||
341 : | return E_FAIL; | ||
342 : | } | ||
343 : | |||
344 : | return NOERROR; | ||
345 : | } | ||
346 : | |||
347 : | ////////////////////////////////////////////////////////////////////////////////////////// | ||
348 : | |||
349 : | HRESULT | ||
350 : | CIRecProgressNotify::GetDimensions(DWORD &Width, DWORD &Height) | ||
351 : | { | ||
352 : | Width = m_Width; | ||
353 : | Height = m_Height; | ||
354 : | |||
355 : | return S_OK; | ||
356 : | } | ||
357 : | |||
358 : | HRESULT | ||
359 : | CIRecProgressNotify::GetBitrate(DWORD &OutFramesCount, | ||
360 : | LONGLONG &OutTotalDataSize) | ||
361 : | { | ||
362 : | OutFramesCount = m_SampleCnt; | ||
363 : | OutTotalDataSize = m_TotalDataSize; | ||
364 : | |||
365 : | return S_OK; | ||
366 : | } | ||
367 : | |||
368 : | HRESULT | ||
369 : | CIRecProgressNotify::SetPass(int in_Pass) | ||
370 : | { | ||
371 : | m_Pass = in_Pass; | ||
372 : | m_SampleCnt = 0; | ||
373 : | |||
374 : | return S_OK; | ||
375 : | } | ||
376 : | |||
377 : | HRESULT | ||
378 : | CIRecProgressNotify::SetTotalFrames(DWORD in_TotalFrames) | ||
379 : | { | ||
380 : | m_TotalFrames = in_TotalFrames; | ||
381 : | |||
382 : | return S_OK; | ||
383 : | } | ||
384 : | |||
385 : | HRESULT | ||
386 : | CIRecProgressNotify::SetNotifyWnd(HWND in_hWnd) | ||
387 : | { | ||
388 : | m_MessageWnd = in_hWnd; | ||
389 : | |||
390 : | return S_OK; | ||
391 : | } | ||
392 : | |||
393 : | STDMETHODIMP | ||
394 : | CIRecProgressNotify::SetTotalSize(int nbTotal) | ||
395 : | { | ||
396 : | m_totalSize = nbTotal; | ||
397 : | |||
398 : | return S_OK; | ||
399 : | } | ||
400 : | |||
401 : | STDMETHODIMP | ||
402 : | CIRecProgressNotify::SetCurSize(int nbCur) | ||
403 : | { | ||
404 : | m_curSize = nbCur; | ||
405 : | |||
406 : | return S_OK; | ||
407 : | } | ||
408 : | |||
409 : | STDMETHODIMP | ||
410 : | CIRecProgressNotify::SetElapsedSize(int nbElapsed) | ||
411 : | { | ||
412 : | m_elapsedSize = nbElapsed; | ||
413 : | |||
414 : | return S_OK; | ||
415 : | } | ||
416 : | |||
417 : | CIRecProgressNotify::CIRecProgressNotify() | ||
418 : | { | ||
419 : | m_Pass = -1; | ||
420 : | m_MessageWnd = 0; | ||
421 : | m_TotalFrames = 0; | ||
422 : | m_SampleCnt = 0; | ||
423 : | m_TotalDataSize = 0; | ||
424 : | m_totalSize = 0; | ||
425 : | m_curSize = 0; | ||
426 : | m_elapsedSize = 0; | ||
427 : | } | ||
428 : | |||
429 : | ////////////////////////////////////////////////////////////////// | ||
430 : | |||
431 : | CUnknown * WINAPI | ||
432 : | ChangeSubtypeT::CreateInstance(IUnknown *pUnk, HRESULT *phr) | ||
433 : | { | ||
434 : | CUnknown *pNewFilter = new ChangeSubtypeT(pUnk, phr ); | ||
435 : | |||
436 : | if (phr) { | ||
437 : | if (pNewFilter == NULL) *phr = E_OUTOFMEMORY; | ||
438 : | else *phr = S_OK; | ||
439 : | } | ||
440 : | |||
441 : | return pNewFilter; | ||
442 : | } | ||
443 : | |||
444 : | ChangeSubtypeT::ChangeSubtypeT(LPUNKNOWN pUnk, HRESULT *phr) : | ||
445 : | CTransformFilter("ChangeSubtypeT", pUnk, CLSID_ChangeSubtypeT) | ||
446 : | { | ||
447 : | m_OutFcc = 'DIVX'; // == FCC('xvid') | ||
448 : | m_SubtypeID = FOURCCMap('divx'); // FCC('XVID') | ||
449 : | m_SampleCnt = 0; | ||
450 : | |||
451 : | if (*phr) *phr = S_OK; | ||
452 : | |||
453 : | m_pMpeg4Sequence = 0; | ||
454 : | m_Mpeg4SequenceSize = 0; | ||
455 : | } | ||
456 : | |||
457 : | ChangeSubtypeT::~ChangeSubtypeT(void) | ||
458 : | { | ||
459 : | } | ||
460 : | |||
461 : | HRESULT | ||
462 : | ChangeSubtypeT::NonDelegatingQueryInterface(REFIID riid, void ** ppv) | ||
463 : | { | ||
464 : | if (riid == IID_IRecProgressNotify) | ||
465 : | return GetInterface((IRecProgressNotify*)this, ppv); | ||
466 : | |||
467 : | return CBaseFilter::NonDelegatingQueryInterface (riid, ppv); | ||
468 : | } | ||
469 : | |||
470 : | HRESULT | ||
471 : | ChangeSubtypeT::CheckInputType(const CMediaType *pmt) | ||
472 : | { | ||
473 : | if (!pmt) | ||
474 : | return E_POINTER; | ||
475 : | |||
476 : | if (pmt->majortype != MEDIATYPE_Video) | ||
477 : | return S_FALSE; | ||
478 : | |||
479 : | return S_OK; | ||
480 : | } | ||
481 : | |||
482 : | HRESULT | ||
483 : | ChangeSubtypeT::CheckTransform (const CMediaType *pmtIn, const CMediaType *pmtOut) | ||
484 : | { | ||
485 : | if (!m_pInput->IsConnected()) | ||
486 : | return E_UNEXPECTED; | ||
487 : | |||
488 : | if (pmtIn->majortype != MEDIATYPE_Video) | ||
489 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
490 : | |||
491 : | BITMAPINFOHEADER *pBmp = 0; | ||
492 : | |||
493 : | if (pmtOut->majortype == MEDIATYPE_Video) { | ||
494 : | |||
495 : | if (m_SubtypeID != pmtOut->subtype) | ||
496 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
497 : | |||
498 : | if (!pmtOut->pbFormat) | ||
499 : | return S_OK; | ||
500 : | |||
501 : | if (pmtOut->formattype == FORMAT_VideoInfo || | ||
502 : | pmtOut->formattype == FORMAT_MPEGVideo) | ||
503 : | { | ||
504 : | pBmp = &((VIDEOINFOHEADER *)pmtOut->pbFormat)->bmiHeader; | ||
505 : | } | ||
506 : | else if (pmtOut->formattype == FORMAT_VideoInfo2 || | ||
507 : | pmtOut->formattype == FORMAT_MPEG2Video) | ||
508 : | { | ||
509 : | pBmp = &((VIDEOINFOHEADER2 *)pmtOut->pbFormat)->bmiHeader; | ||
510 : | } | ||
511 : | else | ||
512 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
513 : | |||
514 : | if (m_OutFcc == pBmp->biCompression) | ||
515 : | return S_OK; | ||
516 : | } | ||
517 : | |||
518 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
519 : | } | ||
520 : | |||
521 : | HRESULT | ||
522 : | ChangeSubtypeT::DecideBufferSize(IMemAllocator * pAlloc, | ||
523 : | ALLOCATOR_PROPERTIES * ppropInputRequest) | ||
524 : | { | ||
525 : | if (!m_pInput->IsConnected()) | ||
526 : | return E_UNEXPECTED; | ||
527 : | |||
528 : | HRESULT hr = NOERROR; | ||
529 : | BITMAPINFOHEADER *pBmp = 0; | ||
530 : | |||
531 : | if (!m_OutMediaType.pbFormat) | ||
532 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
533 : | |||
534 : | if (m_OutMediaType.formattype == FORMAT_VideoInfo || | ||
535 : | m_OutMediaType.formattype == FORMAT_MPEGVideo) | ||
536 : | { | ||
537 : | pBmp = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader; | ||
538 : | } | ||
539 : | else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || | ||
540 : | m_OutMediaType.formattype == FORMAT_MPEG2Video) | ||
541 : | { | ||
542 : | pBmp = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader; | ||
543 : | } | ||
544 : | else | ||
545 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
546 : | |||
547 : | ppropInputRequest->cBuffers = 1; | ||
548 : | ppropInputRequest->cbBuffer = pBmp->biHeight*pBmp->biWidth * (pBmp->biBitCount+7)/8; | ||
549 : | |||
550 : | ALLOCATOR_PROPERTIES Actual; | ||
551 : | hr = pAlloc->SetProperties(ppropInputRequest,&Actual); | ||
552 : | if (FAILED(hr)) | ||
553 : | return hr; | ||
554 : | |||
555 : | if (ppropInputRequest->cBuffers > Actual.cBuffers || | ||
556 : | ppropInputRequest->cbBuffer > Actual.cbBuffer) | ||
557 : | return E_FAIL; | ||
558 : | |||
559 : | return S_OK; | ||
560 : | } | ||
561 : | |||
562 : | HRESULT | ||
563 : | ChangeSubtypeT::GetMediaType(int iPosition, CMediaType *pMediaType) | ||
564 : | { | ||
565 : | if (!m_pInput->IsConnected()) { | ||
566 : | return E_UNEXPECTED; | ||
567 : | } | ||
568 : | else if (iPosition < 0) { | ||
569 : | return E_INVALIDARG; | ||
570 : | } | ||
571 : | else if (iPosition > 0) { | ||
572 : | return VFW_S_NO_MORE_ITEMS; | ||
573 : | } | ||
574 : | else { //if (iPosition == 0) | ||
575 : | *pMediaType = m_OutMediaType; | ||
576 : | return S_OK; | ||
577 : | } | ||
578 : | } | ||
579 : | |||
580 : | HRESULT | ||
581 : | ChangeSubtypeT::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin) | ||
582 : | { | ||
583 : | CMediaType mt; | ||
584 : | BITMAPINFOHEADER *pBmp = 0; | ||
585 : | pReceivePin->ConnectionMediaType(&mt); | ||
586 : | |||
587 : | if (mt.majortype == MEDIATYPE_Video) { | ||
588 : | if (direction == PINDIR_INPUT) { | ||
589 : | |||
590 : | // if (m_pOutput->IsConnected()) { | ||
591 : | // m_pInput->BreakConnection(); | ||
592 : | // } | ||
593 : | |||
594 : | m_InMediaType = mt; | ||
595 : | m_OutMediaType = mt; | ||
596 : | m_OutMediaType.subtype = m_SubtypeID; | ||
597 : | |||
598 : | int NewSequenceSize = 0; | ||
599 : | |||
600 : | if (m_InMediaType.formattype == FORMAT_VideoInfo || | ||
601 : | m_InMediaType.formattype == FORMAT_MPEGVideo) | ||
602 : | { | ||
603 : | pBmp = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader; | ||
604 : | m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->AvgTimePerFrame; | ||
605 : | } | ||
606 : | else { | ||
607 : | if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || | ||
608 : | m_OutMediaType.formattype == FORMAT_MPEG2Video) | ||
609 : | { | ||
610 : | pBmp = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader; | ||
611 : | m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->AvgTimePerFrame; | ||
612 : | } | ||
613 : | else | ||
614 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
615 : | } | ||
616 : | |||
617 : | if (*m_InMediaType.FormatType() == FORMAT_MPEG2Video) { | ||
618 : | MPEG2VIDEOINFO *mpeg2info=(MPEG2VIDEOINFO*)m_InMediaType.Format(); | ||
619 : | |||
620 : | if (mpeg2info->hdr.bmiHeader.biCompression!=0 && mpeg2info->cbSequenceHeader>0) { | ||
621 : | |||
622 : | if (m_pMpeg4Sequence) | ||
623 : | free(m_pMpeg4Sequence); | ||
624 : | |||
625 : | m_Mpeg4SequenceSize = mpeg2info->cbSequenceHeader; | ||
626 : | |||
627 : | if (m_Mpeg4SequenceSize > 0) { | ||
628 : | m_pMpeg4Sequence = (BYTE *)malloc(m_Mpeg4SequenceSize*sizeof(BYTE)); | ||
629 : | memcpy(m_pMpeg4Sequence, (const BYTE *)mpeg2info->dwSequenceHeader, m_Mpeg4SequenceSize); | ||
630 : | } | ||
631 : | } | ||
632 : | } | ||
633 : | |||
634 : | VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)m_OutMediaType.ReallocFormatBuffer(sizeof(VIDEOINFOHEADER)); | ||
635 : | if (pVih==NULL) { | ||
636 : | return E_OUTOFMEMORY; | ||
637 : | } | ||
638 : | |||
639 : | ZeroMemory(pVih, sizeof (VIDEOINFOHEADER)); | ||
640 : | CopyMemory(&pVih->bmiHeader, pBmp, sizeof(BITMAPINFOHEADER)); | ||
641 : | |||
642 : | /* set output format */ | ||
643 : | m_OutMediaType.SetType(&MEDIATYPE_Video); | ||
644 : | m_OutMediaType.SetFormatType(&FORMAT_VideoInfo); | ||
645 : | |||
646 : | m_OutMediaType.SetSubtype(&m_SubtypeID); | ||
647 : | pVih->bmiHeader.biCompression = m_OutFcc; | ||
648 : | |||
649 : | pVih->AvgTimePerFrame = m_AvgTimeForFrame; | ||
650 : | pVih->dwBitErrorRate = 0; | ||
651 : | pVih->dwBitRate = 8 * (DWORD)(((float)pVih->bmiHeader.biSizeImage * 10000000) / m_AvgTimeForFrame); | ||
652 : | |||
653 : | m_OutMediaType.SetTemporalCompression(TRUE); | ||
654 : | m_OutMediaType.SetVariableSize(); | ||
655 : | |||
656 : | if (m_AvgTimeForFrame) { | ||
657 : | switch (m_AvgTimeForFrame) { | ||
658 : | |||
659 : | case 416666: // 24.0 FPS | ||
660 : | m_FpsNom = 24; | ||
661 : | m_FpsDen = 1; | ||
662 : | break; | ||
663 : | |||
664 : | case 417083: // 23.97 FPS | ||
665 : | m_FpsNom = 24000; | ||
666 : | m_FpsDen = 1001; | ||
667 : | break; | ||
668 : | |||
669 : | case 333333: // 30.0 FPS | ||
670 : | m_FpsNom = 30; | ||
671 : | m_FpsDen = 1; | ||
672 : | break; | ||
673 : | |||
674 : | case 333666: // 29.97 FPS | ||
675 : | m_FpsNom = 30000; | ||
676 : | m_FpsDen = 1001; | ||
677 : | break; | ||
678 : | |||
679 : | default: | ||
680 : | m_FpsNom = (int) (10000000 / m_AvgTimeForFrame); | ||
681 : | m_FpsDen = 1; | ||
682 : | } | ||
683 : | } | ||
684 : | |||
685 : | m_SampleCnt = 0; | ||
686 : | return S_OK; | ||
687 : | } | ||
688 : | else { // if (direction == PINDIR_OUTPUT) { | ||
689 : | if (!m_pInput->IsConnected()) | ||
690 : | return E_UNEXPECTED; | ||
691 : | |||
692 : | if (m_SubtypeID != mt.subtype) | ||
693 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
694 : | |||
695 : | if (!mt.pbFormat) | ||
696 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
697 : | |||
698 : | if (mt.formattype == FORMAT_VideoInfo || | ||
699 : | mt.formattype == FORMAT_MPEGVideo) | ||
700 : | { | ||
701 : | pBmp = &((VIDEOINFOHEADER *)mt.pbFormat)->bmiHeader; | ||
702 : | } | ||
703 : | else if (mt.formattype == FORMAT_VideoInfo2 || | ||
704 : | mt.formattype == FORMAT_MPEG2Video) | ||
705 : | { | ||
706 : | pBmp = &((VIDEOINFOHEADER2 *)mt.pbFormat)->bmiHeader; | ||
707 : | } | ||
708 : | else | ||
709 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
710 : | |||
711 : | if (m_OutFcc == pBmp->biCompression) | ||
712 : | return S_OK; | ||
713 : | } | ||
714 : | } | ||
715 : | |||
716 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
717 : | } | ||
718 : | |||
719 : | HRESULT | ||
720 : | ChangeSubtypeT::Transform(IMediaSample *pIn, IMediaSample *pOut) | ||
721 : | { | ||
722 : | BITMAPINFOHEADER *pBmpIn=0, *pBmpOut=0; | ||
723 : | HRESULT hr = S_FALSE; | ||
724 : | |||
725 : | if (m_InMediaType.formattype == FORMAT_VideoInfo || | ||
726 : | m_InMediaType.formattype == FORMAT_MPEGVideo) | ||
727 : | { | ||
728 : | pBmpIn = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader; | ||
729 : | } | ||
730 : | else if (m_InMediaType.formattype == FORMAT_VideoInfo2 || | ||
731 : | m_InMediaType.formattype == FORMAT_MPEG2Video) | ||
732 : | { | ||
733 : | pBmpIn = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader; | ||
734 : | } | ||
735 : | |||
736 : | if (m_OutMediaType.formattype == FORMAT_VideoInfo || | ||
737 : | m_OutMediaType.formattype == FORMAT_MPEGVideo) | ||
738 : | { | ||
739 : | pBmpOut = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader; | ||
740 : | } | ||
741 : | else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || | ||
742 : | m_OutMediaType.formattype == FORMAT_MPEG2Video) | ||
743 : | { | ||
744 : | pBmpOut = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader; | ||
745 : | } | ||
746 : | |||
747 : | if (pBmpIn && pBmpOut && m_InMediaType.lSampleSize == m_OutMediaType.lSampleSize) | ||
748 : | { | ||
749 : | BYTE *pBufIn, *pBufOut; | ||
750 : | pIn->GetPointer(&pBufIn); | ||
751 : | pOut->GetPointer(&pBufOut); | ||
752 : | DWORD lSize = pIn->GetActualDataLength(); | ||
753 : | |||
754 : | DWORD OutOffset = 0; | ||
755 : | if (*((int *)pBufIn) != 0xB0010000 && m_pMpeg4Sequence) { | ||
756 : | if (pIn->IsSyncPoint() == S_OK) { // I-VOP | ||
757 : | memcpy(pBufOut, m_pMpeg4Sequence, m_Mpeg4SequenceSize); | ||
758 : | OutOffset = m_Mpeg4SequenceSize; | ||
759 : | } | ||
760 : | } | ||
761 : | |||
762 : | pOut->SetActualDataLength(lSize + OutOffset); | ||
763 : | memcpy(&pBufOut[OutOffset], pBufIn, lSize); | ||
764 : | LONGLONG UnitDuration = (10000000LL * m_FpsDen)/m_FpsNom; | ||
765 : | LONGLONG NormalStart = (m_SampleCnt * 10000000LL * m_FpsDen)/m_FpsNom; | ||
766 : | LONGLONG NormalEnd = ((m_SampleCnt + 1) * 10000000LL * m_FpsDen)/m_FpsNom; | ||
767 : | |||
768 : | LONGLONG sTime, eTime; | ||
769 : | pOut->GetTime(&sTime, &eTime); | ||
770 : | int bSetTime = 0; | ||
771 : | LONGLONG sDuration = eTime - sTime; | ||
772 : | |||
773 : | // simply set correct end time - seems to work here... | ||
774 : | if (eTime < sTime + UnitDuration) { | ||
775 : | eTime = sTime + UnitDuration; | ||
776 : | bSetTime = 1; | ||
777 : | } | ||
778 : | |||
779 : | if (bSetTime) pOut->SetTime(&sTime, &eTime); | ||
780 : | |||
781 : | #if 0 | ||
782 : | LONGLONG sTime=0, eTime=0; | ||
783 : | sTime = (m_SampleCnt * 10000000LL * m_FpsDen)/m_FpsNom; | ||
784 : | eTime = ((m_SampleCnt + 1) * 10000000LL * m_FpsDen)/m_FpsNom - 1; | ||
785 : | pOut->SetTime(&sTime, &eTime); | ||
786 : | #endif | ||
787 : | |||
788 : | m_startTime = sTime; | ||
789 : | m_stopTime = eTime; | ||
790 : | m_SampleCnt ++; | ||
791 : | |||
792 : | int CurPos = (int) ((double)(100.0 * m_SampleCnt/m_TotalFrames) + 0.5); | ||
793 : | if (m_Pass == 0) | ||
794 : | CurPos /= 2; | ||
795 : | else if (m_Pass == 2) | ||
796 : | CurPos = CurPos /2 + 50; | ||
797 : | |||
798 : | if (m_MessageWnd) | ||
799 : | PostMessage(m_MessageWnd, PBM_SETPOS, CurPos, 0); | ||
800 : | |||
801 : | hr = S_OK; | ||
802 : | } | ||
803 : | |||
804 : | return hr; | ||
805 : | } |
No admin address has been configured | ViewVC Help |
Powered by ViewVC 1.0.4 |