Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/libtheora/decapiwrapper.c
9903 views
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 *
10
* https://www.xiph.org/ *
11
* *
12
********************************************************************
13
14
function:
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
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
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
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
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
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
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
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
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
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
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
195