2 * Copyright 2020 Esme Povirk
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.
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.
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
27 #include "wincodecs_private.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
34 IWICBitmapDecoder IWICBitmapDecoder_iface
;
36 CRITICAL_SECTION lock
; /* must be held when stream or decoder is accessed */
38 struct decoder
*decoder
;
39 struct decoder_info decoder_info
;
40 struct decoder_stat file_info
;
41 WICDecodeOptions cache_options
;
44 static inline CommonDecoder
*impl_from_IWICBitmapDecoder(IWICBitmapDecoder
*iface
)
46 return CONTAINING_RECORD(iface
, CommonDecoder
, IWICBitmapDecoder_iface
);
49 static HRESULT WINAPI
CommonDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
52 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
53 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
55 if (!ppv
) return E_INVALIDARG
;
57 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICBitmapDecoder
, iid
))
59 *ppv
= &This
->IWICBitmapDecoder_iface
;
67 IUnknown_AddRef((IUnknown
*)*ppv
);
71 static ULONG WINAPI
CommonDecoder_AddRef(IWICBitmapDecoder
*iface
)
73 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
74 ULONG ref
= InterlockedIncrement(&This
->ref
);
76 TRACE("(%p) refcount=%lu\n", iface
, ref
);
81 static ULONG WINAPI
CommonDecoder_Release(IWICBitmapDecoder
*iface
)
83 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
84 ULONG ref
= InterlockedDecrement(&This
->ref
);
86 TRACE("(%p) refcount=%lu\n", iface
, ref
);
91 IStream_Release(This
->stream
);
92 This
->lock
.DebugInfo
->Spare
[0] = 0;
93 DeleteCriticalSection(&This
->lock
);
94 decoder_destroy(This
->decoder
);
101 static HRESULT WINAPI
CommonDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*stream
,
104 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
107 TRACE("(%p,%p,%p)\n", iface
, stream
, capability
);
109 if (!stream
|| !capability
) return E_INVALIDARG
;
111 hr
= IWICBitmapDecoder_Initialize(iface
, stream
, WICDecodeMetadataCacheOnDemand
);
112 if (hr
!= S_OK
) return hr
;
114 *capability
= (This
->file_info
.flags
& DECODER_FLAGS_CAPABILITY_MASK
);
118 static HRESULT WINAPI
CommonDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
119 WICDecodeOptions cacheOptions
)
121 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
124 TRACE("(%p,%p,%x)\n", iface
, pIStream
, cacheOptions
);
126 EnterCriticalSection(&This
->lock
);
129 hr
= WINCODEC_ERR_WRONGSTATE
;
132 hr
= decoder_initialize(This
->decoder
, pIStream
, &This
->file_info
);
136 This
->cache_options
= cacheOptions
;
137 This
->stream
= pIStream
;
138 IStream_AddRef(This
->stream
);
141 LeaveCriticalSection(&This
->lock
);
146 static HRESULT WINAPI
CommonDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
147 GUID
*pguidContainerFormat
)
149 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
150 memcpy(pguidContainerFormat
, &This
->decoder_info
.container_format
, sizeof(GUID
));
154 static HRESULT WINAPI
CommonDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
155 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
157 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
158 TRACE("(%p,%p)\n", iface
, ppIDecoderInfo
);
160 return get_decoder_info(&This
->decoder_info
.clsid
, ppIDecoderInfo
);
163 static HRESULT WINAPI
CommonDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
164 IWICPalette
*palette
)
166 TRACE("(%p,%p)\n", iface
, palette
);
167 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
170 static HRESULT WINAPI
CommonDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
171 IWICMetadataQueryReader
**reader
)
173 TRACE("(%p,%p)\n", iface
, reader
);
175 if (!reader
) return E_INVALIDARG
;
178 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
181 static HRESULT WINAPI
CommonDecoder_GetPreview(IWICBitmapDecoder
*iface
,
182 IWICBitmapSource
**ppIBitmapSource
)
184 TRACE("(%p,%p)\n", iface
, ppIBitmapSource
);
186 if (!ppIBitmapSource
) return E_INVALIDARG
;
188 *ppIBitmapSource
= NULL
;
189 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
192 static HRESULT WINAPI
CommonDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
193 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
195 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
196 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
199 static HRESULT WINAPI
CommonDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
200 IWICBitmapSource
**ppIThumbnail
)
202 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
204 if (!ppIThumbnail
) return E_INVALIDARG
;
206 *ppIThumbnail
= NULL
;
207 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
210 static HRESULT WINAPI
CommonDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
213 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
214 if (!pCount
) return E_INVALIDARG
;
217 *pCount
= This
->file_info
.frame_count
;
224 static HRESULT WINAPI
CommonDecoder_GetFrame(IWICBitmapDecoder
*iface
,
225 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
);
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
245 IWICBitmapFrameDecode IWICBitmapFrameDecode_iface
;
246 IWICMetadataBlockReader IWICMetadataBlockReader_iface
;
248 CommonDecoder
*parent
;
250 struct decoder_frame decoder_frame
;
251 BOOL metadata_initialized
;
253 struct decoder_block
* metadata_blocks
;
254 } CommonDecoderFrame
;
256 static inline CommonDecoderFrame
*impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface
)
258 return CONTAINING_RECORD(iface
, CommonDecoderFrame
, IWICBitmapFrameDecode_iface
);
261 static inline CommonDecoderFrame
*impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader
*iface
)
263 return CONTAINING_RECORD(iface
, CommonDecoderFrame
, IWICMetadataBlockReader_iface
);
266 static HRESULT WINAPI
CommonDecoderFrame_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
269 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
270 if (!ppv
) return E_INVALIDARG
;
272 if (IsEqualIID(&IID_IUnknown
, iid
) ||
273 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
274 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
))
276 *ppv
= &This
->IWICBitmapFrameDecode_iface
;
278 else if (IsEqualIID(&IID_IWICMetadataBlockReader
, iid
) &&
279 (This
->parent
->file_info
.flags
& WICBitmapDecoderCapabilityCanEnumerateMetadata
))
281 *ppv
= &This
->IWICMetadataBlockReader_iface
;
286 return E_NOINTERFACE
;
289 IUnknown_AddRef((IUnknown
*)*ppv
);
293 static ULONG WINAPI
CommonDecoderFrame_AddRef(IWICBitmapFrameDecode
*iface
)
295 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
296 ULONG ref
= InterlockedIncrement(&This
->ref
);
298 TRACE("(%p) refcount=%lu\n", iface
, ref
);
303 static ULONG WINAPI
CommonDecoderFrame_Release(IWICBitmapFrameDecode
*iface
)
305 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
306 ULONG ref
= InterlockedDecrement(&This
->ref
);
308 TRACE("(%p) refcount=%lu\n", iface
, ref
);
312 IWICBitmapDecoder_Release(&This
->parent
->IWICBitmapDecoder_iface
);
313 free(This
->metadata_blocks
);
320 static HRESULT WINAPI
CommonDecoderFrame_GetSize(IWICBitmapFrameDecode
*iface
,
321 UINT
*puiWidth
, UINT
*puiHeight
)
323 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
325 TRACE("(%p,%p,%p)\n", This
, puiWidth
, puiHeight
);
327 if (!puiWidth
|| !puiHeight
)
330 *puiWidth
= This
->decoder_frame
.width
;
331 *puiHeight
= This
->decoder_frame
.height
;
335 static HRESULT WINAPI
CommonDecoderFrame_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
336 WICPixelFormatGUID
*pPixelFormat
)
338 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
340 TRACE("(%p,%p)\n", This
, pPixelFormat
);
345 *pPixelFormat
= This
->decoder_frame
.pixel_format
;
349 static HRESULT WINAPI
CommonDecoderFrame_GetResolution(IWICBitmapFrameDecode
*iface
,
350 double *pDpiX
, double *pDpiY
)
352 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
354 TRACE("(%p,%p,%p)\n", This
, pDpiX
, pDpiY
);
356 if (!pDpiX
|| !pDpiY
)
359 *pDpiX
= This
->decoder_frame
.dpix
;
360 *pDpiY
= This
->decoder_frame
.dpiy
;
364 static HRESULT WINAPI
CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode
*iface
,
365 IWICPalette
*pIPalette
)
367 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
370 TRACE("(%p,%p)\n", iface
, pIPalette
);
372 if (This
->decoder_frame
.num_colors
)
374 hr
= IWICPalette_InitializeCustom(pIPalette
, This
->decoder_frame
.palette
, This
->decoder_frame
.num_colors
);
378 hr
= WINCODEC_ERR_PALETTEUNAVAILABLE
;
384 static HRESULT WINAPI
CommonDecoderFrame_CopyPixels(IWICBitmapFrameDecode
*iface
,
385 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
387 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
392 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
401 rect
.Width
= This
->decoder_frame
.width
;
402 rect
.Height
= This
->decoder_frame
.height
;
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
)
413 bytesperrow
= ((This
->decoder_frame
.bpp
* prc
->Width
)+7)/8;
415 if (cbStride
< bytesperrow
)
418 if ((cbStride
* (prc
->Height
-1)) + bytesperrow
> cbBufferSize
)
421 EnterCriticalSection(&This
->parent
->lock
);
423 hr
= decoder_copy_pixels(This
->parent
->decoder
, This
->frame
,
424 prc
, cbStride
, cbBufferSize
, pbBuffer
);
426 LeaveCriticalSection(&This
->parent
->lock
);
431 static HRESULT WINAPI
CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
432 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
434 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
435 IWICComponentFactory
* factory
;
438 TRACE("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
440 if (!ppIMetadataQueryReader
)
443 if (!(This
->parent
->file_info
.flags
& WICBitmapDecoderCapabilityCanEnumerateMetadata
))
444 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
446 hr
= create_instance(&CLSID_WICImagingFactory
, &IID_IWICComponentFactory
, (void**)&factory
);
450 hr
= IWICComponentFactory_CreateQueryReaderFromBlockReader(factory
, &This
->IWICMetadataBlockReader_iface
, ppIMetadataQueryReader
);
451 IWICComponentFactory_Release(factory
);
455 *ppIMetadataQueryReader
= NULL
;
460 static HRESULT WINAPI
CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode
*iface
,
461 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
463 CommonDecoderFrame
*This
= impl_from_IWICBitmapFrameDecode(iface
);
469 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
471 if (!pcActualCount
) return E_INVALIDARG
;
473 if (This
->parent
->file_info
.flags
& DECODER_FLAGS_UNSUPPORTED_COLOR_CONTEXT
)
475 FIXME("not supported for %s\n", wine_dbgstr_guid(&This
->parent
->decoder_info
.clsid
));
477 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
480 *pcActualCount
= This
->decoder_frame
.num_color_contexts
;
482 if (This
->decoder_frame
.num_color_contexts
&& cCount
&& ppIColorContexts
)
484 if (cCount
>= This
->decoder_frame
.num_color_contexts
)
486 EnterCriticalSection(&This
->parent
->lock
);
488 for (i
=0; i
<This
->decoder_frame
.num_color_contexts
; i
++)
490 hr
= decoder_get_color_context(This
->parent
->decoder
, This
->frame
, i
,
491 &profile
, &profile_len
);
494 hr
= IWICColorContext_InitializeFromMemory(ppIColorContexts
[i
], profile
, profile_len
);
503 LeaveCriticalSection(&This
->parent
->lock
);
514 static HRESULT WINAPI
CommonDecoderFrame_GetThumbnail(IWICBitmapFrameDecode
*iface
,
515 IWICBitmapSource
**ppIThumbnail
)
517 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
519 if (!ppIThumbnail
) return E_INVALIDARG
;
521 *ppIThumbnail
= NULL
;
522 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
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
539 static HRESULT WINAPI
CommonDecoderFrame_Block_QueryInterface(IWICMetadataBlockReader
*iface
, REFIID iid
,
542 CommonDecoderFrame
*This
= impl_from_IWICMetadataBlockReader(iface
);
543 return IWICBitmapFrameDecode_QueryInterface(&This
->IWICBitmapFrameDecode_iface
, iid
, ppv
);
546 static ULONG WINAPI
CommonDecoderFrame_Block_AddRef(IWICMetadataBlockReader
*iface
)
548 CommonDecoderFrame
*This
= impl_from_IWICMetadataBlockReader(iface
);
549 return IWICBitmapFrameDecode_AddRef(&This
->IWICBitmapFrameDecode_iface
);
552 static ULONG WINAPI
CommonDecoderFrame_Block_Release(IWICMetadataBlockReader
*iface
)
554 CommonDecoderFrame
*This
= impl_from_IWICMetadataBlockReader(iface
);
555 return IWICBitmapFrameDecode_Release(&This
->IWICBitmapFrameDecode_iface
);
558 static HRESULT WINAPI
CommonDecoderFrame_Block_GetContainerFormat(IWICMetadataBlockReader
*iface
,
559 GUID
*pguidContainerFormat
)
561 CommonDecoderFrame
*This
= impl_from_IWICMetadataBlockReader(iface
);
562 if (!pguidContainerFormat
) return E_INVALIDARG
;
563 *pguidContainerFormat
= This
->parent
->decoder_info
.block_format
;
567 static HRESULT
CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame
*This
)
571 if (This
->metadata_initialized
)
574 EnterCriticalSection(&This
->parent
->lock
);
576 if (!This
->metadata_initialized
)
578 hr
= decoder_get_metadata_blocks(This
->parent
->decoder
, This
->frame
, &This
->metadata_count
, &This
->metadata_blocks
);
580 This
->metadata_initialized
= TRUE
;
583 LeaveCriticalSection(&This
->parent
->lock
);
588 static HRESULT WINAPI
CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader
*iface
,
591 CommonDecoderFrame
*This
= impl_from_IWICMetadataBlockReader(iface
);
594 TRACE("%p,%p\n", iface
, pcCount
);
596 if (!pcCount
) return E_INVALIDARG
;
598 hr
= CommonDecoderFrame_InitializeMetadata(This
);
600 *pcCount
= This
->metadata_count
;
605 static HRESULT WINAPI
CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader
*iface
,
606 UINT nIndex
, IWICMetadataReader
**ppIMetadataReader
)
608 CommonDecoderFrame
*This
= impl_from_IWICMetadataBlockReader(iface
);
610 IWICComponentFactory
* factory
= NULL
;
613 TRACE("%p,%d,%p\n", iface
, nIndex
, ppIMetadataReader
);
615 if (!ppIMetadataReader
)
618 hr
= CommonDecoderFrame_InitializeMetadata(This
);
620 if (SUCCEEDED(hr
) && nIndex
>= This
->metadata_count
)
624 hr
= create_instance(&CLSID_WICImagingFactory
, &IID_IWICComponentFactory
, (void**)&factory
);
627 hr
= IWICComponentFactory_CreateStream(factory
, &stream
);
631 if (This
->metadata_blocks
[nIndex
].options
& DECODER_BLOCK_FULL_STREAM
)
633 LARGE_INTEGER offset
;
634 offset
.QuadPart
= This
->metadata_blocks
[nIndex
].offset
;
636 hr
= IWICStream_InitializeFromIStream(stream
, This
->parent
->stream
);
639 hr
= IWICStream_Seek(stream
, offset
, STREAM_SEEK_SET
, NULL
);
643 ULARGE_INTEGER offset
, length
;
645 offset
.QuadPart
= This
->metadata_blocks
[nIndex
].offset
;
646 length
.QuadPart
= This
->metadata_blocks
[nIndex
].length
;
648 hr
= IWICStream_InitializeFromIStreamRegion(stream
, This
->parent
->stream
,
652 if (This
->metadata_blocks
[nIndex
].options
& DECODER_BLOCK_READER_CLSID
)
654 IWICMetadataReader
*reader
;
655 IWICPersistStream
*persist
;
658 hr
= create_instance(&This
->metadata_blocks
[nIndex
].reader_clsid
,
659 &IID_IWICMetadataReader
, (void**)&reader
);
664 hr
= IWICMetadataReader_QueryInterface(reader
, &IID_IWICPersistStream
, (void**)&persist
);
668 hr
= IWICPersistStream_LoadEx(persist
, (IStream
*)stream
, NULL
,
669 This
->metadata_blocks
[nIndex
].options
& DECODER_BLOCK_OPTION_MASK
);
671 IWICPersistStream_Release(persist
);
675 *ppIMetadataReader
= reader
;
677 IWICMetadataReader_Release(reader
);
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
);
688 IWICStream_Release(stream
);
691 if (factory
) IWICComponentFactory_Release(factory
);
694 *ppIMetadataReader
= NULL
;
699 static HRESULT WINAPI
CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader
*iface
,
700 IEnumUnknown
**ppIEnumMetadata
)
702 FIXME("%p,%p\n", iface
, ppIEnumMetadata
);
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
,
716 static HRESULT WINAPI
CommonDecoder_GetFrame(IWICBitmapDecoder
*iface
,
717 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
719 CommonDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
721 CommonDecoderFrame
*result
;
723 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
728 EnterCriticalSection(&This
->lock
);
730 if (!This
->stream
|| index
>= This
->file_info
.frame_count
)
731 hr
= WINCODEC_ERR_FRAMEMISSING
;
735 result
= malloc(sizeof(*result
));
742 result
->IWICBitmapFrameDecode_iface
.lpVtbl
= &CommonDecoderFrameVtbl
;
743 result
->IWICMetadataBlockReader_iface
.lpVtbl
= &CommonDecoderFrame_BlockVtbl
;
745 result
->parent
= This
;
746 result
->frame
= index
;
747 result
->metadata_initialized
= FALSE
;
748 result
->metadata_count
= 0;
749 result
->metadata_blocks
= NULL
;
751 hr
= decoder_get_frame_info(This
->decoder
, index
, &result
->decoder_frame
);
753 if (SUCCEEDED(hr
) && This
->cache_options
== WICDecodeMetadataCacheOnLoad
)
754 hr
= CommonDecoderFrame_InitializeMetadata(result
);
760 LeaveCriticalSection(&This
->lock
);
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
;
774 *ppIBitmapFrame
= NULL
;
780 HRESULT
CommonDecoder_CreateInstance(struct decoder
*decoder
,
781 const struct decoder_info
*decoder_info
, REFIID iid
, void** ppv
)
786 TRACE("(%s,%s,%p)\n", debugstr_guid(&decoder_info
->clsid
), debugstr_guid(iid
), ppv
);
788 This
= malloc(sizeof(*This
));
791 decoder_destroy(decoder
);
792 return E_OUTOFMEMORY
;
795 This
->IWICBitmapDecoder_iface
.lpVtbl
= &CommonDecoder_Vtbl
;
798 This
->decoder
= decoder
;
799 This
->decoder_info
= *decoder_info
;
800 InitializeCriticalSectionEx(&This
->lock
, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
);
801 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": CommonDecoder.lock");
803 hr
= IWICBitmapDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
804 IWICBitmapDecoder_Release(&This
->IWICBitmapDecoder_iface
);