Make mv's use signed chars explicitly.
[xiph/unicode.git] / w3d / tarkin.c
blobdaa1b5a2ddaf3f64434c04d2d11c41a6e8f430b0
1 /*
2 * The real io-stuff is in tarkin-io.c
3 * (this one has to be rewritten to write ogg streams ...)
4 */
6 #include "mem.h"
7 #include "tarkin.h"
8 #include "yuv.h"
11 #define N_FRAMES 1
15 TarkinStream* tarkin_stream_new ()
17 TarkinStream *s = (TarkinStream*) CALLOC (1, sizeof(TarkinStream));
19 if (!s)
20 return NULL;
21 memset(s,0,sizeof(*s));
23 s->frames_per_buf = N_FRAMES;
25 return s;
29 void tarkin_stream_destroy (TarkinStream *s)
31 uint32_t i, j;
33 if (!s)
34 return;
36 for (i=0; i<s->n_layers; i++) {
37 if (s->layer[i].waveletbuf) {
38 for (j=0; j<s->layer[i].n_comp; j++) {
39 wavelet_3d_buf_destroy (s->layer[i].waveletbuf[j]);
40 FREE (s->layer[i].packet[j].data);
42 FREE(s->layer[i].waveletbuf);
43 FREE(s->layer[i].packet);
47 if (s->layer)
48 FREE(s->layer);
50 if (s->headers.header)
51 FREE(s->headers.header);
53 if (s->headers.header1)
54 FREE(s->headers.header1);
56 if (s->headers.header2)
57 FREE(s->headers.header2);
60 FREE(s);
64 int tarkin_analysis_init(TarkinStream *s, TarkinInfo *ti,
65 TarkinError (*free_frame)(void *s, void *ptr),
66 TarkinError (*packet_out)(void *s, ogg_packet *ptr),
67 void *user_ptr)
69 if((!ti->inter.numerator)||(!ti->inter.denominator))return (-TARKIN_FAULT);
70 if((!free_frame) || (!packet_out)) return (-TARKIN_FAULT);
71 s->ti = ti;
72 s->free_frame = free_frame;
73 s->packet_out = packet_out;
74 s->user_ptr = user_ptr;
75 return(0);
79 extern int tarkin_analysis_add_layer(TarkinStream *s,
80 TarkinVideoLayerDesc *tvld)
82 int i;
83 TarkinVideoLayer *layer;
84 if(s->n_layers) {
85 s->layer = REALLOC(s->layer,(s->n_layers+1) * sizeof(*s->layer));
86 } else {
87 s->layer = MALLOC(sizeof(*s->layer));
89 layer = s->layer + s->n_layers;
90 memset(layer,0,sizeof(*s->layer));
91 memcpy (&layer->desc , tvld, sizeof(TarkinVideoLayerDesc));
93 s->n_layers++;
94 s->ti->n_layers = s->n_layers;
95 s->ti->layer = s->layer;
97 switch (layer->desc.format) {
98 case TARKIN_GRAYSCALE:
99 layer->n_comp = 1;
100 layer->color_fwd_xform = grayscale_to_y;
101 layer->color_inv_xform = y_to_grayscale;
102 break;
103 case TARKIN_RGB24:
104 layer->n_comp = 3;
105 layer->color_fwd_xform = rgb24_to_yuv;
106 layer->color_inv_xform = yuv_to_rgb24;
107 break;
108 case TARKIN_RGB32:
109 layer->n_comp = 3;
110 layer->color_fwd_xform = rgb32_to_yuv;
111 layer->color_inv_xform = yuv_to_rgb32;
112 break;
113 case TARKIN_RGBA:
114 layer->n_comp = 4;
115 layer->color_fwd_xform = rgba_to_yuv;
116 layer->color_inv_xform = yuv_to_rgba;
117 break;
118 default:
119 return -TARKIN_INVALID_COLOR_FORMAT;
122 #ifdef DBG_OGG
123 printf("dbg_ogg:add_layer %d with %d components\n",
124 s->n_layers, layer->n_comp);
125 #endif
127 layer->waveletbuf = (Wavelet3DBuf**) CALLOC (layer->n_comp,
128 sizeof(Wavelet3DBuf*));
130 layer->packet = MALLOC (layer->n_comp * sizeof(*layer->packet));
131 memset(layer->packet, 0, layer->n_comp * sizeof(*layer->packet));
133 for (i=0; i<layer->n_comp; i++){
134 layer->waveletbuf[i] = wavelet_3d_buf_new (layer->desc.width,
135 layer->desc.height,
136 layer->desc.frames_per_buf);
137 layer->packet[i].data = MALLOC(layer->desc.bitstream_len);
138 layer->packet[i].storage = layer->desc.bitstream_len;
141 max_bitstream_len += layer->desc.bitstream_len
142 + 2 * 10 * sizeof(uint32_t) * layer->n_comp; // truncation tables
144 return (TARKIN_OK);
147 TarkinError _analysis_packetout(TarkinStream *s, uint32_t layer_id,
148 uint32_t comp)
150 ogg_packet op;
151 oggpack_buffer opb;
152 uint8_t *data;
153 uint32_t data_len;
154 int i;
155 data = s->layer[layer_id].packet[comp].data;
156 data_len = s->layer[layer_id].packet[comp].data_len;
158 oggpack_writeinit(&opb);
159 oggpack_write(&opb,0,8); /* No feature flags for now */
160 oggpack_write(&opb,layer_id,12);
161 oggpack_write(&opb,comp,12);
162 for(i=0;i<data_len;i++)
163 oggpack_write(&opb,*(data + i), 8);
165 op.b_o_s = 0;
166 op.e_o_s = data_len?0:1;
167 op.granulepos = 0;
168 op.bytes = oggpack_bytes(&opb)+4;
169 op.packet = opb.buffer;
170 #ifdef DBG_OGG
171 printf("dbg_ogg: writing packet layer %d, comp %d, data_len %d %s\n",
172 layer_id, comp, data_len, op.e_o_s?"eos":"");
173 #endif
174 s->layer[layer_id].packet[comp].data_len = 0; /* so direct call => eos */
175 return(s->packet_out(s,&op));
178 void _stream_flush (TarkinStream *s)
180 uint32_t i, j;
182 s->current_frame_in_buf=0;
184 for (i=0; i<s->n_layers; i++) {
185 TarkinVideoLayer *layer = &s->layer[i];
187 for (j=0; j<layer->n_comp; j++) {
188 uint32_t comp_bitstream_len;
189 TarkinPacket *packet = layer->packet + j;
192 * implicit 6:1:1 subsampling
194 if (j == 0)
195 comp_bitstream_len = 6*layer->desc.bitstream_len/(layer->n_comp+5);
196 else
197 comp_bitstream_len = layer->desc.bitstream_len/(layer->n_comp+5);
199 if(packet->storage < comp_bitstream_len) {
200 packet->storage = comp_bitstream_len;
201 packet->data = REALLOC (packet->data, comp_bitstream_len);
204 wavelet_3d_buf_dump ("color-%d-%03d.pgm",
205 s->current_frame, j,
206 layer->waveletbuf[j], j == 0 ? 0 : 128);
208 wavelet_3d_buf_fwd_xform (layer->waveletbuf[j],
209 layer->desc.a_moments,
210 layer->desc.s_moments);
212 wavelet_3d_buf_dump ("coeff-%d-%03d.pgm",
213 s->current_frame, j,
214 layer->waveletbuf[j], 128);
216 packet->data_len = wavelet_3d_buf_encode_coeff (layer->waveletbuf[j],
217 packet->data,
218 comp_bitstream_len);
220 _analysis_packetout (s, i, j);
226 uint32_t tarkin_analysis_framein (TarkinStream *s, uint8_t *frame,
227 uint32_t layer_id, TarkinTime *date)
229 TarkinVideoLayer *layer;
230 if(!frame) return (_analysis_packetout(s, 0, 0)); /* eos */
231 if((layer_id>=s->n_layers) || (date->denominator==0)) return (TARKIN_FAULT);
233 layer = s->layer + layer_id;
234 layer->color_fwd_xform (frame, layer->waveletbuf,
235 s->current_frame_in_buf);
236 /* We don't use this feature for now, neither date... */
237 s->free_frame(s,frame);
239 s->current_frame_in_buf++;
241 if (s->current_frame_in_buf == s->frames_per_buf)
242 _stream_flush (s);
244 #ifdef DBG_OGG
245 printf("dbg_ogg: framein at pos %d/%d, n° %d,%d on layer %d\n",
246 date->numerator, date->denominator,
247 layer->frameno, s->current_frame, layer_id);
248 #endif
250 layer->frameno++;
251 return (++s->current_frame);
258 * tarkin_stream_read_header() is now info.c:_tarkin_unpack_layer_desc()
263 TarkinError tarkin_stream_get_layer_desc (TarkinStream *s,
264 uint32_t layer_id,
265 TarkinVideoLayerDesc *desc)
267 if (layer_id > s->n_layers-1)
268 return -TARKIN_INVALID_LAYER;
270 memcpy (desc, &(s->layer[layer_id].desc), sizeof(TarkinVideoLayerDesc));
272 return TARKIN_OK;
275 TarkinError tarkin_synthesis_init (TarkinStream *s, TarkinInfo *ti)
277 s->ti = ti;
278 s->layer = ti->layer; /* It was malloc()ed by headerin() */
279 s->n_layers = ti->n_layers;
280 return (TARKIN_OK);
283 TarkinError tarkin_synthesis_packetin (TarkinStream *s, ogg_packet *op)
285 uint32_t i, layer_id, comp, data_len;
286 uint32_t flags, junk;
287 int nread;
288 oggpack_buffer opb;
289 TarkinPacket *packet;
290 #ifdef DBG_OGG
291 printf("dbg_ogg: Reading packet n° %lld, granulepos %lld, len %ld, %s%s\n",
292 op->packetno, op->granulepos, op->bytes,
293 op->b_o_s?"b_o_s":"", op->e_o_s?"e_o_s":"");
294 #endif
295 oggpack_readinit(&opb,op->packet,op->bytes);
296 flags = oggpack_read(&opb,8);
297 layer_id = oggpack_read(&opb,12); /* Theses are required for */
298 comp = oggpack_read(&opb,12); /* data hole handling (or maybe
299 * packetno would be enough ?) */
300 nread = 4;
302 if(flags){ /* This is void "infinite future features" feature ;) */
303 if(flags & 1<<7){
304 junk = flags;
305 while (junk & 1<<7)
306 junk = oggpack_read(&opb,8); /* allow for many future flags
307 that must be correctly ordonned. */
309 /* This shows how to get a feature's data:
310 if (flags & TARKIN_FLAGS_EXAMPLE){
311 tp->example = oggpack_read(&opb,32);
312 junk = tp->example & 3<<30;
313 tp->example &= 0x4fffffff;
316 for(junk=1<<31;junk & 1<<31;) /* and many future data */
317 while((junk=oggpack_read(&opb,32)) & 1<<30);
318 /* That is, feature data comes in 30 bit chunks. We also have
319 * 31 potentially usefull bits in last chunk. */
322 nread = (opb.ptr - opb.buffer);
323 data_len = op->bytes - nread;
325 #ifdef DBG_OGG
326 printf(" layer_id %d, comp %d, meta-data %dB, w3d data %dB.\n",
327 layer_id, comp,nread, data_len);
328 #endif
330 /* We now have for shure our data. */
331 packet = &s->layer[layer_id].packet[comp];
332 if(packet->data_len)return(-TARKIN_UNUSED); /* Previous data wasn't used */
334 if(packet->storage < data_len){
335 packet->storage = data_len + 255;
336 packet->data = REALLOC (packet->data, packet->storage);
339 for(i=0;i < data_len ; i++)
340 packet->data[i] = oggpack_read(&opb,8);
342 packet->data_len = data_len;
344 return(TARKIN_OK);
347 TarkinError tarkin_synthesis_frameout(TarkinStream *s,
348 uint8_t **frame,
349 uint32_t layer_id, TarkinTime *date)
351 int j;
352 TarkinVideoLayer *layer = &s->layer[layer_id];
353 if (s->current_frame_in_buf == 0) {
354 *frame = MALLOC (layer->desc.width * layer->desc.height * layer->n_comp);
355 for (j=0; j<layer->n_comp; j++) {
356 TarkinPacket *packet = layer->packet + j;
358 if(packet->data_len == 0)goto err_out ;
360 wavelet_3d_buf_decode_coeff (layer->waveletbuf[j], packet->data,
361 packet->data_len);
363 wavelet_3d_buf_dump ("rcoeff-%d-%03d.pgm",
364 s->current_frame, j, layer->waveletbuf[j],
365 128);
367 wavelet_3d_buf_inv_xform (layer->waveletbuf[j],
368 layer->desc.a_moments,
369 layer->desc.s_moments);
371 wavelet_3d_buf_dump ("rcolor-%d-%03d.pgm",
372 s->current_frame, j,
373 layer->waveletbuf[j], j == 0 ? 0 : 128);
376 /* We did successfylly read a block from this layer, acknowledge it. */
377 for (j=0; j < layer->n_comp; j++)
378 layer->packet[j].data_len = 0;
381 layer->color_inv_xform (layer->waveletbuf, *frame,
382 s->current_frame_in_buf);
383 s->current_frame_in_buf++;
384 s->current_frame++;
386 if (s->current_frame_in_buf == s->frames_per_buf)
387 s->current_frame_in_buf=0;
389 date->numerator = layer->frameno * s->ti->inter.numerator;
390 date->denominator = s->ti->inter.denominator;
391 #ifdef DBG_OGG
392 printf("dbg_ogg: outputting frame pos %d/%d from layer %d.\n",
393 date->numerator, date->denominator, layer_id);
394 #endif
395 layer->frameno++;
396 return (TARKIN_OK);
397 err_out:
398 FREE(*frame);
399 return (TARKIN_NEED_MORE);
402 int tarkin_synthesis_freeframe(TarkinStream *s, uint8_t *frame)
404 FREE(frame);
406 return(TARKIN_OK);