2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
25 #include "DirectVobSubFilter.h"
26 #include "TextInputPin.h"
27 #include "DirectVobSubPropPage.h"
30 #include "../../../DSUtil/MediaTypes.h"
31 #include "../../../SubPic/SimpleSubPicProviderImpl.h"
32 #include "../../../SubPic/PooledSubPic.h"
33 #include "../../../subpic/color_conv_table.h"
34 #include "../../../subpic/SimpleSubPicWrapper.h"
37 #include "..\..\..\..\include\moreuuids.h"
39 #include "CAutoTiming.h"
40 #include "xy_logger.h"
43 #define MAX_SUBPIC_QUEUE_LENGTH 1
45 ///////////////////////////////////////////////////////////////////////////
48 bool g_RegOK
= true;//false; // doesn't work with the dvd graph builder
52 EXTERN_C IMAGE_DOS_HEADER __ImageBase
;
55 using namespace DirectVobSubXyOptions
;
57 ////////////////////////////////////////////////////////////////////////////
62 CDirectVobSubFilter::CDirectVobSubFilter(LPUNKNOWN punk
, HRESULT
* phr
, const GUID
& clsid
)
63 : CBaseVideoFilter(NAME("CDirectVobSubFilter"), punk
, phr
, clsid
)
65 , m_fMSMpeg4Fix(false)
68 DbgLog((LOG_TRACE
, 3, _T("CDirectVobSubFilter::CDirectVobSubFilter")));
70 // and then, anywhere you need it:
73 LPTSTR strDLLPath
= new TCHAR
[_MAX_PATH
];
74 ::GetModuleFileName( reinterpret_cast<HINSTANCE
>(&__ImageBase
), strDLLPath
, _MAX_PATH
);
75 CString dllPath
= strDLLPath
;
76 dllPath
+= ".properties";
77 xy_logger::doConfigure( dllPath
.GetString() );
80 AFX_MANAGE_STATE(AfxGetStaticModuleState());
88 memset(&lf
, 0, sizeof(lf
));
89 lf
.lfCharSet
= DEFAULT_CHARSET
;
90 lf
.lfOutPrecision
= OUT_CHARACTER_PRECIS
;
91 lf
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
92 lf
.lfQuality
= ANTIALIASED_QUALITY
;
93 HDC hdc
= GetDC(NULL
);
95 //MulDiv(20, GetDeviceCaps(hdc, LOGPIXELSY), 54);
97 lf
.lfWeight
= FW_BOLD
;
98 _tcscpy(lf
.lfFaceName
, _T("Arial"));
99 m_hfont
= CreateFontIndirect(&lf
);
102 theApp
.WriteProfileString(ResStr(IDS_R_DEFTEXTPATHES
), _T("Hint"), _T("The first three are fixed, but you can add more up to ten entries."));
103 theApp
.WriteProfileString(ResStr(IDS_R_DEFTEXTPATHES
), _T("Path0"), _T("."));
104 theApp
.WriteProfileString(ResStr(IDS_R_DEFTEXTPATHES
), _T("Path1"), _T("c:\\subtitles"));
105 theApp
.WriteProfileString(ResStr(IDS_R_DEFTEXTPATHES
), _T("Path2"), _T(".\\subtitles"));
109 m_hSystrayThread
= 0;
110 m_tbid
.hSystrayWnd
= NULL
;
112 m_tbid
.fRunOnce
= false;
113 m_tbid
.fShowIcon
= (theApp
.m_AppName
.Find(_T("zplayer"), 0) < 0 || !!theApp
.GetProfileInt(ResStr(IDS_R_GENERAL
), ResStr(IDS_RG_ENABLEZPICON
), 0));
116 m_pTextInput
.Add(new CTextInputPin(this, m_pLock
, &m_csSubLock
, &hr
));
117 ASSERT(SUCCEEDED(hr
));
120 m_frd
.EndThreadEvent
.Create(0, FALSE
, FALSE
, 0);
121 m_frd
.RefreshEvent
.Create(0, FALSE
, FALSE
, 0);
123 memset(&m_CurrentVIH2
, 0, sizeof(VIDEOINFOHEADER2
));
125 m_donot_follow_upstream_preferred_order
= !m_xy_bool_opt
[BOOL_FOLLOW_UPSTREAM_PREFERRED_ORDER
];
127 m_time_alphablt
= m_time_rasterization
= 0;
129 m_script_selected_yuv
= CSimpleTextSubtitle::YCbCrMatrix_AUTO
;
130 m_script_selected_range
= CSimpleTextSubtitle::YCbCrRange_AUTO
;
133 CDirectVobSubFilter::~CDirectVobSubFilter()
135 CAutoLock
cAutoLock(&m_csQueueLock
);
136 if(m_simple_provider
)
138 DbgLog((LOG_TRACE
, 3, "~CDirectVobSubFilter::Invalidate"));
139 m_simple_provider
->Invalidate();
141 m_simple_provider
= NULL
;
143 if(m_hfont
) {DeleteObject(m_hfont
); m_hfont
= 0;}
144 if(m_hbm
) {DeleteObject(m_hbm
); m_hbm
= 0;}
145 if(m_hdc
) {DeleteObject(m_hdc
); m_hdc
= 0;}
147 for(size_t i
= 0; i
< m_pTextInput
.GetCount(); i
++)
148 delete m_pTextInput
[i
];
150 m_frd
.EndThreadEvent
.Set();
153 DbgLog((LOG_TRACE
, 3, _T("CDirectVobSubFilter::~CDirectVobSubFilter")));
155 //Trace(_T("CDirectVobSubFilter::~CDirectVobSubFilter"));
159 STDMETHODIMP
CDirectVobSubFilter::NonDelegatingQueryInterface(REFIID riid
, void** ppv
)
161 CheckPointer(ppv
, E_POINTER
);
168 QI(ISpecifyPropertyPages
)
170 __super::NonDelegatingQueryInterface(riid
, ppv
);
175 void CDirectVobSubFilter::GetOutputSize(int& w
, int& h
, int& arx
, int& ary
)
177 CSize
s(w
, h
), os
= s
;
184 while(arx
< 100) arx
*= 10, ary
*= 10;
185 arx
= arx
* w
/ os
.cx
;
190 while(ary
< 100) arx
*= 10, ary
*= 10;
191 ary
= ary
* h
/ os
.cy
;
195 HRESULT
CDirectVobSubFilter::TryNotCopy(IMediaSample
* pIn
, const CMediaType
& mt
, const BITMAPINFOHEADER
& bihIn
)
198 CSize
in(bihIn
.biWidth
, bihIn
.biHeight
);
199 BYTE
* pDataIn
= NULL
;
200 if(FAILED(pIn
->GetPointer(&pDataIn
)) || !pDataIn
)
204 m_spd
.bits
= pDataIn
;
208 m_spd
.bits
= static_cast<BYTE
*>(m_pTempPicBuff
);
209 bool fYV12
= (mt
.subtype
== MEDIASUBTYPE_YV12
|| mt
.subtype
== MEDIASUBTYPE_I420
|| mt
.subtype
== MEDIASUBTYPE_IYUV
);
210 bool fNV12
= (mt
.subtype
== MEDIASUBTYPE_NV12
|| mt
.subtype
== MEDIASUBTYPE_NV21
);
211 bool fP010
= (mt
.subtype
== MEDIASUBTYPE_P010
|| mt
.subtype
== MEDIASUBTYPE_P016
);
213 int bpp
= fP010
? 16 : (fYV12
||fNV12
) ? 8 : bihIn
.biBitCount
;
214 DWORD black
= fP010
? 0x10001000 : (fYV12
||fNV12
) ? 0x10101010 : (bihIn
.biCompression
== '2YUY') ? 0x80108010 : 0;
217 if(FAILED(Copy((BYTE
*)m_pTempPicBuff
, pDataIn
, sub
, in
, bpp
, mt
.subtype
, black
)))
222 BYTE
* pSubV
= (BYTE
*)m_pTempPicBuff
+ (sub
.cx
*bpp
>>3)*sub
.cy
;
223 BYTE
* pInV
= pDataIn
+ (in
.cx
*bpp
>>3)*in
.cy
;
224 sub
.cx
>>= 1; sub
.cy
>>= 1; in
.cx
>>= 1; in
.cy
>>= 1;
225 BYTE
* pSubU
= pSubV
+ (sub
.cx
*bpp
>>3)*sub
.cy
;
226 BYTE
* pInU
= pInV
+ (in
.cx
*bpp
>>3)*in
.cy
;
227 if(FAILED(Copy(pSubV
, pInV
, sub
, in
, bpp
, mt
.subtype
, 0x80808080)))
229 if(FAILED(Copy(pSubU
, pInU
, sub
, in
, bpp
, mt
.subtype
, 0x80808080)))
234 BYTE
* pSubUV
= (BYTE
*)m_pTempPicBuff
+ (sub
.cx
*bpp
>>3)*sub
.cy
;
235 BYTE
* pInUV
= pDataIn
+ (in
.cx
*bpp
>>3)*in
.cy
;
236 sub
.cy
>>= 1; in
.cy
>>= 1;
237 if(FAILED(Copy(pSubUV
, pInUV
, sub
, in
, bpp
, mt
.subtype
, 0x80008000)))
241 BYTE
* pSubUV
= (BYTE
*)m_pTempPicBuff
+ (sub
.cx
*bpp
>>3)*sub
.cy
;
242 BYTE
* pInUV
= pDataIn
+ (in
.cx
*bpp
>>3)*in
.cy
;
245 if(FAILED(Copy(pSubUV
, pInUV
, sub
, in
, bpp
, mt
.subtype
, 0x80808080)))
252 HRESULT
CDirectVobSubFilter::Transform(IMediaSample
* pIn
)
254 XY_LOG_ONCE(0, _T("CDirectVobSubFilter::Transform"));
258 REFERENCE_TIME rtStart
, rtStop
;
259 if(SUCCEEDED(pIn
->GetTime(&rtStart
, &rtStop
)))
261 double dRate
= m_pInput
->CurrentRate();
263 m_tPrev
= m_pInput
->CurrentStartTime() + dRate
*rtStart
;
265 REFERENCE_TIME rtAvgTimePerFrame
= rtStop
- rtStart
;
266 if(CComQIPtr
<ISubClock2
> pSC2
= m_pSubClock
)
269 if(S_OK
== pSC2
->GetAvgTimePerFrame(&rt
))
270 rtAvgTimePerFrame
= rt
;
273 m_fps
= 10000000.0/rtAvgTimePerFrame
/ dRate
;
279 CAutoLock
cAutoLock(&m_csQueueLock
);
281 if(m_simple_provider
)
283 m_simple_provider
->SetTime(CalcCurrentTime());
284 m_simple_provider
->SetFPS(m_fps
);
291 const CMediaType
& mt
= m_pInput
->CurrentMediaType();
293 BITMAPINFOHEADER bihIn
;
294 ExtractBIH(&mt
, &bihIn
);
296 hr
= TryNotCopy(pIn
, mt
, bihIn
);
304 SubPicDesc spd
= m_spd
;
306 CComPtr
<IMediaSample
> pOut
;
307 BYTE
* pDataOut
= NULL
;
308 if(FAILED(hr
= GetDeliveryBuffer(spd
.w
, spd
.h
, &pOut
))
309 || FAILED(hr
= pOut
->GetPointer(&pDataOut
)))
311 pOut
->SetTime(&rtStart
, &rtStop
);
312 pOut
->SetMediaTime(NULL
, NULL
);
313 pOut
->SetDiscontinuity(pIn
->IsDiscontinuity() == S_OK
);
314 pOut
->SetSyncPoint(pIn
->IsSyncPoint() == S_OK
);
315 pOut
->SetPreroll(pIn
->IsPreroll() == S_OK
);
318 BITMAPINFOHEADER bihOut
;
319 ExtractBIH(&m_pOutput
->CurrentMediaType(), &bihOut
);
321 bool fInputFlipped
= bihIn
.biHeight
>= 0 && bihIn
.biCompression
<= 3;
322 bool fOutputFlipped
= bihOut
.biHeight
>= 0 && bihOut
.biCompression
<= 3;
324 bool fFlip
= fInputFlipped
!= fOutputFlipped
;
325 if(m_fFlipPicture
) fFlip
= !fFlip
;
326 if(m_fMSMpeg4Fix
) fFlip
= !fFlip
;
328 bool fFlipSub
= fOutputFlipped
;
329 if(m_fFlipSubtitles
) fFlipSub
= !fFlipSub
;
334 CAutoLock
cAutoLock(&m_csQueueLock
);
336 if(m_simple_provider
)
338 CComPtr
<ISimpleSubPic
> pSubPic
;
339 //int timeStamp1 = GetTickCount();
340 bool lookupResult
= m_simple_provider
->LookupSubPic(CalcCurrentTime(), &pSubPic
);
341 //int timeStamp2 = GetTickCount();
342 //m_time_rasterization += timeStamp2-timeStamp1;
344 if(lookupResult
&& pSubPic
)
348 pSubPic
->AlphaBlt(&spd
);
349 DbgLog((LOG_TRACE
,3,"AlphaBlt time:%lu", (ULONG
)(CalcCurrentTime()/10000)));
353 CopyBuffer(pDataOut
, (BYTE
*)spd
.bits
, spd
.w
, abs(spd
.h
)*(fFlip
?-1:1), spd
.pitch
, mt
.subtype
);
355 PrintMessages(pDataOut
);
356 return m_pOutput
->Deliver(pOut
);
361 CBasePin
* CDirectVobSubFilter::GetPin(int n
)
363 if(n
< __super::GetPinCount())
364 return __super::GetPin(n
);
366 n
-= __super::GetPinCount();
368 if(n
>= 0 && n
< m_pTextInput
.GetCount())
369 return m_pTextInput
[n
];
371 n
-= m_pTextInput
.GetCount();
376 int CDirectVobSubFilter::GetPinCount()
378 return __super::GetPinCount() + m_pTextInput
.GetCount();
381 HRESULT
CDirectVobSubFilter::JoinFilterGraph(IFilterGraph
* pGraph
, LPCWSTR pName
)
385 AFX_MANAGE_STATE(AfxGetStaticModuleState());
387 if(!theApp
.GetProfileInt(ResStr(IDS_R_GENERAL
), ResStr(IDS_RG_SEENDIVXWARNING
), 0))
389 unsigned __int64 ver
= GetFileVersion(_T("divx_c32.ax"));
390 if(((ver
>> 48)&0xffff) == 4 && ((ver
>> 32)&0xffff) == 2)
392 DWORD dwVersion
= GetVersion();
393 DWORD dwWindowsMajorVersion
= (DWORD
)(LOBYTE(LOWORD(dwVersion
)));
394 DWORD dwWindowsMinorVersion
= (DWORD
)(HIBYTE(LOWORD(dwVersion
)));
396 if(dwVersion
< 0x80000000 && dwWindowsMajorVersion
>= 5)
398 AfxMessageBox(IDS_DIVX_WARNING
);
399 theApp
.WriteProfileInt(ResStr(IDS_R_GENERAL
), ResStr(IDS_RG_SEENDIVXWARNING
), 1);
415 SendMessage(m_tbid
.hSystrayWnd
, WM_CLOSE
, 0, 0);
417 if(WaitForSingleObject(m_hSystrayThread
, 10000) != WAIT_OBJECT_0
)
419 DbgLog((LOG_TRACE
, 0, _T("CALL THE AMBULANCE!!!")));
420 TerminateThread(m_hSystrayThread
, (DWORD
)-1);
423 m_hSystrayThread
= 0;
427 return __super::JoinFilterGraph(pGraph
, pName
);
430 STDMETHODIMP
CDirectVobSubFilter::QueryFilterInfo(FILTER_INFO
* pInfo
)
432 CheckPointer(pInfo
, E_POINTER
);
433 ValidateReadWritePtr(pInfo
, sizeof(FILTER_INFO
));
436 return __super::QueryFilterInfo(pInfo
);
438 wcscpy(pInfo
->achName
, L
"DirectVobSub (forced auto-loading version)");
439 if(pInfo
->pGraph
= m_pGraph
) m_pGraph
->AddRef();
446 HRESULT
CDirectVobSubFilter::SetMediaType(PIN_DIRECTION dir
, const CMediaType
* pmt
)
448 HRESULT hr
= __super::SetMediaType(dir
, pmt
);
449 if(FAILED(hr
)) return hr
;
451 if(dir
== PINDIR_INPUT
)
453 CAutoLock
cAutoLock(&m_csReceive
);
455 REFERENCE_TIME atpf
=
456 pmt
->formattype
== FORMAT_VideoInfo
? ((VIDEOINFOHEADER
*)pmt
->Format())->AvgTimePerFrame
:
457 pmt
->formattype
== FORMAT_VideoInfo2
? ((VIDEOINFOHEADER2
*)pmt
->Format())->AvgTimePerFrame
:
460 m_fps
= atpf
? 10000000.0 / atpf
: 25;
462 if (pmt
->formattype
== FORMAT_VideoInfo2
)
463 m_CurrentVIH2
= *(VIDEOINFOHEADER2
*)pmt
->Format();
465 DbgLog((LOG_TRACE
, 3, "SetMediaType => InitSubPicQueue"));
468 else if(dir
== PINDIR_OUTPUT
)
476 HRESULT
CDirectVobSubFilter::CheckConnect(PIN_DIRECTION dir
, IPin
* pPin
)
478 if(dir
== PINDIR_INPUT
)
481 else if(dir
== PINDIR_OUTPUT
)
484 if(HmGyanusVagyTeNekem(pPin
)) return(E_FAIL
);
487 return __super::CheckConnect(dir
, pPin
);
490 HRESULT
CDirectVobSubFilter::CompleteConnect(PIN_DIRECTION dir
, IPin
* pReceivePin
)
492 bool reconnected
= false;
493 if(dir
== PINDIR_INPUT
)
495 DbgLog((LOG_TRACE
, 3, TEXT("connect input")));
496 DumpGraph(m_pGraph
,0);
497 CComPtr
<IBaseFilter
> pFilter
;
499 // needed when we have a decoder with a version number of 3.x
500 if(SUCCEEDED(m_pGraph
->FindFilterByName(L
"DivX MPEG-4 DVD Video Decompressor ", &pFilter
))
501 && (GetFileVersion(_T("divx_c32.ax")) >> 48) <= 4
502 || SUCCEEDED(m_pGraph
->FindFilterByName(L
"Microcrap MPEG-4 Video Decompressor", &pFilter
))
503 || SUCCEEDED(m_pGraph
->FindFilterByName(L
"Microsoft MPEG-4 Video Decompressor", &pFilter
))
504 && (GetFileVersion(_T("mpg4ds32.ax")) >> 48) <= 3)
506 m_fMSMpeg4Fix
= true;
509 else if(dir
== PINDIR_OUTPUT
)
511 DbgLog((LOG_TRACE
, 3, TEXT("connect output")));
512 DumpGraph(m_pGraph
,0);
513 const CMediaType
* mtIn
= &(m_pInput
->CurrentMediaType());
514 const CMediaType
* mtOut
= &(m_pOutput
->CurrentMediaType());
515 CMediaType desiredMt
;
519 bool can_reconnect
= false;
520 bool can_transform
= (DoCheckTransform(mtIn
, mtOut
, true)==S_OK
);
521 if( mtIn
->subtype
!=mtOut
->subtype
)
523 position
= GetOutputSubtypePosition(mtOut
->subtype
);
526 hr
= GetMediaType(position
, &desiredMt
);
529 DbgLog((LOG_ERROR
, 3, TEXT("Unexpected error when GetMediaType, position:%d"), position
));
533 hr
= DoCheckTransform(&desiredMt
, mtOut
, true);
536 DbgLog((LOG_TRACE
, 3, TEXT("Transform not accept:")));
537 DisplayType(0,&desiredMt
);
538 DisplayType(0,mtOut
);
542 hr
= m_pInput
->GetConnected()->QueryAccept(&desiredMt
);
545 DbgLog((LOG_TRACE
, 3, TEXT("Upstream not accept:")));
546 DisplayType(0, &desiredMt
);
550 can_reconnect
= true;
551 DbgLog((LOG_ERROR
, 3, TEXT("Can use the same subtype!")));
558 DbgLog((LOG_ERROR
, 3, TEXT("Cannot use the same subtype!")));
561 if(!can_reconnect
&& !can_transform
)
566 hr
= GetMediaType(position
, &desiredMt
);
572 DbgLog((LOG_TRACE
, 3, TEXT("Checking reconnect with media type:")));
573 DisplayType(0, &desiredMt
);
575 if( DoCheckTransform(&desiredMt
, mtOut
, true)!=S_OK
||
576 m_pInput
->GetConnected()->QueryAccept(&desiredMt
)!=S_OK
)
582 can_reconnect
= true;
589 if (SUCCEEDED(ReconnectPin(m_pInput
, &desiredMt
)))
592 DumpGraph(m_pGraph
,0);
593 //m_pInput->SetMediaType(&desiredMt);
594 DbgLog((LOG_TRACE
, 3, TEXT("reconnected succeed!")));
597 else if(!can_transform
)
599 DbgLog((LOG_TRACE
, 3, TEXT("Failed to agree reconnect type!")));
600 if(m_pInput
->IsConnected())
602 m_pInput
->GetConnected()->Disconnect();
603 m_pInput
->Disconnect();
605 if(m_pOutput
->IsConnected())
607 m_pOutput
->GetConnected()->Disconnect();
608 m_pOutput
->Disconnect();
610 return VFW_E_TYPE_NOT_ACCEPTED
;
613 if (!reconnected
&& m_pOutput
->IsConnected())
615 if(!m_hSystrayThread
&& !m_xy_bool_opt
[BOOL_HIDE_TRAY_ICON
])
617 m_tbid
.graph
= m_pGraph
;
618 m_tbid
.dvs
= static_cast<IDirectVobSub
*>(this);
621 m_hSystrayThread
= CreateThread(0, 0, SystrayThreadProc
, &m_tbid
, 0, &tid
);
623 m_pInput
->SetMediaType( &m_pInput
->CurrentMediaType() );
626 HRESULT hr
= __super::CompleteConnect(dir
, pReceivePin
);
627 DbgLog((LOG_TRACE
, 3, TEXT("connect fininshed!")));
628 DumpGraph(m_pGraph
,0);
632 HRESULT
CDirectVobSubFilter::BreakConnect(PIN_DIRECTION dir
)
634 if(dir
== PINDIR_INPUT
)
636 //if(m_pOutput->IsConnected())
638 // m_pOutput->GetConnected()->Disconnect();
639 // m_pOutput->Disconnect();
642 else if(dir
== PINDIR_OUTPUT
)
644 // not really needed, but may free up a little memory
645 CAutoLock
cAutoLock(&m_csQueueLock
);
646 m_simple_provider
= NULL
;
649 return __super::BreakConnect(dir
);
652 HRESULT
CDirectVobSubFilter::StartStreaming()
654 /* WARNING: calls to m_pGraph member functions from within this function will generate deadlock with Haali
655 * Video Renderer in MPC. Reason is that CAutoLock's variables in IFilterGraph functions are overriden by
661 DbgLog((LOG_TRACE
, 3, "StartStreaming => InitSubPicQueue"));
664 m_tbid
.fRunOnce
= true;
666 put_MediaFPS(m_fMediaFPSEnabled
, m_MediaFPS
);
668 return __super::StartStreaming();
671 HRESULT
CDirectVobSubFilter::StopStreaming()
673 InvalidateSubtitle();
676 //FILE * timingFile = fopen("C:\\vsfilter_timing.txt", "at");
677 //fprintf(timingFile, "%s:%ld %s:%ld\n", "m_time_alphablt", m_time_alphablt, "m_time_rasterization", m_time_rasterization);
678 //fclose(timingFile);
680 return __super::StopStreaming();
683 HRESULT
CDirectVobSubFilter::NewSegment(REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
)
686 return __super::NewSegment(tStart
, tStop
, dRate
);
691 REFERENCE_TIME
CDirectVobSubFilter::CalcCurrentTime()
693 REFERENCE_TIME rt
= m_pSubClock
? m_pSubClock
->GetTime() : m_tPrev
;
694 return (rt
- 10000i64
*m_SubtitleDelay
) * m_SubtitleSpeedMul
/ m_SubtitleSpeedDiv
; // no, it won't overflow if we use normal parameters (__int64 is enough for about 2000 hours if we multiply it by the max: 65536 as m_SubtitleSpeedMul)
697 void CDirectVobSubFilter::InitSubPicQueue()
699 CAutoLock
cAutoLock(&m_csQueueLock
);
701 CacheManager::GetPathDataMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_PATH_DATA_CACHE_MAX_ITEM_NUM
]);
702 CacheManager::GetScanLineData2MruCache()->SetMaxItemNum(m_xy_int_opt
[INT_SCAN_LINE_DATA_CACHE_MAX_ITEM_NUM
]);
703 CacheManager::GetOverlayNoBlurMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_OVERLAY_NO_BLUR_CACHE_MAX_ITEM_NUM
]);
704 CacheManager::GetOverlayMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_OVERLAY_CACHE_MAX_ITEM_NUM
]);
706 XyFwGroupedDrawItemsHashKey::GetCacher()->SetMaxItemNum(m_xy_int_opt
[INT_BITMAP_MRU_CACHE_ITEM_NUM
]);
707 CacheManager::GetBitmapMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_BITMAP_MRU_CACHE_ITEM_NUM
]);
709 CacheManager::GetClipperAlphaMaskMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_CLIPPER_MRU_CACHE_ITEM_NUM
]);
710 CacheManager::GetTextInfoCache()->SetMaxItemNum(m_xy_int_opt
[INT_TEXT_INFO_CACHE_ITEM_NUM
]);
711 CacheManager::GetAssTagListMruCache()->SetMaxItemNum(m_xy_int_opt
[INT_ASS_TAG_LIST_CACHE_ITEM_NUM
]);
713 SubpixelPositionControler::GetGlobalControler().SetSubpixelLevel( static_cast<SubpixelPositionControler::SUBPIXEL_LEVEL
>(m_xy_int_opt
[INT_SUBPIXEL_POS_LEVEL
]) );
715 m_simple_provider
= NULL
;
717 const GUID
& subtype
= m_pInput
->CurrentMediaType().subtype
;
719 BITMAPINFOHEADER bihIn
;
720 ExtractBIH(&m_pInput
->CurrentMediaType(), &bihIn
);
724 if(subtype
== MEDIASUBTYPE_YV12
) m_spd
.type
= MSP_YV12
;
725 else if(subtype
== MEDIASUBTYPE_P010
) m_spd
.type
= MSP_P010
;
726 else if(subtype
== MEDIASUBTYPE_P016
) m_spd
.type
= MSP_P016
;
727 else if(subtype
== MEDIASUBTYPE_I420
|| subtype
== MEDIASUBTYPE_IYUV
) m_spd
.type
= MSP_IYUV
;
728 else if(subtype
== MEDIASUBTYPE_YUY2
) m_spd
.type
= MSP_YUY2
;
729 else if(subtype
== MEDIASUBTYPE_RGB32
) m_spd
.type
= MSP_RGB32
;
730 else if(subtype
== MEDIASUBTYPE_RGB24
) m_spd
.type
= MSP_RGB24
;
731 else if(subtype
== MEDIASUBTYPE_RGB565
) m_spd
.type
= MSP_RGB16
;
732 else if(subtype
== MEDIASUBTYPE_RGB555
) m_spd
.type
= MSP_RGB15
;
733 else if(subtype
== MEDIASUBTYPE_NV12
) m_spd
.type
= MSP_NV12
;
734 else if(subtype
== MEDIASUBTYPE_NV21
) m_spd
.type
= MSP_NV21
;
735 else if(subtype
== MEDIASUBTYPE_AYUV
) m_spd
.type
= MSP_AYUV
;
739 m_spd
.bpp
= (m_spd
.type
== MSP_P010
|| m_spd
.type
== MSP_P016
) ? 16 :
740 (m_spd
.type
== MSP_YV12
|| m_spd
.type
== MSP_IYUV
|| m_spd
.type
== MSP_NV12
|| m_spd
.type
== MSP_NV21
) ? 8 : bihIn
.biBitCount
;
741 m_spd
.pitch
= m_spd
.w
*m_spd
.bpp
>>3;
743 m_pTempPicBuff
.Free();
744 if(m_spd
.type
== MSP_YV12
|| m_spd
.type
== MSP_IYUV
|| m_spd
.type
== MSP_NV12
|| m_spd
.type
== MSP_NV21
)
745 m_pTempPicBuff
.Allocate(4*m_spd
.pitch
*m_spd
.h
);//fix me: can be smaller
746 else if(m_spd
.type
== MSP_P010
|| m_spd
.type
== MSP_P016
)
747 m_pTempPicBuff
.Allocate(m_spd
.pitch
*m_spd
.h
+m_spd
.pitch
*m_spd
.h
/2);
749 m_pTempPicBuff
.Allocate(m_spd
.pitch
*m_spd
.h
);
750 m_spd
.bits
= (void*)m_pTempPicBuff
;
752 CSize
video(bihIn
.biWidth
, bihIn
.biHeight
), window
= video
;
753 if(AdjustFrameSize(window
)) video
+= video
;
754 ASSERT(window
== CSize(m_w
, m_h
));
755 CRect
video_rect(CPoint((window
.cx
- video
.cx
)/2, (window
.cy
- video
.cy
)/2), video
);
758 //m_pSubPicQueue = m_fDoPreBuffering
759 // ? (ISubPicQueue*)new CSubPicQueue(MAX_SUBPIC_QUEUE_LENGTH, pSubPicAllocator, &hr)
760 // : (ISubPicQueue*)new CSubPicQueueNoThread(pSubPicAllocator, &hr);
761 m_simple_provider
= new SimpleSubPicProvider2(m_spd
.type
, CSize(m_w
, m_h
), window
, video_rect
, this, &hr
);
763 if(FAILED(hr
)) m_simple_provider
= NULL
;
765 XySetSize(DirectVobSubXyOptions::SIZE_ORIGINAL_VIDEO
, CSize(m_w
, m_h
));
766 UpdateSubtitle(false);
768 if(m_hbm
) {DeleteObject(m_hbm
); m_hbm
= NULL
;}
769 if(m_hdc
) {DeleteDC(m_hdc
); m_hdc
= NULL
;}
771 struct {BITMAPINFOHEADER bih
; DWORD mask
[3];} b
= {{sizeof(BITMAPINFOHEADER
), m_w
, -(int)m_h
, 1, 32, BI_BITFIELDS
, 0, 0, 0, 0, 0}, 0xFF0000, 0x00FF00, 0x0000FF};
772 m_hdc
= CreateCompatibleDC(NULL
);
773 m_hbm
= CreateDIBSection(m_hdc
, (BITMAPINFO
*)&b
, DIB_RGB_COLORS
, NULL
, NULL
, 0);
776 GetObject(m_hbm
, sizeof(bm
), &bm
);
777 memsetd(bm
.bmBits
, 0xFF000000, bm
.bmHeight
*bm
.bmWidthBytes
);
780 bool CDirectVobSubFilter::AdjustFrameSize(CSize
& s
)
782 int horizontal
, vertical
, resx2
, resx2minw
, resx2minh
;
783 get_ExtendPicture(&horizontal
, &vertical
, &resx2
, &resx2minw
, &resx2minh
);
785 bool fRet
= (resx2
== 1) || (resx2
== 2 && s
.cx
*s
.cy
<= resx2minw
*resx2minh
);
794 switch(vertical
&0x7f)
798 if(s
.cy
< h
|| !!(vertical
&0x80)) s
.cy
= (h
+ 3) & ~3;
802 if(s
.cy
< h
|| !!(vertical
&0x80)) s
.cy
= (h
+ 3) & ~3;
806 if(s
.cy
< h
|| !!(vertical
&0x80)) s
.cy
= (h
+ 3) & ~3;
810 if(s
.cy
< h
|| !!(vertical
&0x80)) s
.cy
= (h
+ 3) & ~3;
816 s
.cx
= (s
.cx
+ 31) & ~31;
817 s
.cy
= (s
.cy
+ 1) & ~1;
823 STDMETHODIMP
CDirectVobSubFilter::Count(DWORD
* pcStreams
)
825 if(!pcStreams
) return E_POINTER
;
830 if(SUCCEEDED(get_LanguageCount(&nLangs
)))
831 (*pcStreams
) += nLangs
;
833 (*pcStreams
) += 2; // enable ... disable
835 (*pcStreams
) += 2; // normal flipped
840 #define MAXPREFLANGS 5
842 int CDirectVobSubFilter::FindPreferedLanguage(bool fHideToo
)
844 AFX_MANAGE_STATE(AfxGetStaticModuleState());
847 get_LanguageCount(&nLangs
);
849 if(nLangs
<= 0) return(0);
851 for(int i
= 0; i
< MAXPREFLANGS
; i
++)
854 tmp
.Format(IDS_RL_LANG
, i
);
856 CString lang
= theApp
.GetProfileString(ResStr(IDS_R_PREFLANGS
), tmp
);
860 for(int ret
= 0; ret
< nLangs
; ret
++)
864 get_LanguageName(ret
, &pName
);
866 CoTaskMemFree(pName
);
868 if(!l
.CompareNoCase(lang
)) return(ret
);
876 void CDirectVobSubFilter::UpdatePreferedLanguages(CString l
)
878 AFX_MANAGE_STATE(AfxGetStaticModuleState());
880 CString langs
[MAXPREFLANGS
+1];
882 int i
= 0, j
= 0, k
= -1;
883 for(; i
< MAXPREFLANGS
; i
++)
886 tmp
.Format(IDS_RL_LANG
, i
);
888 langs
[j
] = theApp
.GetProfileString(ResStr(IDS_R_PREFLANGS
), tmp
);
890 if(!langs
[j
].IsEmpty())
892 if(!langs
[j
].CompareNoCase(l
)) k
= j
;
903 // move the selected to the top of the list
907 CString tmp
= langs
[k
]; langs
[k
] = langs
[k
-1]; langs
[k
-1] = tmp
;
911 // move "Hide subtitles" to the last position if it wasn't our selection
914 hidesubs
.LoadString(IDS_M_HIDESUBTITLES
);
916 for(k
= 1; k
< j
; k
++)
918 if(!langs
[k
].CompareNoCase(hidesubs
)) break;
923 CString tmp
= langs
[k
]; langs
[k
] = langs
[k
+1]; langs
[k
+1] = tmp
;
927 for(i
= 0; i
< j
; i
++)
930 tmp
.Format(IDS_RL_LANG
, i
);
932 theApp
.WriteProfileString(ResStr(IDS_R_PREFLANGS
), tmp
, langs
[i
]);
936 STDMETHODIMP
CDirectVobSubFilter::Enable(long lIndex
, DWORD dwFlags
)
938 if(!(dwFlags
& AMSTREAMSELECTENABLE_ENABLE
))
942 get_LanguageCount(&nLangs
);
944 if(!(lIndex
>= 0 && lIndex
< nLangs
+2+2))
949 if(i
== -1 && !m_fLoading
) // we need this because when loading something stupid media player pushes the first stream it founds, which is "enable" in our case
951 put_HideSubtitles(false);
953 else if(i
>= 0 && i
< nLangs
)
955 put_HideSubtitles(false);
956 put_SelectedLanguage(i
);
959 if(SUCCEEDED(get_LanguageName(i
, &pName
)))
961 UpdatePreferedLanguages(CString(pName
));
962 if(pName
) CoTaskMemFree(pName
);
965 else if(i
== nLangs
&& !m_fLoading
)
967 put_HideSubtitles(true);
969 else if((i
== nLangs
+1 || i
== nLangs
+2) && !m_fLoading
)
971 put_Flip(i
== nLangs
+2, m_fFlipSubtitles
);
977 STDMETHODIMP
CDirectVobSubFilter::Info(long lIndex
, AM_MEDIA_TYPE
** ppmt
, DWORD
* pdwFlags
, LCID
* plcid
, DWORD
* pdwGroup
, WCHAR
** ppszName
, IUnknown
** ppObject
, IUnknown
** ppUnk
)
979 AFX_MANAGE_STATE(AfxGetStaticModuleState());
980 const int FLAG_CMD
= 1;
981 const int FLAG_EXTERNAL_SUB
= 2;
982 const int FLAG_PICTURE_CMD
= 4;
983 const int FLAG_VISIBILITY_CMD
= 8;
985 const int GROUP_NUM_BASE
= 0x648E40;//random number
988 get_LanguageCount(&nLangs
);
990 if(!(lIndex
>= 0 && lIndex
< nLangs
+2+2))
995 if(ppmt
) *ppmt
= CreateMediaType(&m_pInput
->CurrentMediaType());
1001 if(i
== -1 && !m_fHideSubtitles
1002 || i
>= 0 && i
< nLangs
&& i
== m_iSelectedLanguage
1003 || i
== nLangs
&& m_fHideSubtitles
1004 || i
== nLangs
+1 && !m_fFlipPicture
1005 || i
== nLangs
+2 && m_fFlipPicture
)
1007 *pdwFlags
|= AMSTREAMSELECTINFO_ENABLED
;
1011 if(plcid
) *plcid
= 0;
1015 *pdwGroup
= GROUP_NUM_BASE
;
1018 *pdwGroup
= GROUP_NUM_BASE
| FLAG_CMD
| FLAG_VISIBILITY_CMD
;
1020 else if(i
>= 0 && i
< nLangs
)
1022 bool isEmbedded
= false;
1023 if( SUCCEEDED(GetIsEmbeddedSubStream(i
, &isEmbedded
)) )
1027 *pdwGroup
= GROUP_NUM_BASE
& ~(FLAG_CMD
| FLAG_EXTERNAL_SUB
);
1031 *pdwGroup
= (GROUP_NUM_BASE
& ~FLAG_CMD
) | FLAG_EXTERNAL_SUB
;
1035 else if(i
== nLangs
)
1037 *pdwGroup
= GROUP_NUM_BASE
| FLAG_CMD
| FLAG_VISIBILITY_CMD
;
1039 else if(i
== nLangs
+1)
1041 *pdwGroup
= GROUP_NUM_BASE
| FLAG_CMD
| FLAG_PICTURE_CMD
;
1043 else if(i
== nLangs
+2)
1045 *pdwGroup
= GROUP_NUM_BASE
| FLAG_CMD
| FLAG_PICTURE_CMD
;
1054 if(i
== -1) str
= ResStr(IDS_M_SHOWSUBTITLES
);
1055 else if(i
>= 0 && i
< nLangs
)
1057 get_LanguageName(i
, ppszName
);
1059 else if(i
== nLangs
)
1061 str
= ResStr(IDS_M_HIDESUBTITLES
);
1063 else if(i
== nLangs
+1)
1065 str
= ResStr(IDS_M_ORIGINALPICTURE
);
1067 else if(i
== nLangs
+2)
1069 str
= ResStr(IDS_M_FLIPPEDPICTURE
);
1074 *ppszName
= (WCHAR
*)CoTaskMemAlloc((str
.GetLength()+1)*sizeof(WCHAR
));
1075 if(*ppszName
== NULL
) return S_FALSE
;
1076 wcscpy(*ppszName
, str
);
1080 if(ppObject
) *ppObject
= NULL
;
1082 if(ppUnk
) *ppUnk
= NULL
;
1087 STDMETHODIMP
CDirectVobSubFilter::GetClassID(CLSID
* pClsid
)
1089 if(pClsid
== NULL
) return E_POINTER
;
1094 STDMETHODIMP
CDirectVobSubFilter::GetPages(CAUUID
* pPages
)
1096 CheckPointer(pPages
, E_POINTER
);
1099 pPages
->pElems
= (GUID
*)CoTaskMemAlloc(sizeof(GUID
)*pPages
->cElems
);
1101 if(pPages
->pElems
== NULL
) return E_OUTOFMEMORY
;
1104 pPages
->pElems
[i
++] = __uuidof(CDVSMainPPage
);
1105 pPages
->pElems
[i
++] = __uuidof(CDVSGeneralPPage
);
1106 pPages
->pElems
[i
++] = __uuidof(CDVSMiscPPage
);
1107 pPages
->pElems
[i
++] = __uuidof(CDVSMorePPage
);
1108 pPages
->pElems
[i
++] = __uuidof(CDVSTimingPPage
);
1109 pPages
->pElems
[i
++] = __uuidof(CDVSColorPPage
);
1110 pPages
->pElems
[i
++] = __uuidof(CDVSPathsPPage
);
1111 pPages
->pElems
[i
++] = __uuidof(CDVSAboutPPage
);
1118 STDMETHODIMP
CDirectVobSubFilter::put_FileName(WCHAR
* fn
)
1120 AMTRACE((TEXT(__FUNCTION__
),0));
1121 HRESULT hr
= CDirectVobSub::put_FileName(fn
);
1123 if(hr
== S_OK
&& !Open())
1132 STDMETHODIMP
CDirectVobSubFilter::get_LanguageCount(int* nLangs
)
1134 HRESULT hr
= CDirectVobSub::get_LanguageCount(nLangs
);
1136 if(hr
== NOERROR
&& nLangs
)
1138 CAutoLock
cAutolock(&m_csQueueLock
);
1141 POSITION pos
= m_pSubStreams
.GetHeadPosition();
1142 while(pos
) (*nLangs
) += m_pSubStreams
.GetNext(pos
)->GetStreamCount();
1148 STDMETHODIMP
CDirectVobSubFilter::get_LanguageName(int iLanguage
, WCHAR
** ppName
)
1150 HRESULT hr
= CDirectVobSub::get_LanguageName(iLanguage
, ppName
);
1152 if(!ppName
) return E_POINTER
;
1156 CAutoLock
cAutolock(&m_csQueueLock
);
1162 POSITION pos
= m_pSubStreams
.GetHeadPosition();
1163 while(i
>= 0 && pos
)
1165 CComPtr
<ISubStream
> pSubStream
= m_pSubStreams
.GetNext(pos
);
1167 if(i
< pSubStream
->GetStreamCount())
1169 pSubStream
->GetStreamInfo(i
, ppName
, NULL
);
1174 i
-= pSubStream
->GetStreamCount();
1181 STDMETHODIMP
CDirectVobSubFilter::put_SelectedLanguage(int iSelected
)
1183 HRESULT hr
= CDirectVobSub::put_SelectedLanguage(iSelected
);
1187 UpdateSubtitle(false);
1193 STDMETHODIMP
CDirectVobSubFilter::put_HideSubtitles(bool fHideSubtitles
)
1195 HRESULT hr
= CDirectVobSub::put_HideSubtitles(fHideSubtitles
);
1199 UpdateSubtitle(false);
1205 STDMETHODIMP
CDirectVobSubFilter::put_PreBuffering(bool fDoPreBuffering
)
1207 HRESULT hr
= CDirectVobSub::put_PreBuffering(fDoPreBuffering
);
1211 DbgLog((LOG_TRACE
, 3, "put_PreBuffering => InitSubPicQueue"));
1218 STDMETHODIMP
CDirectVobSubFilter::put_Placement(bool fOverridePlacement
, int xperc
, int yperc
)
1220 DbgLog((LOG_TRACE
, 3, "%s(%d) %s", __FILE__
, __LINE__
, __FUNCTION__
));
1221 HRESULT hr
= CDirectVobSub::put_Placement(fOverridePlacement
, xperc
, yperc
);
1225 //DbgLog((LOG_TRACE, 3, "%d %s:UpdateSubtitle(true)", __LINE__, __FUNCTION__));
1226 //UpdateSubtitle(true);
1227 UpdateSubtitle(false);
1233 STDMETHODIMP
CDirectVobSubFilter::put_VobSubSettings(bool fBuffer
, bool fOnlyShowForcedSubs
, bool fReserved
)
1235 HRESULT hr
= CDirectVobSub::put_VobSubSettings(fBuffer
, fOnlyShowForcedSubs
, fReserved
);
1239 // UpdateSubtitle(false);
1240 InvalidateSubtitle();
1246 STDMETHODIMP
CDirectVobSubFilter::put_TextSettings(void* lf
, int lflen
, COLORREF color
, bool fShadow
, bool fOutline
, bool fAdvancedRenderer
)
1248 HRESULT hr
= CDirectVobSub::put_TextSettings(lf
, lflen
, color
, fShadow
, fOutline
, fAdvancedRenderer
);
1252 // UpdateSubtitle(true);
1253 InvalidateSubtitle();
1259 STDMETHODIMP
CDirectVobSubFilter::put_SubtitleTiming(int delay
, int speedmul
, int speeddiv
)
1261 HRESULT hr
= CDirectVobSub::put_SubtitleTiming(delay
, speedmul
, speeddiv
);
1265 InvalidateSubtitle();
1271 STDMETHODIMP
CDirectVobSubFilter::get_CachesInfo(CachesInfo
* caches_info
)
1273 CAutoLock
cAutoLock(&m_csQueueLock
);
1274 HRESULT hr
= CDirectVobSub::get_CachesInfo(caches_info
);
1276 caches_info
->path_cache_cur_item_num
= CacheManager::GetPathDataMruCache()->GetCurItemNum();
1277 caches_info
->path_cache_hit_count
= CacheManager::GetPathDataMruCache()->GetCacheHitCount();
1278 caches_info
->path_cache_query_count
= CacheManager::GetPathDataMruCache()->GetQueryCount();
1279 caches_info
->scanline_cache2_cur_item_num
= CacheManager::GetScanLineData2MruCache()->GetCurItemNum();
1280 caches_info
->scanline_cache2_hit_count
= CacheManager::GetScanLineData2MruCache()->GetCacheHitCount();
1281 caches_info
->scanline_cache2_query_count
= CacheManager::GetScanLineData2MruCache()->GetQueryCount();
1282 caches_info
->non_blur_cache_cur_item_num
= CacheManager::GetOverlayNoBlurMruCache()->GetCurItemNum();
1283 caches_info
->non_blur_cache_hit_count
= CacheManager::GetOverlayNoBlurMruCache()->GetCacheHitCount();
1284 caches_info
->non_blur_cache_query_count
= CacheManager::GetOverlayNoBlurMruCache()->GetQueryCount();
1285 caches_info
->overlay_cache_cur_item_num
= CacheManager::GetOverlayMruCache()->GetCurItemNum();
1286 caches_info
->overlay_cache_hit_count
= CacheManager::GetOverlayMruCache()->GetCacheHitCount();
1287 caches_info
->overlay_cache_query_count
= CacheManager::GetOverlayMruCache()->GetQueryCount();
1289 caches_info
->bitmap_cache_cur_item_num
= CacheManager::GetBitmapMruCache()->GetCurItemNum();
1290 caches_info
->bitmap_cache_hit_count
= CacheManager::GetBitmapMruCache()->GetCacheHitCount();
1291 caches_info
->bitmap_cache_query_count
= CacheManager::GetBitmapMruCache()->GetQueryCount();
1293 caches_info
->interpolate_cache_cur_item_num
= CacheManager::GetSubpixelVarianceCache()->GetCurItemNum();
1294 caches_info
->interpolate_cache_hit_count
= CacheManager::GetSubpixelVarianceCache()->GetCacheHitCount();
1295 caches_info
->interpolate_cache_query_count
= CacheManager::GetSubpixelVarianceCache()->GetQueryCount();
1296 caches_info
->text_info_cache_cur_item_num
= CacheManager::GetTextInfoCache()->GetCurItemNum();
1297 caches_info
->text_info_cache_hit_count
= CacheManager::GetTextInfoCache()->GetCacheHitCount();
1298 caches_info
->text_info_cache_query_count
= CacheManager::GetTextInfoCache()->GetQueryCount();
1300 caches_info
->word_info_cache_cur_item_num
= CacheManager::GetAssTagListMruCache()->GetCurItemNum();
1301 caches_info
->word_info_cache_hit_count
= CacheManager::GetAssTagListMruCache()->GetCacheHitCount();
1302 caches_info
->word_info_cache_query_count
= CacheManager::GetAssTagListMruCache()->GetQueryCount();
1304 caches_info
->scanline_cache_cur_item_num
= CacheManager::GetScanLineDataMruCache()->GetCurItemNum();
1305 caches_info
->scanline_cache_hit_count
= CacheManager::GetScanLineDataMruCache()->GetCacheHitCount();
1306 caches_info
->scanline_cache_query_count
= CacheManager::GetScanLineDataMruCache()->GetQueryCount();
1308 caches_info
->overlay_key_cache_cur_item_num
= CacheManager::GetOverlayNoOffsetMruCache()->GetCurItemNum();
1309 caches_info
->overlay_key_cache_hit_count
= CacheManager::GetOverlayNoOffsetMruCache()->GetCacheHitCount();
1310 caches_info
->overlay_key_cache_query_count
= CacheManager::GetOverlayNoOffsetMruCache()->GetQueryCount();
1312 caches_info
->clipper_cache_cur_item_num
= CacheManager::GetClipperAlphaMaskMruCache()->GetCurItemNum();
1313 caches_info
->clipper_cache_hit_count
= CacheManager::GetClipperAlphaMaskMruCache()->GetCacheHitCount();
1314 caches_info
->clipper_cache_query_count
= CacheManager::GetClipperAlphaMaskMruCache()->GetQueryCount();
1319 STDMETHODIMP
CDirectVobSubFilter::get_XyFlyWeightInfo( XyFlyWeightInfo
* xy_fw_info
)
1321 CAutoLock
cAutoLock(&m_csQueueLock
);
1322 HRESULT hr
= CDirectVobSub::get_XyFlyWeightInfo(xy_fw_info
);
1324 xy_fw_info
->xy_fw_string_w
.cur_item_num
= XyFwStringW::GetCacher()->GetCurItemNum();
1325 xy_fw_info
->xy_fw_string_w
.hit_count
= XyFwStringW::GetCacher()->GetCacheHitCount();
1326 xy_fw_info
->xy_fw_string_w
.query_count
= XyFwStringW::GetCacher()->GetQueryCount();
1328 xy_fw_info
->xy_fw_grouped_draw_items_hash_key
.cur_item_num
= XyFwGroupedDrawItemsHashKey::GetCacher()->GetCurItemNum();
1329 xy_fw_info
->xy_fw_grouped_draw_items_hash_key
.hit_count
= XyFwGroupedDrawItemsHashKey::GetCacher()->GetCacheHitCount();
1330 xy_fw_info
->xy_fw_grouped_draw_items_hash_key
.query_count
= XyFwGroupedDrawItemsHashKey::GetCacher()->GetQueryCount();
1335 STDMETHODIMP
CDirectVobSubFilter::get_MediaFPS(bool* fEnabled
, double* fps
)
1337 HRESULT hr
= CDirectVobSub::get_MediaFPS(fEnabled
, fps
);
1339 CComQIPtr
<IMediaSeeking
> pMS
= m_pGraph
;
1341 if(pMS
&& SUCCEEDED(pMS
->GetRate(&rate
)))
1343 m_MediaFPS
= rate
* m_fps
;
1344 if(fps
) *fps
= m_MediaFPS
;
1350 STDMETHODIMP
CDirectVobSubFilter::put_MediaFPS(bool fEnabled
, double fps
)
1352 HRESULT hr
= CDirectVobSub::put_MediaFPS(fEnabled
, fps
);
1354 CComQIPtr
<IMediaSeeking
> pMS
= m_pGraph
;
1359 hr
= pMS
->SetRate(m_fMediaFPSEnabled
? m_MediaFPS
/ m_fps
: 1.0);
1363 if(SUCCEEDED(pMS
->GetRate(&dRate
)))
1364 m_MediaFPS
= dRate
* m_fps
;
1370 STDMETHODIMP
CDirectVobSubFilter::get_ZoomRect(NORMALIZEDRECT
* rect
)
1375 STDMETHODIMP
CDirectVobSubFilter::put_ZoomRect(NORMALIZEDRECT
* rect
)
1382 STDMETHODIMP
CDirectVobSubFilter::put_TextSettings(STSStyle
* pDefStyle
)
1384 HRESULT hr
= CDirectVobSub::put_TextSettings(pDefStyle
);
1388 //DbgLog((LOG_TRACE, 3, "%d %s:UpdateSubtitle(true)", __LINE__, __FUNCTION__));
1389 //UpdateSubtitle(true);
1390 UpdateSubtitle(false);
1396 STDMETHODIMP
CDirectVobSubFilter::put_AspectRatioSettings(CSimpleTextSubtitle::EPARCompensationType
* ePARCompensationType
)
1398 HRESULT hr
= CDirectVobSub::put_AspectRatioSettings(ePARCompensationType
);
1402 //DbgLog((LOG_TRACE, 3, "%d %s:UpdateSubtitle(true)", __LINE__, __FUNCTION__));
1403 //UpdateSubtitle(true);
1404 UpdateSubtitle(false);
1410 // IDirectVobSubFilterColor
1412 STDMETHODIMP
CDirectVobSubFilter::HasConfigDialog(int iSelected
)
1415 if(FAILED(get_LanguageCount(&nLangs
))) return E_FAIL
;
1417 // TODO: temporally disabled since we don't have a new textsub/vobsub editor dlg for dvs yet
1418 // return(nLangs >= 0 && iSelected < nLangs ? S_OK : E_FAIL);
1421 STDMETHODIMP
CDirectVobSubFilter::ShowConfigDialog(int iSelected
, HWND hWndParent
)
1423 // TODO: temporally disabled since we don't have a new textsub/vobsub editor dlg for dvs yet
1427 ///////////////////////////////////////////////////////////////////////////
1429 CDirectVobSubFilter2::CDirectVobSubFilter2(LPUNKNOWN punk
, HRESULT
* phr
, const GUID
& clsid
) :
1430 CDirectVobSubFilter(punk
, phr
, clsid
)
1434 HRESULT
CDirectVobSubFilter2::CheckConnect(PIN_DIRECTION dir
, IPin
* pPin
)
1437 if(FAILED(pPin
->QueryPinInfo(&pi
))) return E_FAIL
;
1439 if(CComQIPtr
<IDirectVobSub
>(pi
.pFilter
)) return E_FAIL
;
1441 if(dir
== PINDIR_INPUT
)
1444 if(SUCCEEDED(pi
.pFilter
->QueryFilterInfo(&fi
))
1445 && !wcsnicmp(fi
.achName
, L
"Overlay Mixer", 13))
1452 return __super::CheckConnect(dir
, pPin
);
1455 HRESULT
CDirectVobSubFilter2::JoinFilterGraph(IFilterGraph
* pGraph
, LPCWSTR pName
)
1457 XY_AUTO_TIMING(_T("CDirectVobSubFilter2::JoinFilterGraph"));
1460 BeginEnumFilters(pGraph
, pEF
, pBF
)
1462 if(pBF
!= (IBaseFilter
*)this && CComQIPtr
<IDirectVobSub
>(pBF
))
1467 // don't look... we will do some serious graph hacking again...
1469 // we will add dvs2 to the filter graph cache
1470 // - if the main app has already added some kind of renderer or overlay mixer (anything which accepts video on its input)
1472 // - if we have a reason to auto-load (we don't want to make any trouble when there is no need :)
1474 // This whole workaround is needed because the video stream will always be connected
1475 // to the pre-added filters first, no matter how high merit we have.
1479 BeginEnumFilters(pGraph
, pEF
, pBF
)
1481 if(CComQIPtr
<IDirectVobSub
>(pBF
))
1484 CComPtr
<IPin
> pInPin
= GetFirstPin(pBF
, PINDIR_INPUT
);
1485 CComPtr
<IPin
> pOutPin
= GetFirstPin(pBF
, PINDIR_OUTPUT
);
1491 if(pInPin
&& SUCCEEDED(pInPin
->ConnectedTo(&pPin
))
1492 || pOutPin
&& SUCCEEDED(pOutPin
->ConnectedTo(&pPin
)))
1495 if(pOutPin
&& GetFilterName(pBF
) == _T("Overlay Mixer"))
1498 bool fVideoInputPin
= false;
1502 BITMAPINFOHEADER bih
= {sizeof(BITMAPINFOHEADER
), 384, 288, 1, 16, '2YUY', 384*288*2, 0, 0, 0, 0};
1505 cmt
.majortype
= MEDIATYPE_Video
;
1506 cmt
.subtype
= MEDIASUBTYPE_YUY2
;
1507 cmt
.formattype
= FORMAT_VideoInfo
;
1509 cmt
.bFixedSizeSamples
= TRUE
;
1510 cmt
.bTemporalCompression
= TRUE
;
1511 cmt
.lSampleSize
= 384*288*2;
1512 VIDEOINFOHEADER
* vih
= (VIDEOINFOHEADER
*)cmt
.AllocFormatBuffer(sizeof(VIDEOINFOHEADER
));
1513 memset(vih
, 0, sizeof(VIDEOINFOHEADER
));
1514 memcpy(&vih
->bmiHeader
, &bih
, sizeof(bih
));
1515 vih
->AvgTimePerFrame
= 400000;
1517 if(SUCCEEDED(pInPin
->QueryAccept(&cmt
)))
1519 fVideoInputPin
= true;
1523 VIDEOINFOHEADER2
* vih2
= (VIDEOINFOHEADER2
*)cmt
.AllocFormatBuffer(sizeof(VIDEOINFOHEADER2
));
1524 memset(vih2
, 0, sizeof(VIDEOINFOHEADER2
));
1525 memcpy(&vih2
->bmiHeader
, &bih
, sizeof(bih
));
1526 vih2
->AvgTimePerFrame
= 400000;
1527 vih2
->dwPictAspectRatioX
= 384;
1528 vih2
->dwPictAspectRatioY
= 288;
1530 if(SUCCEEDED(pInPin
->QueryAccept(&cmt
)))
1532 fVideoInputPin
= true;
1540 CComPtr
<IBaseFilter
> pDVS
;
1541 if(ShouldWeAutoload(pGraph
) && SUCCEEDED(pDVS
.CoCreateInstance(__uuidof(CDirectVobSubFilter2
))))
1543 CComQIPtr
<IDirectVobSub2
>(pDVS
)->put_Forced(true);
1544 CComQIPtr
<IGraphConfig
>(pGraph
)->AddFilterToCache(pDVS
);
1557 return __super::JoinFilterGraph(pGraph
, pName
);
1560 HRESULT
CDirectVobSubFilter2::CheckInputType(const CMediaType
* mtIn
)
1562 XY_AUTO_TIMING(_T("CDirectVobSubFilter2::CheckInputType"));
1563 HRESULT hr
= __super::CheckInputType(mtIn
);
1565 if(FAILED(hr
) || m_pInput
->IsConnected()) return hr
;
1567 if(!ShouldWeAutoload(m_pGraph
)) return VFW_E_TYPE_NOT_ACCEPTED
;
1569 GetRidOfInternalScriptRenderer();
1574 bool CDirectVobSubFilter2::ShouldWeAutoload(IFilterGraph
* pGraph
)
1576 XY_AUTO_TIMING(_T("CDirectVobSubFilter2::ShouldWeAutoload"));
1577 TCHAR blacklistedapps
[][32] =
1579 _T("WM8EUTIL."), // wmp8 encoder's dummy renderer releases the outputted media sample after calling Receive on its input pin (yes, even when dvobsub isn't registered at all)
1580 _T("explorer."), // as some users reported thumbnail preview loads dvobsub, I've never experienced this yet...
1581 _T("producer."), // this is real's producer
1582 _T("GoogleDesktopIndex."), // Google Desktop
1583 _T("GoogleDesktopDisplay."), // Google Desktop
1584 _T("GoogleDesktopCrawl."), // Google Desktop
1587 for(int i
= 0; i
< countof(blacklistedapps
); i
++)
1589 if(theApp
.m_AppName
.Find(blacklistedapps
[i
]) >= 0)
1594 bool m_fExternalLoad
, m_fWebLoad
, m_fEmbeddedLoad
;
1595 get_LoadSettings(&level
, &m_fExternalLoad
, &m_fWebLoad
, &m_fEmbeddedLoad
);
1597 if(level
< 0 || level
>= 2) return(false);
1602 fRet
= m_fExternalLoad
= m_fWebLoad
= m_fEmbeddedLoad
= true;
1604 // find text stream on known splitters
1606 if(!fRet
&& m_fEmbeddedLoad
)
1608 CComPtr
<IBaseFilter
> pBF
;
1609 if((pBF
= FindFilter(CLSID_OggSplitter
, pGraph
)) || (pBF
= FindFilter(CLSID_AviSplitter
, pGraph
))
1610 || (pBF
= FindFilter(L
"{34293064-02F2-41D5-9D75-CC5967ACA1AB}", pGraph
)) // matroska demux
1611 || (pBF
= FindFilter(L
"{0A68C3B5-9164-4a54-AFAF-995B2FF0E0D4}", pGraph
)) // matroska source
1612 || (pBF
= FindFilter(L
"{149D2E01-C32E-4939-80F6-C07B81015A7A}", pGraph
)) // matroska splitter
1613 || (pBF
= FindFilter(L
"{55DA30FC-F16B-49fc-BAA5-AE59FC65F82D}", pGraph
)) // Haali Media Splitter
1614 || (pBF
= FindFilter(L
"{564FD788-86C9-4444-971E-CC4A243DA150}", pGraph
)) // Haali Media Splitter (AR)
1615 || (pBF
= FindFilter(L
"{8F43B7D9-9D6B-4F48-BE18-4D787C795EEA}", pGraph
)) // Haali Simple Media Splitter
1616 || (pBF
= FindFilter(L
"{52B63861-DC93-11CE-A099-00AA00479A58}", pGraph
)) // 3ivx splitter
1617 || (pBF
= FindFilter(L
"{6D3688CE-3E9D-42F4-92CA-8A11119D25CD}", pGraph
)) // our ogg source
1618 || (pBF
= FindFilter(L
"{9FF48807-E133-40AA-826F-9B2959E5232D}", pGraph
)) // our ogg splitter
1619 || (pBF
= FindFilter(L
"{803E8280-F3CE-4201-982C-8CD8FB512004}", pGraph
)) // dsm source
1620 || (pBF
= FindFilter(L
"{0912B4DD-A30A-4568-B590-7179EBB420EC}", pGraph
)) // dsm splitter
1621 || (pBF
= FindFilter(L
"{3CCC052E-BDEE-408a-BEA7-90914EF2964B}", pGraph
)) // mp4 source
1622 || (pBF
= FindFilter(L
"{61F47056-E400-43d3-AF1E-AB7DFFD4C4AD}", pGraph
)) // mp4 splitter
1623 || (pBF
= FindFilter(L
"{171252A0-8820-4AFE-9DF8-5C92B2D66B04}", pGraph
)) // LAV splitter
1624 || (pBF
= FindFilter(L
"{B98D13E7-55DB-4385-A33D-09FD1BA26338}", pGraph
)) // LAV Splitter Source
1625 || (pBF
= FindFilter(L
"{E436EBB5-524F-11CE-9F53-0020AF0BA770}", pGraph
)) // Solveig matroska splitter
1626 || (pBF
= FindFilter(L
"{1365BE7A-C86A-473C-9A41-C0A6E82C9FA3}", pGraph
)) // MPC-HC MPEG PS/TS/PVA source
1627 || (pBF
= FindFilter(L
"{DC257063-045F-4BE2-BD5B-E12279C464F0}", pGraph
)) // MPC-HC MPEG splitter
1628 || (pBF
= FindFilter(L
"{529A00DB-0C43-4f5b-8EF2-05004CBE0C6F}", pGraph
)) // AV splitter
1629 || (pBF
= FindFilter(L
"{D8980E15-E1F6-4916-A10F-D7EB4E9E10B8}", pGraph
)) // AV source
1632 BeginEnumPins(pBF
, pEP
, pPin
)
1634 BeginEnumMediaTypes(pPin
, pEM
, pmt
)
1636 if(pmt
->majortype
== MEDIATYPE_Text
|| pmt
->majortype
== MEDIATYPE_Subtitle
)
1642 EndEnumMediaTypes(pmt
)
1653 BeginEnumFilters(pGraph
, pEF
, pBF
)
1655 if(CComQIPtr
<IFileSourceFilter
> pFSF
= pBF
)
1657 LPOLESTR fnw
= NULL
;
1658 if(!pFSF
|| FAILED(pFSF
->GetCurFile(&fnw
, NULL
)) || !fnw
)
1667 if((m_fExternalLoad
|| m_fWebLoad
) && (m_fWebLoad
|| !(wcsstr(fn
, L
"http://") || wcsstr(fn
, L
"mms://"))))
1669 bool fTemp
= m_fHideSubtitles
;
1670 fRet
= !fn
.IsEmpty() && SUCCEEDED(put_FileName((LPWSTR
)(LPCWSTR
)fn
))
1671 || SUCCEEDED(put_FileName(L
"c:\\tmp.srt"))
1673 if(fTemp
) m_fHideSubtitles
= true;
1679 void CDirectVobSubFilter2::GetRidOfInternalScriptRenderer()
1681 while(CComPtr
<IBaseFilter
> pBF
= FindFilter(L
"{48025243-2D39-11CE-875D-00608CB78066}", m_pGraph
))
1683 BeginEnumPins(pBF
, pEP
, pPin
)
1686 CComPtr
<IPin
> pPinTo
;
1688 if(SUCCEEDED(pPin
->QueryDirection(&dir
)) && dir
== PINDIR_INPUT
1689 && SUCCEEDED(pPin
->ConnectedTo(&pPinTo
)))
1691 m_pGraph
->Disconnect(pPinTo
);
1692 m_pGraph
->Disconnect(pPin
);
1693 m_pGraph
->ConnectDirect(pPinTo
, GetPin(2 + m_pTextInput
.GetCount()-1), NULL
);
1698 if(FAILED(m_pGraph
->RemoveFilter(pBF
)))
1703 ///////////////////////////////////////////////////////////////////////////////
1705 bool CDirectVobSubFilter::Open()
1707 AMTRACE((TEXT(__FUNCTION__
),0));
1708 XY_AUTO_TIMING(TEXT("CDirectVobSubFilter::Open"));
1710 AFX_MANAGE_STATE(AfxGetStaticModuleState());
1712 CAutoLock
cAutolock(&m_csQueueLock
);
1714 m_pSubStreams
.RemoveAll();
1715 m_fIsSubStreamEmbeded
.RemoveAll();
1717 m_frd
.files
.RemoveAll();
1719 CAtlArray
<CString
> paths
;
1721 for(int i
= 0; i
< 10; i
++)
1724 tmp
.Format(IDS_RP_PATH
, i
);
1725 CString path
= theApp
.GetProfileString(ResStr(IDS_R_DEFTEXTPATHES
), tmp
);
1726 if(!path
.IsEmpty()) paths
.Add(path
);
1729 CAtlArray
<SubFile
> ret
;
1730 GetSubFileNames(m_FileName
, paths
, m_xy_str_opt
[DirectVobSubXyOptions::STRING_LOAD_EXT_LIST
], ret
);
1732 for(size_t i
= 0; i
< ret
.GetCount(); i
++)
1734 if(m_frd
.files
.Find(ret
[i
].full_file_name
))
1737 CComPtr
<ISubStream
> pSubStream
;
1741 // CAutoTiming t(TEXT("CRenderedTextSubtitle::Open"), 0);
1742 XY_AUTO_TIMING(TEXT("CRenderedTextSubtitle::Open"));
1743 CAutoPtr
<CRenderedTextSubtitle
> pRTS(new CRenderedTextSubtitle(&m_csSubLock
));
1744 if(pRTS
&& pRTS
->Open(ret
[i
].full_file_name
, DEFAULT_CHARSET
) && pRTS
->GetStreamCount() > 0)
1746 pSubStream
= pRTS
.Detach();
1747 m_frd
.files
.AddTail(ret
[i
].full_file_name
+ _T(".style"));
1753 CAutoTiming
t(TEXT("CVobSubFile::Open"), 0);
1754 CAutoPtr
<CVobSubFile
> pVSF(new CVobSubFile(&m_csSubLock
));
1755 if(pVSF
&& pVSF
->Open(ret
[i
].full_file_name
) && pVSF
->GetStreamCount() > 0)
1757 pSubStream
= pVSF
.Detach();
1758 m_frd
.files
.AddTail(ret
[i
].full_file_name
.Left(ret
[i
].full_file_name
.GetLength()-4) + _T(".sub"));
1764 CAutoTiming
t(TEXT("ssf::CRenderer::Open"), 0);
1765 CAutoPtr
<ssf::CRenderer
> pSSF(new ssf::CRenderer(&m_csSubLock
));
1766 if(pSSF
&& pSSF
->Open(ret
[i
].full_file_name
) && pSSF
->GetStreamCount() > 0)
1768 pSubStream
= pSSF
.Detach();
1774 m_pSubStreams
.AddTail(pSubStream
);
1775 m_fIsSubStreamEmbeded
.AddTail(false);
1776 m_frd
.files
.AddTail(ret
[i
].full_file_name
);
1780 for(size_t i
= 0; i
< m_pTextInput
.GetCount(); i
++)
1782 if(m_pTextInput
[i
]->IsConnected())
1784 m_pSubStreams
.AddTail(m_pTextInput
[i
]->GetSubStream());
1785 m_fIsSubStreamEmbeded
.AddTail(true);
1789 if(S_FALSE
== put_SelectedLanguage(FindPreferedLanguage()))
1790 UpdateSubtitle(false); // make sure pSubPicProvider of our queue gets updated even if the stream number hasn't changed
1792 m_frd
.RefreshEvent
.Set();
1794 return(m_pSubStreams
.GetCount() > 0);
1797 void CDirectVobSubFilter::UpdateSubtitle(bool fApplyDefStyle
)
1799 CAutoLock
cAutolock(&m_csQueueLock
);
1801 if(!m_simple_provider
) return;
1803 InvalidateSubtitle();
1805 CComPtr
<ISubStream
> pSubStream
;
1807 if(!m_fHideSubtitles
)
1809 int i
= m_iSelectedLanguage
;
1811 for(POSITION pos
= m_pSubStreams
.GetHeadPosition(); i
>= 0 && pos
; pSubStream
= NULL
)
1813 pSubStream
= m_pSubStreams
.GetNext(pos
);
1815 if(i
< pSubStream
->GetStreamCount())
1817 CAutoLock
cAutoLock(&m_csSubLock
);
1818 pSubStream
->SetStream(i
);
1822 i
-= pSubStream
->GetStreamCount();
1826 SetSubtitle(pSubStream
, fApplyDefStyle
);
1829 void CDirectVobSubFilter::SetSubtitle(ISubStream
* pSubStream
, bool fApplyDefStyle
)
1831 DbgLog((LOG_TRACE
, 3, "%s(%d): %s", __FILE__
, __LINE__
, __FUNCTION__
));
1832 DbgLog((LOG_TRACE
, 3, "\tpSubStream:%x fApplyDefStyle:%d", pSubStream
, (int)fApplyDefStyle
));
1833 CAutoLock
cAutolock(&m_csQueueLock
);
1836 m_script_selected_yuv
= CSimpleTextSubtitle::YCbCrMatrix_AUTO
;
1837 m_script_selected_range
= CSimpleTextSubtitle::YCbCrRange_AUTO
;
1840 CAutoLock
cAutolock(&m_csSubLock
);
1843 pSubStream
->GetClassID(&clsid
);
1845 if(clsid
== __uuidof(CVobSubFile
))
1847 CVobSubSettings
* pVSS
= dynamic_cast<CVobSubFile
*>(pSubStream
);
1851 pVSS
->SetAlignment(m_fOverridePlacement
, m_PlacementXperc
, m_PlacementYperc
, 1, 1);
1852 pVSS
->m_fOnlyShowForcedSubs
= m_fOnlyShowForcedVobSubs
;
1855 else if(clsid
== __uuidof(CVobSubStream
))
1857 CVobSubSettings
* pVSS
= dynamic_cast<CVobSubStream
*>(pSubStream
);
1861 pVSS
->SetAlignment(m_fOverridePlacement
, m_PlacementXperc
, m_PlacementYperc
, 1, 1);
1862 pVSS
->m_fOnlyShowForcedSubs
= m_fOnlyShowForcedVobSubs
;
1865 else if(clsid
== __uuidof(CRenderedTextSubtitle
))
1867 CRenderedTextSubtitle
* pRTS
= dynamic_cast<CRenderedTextSubtitle
*>(pSubStream
);
1869 if(fApplyDefStyle
|| pRTS
->m_fUsingAutoGeneratedDefaultStyle
)
1871 STSStyle s
= m_defStyle
;
1873 if(m_fOverridePlacement
)
1876 int w
= pRTS
->m_dstScreenSize
.cx
;
1877 int h
= pRTS
->m_dstScreenSize
.cy
;
1878 CRect tmp_rect
= s
.marginRect
.get();
1879 int mw
= w
- tmp_rect
.left
- tmp_rect
.right
;
1880 tmp_rect
.bottom
= h
- MulDiv(h
, m_PlacementYperc
, 100);
1881 tmp_rect
.left
= MulDiv(w
, m_PlacementXperc
, 100) - mw
/2;
1882 tmp_rect
.right
= w
- (tmp_rect
.left
+ mw
);
1883 s
.marginRect
= tmp_rect
;
1886 pRTS
->SetDefaultStyle(s
);
1889 pRTS
->m_ePARCompensationType
= m_ePARCompensationType
;
1890 if (m_CurrentVIH2
.dwPictAspectRatioX
!= 0 && m_CurrentVIH2
.dwPictAspectRatioY
!= 0&& m_CurrentVIH2
.bmiHeader
.biWidth
!= 0 && m_CurrentVIH2
.bmiHeader
.biHeight
!= 0)
1892 pRTS
->m_dPARCompensation
= ((double)abs(m_CurrentVIH2
.bmiHeader
.biWidth
) / (double)abs(m_CurrentVIH2
.bmiHeader
.biHeight
)) /
1893 ((double)abs((long)m_CurrentVIH2
.dwPictAspectRatioX
) / (double)abs((long)m_CurrentVIH2
.dwPictAspectRatioY
));
1898 pRTS
->m_dPARCompensation
= 1.00;
1901 m_script_selected_yuv
= pRTS
->m_eYCbCrMatrix
;
1902 m_script_selected_range
= pRTS
->m_eYCbCrRange
;
1904 playres
= pRTS
->m_dstScreenSize
;
1906 else if(clsid
== __uuidof(CRenderedHdmvSubtitle
))
1908 CRenderedHdmvSubtitle
*sub
= dynamic_cast<CRenderedHdmvSubtitle
*>(pSubStream
);
1909 CompositionObject::ColorType color_type
= CompositionObject::NONE
;
1910 CompositionObject::YuvRangeType range_type
= CompositionObject::RANGE_NONE
;
1911 if ( m_xy_str_opt
[STRING_PGS_YUV_RANGE
].CompareNoCase(_T("PC"))==0 )
1913 range_type
= CompositionObject::RANGE_PC
;
1915 else if ( m_xy_str_opt
[STRING_PGS_YUV_RANGE
].CompareNoCase(_T("TV"))==0 )
1917 range_type
= CompositionObject::RANGE_TV
;
1919 if ( m_xy_str_opt
[STRING_PGS_YUV_MATRIX
].CompareNoCase(_T("BT601"))==0 )
1921 color_type
= CompositionObject::YUV_Rec601
;
1923 else if ( m_xy_str_opt
[STRING_PGS_YUV_MATRIX
].CompareNoCase(_T("BT709"))==0 )
1925 color_type
= CompositionObject::YUV_Rec709
;
1927 sub
->SetYuvType(color_type
, range_type
);
1935 POSITION pos
= m_pSubStreams
.GetHeadPosition();
1938 CComPtr
<ISubStream
> pSubStream2
= m_pSubStreams
.GetNext(pos
);
1940 if(pSubStream
== pSubStream2
)
1942 m_iSelectedLanguage
= i
+ pSubStream2
->GetStream();
1946 i
+= pSubStream2
->GetStreamCount();
1950 m_nSubtitleId
= reinterpret_cast<DWORD_PTR
>(pSubStream
);
1954 XySetSize(SIZE_ASS_PLAY_RESOLUTION
, playres
);
1955 if(m_simple_provider
)
1956 m_simple_provider
->SetSubPicProvider(CComQIPtr
<ISubPicProviderEx
>(pSubStream
));
1959 void CDirectVobSubFilter::InvalidateSubtitle(REFERENCE_TIME rtInvalidate
, DWORD_PTR nSubtitleId
)
1961 CAutoLock
cAutolock(&m_csQueueLock
);
1963 if(m_simple_provider
)
1965 if(nSubtitleId
== -1 || nSubtitleId
== m_nSubtitleId
)
1967 DbgLog((LOG_TRACE
, 3, "InvalidateSubtitle::Invalidate"));
1968 m_simple_provider
->Invalidate(rtInvalidate
);
1973 //////////////////////////////////////////////////////////////////////////////////////////
1975 void CDirectVobSubFilter::AddSubStream(ISubStream
* pSubStream
)
1977 CAutoLock
cAutoLock(&m_csQueueLock
);
1979 POSITION pos
= m_pSubStreams
.Find(pSubStream
);
1982 m_pSubStreams
.AddTail(pSubStream
);
1983 m_fIsSubStreamEmbeded
.AddTail(true);//todo: fix me
1986 int len
= m_pTextInput
.GetCount();
1987 for(size_t i
= 0; i
< m_pTextInput
.GetCount(); i
++)
1988 if(m_pTextInput
[i
]->IsConnected()) len
--;
1993 m_pTextInput
.Add(new CTextInputPin(this, m_pLock
, &m_csSubLock
, &hr
));
1997 void CDirectVobSubFilter::RemoveSubStream(ISubStream
* pSubStream
)
1999 CAutoLock
cAutoLock(&m_csQueueLock
);
2001 POSITION pos
= m_pSubStreams
.GetHeadPosition();
2002 POSITION pos2
= m_fIsSubStreamEmbeded
.GetHeadPosition();
2005 if( m_pSubStreams
.GetAt(pos
)==pSubStream
)
2007 m_pSubStreams
.RemoveAt(pos
);
2008 m_fIsSubStreamEmbeded
.RemoveAt(pos2
);
2013 m_pSubStreams
.GetNext(pos
);
2014 m_fIsSubStreamEmbeded
.GetNext(pos2
);
2019 void CDirectVobSubFilter::Post_EC_OLE_EVENT(CString str
, DWORD_PTR nSubtitleId
)
2021 if(nSubtitleId
!= -1 && nSubtitleId
!= m_nSubtitleId
)
2024 CComQIPtr
<IMediaEventSink
> pMES
= m_pGraph
;
2027 CComBSTR
bstr1("Text"), bstr2(" ");
2030 if(!str
.IsEmpty()) bstr2
= CStringA(str
);
2032 pMES
->Notify(EC_OLE_EVENT
, (LONG_PTR
)bstr1
.Detach(), (LONG_PTR
)bstr2
.Detach());
2035 ////////////////////////////////////////////////////////////////
2037 void CDirectVobSubFilter::SetupFRD(CStringArray
& paths
, CAtlArray
<HANDLE
>& handles
)
2039 CAutoLock
cAutolock(&m_csSubLock
);
2041 for(size_t i
= 2; i
< handles
.GetCount(); i
++)
2043 FindCloseChangeNotification(handles
[i
]);
2047 handles
.RemoveAll();
2049 handles
.Add(m_frd
.EndThreadEvent
);
2050 handles
.Add(m_frd
.RefreshEvent
);
2052 m_frd
.mtime
.SetCount(m_frd
.files
.GetCount());
2054 POSITION pos
= m_frd
.files
.GetHeadPosition();
2055 for(int i
= 0; pos
; i
++)
2057 CString fn
= m_frd
.files
.GetNext(pos
);
2060 if(CFileGetStatus(fn
, status
))
2061 m_frd
.mtime
[i
] = status
.m_mtime
;
2063 fn
.Replace('\\', '/');
2064 fn
= fn
.Left(fn
.ReverseFind('/')+1);
2066 bool fFound
= false;
2068 for(int j
= 0; !fFound
&& j
< paths
.GetCount(); j
++)
2070 if(paths
[j
] == fn
) fFound
= true;
2077 HANDLE h
= FindFirstChangeNotification(fn
, FALSE
, FILE_NOTIFY_CHANGE_LAST_WRITE
);
2078 if(h
!= INVALID_HANDLE_VALUE
) handles
.Add(h
);
2083 DWORD
CDirectVobSubFilter::ThreadProc()
2085 SetThreadPriority(m_hThread
, THREAD_PRIORITY_LOWEST
/*THREAD_PRIORITY_BELOW_NORMAL*/);
2088 CAtlArray
<HANDLE
> handles
;
2090 SetupFRD(paths
, handles
);
2094 DWORD idx
= WaitForMultipleObjects(handles
.GetCount(), handles
.GetData(), FALSE
, INFINITE
);
2096 if(idx
== (WAIT_OBJECT_0
+ 0)) // m_frd.hEndThreadEvent
2100 if(idx
== (WAIT_OBJECT_0
+ 1)) // m_frd.hRefreshEvent
2102 SetupFRD(paths
, handles
);
2104 else if(idx
>= (WAIT_OBJECT_0
+ 2) && idx
< (WAIT_OBJECT_0
+ handles
.GetCount()))
2106 bool fLocked
= true;
2107 IsSubtitleReloaderLocked(&fLocked
);
2108 if(fLocked
) continue;
2110 if(FindNextChangeNotification(handles
[idx
- WAIT_OBJECT_0
]) == FALSE
)
2115 POSITION pos
= m_frd
.files
.GetHeadPosition();
2116 for(int i
= 0; pos
&& j
== 0; i
++)
2118 CString fn
= m_frd
.files
.GetNext(pos
);
2121 if(CFileGetStatus(fn
, status
) && m_frd
.mtime
[i
] != status
.m_mtime
)
2123 for(j
= 0; j
< 10; j
++)
2125 if(FILE* f
= _tfopen(fn
, _T("rb+")))
2142 SetupFRD(paths
, handles
);
2148 POSITION pos
= m_frd
.files
.GetHeadPosition();
2149 for(int i
= 0; pos
; i
++)
2152 if(CFileGetStatus(m_frd
.files
.GetNext(pos
), status
)
2153 && m_frd
.mtime
[i
] != status
.m_mtime
)
2156 SetupFRD(paths
, handles
);
2168 for(size_t i
= 2; i
< handles
.GetCount(); i
++)
2170 FindCloseChangeNotification(handles
[i
]);
2176 void CDirectVobSubFilter::GetInputColorspaces( ColorSpaceId
*preferredOrder
, UINT
*count
)
2178 ColorSpaceOpt
*color_space
=NULL
;
2180 if( XyGetBin(BIN_INPUT_COLOR_FORMAT
, reinterpret_cast<LPVOID
*>(&color_space
), &tempCount
)==S_OK
)
2183 for (int i
=0;i
<tempCount
;i
++)
2185 if(color_space
[i
].selected
)
2187 preferredOrder
[*count
] = color_space
[i
].color_space
;
2194 CBaseVideoFilter::GetInputColorspaces(preferredOrder
, count
);
2196 delete[]color_space
;
2199 void CDirectVobSubFilter::GetOutputColorspaces( ColorSpaceId
*preferredOrder
, UINT
*count
)
2201 ColorSpaceOpt
*color_space
=NULL
;
2203 if( XyGetBin(BIN_OUTPUT_COLOR_FORMAT
, reinterpret_cast<LPVOID
*>(&color_space
), &tempCount
)==S_OK
)
2206 for (int i
=0;i
<tempCount
;i
++)
2208 if(color_space
[i
].selected
)
2210 preferredOrder
[*count
] = color_space
[i
].color_space
;
2217 CBaseVideoFilter::GetInputColorspaces(preferredOrder
, count
);
2219 delete []color_space
;
2222 HRESULT
CDirectVobSubFilter::GetIsEmbeddedSubStream( int iSelected
, bool *fIsEmbedded
)
2224 CAutoLock
cAutolock(&m_csQueueLock
);
2226 HRESULT hr
= E_INVALIDARG
;
2233 *fIsEmbedded
= false;
2235 POSITION pos
= m_pSubStreams
.GetHeadPosition();
2236 POSITION pos2
= m_fIsSubStreamEmbeded
.GetHeadPosition();
2237 while(i
>= 0 && pos
)
2239 CComPtr
<ISubStream
> pSubStream
= m_pSubStreams
.GetNext(pos
);
2240 bool isEmbedded
= m_fIsSubStreamEmbeded
.GetNext(pos2
);
2241 if(i
< pSubStream
->GetStreamCount())
2244 *fIsEmbedded
= isEmbedded
;
2248 i
-= pSubStream
->GetStreamCount();
2253 void CDirectVobSubFilter::SetYuvMatrix()
2255 ColorConvTable::YuvMatrixType yuv_matrix
= ColorConvTable::BT601
;
2256 ColorConvTable::YuvRangeType yuv_range
= ColorConvTable::RANGE_TV
;
2258 if ( m_xy_int_opt
[INT_COLOR_SPACE
]==CDirectVobSub::YuvMatrix_AUTO
)
2260 switch(m_script_selected_yuv
)
2262 case CSimpleTextSubtitle::YCbCrMatrix_BT601
:
2263 yuv_matrix
= ColorConvTable::BT601
;
2265 case CSimpleTextSubtitle::YCbCrMatrix_BT709
:
2266 yuv_matrix
= ColorConvTable::BT709
;
2268 case CSimpleTextSubtitle::YCbCrMatrix_AUTO
:
2270 yuv_matrix
= ColorConvTable::BT601
;
2276 switch(m_xy_int_opt
[INT_COLOR_SPACE
])
2278 case CDirectVobSub::BT_601
:
2279 yuv_matrix
= ColorConvTable::BT601
;
2281 case CDirectVobSub::BT_709
:
2282 yuv_matrix
= ColorConvTable::BT709
;
2284 case CDirectVobSub::GUESS
:
2286 yuv_matrix
= (m_w
> m_bt601Width
|| m_h
> m_bt601Height
) ? ColorConvTable::BT709
: ColorConvTable::BT601
;
2291 if( m_xy_int_opt
[INT_YUV_RANGE
]==CDirectVobSub::YuvRange_Auto
)
2293 switch(m_script_selected_range
)
2295 case CSimpleTextSubtitle::YCbCrRange_PC
:
2296 yuv_range
= ColorConvTable::RANGE_PC
;
2298 case CSimpleTextSubtitle::YCbCrRange_TV
:
2299 yuv_range
= ColorConvTable::RANGE_TV
;
2301 case CSimpleTextSubtitle::YCbCrRange_AUTO
:
2303 yuv_range
= ColorConvTable::RANGE_TV
;
2309 switch(m_xy_int_opt
[INT_YUV_RANGE
])
2311 case CDirectVobSub::YuvRange_TV
:
2312 yuv_range
= ColorConvTable::RANGE_TV
;
2314 case CDirectVobSub::YuvRange_PC
:
2315 yuv_range
= ColorConvTable::RANGE_PC
;
2317 case CDirectVobSub::YuvRange_Auto
:
2318 yuv_range
= ColorConvTable::RANGE_TV
;
2323 ColorConvTable::SetDefaultConvType(yuv_matrix
, yuv_range
);
2328 STDMETHODIMP
CDirectVobSubFilter::XySetBool( int field
, bool value
)
2330 CAutoLock
cAutolock(&m_csQueueLock
);
2331 HRESULT hr
= CDirectVobSub::XySetBool(field
, value
);
2338 case DirectVobSubXyOptions::BOOL_FOLLOW_UPSTREAM_PREFERRED_ORDER
:
2339 m_donot_follow_upstream_preferred_order
= !m_xy_bool_opt
[BOOL_FOLLOW_UPSTREAM_PREFERRED_ORDER
];
2348 STDMETHODIMP
CDirectVobSubFilter::XySetInt( int field
, int value
)
2350 CAutoLock
cAutolock(&m_csQueueLock
);
2351 HRESULT hr
= CDirectVobSub::XySetInt(field
, value
);
2358 case DirectVobSubXyOptions::INT_COLOR_SPACE
:
2359 case DirectVobSubXyOptions::INT_YUV_RANGE
:
2362 case DirectVobSubXyOptions::INT_OVERLAY_CACHE_MAX_ITEM_NUM
:
2363 CacheManager::GetOverlayMruCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2365 case DirectVobSubXyOptions::INT_SCAN_LINE_DATA_CACHE_MAX_ITEM_NUM
:
2366 CacheManager::GetScanLineData2MruCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2368 case DirectVobSubXyOptions::INT_PATH_DATA_CACHE_MAX_ITEM_NUM
:
2369 CacheManager::GetPathDataMruCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2371 case DirectVobSubXyOptions::INT_OVERLAY_NO_BLUR_CACHE_MAX_ITEM_NUM
:
2372 CacheManager::GetOverlayNoBlurMruCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2374 case DirectVobSubXyOptions::INT_BITMAP_MRU_CACHE_ITEM_NUM
:
2375 CacheManager::GetBitmapMruCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2377 case DirectVobSubXyOptions::INT_CLIPPER_MRU_CACHE_ITEM_NUM
:
2378 CacheManager::GetClipperAlphaMaskMruCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2380 case DirectVobSubXyOptions::INT_TEXT_INFO_CACHE_ITEM_NUM
:
2381 CacheManager::GetTextInfoCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2383 case DirectVobSubXyOptions::INT_ASS_TAG_LIST_CACHE_ITEM_NUM
:
2384 CacheManager::GetAssTagListMruCache()->SetMaxItemNum(m_xy_int_opt
[field
]);
2386 case DirectVobSubXyOptions::INT_SUBPIXEL_POS_LEVEL
:
2387 SubpixelPositionControler::GetGlobalControler().SetSubpixelLevel( static_cast<SubpixelPositionControler::SUBPIXEL_LEVEL
>(m_xy_int_opt
[field
]) );