Fix encapiwrapper: we need a th_info struct at the start of th_enc_ctx in order
[xiph/unicode.git] / theora / lib / enc / encapiwrapper.c
blob577594d3ca30a12842a271fe2ba84447843537c5
1 #include <string.h>
2 #include "theora/theoraenc.h"
3 #include "theora/theora.h"
4 #include "codec_internal.h"
6 /*Wrapper to translate the new API into the old API.
7 Eventually we need to convert the old functions to support the new API
8 natively and do the translation the other way.
9 theora-exp already the necessary code to do so.*/
11 static void th_info2theora_info(theora_info *_ci,const th_info *_info){
12 _ci->version_major=_info->version_major;
13 _ci->version_minor=_info->version_minor;
14 _ci->version_subminor=_info->version_subminor;
15 _ci->width=_info->frame_width;
16 _ci->height=_info->frame_height;
17 _ci->frame_width=_info->pic_width;
18 _ci->frame_height=_info->pic_height;
19 _ci->offset_x=_info->pic_x;
20 _ci->offset_y=_info->pic_y;
21 _ci->fps_numerator=_info->fps_numerator;
22 _ci->fps_denominator=_info->fps_denominator;
23 _ci->aspect_numerator=_info->aspect_numerator;
24 _ci->aspect_denominator=_info->aspect_denominator;
25 switch(_info->colorspace){
26 case TH_CS_ITU_REC_470M:_ci->colorspace=OC_CS_ITU_REC_470M;break;
27 case TH_CS_ITU_REC_470BG:_ci->colorspace=OC_CS_ITU_REC_470BG;break;
28 default:_ci->colorspace=OC_CS_UNSPECIFIED;break;
30 switch(_info->pixel_fmt){
31 case TH_PF_420:_ci->pixelformat=OC_PF_420;break;
32 case TH_PF_422:_ci->pixelformat=OC_PF_422;break;
33 case TH_PF_444:_ci->pixelformat=OC_PF_444;break;
34 default:_ci->pixelformat=OC_PF_RSVD;
36 _ci->target_bitrate=_info->target_bitrate;
37 _ci->quality=_info->quality;
38 _ci->codec_setup=NULL;
39 /*Defaults from old encoder_example... eventually most of these should go
40 away when we make the encoder no longer use them.*/
41 _ci->dropframes_p=0;
42 _ci->keyframe_auto_p=1;
43 _ci->keyframe_frequency=1<<_info->keyframe_granule_shift;
44 _ci->keyframe_frequency_force=1<<_info->keyframe_granule_shift;
45 _ci->keyframe_data_target_bitrate=
46 _info->target_bitrate+(_info->target_bitrate>>1);
47 _ci->keyframe_auto_threshold=80;
48 _ci->keyframe_mindistance=8;
49 _ci->noise_sensitivity=1;
50 _ci->sharpness=0;
53 typedef struct th_enc_ctx{
54 /*This is required at the start of the struct for the common functions to
55 work.*/
56 th_info info;
57 /*The actual encoder.*/
58 theora_state state;
62 th_enc_ctx *th_encode_alloc(const th_info *_info){
63 theora_info ci;
64 th_enc_ctx *enc;
65 th_info2theora_info(&ci,_info);
66 enc=(th_enc_ctx *)_ogg_malloc(sizeof(*enc));
67 if(theora_encode_init(&enc->state,&ci)<0){
68 _ogg_free(enc);
69 enc=NULL;
71 else memcpy(&enc->info,_info,sizeof(enc->info));
72 return enc;
75 int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){
76 return theora_control(&_enc->state,_req,_buf,_buf_sz);
79 int th_encode_flushheader(th_enc_ctx *_enc,th_comment *_comments,
80 ogg_packet *_op){
81 theora_state *te;
82 CP_INSTANCE *cpi;
83 if(_enc==NULL||_op==NULL)return OC_FAULT;
84 te=&_enc->state;
85 cpi=(CP_INSTANCE *)te->internal_encode;
86 switch(cpi->doneflag){
87 case -3:{
88 theora_encode_header(te,_op);
89 return -cpi->doneflag++;
90 }break;
91 case -2:{
92 if(_comments==NULL)return OC_FAULT;
93 theora_encode_comment((theora_comment *)_comments,_op);
94 /*The old API does not require a theora_state struct when writing the
95 comment header, so it can't use its internal buffer and relies on the
96 application to free it.
97 The old documentation is wrong on this subject, and this breaks on
98 Windows when linking against multiple versions of libc (which is
99 almost always done when, e.g., using DLLs built with mingw32).
100 The new API _does_ require a th_enc_ctx, and states that libtheora owns
101 the memory.
102 Thus we move the contents of this packet into our internal
103 oggpack_buffer so it can be properly reclaimed.*/
104 oggpackB_reset(cpi->oggbuffer);
105 oggpackB_writecopy(cpi->oggbuffer,_op->packet,_op->bytes*8);
106 _ogg_free(_op->packet);
107 _op->packet=oggpackB_get_buffer(cpi->oggbuffer);
108 return -cpi->doneflag++;
109 }break;
110 case -1:{
111 theora_encode_tables(te,_op);
112 return -cpi->doneflag++;
113 }break;
114 case 0:return 0;
115 default:return OC_EINVAL;
119 int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _ycbcr){
120 CP_INSTANCE *cpi;
121 theora_state *te;
122 yuv_buffer yuv;
123 unsigned char *tmpbuf;
124 int ret;
125 if(_enc==NULL||_ycbcr==NULL)return OC_FAULT;
126 te=&_enc->state;
127 /*theora_encode_YUVin() does not bother to check uv_width and uv_height, and
128 then uses them.
129 This is arguably okay (it will most likely lead to a crash if they're
130 wrong, which will make the developer who passed them fix the problem), but
131 our API promises to return an error code instead.*/
132 cpi=(CP_INSTANCE *)te->internal_encode;
133 if(_ycbcr[1].width!=_ycbcr[0].width>>!(cpi->pb.info.pixelformat&1)||
134 _ycbcr[1].height!=_ycbcr[0].height>>!(cpi->pb.info.pixelformat&2)||
135 _ycbcr[2].width!=_ycbcr[1].width||_ycbcr[2].height!=_ycbcr[1].height){
136 return OC_EINVAL;
138 yuv.y_width=_ycbcr[0].width;
139 yuv.y_height=_ycbcr[0].height;
140 yuv.y_stride=_ycbcr[0].stride;
141 yuv.y=_ycbcr[0].data;
142 yuv.uv_width=_ycbcr[1].width;
143 yuv.uv_height=_ycbcr[1].height;
144 if(_ycbcr[1].stride==_ycbcr[2].stride){
145 yuv.uv_stride=_ycbcr[1].stride;
146 yuv.u=_ycbcr[1].data;
147 yuv.v=_ycbcr[2].data;
148 tmpbuf=NULL;
150 else{
151 unsigned char *src;
152 unsigned char *dst;
153 int i;
154 /*There's no way to signal different strides for the u and v components
155 when we pass them to theora_encode_YUVin().
156 Therefore we have to allocate a temporary buffer and copy them.*/
157 tmpbuf=(unsigned char *)_ogg_malloc(
158 (yuv.uv_width*yuv.uv_height<<1)*sizeof(*tmpbuf));
159 dst=tmpbuf;
160 yuv.u=dst;
161 src=_ycbcr[1].data;
162 for(i=0;i<yuv.uv_height;i++){
163 memcpy(dst,src,yuv.uv_width);
164 dst+=yuv.uv_width;
165 src+=_ycbcr[1].stride;
167 yuv.v=dst;
168 src=_ycbcr[2].data;
169 for(i=0;i<yuv.uv_height;i++){
170 memcpy(dst,src,yuv.uv_width);
171 dst+=yuv.uv_width;
172 src+=_ycbcr[2].stride;
174 yuv.uv_stride=yuv.uv_width;
176 ret=theora_encode_YUVin(te,&yuv);
177 _ogg_free(tmpbuf);
178 return ret;
181 int th_encode_packetout(th_enc_ctx *_enc,int _last,ogg_packet *_op){
182 if(_enc==NULL)return OC_FAULT;
183 return theora_encode_packetout(&_enc->state,_last,_op);
186 void th_encode_free(th_enc_ctx *_enc){
187 if(_enc!=NULL){
188 theora_clear(&_enc->state);
189 _ogg_free(_enc);