OSDN Git Service

Theora.
authorsaintdev <saintdev@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 20 Mar 2008 02:40:02 +0000 (02:40 +0000)
committersaintdev <saintdev@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Thu, 20 Mar 2008 02:40:02 +0000 (02:40 +0000)
This adds the theora encoder to the Xcode project as well. It does not enable
anything in the Mac GUI, just allows it to build.

git-svn-id: svn://localhost/HandBrake/trunk@1350 b64f7644-9d1e-0410-96f1-a4d463321fa5

15 files changed:
Jamfile
contrib/Jamfile
contrib/version_libtheora.txt [new file with mode: 0644]
libhb/Jamfile
libhb/Makefile
libhb/common.h
libhb/enctheora.c [new file with mode: 0644]
libhb/hb.c
libhb/hb.h
libhb/internal.h
libhb/muxmkv.c
libhb/muxogm.c
libhb/work.c
macosx/HandBrake.xcodeproj/project.pbxproj
test/test.c

diff --git a/Jamfile b/Jamfile
index 6a2c5c5..f463bf2 100644 (file)
--- a/Jamfile
+++ b/Jamfile
@@ -16,7 +16,8 @@ HANDBRAKE_LIBS = libhb.a
           contrib/lib/libvorbis.a     contrib/lib/libvorbisenc.a
           contrib/lib/libogg.a        contrib/lib/libsamplerate.a
           contrib/lib/libx264.a       contrib/lib/libxvidcore.a
-          contrib/lib/libmkv.a        contrib/lib/libswscale.a ;
+          contrib/lib/libmkv.a        contrib/lib/libswscale.a
+          contrib/lib/libtheora.a ;
 
 if $(OS) = UNKNOWN
 {
index 06cb557..8914831 100644 (file)
@@ -336,6 +336,24 @@ actions LibVorbisEnc
 }
 LibVorbisEnc $(SUBDIR)/lib/libvorbisenc.a : $(SUBDIR)/lib/libvorbis.a ;
 
