diff options
author | jstebbins <[email protected]> | 2009-07-21 18:18:48 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2009-07-21 18:18:48 +0000 |
commit | 5113f3f269608590a3613c0e1e40673fbd07c52c (patch) | |
tree | 7f291feeea657715296eec4cbd85043cb0d062bf /libhb | |
parent | 6b246add0e017f3758a9564b5067f99449e26fdc (diff) |
libhb: fix theora encoding of non 16pix aligned dimensions
the theora encoder requires it's "frame_width" and "frame_height" to
be aligned to 16pix.
This also updates to using the new API introduced in theora 1.0.
This is an interim fix. Later we will adjust our video buffers to actually
have 16pix aligned data in them.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2718 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/enctheora.c | 91 |
1 files changed, 47 insertions, 44 deletions
diff --git a/libhb/enctheora.c b/libhb/enctheora.c index 29dfed1b5..0973ab613 100644 --- a/libhb/enctheora.c +++ b/libhb/enctheora.c @@ -3,7 +3,8 @@ It may be used under the terms of the GNU General Public License. */ #include "hb.h" -#include "theora/theora.h" +#include "theora/codec.h" +#include "theora/theoraenc.h" int enctheoraInit( hb_work_object_t *, hb_job_t * ); int enctheoraWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** ); @@ -22,7 +23,7 @@ struct hb_work_private_s { hb_job_t * job; - theora_state theora; + th_enc_ctx * ctx; }; int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) @@ -32,14 +33,18 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) pv->job = job; - theora_info ti; - theora_comment tc; + th_info ti; + th_comment tc; ogg_packet op; - theora_info_init( &ti ); + th_info_init( &ti ); + + /* Frame width and height need to be multiples of 16 */ + ti.pic_width = job->width; + ti.pic_height = job->height; + ti.frame_width = (job->width + 0xf) & ~0xf; + ti.frame_height = (job->height + 0xf) & ~0xf; + ti.pic_x = ti.pic_y = 0; - ti.width = ti.frame_width = job->width; - ti.height = ti.frame_height = job->height; - ti.offset_x = ti.offset_y = 0; ti.fps_numerator = job->vrate; ti.fps_denominator = job->vrate_base; if( job->anamorphic.mode ) @@ -51,22 +56,11 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) { ti.aspect_numerator = ti.aspect_denominator = 1; } - ti.colorspace = OC_CS_UNSPECIFIED; - ti.pixelformat = OC_PF_420; - ti.keyframe_auto_p = 1; - ti.keyframe_frequency = (job->vrate / job->vrate_base) + 1; - ti.keyframe_frequency_force = (10 * job->vrate / job->vrate_base) + 1; - /* From encoder_example.c */ - ti.quick_p = 1; - ti.dropframes_p = 0; - ti.keyframe_auto_threshold = 80; - ti.keyframe_mindistance = 8; - ti.noise_sensitivity = 1; - ti.sharpness = 0; + ti.colorspace = TH_CS_UNSPECIFIED; + ti.pixel_fmt = TH_PF_420; if (job->vquality < 0.0) { ti.target_bitrate = job->vbitrate * 1000; - ti.keyframe_data_target_bitrate = job->vbitrate * 1000 * 1.5; ti.quality = 0; } else @@ -83,23 +77,24 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) } } - theora_encode_init( &pv->theora, &ti ); - theora_info_clear( &ti ); + pv->ctx = th_encode_alloc( &ti ); + + th_comment_init( &tc ); - theora_encode_header( &pv->theora, &op ); + th_encode_flushheader( pv->ctx, &tc, &op ); memcpy(w->config->theora.headers[0], &op, sizeof(op)); memcpy(w->config->theora.headers[0] + sizeof(op), op.packet, op.bytes ); - theora_comment_init(&tc); - theora_encode_comment(&tc,&op); + th_encode_flushheader( pv->ctx, &tc, &op ); memcpy(w->config->theora.headers[1], &op, sizeof(op)); memcpy(w->config->theora.headers[1] + sizeof(op), op.packet, op.bytes ); - free(op.packet); - theora_encode_tables(&pv->theora, &op); + th_encode_flushheader( pv->ctx, &tc, &op ); memcpy(w->config->theora.headers[2], &op, sizeof(op)); memcpy(w->config->theora.headers[2] + sizeof(op), op.packet, op.bytes ); + th_comment_clear( &tc ); + return 0; } @@ -111,7 +106,8 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) void enctheoraClose( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; - /* TODO: Free alloc'd */ + + th_encode_free( pv->ctx ); free( pv ); w->private_data = NULL; @@ -128,14 +124,16 @@ int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_work_private_t * pv = w->private_data; hb_job_t * job = pv->job; hb_buffer_t * in = *buf_in, * buf; - yuv_buffer yuv; + th_ycbcr_buffer ycbcr; ogg_packet op; + int frame_width, frame_height; + if ( in->size <= 0 ) { // EOF on input - send it downstream & say we're done. // XXX may need to flush packets via a call to - // theora_encode_packetout(&pv->theora, 1, &op); + // th_encode_packetout( pv->ctx, 1, &op ); // but we don't have a timestamp to put on those packets so we // drop them for now. *buf_out = in; @@ -144,28 +142,33 @@ int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in, } memset(&op, 0, sizeof(op)); - memset(&yuv, 0, sizeof(yuv)); + memset(&ycbcr, 0, sizeof(ycbcr)); + + frame_width = (job->width + 0xf) & ~0xf; + frame_height = (job->height + 0xf) & ~0xf; - yuv.y_width = job->width; - yuv.y_height = job->height; - yuv.y_stride = job->width; + // Y + ycbcr[0].width = frame_width; + ycbcr[0].height = frame_height; + ycbcr[0].stride = job->width; - yuv.uv_width = (job->width + 1) / 2; - yuv.uv_height = (job->height + 1) / 2; - yuv.uv_stride = yuv.uv_width; + // CbCr decimated by factor of 2 in both width and height + ycbcr[1].width = ycbcr[2].width = (frame_width + 1) / 2; + ycbcr[1].height = ycbcr[2].height = (frame_height + 1) / 2; + ycbcr[1].stride = ycbcr[2].stride = (job->width + 1) / 2; - yuv.y = in->data; - yuv.u = in->data + job->width * job->height; - yuv.v = in->data + ( job->width * job->height ) + ( yuv.uv_width * yuv.uv_height ); + ycbcr[0].data = in->data; + ycbcr[1].data = ycbcr[0].data + (ycbcr[0].stride * job->height); + ycbcr[2].data = ycbcr[1].data + (ycbcr[1].stride * ((job->height+1)/2)); - theora_encode_YUVin(&pv->theora, &yuv); + th_encode_ycbcr_in( pv->ctx, &ycbcr ); - theora_encode_packetout(&pv->theora, 0, &op); + th_encode_packetout( pv->ctx, 0, &op ); buf = hb_buffer_init( op.bytes + sizeof(op) ); memcpy(buf->data, &op, sizeof(op)); memcpy(buf->data + sizeof(op), op.packet, op.bytes); - buf->frametype = ( theora_packet_iskeyframe(&op) ) ? HB_FRAME_KEY : HB_FRAME_REF; + buf->frametype = ( th_packet_iskeyframe(&op) ) ? HB_FRAME_KEY : HB_FRAME_REF; buf->start = in->start; buf->stop = in->stop; |