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: decapiwrapper.c 13596 2007-08-23 20:05:38Z tterribe $
15
16 ********************************************************************/
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <limits.h>
21 #include "apiwrapper.h"
22 #include "decint.h"
23 #include "theora/theoradec.h"
24
th_dec_api_clear(th_api_wrapper * _api)25 static void th_dec_api_clear(th_api_wrapper *_api){
26 if(_api->setup)th_setup_free(_api->setup);
27 if(_api->decode)th_decode_free(_api->decode);
28 memset(_api,0,sizeof(*_api));
29 }
30
theora_decode_clear(theora_state * _td)31 static void theora_decode_clear(theora_state *_td){
32 if(_td->i!=NULL)theora_info_clear(_td->i);
33 memset(_td,0,sizeof(*_td));
34 }
35
theora_decode_control(theora_state * _td,int _req,void * _buf,size_t _buf_sz)36 static int theora_decode_control(theora_state *_td,int _req,
37 void *_buf,size_t _buf_sz){
38 return th_decode_ctl(((th_api_wrapper *)_td->i->codec_setup)->decode,
39 _req,_buf,_buf_sz);
40 }
41
theora_decode_granule_frame(theora_state * _td,ogg_int64_t _gp)42 static ogg_int64_t theora_decode_granule_frame(theora_state *_td,
43 ogg_int64_t _gp){
44 return th_granule_frame(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp);
45 }
46
theora_decode_granule_time(theora_state * _td,ogg_int64_t _gp)47 static double theora_decode_granule_time(theora_state *_td,ogg_int64_t _gp){
48 return th_granule_time(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp);
49 }
50
51 static const oc_state_dispatch_vtable OC_DEC_DISPATCH_VTBL={
52 (oc_state_clear_func)theora_decode_clear,
53 (oc_state_control_func)theora_decode_control,
54 (oc_state_granule_frame_func)theora_decode_granule_frame,
55 (oc_state_granule_time_func)theora_decode_granule_time,
56 };
57
th_info2theora_info(theora_info * _ci,const th_info * _info)58 static void th_info2theora_info(theora_info *_ci,const th_info *_info){
59 _ci->version_major=_info->version_major;
60 _ci->version_minor=_info->version_minor;
61 _ci->version_subminor=_info->version_subminor;
62 _ci->width=_info->frame_width;
63 _ci->height=_info->frame_height;
64 _ci->frame_width=_info->pic_width;
65 _ci->frame_height=_info->pic_height;
66 _ci->offset_x=_info->pic_x;
67 _ci->offset_y=_info->pic_y;
68 _ci->fps_numerator=_info->fps_numerator;
69 _ci->fps_denominator=_info->fps_denominator;
70 _ci->aspect_numerator=_info->aspect_numerator;
71 _ci->aspect_denominator=_info->aspect_denominator;
72 switch(_info->colorspace){
73 case TH_CS_ITU_REC_470M:_ci->colorspace=OC_CS_ITU_REC_470M;break;
74 case TH_CS_ITU_REC_470BG:_ci->colorspace=OC_CS_ITU_REC_470BG;break;
75 default:_ci->colorspace=OC_CS_UNSPECIFIED;break;
76 }
77 switch(_info->pixel_fmt){
78 case TH_PF_420:_ci->pixelformat=OC_PF_420;break;
79 case TH_PF_422:_ci->pixelformat=OC_PF_422;break;
80 case TH_PF_444:_ci->pixelformat=OC_PF_444;break;
81 default:_ci->pixelformat=OC_PF_RSVD;
82 }
83 _ci->target_bitrate=_info->target_bitrate;
84 _ci->quality=_info->quality;
85 _ci->keyframe_frequency_force=1<<_info->keyframe_granule_shift;
86 }
87
theora_decode_init(theora_state * _td,theora_info * _ci)88 int theora_decode_init(theora_state *_td,theora_info *_ci){
89 th_api_info *apiinfo;
90 th_api_wrapper *api;
91 th_info info;
92 api=(th_api_wrapper *)_ci->codec_setup;
93 /*Allocate our own combined API wrapper/theora_info struct.
94 We put them both in one malloc'd block so that when the API wrapper is
95 freed, the info struct goes with it.
96 This avoids having to figure out whether or not we need to free the info
97 struct in either theora_info_clear() or theora_clear().*/
98 apiinfo=(th_api_info *)_ogg_calloc(1,sizeof(*apiinfo));
99 if(apiinfo==NULL)return OC_FAULT;
100 /*Make our own copy of the info struct, since its lifetime should be
101 independent of the one we were passed in.*/
102 *&apiinfo->info=*_ci;
103 /*Convert the info struct now instead of saving the the one we decoded with
104 theora_decode_header(), since the user might have modified values (i.e.,
105 color space, aspect ratio, etc. can be specified from a higher level).
106 The user also might be doing something "clever" with the header packets if
107 they are not using an Ogg encapsulation.*/
108 oc_theora_info2th_info(&info,_ci);
109 /*Don't bother to copy the setup info; th_decode_alloc() makes its own copy
110 of the stuff it needs.*/
111 apiinfo->api.decode=th_decode_alloc(&info,api->setup);
112 if(apiinfo->api.decode==NULL){
113 _ogg_free(apiinfo);
114 return OC_EINVAL;
115 }
116 apiinfo->api.clear=(oc_setup_clear_func)th_dec_api_clear;
117 _td->internal_encode=NULL;
118 /*Provide entry points for ABI compatibility with old decoder shared libs.*/
119 _td->internal_decode=(void *)&OC_DEC_DISPATCH_VTBL;
120 _td->granulepos=0;
121 _td->i=&apiinfo->info;
122 _td->i->codec_setup=&apiinfo->api;
123 return 0;
124 }
125
theora_decode_header(theora_info * _ci,theora_comment * _cc,ogg_packet * _op)126 int theora_decode_header(theora_info *_ci,theora_comment *_cc,ogg_packet *_op){
127 th_api_wrapper *api;
128 th_info info;
129 int ret;
130 api=(th_api_wrapper *)_ci->codec_setup;
131 /*Allocate an API wrapper struct on demand, since it will not also include a
132 theora_info struct like the ones that are used in a theora_state struct.*/
133 if(api==NULL){
134 _ci->codec_setup=_ogg_calloc(1,sizeof(*api));
135 if(_ci->codec_setup==NULL)return OC_FAULT;
136 api=(th_api_wrapper *)_ci->codec_setup;
137 api->clear=(oc_setup_clear_func)th_dec_api_clear;
138 }
139 /*Convert from the theora_info struct instead of saving our own th_info
140 struct between calls.
141 The user might be doing something "clever" with the header packets if they
142 are not using an Ogg encapsulation, and we don't want to break this.*/
143 oc_theora_info2th_info(&info,_ci);
144 /*We rely on the fact that theora_comment and th_comment structures are
145 actually identical.
146 Take care not to change this fact unless you change the code here as
147 well!*/
148 ret=th_decode_headerin(&info,(th_comment *)_cc,&api->setup,_op);
149 /*We also rely on the fact that the error return code values are the same,
150 and that the implementations of these two functions return the same set of
151 them.
152 Note that theora_decode_header() really can return OC_NOTFORMAT, even
153 though it is not currently documented to do so.*/
154 if(ret<0)return ret;
155 th_info2theora_info(_ci,&info);
156 return 0;
157 }
158
theora_decode_packetin(theora_state * _td,ogg_packet * _op)159 int theora_decode_packetin(theora_state *_td,ogg_packet *_op){
160 th_api_wrapper *api;
161 ogg_int64_t gp;
162 int ret;
163 if(!_td||!_td->i||!_td->i->codec_setup)return OC_FAULT;
164 api=(th_api_wrapper *)_td->i->codec_setup;
165 ret=th_decode_packetin(api->decode,_op,&gp);
166 if(ret<0)return OC_BADPACKET;
167 _td->granulepos=gp;
168 return 0;
169 }
170
theora_decode_YUVout(theora_state * _td,yuv_buffer * _yuv)171 int theora_decode_YUVout(theora_state *_td,yuv_buffer *_yuv){
172 th_api_wrapper *api;
173 th_dec_ctx *decode;
174 th_ycbcr_buffer buf;
175 int ret;
176 if(!_td||!_td->i||!_td->i->codec_setup)return OC_FAULT;
177 api=(th_api_wrapper *)_td->i->codec_setup;
178 decode=(th_dec_ctx *)api->decode;
179 if(!decode)return OC_FAULT;
180 ret=th_decode_ycbcr_out(decode,buf);
181 if(ret>=0){
182 _yuv->y_width=buf[0].width;
183 _yuv->y_height=buf[0].height;
184 _yuv->y_stride=buf[0].stride;
185 _yuv->uv_width=buf[1].width;
186 _yuv->uv_height=buf[1].height;
187 _yuv->uv_stride=buf[1].stride;
188 _yuv->y=buf[0].data;
189 _yuv->u=buf[1].data;
190 _yuv->v=buf[2].data;
191 }
192 return ret;
193 }
194