// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#ifdef __cplusplus
extern "C" {
#endif

#ifndef MP4PARSE_CAPI_H
#define MP4PARSE_CAPI_H

// THIS FILE IS AUTOGENERATED BY mp4parse_capi/build.rs - DO NOT EDIT

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef enum {
  MP4_PARSE_ENCRYPTION_SCHEME_TYPE_NONE,
  MP4_PARSE_ENCRYPTION_SCHEME_TYPE_CENC,
  MP4_PARSE_ENCRYPTION_SCHEME_TYPE_CBC1,
  MP4_PARSE_ENCRYPTION_SCHEME_TYPE_CENS,
  MP4_PARSE_ENCRYPTION_SCHEME_TYPE_CBCS,
} Mp4ParseEncryptionSchemeType;

typedef enum {
  MP4PARSE_CODEC_UNKNOWN,
  MP4PARSE_CODEC_AAC,
  MP4PARSE_CODEC_FLAC,
  MP4PARSE_CODEC_OPUS,
  MP4PARSE_CODEC_AVC,
  MP4PARSE_CODEC_VP9,
  MP4PARSE_CODEC_AV1,
  MP4PARSE_CODEC_MP3,
  MP4PARSE_CODEC_MP4V,
  MP4PARSE_CODEC_JPEG,
  MP4PARSE_CODEC_AC3,
  MP4PARSE_CODEC_EC3,
  MP4PARSE_CODEC_ALAC,
  MP4PARSE_CODEC_CRAW,
} Mp4parseCodec;

typedef enum {
  MP4PARSE_STATUS_OK = 0,
  MP4PARSE_STATUS_BAD_ARG = 1,
  MP4PARSE_STATUS_INVALID = 2,
  MP4PARSE_STATUS_UNSUPPORTED = 3,
  MP4PARSE_STATUS_EOF = 4,
  MP4PARSE_STATUS_IO = 5,
  MP4PARSE_STATUS_OOM = 6,
} Mp4parseStatus;

typedef enum {
  MP4PARSE_TRACK_TYPE_VIDEO = 0,
  MP4PARSE_TRACK_TYPE_AUDIO = 1,
  MP4PARSE_TRACK_TYPE_METADATA = 2,
} Mp4parseTrackType;

typedef struct Mp4parseAvifParser Mp4parseAvifParser;

typedef struct Mp4parseParser Mp4parseParser;

typedef struct {
  /**
   * The byte offset in the file where the indexed sample begins.
   */
  uint64_t start_offset;
  /**
   * The byte offset in the file where the indexed sample ends. This is
   * equivalent to `start_offset` + the length in bytes of the indexed
   * sample. Typically this will be the `start_offset` of the next sample
   * in the file.
   */
  uint64_t end_offset;
  /**
   * The time in microseconds when the indexed sample should be displayed.
   * Analogous to the concept of presentation time stamp (pts).
   */
  int64_t start_composition;
  /**
   * The time in microseconds when the indexed sample should stop being
   * displayed. Typically this would be the `start_composition` time of the
   * next sample if samples were ordered by composition time.
   */
  int64_t end_composition;
  /**
   * The time in microseconds that the indexed sample should be decoded at.
   * Analogous to the concept of decode time stamp (dts).
   */
  int64_t start_decode;
  /**
   * Set if the indexed sample is a sync sample. The meaning of sync is
   * somewhat codec specific, but essentially amounts to if the sample is a
   * key frame.
   */
  bool sync;
} Mp4parseIndice;

typedef struct {
  uint32_t length;
  const uint8_t *data;
  const Mp4parseIndice *indices;
} Mp4parseByteData;

typedef struct {
  intptr_t (*read)(uint8_t *buffer, uintptr_t size, void *userdata);
  void *userdata;
} Mp4parseIo;

typedef struct {
  Mp4parseByteData cncv;
  uint16_t thumb_w;
  uint16_t thumb_h;
  Mp4parseByteData thumbnail;
  Mp4parseByteData meta1;
  Mp4parseByteData meta2;
  Mp4parseByteData meta3;
  Mp4parseByteData meta4;
} Mp4parseCrawHeader;

typedef struct {
  uint64_t fragment_duration;
} Mp4parseFragmentInfo;

typedef struct {
  Mp4parseByteData data;
} Mp4parsePsshInfo;

typedef struct {
  Mp4ParseEncryptionSchemeType scheme_type;
  uint8_t is_encrypted;
  uint8_t iv_size;
  Mp4parseByteData kid;
  uint8_t crypt_byte_block;
  uint8_t skip_byte_block;
  Mp4parseByteData constant_iv;
} Mp4parseSinfInfo;

typedef struct {
  Mp4parseCodec codec_type;
  uint16_t channels;
  uint16_t bit_depth;
  uint32_t sample_rate;
  uint16_t profile;
  uint16_t extended_profile;
  Mp4parseByteData codec_specific_config;
  Mp4parseByteData extra_data;
  Mp4parseSinfInfo protected_data;
} Mp4parseTrackAudioSampleInfo;

typedef struct {
  uint32_t sample_info_count;
  const Mp4parseTrackAudioSampleInfo *sample_info;
} Mp4parseTrackAudioInfo;

typedef struct {
  Mp4parseTrackType track_type;
  uint32_t track_id;
  uint64_t duration;
  int64_t media_time;
} Mp4parseTrackInfo;

typedef struct {
  uint16_t image_width;
  uint16_t image_height;
  bool is_jpeg;
  uint64_t offset;
  uint64_t size;
} Mp4parseTrackRawInfo;

typedef struct {
  Mp4parseCodec codec_type;
  uint16_t image_width;
  uint16_t image_height;
  Mp4parseByteData extra_data;
  Mp4parseSinfInfo protected_data;
} Mp4parseTrackVideoSampleInfo;

typedef struct {
  uint32_t display_width;
  uint32_t display_height;
  uint16_t rotation;
  uint32_t sample_info_count;
  const Mp4parseTrackVideoSampleInfo *sample_info;
} Mp4parseTrackVideoInfo;

/**
 * Free an `Mp4parseAvifParser*` allocated by `mp4parse_avif_new()`.
 *
 * # Safety
 *
 * This function is unsafe because it creates a box from a raw pointer.
 * Callers should ensure that the parser pointer points to a valid
 * `Mp4parseAvifParser` created by `mp4parse_avif_new`.
 */
void mp4parse_avif_free(Mp4parseAvifParser *parser);

/**
 * Return a pointer to the primary item parsed by previous `mp4parse_avif_new()` call.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences both the parser and
 * primary_item raw pointers passed into it. Callers should ensure the parser
 * pointer points to a valid `Mp4parseAvifParser`, and that the primary_item
 * pointer points to a valid `Mp4parseByteData`. If there was not a previous
 * successful call to `mp4parse_avif_read()`, no guarantees are made as to
 * the state of `primary_item`.
 */
Mp4parseStatus mp4parse_avif_get_primary_item(Mp4parseAvifParser *parser,
                                              Mp4parseByteData *primary_item);

/**
 * Allocate an `Mp4parseAvifParser*` to read from the supplied `Mp4parseIo`.
 *
 * See mp4parse_new; this function is identical except that it allocates an
 * `Mp4parseAvifParser`, which (when successful) must be paired with a call
 * to mp4parse_avif_free.
 *
 * # Safety
 *
 * Same as mp4parse_new.
 */
Mp4parseStatus mp4parse_avif_new(const Mp4parseIo *io, Mp4parseAvifParser **parser_out);

/**
 * Free an `Mp4parseParser*` allocated by `mp4parse_new()`.
 *
 * # Safety
 *
 * This function is unsafe because it creates a box from a raw pointer.
 * Callers should ensure that the parser pointer points to a valid
 * `Mp4parseParser` created by `mp4parse_new`.
 */
void mp4parse_free(Mp4parseParser *parser);

Mp4parseStatus mp4parse_get_craw_header(Mp4parseParser *parser, Mp4parseCrawHeader *header);

Mp4parseStatus mp4parse_get_craw_table_entry(Mp4parseParser *parser,
                                             uintptr_t idx,
                                             uint64_t *offset,
                                             uint64_t *size);

/**
 * Fill the supplied `Mp4parseFragmentInfo` with metadata from fragmented file.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the the parser and
 * info raw pointers passed to it. Callers should ensure the parser
 * pointer points to a valid `Mp4parseParser` and that the info pointer points
 * to a valid `Mp4parseFragmentInfo`.
 */
Mp4parseStatus mp4parse_get_fragment_info(Mp4parseParser *parser, Mp4parseFragmentInfo *info);

/**
 * Fill the supplied `Mp4parseByteData` with index information from `track`.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the the parser and indices
 * raw pointers passed to it. Callers should ensure the parser pointer points
 * to a valid `Mp4parseParser` and that the indices pointer points to a valid
 * `Mp4parseByteData`.
 */
Mp4parseStatus mp4parse_get_indice_table(Mp4parseParser *parser,
                                         uint32_t track_id,
                                         Mp4parseByteData *indices);

/**
 * Get 'pssh' system id and 'pssh' box content for eme playback.
 *
 * The data format of the `info` struct passed to gecko is:
 *
 * - system id (16 byte uuid)
 * - pssh box size (32-bit native endian)
 * - pssh box content (including header)
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the the parser and
 * info raw pointers passed to it. Callers should ensure the parser
 * pointer points to a valid `Mp4parseParser` and that the fragmented pointer
 * points to a valid `Mp4parsePsshInfo`.
 */
Mp4parseStatus mp4parse_get_pssh_info(Mp4parseParser *parser, Mp4parsePsshInfo *info);

/**
 * Fill the supplied `Mp4parseTrackAudioInfo` with metadata for `track`.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the the parser and info raw
 * pointers passed to it. Callers should ensure the parser pointer points to a
 * valid `Mp4parseParser` and that the info pointer points to a valid
 * `Mp4parseTrackAudioInfo`.
 */
Mp4parseStatus mp4parse_get_track_audio_info(Mp4parseParser *parser,
                                             uint32_t track_index,
                                             Mp4parseTrackAudioInfo *info);

/**
 * Return the number of tracks parsed by previous `mp4parse_read()` call.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences both the parser and count
 * raw pointers passed into it. Callers should ensure the parser pointer
 * points to a valid `Mp4parseParser`, and that the count pointer points an
 * appropriate memory location to have a `u32` written to.
 */
Mp4parseStatus mp4parse_get_track_count(const Mp4parseParser *parser, uint32_t *count);

/**
 * Fill the supplied `Mp4parseTrackInfo` with metadata for `track`.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the the parser and info raw
 * pointers passed to it. Callers should ensure the parser pointer points to a
 * valid `Mp4parseParser` and that the info pointer points to a valid
 * `Mp4parseTrackInfo`.
 */
Mp4parseStatus mp4parse_get_track_info(Mp4parseParser *parser,
                                       uint32_t track_index,
                                       Mp4parseTrackInfo *info);

/**
 * File the supplied `Mp4parseTrackRawInfo` with metadata for `track`.
 */
Mp4parseStatus mp4parse_get_track_raw_info(Mp4parseParser *parser,
                                           uint32_t track_index,
                                           Mp4parseTrackRawInfo *info);

/**
 * Fill the supplied `Mp4parseTrackVideoInfo` with metadata for `track`.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the the parser and info raw
 * pointers passed to it. Callers should ensure the parser pointer points to a
 * valid `Mp4parseParser` and that the info pointer points to a valid
 * `Mp4parseTrackVideoInfo`.
 */
Mp4parseStatus mp4parse_get_track_video_info(Mp4parseParser *parser,
                                             uint32_t track_index,
                                             Mp4parseTrackVideoInfo *info);

/**
 * Determine if an mp4 file is fragmented. A fragmented file needs mvex table
 * and contains no data in stts, stsc, and stco boxes.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the the parser and
 * fragmented raw pointers passed to it. Callers should ensure the parser
 * pointer points to a valid `Mp4parseParser` and that the fragmented pointer
 * points to an appropriate memory location to have a `u8` written to.
 */
Mp4parseStatus mp4parse_is_fragmented(Mp4parseParser *parser,
                                      uint32_t track_id,
                                      uint8_t *fragmented);

/**
 * Allocate an `Mp4parseParser*` to read from the supplied `Mp4parseIo` and
 * parse the content from the `Mp4parseIo` argument until EOF or error.
 *
 * # Safety
 *
 * This function is unsafe because it dereferences the `io` and `parser_out`
 * pointers given to it. The caller should ensure that the `Mp4ParseIo`
 * struct passed in is a valid pointer. The caller should also ensure the
 * members of io are valid: the `read` function should be sanely implemented,
 * and the `userdata` pointer should be valid. The `parser_out` should be a
 * valid pointer to a location containing a null pointer. Upon successful
 * return (`Mp4parseStatus::Ok`), that location will contain the address of
 * an `Mp4parseParser` allocated by this function.
 *
 * To avoid leaking memory, any successful return of this function must be
 * paired with a call to `mp4parse_free`. In the event of error, no memory
 * will be allocated and `mp4parse_free` must *not* be called.
 */
Mp4parseStatus mp4parse_new(const Mp4parseIo *io, Mp4parseParser **parser_out);

#endif /* MP4PARSE_CAPI_H */

#ifdef __cplusplus
} /* extern "C" */
#endif
