OSDN Git Service

74ce286635c17cd0a1fd894c19e7dcdd027b35c8
[qtheora/main.git] / Lib / QDecoder / QReader.h
1 // QReader.h
2 // 2009/06/04
3
4 #pragma once
5
6 #define QV_VORBIS_MAX_FRAME_SIZE 0x10000
7
8 // QReader
9 class QReader {
10
11         QM_Reader_t* m_reader;
12
13         QM_FrameExtractor* m_extra;
14
15         INT64 m_duration;
16
17         INT32 m_vid;
18         INT32 m_aid;
19
20         const QM_Track_t* m_vtrack;
21         const QM_Track_t* m_atrack;
22
23         QTheoraDecoderSetup_t* m_vsetup;
24
25         QTheoraDecoder_t* m_vdecoder;
26
27         QVorbisDecoderSetup_t* m_asetup;
28
29         QVorbisDecoder_t* m_adecoder;
30
31         INT64 m_scale;
32         INT64 m_vrate;
33
34         INT32 m_ascale;
35
36         bool  m_bVideoSeek;
37         bool  m_bAudioSeek;
38
39         bool  m_bVideoEOS;
40         bool  m_bAudioEOS;
41
42         INT64 m_StartPos;
43         INT64 m_EndPos;
44
45 public:
46
47         QReader() :
48                 m_reader(0), m_extra(0),
49                 m_duration(0),
50                 m_vid(0), m_aid(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)
58         {
59         }
60
61         ~QReader()
62         {
63                 QM_ReleaseReader(m_reader);
64                 QM_ReleaseFrameExtractor(m_extra);
65
66                 QT_ReleaseDecoder(m_vdecoder);
67                 QT_ReleaseDecoderSetup(m_vsetup);
68
69                 QV_ReleaseDecoder(m_adecoder);
70                 QV_ReleaseDecoderSetup(m_asetup);
71         }
72
73         /* */
74
75         INT64 GetDuration()
76         {
77                 return m_duration;
78         }
79
80         const QM_Track_t* GetVideoTrack()
81         {
82                 return m_vtrack;
83         }
84
85         const QM_Track_t* GetAudioTrack()
86         {
87                 return m_atrack;
88         }
89
90         /* */
91
92         bool Open(LPCWSTR path)
93         {
94                 m_reader = QM_CreateReader();
95                 if (m_reader == 0) {
96                         return false;
97                 }
98
99                 if (!QM_OpenReader(m_reader, path)) {
100                         return false;
101                 }
102
103                 return true;
104         }
105
106         bool Setup()
107         {
108                 INT64 scale = QM_GetTimeCodeScale(m_reader);
109 #if 0
110                 if (scale != 1000*1000) {
111                         return false;
112                 }
113 #else
114                 // matroska ts -> RT : 1ns -> 100ns
115                 m_scale  = (INT32)(scale / 100);
116                 // 1s / matroska ts
117                 m_ascale = (INT32)(1000*1000*1000 / scale);
118 #endif
119
120                 DOUBLE d = QM_GetDuraion(m_reader);
121                 m_duration = (INT64)(d * m_scale);
122
123                 const QM_Track_t* tracks = QM_GetTracks(m_reader);
124
125                 INT32 c = QM_GetTrackCount(m_reader);
126                 for (INT32 i = 0; i < c; i++) {
127                         const QM_Track_t* track = tracks + i;
128
129                         if (strcmp(track->CodecId, "V_THEORA") == 0) {
130                                 if (m_vid == 0) {
131                                         m_vid = track->TrackNo;
132
133                                         m_vtrack = track;
134                                 }
135
136                         } else if (strcmp(track->CodecId, "A_VORBIS") == 0) {
137                                 if (m_aid == 0) {
138                                         m_aid = track->TrackNo;
139
140                                         m_atrack = track;
141                                 }
142                         }
143                 }
144
145                 if (m_vid > 0) {
146                         m_vsetup = QT_CreateDecoderSetup();
147                         if (m_vsetup == 0) {
148                                 return false;
149                         }
150
151                         if (!QT_SetupDecoderSetupLacing(
152                                 m_vsetup,
153                                 m_vtrack->CodecPrivate,
154                                 m_vtrack->CodecPrivateSize)) {
155                                 return false;
156                         }
157
158                         m_vdecoder = QT_CreateDecoder();
159                         if (m_vdecoder == 0) {
160                                 return false;
161                         }
162
163                         if (!QT_SetupDecoder(m_vdecoder, m_vsetup)) {
164                                 return false;
165                         }
166
167                         m_vrate = m_vtrack->TrackDuration / 100; /* ns -> RT (100ns) */
168                 }
169
170                 if (m_aid > 0) {
171                         m_extra = QM_CreateFrameExtractor();
172                         if (m_extra == 0) {
173                                 return false;
174                         }
175
176                         m_asetup = QV_CreateDecoderSetup();
177                         if (m_asetup == 0) {
178                                 return false;
179                         }
180
181                         if (!QV_SetupDecoderSetupLacing(
182                                 m_asetup,
183                                 m_atrack->CodecPrivate,
184                                 m_atrack->CodecPrivateSize)) {
185                                 return false;
186                         }
187
188                         m_adecoder = QV_CreateDecoder();
189                         if (m_adecoder == 0) {
190                                 return false;
191                         }
192
193                         if (!QV_SetupDecoder(m_adecoder, m_asetup, QV_VORBIS_MAX_FRAME_SIZE)) {
194                                 return false;
195                         }
196                 }
197
198                 m_bVideoSeek = true;
199                 m_bAudioSeek = true;
200
201                 m_bVideoEOS = false;
202                 m_bAudioEOS = false;
203
204                 m_StartPos = 0;
205                 m_EndPos   = -1;
206
207                 return true;
208         }
209
210         /* */
211
212         INT32 Read(
213                 IMemAllocator*   valloc,
214                 IMemInputPin*    vpin,
215                 QImageConverter* image,
216                 IMemAllocator*   aalloc,
217                 IMemInputPin*    apin,
218                 QWaveOutputer*   aout)
219         {
220                 if (m_bVideoEOS && m_bAudioEOS) {
221                         return 0;
222                 }
223
224                 QM_Block_t block = { 0 };
225                 INT32 code = QM_ReadBlock(
226                         m_reader,
227                         &block);
228                 if (code < 0) {
229                         return -1;
230                 }
231                 if (code == 0) {
232                         return 0;
233                 }
234
235                 if (block.TrackNo == m_vid && !m_bVideoEOS) {
236                         INT64 ts = block.ClusterTime + block.TimeDelta;
237
238                         if (m_bVideoSeek) {
239                                 if ((block.Flags & QM_FLAGS_KEYFRAME) == 0) {
240                                         return 1;
241                                 }
242
243                                 m_bVideoSeek = false;
244                         }
245
246                         QT_Output_t output = { 0 };
247                         if (!QT_DecodeFrame(
248                                 m_vdecoder,
249                                 block.Payload,
250                                 block.Size,
251                                 &output)) {
252                                 return -1;
253                         }
254
255                         if (ts < m_StartPos) {
256                                 return 1;
257                         }
258
259                         if (m_EndPos > 0 && ts >= m_EndPos) {
260                                 m_bVideoEOS = true;
261                                 return 1;
262                         }
263
264                         if (valloc == 0 || vpin == 0) {
265                                 return 1;
266                         }
267
268                         REFERENCE_TIME rts = (ts - m_StartPos) * m_scale;
269                         REFERENCE_TIME rte = rts + m_vrate;
270
271                         ATL::CComPtr<IMediaSample> samp;
272                         HRESULT hRslt = valloc->GetBuffer(&samp, &rts, &rte, 0);
273                         if (FAILED(hRslt)) {
274                                 return -1;
275                         }
276
277                         BYTE* pb = 0;
278                         samp->GetPointer(&pb);
279                         if (pb != 0) {
280                                 image->Copy(pb, &output);
281                         }
282
283                         samp->SetTime(&rts, &rte);
284
285                         hRslt = vpin->Receive(samp);
286                         if (FAILED(hRslt)) {
287                                 return -1;
288                         }
289
290                 } else if (block.TrackNo == m_aid && !m_bAudioEOS) {
291                         INT64 ts = block.ClusterTime + block.TimeDelta;
292                         INT32 ss = 0;
293
294                         if (QM_DecodeLacingBlock(m_extra, &block)) {
295                                 for (; ; ) {
296                                         QM_Frame_t frame = { 0 };
297                                         INT32 code = QM_ReadFrame(
298                                                 m_extra,
299                                                 &frame);
300                                         if (code < 0) {
301                                                 return -1;
302                                         }
303                                         if (code == 0) {
304                                                 break;
305                                         }
306
307                                         /* */
308
309                                         if (m_bAudioSeek) {
310                                                 QV_ResetDecoder(m_adecoder);
311
312                                                 m_bAudioSeek = false;
313                                         }
314
315                                         QV_Output_t output = { 0 };
316                                         if (!QV_DecodeFrame(
317                                                 m_adecoder,
318                                                 frame.Payload,
319                                                 frame.Size,
320                                                 &output)) {
321                                                 return -1;
322                                         }
323
324                                         INT64 t0 = ts + aout->GetTime(ss * m_ascale);
325
326                                         ss += aout->GetSamples(output.Length);
327
328                                         if (t0 < m_StartPos) {
329                                                 continue;
330                                         }
331
332                                         if (m_EndPos > 0 && t0 >= m_EndPos) {
333                                                 m_bAudioEOS = true;
334                                                 return 1;
335                                         }
336
337                                         REFERENCE_TIME rts = (t0 - m_StartPos) * m_scale;
338
339                                         if (output.Length > 0) {
340                                                 QV_Convert_t conv = { 0 };
341                                                 if (!QV_ConvertFrame(
342                                                         m_adecoder,
343                                                         &output,
344                                                         &conv)) {
345                                                         return -1;
346                                                 }
347
348                                                 if (!aout->Output(
349                                                         aalloc,
350                                                         apin,
351                                                         rts,
352                                                         conv.Sample,
353                                                         conv.Samples)) {
354                                                         return -1;
355                                                 }
356                                         }
357                                 }
358                         }
359                 }
360
361                 return 1;
362         }
363
364         /* */
365
366         bool Seek(INT64 pos)
367         {
368                 INT64 ts = pos / m_scale;
369
370                 if (!QM_SeekCluster(m_reader, ts)) {
371                         return false;
372                 }
373
374                 m_bVideoSeek = true,
375                 m_bAudioSeek = true,
376
377                 m_bVideoEOS = false;
378                 m_bAudioEOS = false;
379
380                 m_StartPos = ts;
381                 m_EndPos   = -1;
382
383                 return true;
384         }
385
386         /* */
387
388 }; // QReader
389