HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
openexr_encode.h
Go to the documentation of this file.
1 /*
2 ** SPDX-License-Identifier: BSD-3-Clause
3 ** Copyright Contributors to the OpenEXR Project.
4 */
5 
6 #ifndef OPENEXR_CORE_ENCODE_H
7 #define OPENEXR_CORE_ENCODE_H
8 
9 #include "openexr_chunkio.h"
10 #include "openexr_coding.h"
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /** @file */
17 
18 /** Can be bit-wise or'ed into the decode_flags in the decode pipeline.
19  *
20  * Indicates that the sample count table should be encoded from an
21  * individual sample count list (n, m, o, ...), meaning it will have
22  * to compute the cumulative counts on the fly.
23  *
24  * Without this (i.e. a value of 0 in that bit), indicates the sample
25  * count table is already a cumulative list (n, n+m, n+m+o, ...),
26  * which is the on-disk representation.
27  */
28 #define EXR_ENCODE_DATA_SAMPLE_COUNTS_ARE_INDIVIDUAL ((uint16_t) (1 << 0))
29 
30 /** Can be bit-wise or'ed into the decode_flags in the decode pipeline.
31  *
32  * Indicates that the data in the channel pointers to encode from is not
33  * a direct pointer, but instead is a pointer-to-pointers. In this
34  * mode, the user_pixel_stride and user_line_stride are used to
35  * advance the pointer offsets for each pixel in the output, but the
36  * user_bytes_per_element and user_data_type are used to put
37  * (successive) entries into each destination.
38  *
39  * So each channel pointer must then point to an array of
40  * chunk.width * chunk.height pointers. If an entry is
41  * `NULL`, 0 samples will be placed in the output.
42  *
43  * If this is NOT set (0), the default packing routine assumes the
44  * data will be planar and contiguous (each channel is a separate
45  * memory block), ignoring user_line_stride and user_pixel_stride and
46  * advancing only by the sample counts and bytes per element.
47  */
48 #define EXR_ENCODE_NON_IMAGE_DATA_AS_POINTERS ((uint16_t) (1 << 1))
49 
50 /** Struct meant to be used on a per-thread basis for writing exr data.
51  *
52  * As should be obvious, this structure is NOT thread safe, but rather
53  * meant to be used by separate threads, which can all be accessing
54  * the same context concurrently.
55  */
56 typedef struct _exr_encode_pipeline
57 {
58  /** The output channel information for this chunk.
59  *
60  * User is expected to fill the channel pointers for the input
61  * channels. For writing, all channels must be initialized prior
62  * to using exr_encoding_choose_default_routines(). If a custom pack routine
63  * is written, that is up to the implementor.
64  *
65  * Describes the channel information. This information is
66  * allocated dynamically during exr_encoding_initialize().
67  */
69  int16_t channel_count;
70 
71  /** Encode flags to control the behavior. */
72  uint16_t encode_flags;
73 
74  /** Copy of the parameters given to the initialize/update for convenience. */
78 
79  /** Can be used by the user to pass custom context data through
80  * the encode pipeline.
81  */
83 
84  /** The packed buffer where individual channels have been put into here.
85  *
86  * If `NULL`, will be allocated during the run of the pipeline.
87  *
88  * If the caller wishes to take control of the buffer, simple
89  * adopt the pointer and set it to `NULL` here. Be cognizant of any
90  * custom allocators.
91  */
93 
94  /** Differing from the allocation size, the number of actual bytes */
95  uint64_t packed_bytes;
96 
97  /** Used when re-using the same encode pipeline struct to know if
98  * chunk is changed size whether current buffer is large enough
99  *
100  * If `NULL`, will be allocated during the run of the pipeline.
101  *
102  * If the caller wishes to take control of the buffer, simple
103  * adopt the pointer and set it to `NULL` here. Be cognizant of any
104  * custom allocators.
105  */
107 
108  /** For deep data. NB: the members NOT const because we need to
109  * temporarily swap it to xdr order and restore it (to avoid a
110  * duplicate buffer allocation).
111  *
112  * Depending on the flag set above, will be treated either as a
113  * cumulative list (n, n+m, n+m+o, ...), or an individual table
114  * (n, m, o, ...). */
116 
117  /** Allocated table size (to avoid re-allocations). Number of
118  * samples must always be width * height for the chunk.
119  */
121 
122  /** Packed sample table (compressed, raw on disk representation)
123  * for deep or other non-image data.
124  */
126 
127  /** Number of bytes to write (actual size) for the
128  * packed_sample_count_table.
129  */
131 
132  /** Allocated size (to avoid re-allocations) for the
133  * packed_sample_count_table.
134  */
136 
137  /** The compressed buffer, only needed for compressed files.
138  *
139  * If `NULL`, will be allocated during the run of the pipeline when
140  * needed.
141  *
142  * If the caller wishes to take control of the buffer, simple
143  * adopt the pointer and set it to `NULL` here. Be cognizant of any
144  * custom allocators.
145  */
147 
148  /** Must be filled in as the pipeline runs to inform the writing
149  * software about the compressed size of the chunk (if it is an
150  * uncompressed file or the compression would make the file
151  * larger, it is expected to be the packed_buffer)
152  *
153  * If the caller wishes to take control of the buffer, simple
154  * adopt the pointer and set it to zero here. Be cognizant of any
155  * custom allocators.
156  */
158 
159  /** Used when re-using the same encode pipeline struct to know if
160  * chunk is changed size whether current buffer is large enough.
161  *
162  * If `NULL`, will be allocated during the run of the pipeline when
163  * needed.
164  *
165  * If the caller wishes to take control of the buffer, simple
166  * adopt the pointer and set it to zero here. Be cognizant of any
167  * custom allocators.
168  */
170 
171  /** A scratch buffer for intermediate results.
172  *
173  * If `NULL`, will be allocated during the run of the pipeline when
174  * needed.
175  *
176  * If the caller wishes to take control of the buffer, simple
177  * adopt the pointer and set it to `NULL` here. Be cognizant of any
178  * custom allocators.
179  */
181 
182  /** Used when re-using the same encode pipeline struct to know if
183  * chunk is changed size whether current buffer is large enough.
184  *
185  * If `NULL`, will be allocated during the run of the pipeline when
186  * needed.
187  *
188  * If the caller wishes to take control of the buffer, simple
189  * adopt the pointer and set it to `NULL` here. Be cognizant of any
190  * custom allocators.
191  */
193 
194  /** Some compression routines may need a second scratch buffer.
195  *
196  * If `NULL`, will be allocated during the run of the pipeline when
197  * needed.
198  *
199  * If the caller wishes to take control of the buffer, simple
200  * adopt the pointer and set it to `NULL` here. Be cognizant of any
201  * custom allocators.
202  */
204 
205  /** Used when re-using the same encode pipeline struct to know if
206  * chunk is changed size whether current buffer is large enough.
207  */
209 
210  /** Enable a custom allocator for the different buffers (if
211  * encoding on a GPU). If `NULL`, will use the allocator from the
212  * context.
213  */
214  void* (*alloc_fn) (exr_transcoding_pipeline_buffer_id_t, size_t);
215 
216  /** Enable a custom allocator for the different buffers (if
217  * encoding on a GPU). If `NULL`, will use the allocator from the
218  * context.
219  */
221 
222  /** Function chosen based on the output layout of the channels of the part to
223  * decompress data.
224  *
225  * If the user has a custom method for the
226  * compression on this part, this can be changed after
227  * initialization.
228  */
230 
231  /** Function chosen based on the compression type of the part to
232  * compress data.
233  *
234  * If the user has a custom compression method for the compression
235  * type on this part, this can be changed after initialization.
236  */
238 
239  /** This routine is used when waiting for other threads to finish
240  * writing previous chunks such that this thread can write this
241  * chunk. This is used for parts which have a specified chunk
242  * ordering (increasing/decreasing y) and the chunks can not be
243  * written randomly (as could be true for uncompressed).
244  *
245  * This enables the calling application to contribute thread time
246  * to other computation as needed, or just use something like
247  * pthread_yield().
248  *
249  * By default, this routine will be assigned to a function which
250  * returns an error, failing the encode immediately. In this way,
251  * it assumes that there is only one thread being used for
252  * writing.
253  *
254  * It is up to the user to provide an appropriate routine if
255  * performing multi-threaded writing.
256  */
258  struct _exr_encode_pipeline* pipeline);
259 
260  /** Function chosen to write chunk data to the context.
261  *
262  * This is allowed to be overridden, but probably is not necessary
263  * in most scenarios.
264  */
266 
267  /** Small stash of channel info values. This is faster than calling
268  * malloc when the channel count in the part is small (RGBAZ),
269  * which is super common, however if there are a large number of
270  * channels, it will allocate space for that, so do not rely on
271  * this being used.
272  */
275 
276 /** @brief Simple macro to initialize an empty decode pipeline. */
277 #define EXR_ENCODE_PIPELINE_INITIALIZER \
278  { \
279  0 \
280  }
281 
282 /** Initialize the encoding pipeline structure with the channel info
283  * for the specified part based on the chunk to be written.
284  *
285  * NB: The encode_pipe->pack_and_convert_fn field will be `NULL` after this. If that
286  * stage is desired, initialize the channel output information and
287  * call exr_encoding_choose_default_routines().
288  */
291  exr_const_context_t ctxt,
292  int part_index,
293  const exr_chunk_info_t* cinfo,
294  exr_encode_pipeline_t* encode_pipe);
295 
296 /** Given an initialized encode pipeline, find an appropriate
297  * function to shuffle and convert data into the defined channel
298  * outputs.
299  *
300  * Calling this is not required if a custom routine will be used, or
301  * if just the raw decompressed data is desired.
302  */
305  exr_const_context_t ctxt,
306  int part_index,
307  exr_encode_pipeline_t* encode_pipe);
308 
309 /** Given a encode pipeline previously initialized, update it for the
310  * new chunk to be written.
311  *
312  * In this manner, memory buffers can be re-used to avoid continual
313  * malloc/free calls. Further, it allows the previous choices for
314  * the various functions to be quickly re-used.
315  */
318  exr_const_context_t ctxt,
319  int part_index,
320  const exr_chunk_info_t* cinfo,
321  exr_encode_pipeline_t* encode_pipe);
322 
323 /** Execute the encoding pipeline. */
326  exr_const_context_t ctxt,
327  int part_index,
328  exr_encode_pipeline_t* encode_pipe);
329 
330 /** Free any intermediate memory in the encoding pipeline.
331  *
332  * This does NOT free any pointers referred to in the channel info
333  * areas, but rather only the intermediate buffers and memory needed
334  * for the structure itself.
335  */
338  exr_const_context_t ctxt, exr_encode_pipeline_t* encode_pipe);
339 
340 #ifdef __cplusplus
341 } /* extern "C" */
342 #endif
343 
344 #endif /* OPENEXR_CORE_ENCODE_H */
exr_result_t(* yield_until_ready_fn)(struct _exr_encode_pipeline *pipeline)
struct _exr_encode_pipeline exr_encode_pipeline_t
EXR_EXPORT exr_result_t exr_encoding_run(exr_const_context_t ctxt, int part_index, exr_encode_pipeline_t *encode_pipe)
void
Definition: png.h:1083
Struct for negotiating buffers when decoding/encoding chunks of data.
enum exr_transcoding_pipeline_buffer_id exr_transcoding_pipeline_buffer_id_t
exr_coding_channel_info_t * channels
exr_result_t(* convert_and_pack_fn)(struct _exr_encode_pipeline *pipeline)
const struct _priv_exr_context_t * exr_const_context_t
exr_chunk_info_t chunk
exr_result_t(* write_fn)(struct _exr_encode_pipeline *pipeline)
EXR_EXPORT exr_result_t exr_encoding_initialize(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, exr_encode_pipeline_t *encode_pipe)
exr_const_context_t context
int32_t exr_result_t
exr_result_t(* compress_fn)(struct _exr_encode_pipeline *pipeline)
#define EXR_EXPORT
EXR_EXPORT exr_result_t exr_encoding_update(exr_const_context_t ctxt, int part_index, const exr_chunk_info_t *cinfo, exr_encode_pipeline_t *encode_pipe)
EXR_EXPORT exr_result_t exr_encoding_destroy(exr_const_context_t ctxt, exr_encode_pipeline_t *encode_pipe)
exr_coding_channel_info_t _quick_chan_store[5]
size_t packed_sample_count_alloc_size
int32_t * sample_count_table
void(* free_fn)(exr_transcoding_pipeline_buffer_id_t, void *)
EXR_EXPORT exr_result_t exr_encoding_choose_default_routines(exr_const_context_t ctxt, int part_index, exr_encode_pipeline_t *encode_pipe)