1 /* This file is part of the HandBrake source code.
2 Homepage: <http://handbrake.fr/>.
3 It may be used under the terms of the GNU General Public License. */
6 #include "theora/codec.h"
7 #include "theora/theoraenc.h"
9 int enctheoraInit( hb_work_object_t *, hb_job_t * );
10 int enctheoraWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
11 void enctheoraClose( hb_work_object_t * );
13 hb_work_object_t hb_enctheora =
16 "Theora encoder (libtheora)",
22 struct hb_work_private_s
29 int enctheoraInit( hb_work_object_t * w, hb_job_t * job )
31 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
41 /* Frame width and height need to be multiples of 16 */
42 ti.pic_width = job->width;
43 ti.pic_height = job->height;
44 ti.frame_width = (job->width + 0xf) & ~0xf;
45 ti.frame_height = (job->height + 0xf) & ~0xf;
46 ti.pic_x = ti.pic_y = 0;
48 ti.fps_numerator = job->vrate;
49 ti.fps_denominator = job->vrate_base;
50 if( job->anamorphic.mode )
52 ti.aspect_numerator = job->anamorphic.par_width;
53 ti.aspect_denominator = job->anamorphic.par_height;
57 ti.aspect_numerator = ti.aspect_denominator = 1;
59 ti.colorspace = TH_CS_UNSPECIFIED;
60 ti.pixel_fmt = TH_PF_420;
61 if (job->vquality < 0.0)
63 ti.target_bitrate = job->vbitrate * 1000;
68 ti.target_bitrate = 0;
70 if( job->vquality > 0 && job->vquality < 1 )
72 ti.quality = 63 * job->vquality;
76 ti.quality = job->vquality;
80 pv->ctx = th_encode_alloc( &ti );
82 th_comment_init( &tc );
84 th_encode_flushheader( pv->ctx, &tc, &op );
85 memcpy(w->config->theora.headers[0], &op, sizeof(op));
86 memcpy(w->config->theora.headers[0] + sizeof(op), op.packet, op.bytes );
88 th_encode_flushheader( pv->ctx, &tc, &op );
89 memcpy(w->config->theora.headers[1], &op, sizeof(op));
90 memcpy(w->config->theora.headers[1] + sizeof(op), op.packet, op.bytes );
92 th_encode_flushheader( pv->ctx, &tc, &op );
93 memcpy(w->config->theora.headers[2], &op, sizeof(op));
94 memcpy(w->config->theora.headers[2] + sizeof(op), op.packet, op.bytes );
96 th_comment_clear( &tc );
101 /***********************************************************************
103 ***********************************************************************
105 **********************************************************************/
106 void enctheoraClose( hb_work_object_t * w )
108 hb_work_private_t * pv = w->private_data;
110 th_encode_free( pv->ctx );
113 w->private_data = NULL;
116 /***********************************************************************
118 ***********************************************************************
120 **********************************************************************/
121 int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
122 hb_buffer_t ** buf_out )
124 hb_work_private_t * pv = w->private_data;
125 hb_job_t * job = pv->job;
126 hb_buffer_t * in = *buf_in, * buf;
127 th_ycbcr_buffer ycbcr;
130 int frame_width, frame_height;
134 // EOF on input - send it downstream & say we're done.
135 // XXX may need to flush packets via a call to
136 // th_encode_packetout( pv->ctx, 1, &op );
137 // but we don't have a timestamp to put on those packets so we
138 // drop them for now.
144 memset(&op, 0, sizeof(op));
145 memset(&ycbcr, 0, sizeof(ycbcr));
147 frame_width = (job->width + 0xf) & ~0xf;
148 frame_height = (job->height + 0xf) & ~0xf;
151 ycbcr[0].width = frame_width;
152 ycbcr[0].height = frame_height;
153 ycbcr[0].stride = job->width;
155 // CbCr decimated by factor of 2 in both width and height
156 ycbcr[1].width = ycbcr[2].width = (frame_width + 1) / 2;
157 ycbcr[1].height = ycbcr[2].height = (frame_height + 1) / 2;
158 ycbcr[1].stride = ycbcr[2].stride = (job->width + 1) / 2;
160 ycbcr[0].data = in->data;
161 ycbcr[1].data = ycbcr[0].data + (ycbcr[0].stride * job->height);
162 ycbcr[2].data = ycbcr[1].data + (ycbcr[1].stride * ((job->height+1)/2));
164 th_encode_ycbcr_in( pv->ctx, ycbcr );
166 th_encode_packetout( pv->ctx, 0, &op );
168 buf = hb_buffer_init( op.bytes + sizeof(op) );
169 memcpy(buf->data, &op, sizeof(op));
170 memcpy(buf->data + sizeof(op), op.packet, op.bytes);
171 buf->frametype = ( th_packet_iskeyframe(&op) ) ? HB_FRAME_KEY : HB_FRAME_REF;
172 buf->start = in->start;
173 buf->stop = in->stop;