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
21 #define NONAMELESSUNION
28 #include "wincodecs_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
34 static const PROPBAG2 encoder_option_properties
[ENCODER_OPTION_END
] = {
35 { PROPBAG2_TYPE_DATA
, VT_BOOL
, 0, 0, (LPOLESTR
)L
"InterlaceOption" },
36 { PROPBAG2_TYPE_DATA
, VT_UI1
, 0, 0, (LPOLESTR
)L
"FilterOption" },
37 { PROPBAG2_TYPE_DATA
, VT_UI1
, 0, 0, (LPOLESTR
)L
"TiffCompressionMethod" },
38 { PROPBAG2_TYPE_DATA
, VT_R4
, 0, 0, (LPOLESTR
)L
"CompressionQuality" },
39 { PROPBAG2_TYPE_DATA
, VT_R4
, 0, 0, (LPOLESTR
)L
"ImageQuality" },
40 { PROPBAG2_TYPE_DATA
, VT_UI1
, 0, 0, (LPOLESTR
)L
"BitmapTransform" },
41 { PROPBAG2_TYPE_DATA
, VT_I4
| VT_ARRAY
, 0, 0, (LPOLESTR
)L
"Luminance" },
42 { PROPBAG2_TYPE_DATA
, VT_I4
| VT_ARRAY
, 0, 0, (LPOLESTR
)L
"Chrominance" },
43 { PROPBAG2_TYPE_DATA
, VT_UI1
, 0, 0, (LPOLESTR
)L
"JpegYCrCbSubsampling" },
44 { PROPBAG2_TYPE_DATA
, VT_BOOL
, 0, 0, (LPOLESTR
)L
"SuppressApp0" }
47 typedef struct CommonEncoder
{
48 IWICBitmapEncoder IWICBitmapEncoder_iface
;
50 CRITICAL_SECTION lock
; /* must be held when stream or encoder is accessed */
52 struct encoder
*encoder
;
53 struct encoder_info encoder_info
;
55 BOOL uncommitted_frame
;
59 typedef struct CommonEncoderFrame
{
60 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface
;
61 IWICMetadataBlockWriter IWICMetadataBlockWriter_iface
;
63 CommonEncoder
*parent
;
64 struct encoder_frame encoder_frame
;
71 static inline CommonEncoder
*impl_from_IWICBitmapEncoder(IWICBitmapEncoder
*iface
)
73 return CONTAINING_RECORD(iface
, CommonEncoder
, IWICBitmapEncoder_iface
);
76 static inline CommonEncoderFrame
*impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface
)
78 return CONTAINING_RECORD(iface
, CommonEncoderFrame
, IWICBitmapFrameEncode_iface
);
81 static inline CommonEncoderFrame
*impl_from_IWICMetadataBlockWriter(IWICMetadataBlockWriter
*iface
)
83 return CONTAINING_RECORD(iface
, CommonEncoderFrame
, IWICMetadataBlockWriter_iface
);
86 static HRESULT WINAPI
CommonEncoderFrame_QueryInterface(IWICBitmapFrameEncode
*iface
, REFIID iid
,
89 CommonEncoderFrame
*object
= impl_from_IWICBitmapFrameEncode(iface
);
90 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
92 if (!ppv
) return E_INVALIDARG
;
94 if (IsEqualIID(&IID_IUnknown
, iid
) ||
95 IsEqualIID(&IID_IWICBitmapFrameEncode
, iid
))
97 *ppv
= &object
->IWICBitmapFrameEncode_iface
;
99 else if (object
->parent
->encoder_info
.flags
& ENCODER_FLAGS_SUPPORTS_METADATA
100 && IsEqualIID(&IID_IWICMetadataBlockWriter
, iid
))
102 *ppv
= &object
->IWICMetadataBlockWriter_iface
;
107 return E_NOINTERFACE
;
110 IUnknown_AddRef((IUnknown
*)*ppv
);
114 static ULONG WINAPI
CommonEncoderFrame_AddRef(IWICBitmapFrameEncode
*iface
)
116 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
117 ULONG ref
= InterlockedIncrement(&This
->ref
);
119 TRACE("(%p) refcount=%u\n", iface
, ref
);
124 static ULONG WINAPI
CommonEncoderFrame_Release(IWICBitmapFrameEncode
*iface
)
126 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
127 ULONG ref
= InterlockedDecrement(&This
->ref
);
129 TRACE("(%p) refcount=%u\n", iface
, ref
);
133 IWICBitmapEncoder_Release(&This
->parent
->IWICBitmapEncoder_iface
);
134 HeapFree(GetProcessHeap(), 0, This
);
140 static HRESULT WINAPI
CommonEncoderFrame_Initialize(IWICBitmapFrameEncode
*iface
,
141 IPropertyBag2
*pIEncoderOptions
)
143 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
145 struct encoder_frame options
= {{0}};
146 PROPBAG2 opts
[7]= {{0}};
147 VARIANT opt_values
[7];
151 TRACE("(%p,%p)\n", iface
, pIEncoderOptions
);
153 if (pIEncoderOptions
)
155 for (i
=0; This
->parent
->encoder_info
.encoder_options
[i
] != ENCODER_OPTION_END
; i
++)
156 opts
[i
] = encoder_option_properties
[This
->parent
->encoder_info
.encoder_options
[i
]];
159 hr
= IPropertyBag2_Read(pIEncoderOptions
, num_opts
, opts
, NULL
, opt_values
, opt_hres
);
164 for (i
=0; This
->parent
->encoder_info
.encoder_options
[i
] != ENCODER_OPTION_END
; i
++)
166 VARIANT
*val
= &opt_values
[i
];
168 switch (This
->parent
->encoder_info
.encoder_options
[i
])
170 case ENCODER_OPTION_INTERLACE
:
171 if (V_VT(val
) == VT_EMPTY
)
172 options
.interlace
= FALSE
;
174 options
.interlace
= (V_BOOL(val
) != 0);
176 case ENCODER_OPTION_FILTER
:
177 options
.filter
= V_UI1(val
);
178 if (options
.filter
> WICPngFilterAdaptive
)
180 WARN("Unrecognized filter option value %u.\n", options
.filter
);
181 options
.filter
= WICPngFilterUnspecified
;
191 options
.interlace
= FALSE
;
192 options
.filter
= WICPngFilterUnspecified
;
195 EnterCriticalSection(&This
->parent
->lock
);
197 if (This
->initialized
)
198 hr
= WINCODEC_ERR_WRONGSTATE
;
201 This
->encoder_frame
= options
;
202 This
->initialized
= TRUE
;
205 LeaveCriticalSection(&This
->parent
->lock
);
210 static HRESULT WINAPI
CommonEncoderFrame_SetSize(IWICBitmapFrameEncode
*iface
,
211 UINT uiWidth
, UINT uiHeight
)
213 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
216 TRACE("(%p,%u,%u)\n", iface
, uiWidth
, uiHeight
);
218 EnterCriticalSection(&This
->parent
->lock
);
220 if (This
->parent
->encoder_info
.flags
& ENCODER_FLAGS_ICNS_SIZE
)
222 if (uiWidth
!= uiHeight
)
224 WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth
, uiHeight
);
239 WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth
, uiHeight
);
245 if (!This
->initialized
|| This
->frame_created
)
247 hr
= WINCODEC_ERR_WRONGSTATE
;
251 This
->encoder_frame
.width
= uiWidth
;
252 This
->encoder_frame
.height
= uiHeight
;
257 LeaveCriticalSection(&This
->parent
->lock
);
262 static HRESULT WINAPI
CommonEncoderFrame_SetResolution(IWICBitmapFrameEncode
*iface
,
263 double dpiX
, double dpiY
)
265 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
268 TRACE("(%p,%0.2f,%0.2f)\n", iface
, dpiX
, dpiY
);
270 EnterCriticalSection(&This
->parent
->lock
);
272 if (!This
->initialized
|| This
->frame_created
)
274 hr
= WINCODEC_ERR_WRONGSTATE
;
278 This
->encoder_frame
.dpix
= dpiX
;
279 This
->encoder_frame
.dpiy
= dpiY
;
283 LeaveCriticalSection(&This
->parent
->lock
);
288 static HRESULT WINAPI
CommonEncoderFrame_SetPixelFormat(IWICBitmapFrameEncode
*iface
,
289 WICPixelFormatGUID
*pPixelFormat
)
291 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
297 TRACE("(%p,%s)\n", iface
, debugstr_guid(pPixelFormat
));
299 EnterCriticalSection(&This
->parent
->lock
);
301 if (!This
->initialized
|| This
->frame_created
)
303 hr
= WINCODEC_ERR_WRONGSTATE
;
307 pixel_format
= *pPixelFormat
;
308 hr
= encoder_get_supported_format(This
->parent
->encoder
, &pixel_format
, &bpp
, &indexed
);
313 TRACE("<-- %s bpp=%i indexed=%i\n", wine_dbgstr_guid(&pixel_format
), bpp
, indexed
);
314 *pPixelFormat
= pixel_format
;
315 This
->encoder_frame
.pixel_format
= pixel_format
;
316 This
->encoder_frame
.bpp
= bpp
;
317 This
->encoder_frame
.indexed
= indexed
;
320 LeaveCriticalSection(&This
->parent
->lock
);
325 static HRESULT WINAPI
CommonEncoderFrame_SetColorContexts(IWICBitmapFrameEncode
*iface
,
326 UINT cCount
, IWICColorContext
**ppIColorContext
)
328 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
332 static HRESULT WINAPI
CommonEncoderFrame_SetPalette(IWICBitmapFrameEncode
*iface
,
333 IWICPalette
*palette
)
335 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
338 TRACE("(%p,%p)\n", iface
, palette
);
343 EnterCriticalSection(&This
->parent
->lock
);
345 if (!This
->initialized
)
346 hr
= WINCODEC_ERR_NOTINITIALIZED
;
347 else if (This
->frame_created
)
348 hr
= WINCODEC_ERR_WRONGSTATE
;
350 hr
= IWICPalette_GetColors(palette
, 256, This
->encoder_frame
.palette
,
351 &This
->encoder_frame
.num_colors
);
353 LeaveCriticalSection(&This
->parent
->lock
);
358 static HRESULT WINAPI
CommonEncoderFrame_SetThumbnail(IWICBitmapFrameEncode
*iface
,
359 IWICBitmapSource
*pIThumbnail
)
361 FIXME("(%p,%p): stub\n", iface
, pIThumbnail
);
362 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
365 static HRESULT WINAPI
CommonEncoderFrame_WritePixels(IWICBitmapFrameEncode
*iface
,
366 UINT lineCount
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbPixels
)
368 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
370 DWORD required_stride
;
372 TRACE("(%p,%u,%u,%u,%p)\n", iface
, lineCount
, cbStride
, cbBufferSize
, pbPixels
);
374 EnterCriticalSection(&This
->parent
->lock
);
376 if (!This
->initialized
|| !This
->encoder_frame
.height
|| !This
->encoder_frame
.width
||
377 !This
->encoder_frame
.bpp
)
379 LeaveCriticalSection(&This
->parent
->lock
);
380 return WINCODEC_ERR_WRONGSTATE
;
383 required_stride
= (This
->encoder_frame
.width
* This
->encoder_frame
.bpp
+ 7)/8;
385 if (lineCount
== 0 || This
->encoder_frame
.height
- This
->lines_written
< lineCount
||
386 cbStride
< required_stride
|| cbBufferSize
< cbStride
* (lineCount
- 1) + required_stride
||
389 LeaveCriticalSection(&This
->parent
->lock
);
393 if (!This
->frame_created
)
395 hr
= encoder_create_frame(This
->parent
->encoder
, &This
->encoder_frame
);
397 This
->frame_created
= TRUE
;
402 hr
= encoder_write_lines(This
->parent
->encoder
, pbPixels
, lineCount
, cbStride
);
404 This
->lines_written
+= lineCount
;
407 LeaveCriticalSection(&This
->parent
->lock
);
412 static HRESULT WINAPI
CommonEncoderFrame_WriteSource(IWICBitmapFrameEncode
*iface
,
413 IWICBitmapSource
*pIBitmapSource
, WICRect
*prc
)
415 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
417 TRACE("(%p,%p,%s)\n", iface
, pIBitmapSource
, debug_wic_rect(prc
));
419 if (!This
->initialized
)
420 return WINCODEC_ERR_WRONGSTATE
;
422 hr
= configure_write_source(iface
, pIBitmapSource
, prc
,
423 This
->encoder_frame
.bpp
? &This
->encoder_frame
.pixel_format
: NULL
,
424 This
->encoder_frame
.width
, This
->encoder_frame
.height
,
425 This
->encoder_frame
.dpix
, This
->encoder_frame
.dpiy
);
429 hr
= write_source(iface
, pIBitmapSource
, prc
,
430 &This
->encoder_frame
.pixel_format
, This
->encoder_frame
.bpp
,
431 !This
->encoder_frame
.num_colors
&& This
->encoder_frame
.indexed
,
432 This
->encoder_frame
.width
, This
->encoder_frame
.height
);
438 static HRESULT WINAPI
CommonEncoderFrame_Commit(IWICBitmapFrameEncode
*iface
)
440 CommonEncoderFrame
*This
= impl_from_IWICBitmapFrameEncode(iface
);
443 TRACE("(%p)\n", iface
);
445 EnterCriticalSection(&This
->parent
->lock
);
447 if (!This
->frame_created
|| This
->lines_written
!= This
->encoder_frame
.height
||
450 hr
= WINCODEC_ERR_WRONGSTATE
;
454 hr
= encoder_commit_frame(This
->parent
->encoder
);
457 This
->committed
= TRUE
;
458 This
->parent
->uncommitted_frame
= FALSE
;
462 LeaveCriticalSection(&This
->parent
->lock
);
467 static HRESULT WINAPI
CommonEncoderFrame_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface
,
468 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
470 CommonEncoderFrame
*encoder
= impl_from_IWICBitmapFrameEncode(iface
);
472 TRACE("iface, %p, ppIMetadataQueryWriter %p.\n", iface
, ppIMetadataQueryWriter
);
474 if (!ppIMetadataQueryWriter
)
477 if (!encoder
->initialized
)
478 return WINCODEC_ERR_NOTINITIALIZED
;
480 if (!(encoder
->parent
->encoder_info
.flags
& ENCODER_FLAGS_SUPPORTS_METADATA
))
481 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
483 return MetadataQueryWriter_CreateInstance(&encoder
->IWICMetadataBlockWriter_iface
, NULL
, ppIMetadataQueryWriter
);
486 static const IWICBitmapFrameEncodeVtbl CommonEncoderFrame_Vtbl
= {
487 CommonEncoderFrame_QueryInterface
,
488 CommonEncoderFrame_AddRef
,
489 CommonEncoderFrame_Release
,
490 CommonEncoderFrame_Initialize
,
491 CommonEncoderFrame_SetSize
,
492 CommonEncoderFrame_SetResolution
,
493 CommonEncoderFrame_SetPixelFormat
,
494 CommonEncoderFrame_SetColorContexts
,
495 CommonEncoderFrame_SetPalette
,
496 CommonEncoderFrame_SetThumbnail
,
497 CommonEncoderFrame_WritePixels
,
498 CommonEncoderFrame_WriteSource
,
499 CommonEncoderFrame_Commit
,
500 CommonEncoderFrame_GetMetadataQueryWriter
503 static HRESULT WINAPI
CommonEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
506 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
507 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
509 if (!ppv
) return E_INVALIDARG
;
511 if (IsEqualIID(&IID_IUnknown
, iid
) ||
512 IsEqualIID(&IID_IWICBitmapEncoder
, iid
))
514 *ppv
= &This
->IWICBitmapEncoder_iface
;
519 return E_NOINTERFACE
;
522 IUnknown_AddRef((IUnknown
*)*ppv
);
526 static ULONG WINAPI
CommonEncoder_AddRef(IWICBitmapEncoder
*iface
)
528 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
529 ULONG ref
= InterlockedIncrement(&This
->ref
);
531 TRACE("(%p) refcount=%u\n", iface
, ref
);
536 static ULONG WINAPI
CommonEncoder_Release(IWICBitmapEncoder
*iface
)
538 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
539 ULONG ref
= InterlockedDecrement(&This
->ref
);
541 TRACE("(%p) refcount=%u\n", iface
, ref
);
545 This
->lock
.DebugInfo
->Spare
[0] = 0;
546 DeleteCriticalSection(&This
->lock
);
548 IStream_Release(This
->stream
);
549 encoder_destroy(This
->encoder
);
550 HeapFree(GetProcessHeap(), 0, This
);
556 static HRESULT WINAPI
CommonEncoder_Initialize(IWICBitmapEncoder
*iface
,
557 IStream
*pIStream
, WICBitmapEncoderCacheOption cacheOption
)
559 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
562 TRACE("(%p,%p,%u)\n", iface
, pIStream
, cacheOption
);
567 EnterCriticalSection(&This
->lock
);
571 LeaveCriticalSection(&This
->lock
);
572 return WINCODEC_ERR_WRONGSTATE
;
575 hr
= encoder_initialize(This
->encoder
, pIStream
);
579 This
->stream
= pIStream
;
580 IStream_AddRef(This
->stream
);
583 LeaveCriticalSection(&This
->lock
);
588 static HRESULT WINAPI
CommonEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
, GUID
*format
)
590 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
591 TRACE("(%p,%p)\n", iface
, format
);
596 memcpy(format
, &This
->encoder_info
.container_format
, sizeof(*format
));
600 static HRESULT WINAPI
CommonEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
, IWICBitmapEncoderInfo
**info
)
602 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
603 IWICComponentInfo
*comp_info
;
606 TRACE("%p,%p\n", iface
, info
);
608 if (!info
) return E_INVALIDARG
;
610 hr
= CreateComponentInfo(&This
->encoder_info
.clsid
, &comp_info
);
613 hr
= IWICComponentInfo_QueryInterface(comp_info
, &IID_IWICBitmapEncoderInfo
, (void **)info
);
614 IWICComponentInfo_Release(comp_info
);
619 static HRESULT WINAPI
CommonEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
620 UINT cCount
, IWICColorContext
**ppIColorContext
)
622 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
626 static HRESULT WINAPI
CommonEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*palette
)
628 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
631 TRACE("(%p,%p)\n", iface
, palette
);
633 EnterCriticalSection(&This
->lock
);
635 hr
= This
->stream
? WINCODEC_ERR_UNSUPPORTEDOPERATION
: WINCODEC_ERR_NOTINITIALIZED
;
637 LeaveCriticalSection(&This
->lock
);
642 static HRESULT WINAPI
CommonEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
644 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
645 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
648 static HRESULT WINAPI
CommonEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
650 TRACE("(%p,%p)\n", iface
, pIPreview
);
651 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
654 static HRESULT WINAPI
CommonEncoderFrame_Block_QueryInterface(IWICMetadataBlockWriter
*iface
, REFIID iid
, void **ppv
)
656 CommonEncoderFrame
*encoder
= impl_from_IWICMetadataBlockWriter(iface
);
658 return IWICBitmapFrameEncode_QueryInterface(&encoder
->IWICBitmapFrameEncode_iface
, iid
, ppv
);
661 static ULONG WINAPI
CommonEncoderFrame_Block_AddRef(IWICMetadataBlockWriter
*iface
)
663 CommonEncoderFrame
*encoder
= impl_from_IWICMetadataBlockWriter(iface
);
665 return IWICBitmapFrameEncode_AddRef(&encoder
->IWICBitmapFrameEncode_iface
);
668 static ULONG WINAPI
CommonEncoderFrame_Block_Release(IWICMetadataBlockWriter
*iface
)
670 CommonEncoderFrame
*encoder
= impl_from_IWICMetadataBlockWriter(iface
);
672 return IWICBitmapFrameEncode_Release(&encoder
->IWICBitmapFrameEncode_iface
);
675 static HRESULT WINAPI
CommonEncoderFrame_Block_GetContainerFormat(IWICMetadataBlockWriter
*iface
, GUID
*container_format
)
677 FIXME("iface %p, container_format %p stub.\n", iface
, container_format
);
682 static HRESULT WINAPI
CommonEncoderFrame_Block_GetCount(IWICMetadataBlockWriter
*iface
, UINT
*count
)
684 FIXME("iface %p, count %p stub.\n", iface
, count
);
689 static HRESULT WINAPI
CommonEncoderFrame_Block_GetReaderByIndex(IWICMetadataBlockWriter
*iface
,
690 UINT index
, IWICMetadataReader
**metadata_reader
)
692 FIXME("iface %p, index %d, metadata_reader %p stub.\n", iface
, index
, metadata_reader
);
697 static HRESULT WINAPI
CommonEncoderFrame_Block_GetEnumerator(IWICMetadataBlockWriter
*iface
, IEnumUnknown
**enum_metadata
)
699 FIXME("iface %p, ppIEnumMetadata %p stub.\n", iface
, enum_metadata
);
704 static HRESULT WINAPI
CommonEncoderFrame_Block_InitializeFromBlockReader(IWICMetadataBlockWriter
*iface
,
705 IWICMetadataBlockReader
*metadata_block_reader
)
707 FIXME("iface %p, metadata_block_reader %p stub.\n", iface
, metadata_block_reader
);
712 static HRESULT WINAPI
CommonEncoderFrame_Block_GetWriterByIndex(IWICMetadataBlockWriter
*iface
, UINT index
,
713 IWICMetadataWriter
**metadata_writer
)
715 FIXME("iface %p, index %u, metadata_writer %p stub.\n", iface
, index
, metadata_writer
);
720 static HRESULT WINAPI
CommonEncoderFrame_Block_AddWriter(IWICMetadataBlockWriter
*iface
, IWICMetadataWriter
*metadata_writer
)
722 FIXME("iface %p, metadata_writer %p.\n", iface
, metadata_writer
);
727 static HRESULT WINAPI
CommonEncoderFrame_Block_SetWriterByIndex(IWICMetadataBlockWriter
*iface
, UINT index
,
728 IWICMetadataWriter
*metadata_writer
)
730 FIXME("iface %p, index %u, metadata_writer %p stub.\n", iface
, index
, metadata_writer
);
735 static HRESULT WINAPI
CommonEncoderFrame_Block_RemoveWriterByIndex(IWICMetadataBlockWriter
*iface
, UINT index
)
737 FIXME("iface %p, index %u.\n", iface
, index
);
742 static const IWICMetadataBlockWriterVtbl CommonEncoderFrame_BlockVtbl
=
744 CommonEncoderFrame_Block_QueryInterface
,
745 CommonEncoderFrame_Block_AddRef
,
746 CommonEncoderFrame_Block_Release
,
747 CommonEncoderFrame_Block_GetContainerFormat
,
748 CommonEncoderFrame_Block_GetCount
,
749 CommonEncoderFrame_Block_GetReaderByIndex
,
750 CommonEncoderFrame_Block_GetEnumerator
,
751 CommonEncoderFrame_Block_InitializeFromBlockReader
,
752 CommonEncoderFrame_Block_GetWriterByIndex
,
753 CommonEncoderFrame_Block_AddWriter
,
754 CommonEncoderFrame_Block_SetWriterByIndex
,
755 CommonEncoderFrame_Block_RemoveWriterByIndex
,
758 static HRESULT WINAPI
CommonEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
759 IWICBitmapFrameEncode
**ppIFrameEncode
, IPropertyBag2
**ppIEncoderOptions
)
761 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
762 CommonEncoderFrame
*result
;
767 TRACE("(%p,%p,%p)\n", iface
, ppIFrameEncode
, ppIEncoderOptions
);
769 EnterCriticalSection(&This
->lock
);
771 if (This
->frame_count
!= 0 && !(This
->encoder_info
.flags
& ENCODER_FLAGS_MULTI_FRAME
))
773 LeaveCriticalSection(&This
->lock
);
774 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
777 if (!This
->stream
|| This
->committed
|| This
->uncommitted_frame
)
779 LeaveCriticalSection(&This
->lock
);
780 return WINCODEC_ERR_NOTINITIALIZED
;
783 result
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*result
));
786 LeaveCriticalSection(&This
->lock
);
787 return E_OUTOFMEMORY
;
790 result
->IWICBitmapFrameEncode_iface
.lpVtbl
= &CommonEncoderFrame_Vtbl
;
791 result
->IWICMetadataBlockWriter_iface
.lpVtbl
= &CommonEncoderFrame_BlockVtbl
;
793 result
->parent
= This
;
795 if (ppIEncoderOptions
)
797 for (opts_length
= 0; This
->encoder_info
.encoder_options
[opts_length
] < ENCODER_OPTION_END
; opts_length
++)
799 opts
[opts_length
] = encoder_option_properties
[This
->encoder_info
.encoder_options
[opts_length
]];
802 hr
= CreatePropertyBag2(opts
, opts_length
, ppIEncoderOptions
);
805 LeaveCriticalSection(&This
->lock
);
806 HeapFree(GetProcessHeap(), 0, result
);
811 IWICBitmapEncoder_AddRef(iface
);
813 This
->uncommitted_frame
= TRUE
;
815 LeaveCriticalSection(&This
->lock
);
817 *ppIFrameEncode
= &result
->IWICBitmapFrameEncode_iface
;
822 static HRESULT WINAPI
CommonEncoder_Commit(IWICBitmapEncoder
*iface
)
824 CommonEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
827 TRACE("(%p)\n", iface
);
829 EnterCriticalSection(&This
->lock
);
831 if (This
->committed
|| This
->uncommitted_frame
)
832 hr
= WINCODEC_ERR_WRONGSTATE
;
835 hr
= encoder_commit_file(This
->encoder
);
837 This
->committed
= TRUE
;
840 LeaveCriticalSection(&This
->lock
);
845 static HRESULT WINAPI
CommonEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
846 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
848 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
852 static const IWICBitmapEncoderVtbl CommonEncoder_Vtbl
= {
853 CommonEncoder_QueryInterface
,
854 CommonEncoder_AddRef
,
855 CommonEncoder_Release
,
856 CommonEncoder_Initialize
,
857 CommonEncoder_GetContainerFormat
,
858 CommonEncoder_GetEncoderInfo
,
859 CommonEncoder_SetColorContexts
,
860 CommonEncoder_SetPalette
,
861 CommonEncoder_SetThumbnail
,
862 CommonEncoder_SetPreview
,
863 CommonEncoder_CreateNewFrame
,
864 CommonEncoder_Commit
,
865 CommonEncoder_GetMetadataQueryWriter
868 HRESULT
CommonEncoder_CreateInstance(struct encoder
*encoder
,
869 const struct encoder_info
*encoder_info
, REFIID iid
, void** ppv
)
874 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
878 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(CommonEncoder
));
881 encoder_destroy(encoder
);
882 return E_OUTOFMEMORY
;
885 This
->IWICBitmapEncoder_iface
.lpVtbl
= &CommonEncoder_Vtbl
;
888 This
->encoder
= encoder
;
889 This
->encoder_info
= *encoder_info
;
890 This
->frame_count
= 0;
891 This
->uncommitted_frame
= FALSE
;
892 This
->committed
= FALSE
;
893 InitializeCriticalSection(&This
->lock
);
894 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": CommonEncoder.lock");
896 ret
= IWICBitmapEncoder_QueryInterface(&This
->IWICBitmapEncoder_iface
, iid
, ppv
);
897 IWICBitmapEncoder_Release(&This
->IWICBitmapEncoder_iface
);