[svn] / branches / release-1_3-branch / xvidextra / src / apps / miniconvert / filters.cpp Repository:
ViewVC logotype

Annotation of /branches/release-1_3-branch/xvidextra/src/apps/miniconvert/filters.cpp

Parent Directory Parent Directory | Revision Log 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