X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=libhb%2Fenctheora.c;h=4206a2f70c9a75b47e1f2ebb7b111286c64cd172;hb=ed5a81836cbf7880f751d04a00558cd35a401600;hp=59414687c2c650496fc0a331ee3939a87bf9645a;hpb=2707a4c05f84b3846e4e77ca4e9850cc61ffca10;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/libhb/enctheora.c b/libhb/enctheora.c index 59414687..4206a2f7 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,66 +33,68 @@ 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->pixel_ratio) + if( job->anamorphic.mode ) { - ti.aspect_numerator = job->pixel_aspect_width; - ti.aspect_denominator = job->pixel_aspect_height; + ti.aspect_numerator = job->anamorphic.par_width; + ti.aspect_denominator = job->anamorphic.par_height; } else { 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; - if (job->vquality < 0.0 || job->vquality > 1.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 { ti.target_bitrate = 0; - ti.quality = 63 * job->vquality; + + if( job->vquality > 0 && job->vquality < 1 ) + { + ti.quality = 63 * job->vquality; + } + else + { + ti.quality = job->vquality; + } } - 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; } @@ -103,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; @@ -120,46 +124,51 @@ 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; - static int last_p = 0; - memset(&op, 0, sizeof(op)); - memset(&yuv, 0, sizeof(yuv)); + int frame_width, frame_height; - /* If this is the last empty frame, we're done */ - if(!in->data) + if ( in->size <= 0 ) { - if (!last_p) - { - last_p++; - goto finish; - } - *buf_out = NULL; + // EOF on input - send it downstream & say we're done. + // XXX may need to flush packets via a call to + // 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; + *buf_in = NULL; return HB_WORK_DONE; } - yuv.y_width = job->width; - yuv.y_height = job->height; - yuv.y_stride = job->width; + memset(&op, 0, sizeof(op)); + memset(&ycbcr, 0, sizeof(ycbcr)); + + frame_width = (job->width + 0xf) & ~0xf; + frame_height = (job->height + 0xf) & ~0xf; + + // Y + ycbcr[0].width = frame_width; + ycbcr[0].height = frame_height; + ycbcr[0].stride = job->width; - yuv.uv_width = job->width / 2; - yuv.uv_height = job->height / 2; - yuv.uv_stride = job->width / 2; + // 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 * 5/4; + 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 ); -finish: - theora_encode_packetout(&pv->theora, last_p, &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;