1 /********************************************************************
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. *
8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
14 last mod: $Id: toplevel.c,v 1.39 2004/03/18 02:00:30 giles Exp $
16 ********************************************************************/
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
)
33 for (i
= 0; i
< len
; i
++) {
34 theora_read(opb
, 8, &ret
);
39 static void _tp_readlsbint(oggpack_buffer
*opb
, long *value
)
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
){
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
);
66 theora_read(opb
,16,&ret
);
68 theora_read(opb
,24,&ret
);
70 theora_read(opb
,24,&ret
);
72 theora_read(opb
,8,&ret
);
74 theora_read(opb
,8,&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
);
88 theora_read(opb
,24,&ret
);
89 ci
->target_bitrate
=ret
;
90 theora_read(opb
,6,&ret
);
93 theora_read(opb
,5,&ret
);
94 ci
->granule_shift
= ret
;
96 theora_read(opb
,2,&ret
);
99 /* spare configuration bits */
100 if ( theora_read(opb
,3,&ret
) == -1 )
101 return (OC_BADHEADER
);
106 void theora_comment_clear(theora_comment
*tc
){
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
){
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
;
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 */
152 int theora_decode_header(theora_info
*ci
, theora_comment
*cc
, ogg_packet
*op
){
156 if(!op
)return OC_BADHEADER
;
158 opb
= _ogg_malloc(sizeof(oggpack_buffer
));
159 oggpackB_readinit(opb
,op
->packet
,op
->bytes
);
164 theora_read(opb
,8,&ret
);
166 if(!(typeflag
&0x80)) {
168 return(OC_NOTFORMAT
);
171 _tp_readbuffer(opb
,id
,6);
172 if(memcmp(id
,"theora",6)) {
174 return(OC_NOTFORMAT
);
180 /* Not the initial packet */
182 return(OC_BADHEADER
);
184 if(ci
->version_major
!=0){
185 /* previously initialized info header */
190 ret
= _theora_unpack_info(ci
,opb
);
195 if(ci
->version_major
==0){
196 /* um... we didn't get the initial header */
198 return(OC_BADHEADER
);
201 ret
= _theora_unpack_comment(cc
,opb
);
206 if(ci
->version_major
==0 || cc
->vendor
==NULL
){
207 /* um... we didn't get the initial header or comments yet */
209 return(OC_BADHEADER
);
212 ret
= _theora_unpack_tables(ci
,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.. */
224 return(OC_BADHEADER
);