windowscodecs: Silence fixme for IID_CMetaBitmapRenderTarget.
[wine.git] / dlls / windowscodecs / decoder.c
blobea8bb2d75bb554928553a9a11cfc3b67206bdc45
1 /*
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
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
27 #include "wincodecs_private.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
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;
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,
50 void **ppv)
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;
61 else
63 *ppv = NULL;
64 return E_NOINTERFACE;
67 IUnknown_AddRef((IUnknown*)*ppv);
68 return S_OK;
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);
78 return 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);
88 if (ref == 0)
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);
98 return ref;
101 static HRESULT WINAPI CommonDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
102 DWORD *capability)
104 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
105 HRESULT hr;
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);
115 return S_OK;
118 static HRESULT WINAPI CommonDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
119 WICDecodeOptions cacheOptions)
121 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
122 HRESULT hr=S_OK;
124 TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
126 EnterCriticalSection(&This->lock);
128 if (This->stream)
129 hr = WINCODEC_ERR_WRONGSTATE;
131 if (SUCCEEDED(hr))
132 hr = decoder_initialize(This->decoder, pIStream, &This->file_info);
134 if (SUCCEEDED(hr))
136 This->cache_options = cacheOptions;
137 This->stream = pIStream;
138 IStream_AddRef(This->stream);
141 LeaveCriticalSection(&This->lock);
143 return hr;
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));
151 return S_OK;
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;
177 *reader = NULL;
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,
211 UINT *pCount)
213 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
214 if (!pCount) return E_INVALIDARG;
216 if (This->stream)
217 *pCount = This->file_info.frame_count;
218 else
219 *pCount = 0;
221 return S_OK;
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
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;
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,
267 void **ppv)
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;
283 else
285 *ppv = NULL;
286 return E_NOINTERFACE;
289 IUnknown_AddRef((IUnknown*)*ppv);
290 return S_OK;
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);
300 return 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);
310 if (ref == 0)
312 IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface);
313 free(This->metadata_blocks);
314 free(This);
317 return ref;
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)
328 return E_POINTER;
330 *puiWidth = This->decoder_frame.width;
331 *puiHeight = This->decoder_frame.height;
332 return S_OK;
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);
342 if (!pPixelFormat)
343 return E_POINTER;
345 *pPixelFormat = This->decoder_frame.pixel_format;
346 return S_OK;
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)
357 return E_POINTER;
359 *pDpiX = This->decoder_frame.dpix;
360 *pDpiY = This->decoder_frame.dpiy;
361 return S_OK;
364 static HRESULT WINAPI CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode *iface,
365 IWICPalette *pIPalette)
367 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
368 HRESULT hr=S_OK;
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);
376 else
378 hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
381 return hr;
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);
388 HRESULT hr;
389 UINT bytesperrow;
390 WICRect rect;
392 TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
394 if (!pbBuffer)
395 return E_POINTER;
397 if (!prc)
399 rect.X = 0;
400 rect.Y = 0;
401 rect.Width = This->decoder_frame.width;
402 rect.Height = This->decoder_frame.height;
403 prc = &rect;
405 else
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;
413 bytesperrow = ((This->decoder_frame.bpp * prc->Width)+7)/8;
415 if (cbStride < bytesperrow)
416 return E_INVALIDARG;
418 if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize)
419 return E_INVALIDARG;
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);
428 return hr;
431 static HRESULT WINAPI CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
432 IWICMetadataQueryReader **ppIMetadataQueryReader)
434 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
435 IWICComponentFactory* factory;
436 HRESULT hr;
438 TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
440 if (!ppIMetadataQueryReader)
441 return E_INVALIDARG;
443 if (!(This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata))
444 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
446 hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory);
448 if (SUCCEEDED(hr))
450 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader);
451 IWICComponentFactory_Release(factory);
454 if (FAILED(hr))
455 *ppIMetadataQueryReader = NULL;
457 return hr;
460 static HRESULT WINAPI CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode *iface,
461 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
463 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
464 HRESULT hr=S_OK;
465 UINT i;
466 BYTE *profile;
467 DWORD profile_len;
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));
476 *pcActualCount = 0;
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);
492 if (SUCCEEDED(hr))
494 hr = IWICColorContext_InitializeFromMemory(ppIColorContexts[i], profile, profile_len);
496 free(profile);
499 if (FAILED(hr))
500 break;
503 LeaveCriticalSection(&This->parent->lock);
505 else
507 hr = E_INVALIDARG;
511 return hr;
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,
540 void **ppv)
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;
564 return S_OK;
567 static HRESULT CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame *This)
569 HRESULT hr=S_OK;
571 if (This->metadata_initialized)
572 return S_OK;
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);
579 if (SUCCEEDED(hr))
580 This->metadata_initialized = TRUE;
583 LeaveCriticalSection(&This->parent->lock);
585 return hr;
588 static HRESULT WINAPI CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader *iface,
589 UINT *pcCount)
591 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
592 HRESULT hr;
594 TRACE("%p,%p\n", iface, pcCount);
596 if (!pcCount) return E_INVALIDARG;
598 hr = CommonDecoderFrame_InitializeMetadata(This);
599 if (SUCCEEDED(hr))
600 *pcCount = This->metadata_count;
602 return hr;
605 static HRESULT WINAPI CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
606 UINT nIndex, IWICMetadataReader **ppIMetadataReader)
608 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
609 HRESULT hr;
610 IWICComponentFactory* factory = NULL;
611 IWICStream* stream;
613 TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
615 if (!ppIMetadataReader)
616 return E_INVALIDARG;
618 hr = CommonDecoderFrame_InitializeMetadata(This);
620 if (SUCCEEDED(hr) && nIndex >= This->metadata_count)
621 hr = E_INVALIDARG;
623 if (SUCCEEDED(hr))
624 hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory);
626 if (SUCCEEDED(hr))
627 hr = IWICComponentFactory_CreateStream(factory, &stream);
629 if (SUCCEEDED(hr))
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);
638 if (SUCCEEDED(hr))
639 hr = IWICStream_Seek(stream, offset, STREAM_SEEK_SET, NULL);
641 else
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,
649 offset, length);
652 if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_READER_CLSID)
654 IWICMetadataReader *reader;
655 IWICPersistStream *persist;
656 if (SUCCEEDED(hr))
658 hr = create_instance(&This->metadata_blocks[nIndex].reader_clsid,
659 &IID_IWICMetadataReader, (void**)&reader);
662 if (SUCCEEDED(hr))
664 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
666 if (SUCCEEDED(hr))
668 hr = IWICPersistStream_LoadEx(persist, (IStream*)stream, NULL,
669 This->metadata_blocks[nIndex].options & DECODER_BLOCK_OPTION_MASK);
671 IWICPersistStream_Release(persist);
674 if (SUCCEEDED(hr))
675 *ppIMetadataReader = reader;
676 else
677 IWICMetadataReader_Release(reader);
680 else
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);
693 if (FAILED(hr))
694 *ppIMetadataReader = NULL;
696 return S_OK;
699 static HRESULT WINAPI CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader *iface,
700 IEnumUnknown **ppIEnumMetadata)
702 FIXME("%p,%p\n", iface, ppIEnumMetadata);
703 return E_NOTIMPL;
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);
720 HRESULT hr=S_OK;
721 CommonDecoderFrame *result;
723 TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
725 if (!ppIBitmapFrame)
726 return E_INVALIDARG;
728 EnterCriticalSection(&This->lock);
730 if (!This->stream || index >= This->file_info.frame_count)
731 hr = WINCODEC_ERR_FRAMEMISSING;
733 if (SUCCEEDED(hr))
735 result = malloc(sizeof(*result));
736 if (!result)
737 hr = E_OUTOFMEMORY;
740 if (SUCCEEDED(hr))
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;
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);
756 if (FAILED(hr))
757 free(result);
760 LeaveCriticalSection(&This->lock);
762 if (SUCCEEDED(hr))
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;
772 else
774 *ppIBitmapFrame = NULL;
777 return hr;
780 HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
781 const struct decoder_info *decoder_info, REFIID iid, void** ppv)
783 CommonDecoder *This;
784 HRESULT hr;
786 TRACE("(%s,%s,%p)\n", debugstr_guid(&decoder_info->clsid), debugstr_guid(iid), ppv);
788 This = malloc(sizeof(*This));
789 if (!This)
791 decoder_destroy(decoder);
792 return E_OUTOFMEMORY;
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 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);
806 return hr;