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