+# libtheora
+rule LibTheora
+{
+    Depends $(<) : $(>) ;
+    Depends lib  : $(<) ;
+}
+actions LibTheora
+{
+    cd `dirname $(>)` && CONTRIB=`pwd` && rm -rf libtheora &&
+    (gzip -dc libtheora.tar.gz | tar xf - ) && cd libtheora &&
+    ./configure --prefix=$CONTRIB --with-ogg=$CONTRIB --with-vorbis=$CONTRIB --cache-file=$CONTRIB/config.cache --disable-shared \
+            --disable-oggtest --disable-vorbistest --disable-sdltest --disable-examples &&
+    $(MAKE) && $(MAKE) install &&
+    $(STRIP) $CONTRIB/lib/libtheora.a
+}
+Wget      $(SUBDIR)/libtheora.tar.gz : $(SUBDIR)/version_libtheora.txt ;
+LibTheora $(SUBDIR)/lib/libtheora.a  : $(SUBDIR)/libtheora.tar.gz ;
+
 # libx264
 rule LibX264
 {
diff --git a/contrib/version_libtheora.txt b/contrib/version_libtheora.txt
new file mode 100644 (file)
index 0000000..30401af
--- /dev/null
@@ -0,0 +1,2 @@
+http://download.m0k.org/handbrake/contrib/libtheora-1.0beta2.tar.gz
+
index bcf4a54..4f20701 100644 (file)
@@ -11,7 +11,7 @@ ipodutil.cpp common.c hb.c ports.c scan.c work.c decmpeg2.c encavcodec.c update.
 demuxmpeg.c fifo.c render.c reader.c muxcommon.c muxmp4.c sync.c stream.c
 decsub.c deca52.c decdca.c encfaac.c declpcm.c encx264.c decavcodec.c encxvid.c
 muxavi.c enclame.c muxogm.c encvorbis.c dvd.c muxmkv.c deblock.c deinterlace.c 
-denoise.c detelecine.c lang.c ;
+denoise.c detelecine.c lang.c enctheora.c ;
 
 Library libhb : $(LIBHB_SRC) ;
 
index 5b19385..fb05e5a 100644 (file)
@@ -21,7 +21,7 @@ ifeq ($(SYSTEM),Linux)
        LDFLAGS += -lpthread -lm -ldl
 endif
 
-SRCS = common.c hb.c ports.c scan.c work.c decmpeg2.c encavcodec.c \
+SRCS = common.c hb.c ports.c scan.c work.c decmpeg2.c encavcodec.c enctheora.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 \
@@ -39,7 +39,8 @@ CONTRIBS = ../contrib/lib/liba52.a ../contrib/lib/libavformat.a \
                   ../contrib/lib/libvorbisfile.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 ../contrib/lib/libswscale.a
+                  ../contrib/lib/libmkv.a ../contrib/lib/libswscale.a \
+                  ../contrib/lib/libtheora.a
 else
 CONTRIBS = ../contrib/lib/liba52.a ../contrib/lib/libavformat.a \
                   ../contrib/lib/libavcodec.a ../contrib/lib/libavutil.a \
@@ -51,7 +52,7 @@ CONTRIBS = ../contrib/lib/liba52.a ../contrib/lib/libavformat.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 \
-                  ../contrib/lib/libswscale.a
+                  ../contrib/lib/libswscale.a ../contrib/lib/libtheora.a
 endif
 
 CFLAGS += -I../contrib/include -D__LIBHB__ -DUSE_PTHREAD -DHB_VERSION=\"$(HB_VERSION)\" -DHB_BUILD=$(HB_BUILD) $(SYSDEF)
index 953c243..aa4cfc0 100644 (file)
@@ -160,6 +160,7 @@ struct hb_job_s
 #define HB_VCODEC_FFMPEG 0x000001
 #define HB_VCODEC_XVID   0x000002
 #define HB_VCODEC_X264   0x000004
+#define HB_VCODEC_THEORA 0x000008
 
     int             vcodec;
     float           vquality;
@@ -526,6 +527,7 @@ extern hb_work_object_t hb_render;
 extern hb_work_object_t hb_encavcodec;
 extern hb_work_object_t hb_encxvid;
 extern hb_work_object_t hb_encx264;
+extern hb_work_object_t hb_enctheora;
 extern hb_work_object_t hb_deca52;
 extern hb_work_object_t hb_decdca;
 extern hb_work_object_t hb_decavcodec;
diff --git a/libhb/enctheora.c b/libhb/enctheora.c
new file mode 100644 (file)
index 0000000..3773b70
--- /dev/null
@@ -0,0 +1,170 @@
+/* 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 "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 theora;
+};
+
+int enctheoraInit( hb_work_object_t * w, hb_job_t * job )
+{
+    hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
+    w->private_data = pv;
+
+    pv->job = job;
+
+    theora_info ti;
+    theora_comment tc;
+    ogg_packet op;
+    theora_info_init( &ti );
+
+    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)
+    {
+        ti.aspect_numerator = job->pixel_aspect_width;
+        ti.aspect_denominator = job->pixel_aspect_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.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;
+    }
+
+    theora_encode_init( &pv->theora, &ti );
+    theora_info_clear( &ti );
+
+    theora_encode_header( &pv->theora, &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);
+    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);
+    memcpy(w->config->theora.headers[2], &op, sizeof(op));
+    memcpy(w->config->theora.headers[2] + sizeof(op), op.packet, op.bytes );
+
+    return 0;
+}
+
+/***********************************************************************
+ * Close
+ ***********************************************************************
+ *
+ **********************************************************************/
+void enctheoraClose( hb_work_object_t * w )
+{
+    hb_work_private_t * pv = w->private_data;
+    /* TODO: Free alloc'd */
+
+    free( pv );
+    w->private_data = NULL;
+}
+
+/***********************************************************************
+ * Work
+ ***********************************************************************
+ *
+ **********************************************************************/
+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;
+    yuv_buffer yuv;
+    ogg_packet op;
+    static int last_p = 0;
+
+    memset(&op, 0, sizeof(op));
+    memset(&yuv, 0, sizeof(yuv));
+
+    /* If this is the last empty frame, we're done */
+    if(!in->data)
+    {
+        if (!last_p)
+        {
+            last_p++;
+            goto finish;
+        }
+       *buf_out        = NULL;
+       return HB_WORK_DONE;
+    }
+
+    yuv.y_width = job->width;
+    yuv.y_height = job->height;
+    yuv.y_stride = job->width;
+
+    yuv.uv_width = job->width / 2;
+    yuv.uv_height = job->height / 2;
+    yuv.uv_stride = job->width / 2;
+
+    yuv.y = in->data;
+    yuv.u = in->data + job->width * job->height;
+    yuv.v = in->data + job->width * job->height * 5/4;
+
+    theora_encode_YUVin(&pv->theora, &yuv);
+
+finish:
+    theora_encode_packetout(&pv->theora, last_p, &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->start = in->start;
+    buf->stop  = in->stop;
+
+    *buf_out = buf;
+
+    return HB_WORK_OK;
+}
+
index fd02d06..62fe9c4 100644 (file)
@@ -216,6 +216,7 @@ hb_handle_t * hb_init_dl( int verbose, int update_check )
        hb_register( &hb_encavcodec );
        hb_register( &hb_encxvid );
        hb_register( &hb_encx264 );
+    hb_register( &hb_enctheora );
        hb_register( &hb_deca52 );
        hb_register( &hb_decdca );
        hb_register( &hb_decavcodec );
index 8324ca5..7454b63 100644 (file)
@@ -25,6 +25,7 @@ hb_register( &hb_render ); \
 hb_register( &hb_encavcodec ); \
 hb_register( &hb_encxvid ); \
 hb_register( &hb_encx264 ); \
+hb_register( &hb_enctheora ); \
 hb_register( &hb_deca52 ); \
 hb_register( &hb_decdca ); \
 hb_register( &hb_decavcodec ); \
index 8dfc3af..a2b4799 100644 (file)
@@ -166,6 +166,11 @@ union hb_esconfig_u
 
     struct
     {
+        uint8_t headers[3][HB_CONFIG_MAX_SIZE];
+    } theora;
+
+    struct
+    {
         uint8_t bytes[HB_CONFIG_MAX_SIZE];
         int     length;
     } aac;
@@ -199,6 +204,7 @@ enum
     WORK_ENCAVCODEC,
     WORK_ENCXVID,
     WORK_ENCX264,
+    WORK_ENCTHEORA,
     WORK_DECA52,
     WORK_DECDCA,
     WORK_DECAVCODEC,
index 58de30f..6ed6a6d 100644 (file)
@@ -106,6 +106,28 @@ static int MKVInit( hb_mux_object_t * m )
             track->codecPrivate = job->config.mpeg4.bytes;
             track->codecPrivateSize = job->config.mpeg4.length;
             break;
+        case HB_VCODEC_THEORA:
+            {
+                int i;
+                uint64_t cp_size = 0;
+                track->codecID = MK_VCODEC_THEORA;
+                uint64_t  header_sizes[3];
+                for (i = 0; i < 3; ++i)
+                {
+                    ogg_headers[i] = (ogg_packet *)job->config.theora.headers[i];
+                    ogg_headers[i]->packet = (unsigned char *)&job->config.theora.headers[i] + sizeof( ogg_packet );
+                    header_sizes[i] = ogg_headers[i]->bytes;
+                }
+                track->codecPrivate = mk_laceXiph(header_sizes, 2, &cp_size);
+                track->codecPrivate = realloc(track->codecPrivate, cp_size + ogg_headers[0]->bytes + ogg_headers[1]->bytes + ogg_headers[2]->bytes);
+                for(i = 0; i < 3; ++i)
+                {
+                    memcpy(track->codecPrivate + cp_size, ogg_headers[i]->packet, ogg_headers[i]->bytes);
+                    cp_size += ogg_headers[i]->bytes;
+                }
+                track->codecPrivateSize = cp_size;
+            }
+            break;
         default:
             *job->die = 1;
             hb_error("muxmkv: Unknown video codec: %x", job->vcodec);
@@ -177,7 +199,7 @@ static int MKVInit( hb_mux_object_t * m )
                 {
                     track->codecPrivate = NULL;
                     track->codecPrivateSize = 0;
-                    track->codecID = MK_ACODEC_AC3; 
+                    track->codecID = MK_ACODEC_AC3;
                 }
                 else
                 {
@@ -224,12 +246,14 @@ static int MKVInit( hb_mux_object_t * m )
 static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
                    hb_buffer_t * buf )
 {
+    ogg_packet  *op = NULL;
     hb_job_t * job = m->job;
     hb_title_t * title = job->title;
     uint64_t   timecode = 0;
     hb_chapter_t *chapter_data;
     char tmp_buffer[1024];
     char *string = tmp_buffer;
+
     if (mux_data == job->mux_data)
     {
         /* Video */
@@ -264,6 +288,21 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
             }
             mux_data->prev_chapter_tc = timecode;
         }
+
+        if (job->vcodec == HB_VCODEC_THEORA)
+        {
+            /* ughhh, theora is a pain :( */
+            op = (ogg_packet *)buf->data;
+            op->packet = buf->data + sizeof( ogg_packet );
+            if (mk_startFrame(m->file, mux_data->track) < 0)
+            {
+                hb_error( "Failed to write frame to output file, Disk Full?" );
+                *job->die = 1;
+            }
+            mk_addFrameData(m->file, mux_data->track, op->packet, op->bytes);
+            mk_setFrameFlags(m->file, mux_data->track, timecode, 1);
+            return 0;
+        }
     }
     else
     {
@@ -272,11 +311,13 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
         if (job->acodec == HB_ACODEC_VORBIS)
         {
             /* ughhh, vorbis is a pain :( */
-            ogg_packet  *op;
-
             op = (ogg_packet *)buf->data;
             op->packet = buf->data + sizeof( ogg_packet );
-            mk_startFrame(m->file, mux_data->track);
+            if (mk_startFrame(m->file, mux_data->track))
+            {
+                hb_error( "Failed to write frame to output file, Disk Full?" );
+                *job->die = 1;
+            }
             mk_addFrameData(m->file, mux_data->track, op->packet, op->bytes);
             mk_setFrameFlags(m->file, mux_data->track, timecode, 1);
             return 0;
index 16c2d46..4331224 100644 (file)
@@ -143,40 +143,57 @@ static int OGMInit( hb_mux_object_t * m )
 
 
     /* First pass: all b_o_s packets */
-
+    hb_log("muxogm: Writing b_o_s header packets");
     /* Video */
     mux_data = job->mux_data;
-    memset( &h, 0, sizeof( ogg_stream_header_t ) );
-    h.i_packet_type = 0x01;
-    memcpy( h.stream_type, "video    ", 8 );
-    if( mux_data->codec == HB_VCODEC_X264 )
-    {
-        memcpy( h.sub_type, "H264", 4 );
-    }
-    else if( mux_data->codec == HB_VCODEC_XVID )
+    switch( job->vcodec )
     {
-        memcpy( h.sub_type, "XVID", 4 );
-    }
-    else
-    {
-        memcpy( h.sub_type, "DX50", 4 );
+        case HB_VCODEC_THEORA:
+            memcpy(&op, job->config.theora.headers[0], sizeof(op));
+            op.packet = job->config.theora.headers[0] + sizeof(op);
+            ogg_stream_packetin( &mux_data->os, &op );
+            break;
+        case HB_VCODEC_XVID:
+        case HB_VCODEC_X264:
+        case HB_VCODEC_FFMPEG:
+        {
+                memset( &h, 0, sizeof( ogg_stream_header_t ) );
+                h.i_packet_type = 0x01;
+                memcpy( h.stream_type, "video    ", 8 );
+                if( mux_data->codec == HB_VCODEC_X264 )
+                {
+                    memcpy( h.sub_type, "H264", 4 );
+                }
+                else if( mux_data->codec == HB_VCODEC_XVID )
+                {
+                    memcpy( h.sub_type, "XVID", 4 );
+                }
+                else
+                {
+                    memcpy( h.sub_type, "DX50", 4 );
+                }
+                SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);
+                SetQWLE( &h.i_time_unit, (int64_t) 10 * 1000 * 1000 *
+                         (int64_t) job->vrate_base / (int64_t) job->vrate );
+                SetQWLE( &h.i_samples_per_unit, 1 );
+                SetDWLE( &h.i_default_len, 0 );
+                SetDWLE( &h.i_buffer_size, 1024*1024 );
+                SetWLE ( &h.i_bits_per_sample, 0 );
+                SetDWLE( &h.header.video.i_width,  job->width );
+                SetDWLE( &h.header.video.i_height, job->height );
+                op.packet   = (unsigned char*)&h;
+                op.bytes    = sizeof( ogg_stream_header_t );
+                op.b_o_s    = 1;
+                op.e_o_s    = 0;
+                op.granulepos = 0;
+                op.packetno = mux_data->i_packet_no++;
+                ogg_stream_packetin( &mux_data->os, &op );
+                break;
+            }
+        default:
+            hb_error( "muxogm: unhandled video codec" );
+            *job->die = 1;
     }
-    SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);
-    SetQWLE( &h.i_time_unit, (int64_t) 10 * 1000 * 1000 *
-             (int64_t) job->vrate_base / (int64_t) job->vrate );
-    SetQWLE( &h.i_samples_per_unit, 1 );
-    SetDWLE( &h.i_default_len, 0 );
-    SetDWLE( &h.i_buffer_size, 1024*1024 );
-    SetWLE ( &h.i_bits_per_sample, 0 );
-    SetDWLE( &h.header.video.i_width,  job->width );
-    SetDWLE( &h.header.video.i_height, job->height );
-    op.packet   = (unsigned char*)&h;
-    op.bytes    = sizeof( ogg_stream_header_t );
-    op.b_o_s    = 1;
-    op.e_o_s    = 0;
-    op.granulepos = 0;
-    op.packetno = mux_data->i_packet_no++;
-    ogg_stream_packetin( &mux_data->os, &op );
     OGMFlush( m, mux_data );
 
     /* Audio */
