#ifndef P2P_API_H_
#define P2P_API_H_

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Notation: [Xa-Ya-Za]
 *
 * [] denotes a machine word of the specified endianness.  Xa-Ya-Za denote
 * component X, Y, and Z packed in the word, with bit depths a, b, c, in order
 * from MSB to LSB.  Padding bits are represented by the component '!'.
 */
enum p2p_packing {
	/** [R8-G8-B8] */
	p2p_rgb24_be, /* RGB */
	p2p_rgb24_le, /* BGR */
	p2p_rgb24,
	/** [A8-R8-G8-B8] */
	p2p_argb32_be, /* ARGB */
	p2p_argb32_le, /* BGRA */
	p2p_argb32,
	/** [A8-Y8-U8-V8] */
	p2p_ayuv_be, /* AYUV */
	p2p_ayuv_le, /* VUYA */
	p2p_ayuv,
	/** [R16-G16-B16] */
	p2p_rgb48_be, /* RGB, big-endian components */
	p2p_rgb48_le, /* BGR, little-endian components */
	p2p_rgb48,
	/** [A16-R16-G16-B16] */
	p2p_argb64_be, /* ARGB big-endian components */
	p2p_argb64_le, /* BGRA little-endian components */
	p2p_argb64,
	/** [A2-R10-G10-B10] */
	p2p_rgb30_be, /* ARGB packed in big-endian DWORD */
	p2p_rgb30_le, /* ARGB packed in little-endian DWORD */
	p2p_rgb30,
	/** [A2-V10-Y10-U10] */
	p2p_y410_be, /* AVYU packed in big-endian DWORD */
	p2p_y410_le, /* AVYU packed in little-endian DWORD. Microsoft Y410 */
	p2p_y410,
	/** [A12-!4-V12-!4-Y12-!4-U12-!4] */
	p2p_y412_be, /* AVYU, big-endian components, lower 4 bits zero */
	p2p_y412_le, /* UYVA, little-endian component, lower 4 bits zero. Y412 */
	p2p_y412,
	/** [A16-V16-Y16-U16] */
	p2p_y416_be, /* AVYU, big-endian components */
	p2p_y416_le, /* UYVA, little-endian components. Microsoft Y416 */
	p2p_y416,
	/** [Y8] [U8] [Y8] [V8] */
	p2p_yuy2,
	/** [U8] [Y8] [V8] [Y8] */
	p2p_uyvy,
	/** [Y10-!6] [U10-!6] [Y10-!6] [V10-!6] */
	p2p_y210_be, /* YUYV, big-endian components, lower 6 bits zero */
	p2p_y210_le, /* YUYV, little-endian components, lower 6 bits zero. Microsoft Y210 */
	p2p_y210,
	/** [Y12-!4] [U12-!4] [Y12-!4] [V12-!4] */
	p2p_y212_be, /* YUYV, big-endian components, lower 4 bits zero */
	p2p_y212_le, /* YUYV, little-endian components, lower 4 bits zero. Y212 */
	p2p_y212,
	/** [Y16] [U16] [Y16] [V16] */
	p2p_y216_be, /* YUYV, big-endian components */
	p2p_y216_le, /* YUYV, little-endian components. Microsoft Y216 */
	p2p_y216,
	/** [!2-V10-Y10-U10] [!2-Y10-U10-Y10] [!2-U10-Y10-V10] [!2-Y10-V10-Y10] */
	p2p_v210_be, /* v210 with big-endian DWORDs */
	p2p_v210_le, /* Apple/QuickTime v210 */
	p2p_v210,
	/** [U16] [Y16] [V16] [Y16] */
	p2p_v216_be, /* UYVY, big-endian components */
	p2p_v216_le, /* UYVY, little-endian components. Apple/QuickTime v216 */
	p2p_v216,
	/** [U8-V8] */
	p2p_nv12_be, /* NV21, V first */
	p2p_nv12_le, /* NV12 */
	p2p_nv12,
	/** [U8-V8] */
	p2p_nv16_be, /* NV61, V first */
	p2p_nv16_le, /* NV16 */
	p2p_nv16,
	/** [U10-!6-V10-!6] */
	p2p_p010_be, /* NV21, big-endian components, lower 6 bits zero */
	p2p_p010_le, /* NV12, little-endian components, lower 6 bits zero. Microsoft P010 */
	p2p_p010,
	/** [U12-!4-V12-!4] */
	p2p_p012_be, /* NV21, big-endian components, lower 4 bits zero */
	p2p_p012_le, /* NV12, little-endian components, lower 4 bits zero. P012 */
	p2p_p012,
	/** [U16-V16] */
	p2p_p016_be, /* NV21-like, big-endian components */
	p2p_p016_le, /* NV12-like, little-endian components. Microsoft P016 */
	p2p_p016,
	/** [U10-!6-V10-!6] */
	p2p_p210_be, /* NV21-like, big-endian components, lower 6 bits zero */
	p2p_p210_le, /* NV12-like, little-endian components, lower 6 bits zero. Microsoft P210 */
	p2p_p210,
	/** [U12-!4-V12-!4] */
	p2p_p212_be, /* NV21-like, big-endian components, lower 4 bits zero */
	p2p_p212_le, /* NV12-like, little-endian components, lower 4 bits zero. P212 */
	p2p_p212,
	/** [U16-V16] */
	p2p_p216_be, /* NV21-like, big-endian components */
	p2p_p216_le, /* NV12-like, little-endian components. Microsoft P216 */
	p2p_p216,
	/** [R8-G8-B8-A8] */
	p2p_rgba32_be, /* RGBA */
	p2p_rgba32_le, /* ABGR */
	p2p_rgba32,
	/** [R16-G16-B16-A16] */
	p2p_rgba64_be, /* RGBA, big-endian components */
	p2p_rgba64_le, /* ABGR, little-endian components */
	p2p_rgba64,
	/** [A16-B16-G16-R16] */
	p2p_abgr64_be, /* ABGR, big-endian components */
	p2p_abgr64_le, /* RGBA, little-endian components */
	p2p_abgr64,
	/** [B16-G16-R16] */
	p2p_bgr48_be, /* BGR, big-endian components */
	p2p_bgr48_le, /* RGB, little-endian components */
	p2p_bgr48,
	/** [B16-G16-R16-A16] */
	p2p_bgra64_be, /* BGRA, big-endian components */
	p2p_bgra64_le, /* ARGB, little-endian components */
	p2p_bgra64,

