]> 4ch.mooo.com Git - 16.git/blob - src/lib/dl/ext/vorbtool/theora.c
cleaned up the repo from debugging watcom2 ^^
[16.git] / src / lib / dl / ext / vorbtool / theora.c
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  ********************************************************************
12
13   function:
14   last mod: $Id: theora.c 17072 2010-03-26 05:07:26Z giles $
15
16  ********************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include "theora.h"
25
26 #define theora_read(x,y,z) ( *z = oggpackB_read(x,y) )
27
28 static void _tp_readbuffer(oggpack_buffer *opb, char *buf, const long len)
29 {
30   long i;
31   long ret;
32
33   for (i = 0; i < len; i++) {
34     theora_read(opb, 8, &ret);
35     *buf++=(char)ret;
36   }
37 }
38
39 static void _tp_readlsbint(oggpack_buffer *opb, long *value)
40 {
41   int i;
42   long ret[4];
43
44   for (i = 0; i < 4; i++) {
45     theora_read(opb,8,&ret[i]);
46   }
47   *value = ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24;
48 }
49
50 void theora_info_clear(theora_info *c) {
51   memset(c,0,sizeof(*c));
52 }
53
54 static int _theora_unpack_info(theora_info *ci, oggpack_buffer *opb){
55   long ret;
56
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;
63
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;
76
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;
85
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;
92
93   theora_read(opb,5,&ret);
94   ci->granule_shift = ret;
95
96   theora_read(opb,2,&ret);
97   ci->pixelformat=ret;
98
99   /* spare configuration bits */
100   if ( theora_read(opb,3,&ret) == -1 )
101     return (OC_BADHEADER);
102
103   return(0);
104 }
105
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);
114     memset(tc,0,sizeof(*tc));
115   }
116 }
117
118 static int _theora_unpack_comment(theora_comment *tc, oggpack_buffer *opb){
119   int i;
120   long len;
121
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';
127
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;
139   }
140   return(0);
141
142 parse_err:
143   theora_comment_clear(tc);
144   return(OC_BADHEADER);
145 }
146
147 static int _theora_unpack_tables(theora_info *c, oggpack_buffer *opb){
148   /* NOP: ogginfo doesn't use this information */
149   return 0;
150 }
151
152 int theora_decode_header(theora_info *ci, theora_comment *cc, ogg_packet *op){
153   long ret;
154   oggpack_buffer *opb;
155
156   if(!op)return OC_BADHEADER;
157
158   opb = _ogg_malloc(sizeof(oggpack_buffer));
159   oggpackB_readinit(opb,op->packet,op->bytes);
160   {
161     char id[6];
162     int typeflag;
163
164     theora_read(opb,8,&ret);
165     typeflag = ret;
166     if(!(typeflag&0x80)) {
167       free(opb);
168       return(OC_NOTFORMAT);
169     }
170
171     _tp_readbuffer(opb,id,6);
172     if(memcmp(id,"theora",6)) {
173       free(opb);
174       return(OC_NOTFORMAT);
175     }
176
177     switch(typeflag){
178     case 0x80:
179       if(!op->b_o_s){
180         /* Not the initial packet */
181         free(opb);
182         return(OC_BADHEADER);
183       }
184       if(ci->version_major!=0){
185         /* previously initialized info header */
186         free(opb);
187         return OC_BADHEADER;
188       }
189
190       ret = _theora_unpack_info(ci,opb);
191       free(opb);
192       return(ret);
193
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);
199       }
200
201       ret = _theora_unpack_comment(cc,opb);
202       free(opb);
203       return(ret);
204
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);
210       }
211
212       ret = _theora_unpack_tables(ci,opb);
213       free(opb);
214       return(ret);
215
216     default:
217       free(opb);
218       /* ignore any trailing header packets for forward compatibility */
219       return(OC_NEWPACKET);
220     }
221   }
222   /* I don't think it's possible to get this far, but better safe.. */
223   free(opb);
224   return(OC_BADHEADER);
225 }