@@ -231,6 +248,30 @@ static int OGMInit( hb_mux_object_t * m )
     }
 
     /* second pass: all non b_o_s packets */
+    hb_log("muxogm: Writing non b_o_s header packets");
+    /* Video */
+    mux_data = job->mux_data;
+    switch( job->vcodec )
+    {
+        case HB_VCODEC_THEORA:
+            for (i = 1; i < 3; i++)
+            {
+                memcpy(&op, job->config.theora.headers[i], sizeof(op));
+                op.packet = job->config.theora.headers[i] + sizeof(op);
+                ogg_stream_packetin( &mux_data->os, &op );
+                OGMFlush( m, mux_data );
+            }
+            break;
+        case HB_VCODEC_XVID:
+        case HB_VCODEC_X264:
+        case HB_VCODEC_FFMPEG:
+            break;
+        default:
+            hb_error( "muxogm: unhandled video codec" );
+            *job->die = 1;
+    }
+
+    /* Audio */
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
         audio = hb_list_item( title->list_audio, i );
@@ -263,6 +304,11 @@ static int OGMMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
 
     switch( mux_data->codec )
     {
+        case HB_VCODEC_THEORA:
+            memcpy( &op, buf->data, sizeof( ogg_packet ) );
+            op.packet = malloc( op.bytes );
+            memcpy( op.packet, buf->data + sizeof( ogg_packet ), op.bytes );
+            break;
         case HB_VCODEC_FFMPEG:
         case HB_VCODEC_XVID:
         case HB_VCODEC_X264:
index c6357ae..9ebc33b 100644 (file)
@@ -264,6 +264,10 @@ static void do_job( hb_job_t * job, int cpu_count )
                 hb_log( "   + x264 options: %s", job->x264opts);
             w = getWork( WORK_ENCX264 );
             break;
+        case HB_VCODEC_THEORA:
+            hb_log( " + encoder Theora" );
+            w = getWork( WORK_ENCTHEORA );
+            break;
     }
     w->fifo_in  = job->fifo_render;
     w->fifo_out = job->fifo_mpeg4;