	p2p_packing_max,
};

struct p2p_buffer_param {
	/**
	 * Planar order: R-G-B-A or Y-U-V-A. Alpha is optional.
	 * Packed order: Y-UV if NV12/21, else single plane. Y optional for NV12/21.
	 */
	const void *src[4];
	void *dst[4];
	ptrdiff_t src_stride[4];
	ptrdiff_t dst_stride[4];
	unsigned width;
	unsigned height;
	enum p2p_packing packing;
};

/** Pack/unpack a range of pixels from a scanline. */
typedef void (*p2p_unpack_func)(const void *src, void * const dst[4], unsigned left, unsigned right);
typedef void (*p2p_pack_func)(const void * const src[4], void *dst, unsigned left, unsigned right);

/** Select a line pack/unpack function. */
p2p_unpack_func p2p_select_unpack_func(enum p2p_packing packing);
p2p_pack_func p2p_select_pack_func(enum p2p_packing packing);
p2p_pack_func p2p_select_pack_func_ex(enum p2p_packing packing, int alpha_one_fill);


/** When processing formats like NV12, ignore the unpacked plane. */
#define P2P_SKIP_UNPACKED_PLANES (1UL << 0)
/** When packing, store a bit pattern of all ones in the alpha channel instead of all zeros. */
#define P2P_ALPHA_SET_ONE (1UL << 1)

/** Helper function to pack/unpack between memory locations. */
void p2p_unpack_frame(const struct p2p_buffer_param *param, unsigned long flags);
void p2p_pack_frame(const struct p2p_buffer_param *param, unsigned long flags);

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

#endif /* P2P_API_H_ */
