1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
11 ********************************************************************
13 function: maintain the info structure, info <-> header packets
14 last mod: $Id: info.c,v 1.3 2002/03/11 09:24:17 holger Exp $
16 ********************************************************************/
18 /* general handling of the header and the TarkinInfo structure (and
31 static void _v_writestring(oggpack_buffer
*o
,char *s
, int bytes
){
33 oggpack_write(o
,*s
++,8);
37 static void _v_readstring(oggpack_buffer
*o
,char *buf
,int bytes
){
39 *buf
++=oggpack_read(o
,8);
43 void tarkin_comment_init(TarkinComment
*vc
){
44 memset(vc
,0,sizeof(*vc
));
47 void tarkin_comment_add(TarkinComment
*vc
,char *comment
){
48 vc
->user_comments
=REALLOC(vc
->user_comments
,
49 (vc
->comments
+2)*sizeof(*vc
->user_comments
));
50 vc
->comment_lengths
=REALLOC(vc
->comment_lengths
,
51 (vc
->comments
+2)*sizeof(*vc
->comment_lengths
));
52 vc
->comment_lengths
[vc
->comments
]=strlen(comment
);
53 vc
->user_comments
[vc
->comments
]=MALLOC(vc
->comment_lengths
[vc
->comments
]+1);
54 strcpy(vc
->user_comments
[vc
->comments
], comment
);
56 vc
->user_comments
[vc
->comments
]=NULL
;
59 void tarkin_comment_add_tag(TarkinComment
*vc
, char *tag
, char *contents
){
60 char *comment
=alloca(strlen(tag
)+strlen(contents
)+2); /* +2 for = and \0 */
63 strcat(comment
, contents
);
64 tarkin_comment_add(vc
, comment
);
67 /* This is more or less the same as strncasecmp - but that doesn't exist
68 * everywhere, and this is a fairly trivial function, so we include it */
69 static int tagcompare(const char *s1
, const char *s2
, int n
){
72 if(toupper(s1
[c
]) != toupper(s2
[c
]))
79 char *tarkin_comment_query(TarkinComment
*vc
, char *tag
, int count
){
82 int taglen
= strlen(tag
)+1; /* +1 for the = we append */
83 char *fulltag
= alloca(taglen
+ 1);
88 for(i
=0;i
<vc
->comments
;i
++){
89 if(!tagcompare(vc
->user_comments
[i
], fulltag
, taglen
)){
91 /* We return a pointer to the data, not a copy */
92 return vc
->user_comments
[i
] + taglen
;
97 return NULL
; /* didn't find anything */
100 int tarkin_comment_query_count(TarkinComment
*vc
, char *tag
){
102 int taglen
= strlen(tag
)+1; /* +1 for the = we append */
103 char *fulltag
= alloca(taglen
+1);
105 strcat(fulltag
, "=");
107 for(i
=0;i
<vc
->comments
;i
++){
108 if(!tagcompare(vc
->user_comments
[i
], fulltag
, taglen
))
115 void tarkin_comment_clear(TarkinComment
*vc
){
118 for(i
=0;i
<vc
->comments
;i
++)
119 if(vc
->user_comments
[i
])FREE(vc
->user_comments
[i
]);
120 if(vc
->user_comments
)FREE(vc
->user_comments
);
121 if(vc
->comment_lengths
)FREE(vc
->comment_lengths
);
122 if(vc
->vendor
)FREE(vc
->vendor
);
124 memset(vc
,0,sizeof(*vc
));
127 /* used by synthesis, which has a full, alloced vi */
128 void tarkin_info_init(TarkinInfo
*vi
){
129 memset(vi
,0,sizeof(*vi
));
132 void tarkin_info_clear(TarkinInfo
*vi
){
133 memset(vi
,0,sizeof(*vi
));
136 /* Header packing/unpacking ********************************************/
138 static int _tarkin_unpack_info(TarkinInfo
*vi
,oggpack_buffer
*opb
)
141 printf("dbg_ogg: Decoding Info: ");
143 vi
->version
=oggpack_read(opb
,32);
144 if(vi
->version
!=0)return(-TARKIN_VERSION
);
146 vi
->n_layers
=oggpack_read(opb
,8);
147 vi
->inter
.numerator
=oggpack_read(opb
,32);
148 vi
->inter
.denominator
=oggpack_read(opb
,32);
150 vi
->bitrate_upper
=oggpack_read(opb
,32);
151 vi
->bitrate_nominal
=oggpack_read(opb
,32);
152 vi
->bitrate_lower
=oggpack_read(opb
,32);
155 printf(" n_layers %d, interleave: %d/%d, ",
156 vi
->n_layers
, vi
->inter
.numerator
, vi
->inter
.denominator
);
159 if(vi
->inter
.numerator
<1)goto err_out
;
160 if(vi
->inter
.denominator
<1)goto err_out
;
161 if(vi
->n_layers
<1)goto err_out
;
163 if(oggpack_read(opb
,1)!=1)goto err_out
; /* EOP check */
173 tarkin_info_clear(vi
);
174 return(-TARKIN_BAD_HEADER
);
177 static int _tarkin_unpack_comment(TarkinComment
*vc
,oggpack_buffer
*opb
)
180 int vendorlen
=oggpack_read(opb
,32);
183 printf("dbg_ogg: Decoding comment: ");
185 if(vendorlen
<0)goto err_out
;
186 vc
->vendor
=_ogg_calloc(vendorlen
+1,1);
187 _v_readstring(opb
,vc
->vendor
,vendorlen
);
188 vc
->comments
=oggpack_read(opb
,32);
189 if(vc
->comments
<0)goto err_out
;
190 vc
->user_comments
=_ogg_calloc(vc
->comments
+1,sizeof(*vc
->user_comments
));
191 vc
->comment_lengths
=_ogg_calloc(vc
->comments
+1,
192 sizeof(*vc
->comment_lengths
));
194 for(i
=0;i
<vc
->comments
;i
++){
195 int len
=oggpack_read(opb
,32);
196 if(len
<0)goto err_out
;
197 vc
->comment_lengths
[i
]=len
;
198 vc
->user_comments
[i
]=_ogg_calloc(len
+1,1);
199 _v_readstring(opb
,vc
->user_comments
[i
],len
);
201 if(oggpack_read(opb
,1)!=1)goto err_out
; /* EOP check */
204 printf("Success, read %d comments\n", vc
->comments
);
211 tarkin_comment_clear(vc
);
212 return(-TARKIN_BAD_HEADER
);
215 /* the real encoding details are here, currently TarkinVideoLayerDesc. */
216 static int _tarkin_unpack_layer_desc(TarkinInfo
*vi
,oggpack_buffer
*opb
){
218 vi
->layer
= CALLOC (vi
->n_layers
, (sizeof(*vi
->layer
)));
219 memset(vi
->layer
,0, vi
->n_layers
* sizeof(*vi
->layer
));
222 printf("ogg: Decoding layers description: ");
224 for(i
=0;i
<vi
->n_layers
;i
++){
225 TarkinVideoLayer
*layer
= vi
->layer
+ i
;
226 layer
->desc
.width
= oggpack_read(opb
,32);
227 layer
->desc
.height
= oggpack_read(opb
,32);
228 layer
->desc
.a_moments
= oggpack_read(opb
,32);
229 layer
->desc
.s_moments
= oggpack_read(opb
,32);
230 layer
->desc
.frames_per_buf
= oggpack_read(opb
,32);
231 layer
->desc
.bitstream_len
= oggpack_read(opb
,32);
232 layer
->desc
.format
= oggpack_read(opb
,32);
234 switch (layer
->desc
.format
) {
235 case TARKIN_GRAYSCALE
:
237 layer
->color_fwd_xform
= grayscale_to_y
;
238 layer
->color_inv_xform
= y_to_grayscale
;
242 layer
->color_fwd_xform
= rgb24_to_yuv
;
243 layer
->color_inv_xform
= yuv_to_rgb24
;
247 layer
->color_fwd_xform
= rgb32_to_yuv
;
248 layer
->color_inv_xform
= yuv_to_rgb32
;
252 layer
->color_fwd_xform
= rgba_to_yuv
;
253 layer
->color_inv_xform
= yuv_to_rgba
;
256 return -TARKIN_INVALID_COLOR_FORMAT
;
259 layer
->waveletbuf
= (Wavelet3DBuf
**) CALLOC (layer
->n_comp
,
260 sizeof(Wavelet3DBuf
*));
262 layer
->packet
= MALLOC (layer
->n_comp
* sizeof(*layer
->packet
));
263 memset(layer
->packet
, 0, layer
->n_comp
* sizeof(*layer
->packet
));
265 for (j
=0; j
<layer
->n_comp
; j
++){
266 layer
->waveletbuf
[j
] = wavelet_3d_buf_new (layer
->desc
.width
,
268 layer
->desc
.frames_per_buf
);
269 layer
->packet
[j
].data
= MALLOC(layer
->desc
.bitstream_len
);
270 layer
->packet
[j
].storage
= layer
->desc
.bitstream_len
;
273 vi
->max_bitstream_len
+= layer
->desc
.bitstream_len
274 + 2 * 10 * sizeof(uint32_t) * layer
->n_comp
; // truncation tables
277 printf("\n layer%d: size %dx%dx%d, format %d, a_m %d, s_m %d, %d fpb\n",
278 i
, layer
->desc
.width
, layer
->desc
.height
, layer
->n_comp
,
279 layer
->desc
.format
, layer
->desc
.a_moments
, layer
->desc
.s_moments
,
280 layer
->desc
.frames_per_buf
);
282 } /* for each layer */
284 if(oggpack_read(opb
,1)!=1)goto err_out
; /* EOP check */
295 tarkin_info_clear(vi
);
296 return(-TARKIN_BAD_HEADER
);
299 /* The Tarkin header is in three packets; the initial small packet in
300 the first page that identifies basic parameters, a second packet
301 with bitstream comments and a third packet that holds the
302 layer description structures. */
304 TarkinError
tarkin_synthesis_headerin(TarkinInfo
*vi
,TarkinComment
*vc
,ogg_packet
*op
){
308 oggpack_readinit(&opb
,op
->packet
,op
->bytes
);
310 /* Which of the three types of header is this? */
311 /* Also verify header-ness, tarkin */
314 int packtype
=oggpack_read(&opb
,8);
316 _v_readstring(&opb
,buffer
,6);
317 if(memcmp(buffer
,"tarkin",6)){
318 /* not a tarkin header */
319 return(-TARKIN_NOT_TARKIN
);
322 case 0x01: /* least significant *bit* is read first */
324 /* Not the initial packet */
325 return(-TARKIN_BAD_HEADER
);
327 if(vi
->inter
.numerator
!=0){
328 /* previously initialized info header */
329 return(-TARKIN_BAD_HEADER
);
332 return(_tarkin_unpack_info(vi
,&opb
));
334 case 0x03: /* least significant *bit* is read first */
335 if(vi
->inter
.denominator
==0){
336 /* um... we didn't get the initial header */
337 return(-TARKIN_BAD_HEADER
);
340 return(_tarkin_unpack_comment(vc
,&opb
));
342 case 0x05: /* least significant *bit* is read first */
343 if(vi
->inter
.numerator
== 0 || vc
->vendor
==NULL
){
344 /* um... we didn;t get the initial header or comments yet */
345 return(-TARKIN_BAD_HEADER
);
348 return(_tarkin_unpack_layer_desc(vi
,&opb
));
351 /* Not a valid tarkin header type */
352 return(-TARKIN_BAD_HEADER
);
357 return(-TARKIN_BAD_HEADER
);
360 /* pack side **********************************************************/
362 static int _tarkin_pack_info(oggpack_buffer
*opb
,TarkinInfo
*vi
){
365 oggpack_write(opb
,0x01,8);
366 _v_writestring(opb
,"tarkin", 6);
368 /* basic information about the stream */
369 oggpack_write(opb
,0x00,32);
370 oggpack_write(opb
,vi
->n_layers
,8);
371 oggpack_write(opb
,vi
->inter
.numerator
,32);
372 oggpack_write(opb
,vi
->inter
.denominator
,32);
374 oggpack_write(opb
,vi
->bitrate_upper
,32);
375 oggpack_write(opb
,vi
->bitrate_nominal
,32);
376 oggpack_write(opb
,vi
->bitrate_lower
,32);
378 oggpack_write(opb
,1,1);
381 printf("dbg_ogg: Putting out info, inter %d/%d, n_layers %d\n",
382 vi
->inter
.numerator
,vi
->inter
.denominator
,vi
->n_layers
);
387 static int _tarkin_pack_comment(oggpack_buffer
*opb
,TarkinComment
*vc
){
388 char temp
[]="libTarkin debugging edition 20011104";
389 int bytes
= strlen(temp
);
392 oggpack_write(opb
,0x03,8);
393 _v_writestring(opb
,"tarkin", 6);
396 oggpack_write(opb
,bytes
,32);
397 _v_writestring(opb
,temp
, bytes
);
401 oggpack_write(opb
,vc
->comments
,32);
404 for(i
=0;i
<vc
->comments
;i
++){
405 if(vc
->user_comments
[i
]){
406 oggpack_write(opb
,vc
->comment_lengths
[i
],32);
407 _v_writestring(opb
,vc
->user_comments
[i
], vc
->comment_lengths
[i
]);
409 oggpack_write(opb
,0,32);
413 oggpack_write(opb
,1,1);
416 printf("dbg_ogg: Putting out %d comments\n", vc
->comments
);
422 static int _tarkin_pack_layer_desc(oggpack_buffer
*opb
,TarkinInfo
*vi
)
425 TarkinVideoLayer
*layer
;
428 printf("dbg_ogg: Putting out layers description:\n");
431 oggpack_write(opb
,0x05,8);
432 _v_writestring(opb
,"tarkin", 6);
434 for(i
=0;i
<vi
->n_layers
;i
++){
435 layer
= vi
->layer
+ i
;
436 oggpack_write(opb
,layer
->desc
.width
,32);
437 oggpack_write(opb
,layer
->desc
.height
,32);
438 oggpack_write(opb
,layer
->desc
.a_moments
,32);
439 oggpack_write(opb
,layer
->desc
.s_moments
,32);
440 oggpack_write(opb
,layer
->desc
.frames_per_buf
,32);
441 oggpack_write(opb
,layer
->desc
.bitstream_len
,32);
442 oggpack_write(opb
,layer
->desc
.format
,32);
445 printf(" res. %dx%d, format %d, a_m %d, s_m %d, fpb %d\n",
446 layer
->desc
.width
, layer
->desc
.height
, layer
->desc
.format
,
447 layer
->desc
.a_moments
, layer
->desc
.s_moments
,
448 layer
->desc
.frames_per_buf
);
452 oggpack_write(opb
,1,1);
455 printf(" wrote %ld bytes.\n", oggpack_bytes(opb
));
461 int tarkin_comment_header_out(TarkinComment
*vc
, ogg_packet
*op
)
466 oggpack_writeinit(&opb
);
467 if(_tarkin_pack_comment(&opb
,vc
)) return -TARKIN_NOT_IMPLEMENTED
;
469 op
->packet
= MALLOC(oggpack_bytes(&opb
));
470 memcpy(op
->packet
, opb
.buffer
, oggpack_bytes(&opb
));
472 op
->bytes
=oggpack_bytes(&opb
);
480 TarkinError
tarkin_analysis_headerout(TarkinStream
*v
,
486 int ret
=-TARKIN_NOT_IMPLEMENTED
;
489 tarkin_header_store
*b
=&v
->headers
;
493 /* first header packet **********************************************/
495 oggpack_writeinit(&opb
);
496 if(_tarkin_pack_info(&opb
,vi
))goto err_out
;
498 /* build the packet */
499 if(b
->header
)FREE(b
->header
);
500 b
->header
=MALLOC(oggpack_bytes(&opb
));
501 memcpy(b
->header
,opb
.buffer
,oggpack_bytes(&opb
));
502 op
->packet
=b
->header
;
503 op
->bytes
=oggpack_bytes(&opb
);
508 /* second header packet (comments) **********************************/
511 if(_tarkin_pack_comment(&opb
,vc
))goto err_out
;
513 if(b
->header1
)FREE(b
->header1
);
514 b
->header1
=MALLOC(oggpack_bytes(&opb
));
515 memcpy(b
->header1
,opb
.buffer
,oggpack_bytes(&opb
));
516 op_comm
->packet
=b
->header1
;
517 op_comm
->bytes
=oggpack_bytes(&opb
);
520 op_comm
->granulepos
=0;
522 /* third header packet (modes/codebooks) ****************************/
525 if(_tarkin_pack_layer_desc(&opb
,vi
))goto err_out
;
527 if(b
->header2
)FREE(b
->header2
);
528 b
->header2
=MALLOC(oggpack_bytes(&opb
));
529 memcpy(b
->header2
,opb
.buffer
,oggpack_bytes(&opb
));
530 op_code
->packet
=b
->header2
;
531 op_code
->bytes
=oggpack_bytes(&opb
);
534 op_code
->granulepos
=0;
536 oggpack_writeclear(&opb
);
539 oggpack_writeclear(&opb
);
540 memset(op
,0,sizeof(*op
));
541 memset(op_comm
,0,sizeof(*op_comm
));
542 memset(op_code
,0,sizeof(*op_code
));
544 if(b
->header
)FREE(b
->header
);
545 if(b
->header1
)FREE(b
->header1
);
546 if(b
->header2
)FREE(b
->header2
);