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
->keyframe_frequency_force
=1<<_info
->keyframe_granule_shift
;
41 th_enc_ctx
*th_encode_alloc(const th_info
*_info
){
44 th_info2theora_info(&ci
,_info
);
45 te
=(theora_state
*)_ogg_malloc(sizeof(*te
));
46 if(theora_encode_init(te
,&ci
)<0){
50 return (th_enc_ctx
*)te
;
53 int th_encode_ctl(th_enc_ctx
*_enc
,int _req
,void *_buf
,size_t _buf_sz
){
54 return theora_control((theora_state
*)_enc
,_req
,_buf
,_buf_sz
);
57 int th_encode_flushheader(th_enc_ctx
*_enc
,th_comment
*_comments
,
61 if(_enc
==NULL
||_op
==NULL
)return OC_FAULT
;
62 te
=(theora_state
*)_enc
;
63 cpi
=(CP_INSTANCE
*)te
->internal_encode
;
64 switch(cpi
->doneflag
){
66 theora_encode_header(te
,_op
);
67 return -cpi
->doneflag
++;
70 if(_comments
==NULL
)return OC_FAULT
;
71 theora_encode_comment((theora_comment
*)_comments
,_op
);
73 /*The old API does not require a theora_state struct when writing the
74 comment header, so it can't use its internal buffer and relies on the
75 application to free it when using libogg 1.
76 The old documentation is wrong on this subject, and this breaks on
77 Windows when linking against multiple versions of libc (which is
78 almost always done when, e.g., using DLLs built with mingw32).
79 The new API _does_ require a th_enc_ctx, and states that libtheora owns
81 Thus we move the contents of this packet into our internal
82 oggpack_buffer so it can be properly reclaimed.*/
83 oggpackB_reset(cpi
->oggbuffer
);
84 oggpackB_writecopy(cpi
->oggbuffer
,_op
->packet
,_op
->bytes
*8);
85 _ogg_free(_op
->packet
);
86 _op
->packet
=oggpackB_get_buffer(cpi
->oggbuffer
);
88 return -cpi
->doneflag
++;
91 theora_encode_tables(te
,_op
);
92 return -cpi
->doneflag
++;
95 default:return OC_EINVAL
;
99 int th_encode_ycbcr_in(th_enc_ctx
*_enc
,th_ycbcr_buffer _ycbcr
){
103 unsigned char *tmpbuf
;
105 if(_enc
==NULL
||_ycbcr
==NULL
)return OC_FAULT
;
106 te
=(theora_state
*)_enc
;
107 /*theora_encode_YUVin() does not bother to check uv_width and uv_height, and
109 This is arguably okay (it will most likely lead to a crash if they're
110 wrong, which will make the developer who passed them fix the problem), but
111 our API promises to return an error code instead.*/
112 cpi
=(CP_INSTANCE
*)te
->internal_encode
;
113 if(_ycbcr
[1].width
!=_ycbcr
[0].width
>>!(cpi
->pb
.info
.pixelformat
&1)||
114 _ycbcr
[1].height
!=_ycbcr
[0].height
>>!(cpi
->pb
.info
.pixelformat
&2)||
115 _ycbcr
[2].width
!=_ycbcr
[1].width
||_ycbcr
[2].height
!=_ycbcr
[1].height
){
118 yuv
.y_width
=_ycbcr
[0].width
;
119 yuv
.y_height
=_ycbcr
[0].height
;
120 yuv
.y_stride
=_ycbcr
[0].ystride
;
121 yuv
.y
=_ycbcr
[0].data
;
122 yuv
.uv_width
=_ycbcr
[1].width
;
123 yuv
.uv_height
=_ycbcr
[1].height
;
124 if(_ycbcr
[1].ystride
==_ycbcr
[2].ystride
){
125 yuv
.uv_stride
=_ycbcr
[1].ystride
;
126 yuv
.u
=_ycbcr
[1].data
;
127 yuv
.v
=_ycbcr
[2].data
;
134 /*There's no way to signal different strides for the u and v components
135 when we pass them to theora_encode_YUVin().
136 Therefore we have to allocate a temporary buffer and copy them.*/
137 tmpbuf
=(unsigned char *)_ogg_malloc(
138 (yuv
.uv_width
*yuv
.uv_height
<<1)*sizeof(*tmpbuf
));
142 for(i
=0;i
<yuv
.uv_height
;i
++){
143 memcpy(dst
,src
,yuv
.uv_width
);
145 src
+=_ycbcr
[1].ystride
;
149 for(i
=0;i
<yuv
.uv_height
;i
++){
150 memcpy(dst
,src
,yuv
.uv_width
);
152 src
+=_ycbcr
[2].ystride
;
154 yuv
.uv_stride
=yuv
.uv_width
;
156 ret
=theora_encode_YUVin(te
,&yuv
);
161 int th_encode_packetout(th_enc_ctx
*_enc
,int _last
,ogg_packet
*_op
){
162 if(_enc
==NULL
)return OC_FAULT
;
163 return theora_encode_packetout((theora_state
*)_enc
,_last
,_op
);
166 void th_encode_free(th_enc_ctx
*_enc
){
168 theora_clear((theora_state
*)_enc
);