index 555e0e4..7cc5b52 100644 (file)
@@ -92,6 +92,8 @@
                59CBD2650BBB4D1B004A3BE3 /* ChapterTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = 593034EA0BBA39A100172349 /* ChapterTitles.m */; };
                A22C85EC0D05D35000C10E36 /* HBPresets.h in Headers */ = {isa = PBXBuildFile; fileRef = A22C85EA0D05D35000C10E36 /* HBPresets.h */; };
                A22C85ED0D05D35100C10E36 /* HBPresets.m in Sources */ = {isa = PBXBuildFile; fileRef = A22C85EB0D05D35000C10E36 /* HBPresets.m */; };
+               A25289E60D87A27D00461D5B /* enctheora.c in Sources */ = {isa = PBXBuildFile; fileRef = A25289E50D87A27D00461D5B /* enctheora.c */; };
+               A25289E70D87A2CB00461D5B /* enctheora.c in Sources */ = {isa = PBXBuildFile; fileRef = A25289E50D87A27D00461D5B /* enctheora.c */; };
                A273E0510C57B39A00493A45 /* Pause.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A273E04A0C57B39A00493A45 /* Pause.tiff */; };
                A273E0520C57B39A00493A45 /* Play.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A273E04B0C57B39A00493A45 /* Play.tiff */; };
                A273E0530C57B39A00493A45 /* Stop.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A273E04C0C57B39A00493A45 /* Stop.tiff */; };
                59CBD2360BBB44DA004A3BE3 /* parsecsv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = parsecsv.c; path = ../test/parsecsv.c; sourceTree = SOURCE_ROOT; };
                A22C85EA0D05D35000C10E36 /* HBPresets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBPresets.h; sourceTree = "<group>"; };
                A22C85EB0D05D35000C10E36 /* HBPresets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPresets.m; sourceTree = "<group>"; };
+               A25289E50D87A27D00461D5B /* enctheora.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = enctheora.c; path = ../libhb/enctheora.c; sourceTree = SOURCE_ROOT; };
                A273E04A0C57B39A00493A45 /* Pause.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Pause.tiff; sourceTree = "<group>"; };
                A273E04B0C57B39A00493A45 /* Play.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Play.tiff; sourceTree = "<group>"; };
                A273E04C0C57B39A00493A45 /* Stop.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Stop.tiff; sourceTree = "<group>"; };
                526FBC8D0B4CA9F90064E04C /* libhb Sources */ = {
                        isa = PBXGroup;
                        children = (
+                               A25289E50D87A27D00461D5B /* enctheora.c */,
                                B48359A70C82960500E04440 /* lang.c */,
                                EAA526920C3B25D200944FF2 /* stream.c */,
                                0DFA5C7E0B8DD3B60020BC09 /* declpcm.c */,
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               A25289E70D87A2CB00461D5B /* enctheora.c in Sources */,
                                D4D49FED0C83355600F01215 /* lang.c in Sources */,
                                0DFA5CD90B8DD4210020BC09 /* declpcm.c in Sources */,
                                0DFA5CDA0B8DD4210020BC09 /* decmpeg2.c in Sources */,
                                FC8519520C59A02C0073812C /* deblock.c in Sources */,
                                FC8519530C59A02C0073812C /* detelecine.c in Sources */,
                                B48359A80C82960500E04440 /* lang.c in Sources */,
+                               A25289E60D87A27D00461D5B /* enctheora.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                        ../contrib/lib/libdca.a,
                                        ../contrib/lib/libmkv.a,
                                        ../contrib/lib/libswscale.a,
+                                       ../contrib/lib/libtheora.a,
                                );
                                PRODUCT_NAME = HandBrake;
                                SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
                                        ../contrib/lib/libdca.a,
                                        ../contrib/lib/libmkv.a,
                                        ../contrib/lib/libswscale.a,
+                                       ../contrib/lib/libtheora.a,
                                );
                                PREBINDING = NO;
                                PRODUCT_NAME = HandBrakeCLI;
                                        ../contrib/lib/libdca.a,
                                        ../contrib/lib/libmkv.a,
                                        ../contrib/lib/libswscale.a,
+                                       ../contrib/lib/libtheora.a,
                                );
                                PREBINDING = NO;
                                PRODUCT_NAME = HandBrakeCLI;
                                        ../contrib/lib/libdca.a,
                                        ../contrib/lib/libmkv.a,
                                        ../contrib/lib/libswscale.a,
+                                       ../contrib/lib/libtheora.a,
                                );
                                PREBINDING = NO;
                                PRODUCT_NAME = HandBrakeCLI;
                                        ../contrib/lib/libdca.a,
                                        ../contrib/lib/libmkv.a,
                                        ../contrib/lib/libswscale.a,
+                                       ../contrib/lib/libtheora.a,
                                );
                                PRODUCT_NAME = HandBrake;
                                SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
                                        ../contrib/lib/libdca.a,
                                        ../contrib/lib/libmkv.a,
                                        ../contrib/lib/libswscale.a,
+                                       ../contrib/lib/libtheora.a,
                                );
                                PRODUCT_NAME = HandBrake;
                                SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
index b0da889..e6c978c 100644 (file)
@@ -1178,7 +1178,7 @@ static void ShowHelp()
 
        "### Video Options------------------------------------------------------------\n\n"
        "    -e, --encoder <string>  Set video library encoder (ffmpeg,xvid,\n"
-    "                            x264,x264b13,x264b30 default: ffmpeg)\n"
+    "                            x264,x264b13,x264b30,theora default: ffmpeg)\n"
        "    -q, --quality <float>   Set video quality (0.0..1.0)\n"
        "    -Q, --cqp               Use with -q for CQP instead of CRF\n"
     "    -S, --size <MB>         Set target size\n"
@@ -1586,6 +1586,10 @@ static int ParseOptions( int argc, char ** argv )
                     vcodec = HB_VCODEC_X264;
                     h264_30 = 1;
                 }
+                else if( !strcasecmp( optarg, "theora" ) )
+                {
+                    vcodec = HB_VCODEC_THEORA;
+                }
                 else
                 {
                     fprintf( stderr, "invalid codec (%s)\n", optarg );