Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / theora-old / lib / toplevel.c
blobdb9e6289cc232ef52f7224b9ea9633ed33d6ab7c
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-2005 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
10 * *
11 ********************************************************************
13 function:
14 last mod: $Id$
16 ********************************************************************/
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
22 #include <stdlib.h>
23 #include <string.h>
24 #include "theora/theora.h"
25 #include "toplevel.h"
26 #include "dsp.h"
28 static int _ilog(unsigned int v){
29 int ret=0;
30 while(v){
31 ret++;
32 v>>=1;
34 return(ret);
37 const char *theora_version_string(void){
38 return VENDOR_STRING;
41 ogg_uint32_t theora_version_number(void){
42 return (VERSION_MAJOR<<16) + (VERSION_MINOR<<8) + (VERSION_SUB);
46 static void _tp_readbuffer(oggpack_buffer *opb, char *buf, const long len)
48 long i;
49 long ret;
51 for (i = 0; i < len; i++) {
52 theora_read(opb, 8, &ret);
53 *buf++=(char)ret;
57 static void _tp_readlsbint(oggpack_buffer *opb, long *value)
59 int i;
60 long ret[4];
62 for (i = 0; i < 4; i++) {
63 theora_read(opb,8,&ret[i]);
65 *value = ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24;
68 void theora_info_init(theora_info *c) {
69 memset(c,0,sizeof(*c));
70 c->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
73 void theora_info_clear(theora_info *c) {
74 codec_setup_info *ci=c->codec_setup;
75 int i;
76 if(ci){
77 if(ci->qmats) _ogg_free(ci->qmats);
78 for(i=0;i<6;i++)
79 if(ci->range_table[i]) _ogg_free(ci->range_table[i]);
80 ClearHuffmanTrees(ci->HuffRoot);
81 _ogg_free(ci);
83 memset(c,0,sizeof(*c));
86 void theora_clear(theora_state *t){
87 if(t){
88 CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal_encode);
89 PB_INSTANCE *pbi=(PB_INSTANCE *)(t->internal_decode);
91 if (cpi) theora_encoder_clear (cpi);
93 if(pbi){
95 theora_info_clear(&pbi->info);
96 ClearHuffmanSet(pbi);
97 ClearFragmentInfo(pbi);
98 ClearFrameInfo(pbi);
99 ClearPBInstance(pbi);
101 _ogg_free(t->internal_decode);
104 t->internal_encode=NULL;
105 t->internal_decode=NULL;
109 /********************** The toplevel: decode ***********************/
111 static int _theora_unpack_info(theora_info *ci, oggpack_buffer *opb){
112 long ret;
114 theora_read(opb,8,&ret);
115 ci->version_major=(unsigned char)ret;
116 theora_read(opb,8,&ret);
117 ci->version_minor=(unsigned char)ret;
118 theora_read(opb,8,&ret);
119 ci->version_subminor=(unsigned char)ret;
121 if(ci->version_major!=VERSION_MAJOR)return(OC_VERSION);
122 if(ci->version_minor>VERSION_MINOR)return(OC_VERSION);
124 theora_read(opb,16,&ret);
125 ci->width=ret<<4;
126 theora_read(opb,16,&ret);
127 ci->height=ret<<4;
128 theora_read(opb,24,&ret);
129 ci->frame_width=ret;
130 theora_read(opb,24,&ret);
131 ci->frame_height=ret;
132 theora_read(opb,8,&ret);
133 ci->offset_x=ret;
134 theora_read(opb,8,&ret);
135 ci->offset_y=ret;
136 /* Change offset_y to have the meaning everyone expects it to have */
137 ci->offset_y = ci->height - ci->frame_height - ci->offset_y;
139 theora_read(opb,32,&ret);
140 ci->fps_numerator=ret;
141 theora_read(opb,32,&ret);
142 ci->fps_denominator=ret;
143 theora_read(opb,24,&ret);
144 ci->aspect_numerator=ret;
145 theora_read(opb,24,&ret);
146 ci->aspect_denominator=ret;
148 theora_read(opb,8,&ret);
149 ci->colorspace=ret;
150 theora_read(opb,24,&ret);
151 ci->target_bitrate=ret;
152 theora_read(opb,6,&ret);
153 ci->quality=ret;
155 theora_read(opb,5,&ret);
156 ci->keyframe_frequency_force=1<<ret;
158 theora_read(opb,2,&ret);
159 ci->pixelformat=ret;
160 if(ci->pixelformat==OC_PF_RSVD)
161 return (OC_BADHEADER);
162 /* 4:2:2 and 4:4:4 not currently implemented */
163 else if(ci->pixelformat != OC_PF_420)
164 return (OC_IMPL);
166 /* spare configuration bits */
167 if ( theora_read(opb,3,&ret) == -1 )
168 return (OC_BADHEADER);
170 return(0);
173 static int _theora_unpack_comment(theora_comment *tc, oggpack_buffer *opb){
174 int i;
175 long len,tmp;
177 _tp_readlsbint(opb,&len);
178 if(len<0)return(OC_BADHEADER);
179 tc->vendor=_ogg_calloc(1,len+1);
180 _tp_readbuffer(opb,tc->vendor, len);
181 tc->vendor[len]='\0';
183 _tp_readlsbint(opb,&tmp);
184 tc->comments=tmp;
185 if(tc->comments<0)goto parse_err;
186 tc->user_comments=_ogg_calloc(tc->comments,sizeof(*tc->user_comments));
187 tc->comment_lengths=_ogg_calloc(tc->comments,sizeof(*tc->comment_lengths));
188 for(i=0;i<tc->comments;i++){
189 _tp_readlsbint(opb,&len);
190 if(len<0)goto parse_err;
191 tc->user_comments[i]=_ogg_calloc(1,len+1);
192 _tp_readbuffer(opb,tc->user_comments[i],len);
193 tc->user_comments[i][len]='\0';
194 tc->comment_lengths[i]=len;
196 return(0);
198 parse_err:
199 theora_comment_clear(tc);
200 return(OC_BADHEADER);
203 static int _theora_unpack_tables(theora_info *c, oggpack_buffer *opb){
204 codec_setup_info *ci;
205 int ret;
207 ci=(codec_setup_info *)c->codec_setup;
209 ret=ReadFilterTables(ci, opb);
210 if(ret)return ret;
211 ret=ReadQTables(ci, opb);
212 if(ret)return ret;
213 ret=ReadHuffmanTrees(ci, opb);
214 if(ret)return ret;
216 return ret;
219 int theora_decode_header(theora_info *ci, theora_comment *cc, ogg_packet *op){
220 long ret;
221 oggpack_buffer *opb;
223 if(!op)return OC_BADHEADER;
225 #ifndef LIBOGG2
226 opb = _ogg_malloc(sizeof(oggpack_buffer));
227 oggpackB_readinit(opb,op->packet,op->bytes);
228 #else
229 opb = _ogg_malloc(oggpack_buffersize());
230 oggpackB_readinit(opb,op->packet);
231 #endif
233 char id[6];
234 int typeflag;
236 theora_read(opb,8,&ret);
237 typeflag = ret;
238 if(!(typeflag&0x80)) {
239 _ogg_free(opb);
240 return(OC_NOTFORMAT);
243 _tp_readbuffer(opb,id,6);
244 if(memcmp(id,"theora",6)) {
245 _ogg_free(opb);
246 return(OC_NOTFORMAT);
249 switch(typeflag){
250 case 0x80:
251 if(!op->b_o_s){
252 /* Not the initial packet */
253 _ogg_free(opb);
254 return(OC_BADHEADER);
256 if(ci->version_major!=0){
257 /* previously initialized info header */
258 _ogg_free(opb);
259 return OC_BADHEADER;
262 ret = _theora_unpack_info(ci,opb);
263 _ogg_free(opb);
264 return(ret);
266 case 0x81:
267 if(ci->version_major==0){
268 /* um... we didn't get the initial header */
269 _ogg_free(opb);
270 return(OC_BADHEADER);
273 ret = _theora_unpack_comment(cc,opb);
274 _ogg_free(opb);
275 return(ret);
277 case 0x82:
278 if(ci->version_major==0 || cc->vendor==NULL){
279 /* um... we didn't get the initial header or comments yet */
280 _ogg_free(opb);
281 return(OC_BADHEADER);
284 ret = _theora_unpack_tables(ci,opb);
285 _ogg_free(opb);
286 return(ret);
288 default:
289 _ogg_free(opb);
290 if(ci->version_major==0 || cc->vendor==NULL ||
291 ((codec_setup_info *)ci->codec_setup)->HuffRoot[0]==NULL){
292 /* we haven't gotten the three required headers */
293 return(OC_BADHEADER);
295 /* ignore any trailing header packets for forward compatibility */
296 return(OC_NEWPACKET);
299 /* I don't think it's possible to get this far, but better safe.. */
300 _ogg_free(opb);
301 return(OC_BADHEADER);
304 int theora_decode_init(theora_state *th, theora_info *c){
305 PB_INSTANCE *pbi;
306 codec_setup_info *ci;
308 ci=(codec_setup_info *)c->codec_setup;
309 memset(th, 0, sizeof(*th));
310 th->internal_decode=pbi=_ogg_calloc(1,sizeof(*pbi));
311 th->internal_encode=NULL;
313 InitPBInstance(pbi);
315 dsp_static_init (&pbi->dsp);
317 memcpy(&pbi->info,c,sizeof(*c));
318 pbi->info.codec_setup=NULL;
319 th->i=&pbi->info;
320 th->granulepos=-1;
322 InitFrameDetails(pbi);
324 pbi->keyframe_granule_shift=_ilog(c->keyframe_frequency_force-1);
326 pbi->LastFrameQualityValue = 0;
327 pbi->DecoderErrorCode = 0;
329 /* Clear down the YUVtoRGB conversion skipped list. */
330 memset(pbi->skipped_display_fragments, 0, pbi->UnitFragments );
332 /* Initialise quantiser and in-loop filter */
333 CopyQTables(pbi, ci);
334 CopyFilterTables(pbi, ci);
336 /* Huffman setup */
337 InitHuffmanTrees(pbi, ci);
339 return(0);
343 int theora_decode_packetin(theora_state *th,ogg_packet *op){
344 long ret;
345 PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal_decode);
347 pbi->DecoderErrorCode = 0;
349 #ifndef LIBOGG2
350 oggpackB_readinit(pbi->opb,op->packet,op->bytes);
351 #else
352 oggpackB_readinit(pbi->opb,op->packet);
353 #endif
355 if(op->bytes!=0){
356 /* verify that this is a video frame */
357 theora_read(pbi->opb,1,&ret);
359 if (ret==0) {
360 ret=LoadAndDecode(pbi);
362 if(ret)return ret;
364 if(pbi->PostProcessingLevel)
365 PostProcess(pbi);
367 if(op->granulepos>-1)
368 th->granulepos=op->granulepos;
369 else{
370 if(th->granulepos==-1){
371 th->granulepos=0;
372 }else{
373 if(pbi->FrameType==KEY_FRAME){
374 long frames= th->granulepos & ((1<<pbi->keyframe_granule_shift)-1);
375 th->granulepos>>=pbi->keyframe_granule_shift;
376 th->granulepos+=frames+1;
377 th->granulepos<<=pbi->keyframe_granule_shift;
378 }else
379 th->granulepos++;
383 return(0);
385 }else{
386 th->granulepos++;
387 return(OC_DUPFRAME);
390 return OC_BADPACKET;
393 int theora_decode_YUVout(theora_state *th,yuv_buffer *yuv){
394 PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal_decode);
396 yuv->y_width = pbi->info.width;
397 yuv->y_height = pbi->info.height;
398 yuv->y_stride = pbi->YStride;
400 yuv->uv_width = pbi->info.width / 2;
401 yuv->uv_height = pbi->info.height / 2;
402 yuv->uv_stride = pbi->UVStride;
404 if(pbi->PostProcessingLevel){
405 yuv->y = &pbi->PostProcessBuffer[pbi->ReconYDataOffset];
406 yuv->u = &pbi->PostProcessBuffer[pbi->ReconUDataOffset];
407 yuv->v = &pbi->PostProcessBuffer[pbi->ReconVDataOffset];
408 }else{
409 yuv->y = &pbi->LastFrameRecon[pbi->ReconYDataOffset];
410 yuv->u = &pbi->LastFrameRecon[pbi->ReconUDataOffset];
411 yuv->v = &pbi->LastFrameRecon[pbi->ReconVDataOffset];
414 /* we must flip the internal representation,
415 so make the stride negative and start at the end */
416 yuv->y += yuv->y_stride * (yuv->y_height - 1);
417 yuv->u += yuv->uv_stride * (yuv->uv_height - 1);
418 yuv->v += yuv->uv_stride * (yuv->uv_height - 1);
419 yuv->y_stride = - yuv->y_stride;
420 yuv->uv_stride = - yuv->uv_stride;
422 return 0;
425 /* returns, in seconds, absolute time of current packet in given
426 logical stream */
427 double theora_granule_time(theora_state *th,ogg_int64_t granulepos){
428 #ifndef THEORA_DISABLE_FLOAT
429 CP_INSTANCE *cpi=(CP_INSTANCE *)(th->internal_encode);
430 PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal_decode);
432 if(cpi)pbi=&cpi->pb;
434 if(granulepos>=0){
435 ogg_int64_t iframe=granulepos>>pbi->keyframe_granule_shift;
436 ogg_int64_t pframe=granulepos-(iframe<<pbi->keyframe_granule_shift);
438 return (iframe+pframe)*
439 ((double)pbi->info.fps_denominator/pbi->info.fps_numerator);
442 #endif
444 return(-1); /* negative granulepos or float calculations disabled */
447 /* check for header flag */
448 int theora_packet_isheader(ogg_packet *op)
450 return (op->packet[0] & 0x80) ? 1 : 0;
453 /* check for keyframe */
454 int theora_packet_iskeyframe(ogg_packet *op)
456 if (op->packet[0] & 0x80) return -1; /* not a data packet */
457 return (op->packet[0] & 0x40) ? 0 : 1; /* inter or intra */
460 /* returns the shift radix used to split the granulepos into two fields */
461 int theora_granule_shift(theora_info *ti)
463 return _ilog(ti->keyframe_frequency_force - 1);
466 /* returns frame number of current packet in given logical stream */
467 ogg_int64_t theora_granule_frame(theora_state *th,ogg_int64_t granulepos){
468 CP_INSTANCE *cpi=(CP_INSTANCE *)(th->internal_encode);
469 PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal_decode);
471 if(cpi)pbi=&cpi->pb;
473 if(granulepos>=0){
474 ogg_int64_t iframe=granulepos>>pbi->keyframe_granule_shift;
475 ogg_int64_t pframe=granulepos-(iframe<<pbi->keyframe_granule_shift);
477 return (iframe+pframe);
480 return(-1);