/* avi.h
 * AVI container format
 * Copyright(c) 2024 Sensoray Co., Inc.
 */

#ifndef _AVI_12347890_H
#define _AVI_12347890_H

#include <stdio.h> // for FILE

#if defined(_WIN32) && !defined(__MINGW32__)
// Windows
// calling convention
#define AVICC __stdcall
// additional parameters
#define AVIAPI
#else
// Linux
#define AVICC
#define AVIAPI extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct muxavi_state;
typedef struct muxavi_state *muxavi_handle;

/* creation and deletion */
//aud_sr == audio_sample_rate
#define AVI_AUDTYPE_NONE 0x0000
#define AVI_AUDTYPE_PCM  0x0001
#define AVI_AUDTYPE_AAC  0x00ff // raw AAC without ADTS
#define AVI_AUDTYPE_MP2  0x0050
#define AVI_AUDTYPE_MP3  0x0055
#define AVI_AUDTYPE_HEAAC 0x1610
#define AVI_AUDTYPE_AAC_ADTS 0x1600
//#define AVI_AUDTYPE_AAC_ADTS 0x2000

// audio bitrate. kbits/s
AVIAPI muxavi_handle AVICC avi_writer_create(int w, int h, int bitrate, int fr,
					int audio_type, int aud_sr, int aud_br);
AVIAPI void AVICC avi_write_headers(muxavi_handle m);
AVIAPI void AVICC avi_delete(muxavi_handle mux);
/* turn on/off debugging */
AVIAPI void AVICC avi_debug(muxavi_handle mux, int debug);

/* associate a reader/writer with an open file descriptor or pointer */
AVIAPI void AVICC avi_file_descriptor(muxavi_handle mux, int fd);
AVIAPI void AVICC avi_file_pointer(muxavi_handle mux, FILE *file);
AVIAPI void AVICC avi_file2_pointer(muxavi_handle mux, FILE *file);
AVIAPI void AVICC avi_file_name_ascii(muxavi_handle mux, char *fname);

/* when a reader/writer is not associated with a file,
   memory buffers must be transferred for read/write using these two functions: */
/* give a buffer to the muxer to write to, or read from */
AVIAPI void AVICC avi_buf_put(muxavi_handle mux, unsigned char* buf, unsigned int size);
/* take back the filled buffer after writing tracks or headers, returns actual length */
AVIAPI unsigned int AVICC avi_buf_get(muxavi_handle mux);

/* write track data */
/* use trackno = 0 for video, trackno = 1 for audio */
AVIAPI void AVICC avi_write_track(muxavi_handle mux, unsigned int trackno, unsigned char* buf, unsigned int len, unsigned int dur);
AVIAPI void AVICC avi_write_atrack(muxavi_handle mux, unsigned int trackno, unsigned char* buf, unsigned int len, unsigned int dur);

/* set avcC or esds parameter data, to be written during mp4_write_header.
   Note: the pointer is copied, not the data, so don't free buf until after the call mp4_write_header. */
AVIAPI void AVICC avi_set_parameter_data(muxavi_handle mux, unsigned char *buf, unsigned int len);
/* get parameter size for buffer passed to avi_get_parameter_data */
AVIAPI unsigned int AVICC avi_get_parameter_size(muxavi_handle mux);
/* get parameter data from avcC or mp4v decoder-specific info, after reading the header.
   buf should be at least size returned by mp4_get_parameter_size */
AVIAPI void AVICC avi_get_parameter_data(muxavi_handle mux, unsigned char *buf);
/* returns a fourcc code for a track for a reader muxer */
AVIAPI unsigned int AVICC avi_get_fourcc(muxavi_handle mux, unsigned int trackno);
/* return a mostly-correct timestamp for a particular track (and internally increment it) */
AVIAPI unsigned int AVICC avi_get_timestamp(muxavi_handle mux, int trackno);
/* get the default duration for a track */
AVIAPI unsigned int AVICC avi_get_default_duration(muxavi_handle mux, int trackno);
AVIAPI unsigned int avi_get_timescale(muxavi_handle mux, unsigned int trackno);
AVIAPI unsigned int avi_get_samplerate(muxavi_handle mux, unsigned int trackno);

AVIAPI int AVICC avi_was_write_error(muxavi_handle mux);

AVIAPI const char * AVICC avi_get_error(muxavi_handle mux);
AVIAPI int AVICC avi_get_error_code(muxavi_handle mux);


/* set the duration for interleaving audio and video frames */
AVIAPI void AVICC avi_interleave_duration(muxavi_handle mux, unsigned int dur);

typedef void (AVICC *avi_callback_ptr)(unsigned long long offset, unsigned long long timestamp, unsigned int len, unsigned int flags);
#define AVI_CALLBACK_FLAG_VIDEO_KEYFRAME 1
#define AVI_CALLBACK_FLAG_AUDIO 2
AVIAPI void AVICC avi_set_callback(muxavi_handle mux, avi_callback_ptr cb);
// find the next frame in the mp4_reader and call the callback, returns 0 else -1 at end of file
AVIAPI int AVICC avi_play(muxavi_handle mux);
AVIAPI int AVICC avi_play_reverse(muxavi_handle mux);
AVIAPI int AVICC avi_seek(muxavi_handle mux, unsigned long long timestamp);
// the mp4_get_error will return file size error if this size would be exceeded (taking moov into account)
AVIAPI void AVICC avi_max_file_size(muxavi_handle mux, unsigned long long max_size);

#ifdef __cplusplus
}
#endif
/* define some useful fourcc codes */
#define UUID(c3,c2,c1,c0) (c0 + (c1 << 8) + (c2 << 16) + (c3 << 24))
#define AVC1    UUID('a','v','c','1')
#define MP4A    UUID('m','p','4','a')
#define MP4V    UUID('m','p','4','v')
#define MP2V    UUID('m','p','2','v')
#define MP1V    UUID('m','p','1','v')
#define MPG2    UUID('m','p','g','2')
#define MPG1    UUID('m','p','g','1')
#define MP4S    UUID('m','p','4','s')
#define SOWT    UUID('s','o','w','t')

#endif
