OSDN Git Service

fix video size.
[qtheora/main.git] / Lib / QDecoder / QMediaType.h
1 // QMediaType.h
2 // 2009/06/01
3
4 #pragma once
5
6 /* */
7
8 #ifndef MAKEFOURCC
9 #define MAKEFOURCC(ch0, ch1, ch2, ch3)                                \
10             ((DWORD)(BYTE)(ch0)        | ((DWORD)(BYTE)(ch1) <<  8) | \
11             ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
12 #endif /* defined(MAKEFOURCC) */
13
14 /* */
15
16 // QMediaType
17 struct QMediaType : public AM_MEDIA_TYPE {
18
19         QMediaType()
20         {
21                 memset(this, 0, sizeof(QMediaType));
22         }
23
24         ~QMediaType()
25         {
26                 SafeRelease();
27         }
28
29         void SafeRelease()
30         {
31                 if (pUnk != 0) {
32                         pUnk->Release();
33                         pUnk = 0;
34                 }
35
36                 if (pbFormat != 0) {
37                         CoTaskMemFree(pbFormat);
38                         pbFormat = 0;
39                 }
40
41                 memset(this, 0, sizeof(QMediaType));
42         }
43
44         void Assign(const AM_MEDIA_TYPE* p)
45         {
46                 SafeRelease();
47
48                 if (p != 0) {
49                         Copy(this, p);
50                 }
51         }
52
53         static bool Copy(AM_MEDIA_TYPE* d, const AM_MEDIA_TYPE* p)
54         {
55                 memcpy(d, p, sizeof(AM_MEDIA_TYPE));
56
57                 if (p->pbFormat != 0) {
58                         BYTE* pb = static_cast<BYTE*>(CoTaskMemAlloc(p->cbFormat));
59                         if (pb == 0) {
60                                 return false;
61                         }
62
63                         memcpy(pb, p->pbFormat, p->cbFormat);
64
65                         d->pbFormat = pb;
66                 }
67
68                 if (p->pUnk != 0) {
69                         p->pUnk->Release();
70                 }
71
72                 return true;
73         }
74
75         static AM_MEDIA_TYPE* CopyFrom(const AM_MEDIA_TYPE* p)
76         {
77                 if (p == 0) {
78                         return 0;
79                 }
80
81                 AM_MEDIA_TYPE* d = static_cast<AM_MEDIA_TYPE*>(CoTaskMemAlloc(
82                         sizeof(AM_MEDIA_TYPE)));
83                 if (d == 0) {
84                         return 0;
85                 }
86
87                 if (!Copy(d, p)) {
88                         CoTaskMemFree(d);
89                         return 0;
90                 }
91
92                 return d;
93         }
94
95         static void Free(AM_MEDIA_TYPE* p)
96         {
97                 if (p == 0) {
98                         return;
99                 }
100
101                 if (p->pUnk != 0) {
102                         p->pUnk->Release();
103                 }
104
105                 if (p->pbFormat != 0) {
106                         CoTaskMemFree(p->pbFormat);
107                 }
108
109                 CoTaskMemFree(p);
110         }
111
112         /* */
113
114         void SetFormat(const void* pv, SIZE_T cb)
115         {
116                 if (pbFormat != 0) {
117                         CoTaskMemFree(pbFormat);
118
119                         pbFormat = 0;
120                         cbFormat = 0;
121                 }
122
123                 BYTE* pb = static_cast<BYTE*>(CoTaskMemAlloc(cb));
124                 if (pb == 0) {
125                         return;
126                 }
127
128                 memcpy(pb, pv, cb);
129
130                 cbFormat = cb;
131                 pbFormat = pb;
132         }
133
134         /* */
135
136         enum {
137                 VID_YUY2,
138                 VID_YV12,
139
140                 VID_RGB32,
141                 VID_RGB24,
142
143                 VID_Count
144         };
145
146         void SetVideo(INT32 id, const QT_Format_t* fmt, INT64 rate)
147         {
148                 majortype = MEDIATYPE_Video;
149
150                 bFixedSizeSamples    = TRUE;
151                 bTemporalCompression = FALSE;
152
153                 formattype = FORMAT_VideoInfo2;
154
155                 VIDEOINFOHEADER2 v    = { 0 };
156                 BITMAPINFOHEADER* bmi = &(v.bmiHeader);
157
158                 v.AvgTimePerFrame = rate;
159
160                 INT32 cx = fmt->PW;
161                 INT32 cy = fmt->PH;
162
163                 INT32 g = gcd(cx, cy);
164
165                 v.dwPictAspectRatioX = cx / g;
166                 v.dwPictAspectRatioY = cy / g;
167
168                 bmi->biSize = sizeof(BITMAPINFOHEADER);
169
170                 bmi->biWidth  = cx;
171                 bmi->biHeight = -cy;
172
173                 bmi->biPlanes = 1;
174
175                 switch (id) {
176                 case VID_YUY2:
177                         subtype     = MEDIASUBTYPE_YUY2;
178                         lSampleSize = 2 * cx * cy;
179
180                         bmi->biBitCount    = 16;
181                         bmi->biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
182                         break;
183
184                 case VID_YV12:
185                         subtype     = MEDIASUBTYPE_YV12;
186                         lSampleSize = cx * cy + (cx * cy) / 2;
187
188                         bmi->biBitCount    = 12;
189                         bmi->biCompression = MAKEFOURCC('Y', 'V', '1', '2');
190                         break;
191
192                 case VID_RGB32:
193                         subtype     = MEDIASUBTYPE_RGB32;
194                         lSampleSize = (cx * cy) * 4;
195
196                         bmi->biBitCount    = 32;
197                         bmi->biCompression = BI_RGB;
198                         break;
199
200                 case VID_RGB24:
201                         subtype     = MEDIASUBTYPE_RGB24;
202                         lSampleSize = (cx * cy) * 3;
203
204                         bmi->biBitCount    = 24;
205                         bmi->biCompression = BI_RGB;
206                         break;
207
208                 default:
209                         return;
210                 }
211
212                 bmi->biSizeImage = lSampleSize;
213
214                 SetFormat(&v, sizeof(v));
215         }
216
217         void SetAudio(
218                 INT32 channels,
219                 INT32 samplingRate)
220         {
221                 majortype = MEDIATYPE_Audio;
222                 subtype   = MEDIASUBTYPE_PCM;
223
224                 bFixedSizeSamples    = TRUE;
225                 bTemporalCompression = FALSE;
226
227                 formattype = FORMAT_WaveFormatEx;
228
229                 lSampleSize = channels * 2 * samplingRate;
230
231                 WAVEFORMATEX wfx = { 0 };
232
233                 wfx.wFormatTag      = WAVE_FORMAT_PCM;
234                 wfx.nChannels       = channels;
235                 wfx.nSamplesPerSec  = samplingRate;
236                 wfx.nAvgBytesPerSec = channels * 2 * samplingRate;
237                 wfx.nBlockAlign     = channels * 2;
238                 wfx.wBitsPerSample  = 16;
239                 wfx.cbSize          = 0;
240
241                 SetFormat(&wfx, sizeof(wfx));
242         }
243
244         /* */
245
246 private:
247
248         static INT32 gcd(INT32 x, INT32 y)
249         {
250                 while (y != 0) {
251                         INT32 t = x % y;
252                         x = y;
253                         y = t;
254                 }
255                 return x;
256         }
257
258         /* */
259
260 }; // QMediaType
261
262 /* */
263
264 // QEnumMediaTypes
265 class ATL_NO_VTABLE QEnumMediaTypes :
266         public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>,
267
268         public IEnumMediaTypes {
269
270         ATL::CComCriticalSection m_cs;
271
272         AM_MEDIA_TYPE* m_pStart;
273         AM_MEDIA_TYPE* m_pEnd;
274
275         AM_MEDIA_TYPE* m_p;
276
277         ATL::CComPtr<IUnknown> m_Pin;
278
279 public:
280
281         DECLARE_NOT_AGGREGATABLE(QEnumMediaTypes)
282
283         DECLARE_PROTECT_FINAL_CONSTRUCT()
284
285         BEGIN_COM_MAP(QEnumMediaTypes)
286                 COM_INTERFACE_ENTRY(IEnumMediaTypes)
287         END_COM_MAP()
288
289 public:
290
291         QEnumMediaTypes() : m_pStart(0), m_pEnd(0), m_p(0)
292         {
293         }
294
295         ~QEnumMediaTypes()
296         {
297         }
298
299         HRESULT FinalConstruct()
300         {
301                 ATLTRACE("QEnumMediaTypes::FinalConstruct()\n");
302
303                 HRESULT hRslt = m_cs.Init();
304                 if (FAILED(hRslt)) {
305                         return hRslt;
306                 }
307
308                 return S_OK;
309         }
310
311         void FinalRelease()
312         {
313                 ATLTRACE("QEnumMediaTypes::FinalRelease()\n");
314
315                 m_Pin.Release();
316         }
317
318         void Init(AM_MEDIA_TYPE* s, AM_MEDIA_TYPE* e, IUnknown* p)
319         {
320                 m_pStart = s;
321                 m_pEnd   = e;
322
323                 m_p = m_pStart;
324
325                 m_Pin = p;
326         }
327
328         /* */
329
330         static HRESULT Create(AM_MEDIA_TYPE* s, AM_MEDIA_TYPE* e, IUnknown* p, IEnumMediaTypes** ppEnum)
331         {
332                 if (ppEnum == 0) {
333                         return E_INVALIDARG;
334                 }
335
336                 ATL::CComObject<QEnumMediaTypes>* obj = 0;
337
338                 HRESULT hRslt = ATL::CComObject<QEnumMediaTypes>::CreateInstance(&obj);
339                 if (FAILED(hRslt)) {
340                         return hRslt;
341                 }
342
343                 obj->Init(s, e, p);
344
345                 hRslt = obj->QueryInterface(ppEnum);
346                 if (FAILED(hRslt)) {
347                         delete obj;
348                         return hRslt;
349                 }
350
351                 return S_OK;
352         }
353
354         /* */
355
356         STDMETHOD(Next)(
357                 ULONG           cMediaTypes,
358                 AM_MEDIA_TYPE** ppMediaTypes,
359                 ULONG*          pcFetched)
360         {
361                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
362
363                 if (ppMediaTypes == 0) {
364                         return E_INVALIDARG;
365                 }
366
367                 if (pcFetched == 0 && cMediaTypes != 1) {
368                         return E_INVALIDARG;
369                 }
370
371                 if (pcFetched != 0) {
372                         *pcFetched = 0;
373                 }
374
375                 ULONG i;
376                 AM_MEDIA_TYPE** pp = ppMediaTypes;
377                 for (i = 0; i < cMediaTypes && m_p < m_pEnd; i++, pp++, m_p++) {
378                         AM_MEDIA_TYPE* mt = QMediaType::CopyFrom(m_p);
379                         if (mt == 0) {
380                                 return E_OUTOFMEMORY;
381                         }
382                         *pp = mt;
383                 }
384
385                 if (pcFetched != 0) {
386                         *pcFetched = i;
387                 }
388
389                 if (i == 0) {
390                         return S_FALSE;
391                 }
392
393                 return S_OK;
394         }
395
396         STDMETHOD(Skip)(
397                 ULONG cMediaTypes)
398         {
399                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
400
401                 m_p += cMediaTypes;
402
403                 if (m_p > m_pEnd) {
404                         m_p = m_pEnd;
405                 }
406
407                 return S_OK;
408         }
409
410
411         STDMETHOD(Reset)(void)
412         {
413                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
414
415                 m_p = m_pStart;
416
417                 return S_OK;
418         }
419
420         STDMETHOD(Clone)( 
421                 IEnumMediaTypes** ppEnum)
422         {
423                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
424
425                 HRESULT hRslt = Create(m_pStart, m_pEnd, m_Pin, ppEnum);
426                 if (FAILED(hRslt)) {
427                         return hRslt;
428                 }
429
430                 return S_OK;
431         }
432
433         /* */
434
435 }; // QEnumMediaTypes
436