rendered paste bodyIndex: libhb/Makefile===================================================================--- libhb/Makefile (revision 1147)+++ libhb/Makefile (working copy)@@ -24,7 +24,8 @@ SRCS = common.c hb.c ports.c scan.c work.c decmpeg2.c encavcodec.c \ update.c demuxmpeg.c fifo.c render.c reader.c muxcommon.c stream.c \ muxmp4.c sync.c decsub.c deca52.c decdca.c encfaac.c declpcm.c encx264.c \- decavcodec.c encxvid.c muxmkv.c muxavi.c enclame.c muxogm.c encvorbis.c \+ decavcodec.c encxvid.c muxmkv.c muxavi.c enclame.c muxogm.c \+ encvorbis.c enctheora.c \ dvd.c ipodutil.cpp deblock.c deinterlace.c denoise.c detelecine.c lang.c OTMP = $(SRCS:%.c=%.o) OBJS = $(OTMP:%.cpp=%.o)@@ -37,6 +38,7 @@ ../contrib/lib/libmpeg2.a ../contrib/lib/libmpeg2convert.a \ ../contrib/lib/libvorbis.a ../contrib/lib/libvorbisenc.a \ ../contrib/lib/libvorbisfile.a ../contrib/lib/libogg.a \+ ../contrib/lib/libtheora.a \ ../contrib/lib/libsamplerate.a ../contrib/lib/libx264.a \ ../contrib/lib/libxvidcore.a ../contrib/lib/libmp4v2.a \ ../contrib/lib/libmkv.a ../contrib/lib/libswscale.a@@ -48,6 +50,7 @@ ../contrib/lib/libmp3lame.a ../contrib/lib/libmpeg2.a \ ../contrib/lib/libmpeg2convert.a ../contrib/lib/libvorbis.a \ ../contrib/lib/libvorbisenc.a ../contrib/lib/libvorbisfile.a \+ ../contrib/lib/libtheora.a \ ../contrib/lib/libogg.a ../contrib/lib/libsamplerate.a \ ../contrib/lib/libx264.a ../contrib/lib/libxvidcore.a \ ../contrib/lib/libmp4v2.a ../contrib/lib/libmkv.a \Index: libhb/hb.h===================================================================--- libhb/hb.h (revision 1147)+++ libhb/hb.h (working copy)@@ -32,6 +32,7 @@ hb_register( &hb_encfaac ); \ hb_register( &hb_enclame ); \ hb_register( &hb_encvorbis ); \+hb_register( &hb_enctheora ); \ #define hb_init_express(v,u) \ hb_init_real( v, u ); \Index: libhb/enctheora.c===================================================================--- libhb/enctheora.c (revision 0)+++ libhb/enctheora.c (revision 0)@@ -0,0 +1,329 @@+/* $Id: $++ This file is part of the HandBrake source code.+ Homepage: <http://handbrake.m0k.org/>.+ It may be used under the terms of the GNU General Public License. */++#include <stdarg.h>++#include "hb.h"++#include "theora/theora.h"++int enctheoraInit( hb_work_object_t *, hb_job_t * );+int enctheoraWork( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );+void enctheoraClose( hb_work_object_t * );++hb_work_object_t hb_enctheora =+{+ WORK_ENCTHEORA,+ "Theora encoder (libtheora)",+ enctheoraInit,+ enctheoraWork,+ enctheoraClose+};++struct hb_work_private_s+{+ hb_job_t * job;+ theora_state te;+ ogg_packet header[3];+ yuv_buffer yuv;+ ogg_packet op;+};++/***********************************************************************+ * hb_work_enctheora_init+ ***********************************************************************+ *+ **********************************************************************/+int enctheoraInit( hb_work_object_t * w, hb_job_t * job )+{+ theora_info ti;+ theora_comment tc;+ + hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );+ w->private_data = pv;++ pv->job = job;++ theora_info_init(&ti);+ ti.width = job->width;+ ti.height = job->height;+ + /* job frames should always be a multiple of 16 */+ if ( job->width & 4 )+ {+ hb_log( "enctheora: WARNING: frame width %d is not a multiple of 16!", job->width);+ }+ ti.frame_width = job->width;+ ti.offset_x = 0;+ if ( job->height & 4 )+ {+ hb_log( "enctheora: WARNING: frame height %d is not a multiple of 16!", job->height);+ }+ ti.frame_height = job->height;+ ti.offset_y = 0;+ + ti.fps_numerator = job->vrate;+ ti.fps_denominator = job->vrate_base;+ + if( job->pixel_ratio )+ {+ ti.aspect_numerator = job->pixel_aspect_width;+ ti.aspect_denominator = job->pixel_aspect_height;++ hb_log( "enctheora: encoding with pixel aspect ratio %d:%d",+ ti.aspect_numerator, ti.aspect_denominator );+ }+ else+ {+ ti.aspect_numerator = 0;+ ti.aspect_denominator = 0;+ + hb_log( "enctheora: encoding with an unknown aspect ratio (displayed as 1:1)" );+ }+ + /* todo: this should be guessable for DVD from the input resolution */+ ti.colorspace = OC_CS_UNSPECIFIED;+ ti.pixelformat = OC_PF_420;++ if( job->vquality >= 0.0 && job->vquality <= 1.0 )+ {+ /* quality rate-control target */+ ti.quality = 63.0 * job->vquality;+ ti.target_bitrate = 0;+ }+ else+ {+ /* bitrate rate-control target */+ ti.quality = 0;+ ti.target_bitrate = job->vbitrate;+ }+ + hb_log( "enctheora: opening libtheora" );+ theora_encode_init( &(pv->te), &ti );+ theora_info_clear( &ti );++ /* first header packet (parameters) */+ theora_encode_header( &pv->te, &pv->header[0] );+ + /* second header packet (metadata) */+ theora_comment_init( &tc );+ theora_comment_add_tag( &tc, "Encoder", "HandBreak" );+ theora_encode_comment( &tc, &(pv->header[1]) );+ theora_comment_clear( &tc );+ + /* third header packet (tables) */+ theora_encode_tables( &(pv->te), &(pv->header[2]) );+ + return 0;+}++void enctheoraClose( hb_work_object_t * w )+{+ hb_work_private_t * pv = w->private_data;+ + theora_clear( &(pv->te) );+ ogg_packet_clear( &(pv->header[2]) );+ ogg_packet_clear( &(pv->header[1]) );+ ogg_packet_clear( &(pv->header[0]) );+ ogg_packet_clear( &(pv->op) );++ free( pv );+ w->private_data = NULL;+}++int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,+ hb_buffer_t ** buf_out )+{+ hb_work_private_t * pv = w->private_data;+ hb_job_t * job = pv->job;+ hb_buffer_t * in = *buf_in, * buf;++#if 0+ if( in->data )+ {+ /* XXX avoid this memcpy ? */+ memcpy( pv->pic_in.img.plane[0], in->data, job->width * job->height );+ if( job->grayscale )+ {+ /* XXX x264 has currently no option for grayscale encoding */+ memset( pv->pic_in.img.plane[1], 0x80, job->width * job->height / 4 );+ memset( pv->pic_in.img.plane[2], 0x80, job->width * job->height / 4 );+ }+ else+ {+ memcpy( pv->pic_in.img.plane[1], in->data + job->width * job->height,+ job->width * job->height / 4 );+ memcpy( pv->pic_in.img.plane[2], in->data + 5 * job->width *+ job->height / 4, job->width * job->height / 4 );+ }++ if( in->new_chap && job->chapter_markers )+ {+ /* chapters have to start with an IDR frame so request that this+ frame be coded as IDR. Since there may be up to 16 frames+ currently buffered in the encoder remember the timestamp so+ when this frame finally pops out of the encoder we'll mark+ its buffer as the start of a chapter. */+ pv->pic_in.i_type = X264_TYPE_IDR;+ if( pv->next_chap == 0 )+ {+ pv->next_chap = in->start;+ }+ /* don't let 'work_loop' put a chapter mark on the wrong buffer */+ in->new_chap = 0;+ }+ else+ {+ pv->pic_in.i_type = X264_TYPE_AUTO;+ }+ pv->pic_in.i_qpplus1 = 0;++ // Remember current PTS value, use as DTS later+ pv->dts_start[pv->dts_write_index & (MAX_INFLIGHT_FRAMES-1)] = in->start;+ pv->dts_stop[pv->dts_write_index & (MAX_INFLIGHT_FRAMES-1)] = in->stop;+ pv->dts_write_index++;++ /* Feed the input DTS to x264 so it can figure out proper output PTS */+ pv->pic_in.i_pts = in->start;++ x264_encoder_encode( pv->x264, &nal, &i_nal,+ &pv->pic_in, &pic_out ); + }+ else+ {+ x264_encoder_encode( pv->x264, &nal, &i_nal,+ NULL, &pic_out );+ /* No more delayed B frames */+ if( i_nal == 0 )+ {+ *buf_out = NULL;+ return HB_WORK_DONE;+ }+ else+ {+ /* Since we output at least one more frame, drop another empty+ one onto our input fifo. We'll keep doing this automatically+ until we stop getting frames out of the encoder. */+ hb_fifo_push(w->fifo_in, hb_buffer_init(0));+ }+ }++ if( i_nal )+ {+ /* Should be way too large */+ buf = hb_buffer_init( 3 * job->width * job->height / 2 );+ buf->size = 0;+ buf->start = in->start;+ buf->stop = in->stop;+ buf->frametype = 0;++ int64_t dts_start, dts_stop;++ /* Get next DTS value to use */+ dts_start = pv->dts_start[pv->dts_read_index & (MAX_INFLIGHT_FRAMES-1)];+ dts_stop = pv->dts_stop[pv->dts_read_index & (MAX_INFLIGHT_FRAMES-1)];+ pv->dts_read_index++;++ for( i = 0; i < i_nal; i++ )+ {+ int size, data;++ data = buf->alloc - buf->size;+ if( ( size = x264_nal_encode( buf->data + buf->size, &data,+ 1, &nal[i] ) ) < 1 )+ {+ continue;+ }++ if( job->mux & HB_MUX_AVI )+ {+ if( nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )+ {+ buf->frametype = HB_FRAME_KEY;+ }+ buf->size += size;+ continue;+ }++ /* H.264 in .mp4 */+ switch( buf->data[buf->size+4] & 0x1f )+ {+ case 0x7:+ case 0x8:+ /* SPS, PPS */+ break;++ default:+ /* H.264 in mp4 (stolen from mp4creator) */+ buf->data[buf->size+0] = ( ( size - 4 ) >> 24 ) & 0xFF;+ buf->data[buf->size+1] = ( ( size - 4 ) >> 16 ) & 0xFF;+ buf->data[buf->size+2] = ( ( size - 4 ) >> 8 ) & 0xFF;+ buf->data[buf->size+3] = ( ( size - 4 ) >> 0 ) & 0xFF;+ switch( pic_out.i_type )+ {+ /* Decide what type of frame we have. */+ case X264_TYPE_IDR:+ buf->frametype = HB_FRAME_IDR;+ /* if we have a chapter marker pending and this+ frame's presentation time stamp is at or after+ the marker's time stamp, use this as the+ chapter start. */+ if( pv->next_chap != 0 && pv->next_chap <= pic_out.i_pts )+ {+ pv->next_chap = 0;+ buf->new_chap = 1;+ }+ break;+ case X264_TYPE_I:+ buf->frametype = HB_FRAME_I;+ break;+ case X264_TYPE_P:+ buf->frametype = HB_FRAME_P;+ break;+ case X264_TYPE_B:+ buf->frametype = HB_FRAME_B;+ break;+ /* This is for b-pyramid, which has reference b-frames+ However, it doesn't seem to ever be used... */+ case X264_TYPE_BREF:+ buf->frametype = HB_FRAME_BREF;+ break;+ /* If it isn't the above, what type of frame is it?? */+ default:+ buf->frametype = 0;+ }+++ /* Store the output presentation time stamp+ from x264 for use by muxmp4 in off-setting+ b-frames with the CTTS atom.+ For now, just add 1000000 to the offset so that the+ value is pretty much guaranteed to be positive. The+ muxing code will minimize the renderOffset at the end. */++ buf->renderOffset = pic_out.i_pts - dts_start + 1000000;++ /* Send out the next dts values */+ buf->start = dts_start;+ buf->stop = dts_stop;++ buf->size += size;+ }+ }+ }++ else+ buf = NULL;++ *buf_out = buf;+#endif++ return HB_WORK_OK;+}++++Index: libhb/internal.h===================================================================--- libhb/internal.h (revision 1147)+++ libhb/internal.h (working copy)@@ -202,7 +202,8 @@ WORK_DECLPCM, WORK_ENCFAAC, WORK_ENCLAME,- WORK_ENCVORBIS+ WORK_ENCVORBIS,+ WORK_ENCTHEORA }; enumIndex: libhb/common.h===================================================================--- libhb/common.h (revision 1147)+++ libhb/common.h (working copy)@@ -523,6 +523,7 @@ extern hb_work_object_t hb_encfaac; extern hb_work_object_t hb_enclame; extern hb_work_object_t hb_encvorbis;+extern hb_work_object_t hb_enctheora; #define FILTER_OK 0 #define FILTER_DELAY 1Index: macosx/HandBrake.xcodeproj/project.pbxproj===================================================================--- macosx/HandBrake.xcodeproj/project.pbxproj (revision 1147)+++ macosx/HandBrake.xcodeproj/project.pbxproj (working copy)@@ -204,7 +204,7 @@ /* Begin PBXFileReference section */ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 0D096DFF0B707D1200A845D4 /* libhb.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libhb.dylib; sourceTree = BUILT_PRODUCTS_DIR; };- 0D6E35760B6BD4F0005AABB3 /* HandBrake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HandBrake.app; sourceTree = BUILT_PRODUCTS_DIR; };+ 0D6E35760B6BD4F0005AABB3 /* HandBrake.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = HandBrake.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0DF377970B7BF99A00115CB0 /* fakexcode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fakexcode.cpp; path = ../test/fakexcode.cpp; sourceTree = SOURCE_ROOT; }; 0DFA5C7A0B8DD1E90020BC09 /* HandBrake.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = HandBrake.icns; sourceTree = "<group>"; }; 0DFA5C7E0B8DD3B60020BC09 /* declpcm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = declpcm.c; path = ../libhb/declpcm.c; sourceTree = SOURCE_ROOT; };