1 /* enctheora.c
2
3 Copyright (c) 2003-2021 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
9
10 #include "handbrake/handbrake.h"
11 #include "theora/codec.h"
12 #include "theora/theoraenc.h"
13
14 int enctheoraInit( hb_work_object_t *, hb_job_t * );
15 int enctheoraWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
16 void enctheoraClose( hb_work_object_t * );
17
18 hb_work_object_t hb_enctheora =
19 {
20 WORK_ENCTHEORA,
21 "Theora encoder (libtheora)",
22 enctheoraInit,
23 enctheoraWork,
24 enctheoraClose
25 };
26
27 struct hb_work_private_s
28 {
29 hb_job_t * job;
30
31 th_enc_ctx * ctx;
32
33 FILE * file;
34 unsigned char stat_buf[80];
35 int stat_read;
36 int stat_fill;
37 };
38
enctheoraInit(hb_work_object_t * w,hb_job_t * job)39 int enctheoraInit( hb_work_object_t * w, hb_job_t * job )
40 {
41 int keyframe_frequency, log_keyframe, ret;
42 hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
43 w->private_data = pv;
44
45 pv->job = job;
46
47 if( job->pass_id == HB_PASS_ENCODE_1ST ||
48 job->pass_id == HB_PASS_ENCODE_2ND )
49 {
50 char * filename;
51 filename = hb_get_temporary_filename("theora.log");
52 if ( job->pass_id == HB_PASS_ENCODE_1ST )
53 {
54 pv->file = hb_fopen(filename, "wb");
55 }
56 else
57 {
58 pv->file = hb_fopen(filename, "rb");
59 }
60 free(filename);
61 }
62
63 th_info ti;
64 th_comment tc;
65 ogg_packet op;
66 th_info_init( &ti );
67
68 /* Frame width and height need to be multiples of 16 */
69 ti.pic_width = job->width;
70 ti.pic_height = job->height;
71 ti.frame_width = (job->width + 0xf) & ~0xf;
72 ti.frame_height = (job->height + 0xf) & ~0xf;
73 ti.pic_x = ti.pic_y = 0;
74 ti.fps_numerator = job->vrate.num;
75 ti.fps_denominator = job->vrate.den;
76 ti.aspect_numerator = job->par.num;
77 ti.aspect_denominator = job->par.den;
78 ti.colorspace = TH_CS_UNSPECIFIED;
79 ti.pixel_fmt = TH_PF_420;
80 if (job->vquality <= HB_INVALID_VIDEO_QUALITY)
81 {
82 ti.target_bitrate = job->vbitrate * 1000;
83 ti.quality = 0;
84 }
85 else
86 {
87 ti.target_bitrate = 0;
88 ti.quality = job->vquality;
89 }
90
91 keyframe_frequency = ((double)job->orig_vrate.num / job->orig_vrate.den +
92 0.5) * 10;
93
94 hb_log("theora: keyint: %i", keyframe_frequency);
95
96 int tmp = keyframe_frequency - 1;
97 for (log_keyframe = 0; tmp; log_keyframe++)
98 tmp >>= 1;
99
100 ti.keyframe_granule_shift = log_keyframe;
101
102 pv->ctx = th_encode_alloc( &ti );
103 th_info_clear( &ti );
104
105 ret = th_encode_ctl(pv->ctx, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
106 &keyframe_frequency, sizeof(keyframe_frequency));
107 if( ret < 0 )
108 {
109 hb_log("theora: Could not set keyframe interval to %d", keyframe_frequency);
110 }
111
112 /* Set "soft target" rate control which improves quality at the
113 * expense of solid bitrate caps */
114 int arg = TH_RATECTL_CAP_UNDERFLOW;
115 ret = th_encode_ctl(pv->ctx, TH_ENCCTL_SET_RATE_FLAGS, &arg, sizeof(arg));
116 if( ret < 0 )
117 {
118 hb_log("theora: Could not set soft ratecontrol");
119 }
120 if( job->pass_id == HB_PASS_ENCODE_1ST ||
121 job->pass_id == HB_PASS_ENCODE_2ND )
122 {
123 arg = keyframe_frequency * 7 >> 1;
124 ret = th_encode_ctl(pv->ctx, TH_ENCCTL_SET_RATE_BUFFER, &arg, sizeof(arg));
125 if( ret < 0 )
126 {
127 hb_log("theora: Could not set rate control buffer");
128 }
129 }
130
131 if( job->pass_id == HB_PASS_ENCODE_1ST )
132 {
133 unsigned char *buffer;
134 int bytes;
135 bytes = th_encode_ctl(pv->ctx, TH_ENCCTL_2PASS_OUT, &buffer, sizeof(buffer));
136 if( bytes < 0 )
137 {
138 hb_error("Could not set up the first pass of two-pass mode.\n");
139 hb_error("Did you remember to specify an estimated bitrate?\n");
140 return 1;
141 }
142 if( fwrite( buffer, 1, bytes, pv->file ) < bytes )
143 {
144 hb_error("Unable to write to two-pass data file.\n");
145 return 1;
146 }
147 fflush( pv->file );
148 }
149 if( job->pass_id == HB_PASS_ENCODE_2ND )
150 {
151 /* Enable the second pass here.
152 * We make this call just to set the encoder into 2-pass mode, because
153 * by default enabling two-pass sets the buffer delay to the whole file
154 * (because there's no way to explicitly request that behavior).
155 * If we waited until we were actually encoding, it would overwrite our
156 * settings.*/
157 hb_log("enctheora: init 2nd pass");
158 if( th_encode_ctl( pv->ctx, TH_ENCCTL_2PASS_IN, NULL, 0) < 0)
159 {
160 hb_log("theora: Could not set up the second pass of two-pass mode.");
161 return 1;
162 }
163 }
164
165 th_comment_init( &tc );
166
167 ogg_packet *header;
168
169 int ii;
170 for (ii = 0; ii < 3; ii++)
171 {
172 th_encode_flushheader( pv->ctx, &tc, &op );
173 header = (ogg_packet*)w->config->theora.headers[ii];
174 memcpy(header, &op, sizeof(op));
175 header->packet = w->config->theora.headers[ii] + sizeof(ogg_packet);
176 memcpy(header->packet, op.packet, op.bytes );
177 }
178
179 th_comment_clear( &tc );
180
181 return 0;
182 }
183
184 /***********************************************************************
185 * Close
186 ***********************************************************************
187 *
188 **********************************************************************/
enctheoraClose(hb_work_object_t * w)189 void enctheoraClose( hb_work_object_t * w )
190 {
191 hb_work_private_t * pv = w->private_data;
192
193 if (pv == NULL)
194 {
195 return;
196 }
197
198 th_encode_free( pv->ctx );
199
200 if( pv->file )
201 {
202 fclose( pv->file );
203 }
204 free( pv );
205 w->private_data = NULL;
206 }
207
208 /***********************************************************************
209 * Work
210 ***********************************************************************
211 *
212 **********************************************************************/
enctheoraWork(hb_work_object_t * w,hb_buffer_t ** buf_in,hb_buffer_t ** buf_out)213 int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
214 hb_buffer_t ** buf_out )
215 {
216 hb_work_private_t * pv = w->private_data;
217 hb_job_t * job = pv->job;
218 hb_buffer_t * in = *buf_in, * buf;
219 th_ycbcr_buffer ycbcr;
220 ogg_packet op;
221
222 int frame_width, frame_height;
223
224 if (in->s.flags & HB_BUF_FLAG_EOF)
225 {
226 // EOF on input - send it downstream & say we're done.
227 // XXX may need to flush packets via a call to
228 // th_encode_packetout( pv->ctx, 1, &op );
229 // but we don't have a timestamp to put on those packets so we
230 // drop them for now.
231 *buf_out = in;
232 *buf_in = NULL;
233 th_encode_packetout( pv->ctx, 1, &op );
234 if( job->pass_id == HB_PASS_ENCODE_1ST )
235 {
236 unsigned char *buffer;
237 int bytes;
238
239 bytes = th_encode_ctl(pv->ctx, TH_ENCCTL_2PASS_OUT,
240 &buffer, sizeof(buffer));
241 if( bytes < 0 )
242 {
243 fprintf(stderr,"Could not read two-pass data from encoder.\n");
244 return HB_WORK_DONE;
245 }
246 fseek( pv->file, 0, SEEK_SET );
247 if( fwrite( buffer, 1, bytes, pv->file ) < bytes)
248 {
249 fprintf(stderr,"Unable to write to two-pass data file.\n");
250 return HB_WORK_DONE;
251 }
252 fflush( pv->file );
253 }
254 return HB_WORK_DONE;
255 }
256
257 if( job->pass_id == HB_PASS_ENCODE_2ND )
258 {
259 for(;;)
260 {
261 int bytes, size, ret;
262 /*Ask the encoder how many bytes it would like.*/
263 bytes = th_encode_ctl( pv->ctx, TH_ENCCTL_2PASS_IN, NULL, 0 );
264 if( bytes < 0 )
265 {
266 hb_error("Error requesting stats size in second pass.");
267 *job->done_error = HB_ERROR_UNKNOWN;
268 *job->die = 1;
269 return HB_WORK_DONE;
270 }
271
272 /*If it's got enough, stop.*/
273 if( bytes == 0 ) break;
274
275 /*Read in some more bytes, if necessary.*/
276 if( bytes > pv->stat_fill - pv->stat_read )
277 size = bytes - (pv->stat_fill - pv->stat_read);
278 else
279 size = 0;
280 if( size > 80 - pv->stat_fill )
281 size = 80 - pv->stat_fill;
282 if( size > 0 &&
283 fread( pv->stat_buf+pv->stat_fill, 1, size, pv->file ) < size )
284 {
285 hb_error("Could not read frame data from two-pass data file!");
286 *job->done_error = HB_ERROR_UNKNOWN;
287 *job->die = 1;
288 return HB_WORK_DONE;
289 }
290 pv->stat_fill += size;
291
292 /*And pass them off.*/
293 if( bytes > pv->stat_fill - pv->stat_read )
294 bytes = pv->stat_fill - pv->stat_read;
295 ret = th_encode_ctl( pv->ctx, TH_ENCCTL_2PASS_IN,
296 pv->stat_buf+pv->stat_read, bytes);
297 if( ret < 0 )
298 {
299 hb_error("Error submitting pass data in second pass.");
300 *job->done_error = HB_ERROR_UNKNOWN;
301 *job->die = 1;
302 return HB_WORK_DONE;
303 }
304 /*If the encoder consumed the whole buffer, reset it.*/
305 if( ret >= pv->stat_fill - pv->stat_read )
306 pv->stat_read = pv->stat_fill = 0;
307 /*Otherwise remember how much it used.*/
308 else
309 pv->stat_read += ret;
310 }
311 }
312 memset(&op, 0, sizeof(op));
313 memset(&ycbcr, 0, sizeof(ycbcr));
314
315 frame_width = (job->width + 0xf) & ~0xf;
316 frame_height = (job->height + 0xf) & ~0xf;
317
318 // Y
319 ycbcr[0].width = frame_width;
320 ycbcr[0].height = frame_height;
321
322 // CbCr decimated by factor of 2 in both width and height
323 ycbcr[1].width = ycbcr[2].width = (frame_width + 1) / 2;
324 ycbcr[1].height = ycbcr[2].height = (frame_height + 1) / 2;
325
326 ycbcr[0].stride = in->plane[0].stride;
327 ycbcr[1].stride = in->plane[1].stride;
328 ycbcr[2].stride = in->plane[2].stride;
329
330 ycbcr[0].data = in->plane[0].data;
331 ycbcr[1].data = in->plane[1].data;
332 ycbcr[2].data = in->plane[2].data;
333
334 th_encode_ycbcr_in( pv->ctx, ycbcr );
335
336 if( job->pass_id == HB_PASS_ENCODE_1ST )
337 {
338 unsigned char *buffer;
339 int bytes;
340
341 bytes = th_encode_ctl(pv->ctx, TH_ENCCTL_2PASS_OUT,
342 &buffer, sizeof(buffer));
343 if( bytes < 0 )
344 {
345 fprintf(stderr,"Could not read two-pass data from encoder.\n");
346 *job->done_error = HB_ERROR_UNKNOWN;
347 *job->die = 1;
348 return HB_WORK_DONE;
349 }
350 if( fwrite( buffer, 1, bytes, pv->file ) < bytes)
351 {
352 fprintf(stderr,"Unable to write to two-pass data file.\n");
353 *job->done_error = HB_ERROR_UNKNOWN;
354 *job->die = 1;
355 return HB_WORK_DONE;
356 }
357 fflush( pv->file );
358 }
359 th_encode_packetout( pv->ctx, 0, &op );
360
361 buf = hb_buffer_init(op.bytes);
362 memcpy(buf->data, op.packet, op.bytes);
363 buf->f.fmt = AV_PIX_FMT_YUV420P;
364 buf->f.width = frame_width;
365 buf->f.height = frame_height;
366 buf->s.flags = HB_FLAG_FRAMETYPE_REF;
367 buf->s.frametype = HB_FRAME_I;
368 if (th_packet_iskeyframe(&op))
369 {
370 buf->s.flags |= HB_FLAG_FRAMETYPE_KEY;
371 }
372 buf->s.start = in->s.start;
373 buf->s.stop = in->s.stop;
374 buf->s.duration = in->s.stop - in->s.start;
375
376 *buf_out = buf;
377
378 return HB_WORK_OK;
379 }
380
381