6 #define QV_VORBIS_MAX_FRAME_SIZE 0x10000
11 QM_Reader_t* m_reader;
13 QM_FrameExtractor* m_extra;
20 const QM_Track_t* m_vtrack;
21 const QM_Track_t* m_atrack;
23 QTheoraDecoderSetup_t* m_vsetup;
25 QTheoraDecoder_t* m_vdecoder;
27 QVorbisDecoderSetup_t* m_asetup;
29 QVorbisDecoder_t* m_adecoder;
48 m_reader(0), m_extra(0),
51 m_vtrack(0), m_atrack(0),
52 m_vsetup(0), m_vdecoder(0),
53 m_asetup(0), m_adecoder(0),
54 m_scale(10*1000), m_vrate(0), m_ascale(1000),
55 m_bVideoSeek(false), m_bAudioSeek(false),
56 m_bVideoEOS(false), m_bAudioEOS(false),
57 m_StartPos(0), m_EndPos(-1)
63 QM_ReleaseReader(m_reader);
64 QM_ReleaseFrameExtractor(m_extra);
66 QT_ReleaseDecoder(m_vdecoder);
67 QT_ReleaseDecoderSetup(m_vsetup);
69 QV_ReleaseDecoder(m_adecoder);
70 QV_ReleaseDecoderSetup(m_asetup);
80 const QM_Track_t* GetVideoTrack()
85 const QM_Track_t* GetAudioTrack()
92 bool Open(LPCWSTR path)
94 m_reader = QM_CreateReader();
99 if (!QM_OpenReader(m_reader, path)) {
108 INT64 scale = QM_GetTimeCodeScale(m_reader);
110 if (scale != 1000*1000) {
114 // matroska ts -> RT : 1ns -> 100ns
115 m_scale = (INT32)(scale / 100);
117 m_ascale = (INT32)(1000*1000*1000 / scale);
120 DOUBLE d = QM_GetDuraion(m_reader);
121 m_duration = (INT64)(d * m_scale);
123 const QM_Track_t* tracks = QM_GetTracks(m_reader);
125 INT32 c = QM_GetTrackCount(m_reader);
126 for (INT32 i = 0; i < c; i++) {
127 const QM_Track_t* track = tracks + i;
129 if (strcmp(track->CodecId, "V_THEORA") == 0) {
131 m_vid = track->TrackNo;
136 } else if (strcmp(track->CodecId, "A_VORBIS") == 0) {
138 m_aid = track->TrackNo;
146 m_vsetup = QT_CreateDecoderSetup();
151 if (!QT_SetupDecoderSetupLacing(
153 m_vtrack->CodecPrivate,
154 m_vtrack->CodecPrivateSize)) {
158 m_vdecoder = QT_CreateDecoder();
159 if (m_vdecoder == 0) {
163 if (!QT_SetupDecoder(m_vdecoder, m_vsetup)) {
167 m_vrate = m_vtrack->TrackDuration / 100; /* ns -> RT (100ns) */
171 m_extra = QM_CreateFrameExtractor();
176 m_asetup = QV_CreateDecoderSetup();
181 if (!QV_SetupDecoderSetupLacing(
183 m_atrack->CodecPrivate,
184 m_atrack->CodecPrivateSize)) {
188 m_adecoder = QV_CreateDecoder();
189 if (m_adecoder == 0) {
193 if (!QV_SetupDecoder(m_adecoder, m_asetup, QV_VORBIS_MAX_FRAME_SIZE)) {
213 IMemAllocator* valloc,
215 QImageConverter* image,
216 IMemAllocator* aalloc,
220 if (m_bVideoEOS && m_bAudioEOS) {
224 QM_Block_t block = { 0 };
225 INT32 code = QM_ReadBlock(
235 if (block.TrackNo == m_vid && !m_bVideoEOS) {
236 INT64 ts = block.ClusterTime + block.TimeDelta;
239 if ((block.Flags & QM_FLAGS_KEYFRAME) == 0) {
243 m_bVideoSeek = false;
246 QT_Output_t output = { 0 };
255 if (ts < m_StartPos) {
259 if (m_EndPos > 0 && ts >= m_EndPos) {
264 if (valloc == 0 || vpin == 0) {
268 REFERENCE_TIME rts = (ts - m_StartPos) * m_scale;
269 REFERENCE_TIME rte = rts + m_vrate;
271 ATL::CComPtr<IMediaSample> samp;
272 HRESULT hRslt = valloc->GetBuffer(&samp, &rts, &rte, 0);
278 samp->GetPointer(&pb);
280 image->Copy(pb, &output);
283 samp->SetTime(&rts, &rte);
285 hRslt = vpin->Receive(samp);
290 } else if (block.TrackNo == m_aid && !m_bAudioEOS) {
291 INT64 ts = block.ClusterTime + block.TimeDelta;
294 if (QM_DecodeLacingBlock(m_extra, &block)) {
296 QM_Frame_t frame = { 0 };
297 INT32 code = QM_ReadFrame(
310 QV_ResetDecoder(m_adecoder);
312 m_bAudioSeek = false;
315 QV_Output_t output = { 0 };
324 INT64 t0 = ts + aout->GetTime(ss * m_ascale);
326 ss += aout->GetSamples(output.Length);
328 if (t0 < m_StartPos) {
332 if (m_EndPos > 0 && t0 >= m_EndPos) {
337 REFERENCE_TIME rts = (t0 - m_StartPos) * m_scale;
339 if (output.Length > 0) {
340 QV_Convert_t conv = { 0 };
341 if (!QV_ConvertFrame(
368 INT64 ts = pos / m_scale;
370 if (!QM_SeekCluster(m_reader, ts)) {