Build script now builds an oggenc binary with flac support.
[vorbis-lancer-gcc.git] / vorbis-tools-1.2.0 / ogginfo / theora.c
blob3e7741bff63328af80b59e8f53f0410afbaed6db
1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggTheora 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. *
7 * *
8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
10 * *
11 ********************************************************************
13 function:
14 last mod: $Id: toplevel.c,v 1.39 2004/03/18 02:00:30 giles Exp $
16 ********************************************************************/
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdlib.h>
23 #include <string.h>
24 #include "theora.h"
26 #define theora_read(x,y,z) ( *z = oggpackB_read(x,y) )
28 static void _tp_readbuffer(oggpack_buffer *opb, char *buf, const long len)
30 long i;
31 long ret;
33 for (i = 0; i < len; i++) {
34 theora_read(opb, 8, &ret);
35 *buf++=(char)ret;
39 static void _tp_readlsbint(oggpack_buffer *opb, long *value)
41 int i;
42 long ret[4];
44 for (i = 0; i < 4; i++) {
45 theora_read(opb,8,&ret[i]);
47 *value = ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24;
50 void theora_info_clear(theora_info *c) {
51 memset(c,0,sizeof(*c));
54 static int _theora_unpack_info(theora_info *ci, oggpack_buffer *opb){
55 long ret;
57 theora_read(opb,8,&ret);
58 ci->version_major=(unsigned char)ret;
59 theora_read(opb,8,&ret);
60 ci->version_minor=(unsigned char)ret;
61 theora_read(opb,8,&ret);
62 ci->version_subminor=(unsigned char)ret;
64 theora_read(opb,16,&ret);
65 ci->width=ret<<4;
66 theora_read(opb,16,&ret);
67 ci->height=ret<<4;
68 theora_read(opb,24,&ret);
69 ci->frame_width=ret;
70 theora_read(opb,24,&ret);
71 ci->frame_height=ret;
72 theora_read(opb,8,&ret);
73 ci->offset_x=ret;
74 theora_read(opb,8,&ret);
75 ci->offset_y=ret;
77 theora_read(opb,32,&ret);
78 ci->fps_numerator=ret;
79 theora_read(opb,32,&ret);
80 ci->fps_denominator=ret;
81 theora_read(opb,24,&ret);
82 ci->aspect_numerator=ret;
83 theora_read(opb,24,&ret);
84 ci->aspect_denominator=ret;
86 theora_read(opb,8,&ret);
87 ci->colorspace=ret;
88 theora_read(opb,24,&ret);
89 ci->target_bitrate=ret;
90 theora_read(opb,6,&ret);
91 ci->quality=ret;
93 theora_read(opb,5,&ret);
94 ci->granule_shift = ret;
96 theora_read(opb,2,&ret);
97 ci->pixelformat=ret;
99 /* spare configuration bits */
100 if ( theora_read(opb,3,&ret) == -1 )
101 return (OC_BADHEADER);
103 return(0);
106 void theora_comment_clear(theora_comment *tc){
107 if(tc){
108 long i;
109 for(i=0;i<tc->comments;i++)
110 if(tc->user_comments[i])_ogg_free(tc->user_comments[i]);
111 if(tc->user_comments)_ogg_free(tc->user_comments);
112 if(tc->comment_lengths)_ogg_free(tc->comment_lengths);
113 if(tc->vendor)_ogg_free(tc->vendor);
115 memset(tc,0,sizeof(*tc));
118 static int _theora_unpack_comment(theora_comment *tc, oggpack_buffer *opb){
119 int i;
120 long len;
122 _tp_readlsbint(opb,&len);
123 if(len<0)return(OC_BADHEADER);
124 tc->vendor=_ogg_calloc(1,len+1);
125 _tp_readbuffer(opb,tc->vendor, len);
126 tc->vendor[len]='\0';
128 _tp_readlsbint(opb,(long *) &tc->comments);
129 if(tc->comments<0)goto parse_err;
130 tc->user_comments=_ogg_calloc(tc->comments,sizeof(*tc->user_comments));
131 tc->comment_lengths=_ogg_calloc(tc->comments,sizeof(*tc->comment_lengths));
132 for(i=0;i<tc->comments;i++){
133 _tp_readlsbint(opb,&len);
134 if(len<0)goto parse_err;
135 tc->user_comments[i]=_ogg_calloc(1,len+1);
136 _tp_readbuffer(opb,tc->user_comments[i],len);
137 tc->user_comments[i][len]='\0';
138 tc->comment_lengths[i]=len;
140 return(0);
142 parse_err:
143 theora_comment_clear(tc);
144 return(OC_BADHEADER);
147 static int _theora_unpack_tables(theora_info *c, oggpack_buffer *opb){
148 /* NOP: ogginfo doesn't use this information */
149 return 0;
152 int theora_decode_header(theora_info *ci, theora_comment *cc, ogg_packet *op){
153 long ret;
154 oggpack_buffer *opb;
156 if(!op)return OC_BADHEADER;
158 opb = _ogg_malloc(sizeof(oggpack_buffer));
159 oggpackB_readinit(opb,op->packet,op->bytes);
161 char id[6];
162 int typeflag;
164 theora_read(opb,8,&ret);
165 typeflag = ret;
166 if(!(typeflag&0x80)) {
167 free(opb);
168 return(OC_NOTFORMAT);
171 _tp_readbuffer(opb,id,6);
172 if(memcmp(id,"theora",6)) {
173 free(opb);
174 return(OC_NOTFORMAT);
177 switch(typeflag){
178 case 0x80:
179 if(!op->b_o_s){
180 /* Not the initial packet */
181 free(opb);
182 return(OC_BADHEADER);
184 if(ci->version_major!=0){
185 /* previously initialized info header */
186 free(opb);
187 return OC_BADHEADER;
190 ret = _theora_unpack_info(ci,opb);
191 free(opb);
192 return(ret);
194 case 0x81:
195 if(ci->version_major==0){
196 /* um... we didn't get the initial header */
197 free(opb);
198 return(OC_BADHEADER);
201 ret = _theora_unpack_comment(cc,opb);
202 free(opb);
203 return(ret);
205 case 0x82:
206 if(ci->version_major==0 || cc->vendor==NULL){
207 /* um... we didn't get the initial header or comments yet */
208 free(opb);
209 return(OC_BADHEADER);
212 ret = _theora_unpack_tables(ci,opb);
213 free(opb);
214 return(ret);
216 default:
217 free(opb);
218 /* ignore any trailing header packets for forward compatibility */
219 return(OC_NEWPACKET);
222 /* I don't think it's possible to get this far, but better safe.. */
223 free(opb);
224 return(OC_BADHEADER);