#ifndef ka_vcodec_h
#define ka_vcodec_h

#include "inttypes.h"
#include "ka_vinfo.h"
#include "ka_block.h"
#include "ka_error.h"

typedef struct ka_vcodec_s ka_vcodec_t;

typedef enum
{ ka_vcodec_event_inerror       = -1
, ka_vcodec_event_buffering     = 0
, ka_vcodec_event_buffer_full   = 1  // Video decoder buffers full
                                     // could be a good time to multitask
, ka_vcodec_event_timeout       = 2  // Allocated time exceeded
, ka_vcodec_event_decode_frame  = 3
, ka_vcodec_event_end_frame     = 4
, ka_vcodec_event_end           = 5
} ka_vcodec_event;

typedef enum
{ ka_vcodec_action_reset      = 1
, ka_vcodec_action_skipframe  = 2
, ka_vcodec_action_monochrome = 3 // decode in monochrome
, ka_vcodec_action_colours    = 4 // decode in full colours
} ka_vcodec_action;

typedef struct
{
  uint32_t typ;            // video type
  uint32_t width;
  uint32_t height;
  uint32_t period;
} ka_vparams_t;

typedef ka_vcodec_t* (*ka_vcodec_FNnew)(ka_error_t* error_block, const ka_vparams_t* params, uint32_t hardware);
typedef void  (*ka_vcodec_FNdelete)(ka_vcodec_t** ppcodec);
typedef ka_vcodec_event (*ka_vcodec_FNdecode)(ka_vcodec_t* pcodec, ka_block_t* b, uint32_t exit_time);
typedef void (*ka_vcodec_FNact)(ka_vcodec_t* pcodec, ka_vcodec_action a);
typedef void (*ka_vcodec_FNgetInfo)(ka_vcodec_t* pcodec, ka_vinfo_t* vinfo);
typedef int (*ka_vcodec_FNgetDecodeFrame)(ka_vcodec_t* pcodec, ka_vframe_t* frame);
typedef int (*ka_vcodec_FNgetDisplayFrame)(ka_vcodec_t* pcodec, ka_vframe_t* frame);
typedef void (*ka_vcodec_FNreleaseFrame)(ka_vcodec_t* pcodec, ka_vframe_t* frame);

typedef struct
{
  const char*                 name;
  ka_vcodec_FNnew             FNnew;
  ka_vcodec_FNdelete          FNdelete;
  ka_vcodec_FNdecode          FNdecode;
  ka_vcodec_FNact             FNact;
  ka_vcodec_FNgetInfo         FNgetInfo;
  ka_vcodec_FNgetDecodeFrame  FNgetDecodeFrame;
  ka_vcodec_FNgetDisplayFrame FNgetDisplayFrame;
  ka_vcodec_FNreleaseFrame    FNreleaseFrame;
} kav_vcodec_t;

extern const kav_vcodec_t kav_vcodec_cvid;
extern const kav_vcodec_t kav_vcodec_mpeg;

struct ka_vcodec_s
{
  const kav_vcodec_t* vptr;
  ka_error_t* pErrorBlock;
};

#endif
