summaryrefslogtreecommitdiff
path: root/ext/tarkin/tarkin.h
blob: 633f9a141f6f2e6570e17046b795d05cb3510f63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#ifndef __TARKIN_H
#define __TARKIN_H

#include <stdio.h>
#include "wavelet.h"
#include <ogg/ogg.h>


#define BUG(x...)                                                            \
   do {                                                                      \
      printf("BUG in %s (%s: line %i): ", __FUNCTION__, __FILE__, __LINE__); \
      printf(#x);                                                            \
      printf("\n");                                                          \
      exit (-1);                                                             \
   } while (0);


/* Theses determine what infos the packet comes with */
#define TARKIN_PACK_EXAMPLE                1

typedef struct {
   uint8_t *data;
   uint32_t data_len;
   uint32_t storage;
}   TarkinPacket;


typedef enum {
   TARKIN_GRAYSCALE,
   TARKIN_RGB24,       /*  tight packed RGB        */
   TARKIN_RGB32,       /*  32bit, no alphachannel  */
   TARKIN_RGBA,        /*  dito w/ alphachannel    */
   TARKIN_YUV2,        /*  16 bits YUV             */
   TARKIN_YUV12,       /*  12 bits YUV             */
   TARKIN_FYUV,        /*  Tarkin's Fast YUV-like? */
} TarkinColorFormat;

#define TARKIN_INTERNAL_FORMAT TARKIN_FYUV

typedef enum {
   TARKIN_OK = 0,
   TARKIN_IO_ERROR,
   TARKIN_SIGNATURE_NOT_FOUND,
   TARKIN_INVALID_LAYER,
   TARKIN_INVALID_COLOR_FORMAT,
   TARKIN_VERSION,
   TARKIN_BAD_HEADER,
   TARKIN_NOT_TARKIN,
   TARKIN_FAULT,
   TARKIN_UNUSED,
   TARKIN_NEED_MORE,
   TARKIN_NOT_IMPLEMENTED
} TarkinError;



typedef struct {
   uint32_t width;
   uint32_t height;
   uint32_t a_moments;
   uint32_t s_moments;
   uint32_t frames_per_buf;
   uint32_t bitstream_len;              /*  for all color components, bytes */
   TarkinColorFormat format;
} TarkinVideoLayerDesc;


typedef struct {
   TarkinVideoLayerDesc desc;
   uint32_t n_comp;                     /*  number of color components */
   Wavelet3DBuf **waveletbuf;
   TarkinPacket *packet;
   uint32_t current_frame_in_buf;
   uint32_t frameno;

   void (*color_fwd_xform) (uint8_t *rgba, Wavelet3DBuf *yuva [], uint32_t count);
   void (*color_inv_xform) (Wavelet3DBuf *yuva [], uint8_t *rgba, uint32_t count);
} TarkinVideoLayer;

typedef struct {
   uint32_t numerator;
   uint32_t denominator;
} TarkinTime; /* Let's say the unit is 1 second */

typedef struct TarkinInfo {
   int version;
   int n_layers;
   TarkinVideoLayer *layer;
   TarkinTime inter;          /* numerator == O if per-frame time info. */
   int frames_per_block;
   int comp_per_block;        /* AKA "packets per block" for now */
   uint32_t max_bitstream_len;

  /* The below bitrate declarations are *hints*.
     Combinations of the three values carry the following implications:
     
     all three set to the same value: 
       implies a fixed rate bitstream
     only nominal set: 
       implies a VBR stream that averages the nominal bitrate.  No hard 
       upper/lower limit
     upper and or lower set: 
       implies a VBR bitstream that obeys the bitrate limits. nominal 
       may also be set to give a nominal rate.
     none set:
       the coder does not care to speculate.
  */

   long bitrate_upper;
   long bitrate_nominal;
   long bitrate_lower;
   long bitrate_window;
} TarkinInfo;

/* This is used for encoding */
typedef struct {
   unsigned char *header;
   unsigned char *header1;
   unsigned char *header2;
} tarkin_header_store;




 /* Some of the fields in TarkinStream are redundent with TarkinInfo ones
  * and will probably get deleted, namely n_layers and frames_per_buf */
typedef struct TarkinStream {
   uint32_t n_layers;
   TarkinVideoLayer *layer;
   uint32_t current_frame;
   uint32_t current_frame_in_buf;
   ogg_int64_t packetno;
   uint32_t frames_per_buf;
   uint32_t max_bitstream_len;
   TarkinInfo *ti;
   tarkin_header_store headers;
   /* These callbacks are only used for encoding */
   TarkinError (*free_frame)(void *tarkinstream, void *ptr);
   /* These thing allows not to buffer but it needs global var in caller. */
   TarkinError (*packet_out)(void *tarkinstream, ogg_packet *ptr);
   void * user_ptr;
} TarkinStream;


typedef struct TarkinComment{
  /* unlimited user comment fields.  libtarkin writes 'libtarkin'
     whatever vendor is set to in encode */
  char **user_comments;
  int   *comment_lengths;
  int    comments;
  char  *vendor;

} TarkinComment;

/* Tarkin PRIMITIVES: general ***************************************/

/* The Tarkin header is in three packets, the initial small packet in
   the first page that identifies basic parameters, that is a TarkinInfo
   structure, a second packet with bitstream comments and a third packet 
   that holds the layers description structures. */


/* Theses are the very same than Vorbis versions, they could be shared. */
extern TarkinStream* tarkin_stream_new ();
extern void          tarkin_stream_destroy (TarkinStream *s);
extern void     tarkin_info_init(TarkinInfo *vi);
extern void     tarkin_info_clear(TarkinInfo *vi);
extern void     tarkin_comment_init(TarkinComment *vc);
extern void     tarkin_comment_add(TarkinComment *vc, char *comment); 
extern void     tarkin_comment_add_tag(TarkinComment *vc, 
                                       char *tag, char *contents);
extern char    *tarkin_comment_query(TarkinComment *vc, char *tag, int count);
extern int      tarkin_comment_query_count(TarkinComment *vc, char *tag);
extern void     tarkin_comment_clear(TarkinComment *vc);

/* Tarkin PRIMITIVES: analysis layer ****************************/
/* Tarkin encoding is done this way : you init it passing a fresh
 * TarkinStream and a fresh TarkinInfo which has at least the rate_num
 * field renseigned. You also pass it two callback functions: free_frame()
 * is called when the lib doesn't need a frame anymore, and packet_out
 * is called when a packet is ready. The pointers given as arguments to 
 * these callback functions are of course only valid at the function call
 * time. The user_ptr is stored in s and can be used by packet_out(). */
extern int tarkin_analysis_init(TarkinStream *s,
               TarkinInfo *ti,
               TarkinError (*free_frame)(void *tarkinstream, void *ptr),
               TarkinError (*packet_out)(void *tarkinstream, ogg_packet *ptr),
               void *user_ptr
               );
/* Then you need to add at least a layer in your stream, passing a 
 * TarkinVideoLayerDesc renseigned at least on the width, height and
 * format parameters. */
extern int   tarkin_analysis_add_layer(TarkinStream *s,
                                TarkinVideoLayerDesc *tvld);
/* At that point you are ready to get headers out the lib by calling
 * tarkin_analysis_headerout() passing it a renseigned TarkinComment
 * structure. It does fill your 3 ogg_packet headers, which are valid
 * till next call */
extern int   TarkinCommentheader_out(TarkinComment *vc, ogg_packet *op);
extern TarkinError  tarkin_analysis_headerout(TarkinStream *s,
                                          TarkinComment *vc,
                                          ogg_packet *op,
                                          ogg_packet *op_comm,
                                          ogg_packet *op_code);
/* You are now ready to pass in frames to the codec, however don't free
 * them before the codec told you so. It'll tell you when packets are
 * ready to be taken out. When you have no more frame, simply pass NULL.
 * If you encode multiple layers you have to do it synchronously, putting 
 * one frame from each layer at a time. */
extern uint32_t      tarkin_analysis_framein(TarkinStream *s,
                                uint8_t *frame, /* NULL for EOS */
                                uint32_t layer,
                                TarkinTime *date);

/* Tarkin PRIMITIVES: synthesis layer *******************************/
/* For decoding, you needs first to give the three first packet of the 
 * stream to tarkin_synthesis_headerin() which will fill for you blank
 * TarkinInfo and TarkinComment. */
extern TarkinError tarkin_synthesis_headerin(TarkinInfo *vi,TarkinComment *vc,
                                        ogg_packet *op);
/* Then you can init your stream with your TarkinInfo struct. */
extern TarkinError tarkin_synthesis_init(TarkinStream *s,TarkinInfo *ti);
/* All subsequent packets are to this be passed to tarkin_synthesis_packetin*/
extern TarkinError tarkin_synthesis_packetin(TarkinStream *s, ogg_packet *op);
/* and then tarkin_synthesis_frameout gives you ptr on next frame, or NULL. It
 * also fills for you date. */
extern TarkinError  tarkin_synthesis_frameout(TarkinStream *s,
                      uint8_t **frame, uint32_t layer_id, TarkinTime *date);
/* When you're done with a frame, tell it to the codec with this. */
extern int tarkin_synthesis_freeframe(TarkinStream *s, uint8_t *frame);


#endif