openexr_encode.h 12 KB

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