1 // Copyright 2019 Joe Drago. All rights reserved.
2 // SPDX-License-Identifier: BSD-2-Clause
3 
4 #ifndef AVIF_INTERNAL_H
5 #define AVIF_INTERNAL_H
6 
7 #include "avif/avif.h"
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 // Yes, clamp macros are nasty. Do not use them.
14 #define AVIF_CLAMP(x, low, high) (((x) < (low)) ? (low) : (((high) < (x)) ? (high) : (x)))
15 #define AVIF_MIN(a, b) (((a) < (b)) ? (a) : (b))
16 #define AVIF_MAX(a, b) (((a) > (b)) ? (a) : (b))
17 
18 // Used by stream related things.
19 #define CHECK(A)               \
20     do {                       \
21         if (!(A))              \
22             return AVIF_FALSE; \
23     } while (0)
24 
25 // Used instead of CHECK if needing to return a specific error on failure, instead of AVIF_FALSE
26 #define CHECKERR(A, ERR) \
27     do {                 \
28         if (!(A))        \
29             return ERR;  \
30     } while (0)
31 
32 // ---------------------------------------------------------------------------
33 // URNs and Content-Types
34 
35 #define URN_ALPHA0 "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha"
36 #define URN_ALPHA1 "urn:mpeg:hevc:2015:auxid:1"
37 
38 #define CONTENT_TYPE_XMP "application/rdf+xml"
39 
40 // ---------------------------------------------------------------------------
41 // Utils
42 
43 float avifRoundf(float v);
44 
45 uint16_t avifHTONS(uint16_t s);
46 uint16_t avifNTOHS(uint16_t s);
47 uint32_t avifHTONL(uint32_t l);
48 uint32_t avifNTOHL(uint32_t l);
49 uint64_t avifHTON64(uint64_t l);
50 uint64_t avifNTOH64(uint64_t l);
51 
52 void avifCalcYUVCoefficients(const avifImage * image, float * outR, float * outG, float * outB);
53 
54 #define AVIF_ARRAY_DECLARE(TYPENAME, ITEMSTYPE, ITEMSNAME) \
55     typedef struct TYPENAME                                \
56     {                                                      \
57         ITEMSTYPE * ITEMSNAME;                             \
58         uint32_t elementSize;                              \
59         uint32_t count;                                    \
60         uint32_t capacity;                                 \
61     } TYPENAME
62 void avifArrayCreate(void * arrayStruct, uint32_t elementSize, uint32_t initialCapacity);
63 uint32_t avifArrayPushIndex(void * arrayStruct);
64 void * avifArrayPushPtr(void * arrayStruct);
65 void avifArrayPush(void * arrayStruct, void * element);
66 void avifArrayDestroy(void * arrayStruct);
67 
68 typedef struct avifAlphaParams
69 {
70     uint32_t width;
71     uint32_t height;
72 
73     uint32_t srcDepth;
74     avifRange srcRange;
75     uint8_t * srcPlane;
76     uint32_t srcRowBytes;
77     uint32_t srcOffsetBytes;
78     uint32_t srcPixelBytes;
79 
80     uint32_t dstDepth;
81     avifRange dstRange;
82     uint8_t * dstPlane;
83     uint32_t dstRowBytes;
84     uint32_t dstOffsetBytes;
85     uint32_t dstPixelBytes;
86 
87 } avifAlphaParams;
88 
89 avifBool avifFillAlpha(const avifAlphaParams * const params);
90 avifBool avifReformatAlpha(const avifAlphaParams * const params);
91 
92 typedef enum avifReformatMode
93 {
94     AVIF_REFORMAT_MODE_YUV_COEFFICIENTS = 0, // Normal YUV conversion using coefficients
95     AVIF_REFORMAT_MODE_IDENTITY,             // Pack GBR directly into YUV planes (AVIF_MATRIX_COEFFICIENTS_IDENTITY)
96     AVIF_REFORMAT_MODE_YCGCO                 // YUV conversion using AVIF_MATRIX_COEFFICIENTS_YCGCO
97 } avifReformatMode;
98 
99 typedef enum avifAlphaMultiplyMode
100 {
101     AVIF_ALPHA_MULTIPLY_MODE_NO_OP = 0,
102     AVIF_ALPHA_MULTIPLY_MODE_MULTIPLY,
103     AVIF_ALPHA_MULTIPLY_MODE_UNMULTIPLY
104 } avifAlphaMultiplyMode;
105 
106 typedef struct avifReformatState
107 {
108     // YUV coefficients
109     float kr;
110     float kg;
111     float kb;
112 
113     uint32_t yuvChannelBytes;
114     uint32_t rgbChannelBytes;
115     uint32_t rgbChannelCount;
116     uint32_t rgbPixelBytes;
117     uint32_t rgbOffsetBytesR;
118     uint32_t rgbOffsetBytesG;
119     uint32_t rgbOffsetBytesB;
120     uint32_t rgbOffsetBytesA;
121 
122     uint32_t yuvDepth;
123     avifRange yuvRange;
124     int yuvMaxChannel;
125     int rgbMaxChannel;
126     float rgbMaxChannelF;
127     float biasY;   // minimum Y value
128     float biasUV;  // the value of 0.5 for the appropriate bit depth [128, 512, 2048]
129     float biasA;   // minimum A value
130     float rangeY;  // difference between max and min Y
131     float rangeUV; // difference between max and min UV
132     float rangeA;  // difference between max and min A
133 
134     avifPixelFormatInfo formatInfo;
135 
136     // LUTs for going from YUV limited/full unorm -> full range RGB FP32
137     float unormFloatTableY[1 << 12];
138     float unormFloatTableUV[1 << 12];
139 
140     avifReformatMode mode;
141     // Used by avifImageYUVToRGB() only. avifImageRGBToYUV() uses a local variable (alphaMode) instead.
142     avifAlphaMultiplyMode toRGBAlphaMode;
143 } avifReformatState;
144 
145 // Returns:
146 // * AVIF_RESULT_OK              - Converted successfully with libyuv
147 // * AVIF_RESULT_NOT_IMPLEMENTED - The fast path for this combination is not implemented with libyuv, use built-in YUV conversion
148 // * [any other error]           - Return error to caller
149 avifResult avifImageYUVToRGBLibYUV(const avifImage * image, avifRGBImage * rgb);
150 
151 // Returns:
152 // * AVIF_RESULT_OK              - (Un)Premultiply successfully with libyuv
153 // * AVIF_RESULT_NOT_IMPLEMENTED - The fast path for this combination is not implemented with libyuv, use built-in (Un)Premultiply
154 // * [any other error]           - Return error to caller
155 avifResult avifRGBImagePremultiplyAlphaLibYUV(avifRGBImage * rgb);
156 avifResult avifRGBImageUnpremultiplyAlphaLibYUV(avifRGBImage * rgb);
157 
158 // ---------------------------------------------------------------------------
159 // Scaling
160 
161 // This scales the YUV/A planes in-place.
162 avifBool avifImageScale(avifImage * image, uint32_t dstWidth, uint32_t dstHeight, uint32_t imageSizeLimit, avifDiagnostics * diag);
163 
164 // ---------------------------------------------------------------------------
165 // avifCodecDecodeInput
166 
167 // Legal spatial_id values are [0,1,2,3], so this serves as a sentinel value for "do not filter by spatial_id"
168 #define AVIF_SPATIAL_ID_UNSET 0xff
169 
170 typedef struct avifDecodeSample
171 {
172     avifROData data;
173     avifBool ownsData;
174     avifBool partialData; // if true, data exists but doesn't have all of the sample in it
175 
176     uint32_t itemID;   // if non-zero, data comes from a mergedExtents buffer in an avifDecoderItem, not a file offset
177     uint64_t offset;   // additional offset into data. Can be used to offset into an itemID's payload as well.
178     size_t size;       //
179     uint8_t spatialID; // If set to a value other than AVIF_SPATIAL_ID_UNSET, output frames from this sample should be
180                        // skipped until the output frame's spatial_id matches this ID.
181     avifBool sync;     // is sync sample (keyframe)
182 } avifDecodeSample;
183 AVIF_ARRAY_DECLARE(avifDecodeSampleArray, avifDecodeSample, sample);
184 
185 typedef struct avifCodecDecodeInput
186 {
187     avifDecodeSampleArray samples;
188     avifBool allLayers; // if true, the underlying codec must decode all layers, not just the best layer
189     avifBool alpha;     // if true, this is decoding an alpha plane
190 } avifCodecDecodeInput;
191 
192 avifCodecDecodeInput * avifCodecDecodeInputCreate(void);
193 void avifCodecDecodeInputDestroy(avifCodecDecodeInput * decodeInput);
194 
195 // ---------------------------------------------------------------------------
196 // avifCodecEncodeOutput
197 
198 typedef struct avifEncodeSample
199 {
200     avifRWData data;
201     avifBool sync; // is sync sample (keyframe)
202 } avifEncodeSample;
203 AVIF_ARRAY_DECLARE(avifEncodeSampleArray, avifEncodeSample, sample);
204 
205 typedef struct avifCodecEncodeOutput
206 {
207     avifEncodeSampleArray samples;
208 } avifCodecEncodeOutput;
209 
210 avifCodecEncodeOutput * avifCodecEncodeOutputCreate(void);
211 void avifCodecEncodeOutputAddSample(avifCodecEncodeOutput * encodeOutput, const uint8_t * data, size_t len, avifBool sync);
212 void avifCodecEncodeOutputDestroy(avifCodecEncodeOutput * encodeOutput);
213 
214 // ---------------------------------------------------------------------------
215 // avifCodecSpecificOptions (key/value string pairs for advanced tuning)
216 
217 typedef struct avifCodecSpecificOption
218 {
219     char * key;   // Must be a simple lowercase alphanumeric string
220     char * value; // Free-form string to be interpreted by the codec
221 } avifCodecSpecificOption;
222 AVIF_ARRAY_DECLARE(avifCodecSpecificOptions, avifCodecSpecificOption, entries);
223 avifCodecSpecificOptions * avifCodecSpecificOptionsCreate(void);
224 void avifCodecSpecificOptionsDestroy(avifCodecSpecificOptions * csOptions);
225 void avifCodecSpecificOptionsSet(avifCodecSpecificOptions * csOptions, const char * key, const char * value); // if(value==NULL), key is deleted
226 
227 // ---------------------------------------------------------------------------
228 // avifCodec (abstraction layer to use different AV1 implementations)
229 
230 struct avifCodec;
231 struct avifCodecInternal;
232 
233 typedef avifBool (*avifCodecGetNextImageFunc)(struct avifCodec * codec,
234                                               struct avifDecoder * decoder,
235                                               const avifDecodeSample * sample,
236                                               avifBool alpha,
237                                               avifImage * image);
238 // EncodeImage and EncodeFinish are not required to always emit a sample, but when all images are
239 // encoded and EncodeFinish is called, the number of samples emitted must match the number of submitted frames.
240 // avifCodecEncodeImageFunc may return AVIF_RESULT_UNKNOWN_ERROR to automatically emit the appropriate
241 // AVIF_RESULT_ENCODE_COLOR_FAILED or AVIF_RESULT_ENCODE_ALPHA_FAILED depending on the alpha argument.
242 typedef avifResult (*avifCodecEncodeImageFunc)(struct avifCodec * codec,
243                                                avifEncoder * encoder,
244                                                const avifImage * image,
245                                                avifBool alpha,
246                                                avifAddImageFlags addImageFlags,
247                                                avifCodecEncodeOutput * output);
248 typedef avifBool (*avifCodecEncodeFinishFunc)(struct avifCodec * codec, avifCodecEncodeOutput * output);
249 typedef void (*avifCodecDestroyInternalFunc)(struct avifCodec * codec);
250 
251 typedef struct avifCodec
252 {
253     avifCodecSpecificOptions * csOptions; // Contains codec-specific key/value pairs for advanced tuning.
254                                           // If a codec uses a value, it must mark it as used.
255                                           // This array is NOT owned by avifCodec.
256     struct avifCodecInternal * internal;  // up to each codec to use how it wants
257                                           //
258     avifDiagnostics * diag;               // Shallow copy; owned by avifEncoder or avifDecoder
259                                           //
260     uint8_t operatingPoint;               // Operating point, defaults to 0.
261     avifBool allLayers;                   // if true, the underlying codec must decode all layers, not just the best layer
262 
263     avifCodecGetNextImageFunc getNextImage;
264     avifCodecEncodeImageFunc encodeImage;
265     avifCodecEncodeFinishFunc encodeFinish;
266     avifCodecDestroyInternalFunc destroyInternal;
267 } avifCodec;
268 
269 avifCodec * avifCodecCreate(avifCodecChoice choice, avifCodecFlags requiredFlags);
270 void avifCodecDestroy(avifCodec * codec);
271 
272 avifCodec * avifCodecCreateAOM(void);     // requires AVIF_CODEC_AOM (codec_aom.c)
273 const char * avifCodecVersionAOM(void);   // requires AVIF_CODEC_AOM (codec_aom.c)
274 avifCodec * avifCodecCreateDav1d(void);   // requires AVIF_CODEC_DAV1D (codec_dav1d.c)
275 const char * avifCodecVersionDav1d(void); // requires AVIF_CODEC_DAV1D (codec_dav1d.c)
276 avifCodec * avifCodecCreateGav1(void);    // requires AVIF_CODEC_LIBGAV1 (codec_libgav1.c)
277 const char * avifCodecVersionGav1(void);  // requires AVIF_CODEC_LIBGAV1 (codec_libgav1.c)
278 avifCodec * avifCodecCreateRav1e(void);   // requires AVIF_CODEC_RAV1E (codec_rav1e.c)
279 const char * avifCodecVersionRav1e(void); // requires AVIF_CODEC_RAV1E (codec_rav1e.c)
280 avifCodec * avifCodecCreateSvt(void);     // requires AVIF_CODEC_SVT (codec_svt.c)
281 const char * avifCodecVersionSvt(void);   // requires AVIF_CODEC_SVT (codec_svt.c)
282 
283 // ---------------------------------------------------------------------------
284 // avifDiagnostics
285 
286 #ifdef __clang__
287 __attribute__((__format__(__printf__, 2, 3)))
288 #endif
289 void avifDiagnosticsPrintf(avifDiagnostics * diag, const char * format, ...);
290 
291 // ---------------------------------------------------------------------------
292 // avifStream
293 
294 typedef size_t avifBoxMarker;
295 
296 typedef struct avifBoxHeader
297 {
298     size_t size;
299     uint8_t type[4];
300 } avifBoxHeader;
301 
302 typedef struct avifROStream
303 {
304     avifROData * raw;
305     size_t offset;
306     avifDiagnostics * diag;
307     const char * diagContext;
308 } avifROStream;
309 
310 const uint8_t * avifROStreamCurrent(avifROStream * stream);
311 void avifROStreamStart(avifROStream * stream, avifROData * raw, avifDiagnostics * diag, const char * diagContext);
312 size_t avifROStreamOffset(const avifROStream * stream);
313 void avifROStreamSetOffset(avifROStream * stream, size_t offset);
314 
315 avifBool avifROStreamHasBytesLeft(const avifROStream * stream, size_t byteCount);
316 size_t avifROStreamRemainingBytes(const avifROStream * stream);
317 avifBool avifROStreamSkip(avifROStream * stream, size_t byteCount);
318 avifBool avifROStreamRead(avifROStream * stream, uint8_t * data, size_t size);
319 avifBool avifROStreamReadU16(avifROStream * stream, uint16_t * v);
320 avifBool avifROStreamReadU32(avifROStream * stream, uint32_t * v);
321 avifBool avifROStreamReadUX8(avifROStream * stream, uint64_t * v, uint64_t factor); // Reads a factor*8 sized uint, saves in v
322 avifBool avifROStreamReadU64(avifROStream * stream, uint64_t * v);
323 avifBool avifROStreamReadString(avifROStream * stream, char * output, size_t outputSize);
324 avifBool avifROStreamReadBoxHeader(avifROStream * stream, avifBoxHeader * header); // This fails if the size reported by the header cannot fit in the stream
325 avifBool avifROStreamReadBoxHeaderPartial(avifROStream * stream, avifBoxHeader * header); // This doesn't require that the full box can fit in the stream
326 avifBool avifROStreamReadVersionAndFlags(avifROStream * stream, uint8_t * version, uint32_t * flags); // version and flags ptrs are both optional
327 avifBool avifROStreamReadAndEnforceVersion(avifROStream * stream, uint8_t enforcedVersion); // currently discards flags
328 
329 typedef struct avifRWStream
330 {
331     avifRWData * raw;
332     size_t offset;
333 } avifRWStream;
334 
335 uint8_t * avifRWStreamCurrent(avifRWStream * stream);
336 void avifRWStreamStart(avifRWStream * stream, avifRWData * raw);
337 size_t avifRWStreamOffset(const avifRWStream * stream);
338 void avifRWStreamSetOffset(avifRWStream * stream, size_t offset);
339 
340 void avifRWStreamFinishWrite(avifRWStream * stream);
341 void avifRWStreamWrite(avifRWStream * stream, const void * data, size_t size);
342 void avifRWStreamWriteChars(avifRWStream * stream, const char * chars, size_t size);
343 avifBoxMarker avifRWStreamWriteBox(avifRWStream * stream, const char * type, size_t contentSize);
344 avifBoxMarker avifRWStreamWriteFullBox(avifRWStream * stream, const char * type, size_t contentSize, int version, uint32_t flags);
345 void avifRWStreamFinishBox(avifRWStream * stream, avifBoxMarker marker);
346 void avifRWStreamWriteU8(avifRWStream * stream, uint8_t v);
347 void avifRWStreamWriteU16(avifRWStream * stream, uint16_t v);
348 void avifRWStreamWriteU32(avifRWStream * stream, uint32_t v);
349 void avifRWStreamWriteU64(avifRWStream * stream, uint64_t v);
350 void avifRWStreamWriteZeros(avifRWStream * stream, size_t byteCount);
351 
352 // This is to make it clear that the box size is currently unknown, and will be determined later (with a call to avifRWStreamFinishBox)
353 #define AVIF_BOX_SIZE_TBD 0
354 
355 typedef struct avifSequenceHeader
356 {
357     uint32_t maxWidth;
358     uint32_t maxHeight;
359     uint32_t bitDepth;
360     avifPixelFormat yuvFormat;
361     avifChromaSamplePosition chromaSamplePosition;
362     avifColorPrimaries colorPrimaries;
363     avifTransferCharacteristics transferCharacteristics;
364     avifMatrixCoefficients matrixCoefficients;
365     avifRange range;
366     avifCodecConfigurationBox av1C;
367 } avifSequenceHeader;
368 avifBool avifSequenceHeaderParse(avifSequenceHeader * header, const avifROData * sample);
369 
370 #ifdef __cplusplus
371 } // extern "C"
372 #endif
373 
374 #endif // ifndef AVIF_INTERNAL_H
375