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  /** Used for versioning the decode pipeline in the future
59  *
60  * \ref EXR_ENCODE_PIPELINE_INITIALIZER
61  */
62  size_t pipe_size;
63 
64  /** The output channel information for this chunk.
65  *
66  * User is expected to fill the channel pointers for the input
67  * channels. For writing, all channels must be initialized prior
68  * to using exr_encoding_choose_default_routines(). If a custom pack routine
69  * is written, that is up to the implementor.
70  *
71  * Describes the channel information. This information is
72  * allocated dynamically during exr_encoding_initialize().
73  */
75  int16_t channel_count;
76 
77  /** Encode flags to control the behavior. */
78  uint16_t encode_flags;
79 
80  /** Copy of the parameters given to the initialize/update for convenience. */
84 
85  /** Can be used by the user to pass custom context data through
86  * the encode pipeline.
87  */
89 
90  /** The packed buffer where individual channels have been put into here.
91  *
92  * If `NULL`, will be allocated during the run of the pipeline.
93  *
94  * If the caller wishes to take control of the buffer, simple
95  * adopt the pointer and set it to `NULL` here. Be cognizant of any
96  * custom allocators.
97  */
99 
100  /** Differing from the allocation size, the number of actual bytes */
101  uint64_t packed_bytes;
102 
103  /** Used when re-using the same encode pipeline struct to know if
104  * chunk is changed size whether current buffer is large enough
105  *
106  * If `NULL`, will be allocated during the run of the pipeline.
107  *
108  * If the caller wishes to take control of the buffer, simple
109  * adopt the pointer and set it to `NULL` here. Be cognizant of any
110  * custom allocators.
111  */
113 
114  /** For deep data. NB: the members NOT const because we need to
115  * temporarily swap it to xdr order and restore it (to avoid a
116  * duplicate buffer allocation).
117  *
118  * Depending on the flag set above, will be treated either as a
119  * cumulative list (n, n+m, n+m+o, ...), or an individual table
120  * (n, m, o, ...). */
122 
123  /** Allocated table size (to avoid re-allocations). Number of
124  * samples must always be width * height for the chunk.
125  */
127 
128  /** Packed sample table (compressed, raw on disk representation)
129  * for deep or other non-image data.
130  */
132 
133  /** Number of bytes to write (actual size) for the
134  * packed_sample_count_table.
135  */
137 
138  /** Allocated size (to avoid re-allocations) for the
139  * packed_sample_count_table.
140  */
142 
143  /** The compressed buffer, only needed for compressed files.
144  *
145  * If `NULL`, will be allocated during the run of the pipeline when
146  * needed.
147  *
148  * If the caller wishes to take control of the buffer, simple
149  * adopt the pointer and set it to `NULL` here. Be cognizant of any
150  * custom allocators.
151  */
153 
154  /** Must be filled in as the pipeline runs to inform the writing
155  * software about the compressed size of the chunk (if it is an
156  * uncompressed file or the compression would make the file
157  * larger, it is expected to be the packed_buffer)
158  *
159  * If the caller wishes to take control of the buffer, simple
160  * adopt the pointer and set it to zero here. Be cognizant of any
161  * custom allocators.
162  */
164 
165  /** Used when re-using the same encode pipeline struct to know if
166  * chunk is changed size whether current buffer is large enough.
167  *
168  * If `NULL`, will be allocated during the run of the pipeline when
169  * needed.
170  *
171  * If the caller wishes to take control of the buffer, simple
172  * adopt the pointer and set it to zero here. Be cognizant of any
173  * custom allocators.
174  */
176 
177  /** A scratch buffer for intermediate results.
178  *
179  * If `NULL`, will be allocated during the run of the pipeline when
180  * needed.
181  *
182  * If the caller wishes to take control of the buffer, simple
183  * adopt the pointer and set it to `NULL` here. Be cognizant of any
184  * custom allocators.
185  */
187 
188  /** Used when re-using the same encode pipeline struct to know if
189  * chunk is changed size whether current buffer is large enough.
190  *
191  * If `NULL`, will be allocated during the run of the pipeline when
192  * needed.
193  *
194  * If the caller wishes to take control of the buffer, simple
195  * adopt the pointer and set it to `NULL` here. Be cognizant of any
196  * custom allocators.
197  */
199 
200  /** Some compression routines may need a second scratch buffer.
201  *
202  * If `NULL`, will be allocated during the run of the pipeline when
203  * needed.
204  *
205  * If the caller wishes to take control of the buffer, simple
206  * adopt the pointer and set it to `NULL` here. Be cognizant of any
207  * custom allocators.
208  */
210 
211  /** Used when re-using the same encode pipeline struct to know if
212  * chunk is changed size whether current buffer is large enough.
213  */
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  */
220  void* (*alloc_fn) (exr_transcoding_pipeline_buffer_id_t, size_t);
221 
222  /** Enable a custom allocator for the different buffers (if
223  * encoding on a GPU). If `NULL`, will use the allocator from the
224  * context.
225  */
227 
228  /** Function chosen based on the output layout of the channels of the part to
229  * decompress data.
230  *
231  * If the user has a custom method for the
232  * compression on this part, this can be changed after
233  * initialization.
234  */
236 
237  /** Function chosen based on the compression type of the part to
238  * compress data.
239  *
240  * If the user has a custom compression method for the compression
241  * type on this part, this can be changed after initialization.
242  */
244 
245  /** This routine is used when waiting for other threads to finish
246  * writing previous chunks such that this thread can write this
247  * chunk. This is used for parts which have a specified chunk
248  * ordering (increasing/decreasing y) and the chunks can not be
249  * written randomly (as could be true for uncompressed).
250  *
251  * This enables the calling application to contribute thread time
252  * to other computation as needed, or just use something like
253  * pthread_yield().
254  *
255  * By default, this routine will be assigned to a function which
256  * returns an error, failing the encode immediately. In this way,
257  * it assumes that there is only one thread being used for
258  * writing.
259  *
260  * It is up to the user to provide an appropriate routine if
261  * performing multi-threaded writing.
262  */
264  struct _exr_encode_pipeline* pipeline);
265 
266  /** Function chosen to write chunk data to the context.
267  *
268  * This is allowed to be overridden, but probably is not necessary
269  * in most scenarios.
270  */
272 
273  /** Small stash of channel info values. This is faster than calling
274  * malloc when the channel count in the part is small (RGBAZ),
275  * which is super common, however if there are a large number of
276  * channels, it will allocate space for that, so do not rely on
277  * this being used.
278  */
281 
282 /** @brief Simple macro to initialize an empty decode pipeline. */
283 #define EXR_ENCODE_PIPELINE_INITIALIZER \
284  { \
285  sizeof(exr_encode_pipeline_t), 0 \
286  }
287 
288 /** Initialize the encoding pipeline structure with the channel info
289  * for the specified part based on the chunk to be written.
290  *
291  * NB: The encode_pipe->pack_and_convert_fn field will be `NULL` after this. If that
292  * stage is desired, initialize the channel output information and
293  * call exr_encoding_choose_default_routines().
294  */
297  exr_const_context_t ctxt,
298  int part_index,
299  const exr_chunk_info_t* cinfo,
300  exr_encode_pipeline_t* encode_pipe);
301 
302 /** Given an initialized encode pipeline, find an appropriate
303  * function to shuffle and convert data into the defined channel
304  * outputs.
305  *
306  * Calling this is not required if a custom routine will be used, or
307  * if just the raw decompressed data is desired.
308  */
311  exr_const_context_t ctxt,
312  int part_index,
313  exr_encode_pipeline_t* encode_pipe);
314 
315 /** Given a encode pipeline previously initialized, update it for the
316  * new chunk to be written.
317  *
318  * In this manner, memory buffers can be re-used to avoid continual
319  * malloc/free calls. Further, it allows the previous choices for
320  * the various functions to be quickly re-used.
321  */
324  exr_const_context_t ctxt,
325  int part_index,
326  const exr_chunk_info_t* cinfo,
327  exr_encode_pipeline_t* encode_pipe);
328 
329 /** Execute the encoding pipeline. */
332  exr_const_context_t ctxt,
333  int part_index,
334  exr_encode_pipeline_t* encode_pipe);
335 
336 /** Free any intermediate memory in the encoding pipeline.
337  *
338  * This does NOT free any pointers referred to in the channel info
339  * areas, but rather only the intermediate buffers and memory needed
340  * for the structure itself.
341  */
344  exr_const_context_t ctxt, exr_encode_pipeline_t* encode_pipe);
345 
346 #ifdef __cplusplus
347 } /* extern "C" */
348 #endif
349 
350 #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)