Merge with MPC-HC 6d1472b2f18266d92e5bc068667de348c0cd3b3b.
[xy_vsfilter.git] / src / subtitles / SSF.cpp
blob692627221d0857a26b701c7cb5e96c2dfff4a0a3
1 /*
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)
8 * any later version.
9 *
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
20 * TODO:
21 * - fill effect
22 * - outline bkg still very slow
26 #include "stdafx.h"
27 #include <xmmintrin.h>
28 #include <emmintrin.h>
29 #include "SSF.h"
31 namespace ssf
33 CRenderer::CRenderer(CCritSec* pLock)
34 : CSubPicProviderImpl(pLock)
38 CRenderer::~CRenderer()
42 bool CRenderer::Open(CString fn, CString name)
44 m_fn.Empty();
45 m_name.Empty();
46 m_file.Free();
47 m_renderer.Free();
49 if(name.IsEmpty())
51 CString str = fn;
52 str.Replace('\\', '/');
53 name = str.Left(str.ReverseFind('.'));
54 name = name.Mid(name.ReverseFind('/')+1);
55 name = name.Mid(name.ReverseFind('.')+1);
58 try
60 if(Open(FileInputStream(fn), name))
62 m_fn = fn;
63 return true;
66 catch(Exception& e)
68 TRACE(_T("%s\n"), e.ToString());
71 return false;
74 bool CRenderer::Open(InputStream& s, CString name)
76 m_fn.Empty();
77 m_name.Empty();
78 m_file.Free();
79 m_renderer.Free();
81 try
83 m_file.Attach(new SubtitleFile());
84 m_file->Parse(s);
85 m_renderer.Attach(new Renderer());
86 m_name = name;
87 return true;
89 catch(Exception& e)
91 TRACE(_T("%s\n"), e.ToString());
94 return false;
97 void CRenderer::Append(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, LPCWSTR str)
99 if(!m_file) return;
103 m_file->Append(ssf::WCharInputStream(str), (float)rtStart / 10000000, (float)rtStop / 10000000);
105 catch(Exception& e)
107 TRACE(_T("%s\n"), e.ToString());
111 STDMETHODIMP CRenderer::NonDelegatingQueryInterface(REFIID riid, void** ppv)
113 CheckPointer(ppv, E_POINTER);
114 *ppv = NULL;
116 return
117 QI(IPersist)
118 QI(ISubStream)
119 QI(ISubPicProvider)
120 __super::NonDelegatingQueryInterface(riid, ppv);
123 // ISubPicProvider
125 STDMETHODIMP_(POSITION) CRenderer::GetStartPosition(REFERENCE_TIME rt, double fps)
127 size_t k;
128 return m_file && m_file->m_segments.Lookup((float)rt/10000000, k) ? (POSITION)(++k) : NULL;
131 STDMETHODIMP_(POSITION) CRenderer::GetNext(POSITION pos)
133 size_t k = (size_t)pos;
134 return m_file && m_file->m_segments.GetSegment(k) ? (POSITION)(++k) : NULL;
137 STDMETHODIMP_(REFERENCE_TIME) CRenderer::GetStart(POSITION pos, double fps)
139 size_t k = (size_t)pos-1;
140 const SubtitleFile::Segment* s = m_file ? m_file->m_segments.GetSegment(k) : NULL;
141 return s ? (REFERENCE_TIME)(s->m_start*10000000) : 0;
144 STDMETHODIMP_(REFERENCE_TIME) CRenderer::GetStop(POSITION pos, double fps)
146 CheckPointer(m_file, 0);
148 size_t k = (size_t)pos-1;
149 const SubtitleFile::Segment* s = m_file ? m_file->m_segments.GetSegment(k) : NULL;
150 return s ? (REFERENCE_TIME)(s->m_stop*10000000) : 0;
153 STDMETHODIMP_(bool) CRenderer::IsAnimated(POSITION pos)
155 return true;
158 STDMETHODIMP CRenderer::Render(SubPicDesc& spd, REFERENCE_TIME rt, double fps, RECT& bbox)
160 CheckPointer(m_file, E_UNEXPECTED);
161 CheckPointer(m_renderer, E_UNEXPECTED);
163 if(spd.type != MSP_RGB32) return E_INVALIDARG;
165 CAutoLock csAutoLock(m_pLock);
167 CRect bbox2;
168 bbox2.SetRectEmpty();
170 CAutoPtrList<Subtitle> subs;
171 m_file->Lookup((float)rt/10000000, subs);
173 m_renderer->NextSegment(subs);
175 POSITION pos = subs.GetHeadPosition();
176 while(pos)
178 const Subtitle* s = subs.GetNext(pos);
179 const RenderedSubtitle* rs = m_renderer->Lookup(s, CSize(spd.w, spd.h), spd.vidrect);
180 if(rs) bbox2 |= rs->Draw(spd);
183 bbox = bbox2 & CRect(0, 0, spd.w, spd.h);
185 return S_OK;
188 // IPersist
190 STDMETHODIMP CRenderer::GetClassID(CLSID* pClassID)
192 return pClassID ? *pClassID = __uuidof(this), S_OK : E_POINTER;
195 // ISubStream
197 STDMETHODIMP_(int) CRenderer::GetStreamCount()
199 return 1;
202 STDMETHODIMP CRenderer::GetStreamInfo(int iStream, WCHAR** ppName, LCID* pLCID)
204 if(iStream != 0) return E_INVALIDARG;
206 if(ppName)
208 if(!(*ppName = (WCHAR*)CoTaskMemAlloc((m_name.GetLength()+1)*sizeof(WCHAR))))
209 return E_OUTOFMEMORY;
211 wcscpy(*ppName, CStringW(m_name));
214 if(pLCID)
216 *pLCID = 0; // TODO
219 return S_OK;
222 STDMETHODIMP_(int) CRenderer::GetStream()
224 return 0;
227 STDMETHODIMP CRenderer::SetStream(int iStream)
229 return iStream == 0 ? S_OK : E_FAIL;
232 STDMETHODIMP CRenderer::Reload()
234 CAutoLock csAutoLock(m_pLock);
236 return !m_fn.IsEmpty() && Open(m_fn, m_name) ? S_OK : E_FAIL;