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 44 static inline CommonDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) 45 { 46 return CONTAINING_RECORD(iface, CommonDecoder, IWICBitmapDecoder_iface); 47 } 48 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 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 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 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 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 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 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 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 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 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 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 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 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 256 static inline CommonDecoderFrame *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface) 257 { 258 return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICBitmapFrameDecode_iface); 259 } 260 261 static inline CommonDecoderFrame *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface) 262 { 263 return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICMetadataBlockReader_iface); 264 } 265 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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