Parent Directory | Revision Log
Revision 2096 - (view) (download)
1 : | Isibaar | 2096 | /***************************************************************************** |
2 : | * | ||
3 : | * Xvid MiniConvert | ||
4 : | * - Helper filters - | ||
5 : | * | ||
6 : | * Copyright(C) 2011-2014 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: filters.cpp 2080 2014-04-08 20:01:07Z Isibaar $ | ||
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.nChannels >= 2 && pMp3->wfx.nAvgBytesPerSec != m_AudioBitrate) | ||
109 : | 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 : | DWORD SamplesSize = pSample->GetActualDataLength(); | ||
127 : | |||
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)) : ((double)(100*m_TotalDataSize / (1024*m_curSize)) + 0.5)); | ||
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 : | DWORD ThisSamples = (pMp3->wfx.nSamplesPerSec >= 32000 ? 1152 : 576) * pMp3->nFramesPerBlock; | ||
166 : | |||
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 : | m_SampleCnt += ThisSamples; | ||
179 : | |||
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 : | 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 : | 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 : | m_StopTimeMin = m_StopTimeMax = m_StartTimeMin = m_StartTimeMax = 0; | ||
451 : | m_bForceTimeStamps = 0; | ||
452 : | m_AudioBitrate = 1600; | ||
453 : | } | ||
454 : | |||
455 : | ////////////////////////////////////////////////////////////////// | ||
456 : | |||
457 : | /***************************************************************************** | ||
458 : | * MPEG-4 header parsing helper function | ||
459 : | ****************************************************************************/ | ||
460 : | |||
461 : | /* Copied from bitstream.c of xvidcore - TODO: BAD... | ||
462 : | /* Copyright (C) 2001-2003 Peter Ross <pross@xvid.org> */ | ||
463 : | |||
464 : | static const unsigned char log2_tab_16[16] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; | ||
465 : | |||
466 : | static unsigned int __inline log2bin(unsigned int value) | ||
467 : | { | ||
468 : | int n = 0; | ||
469 : | if (value & 0xffff0000) { | ||
470 : | value >>= 16; | ||
471 : | n += 16; | ||
472 : | } | ||
473 : | if (value & 0xff00) { | ||
474 : | value >>= 8; | ||
475 : | n += 8; | ||
476 : | } | ||
477 : | if (value & 0xf0) { | ||
478 : | value >>= 4; | ||
479 : | n += 4; | ||
480 : | } | ||
481 : | return n + log2_tab_16[value]; | ||
482 : | } | ||
483 : | |||
484 : | int | ||
485 : | Check_Video_Headers(Bitstream * bs) | ||
486 : | { | ||
487 : | unsigned int dec_ver_id = 1, vol_ver_id, start_code; | ||
488 : | |||
489 : | while ((BitstreamPos(bs) >> 3) + 4 <= bs->length) { | ||
490 : | BitstreamByteAlign(bs); | ||
491 : | start_code = BitstreamShowBits(bs, 32); | ||
492 : | |||
493 : | if (start_code == VISOBJ_START_CODE) { | ||
494 : | |||
495 : | BitstreamSkip(bs, 32); /* visual_object_start_code */ | ||
496 : | if (BitstreamGetBit(bs)) /* is_visual_object_identified */ | ||
497 : | { | ||
498 : | dec_ver_id = BitstreamGetBits(bs, 4); /* visual_object_ver_id */ | ||
499 : | BitstreamSkip(bs, 3); /* visual_object_priority */ | ||
500 : | } else { | ||
501 : | dec_ver_id = 1; | ||
502 : | } | ||
503 : | |||
504 : | if (BitstreamShowBits(bs, 4) != VISOBJ_TYPE_VIDEO) /* visual_object_type */ | ||
505 : | { | ||
506 : | return -1; | ||
507 : | } | ||
508 : | BitstreamSkip(bs, 4); | ||
509 : | |||
510 : | /* video_signal_type */ | ||
511 : | |||
512 : | if (BitstreamGetBit(bs)) /* video_signal_type */ | ||
513 : | { | ||
514 : | BitstreamSkip(bs, 3); /* video_format */ | ||
515 : | BitstreamSkip(bs, 1); /* video_range */ | ||
516 : | if (BitstreamGetBit(bs)) /* color_description */ | ||
517 : | { | ||
518 : | BitstreamSkip(bs, 8); /* color_primaries */ | ||
519 : | BitstreamSkip(bs, 8); /* transfer_characteristics */ | ||
520 : | BitstreamSkip(bs, 8); /* matrix_coefficients */ | ||
521 : | } | ||
522 : | } | ||
523 : | } else if ((start_code & ~VIDOBJLAY_START_CODE_MASK) == VIDOBJLAY_START_CODE) { | ||
524 : | |||
525 : | BitstreamSkip(bs, 32); /* video_object_layer_start_code */ | ||
526 : | BitstreamSkip(bs, 1); /* random_accessible_vol */ | ||
527 : | |||
528 : | BitstreamSkip(bs, 8); /* video_object_type_indication */ | ||
529 : | |||
530 : | if (BitstreamGetBit(bs)) /* is_object_layer_identifier */ | ||
531 : | { | ||
532 : | vol_ver_id = BitstreamGetBits(bs, 4); /* video_object_layer_verid */ | ||
533 : | BitstreamSkip(bs, 3); /* video_object_layer_priority */ | ||
534 : | } else { | ||
535 : | vol_ver_id = dec_ver_id; | ||
536 : | } | ||
537 : | |||
538 : | if (BitstreamGetBits(bs, 4) == VIDOBJLAY_AR_EXTPAR) /* aspect_ratio_info */ | ||
539 : | { | ||
540 : | BitstreamSkip(bs, 16); /* par_width + par_height */ | ||
541 : | } | ||
542 : | |||
543 : | if (BitstreamGetBit(bs)) /* vol_control_parameters */ | ||
544 : | { | ||
545 : | BitstreamSkip(bs, 2); /* chroma_format */ | ||
546 : | BitstreamSkip(bs, 1); /* low_delay */ | ||
547 : | if (BitstreamGetBit(bs)) /* vbv_parameters */ | ||
548 : | { | ||
549 : | BitstreamSkip(bs,15); /* first_half_bit_rate */ | ||
550 : | READ_MARKER(); | ||
551 : | BitstreamSkip(bs,15); /* latter_half_bit_rate */ | ||
552 : | READ_MARKER(); | ||
553 : | |||
554 : | BitstreamSkip(bs, 15); /* first_half_vbv_buffer_size */ | ||
555 : | READ_MARKER(); | ||
556 : | BitstreamSkip(bs, 3); /* latter_half_vbv_buffer_size */ | ||
557 : | |||
558 : | BitstreamSkip(bs, 11); /* first_half_vbv_occupancy */ | ||
559 : | READ_MARKER(); | ||
560 : | BitstreamSkip(bs, 15); /* latter_half_vbv_occupancy */ | ||
561 : | READ_MARKER(); | ||
562 : | } | ||
563 : | } | ||
564 : | |||
565 : | if (BitstreamGetBits(bs, 2) != VIDOBJLAY_SHAPE_RECTANGULAR) /* video_object_layer_shape */ | ||
566 : | { | ||
567 : | return -1; | ||
568 : | } | ||
569 : | |||
570 : | READ_MARKER(); | ||
571 : | |||
572 : | /********************** for decode B-frame time ***********************/ | ||
573 : | unsigned int time_inc_resolution = BitstreamGetBits(bs, 16); /* vop_time_increment_resolution */ | ||
574 : | |||
575 : | unsigned time_inc_bits = 1; | ||
576 : | |||
577 : | if (time_inc_resolution > 0) { | ||
578 : | time_inc_bits = MAX(log2bin(time_inc_resolution-1), 1); | ||
579 : | } | ||
580 : | |||
581 : | READ_MARKER(); | ||
582 : | |||
583 : | if (BitstreamGetBit(bs)) /* fixed_vop_rate */ | ||
584 : | { | ||
585 : | BitstreamSkip(bs, time_inc_bits); /* fixed_vop_time_increment */ | ||
586 : | } | ||
587 : | |||
588 : | READ_MARKER(); | ||
589 : | BitstreamSkip(bs, 13); /* video_object_layer_width */ | ||
590 : | READ_MARKER(); | ||
591 : | BitstreamSkip(bs, 13); /* video_object_layer_height */ | ||
592 : | READ_MARKER(); | ||
593 : | |||
594 : | if (BitstreamGetBit(bs)) | ||
595 : | { | ||
596 : | return -1; | ||
597 : | } | ||
598 : | |||
599 : | if (!BitstreamGetBit(bs)) /* obmc_disable */ | ||
600 : | { | ||
601 : | return -1; | ||
602 : | } | ||
603 : | |||
604 : | if (BitstreamGetBits(bs, (vol_ver_id == 1 ? 1 : 2)) != 0) /* sprite_enable */ | ||
605 : | { | ||
606 : | return -1; | ||
607 : | } | ||
608 : | } | ||
609 : | else /* start_code == ? */ | ||
610 : | { | ||
611 : | BitstreamSkip(bs, 8); | ||
612 : | } | ||
613 : | } | ||
614 : | |||
615 : | return 0; | ||
616 : | } | ||
617 : | |||
618 : | /*****************************************************************************/ | ||
619 : | |||
620 : | CUnknown * WINAPI | ||
621 : | ChangeSubtypeT::CreateInstance(IUnknown *pUnk, HRESULT *phr) | ||
622 : | { | ||
623 : | CUnknown *pNewFilter = new ChangeSubtypeT(pUnk, phr ); | ||
624 : | |||
625 : | if (phr) { | ||
626 : | if (pNewFilter == NULL) *phr = E_OUTOFMEMORY; | ||
627 : | else *phr = S_OK; | ||
628 : | } | ||
629 : | |||
630 : | return pNewFilter; | ||
631 : | } | ||
632 : | |||
633 : | ChangeSubtypeT::ChangeSubtypeT(LPUNKNOWN pUnk, HRESULT *phr) : | ||
634 : | CTransformFilter("ChangeSubtypeT", pUnk, CLSID_ChangeSubtypeT) | ||
635 : | { | ||
636 : | m_OutFcc = 'DIVX'; // == FCC('xvid') | ||
637 : | m_SubtypeID = FOURCCMap('divx'); // FCC('XVID') | ||
638 : | m_SampleCnt = 0; | ||
639 : | |||
640 : | if (*phr) *phr = S_OK; | ||
641 : | |||
642 : | m_pMpeg4Sequence = 0; | ||
643 : | m_Mpeg4SequenceSize = 0; | ||
644 : | } | ||
645 : | |||
646 : | ChangeSubtypeT::~ChangeSubtypeT(void) | ||
647 : | { | ||
648 : | } | ||
649 : | |||
650 : | HRESULT | ||
651 : | ChangeSubtypeT::NonDelegatingQueryInterface(REFIID riid, void ** ppv) | ||
652 : | { | ||
653 : | if (riid == IID_IRecProgressNotify) | ||
654 : | return GetInterface((IRecProgressNotify*)this, ppv); | ||
655 : | |||
656 : | return CBaseFilter::NonDelegatingQueryInterface (riid, ppv); | ||
657 : | } | ||
658 : | |||
659 : | HRESULT | ||
660 : | ChangeSubtypeT::CheckInputType(const CMediaType *pmt) | ||
661 : | { | ||
662 : | if (!pmt) | ||
663 : | return E_POINTER; | ||
664 : | |||
665 : | if (pmt->majortype != MEDIATYPE_Video) | ||
666 : | return S_FALSE; | ||
667 : | |||
668 : | return S_OK; | ||
669 : | } | ||
670 : | |||
671 : | HRESULT | ||
672 : | ChangeSubtypeT::CheckTransform (const CMediaType *pmtIn, const CMediaType *pmtOut) | ||
673 : | { | ||
674 : | if (!m_pInput->IsConnected()) | ||
675 : | return E_UNEXPECTED; | ||
676 : | |||
677 : | if (pmtIn->majortype != MEDIATYPE_Video) | ||
678 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
679 : | |||
680 : | BITMAPINFOHEADER *pBmp = 0; | ||
681 : | |||
682 : | if (pmtOut->majortype == MEDIATYPE_Video) { | ||
683 : | |||
684 : | if (m_SubtypeID != pmtOut->subtype) | ||
685 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
686 : | |||
687 : | if (!pmtOut->pbFormat) | ||
688 : | return S_OK; | ||
689 : | |||
690 : | if (pmtOut->formattype == FORMAT_VideoInfo || | ||
691 : | pmtOut->formattype == FORMAT_MPEGVideo) | ||
692 : | { | ||
693 : | pBmp = &((VIDEOINFOHEADER *)pmtOut->pbFormat)->bmiHeader; | ||
694 : | } | ||
695 : | else if (pmtOut->formattype == FORMAT_VideoInfo2 || | ||
696 : | pmtOut->formattype == FORMAT_MPEG2Video) | ||
697 : | { | ||
698 : | pBmp = &((VIDEOINFOHEADER2 *)pmtOut->pbFormat)->bmiHeader; | ||
699 : | } | ||
700 : | else | ||
701 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
702 : | |||
703 : | if (m_OutFcc == pBmp->biCompression) | ||
704 : | return S_OK; | ||
705 : | } | ||
706 : | |||
707 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
708 : | } | ||
709 : | |||
710 : | HRESULT | ||
711 : | ChangeSubtypeT::DecideBufferSize(IMemAllocator * pAlloc, | ||
712 : | ALLOCATOR_PROPERTIES * ppropInputRequest) | ||
713 : | { | ||
714 : | if (!m_pInput->IsConnected()) | ||
715 : | return E_UNEXPECTED; | ||
716 : | |||
717 : | HRESULT hr = NOERROR; | ||
718 : | BITMAPINFOHEADER *pBmp = 0; | ||
719 : | |||
720 : | if (!m_OutMediaType.pbFormat) | ||
721 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
722 : | |||
723 : | if (m_OutMediaType.formattype == FORMAT_VideoInfo || | ||
724 : | m_OutMediaType.formattype == FORMAT_MPEGVideo) | ||
725 : | { | ||
726 : | pBmp = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader; | ||
727 : | } | ||
728 : | else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || | ||
729 : | m_OutMediaType.formattype == FORMAT_MPEG2Video) | ||
730 : | { | ||
731 : | pBmp = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader; | ||
732 : | } | ||
733 : | else | ||
734 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
735 : | |||
736 : | ppropInputRequest->cBuffers = 1; | ||
737 : | ppropInputRequest->cbBuffer = pBmp->biHeight*pBmp->biWidth * (pBmp->biBitCount+7)/8; | ||
738 : | |||
739 : | ALLOCATOR_PROPERTIES Actual; | ||
740 : | hr = pAlloc->SetProperties(ppropInputRequest,&Actual); | ||
741 : | if (FAILED(hr)) | ||
742 : | return hr; | ||
743 : | |||
744 : | if (ppropInputRequest->cBuffers > Actual.cBuffers || | ||
745 : | ppropInputRequest->cbBuffer > Actual.cbBuffer) | ||
746 : | return E_FAIL; | ||
747 : | |||
748 : | return S_OK; | ||
749 : | } | ||
750 : | |||
751 : | HRESULT | ||
752 : | ChangeSubtypeT::GetMediaType(int iPosition, CMediaType *pMediaType) | ||
753 : | { | ||
754 : | if (!m_pInput->IsConnected()) { | ||
755 : | return E_UNEXPECTED; | ||
756 : | } | ||
757 : | else if (iPosition < 0) { | ||
758 : | return E_INVALIDARG; | ||
759 : | } | ||
760 : | else if (iPosition > 0) { | ||
761 : | return VFW_S_NO_MORE_ITEMS; | ||
762 : | } | ||
763 : | else { //if (iPosition == 0) | ||
764 : | *pMediaType = m_OutMediaType; | ||
765 : | return S_OK; | ||
766 : | } | ||
767 : | } | ||
768 : | |||
769 : | HRESULT | ||
770 : | ChangeSubtypeT::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin) | ||
771 : | { | ||
772 : | CMediaType mt; | ||
773 : | BITMAPINFOHEADER *pBmp = 0; | ||
774 : | pReceivePin->ConnectionMediaType(&mt); | ||
775 : | |||
776 : | if (mt.majortype == MEDIATYPE_Video) { | ||
777 : | if (direction == PINDIR_INPUT) { | ||
778 : | |||
779 : | // if (m_pOutput->IsConnected()) { | ||
780 : | // m_pInput->BreakConnection(); | ||
781 : | // } | ||
782 : | |||
783 : | m_InMediaType = mt; | ||
784 : | m_OutMediaType = mt; | ||
785 : | m_OutMediaType.subtype = m_SubtypeID; | ||
786 : | |||
787 : | int NewSequenceSize = 0; | ||
788 : | |||
789 : | if (m_InMediaType.formattype == FORMAT_VideoInfo || | ||
790 : | m_InMediaType.formattype == FORMAT_MPEGVideo) | ||
791 : | { | ||
792 : | pBmp = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader; | ||
793 : | m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->AvgTimePerFrame; | ||
794 : | } | ||
795 : | else { | ||
796 : | if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || | ||
797 : | m_OutMediaType.formattype == FORMAT_MPEG2Video) | ||
798 : | { | ||
799 : | pBmp = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader; | ||
800 : | m_AvgTimeForFrame = (DWORD) ((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->AvgTimePerFrame; | ||
801 : | } | ||
802 : | else | ||
803 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
804 : | } | ||
805 : | |||
806 : | if (*m_InMediaType.FormatType() == FORMAT_MPEG2Video) { | ||
807 : | MPEG2VIDEOINFO *mpeg2info=(MPEG2VIDEOINFO*)m_InMediaType.Format(); | ||
808 : | |||
809 : | if (mpeg2info->hdr.bmiHeader.biCompression!=0 && mpeg2info->cbSequenceHeader>0) { | ||
810 : | |||
811 : | if (m_pMpeg4Sequence) | ||
812 : | free(m_pMpeg4Sequence); | ||
813 : | |||
814 : | m_Mpeg4SequenceSize = mpeg2info->cbSequenceHeader; | ||
815 : | |||
816 : | if (m_Mpeg4SequenceSize > 0) { | ||
817 : | m_pMpeg4Sequence = (BYTE *)malloc(m_Mpeg4SequenceSize*sizeof(BYTE)); | ||
818 : | memcpy(m_pMpeg4Sequence, (const BYTE *)mpeg2info->dwSequenceHeader, m_Mpeg4SequenceSize); | ||
819 : | |||
820 : | Bitstream bs; | ||
821 : | BitstreamInit(&bs, m_pMpeg4Sequence, m_Mpeg4SequenceSize); | ||
822 : | |||
823 : | if (Check_Video_Headers(&bs) == -1) // Is upstream MPEG-4 video compatible with XVID? | ||
824 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
825 : | } | ||
826 : | } | ||
827 : | } | ||
828 : | |||
829 : | VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)m_OutMediaType.ReallocFormatBuffer(sizeof(VIDEOINFOHEADER)); | ||
830 : | if (pVih==NULL) { | ||
831 : | return E_OUTOFMEMORY; | ||
832 : | } | ||
833 : | |||
834 : | ZeroMemory(pVih, sizeof (VIDEOINFOHEADER)); | ||
835 : | CopyMemory(&pVih->bmiHeader, pBmp, sizeof(BITMAPINFOHEADER)); | ||
836 : | |||
837 : | /* set output format */ | ||
838 : | m_OutMediaType.SetType(&MEDIATYPE_Video); | ||
839 : | m_OutMediaType.SetFormatType(&FORMAT_VideoInfo); | ||
840 : | |||
841 : | m_OutMediaType.SetSubtype(&m_SubtypeID); | ||
842 : | pVih->bmiHeader.biCompression = m_OutFcc; | ||
843 : | |||
844 : | pVih->AvgTimePerFrame = m_AvgTimeForFrame; | ||
845 : | pVih->dwBitErrorRate = 0; | ||
846 : | pVih->dwBitRate = 8 * (DWORD)(((float)pVih->bmiHeader.biSizeImage * 10000000) / m_AvgTimeForFrame); | ||
847 : | |||
848 : | m_OutMediaType.SetTemporalCompression(TRUE); | ||
849 : | m_OutMediaType.SetVariableSize(); | ||
850 : | |||
851 : | if (m_AvgTimeForFrame) { | ||
852 : | switch (m_AvgTimeForFrame) { | ||
853 : | |||
854 : | case 416666: // 24.0 FPS | ||
855 : | m_FpsNom = 24; | ||
856 : | m_FpsDen = 1; | ||
857 : | break; | ||
858 : | |||
859 : | case 417083: // 23.97 FPS | ||
860 : | m_FpsNom = 24000; | ||
861 : | m_FpsDen = 1001; | ||
862 : | break; | ||
863 : | |||
864 : | case 333333: // 30.0 FPS | ||
865 : | m_FpsNom = 30; | ||
866 : | m_FpsDen = 1; | ||
867 : | break; | ||
868 : | |||
869 : | case 333666: // 29.97 FPS | ||
870 : | m_FpsNom = 30000; | ||
871 : | m_FpsDen = 1001; | ||
872 : | break; | ||
873 : | |||
874 : | default: | ||
875 : | m_FpsNom = (int) (10000000 / m_AvgTimeForFrame); | ||
876 : | m_FpsDen = 1; | ||
877 : | } | ||
878 : | } | ||
879 : | |||
880 : | m_SampleCnt = 0; | ||
881 : | m_UnitDuration = (10000000LL * m_FpsDen)/m_FpsNom; | ||
882 : | m_UnitTimeDelta = m_UnitDuration / 5; | ||
883 : | if (m_UnitTimeDelta < 1000) m_UnitTimeDelta = m_UnitDuration > 2000 ? 1000 : m_UnitDuration/2; | ||
884 : | m_stopTime = m_startTime = 0; | ||
885 : | |||
886 : | |||
887 : | m_MaxStartTime = m_MaxStopTime = 0; | ||
888 : | |||
889 : | return S_OK; | ||
890 : | } | ||
891 : | else { // if (direction == PINDIR_OUTPUT) { | ||
892 : | if (!m_pInput->IsConnected()) | ||
893 : | return E_UNEXPECTED; | ||
894 : | |||
895 : | if (m_SubtypeID != mt.subtype) | ||
896 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
897 : | |||
898 : | if (!mt.pbFormat) | ||
899 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
900 : | |||
901 : | if (mt.formattype == FORMAT_VideoInfo || | ||
902 : | mt.formattype == FORMAT_MPEGVideo) | ||
903 : | { | ||
904 : | pBmp = &((VIDEOINFOHEADER *)mt.pbFormat)->bmiHeader; | ||
905 : | } | ||
906 : | else if (mt.formattype == FORMAT_VideoInfo2 || | ||
907 : | mt.formattype == FORMAT_MPEG2Video) | ||
908 : | { | ||
909 : | pBmp = &((VIDEOINFOHEADER2 *)mt.pbFormat)->bmiHeader; | ||
910 : | } | ||
911 : | else | ||
912 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
913 : | |||
914 : | if (m_bForceTimeStamps) { | ||
915 : | if (m_OutMediaType.formattype == FORMAT_VideoInfo || | ||
916 : | m_OutMediaType.formattype == FORMAT_MPEGVideo) { | ||
917 : | ((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->AvgTimePerFrame = | ||
918 : | m_AvgTimeForFrame = (DWORD) (m_FpsNom/m_FpsDen); | ||
919 : | } else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || | ||
920 : | m_OutMediaType.formattype == FORMAT_MPEG2Video) { | ||
921 : | ((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->AvgTimePerFrame = | ||
922 : | m_AvgTimeForFrame = (DWORD) (m_FpsNom/m_FpsDen); | ||
923 : | } | ||
924 : | } | ||
925 : | |||
926 : | if (m_OutFcc == pBmp->biCompression) | ||
927 : | return S_OK; | ||
928 : | } | ||
929 : | } | ||
930 : | |||
931 : | return VFW_E_TYPE_NOT_ACCEPTED; | ||
932 : | } | ||
933 : | |||
934 : | HRESULT | ||
935 : | ChangeSubtypeT::Transform(IMediaSample *pIn, IMediaSample *pOut) | ||
936 : | { | ||
937 : | BITMAPINFOHEADER *pBmpIn=0, *pBmpOut=0; | ||
938 : | HRESULT hr = S_FALSE; | ||
939 : | |||
940 : | if (m_InMediaType.formattype == FORMAT_VideoInfo || | ||
941 : | m_InMediaType.formattype == FORMAT_MPEGVideo) | ||
942 : | { | ||
943 : | pBmpIn = &((VIDEOINFOHEADER *)m_InMediaType.pbFormat)->bmiHeader; | ||
944 : | } | ||
945 : | else if (m_InMediaType.formattype == FORMAT_VideoInfo2 || | ||
946 : | m_InMediaType.formattype == FORMAT_MPEG2Video) | ||
947 : | { | ||
948 : | pBmpIn = &((VIDEOINFOHEADER2 *)m_InMediaType.pbFormat)->bmiHeader; | ||
949 : | } | ||
950 : | |||
951 : | if (m_OutMediaType.formattype == FORMAT_VideoInfo || | ||
952 : | m_OutMediaType.formattype == FORMAT_MPEGVideo) | ||
953 : | { | ||
954 : | pBmpOut = &((VIDEOINFOHEADER *)m_OutMediaType.pbFormat)->bmiHeader; | ||
955 : | } | ||
956 : | else if (m_OutMediaType.formattype == FORMAT_VideoInfo2 || | ||
957 : | m_OutMediaType.formattype == FORMAT_MPEG2Video) | ||
958 : | { | ||
959 : | pBmpOut = &((VIDEOINFOHEADER2 *)m_OutMediaType.pbFormat)->bmiHeader; | ||
960 : | } | ||
961 : | |||
962 : | if (pBmpIn && pBmpOut && m_InMediaType.lSampleSize == m_OutMediaType.lSampleSize) | ||
963 : | { | ||
964 : | BYTE *pBufIn, *pBufOut; | ||
965 : | pIn->GetPointer(&pBufIn); | ||
966 : | pOut->GetPointer(&pBufOut); | ||
967 : | DWORD lSize = pIn->GetActualDataLength(); | ||
968 : | |||
969 : | DWORD OutOffset = 0; | ||
970 : | if (*((int *)pBufIn) != 0xB0010000 && m_pMpeg4Sequence) { | ||
971 : | int FrameType = -1; | ||
972 : | for (int iOffset=0; iOffset < (int) (lSize - 5) && FrameType == -1; iOffset++) { | ||
973 : | if (*((int *)(&(pBufIn[iOffset]))) == 0xB6010000) { | ||
974 : | FrameType = (pBufIn[iOffset + 4] >> 6)& 3; | ||
975 : | } | ||
976 : | } | ||
977 : | pOut->SetSyncPoint(FrameType == 0 ? TRUE : FALSE); | ||
978 : | //if (pIn->IsSyncPoint() == S_OK) { // I-VOP // IsSyncPoint() is not reliable !! | ||
979 : | if (FrameType == 0) { | ||
980 : | memcpy(pBufOut, m_pMpeg4Sequence, m_Mpeg4SequenceSize); | ||
981 : | OutOffset = m_Mpeg4SequenceSize; | ||
982 : | } | ||
983 : | } | ||
984 : | |||
985 : | pOut->SetActualDataLength(lSize + OutOffset); | ||
986 : | memcpy(&pBufOut[OutOffset], pBufIn, lSize); | ||
987 : | LONGLONG ExpectedStart = m_stopTime; | ||
988 : | LONGLONG ExpectedStop = m_stopTime + m_UnitDuration; | ||
989 : | |||
990 : | LONGLONG sTime, eTime; | ||
991 : | pOut->GetTime(&sTime, &eTime); | ||
992 : | int bSetTime = 0; | ||
993 : | LONGLONG sDuration = eTime - sTime; | ||
994 : | |||
995 : | if (m_Pass == 1) { | ||
996 : | if (m_SampleCnt == 0) { | ||
997 : | m_StopTimeMin = m_StopTimeMax = eTime; | ||
998 : | m_StartTimeMin = m_StartTimeMax = sTime; | ||
999 : | } else { | ||
1000 : | if (m_StopTimeMin > eTime) m_StopTimeMin = eTime; | ||
1001 : | if (m_StopTimeMax < eTime) m_StopTimeMax = eTime; | ||
1002 : | if (m_StartTimeMin > sTime) m_StartTimeMin = sTime; | ||
1003 : | if (m_StartTimeMax < sTime) m_StartTimeMax = sTime; | ||
1004 : | } | ||
1005 : | } else if (m_SampleCnt == 0 && m_bForceTimeStamps) { | ||
1006 : | m_UnitDuration = m_FpsNom/m_FpsDen; | ||
1007 : | m_UnitTimeDelta = m_UnitDuration / 5; | ||
1008 : | if (m_UnitTimeDelta < 1000) m_UnitTimeDelta = m_UnitDuration > 2000 ? 1000 : m_UnitDuration/2; | ||
1009 : | } | ||
1010 : | |||
1011 : | int bForceStopTime = 0; | ||
1012 : | if (abs((long)((LONGLONG)(ExpectedStop - m_MaxStopTime))) < m_UnitTimeDelta) { | ||
1013 : | // re-use of time that had one of previous samples | ||
1014 : | // in case when times of samples are reordered | ||
1015 : | // to keep exactly in sync with speed of playing of original speed | ||
1016 : | // in long distance. Any way of calculation based on | ||
1017 : | // number of samples may fail if stream is long enough | ||
1018 : | // and frame duration is calculated not with | ||
1019 : | // absolute precision (NTSC - family framerates: 23.98, 29.97, etc...) | ||
1020 : | |||
1021 : | ExpectedStop = m_MaxStopTime; | ||
1022 : | bForceStopTime = 1; | ||
1023 : | if (ExpectedStart + m_UnitDuration > ExpectedStop + m_UnitTimeDelta) { | ||
1024 : | ExpectedStart = m_MaxStartTime; | ||
1025 : | if (ExpectedStart + m_UnitDuration > ExpectedStop) | ||
1026 : | ExpectedStart = ExpectedStop - m_UnitDuration; | ||
1027 : | } | ||
1028 : | } | ||
1029 : | |||
1030 : | //LONGLONG eTimeN = eTime * m_FpsNom, Den0 = 10000000LL * m_FpsDen; | ||
1031 : | //int SampleEMin = ((eTimeN < 100000) ? 0 : eTimeN - 10000)/Den0, SampleEMax = (eTimeN + 10000)/Den0; | ||
1032 : | //int TimeEDiff = eTime - m_stopTime; | ||
1033 : | LONGLONG MaxStartTime = max(m_MaxStartTime, sTime), | ||
1034 : | MaxStopTime = max(m_MaxStopTime, eTime); | ||
1035 : | |||
1036 : | // simply set correct end time - seems to work here... | ||
1037 : | |||
1038 : | //if (m_Pass ==2 && m_bForceTimeStamps) { | ||
1039 : | // sTime = m_SampleCnt * m_FpsNom / m_FpsDen; | ||
1040 : | // eTime = (m_SampleCnt +1) * m_FpsNom / m_FpsDen; | ||
1041 : | // bSetTime = 1; | ||
1042 : | //} | ||
1043 : | |||
1044 : | if (eTime + m_UnitTimeDelta < sTime + m_UnitDuration) { | ||
1045 : | eTime = sTime + m_UnitDuration; | ||
1046 : | bSetTime = 1; | ||
1047 : | } | ||
1048 : | |||
1049 : | if ((bForceStopTime) || (eTime + m_UnitDuration < ExpectedStop)) { | ||
1050 : | //if ((bForceStopTime) || (eTime > ExpectedStop + m_UnitTimeDelta) || (eTime + m_UnitTimeDelta < ExpectedStop)) { | ||
1051 : | eTime = ExpectedStop; | ||
1052 : | sTime = ExpectedStart; | ||
1053 : | bSetTime = 1; | ||
1054 : | } | ||
1055 : | m_MaxStartTime = max(MaxStartTime, sTime); | ||
1056 : | m_MaxStopTime = max(MaxStopTime, eTime); | ||
1057 : | |||
1058 : | if (bSetTime) pOut->SetTime(&sTime, &eTime); | ||
1059 : | |||
1060 : | m_startTime = sTime; | ||
1061 : | m_stopTime = eTime; | ||
1062 : | m_SampleCnt ++; | ||
1063 : | |||
1064 : | int CurPos = (int) ((double)(100.0 * m_SampleCnt/m_TotalFrames) + 0.5); | ||
1065 : | if (m_Pass == 0) | ||
1066 : | CurPos /= 2; | ||
1067 : | else if (m_Pass == 2) | ||
1068 : | CurPos = CurPos /2 + 50; | ||
1069 : | |||
1070 : | if (m_MessageWnd) | ||
1071 : | PostMessage(m_MessageWnd, PBM_SETPOS, CurPos, 0); | ||
1072 : | |||
1073 : | hr = S_OK; | ||
1074 : | } | ||
1075 : | |||
1076 : | return hr; | ||
1077 : | } |
No admin address has been configured | ViewVC Help |
Powered by ViewVC 1.0.4 |