dbghelp: Use RtlGetVersion() for system version detection instead.
[wine.git] / dlls / windowscodecs / decoder.c
blob769dc779f13dfe6a01fa720135e0ede2503b8735
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 NONAMELESSUNION
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
28 #include "wincodecs_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
34 typedef struct {
35 IWICBitmapDecoder IWICBitmapDecoder_iface;
36 LONG ref;
37 CRITICAL_SECTION lock; /* must be held when stream or decoder is accessed */
38 IStream *stream;
39 struct decoder *decoder;
40 struct decoder_info decoder_info;
41 struct decoder_stat file_info;
42 WICDecodeOptions cache_options;
43 } CommonDecoder;
45 static inline CommonDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
47 return CONTAINING_RECORD(iface, CommonDecoder, IWICBitmapDecoder_iface);
50 static HRESULT WINAPI CommonDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
51 void **ppv)
53 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
54 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
56 if (!ppv) return E_INVALIDARG;
58 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
60 *ppv = &This->IWICBitmapDecoder_iface;
62 else
64 *ppv = NULL;
65 return E_NOINTERFACE;
68 IUnknown_AddRef((IUnknown*)*ppv);
69 return S_OK;
72 static ULONG WINAPI CommonDecoder_AddRef(IWICBitmapDecoder *iface)
74 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
75 ULONG ref = InterlockedIncrement(&This->ref);
77 TRACE("(%p) refcount=%lu\n", iface, ref);
79 return ref;
82 static ULONG WINAPI CommonDecoder_Release(IWICBitmapDecoder *iface)
84 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
85 ULONG ref = InterlockedDecrement(&This->ref);
87 TRACE("(%p) refcount=%lu\n", iface, ref);
89 if (ref == 0)
91 if (This->stream)
92 IStream_Release(This->stream);
93 This->lock.DebugInfo->Spare[0] = 0;
94 DeleteCriticalSection(&This->lock);
95 decoder_destroy(This->decoder);
96 HeapFree(GetProcessHeap(), 0, This);
99 return ref;
102 static HRESULT WINAPI CommonDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
103 DWORD *capability)
105 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
106 HRESULT hr;
108 TRACE("(%p,%p,%p)\n", iface, stream, capability);
110 if (!stream || !capability) return E_INVALIDARG;
112 hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
113 if (hr != S_OK) return hr;
115 *capability = (This->file_info.flags & DECODER_FLAGS_CAPABILITY_MASK);
116 return S_OK;
119 static HRESULT WINAPI CommonDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
120 WICDecodeOptions cacheOptions)
122 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
123 HRESULT hr=S_OK;
125 TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
127 EnterCriticalSection(&This->lock);
129 if (This->stream)
130 hr = WINCODEC_ERR_WRONGSTATE;
132 if (SUCCEEDED(hr))
133 hr = decoder_initialize(This->decoder, pIStream, &This->file_info);
135 if (SUCCEEDED(hr))
137 This->cache_options = cacheOptions;
138 This->stream = pIStream;
139 IStream_AddRef(This->stream);
142 LeaveCriticalSection(&This->lock);
144 return hr;
147 static HRESULT WINAPI CommonDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
148 GUID *pguidContainerFormat)
150 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
151 memcpy(pguidContainerFormat, &This->decoder_info.container_format, sizeof(GUID));
152 return S_OK;
155 static HRESULT WINAPI CommonDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
156 IWICBitmapDecoderInfo **ppIDecoderInfo)
158 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
159 TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
161 return get_decoder_info(&This->decoder_info.clsid, ppIDecoderInfo);
164 static HRESULT WINAPI CommonDecoder_CopyPalette(IWICBitmapDecoder *iface,
165 IWICPalette *palette)
167 TRACE("(%p,%p)\n", iface, palette);
168 return WINCODEC_ERR_PALETTEUNAVAILABLE;
171 static HRESULT WINAPI CommonDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
172 IWICMetadataQueryReader **reader)
174 TRACE("(%p,%p)\n", iface, reader);
176 if (!reader) return E_INVALIDARG;
178 *reader = NULL;
179 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
182 static HRESULT WINAPI CommonDecoder_GetPreview(IWICBitmapDecoder *iface,
183 IWICBitmapSource **ppIBitmapSource)
185 TRACE("(%p,%p)\n", iface, ppIBitmapSource);
187 if (!ppIBitmapSource) return E_INVALIDARG;
189 *ppIBitmapSource = NULL;
190 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
193 static HRESULT WINAPI CommonDecoder_GetColorContexts(IWICBitmapDecoder *iface,
194 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
196 TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
197 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
200 static HRESULT WINAPI CommonDecoder_GetThumbnail(IWICBitmapDecoder *iface,
201 IWICBitmapSource **ppIThumbnail)
203 TRACE("(%p,%p)\n", iface, ppIThumbnail);
205 if (!ppIThumbnail) return E_INVALIDARG;
207 *ppIThumbnail = NULL;
208 return WINCODEC_ERR_CODECNOTHUMBNAIL;
211 static HRESULT WINAPI CommonDecoder_GetFrameCount(IWICBitmapDecoder *iface,
212 UINT *pCount)
214 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
215 if (!pCount) return E_INVALIDARG;
217 if (This->stream)
218 *pCount = This->file_info.frame_count;
219 else
220 *pCount = 0;
222 return S_OK;
225 static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
226 UINT index, IWICBitmapFrameDecode **ppIBitmapFrame);
228 static const IWICBitmapDecoderVtbl CommonDecoder_Vtbl = {
229 CommonDecoder_QueryInterface,
230 CommonDecoder_AddRef,
231 CommonDecoder_Release,
232 CommonDecoder_QueryCapability,
233 CommonDecoder_Initialize,
234 CommonDecoder_GetContainerFormat,
235 CommonDecoder_GetDecoderInfo,
236 CommonDecoder_CopyPalette,
237 CommonDecoder_GetMetadataQueryReader,
238 CommonDecoder_GetPreview,
239 CommonDecoder_GetColorContexts,
240 CommonDecoder_GetThumbnail,
241 CommonDecoder_GetFrameCount,
242 CommonDecoder_GetFrame
245 typedef struct {
246 IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
247 IWICMetadataBlockReader IWICMetadataBlockReader_iface;
248 LONG ref;
249 CommonDecoder *parent;
250 DWORD frame;
251 struct decoder_frame decoder_frame;
252 BOOL metadata_initialized;
253 UINT metadata_count;
254 struct decoder_block* metadata_blocks;
255 } CommonDecoderFrame;
257 static inline CommonDecoderFrame *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
259 return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICBitmapFrameDecode_iface);
262 static inline CommonDecoderFrame *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
264 return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICMetadataBlockReader_iface);
267 static HRESULT WINAPI CommonDecoderFrame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
268 void **ppv)
270 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
271 if (!ppv) return E_INVALIDARG;
273 if (IsEqualIID(&IID_IUnknown, iid) ||
274 IsEqualIID(&IID_IWICBitmapSource, iid) ||
275 IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
277 *ppv = &This->IWICBitmapFrameDecode_iface;
279 else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid) &&
280 (This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata))
282 *ppv = &This->IWICMetadataBlockReader_iface;
284 else
286 *ppv = NULL;
287 return E_NOINTERFACE;
290 IUnknown_AddRef((IUnknown*)*ppv);
291 return S_OK;
294 static ULONG WINAPI CommonDecoderFrame_AddRef(IWICBitmapFrameDecode *iface)
296 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
297 ULONG ref = InterlockedIncrement(&This->ref);
299 TRACE("(%p) refcount=%lu\n", iface, ref);
301 return ref;
304 static ULONG WINAPI CommonDecoderFrame_Release(IWICBitmapFrameDecode *iface)
306 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
307 ULONG ref = InterlockedDecrement(&This->ref);
309 TRACE("(%p) refcount=%lu\n", iface, ref);
311 if (ref == 0)
313 IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface);
314 HeapFree(GetProcessHeap(), 0, This->metadata_blocks);
315 HeapFree(GetProcessHeap(), 0, This);
318 return ref;
321 static HRESULT WINAPI CommonDecoderFrame_GetSize(IWICBitmapFrameDecode *iface,
322 UINT *puiWidth, UINT *puiHeight)
324 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
326 TRACE("(%p,%p,%p)\n", This, puiWidth, puiHeight);
328 if (!puiWidth || !puiHeight)
329 return E_POINTER;
331 *puiWidth = This->decoder_frame.width;
332 *puiHeight = This->decoder_frame.height;
333 return S_OK;
336 static HRESULT WINAPI CommonDecoderFrame_GetPixelFormat(IWICBitmapFrameDecode *iface,
337 WICPixelFormatGUID *pPixelFormat)
339 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
341 TRACE("(%p,%p)\n", This, pPixelFormat);
343 if (!pPixelFormat)
344 return E_POINTER;
346 *pPixelFormat = This->decoder_frame.pixel_format;
347 return S_OK;
350 static HRESULT WINAPI CommonDecoderFrame_GetResolution(IWICBitmapFrameDecode *iface,
351 double *pDpiX, double *pDpiY)
353 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
355 TRACE("(%p,%p,%p)\n", This, pDpiX, pDpiY);
357 if (!pDpiX || !pDpiY)
358 return E_POINTER;
360 *pDpiX = This->decoder_frame.dpix;
361 *pDpiY = This->decoder_frame.dpiy;
362 return S_OK;
365 static HRESULT WINAPI CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode *iface,
366 IWICPalette *pIPalette)
368 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
369 HRESULT hr=S_OK;
371 TRACE("(%p,%p)\n", iface, pIPalette);
373 if (This->decoder_frame.num_colors)
375 hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette, This->decoder_frame.num_colors);
377 else
379 hr = WINCODEC_ERR_PALETTEUNAVAILABLE;
382 return hr;
385 static HRESULT WINAPI CommonDecoderFrame_CopyPixels(IWICBitmapFrameDecode *iface,
386 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
388 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
389 HRESULT hr;
390 UINT bytesperrow;
391 WICRect rect;
393 TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
395 if (!pbBuffer)
396 return E_POINTER;
398 if (!prc)
400 rect.X = 0;
401 rect.Y = 0;
402 rect.Width = This->decoder_frame.width;
403 rect.Height = This->decoder_frame.height;
404 prc = &rect;
406 else
408 if (prc->X < 0 || prc->Y < 0 ||
409 prc->X+prc->Width > This->decoder_frame.width ||
410 prc->Y+prc->Height > This->decoder_frame.height)
411 return E_INVALIDARG;
414 bytesperrow = ((This->decoder_frame.bpp * prc->Width)+7)/8;
416 if (cbStride < bytesperrow)
417 return E_INVALIDARG;
419 if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize)
420 return E_INVALIDARG;
422 EnterCriticalSection(&This->parent->lock);
424 hr = decoder_copy_pixels(This->parent->decoder, This->frame,
425 prc, cbStride, cbBufferSize, pbBuffer);
427 LeaveCriticalSection(&This->parent->lock);
429 return hr;
432 static HRESULT WINAPI CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
433 IWICMetadataQueryReader **ppIMetadataQueryReader)
435 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
436 IWICComponentFactory* factory;
437 HRESULT hr;
439 TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
441 if (!ppIMetadataQueryReader)
442 return E_INVALIDARG;
444 if (!(This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata))
445 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
447 hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory);
449 if (SUCCEEDED(hr))
451 hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader);
452 IWICComponentFactory_Release(factory);
455 if (FAILED(hr))
456 *ppIMetadataQueryReader = NULL;
458 return hr;
461 static HRESULT WINAPI CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode *iface,
462 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
464 CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface);
465 HRESULT hr=S_OK;
466 UINT i;
467 BYTE *profile;
468 DWORD profile_len;
470 TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
472 if (!pcActualCount) return E_INVALIDARG;
474 if (This->parent->file_info.flags & DECODER_FLAGS_UNSUPPORTED_COLOR_CONTEXT)
476 FIXME("not supported for %s\n", wine_dbgstr_guid(&This->parent->decoder_info.clsid));
477 *pcActualCount = 0;
478 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
481 *pcActualCount = This->decoder_frame.num_color_contexts;
483 if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts)
485 if (cCount >= This->decoder_frame.num_color_contexts)
487 EnterCriticalSection(&This->parent->lock);
489 for (i=0; i<This->decoder_frame.num_color_contexts; i++)
491 hr = decoder_get_color_context(This->parent->decoder, This->frame, i,
492 &profile, &profile_len);
493 if (SUCCEEDED(hr))
495 hr = IWICColorContext_InitializeFromMemory(ppIColorContexts[i], profile, profile_len);
497 HeapFree(GetProcessHeap(), 0, profile);
500 if (FAILED(hr))
501 break;
504 LeaveCriticalSection(&This->parent->lock);
506 else
508 hr = E_INVALIDARG;
512 return hr;
515 static HRESULT WINAPI CommonDecoderFrame_GetThumbnail(IWICBitmapFrameDecode *iface,
516 IWICBitmapSource **ppIThumbnail)
518 TRACE("(%p,%p)\n", iface, ppIThumbnail);
520 if (!ppIThumbnail) return E_INVALIDARG;
522 *ppIThumbnail = NULL;
523 return WINCODEC_ERR_CODECNOTHUMBNAIL;
526 static const IWICBitmapFrameDecodeVtbl CommonDecoderFrameVtbl = {
527 CommonDecoderFrame_QueryInterface,
528 CommonDecoderFrame_AddRef,
529 CommonDecoderFrame_Release,
530 CommonDecoderFrame_GetSize,
531 CommonDecoderFrame_GetPixelFormat,
532 CommonDecoderFrame_GetResolution,
533 CommonDecoderFrame_CopyPalette,
534 CommonDecoderFrame_CopyPixels,
535 CommonDecoderFrame_GetMetadataQueryReader,
536 CommonDecoderFrame_GetColorContexts,
537 CommonDecoderFrame_GetThumbnail
540 static HRESULT WINAPI CommonDecoderFrame_Block_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid,
541 void **ppv)
543 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
544 return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
547 static ULONG WINAPI CommonDecoderFrame_Block_AddRef(IWICMetadataBlockReader *iface)
549 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
550 return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
553 static ULONG WINAPI CommonDecoderFrame_Block_Release(IWICMetadataBlockReader *iface)
555 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
556 return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
559 static HRESULT WINAPI CommonDecoderFrame_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
560 GUID *pguidContainerFormat)
562 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
563 if (!pguidContainerFormat) return E_INVALIDARG;
564 *pguidContainerFormat = This->parent->decoder_info.block_format;
565 return S_OK;
568 static HRESULT CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame *This)
570 HRESULT hr=S_OK;
572 if (This->metadata_initialized)
573 return S_OK;
575 EnterCriticalSection(&This->parent->lock);
577 if (!This->metadata_initialized)
579 hr = decoder_get_metadata_blocks(This->parent->decoder, This->frame, &This->metadata_count, &This->metadata_blocks);
580 if (SUCCEEDED(hr))
581 This->metadata_initialized = TRUE;
584 LeaveCriticalSection(&This->parent->lock);
586 return hr;
589 static HRESULT WINAPI CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader *iface,
590 UINT *pcCount)
592 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
593 HRESULT hr;
595 TRACE("%p,%p\n", iface, pcCount);
597 if (!pcCount) return E_INVALIDARG;
599 hr = CommonDecoderFrame_InitializeMetadata(This);
600 if (SUCCEEDED(hr))
601 *pcCount = This->metadata_count;
603 return hr;
606 static HRESULT WINAPI CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
607 UINT nIndex, IWICMetadataReader **ppIMetadataReader)
609 CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface);
610 HRESULT hr;
611 IWICComponentFactory* factory = NULL;
612 IWICStream* stream;
614 TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader);
616 if (!ppIMetadataReader)
617 return E_INVALIDARG;
619 hr = CommonDecoderFrame_InitializeMetadata(This);
621 if (SUCCEEDED(hr) && nIndex >= This->metadata_count)
622 hr = E_INVALIDARG;
624 if (SUCCEEDED(hr))
625 hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory);
627 if (SUCCEEDED(hr))
628 hr = IWICComponentFactory_CreateStream(factory, &stream);
630 if (SUCCEEDED(hr))
632 if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_FULL_STREAM)
634 LARGE_INTEGER offset;
635 offset.QuadPart = This->metadata_blocks[nIndex].offset;
637 hr = IWICStream_InitializeFromIStream(stream, This->parent->stream);
639 if (SUCCEEDED(hr))
640 hr = IWICStream_Seek(stream, offset, STREAM_SEEK_SET, NULL);
642 else
644 ULARGE_INTEGER offset, length;
646 offset.QuadPart = This->metadata_blocks[nIndex].offset;
647 length.QuadPart = This->metadata_blocks[nIndex].length;
649 hr = IWICStream_InitializeFromIStreamRegion(stream, This->parent->stream,
650 offset, length);
653 if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_READER_CLSID)
655 IWICMetadataReader *reader;
656 IWICPersistStream *persist;
657 if (SUCCEEDED(hr))
659 hr = create_instance(&This->metadata_blocks[nIndex].reader_clsid,
660 &IID_IWICMetadataReader, (void**)&reader);
663 if (SUCCEEDED(hr))
665 hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist);
667 if (SUCCEEDED(hr))
669 hr = IWICPersistStream_LoadEx(persist, (IStream*)stream, NULL,
670 This->metadata_blocks[nIndex].options & DECODER_BLOCK_OPTION_MASK);
672 IWICPersistStream_Release(persist);
675 if (SUCCEEDED(hr))
676 *ppIMetadataReader = reader;
677 else
678 IWICMetadataReader_Release(reader);
681 else
683 hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory,
684 &This->parent->decoder_info.block_format, NULL,
685 This->metadata_blocks[nIndex].options & DECODER_BLOCK_OPTION_MASK,
686 (IStream*)stream, ppIMetadataReader);
689 IWICStream_Release(stream);
692 if (factory) IWICComponentFactory_Release(factory);
694 if (FAILED(hr))
695 *ppIMetadataReader = NULL;
697 return S_OK;
700 static HRESULT WINAPI CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader *iface,
701 IEnumUnknown **ppIEnumMetadata)
703 FIXME("%p,%p\n", iface, ppIEnumMetadata);
704 return E_NOTIMPL;
707 static const IWICMetadataBlockReaderVtbl CommonDecoderFrame_BlockVtbl = {
708 CommonDecoderFrame_Block_QueryInterface,
709 CommonDecoderFrame_Block_AddRef,
710 CommonDecoderFrame_Block_Release,
711 CommonDecoderFrame_Block_GetContainerFormat,
712 CommonDecoderFrame_Block_GetCount,
713 CommonDecoderFrame_Block_GetReaderByIndex,
714 CommonDecoderFrame_Block_GetEnumerator,
717 static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface,
718 UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
720 CommonDecoder *This = impl_from_IWICBitmapDecoder(iface);
721 HRESULT hr=S_OK;
722 CommonDecoderFrame *result;
724 TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
726 if (!ppIBitmapFrame)
727 return E_INVALIDARG;
729 EnterCriticalSection(&This->lock);
731 if (!This->stream || index >= This->file_info.frame_count)
732 hr = WINCODEC_ERR_FRAMEMISSING;
734 if (SUCCEEDED(hr))
736 result = HeapAlloc(GetProcessHeap(), 0, sizeof(*result));
737 if (!result)
738 hr = E_OUTOFMEMORY;
741 if (SUCCEEDED(hr))
743 result->IWICBitmapFrameDecode_iface.lpVtbl = &CommonDecoderFrameVtbl;
744 result->IWICMetadataBlockReader_iface.lpVtbl = &CommonDecoderFrame_BlockVtbl;
745 result->ref = 1;
746 result->parent = This;
747 result->frame = index;
748 result->metadata_initialized = FALSE;
749 result->metadata_count = 0;
750 result->metadata_blocks = NULL;
752 hr = decoder_get_frame_info(This->decoder, index, &result->decoder_frame);
754 if (SUCCEEDED(hr) && This->cache_options == WICDecodeMetadataCacheOnLoad)
755 hr = CommonDecoderFrame_InitializeMetadata(result);
757 if (FAILED(hr))
758 HeapFree(GetProcessHeap(), 0, result);
761 LeaveCriticalSection(&This->lock);
763 if (SUCCEEDED(hr))
765 TRACE("-> %ux%u, %u-bit pixelformat=%s res=%f,%f colors=%lu contexts=%lu\n",
766 result->decoder_frame.width, result->decoder_frame.height,
767 result->decoder_frame.bpp, wine_dbgstr_guid(&result->decoder_frame.pixel_format),
768 result->decoder_frame.dpix, result->decoder_frame.dpiy,
769 result->decoder_frame.num_colors, result->decoder_frame.num_color_contexts);
770 IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
771 *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface;
773 else
775 *ppIBitmapFrame = NULL;
778 return hr;
781 HRESULT CommonDecoder_CreateInstance(struct decoder *decoder,
782 const struct decoder_info *decoder_info, REFIID iid, void** ppv)
784 CommonDecoder *This;
785 HRESULT hr;
787 TRACE("(%s,%s,%p)\n", debugstr_guid(&decoder_info->clsid), debugstr_guid(iid), ppv);
789 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
790 if (!This)
792 decoder_destroy(decoder);
793 return E_OUTOFMEMORY;
796 This->IWICBitmapDecoder_iface.lpVtbl = &CommonDecoder_Vtbl;
797 This->ref = 1;
798 This->stream = NULL;
799 This->decoder = decoder;
800 This->decoder_info = *decoder_info;
801 InitializeCriticalSection(&This->lock);
802 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CommonDecoder.lock");
804 hr = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
805 IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
807 return hr;