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: 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 :
25 0 : static void th_dec_api_clear(th_api_wrapper *_api){
26 0 : if(_api->setup)th_setup_free(_api->setup);
27 0 : if(_api->decode)th_decode_free(_api->decode);
28 0 : memset(_api,0,sizeof(*_api));
29 0 : }
30 :
31 0 : static void theora_decode_clear(theora_state *_td){
32 0 : if(_td->i!=NULL)theora_info_clear(_td->i);
33 0 : memset(_td,0,sizeof(*_td));
34 0 : }
35 :
36 0 : static int theora_decode_control(theora_state *_td,int _req,
37 : void *_buf,size_t _buf_sz){
38 0 : return th_decode_ctl(((th_api_wrapper *)_td->i->codec_setup)->decode,
39 : _req,_buf,_buf_sz);
40 : }
41 :
42 0 : static ogg_int64_t theora_decode_granule_frame(theora_state *_td,
43 : ogg_int64_t _gp){
44 0 : return th_granule_frame(((th_api_wrapper *)_td->i->codec_setup)->decode,_gp);
45 : }
46 :
47 0 : static double theora_decode_granule_time(theora_state *_td,ogg_int64_t _gp){
48 0 : 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 :
58 0 : static void th_info2theora_info(theora_info *_ci,const th_info *_info){
59 0 : _ci->version_major=_info->version_major;
60 0 : _ci->version_minor=_info->version_minor;
61 0 : _ci->version_subminor=_info->version_subminor;
62 0 : _ci->width=_info->frame_width;
63 0 : _ci->height=_info->frame_height;
64 0 : _ci->frame_width=_info->pic_width;
65 0 : _ci->frame_height=_info->pic_height;
66 0 : _ci->offset_x=_info->pic_x;
67 0 : _ci->offset_y=_info->pic_y;
68 0 : _ci->fps_numerator=_info->fps_numerator;
69 0 : _ci->fps_denominator=_info->fps_denominator;
70 0 : _ci->aspect_numerator=_info->aspect_numerator;
71 0 : _ci->aspect_denominator=_info->aspect_denominator;
72 0 : switch(_info->colorspace){
73 0 : case TH_CS_ITU_REC_470M:_ci->colorspace=OC_CS_ITU_REC_470M;break;
74 0 : case TH_CS_ITU_REC_470BG:_ci->colorspace=OC_CS_ITU_REC_470BG;break;
75 0 : default:_ci->colorspace=OC_CS_UNSPECIFIED;break;
76 : }
77 0 : switch(_info->pixel_fmt){
78 0 : case TH_PF_420:_ci->pixelformat=OC_PF_420;break;
79 0 : case TH_PF_422:_ci->pixelformat=OC_PF_422;break;
80 0 : case TH_PF_444:_ci->pixelformat=OC_PF_444;break;
81 0 : default:_ci->pixelformat=OC_PF_RSVD;
82 : }
83 0 : _ci->target_bitrate=_info->target_bitrate;
84 0 : _ci->quality=_info->quality;
85 0 : _ci->keyframe_frequency_force=1<<_info->keyframe_granule_shift;
86 0 : }
87 :
88 0 : 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 0 : 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 0 : apiinfo=(th_api_info *)_ogg_calloc(1,sizeof(*apiinfo));
99 0 : 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 0 : *&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 0 : 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 0 : apiinfo->api.decode=th_decode_alloc(&info,api->setup);
112 0 : if(apiinfo->api.decode==NULL){
113 0 : _ogg_free(apiinfo);
114 0 : return OC_EINVAL;
115 : }
116 0 : apiinfo->api.clear=(oc_setup_clear_func)th_dec_api_clear;
117 0 : _td->internal_encode=NULL;
118 : /*Provide entry points for ABI compatibility with old decoder shared libs.*/
119 0 : _td->internal_decode=(void *)&OC_DEC_DISPATCH_VTBL;
120 0 : _td->granulepos=0;
121 0 : _td->i=&apiinfo->info;
122 0 : _td->i->codec_setup=&apiinfo->api;
123 0 : return 0;
124 : }
125 :
126 0 : 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 0 : 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 0 : if(api==NULL){
134 0 : _ci->codec_setup=_ogg_calloc(1,sizeof(*api));
135 0 : if(_ci->codec_setup==NULL)return OC_FAULT;
136 0 : api=(th_api_wrapper *)_ci->codec_setup;
137 0 : 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 0 : 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 0 : 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 0 : if(ret<0)return ret;
155 0 : th_info2theora_info(_ci,&info);
156 0 : return 0;
157 : }
158 :
159 0 : int theora_decode_packetin(theora_state *_td,ogg_packet *_op){
160 : th_api_wrapper *api;
161 : ogg_int64_t gp;
162 : int ret;
163 0 : if(!_td||!_td->i||!_td->i->codec_setup)return OC_FAULT;
164 0 : api=(th_api_wrapper *)_td->i->codec_setup;
165 0 : ret=th_decode_packetin(api->decode,_op,&gp);
166 0 : if(ret<0)return OC_BADPACKET;
167 0 : _td->granulepos=gp;
168 0 : return 0;
169 : }
170 :
171 0 : 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 0 : if(!_td||!_td->i||!_td->i->codec_setup)return OC_FAULT;
177 0 : api=(th_api_wrapper *)_td->i->codec_setup;
178 0 : decode=(th_dec_ctx *)api->decode;
179 0 : if(!decode)return OC_FAULT;
180 0 : ret=th_decode_ycbcr_out(decode,buf);
181 0 : if(ret>=0){
182 0 : _yuv->y_width=buf[0].width;
183 0 : _yuv->y_height=buf[0].height;
184 0 : _yuv->y_stride=buf[0].stride;
185 0 : _yuv->uv_width=buf[1].width;
186 0 : _yuv->uv_height=buf[1].height;
187 0 : _yuv->uv_stride=buf[1].stride;
188 0 : _yuv->y=buf[0].data;
189 0 : _yuv->u=buf[1].data;
190 0 : _yuv->v=buf[2].data;
191 : }
192 0 : return ret;
193 : }
|