Line data Source code
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-2009 *
9 : * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
10 : * *
11 : ********************************************************************
12 :
13 : function:
14 : last mod: $Id: decinfo.c 17276 2010-06-05 05:57:05Z tterribe $
15 :
16 : ********************************************************************/
17 :
18 : #include <stdlib.h>
19 : #include <string.h>
20 : #include <limits.h>
21 : #include "decint.h"
22 :
23 :
24 :
25 : /*Unpacks a series of octets from a given byte array into the pack buffer.
26 : No checking is done to ensure the buffer contains enough data.
27 : _opb: The pack buffer to read the octets from.
28 : _buf: The byte array to store the unpacked bytes in.
29 : _len: The number of octets to unpack.*/
30 0 : static void oc_unpack_octets(oc_pack_buf *_opb,char *_buf,size_t _len){
31 0 : while(_len-->0){
32 : long val;
33 0 : val=oc_pack_read(_opb,8);
34 0 : *_buf++=(char)val;
35 : }
36 0 : }
37 :
38 : /*Unpacks a 32-bit integer encoded by octets in little-endian form.*/
39 0 : static long oc_unpack_length(oc_pack_buf *_opb){
40 : long ret[4];
41 : int i;
42 0 : for(i=0;i<4;i++)ret[i]=oc_pack_read(_opb,8);
43 0 : return ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24;
44 : }
45 :
46 0 : static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
47 : long val;
48 : /*Check the codec bitstream version.*/
49 0 : val=oc_pack_read(_opb,8);
50 0 : _info->version_major=(unsigned char)val;
51 0 : val=oc_pack_read(_opb,8);
52 0 : _info->version_minor=(unsigned char)val;
53 0 : val=oc_pack_read(_opb,8);
54 0 : _info->version_subminor=(unsigned char)val;
55 : /*verify we can parse this bitstream version.
56 : We accept earlier minors and all subminors, by spec*/
57 0 : if(_info->version_major>TH_VERSION_MAJOR||
58 0 : _info->version_major==TH_VERSION_MAJOR&&
59 0 : _info->version_minor>TH_VERSION_MINOR){
60 0 : return TH_EVERSION;
61 : }
62 : /*Read the encoded frame description.*/
63 0 : val=oc_pack_read(_opb,16);
64 0 : _info->frame_width=(ogg_uint32_t)val<<4;
65 0 : val=oc_pack_read(_opb,16);
66 0 : _info->frame_height=(ogg_uint32_t)val<<4;
67 0 : val=oc_pack_read(_opb,24);
68 0 : _info->pic_width=(ogg_uint32_t)val;
69 0 : val=oc_pack_read(_opb,24);
70 0 : _info->pic_height=(ogg_uint32_t)val;
71 0 : val=oc_pack_read(_opb,8);
72 0 : _info->pic_x=(ogg_uint32_t)val;
73 0 : val=oc_pack_read(_opb,8);
74 0 : _info->pic_y=(ogg_uint32_t)val;
75 0 : val=oc_pack_read(_opb,32);
76 0 : _info->fps_numerator=(ogg_uint32_t)val;
77 0 : val=oc_pack_read(_opb,32);
78 0 : _info->fps_denominator=(ogg_uint32_t)val;
79 0 : if(_info->frame_width==0||_info->frame_height==0||
80 0 : _info->pic_width+_info->pic_x>_info->frame_width||
81 0 : _info->pic_height+_info->pic_y>_info->frame_height||
82 0 : _info->fps_numerator==0||_info->fps_denominator==0){
83 0 : return TH_EBADHEADER;
84 : }
85 : /*Note: The sense of pic_y is inverted in what we pass back to the
86 : application compared to how it is stored in the bitstream.
87 : This is because the bitstream uses a right-handed coordinate system, while
88 : applications expect a left-handed one.*/
89 0 : _info->pic_y=_info->frame_height-_info->pic_height-_info->pic_y;
90 0 : val=oc_pack_read(_opb,24);
91 0 : _info->aspect_numerator=(ogg_uint32_t)val;
92 0 : val=oc_pack_read(_opb,24);
93 0 : _info->aspect_denominator=(ogg_uint32_t)val;
94 0 : val=oc_pack_read(_opb,8);
95 0 : _info->colorspace=(th_colorspace)val;
96 0 : val=oc_pack_read(_opb,24);
97 0 : _info->target_bitrate=(int)val;
98 0 : val=oc_pack_read(_opb,6);
99 0 : _info->quality=(int)val;
100 0 : val=oc_pack_read(_opb,5);
101 0 : _info->keyframe_granule_shift=(int)val;
102 0 : val=oc_pack_read(_opb,2);
103 0 : _info->pixel_fmt=(th_pixel_fmt)val;
104 0 : if(_info->pixel_fmt==TH_PF_RSVD)return TH_EBADHEADER;
105 0 : val=oc_pack_read(_opb,3);
106 0 : if(val!=0||oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
107 0 : return 0;
108 : }
109 :
110 0 : static int oc_comment_unpack(oc_pack_buf *_opb,th_comment *_tc){
111 : long len;
112 : int i;
113 : /*Read the vendor string.*/
114 0 : len=oc_unpack_length(_opb);
115 0 : if(len<0||len>oc_pack_bytes_left(_opb))return TH_EBADHEADER;
116 0 : _tc->vendor=_ogg_malloc((size_t)len+1);
117 0 : if(_tc->vendor==NULL)return TH_EFAULT;
118 0 : oc_unpack_octets(_opb,_tc->vendor,len);
119 0 : _tc->vendor[len]='\0';
120 : /*Read the user comments.*/
121 0 : _tc->comments=(int)oc_unpack_length(_opb);
122 0 : len=_tc->comments;
123 0 : if(len<0||len>(LONG_MAX>>2)||len<<2>oc_pack_bytes_left(_opb)){
124 0 : _tc->comments=0;
125 0 : return TH_EBADHEADER;
126 : }
127 0 : _tc->comment_lengths=(int *)_ogg_malloc(
128 0 : _tc->comments*sizeof(_tc->comment_lengths[0]));
129 0 : _tc->user_comments=(char **)_ogg_malloc(
130 0 : _tc->comments*sizeof(_tc->user_comments[0]));
131 0 : if(_tc->comment_lengths==NULL||_tc->user_comments==NULL){
132 0 : _tc->comments=0;
133 0 : return TH_EFAULT;
134 : }
135 0 : for(i=0;i<_tc->comments;i++){
136 0 : len=oc_unpack_length(_opb);
137 0 : if(len<0||len>oc_pack_bytes_left(_opb)){
138 0 : _tc->comments=i;
139 0 : return TH_EBADHEADER;
140 : }
141 0 : _tc->comment_lengths[i]=len;
142 0 : _tc->user_comments[i]=_ogg_malloc((size_t)len+1);
143 0 : if(_tc->user_comments[i]==NULL){
144 0 : _tc->comments=i;
145 0 : return TH_EFAULT;
146 : }
147 0 : oc_unpack_octets(_opb,_tc->user_comments[i],len);
148 0 : _tc->user_comments[i][len]='\0';
149 : }
150 0 : return oc_pack_bytes_left(_opb)<0?TH_EBADHEADER:0;
151 : }
152 :
153 0 : static int oc_setup_unpack(oc_pack_buf *_opb,th_setup_info *_setup){
154 : int ret;
155 : /*Read the quantizer tables.*/
156 0 : ret=oc_quant_params_unpack(_opb,&_setup->qinfo);
157 0 : if(ret<0)return ret;
158 : /*Read the Huffman trees.*/
159 0 : return oc_huff_trees_unpack(_opb,_setup->huff_tables);
160 : }
161 :
162 0 : static void oc_setup_clear(th_setup_info *_setup){
163 0 : oc_quant_params_clear(&_setup->qinfo);
164 0 : oc_huff_trees_clear(_setup->huff_tables);
165 0 : }
166 :
167 0 : static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info,
168 : th_comment *_tc,th_setup_info **_setup,ogg_packet *_op){
169 : char buffer[6];
170 : long val;
171 : int packtype;
172 : int ret;
173 0 : val=oc_pack_read(_opb,8);
174 0 : packtype=(int)val;
175 : /*If we're at a data packet and we have received all three headers, we're
176 : done.*/
177 0 : if(!(packtype&0x80)&&_info->frame_width>0&&_tc->vendor!=NULL&&*_setup!=NULL){
178 0 : return 0;
179 : }
180 : /*Check the codec string.*/
181 0 : oc_unpack_octets(_opb,buffer,6);
182 0 : if(memcmp(buffer,"theora",6)!=0)return TH_ENOTFORMAT;
183 0 : switch(packtype){
184 : /*Codec info header.*/
185 : case 0x80:{
186 : /*This should be the first packet, and we should not already be
187 : initialized.*/
188 0 : if(!_op->b_o_s||_info->frame_width>0)return TH_EBADHEADER;
189 0 : ret=oc_info_unpack(_opb,_info);
190 0 : if(ret<0)th_info_clear(_info);
191 0 : else ret=3;
192 0 : }break;
193 : /*Comment header.*/
194 : case 0x81:{
195 0 : if(_tc==NULL)return TH_EFAULT;
196 : /*We shoud have already decoded the info header, and should not yet have
197 : decoded the comment header.*/
198 0 : if(_info->frame_width==0||_tc->vendor!=NULL)return TH_EBADHEADER;
199 0 : ret=oc_comment_unpack(_opb,_tc);
200 0 : if(ret<0)th_comment_clear(_tc);
201 0 : else ret=2;
202 0 : }break;
203 : /*Codec setup header.*/
204 : case 0x82:{
205 : oc_setup_info *setup;
206 0 : if(_tc==NULL||_setup==NULL)return TH_EFAULT;
207 : /*We should have already decoded the info header and the comment header,
208 : and should not yet have decoded the setup header.*/
209 0 : if(_info->frame_width==0||_tc->vendor==NULL||*_setup!=NULL){
210 0 : return TH_EBADHEADER;
211 : }
212 0 : setup=(oc_setup_info *)_ogg_calloc(1,sizeof(*setup));
213 0 : if(setup==NULL)return TH_EFAULT;
214 0 : ret=oc_setup_unpack(_opb,setup);
215 0 : if(ret<0){
216 0 : oc_setup_clear(setup);
217 0 : _ogg_free(setup);
218 : }
219 : else{
220 0 : *_setup=setup;
221 0 : ret=1;
222 : }
223 0 : }break;
224 : default:{
225 : /*We don't know what this header is.*/
226 0 : return TH_EBADHEADER;
227 : }break;
228 : }
229 0 : return ret;
230 : }
231 :
232 :
233 : /*Decodes one header packet.
234 : This should be called repeatedly with the packets at the beginning of the
235 : stream until it returns 0.*/
236 0 : int th_decode_headerin(th_info *_info,th_comment *_tc,
237 : th_setup_info **_setup,ogg_packet *_op){
238 : oc_pack_buf opb;
239 0 : if(_op==NULL)return TH_EBADHEADER;
240 0 : if(_info==NULL)return TH_EFAULT;
241 0 : oc_pack_readinit(&opb,_op->packet,_op->bytes);
242 0 : return oc_dec_headerin(&opb,_info,_tc,_setup,_op);
243 : }
244 :
245 0 : void th_setup_free(th_setup_info *_setup){
246 0 : if(_setup!=NULL){
247 0 : oc_setup_clear(_setup);
248 0 : _ogg_free(_setup);
249 : }
250 0 : }
|