All pastes #833946 Raw Edit

hbtheora-01

public diff v1 · immutable
#833946 ·published 2007-12-27 19:57 UTC
rendered paste body
Index: 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; };