1 /*
2 * Copyright 2020 Esme Povirk
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include <stdarg.h>
20
21 #define COBJMACROS
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26
27 #include "wincodecs_private.h"
28
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
32
33 typedef struct {
34 IWICBitmapDecoder IWICBitmapDecoder_iface;
35 LONG ref;
36 CRITICAL_SECTION lock; /* must be held when stream or decoder is accessed */
37 IStream *stream;
38 struct decoder *decoder;
39 struct decoder_info decoder_info;
40 struct decoder_stat file_info;
41 WICDecodeOptions cache_options;
42 } CommonDecoder;
43
impl_from_IWICBitmapDecoder(IWICBitmapDecoder * iface)44 static inline CommonDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
45 {
46 return CONTAINING_RECORD(iface, CommonDecoder, IWICBitmapDecoder_iface);
47 }
48
CommonDecoder_QueryInterface(IWICBitmapDecoder * iface,REFIID iid,void ** ppv)49 static HRESULT WINAPI CommonDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
50 void **ppv)
51 {
52 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
53 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
54
55 if (!ppv) return E_INVALIDARG;
56
57 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
58 {
59 *ppv = &This->IWICBitmapDecoder_iface;
60 }
61 else
62 {
63 *ppv = NULL;
64 return E_NOINTERFACE;
65 }
66
67 IUnknown_AddRef((IUnknown*)*ppv);
68 return S_OK;
69 }
70
CommonDecoder_AddRef(IWICBitmapDecoder * iface)71 static ULONG WINAPI CommonDecoder_AddRef(IWICBitmapDecoder *iface)
72 {
73 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
74 ULONG ref = InterlockedIncrement(&This->ref);
75
76 TRACE("(%p) refcount=%lu\n", iface, ref);
77
78 return ref;
79 }
80
CommonDecoder_Release(IWICBitmapDecoder * iface)81 static ULONG WINAPI CommonDecoder_Release(IWICBitmapDecoder *iface)
82 {
83 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
84 ULONG ref = InterlockedDecrement(&This->ref);
85
86 TRACE("(%p) refcount=%lu\n", iface, ref);
87
88 if (ref == 0)
89 {
90 if (This->stream)
91 IStream_Release(This->stream);
92 This->lock.DebugInfo->Spare[0] = 0;
93 DeleteCriticalSection(&This->lock);
94 decoder_destroy(This->decoder);
95 free(This);
96 }
97
98 return ref;
99 }
100
CommonDecoder_QueryCapability(IWICBitmapDecoder * iface,IStream * stream,DWORD * capability)101 static HRESULT WINAPI CommonDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
102 DWORD *capability)
103 {
104 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
105 HRESULT hr;
106
107 TRACE("(%p,%p,%p)\n", iface, stream, capability);
108
109 if (!stream || !capability) return E_INVALIDARG;
110
111 hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
112 if (hr != S_OK) return hr;
113
114 *capability = (This->file_info.flags & DECODER_FLAGS_CAPABILITY_MASK);
115 return S_OK;
116 }
117
CommonDecoder_Initialize(IWICBitmapDecoder * iface,IStream * pIStream,WICDecodeOptions cacheOptions)118 static HRESULT WINAPI CommonDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
119 WICDecodeOptions cacheOptions)
120 {
121 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
122 HRESULT hr=S_OK;
123
124 TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
125
126 EnterCriticalSection(&This->lock);
127
128 if (This->stream)
129 hr = WINCODEC_ERR_WRONGSTATE;
130
131 if (SUCCEEDED(hr))
132 hr = decoder_initialize(This->decoder, pIStream, &This->file_info);
133
134 if (SUCCEEDED(hr))
135 {
136 This->cache_options = cacheOptions;
137 This->stream = pIStream;
138 IStream_AddRef(This->stream);
139 }
140
141 LeaveCriticalSection(&This->lock);
142
143 return hr;
144 }
145
CommonDecoder_GetContainerFormat(IWICBitmapDecoder * iface,GUID * pguidContainerFormat)146 static HRESULT WINAPI CommonDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
147 GUID *pguidContainerFormat)
148 {
149 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
150 memcpy(pguidContainerFormat, &This->decoder_info.container_format, sizeof(GUID));
151 return S_OK;
152 }
153
CommonDecoder_GetDecoderInfo(IWICBitmapDecoder * iface,IWICBitmapDecoderInfo ** ppIDecoderInfo)154 static HRESULT WINAPI CommonDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
155 IWICBitmapDecoderInfo **ppIDecoderInfo)
156 {
157 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
158 TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
159
160 return get_decoder_info(&This->decoder_info.clsid, ppIDecoderInfo);
161 }
162
CommonDecoder_CopyPalette(IWICBitmapDecoder * iface,IWICPalette * palette)163 static HRESULT WINAPI CommonDecoder_CopyPalette(IWICBitmapDecoder *iface,
164 IWICPalette *palette)
165 {
166 TRACE("(%p,%p)\n", iface, palette);
167 return WINCODEC_ERR_PALETTEUNAVAILABLE;
168 }
169
CommonDecoder_GetMetadataQueryReader(IWICBitmapDecoder * iface,IWICMetadataQueryReader ** reader)170 static HRESULT WINAPI CommonDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
171 IWICMetadataQueryReader **reader)
172 {
173 TRACE("(%p,%p)\n", iface, reader);
174
175 if (!reader) return E_INVALIDARG;
176
177 *reader = NULL;
178 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
179 }
180
CommonDecoder_GetPreview(IWICBitmapDecoder * iface,IWICBitmapSource ** ppIBitmapSource)181 static HRESULT WINAPI CommonDecoder_GetPreview(IWICBitmapDecoder *iface,
182 IWICBitmapSource **ppIBitmapSource)
183 {
184 TRACE("(%p,%p)\n", iface, ppIBitmapSource);
185
186 if (!ppIBitmapSource) return E_INVALIDARG;
187
188 *ppIBitmapSource = NULL;
189 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
190 }
191
CommonDecoder_GetColorContexts(IWICBitmapDecoder * iface,UINT cCount,IWICColorContext ** ppIColorContexts,UINT * pcActualCount)192 static HRESULT WINAPI CommonDecoder_GetColorContexts(IWICBitmapDecoder *iface,
193 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
194 {
195 TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
196 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
197 }
198
CommonDecoder_GetThumbnail(IWICBitmapDecoder * iface,IWICBitmapSource ** ppIThumbnail)199 static HRESULT WINAPI CommonDecoder_GetThumbnail(IWICBitmapDecoder *iface,
200 IWICBitmapSource **ppIThumbnail)
201 {
202 TRACE("(%p,%p)\n", iface, ppIThumbnail);
203
204 if (!ppIThumbnail) return E_INVALIDARG;
205
206 *ppIThumbnail = NULL;
207 return WINCODEC_ERR_CODECNOTHUMBNAIL;
208 }
209
CommonDecoder_GetFrameCount(IWICBitmapDecoder * iface,UINT * pCount)210 static HRESULT WINAPI CommonDecoder_GetFrameCount(IWICBitmapDecoder *iface,
211 UINT *pCount)
212 {
213 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
214 if (!pCount) return E_INVALIDARG;
215
216 if (This->stream)
217 *pCount = This->file_info.frame_count;
218 else
219 *pCount = 0;
220
221 return S_OK;
222 }
223
224 static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
225 UINT index, IWICBitmapFrameDecode **ppIBitmapFrame);
226
227 static const IWICBitmapDecoderVtbl CommonDecoder_Vtbl = {
228 CommonDecoder_QueryInterface,
229 CommonDecoder_AddRef,
230 CommonDecoder_Release,
231 CommonDecoder_QueryCapability,
232 CommonDecoder_Initialize,
233 CommonDecoder_GetContainerFormat,
234 CommonDecoder_GetDecoderInfo,
235 CommonDecoder_CopyPalette,
236 CommonDecoder_GetMetadataQueryReader,
237 CommonDecoder_GetPreview,
238 CommonDecoder_GetColorContexts,
239 CommonDecoder_GetThumbnail,
240 CommonDecoder_GetFrameCount,
241 CommonDecoder_GetFrame
242 };
243
244 typedef struct {
245 IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
246 IWICMetadataBlockReader IWICMetadataBlockReader_iface;
247 LONG ref;
248 CommonDecoder *parent;
249 DWORD frame;
250 struct decoder_frame decoder_frame;
251 BOOL metadata_initialized;
252 UINT metadata_count;
253 struct decoder_block* metadata_blocks;
254 } CommonDecoderFrame;
255
impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode * iface)256 static inline CommonDecoderFrame *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
257 {
258 return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICBitmapFrameDecode_iface);
259 }
260
impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader * iface)261 static inline CommonDecoderFrame *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
262 {
263 return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICMetadataBlockReader_iface);
264 }
265
CommonDecoderFrame_QueryInterface(IWICBitmapFrameDecode * iface,REFIID iid,void ** ppv)266 static HRESULT WINAPI CommonDecoderFrame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
267 void **ppv)
268 {
269 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
270 if (!ppv) return E_INVALIDARG;
271
272 if (IsEqualIID(&IID_IUnknown, iid) ||
273 IsEqualIID(&IID_IWICBitmapSource, iid) ||
274 IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
275 {
276 *ppv = &This->IWICBitmapFrameDecode_iface;
277 }
278 else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid) &&
279 (This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata))
280 {
281 *ppv = &This->IWICMetadataBlockReader_iface;
282 }
283 else
284 {
285 *ppv = NULL;
286 return E_NOINTERFACE;
287 }
288
289 IUnknown_AddRef((IUnknown*)*ppv);
290 return S_OK;
291 }
292
CommonDecoderFrame_AddRef(IWICBitmapFrameDecode * iface)293 static ULONG WINAPI CommonDecoderFrame_AddRef(IWICBitmapFrameDecode *iface)
294 {
295 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
296 ULONG ref = InterlockedIncrement(&This->ref);
297
298 TRACE("(%p) refcount=%lu\n", iface, ref);
299
300 return ref;
301 }
302
CommonDecoderFrame_Release(IWICBitmapFrameDecode * iface)303 static ULONG WINAPI CommonDecoderFrame_Release(IWICBitmapFrameDecode *iface)
304 {
305 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
306 ULONG ref = InterlockedDecrement(&This->ref);
307
308 TRACE("(%p) refcount=%lu\n", iface, ref);
309
310 if (ref == 0)
311 {
312 IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface);
313 free(This->metadata_blocks);
314 free(This);
315 }
316
317 return ref;
318 }
319
CommonDecoderFrame_GetSize(IWICBitmapFrameDecode * iface,UINT * puiWidth,UINT * puiHeight)320 static HRESULT WINAPI CommonDecoderFrame_GetSize(IWICBitmapFrameDecode *iface,
321 UINT *puiWidth, UINT *puiHeight)
322 {
323 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
324
325 TRACE("(%p,%p,%p)\n", This, puiWidth, puiHeight);
326
327 if (!puiWidth || !puiHeight)
328 return E_POINTER;
329
330 *puiWidth = This->decoder_frame.width;
331 *puiHeight = This->decoder_frame.height;
332 return S_OK;
333 }
334
CommonDecoderFrame_GetPixelFormat(IWICBitmapFrameDecode * iface,WICPixelFormatGUID * pPixelFormat)335 static HRESULT WINAPI CommonDecoderFrame_GetPixelFormat(IWICBitmapFrameDecode *iface,
336 WICPixelFormatGUID *pPixelFormat)
337 {
338 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
339
340 TRACE("(%p,%p)\n", This, pPixelFormat);
341
342 if (!pPixelFormat)
343 return E_POINTER;
344
345 *pPixelFormat = This->decoder_frame.pixel_format;
346 return S_OK;
347 }
348
CommonDecoderFrame_GetResolution(IWICBitmapFrameDecode * iface,double * pDpiX,double * pDpiY)349 static HRESULT WINAPI CommonDecoderFrame_GetResolution(IWICBitmapFrameDecode *iface,
350 double *pDpiX, double *pDpiY)
351 {
352 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
353
354 TRACE("(%p,%p,%p)\n", This, pDpiX, pDpiY);
355
356 if (!pDpiX || !pDpiY)
357 return E_POINTER;
358
359 *pDpiX = This->decoder_frame.dpix;
360 *pDpiY = This->decoder_frame.dpiy;
361 return S_OK;
362 }
363
CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode * iface,IWICPalette * pIPalette)364 static HRESULT WINAPI CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode *iface,
365 IWICPalette *pIPalette)
366 {
367 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
368 HRESULT hr=S_OK;
369
370 TRACE("(%p,%p)\n", iface, pIPalette);
371
372 if (This->decoder_frame.num_colors)
373 {
374 hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette, This->decoder_frame.num_colors);
375 }
376 else
377 {
378 hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
379 }
380
381 return hr;
382 }
383
CommonDecoderFrame_CopyPixels(IWICBitmapFrameDecode * iface,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer)384 static HRESULT WINAPI CommonDecoderFrame_CopyPixels(IWICBitmapFrameDecode *iface,
385 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
386 {
387 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
388 HRESULT hr;
389 UINT bytesperrow;
390 WICRect rect;
391
392 TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
393
394 if (!pbBuffer)
395 return E_POINTER;
396
397 if (!prc)
398 {
399 rect.X = 0;
400 rect.Y = 0;
401 rect.Width = This->decoder_frame.width;
402 rect.Height = This->decoder_frame.height;
403 prc = ▭
404 }
405 else
406 {
407 if (prc->X < 0 || prc->Y < 0 ||
408 prc->X+prc->Width > This->decoder_frame.width ||
409 prc->Y+prc->Height > This->decoder_frame.height)
410 return E_INVALIDARG;
411 }
412
413 bytesperrow = ((This->decoder_frame.bpp * prc->Width)+7)/8;
414
415 if (cbStride < bytesperrow)
416 return E_INVALIDARG;
417
418 if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize)
419 return E_INVALIDARG;
420
421 EnterCriticalSection(&This->parent->lock);
422
423 hr = decoder_copy_pixels(This->parent->decoder, This->frame,
424 prc, cbStride, cbBufferSize, pbBuffer);
425
426 LeaveCriticalSection(&This->parent->lock);
427
428 return hr;
429 }
430
CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode * iface,IWICMetadataQueryReader ** ppIMetadataQueryReader)431 static HRESULT WINAPI CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
432 IWICMetadataQueryReader **ppIMetadataQueryReader)
433 {
434 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
435 IWICComponentFactory* factory;
436 HRESULT hr;
437
438 TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
439
440 if (!ppIMetadataQueryReader)
441 return E_INVALIDARG;
442
443 if (!(This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata))
444 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
445
446 hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory);
447
448 if (SUCCEEDED(hr))
449 {
450 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader);
451 IWICComponentFactory_Release(factory);
452 }
453
454 if (FAILED(hr))
455 *ppIMetadataQueryReader = NULL;
456
457 return hr;
458 }
459
CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode * iface,UINT cCount,IWICColorContext ** ppIColorContexts,UINT * pcActualCount)460 static HRESULT WINAPI CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode *iface,
461 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
462 {
463 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
464 HRESULT hr=S_OK;
465 UINT i;
466 BYTE *profile;
467 DWORD profile_len;
468
469 TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
470
471 if (!pcActualCount) return E_INVALIDARG;
472
473 if (This->parent->file_info.flags & DECODER_FLAGS_UNSUPPORTED_COLOR_CONTEXT)
474 {
475 FIXME("not supported for %s\n", wine_dbgstr_guid(&This->parent->decoder_info.clsid));
476 *pcActualCount = 0;
477 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
478 }
479
480 *pcActualCount = This->decoder_frame.num_color_contexts;
481
482 if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts)
483 {
484 if (cCount >= This->decoder_frame.num_color_contexts)
485 {
486 EnterCriticalSection(&This->parent->lock);
487
488 for (i=0; i<This->decoder_frame.num_color_contexts; i++)
489 {
490 hr = decoder_get_color_context(This->parent->decoder, This->frame, i,
491 &profile, &profile_len);
492 if (SUCCEEDED(hr))
493 {
494 hr = IWICColorContext_InitializeFromMemory(ppIColorContexts[i], profile, profile_len);
495
496 free(profile);
497 }
498
499 if (FAILED(hr))
500 break;
501 }
502
503 LeaveCriticalSection(&This->parent->lock);
504 }
505 else
506 {
507 hr = E_INVALIDARG;
508 }
509 }
510
511 return hr;
512 }
513
CommonDecoderFrame_GetThumbnail(IWICBitmapFrameDecode * iface,IWICBitmapSource ** ppIThumbnail)514 static HRESULT WINAPI CommonDecoderFrame_GetThumbnail(IWICBitmapFrameDecode *iface,
515 IWICBitmapSource **ppIThumbnail)
516 {
517 TRACE("(%p,%p)\n", iface, ppIThumbnail);
518
519 if (!ppIThumbnail) return E_INVALIDARG;
520
521 *ppIThumbnail = NULL;
522 return WINCODEC_ERR_CODECNOTHUMBNAIL;
523 }
524
525 static const IWICBitmapFrameDecodeVtbl CommonDecoderFrameVtbl = {
526 CommonDecoderFrame_QueryInterface,
527 CommonDecoderFrame_AddRef,
528 CommonDecoderFrame_Release,
529 CommonDecoderFrame_GetSize,
530 CommonDecoderFrame_GetPixelFormat,
531 CommonDecoderFrame_GetResolution,
532 CommonDecoderFrame_CopyPalette,
533 CommonDecoderFrame_CopyPixels,
534 CommonDecoderFrame_GetMetadataQueryReader,
535 CommonDecoderFrame_GetColorContexts,
536 CommonDecoderFrame_GetThumbnail
537 };
538
CommonDecoderFrame_Block_QueryInterface(IWICMetadataBlockReader * iface,REFIID iid,void ** ppv)539 static HRESULT WINAPI CommonDecoderFrame_Block_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid,
540 void **ppv)
541 {
542 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
543 return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
544 }
545
CommonDecoderFrame_Block_AddRef(IWICMetadataBlockReader * iface)546 static ULONG WINAPI CommonDecoderFrame_Block_AddRef(IWICMetadataBlockReader *iface)
547 {
548 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
549 return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
550 }
551
CommonDecoderFrame_Block_Release(IWICMetadataBlockReader * iface)552 static ULONG WINAPI CommonDecoderFrame_Block_Release(IWICMetadataBlockReader *iface)
553 {
554 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
555 return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
556 }
557
CommonDecoderFrame_Block_GetContainerFormat(IWICMetadataBlockReader * iface,GUID * pguidContainerFormat)558 static HRESULT WINAPI CommonDecoderFrame_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
559 GUID *pguidContainerFormat)
560 {
561 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
562 if (!pguidContainerFormat) return E_INVALIDARG;
563 *pguidContainerFormat = This->parent->decoder_info.block_format;
564 return S_OK;
565 }
566
CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame * This)567 static HRESULT CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame *This)
568 {
569 HRESULT hr=S_OK;
570
571 if (This->metadata_initialized)
572 return S_OK;
573
574 EnterCriticalSection(&This->parent->lock);
575
576 if (!This->metadata_initialized)
577 {
578 hr = decoder_get_metadata_blocks(This->parent->decoder, This->frame, &This->metadata_count, &This->metadata_blocks);
579 if (SUCCEEDED(hr))
580 This->metadata_initialized = TRUE;
581 }
582
583 LeaveCriticalSection(&This->parent->lock);
584
585 return hr;
586 }
587
CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader * iface,UINT * pcCount)588 static HRESULT WINAPI CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader *iface,
589 UINT *pcCount)
590 {
591 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
592 HRESULT hr;
593
594 TRACE("%p,%p\n", iface, pcCount);
595
596 if (!pcCount) return E_INVALIDARG;
597
598 hr = CommonDecoderFrame_InitializeMetadata(This);
599 if (SUCCEEDED(hr))
600 *pcCount = This->metadata_count;
601
602 return hr;
603 }
604
CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader * iface,UINT nIndex,IWICMetadataReader ** ppIMetadataReader)605 static HRESULT WINAPI CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
606 UINT nIndex, IWICMetadataReader **ppIMetadataReader)
607 {
608 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
609 HRESULT hr;
610 IWICComponentFactory* factory = NULL;
611 IWICStream* stream;
612
613 TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
614
615 if (!ppIMetadataReader)
616 return E_INVALIDARG;
617
618 hr = CommonDecoderFrame_InitializeMetadata(This);
619
620 if (SUCCEEDED(hr) && nIndex >= This->metadata_count)
621 hr = E_INVALIDARG;
622
623 if (SUCCEEDED(hr))
624 hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory);
625
626 if (SUCCEEDED(hr))
627 hr = IWICComponentFactory_CreateStream(factory, &stream);
628
629 if (SUCCEEDED(hr))
630 {
631 if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_FULL_STREAM)
632 {
633 LARGE_INTEGER offset;
634 offset.QuadPart = This->metadata_blocks[nIndex].offset;
635
636 hr = IWICStream_InitializeFromIStream(stream, This->parent->stream);
637
638 if (SUCCEEDED(hr))
639 hr = IWICStream_Seek(stream, offset, STREAM_SEEK_SET, NULL);
640 }
641 else
642 {
643 ULARGE_INTEGER offset, length;
644
645 offset.QuadPart = This->metadata_blocks[nIndex].offset;
646 length.QuadPart = This->metadata_blocks[nIndex].length;
647
648 hr = IWICStream_InitializeFromIStreamRegion(stream, This->parent->stream,
649 offset, length);
650 }
651
652 if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_READER_CLSID)
653 {
654 IWICMetadataReader *reader;
655 IWICPersistStream *persist;
656 if (SUCCEEDED(hr))
657 {
658 hr = create_instance(&This->metadata_blocks[nIndex].reader_clsid,
659 &IID_IWICMetadataReader, (void**)&reader);
660 }
661
662 if (SUCCEEDED(hr))
663 {
664 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
665
666 if (SUCCEEDED(hr))
667 {
668 hr = IWICPersistStream_LoadEx(persist, (IStream*)stream, NULL,
669 This->metadata_blocks[nIndex].options & DECODER_BLOCK_OPTION_MASK);
670
671 IWICPersistStream_Release(persist);
672 }
673
674 if (SUCCEEDED(hr))
675 *ppIMetadataReader = reader;
676 else
677 IWICMetadataReader_Release(reader);
678 }
679 }
680 else
681 {
682 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
683 &This->parent->decoder_info.block_format, NULL,
684 This->metadata_blocks[nIndex].options & DECODER_BLOCK_OPTION_MASK,
685 (IStream*)stream, ppIMetadataReader);
686 }
687
688 IWICStream_Release(stream);
689 }
690
691 if (factory) IWICComponentFactory_Release(factory);
692
693 if (FAILED(hr))
694 *ppIMetadataReader = NULL;
695
696 return S_OK;
697 }
698
CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader * iface,IEnumUnknown ** ppIEnumMetadata)699 static HRESULT WINAPI CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader *iface,
700 IEnumUnknown **ppIEnumMetadata)
701 {
702 FIXME("%p,%p\n", iface, ppIEnumMetadata);
703 return E_NOTIMPL;
704 }
705
706 static const IWICMetadataBlockReaderVtbl CommonDecoderFrame_BlockVtbl = {
707 CommonDecoderFrame_Block_QueryInterface,
708 CommonDecoderFrame_Block_AddRef,
709 CommonDecoderFrame_Block_Release,
710 CommonDecoderFrame_Block_GetContainerFormat,
711 CommonDecoderFrame_Block_GetCount,
712 CommonDecoderFrame_Block_GetReaderByIndex,
713 CommonDecoderFrame_Block_GetEnumerator,
714 };
715
CommonDecoder_GetFrame(IWICBitmapDecoder * iface,UINT index,IWICBitmapFrameDecode ** ppIBitmapFrame)716 static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
717 UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
718 {
719 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
720 HRESULT hr=S_OK;
721 CommonDecoderFrame *result;
722
723 TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
724
725 if (!ppIBitmapFrame)
726 return E_INVALIDARG;
727
728 EnterCriticalSection(&This->lock);
729
730 if (!This->stream || index >= This->file_info.frame_count)
731 hr = WINCODEC_ERR_FRAMEMISSING;
732
733 if (SUCCEEDED(hr))
734 {
735 result = malloc(sizeof(*result));
736 if (!result)
737 hr = E_OUTOFMEMORY;
738 }
739
740 if (SUCCEEDED(hr))
741 {
742 result->IWICBitmapFrameDecode_iface.lpVtbl = &CommonDecoderFrameVtbl;
743 result->IWICMetadataBlockReader_iface.lpVtbl = &CommonDecoderFrame_BlockVtbl;
744 result->ref = 1;
745 result->parent = This;
746 result->frame = index;
747 result->metadata_initialized = FALSE;
748 result->metadata_count = 0;
749 result->metadata_blocks = NULL;
750
751 hr = decoder_get_frame_info(This->decoder, index, &result->decoder_frame);
752
753 if (SUCCEEDED(hr) && This->cache_options == WICDecodeMetadataCacheOnLoad)
754 hr = CommonDecoderFrame_InitializeMetadata(result);
755
756 if (FAILED(hr))
757 free(result);
758 }
759
760 LeaveCriticalSection(&This->lock);
761
762 if (SUCCEEDED(hr))
763 {
764 TRACE("-> %ux%u, %u-bit pixelformat=%s res=%f,%f colors=%lu contexts=%lu\n",
765 result->decoder_frame.width, result->decoder_frame.height,
766 result->decoder_frame.bpp, wine_dbgstr_guid(&result->decoder_frame.pixel_format),
767 result->decoder_frame.dpix, result->decoder_frame.dpiy,
768 result->decoder_frame.num_colors, result->decoder_frame.num_color_contexts);
769 IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
770 *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface;
771 }
772 else
773 {
774 *ppIBitmapFrame = NULL;
775 }
776
777 return hr;
778 }
779
CommonDecoder_CreateInstance(struct decoder * decoder,const struct decoder_info * decoder_info,REFIID iid,void ** ppv)780 HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
781 const struct decoder_info *decoder_info, REFIID iid, void** ppv)
782 {
783 CommonDecoder *This;
784 HRESULT hr;
785
786 TRACE("(%s,%s,%p)\n", debugstr_guid(&decoder_info->clsid), debugstr_guid(iid), ppv);
787
788 This = malloc(sizeof(*This));
789 if (!This)
790 {
791 decoder_destroy(decoder);
792 return E_OUTOFMEMORY;
793 }
794
795 This->IWICBitmapDecoder_iface.lpVtbl = &CommonDecoder_Vtbl;
796 This->ref = 1;
797 This->stream = NULL;
798 This->decoder = decoder;
799 This->decoder_info = *decoder_info;
800 #ifdef __REACTOS__
801 InitializeCriticalSection(&This->lock);
802 #else
803 InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
804 #endif
805 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CommonDecoder.lock");
806
807 hr = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
808 IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
809
810 return hr;
811 }
812