[xiph-commits] r14950 - in trunk/ffmpeg2theora: . src

j at svn.xiph.org j at svn.xiph.org
Fri May 23 10:56:21 PDT 2008


Author: j
Date: 2008-05-23 10:56:21 -0700 (Fri, 23 May 2008)
New Revision: 14950

Added:
   trunk/ffmpeg2theora/src/
   trunk/ffmpeg2theora/src/ffmpeg2theora.c
   trunk/ffmpeg2theora/src/ffmpeg2theora.h
   trunk/ffmpeg2theora/src/subtitles.c
   trunk/ffmpeg2theora/src/subtitles.h
   trunk/ffmpeg2theora/src/theorautils.c
   trunk/ffmpeg2theora/src/theorautils.h
Removed:
   trunk/ffmpeg2theora/ffmpeg2theora.c
   trunk/ffmpeg2theora/subtitles.c
   trunk/ffmpeg2theora/subtitles.h
   trunk/ffmpeg2theora/theorautils.c
   trunk/ffmpeg2theora/theorautils.h
Modified:
   trunk/ffmpeg2theora/
   trunk/ffmpeg2theora/INSTALL
   trunk/ffmpeg2theora/Makefile.am
   trunk/ffmpeg2theora/README
   trunk/ffmpeg2theora/SConstruct
   trunk/ffmpeg2theora/TODO
   trunk/ffmpeg2theora/get_libkate.sh
Log:
more files to ./src


Property changes on: trunk/ffmpeg2theora
___________________________________________________________________
Name: bzr:revision-info
   - timestamp: 2008-05-23 18:59:04.180999994 +0200
committer: j
properties: 
	branch-nick: ffmpeg2theora

   + timestamp: 2008-05-23 19:54:32.194999933 +0200
committer: j
properties: 
	branch-nick: ffmpeg2theora

Name: bzr:file-ids
   - SConstruct	sconstruct-20080523165848-8nlost8hilp0zdcm-1

   + src	src-20080523174144-dkwx1i25ujognb2c-1
src/ffmpeg2theora.c	6863 at 0101bb08-14d6-0310-b084-bc0e0c8e3800:trunk%2Fffmpeg2theora:ffmpeg2theora.c
src/ffmpeg2theora.h	ffmpeg2theora.h-20080523174200-q6z54q34pgkgpz50-1
src/subtitles.c	subtitles.c-20080523092315-berdpbqhudpfrkh7-1
src/subtitles.h	subtitles.h-20080523092316-79y08zf0g4v687h5-1
src/theorautils.c	6863 at 0101bb08-14d6-0310-b084-bc0e0c8e3800:trunk%2Fffmpeg2theora:theorautils.c
src/theorautils.h	6863 at 0101bb08-14d6-0310-b084-bc0e0c8e3800:trunk%2Fffmpeg2theora:theorautils.h

Name: bzr:revision-id:v3-single1-dHJ1bmsvZmZtcGVnMnRoZW9yYQ..
   - 191 j-20080517230830-he5x8v2m8yrfiw35
192 j-20080518224037-pkmoctzf4qce7tog
193 j-20080518224409-6hbfp3k2ssn6egqa
194 j-20080520111939-dhi52qwbqe7a47cu
195 j-20080523092252-gj9k9db0s67vl7dw
196 j-20080523092420-l0850yrq1qkgz9t0
197 j-20080523093057-l5g0ezzy5geu0pey
198 j-20080523094343-kcno1dm2e1lr38q4
199 j-20080523163006-kjl6ewea5sxawmq2
200 j-20080523165904-l2vm52qae0hlqkhp

   + 191 j-20080517230830-he5x8v2m8yrfiw35
192 j-20080518224037-pkmoctzf4qce7tog
193 j-20080518224409-6hbfp3k2ssn6egqa
194 j-20080520111939-dhi52qwbqe7a47cu
195 j-20080523092252-gj9k9db0s67vl7dw
196 j-20080523092420-l0850yrq1qkgz9t0
197 j-20080523093057-l5g0ezzy5geu0pey
198 j-20080523094343-kcno1dm2e1lr38q4
199 j-20080523163006-kjl6ewea5sxawmq2
200 j-20080523165904-l2vm52qae0hlqkhp
201 j-20080523175432-2ed953iktnl8c7cr


Modified: trunk/ffmpeg2theora/INSTALL
===================================================================
--- trunk/ffmpeg2theora/INSTALL	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/INSTALL	2008-05-23 17:56:21 UTC (rev 14950)
@@ -1,7 +1,7 @@
 Compiling from SVN
 ------------------
-If you donwloaded ffmpeg2theora from svn you have
-need automake 1.6 or later to build the configure script.
+If you donwloaded ffmpeg2theora from svn you need
+automake 1.8 or later to build the configure script.
 To do this run ./autogen.sh
 Then build as you would from a tarball.
 
@@ -36,14 +36,6 @@
 
 sudo make install
 
-Compiling on windows using mingw32:
----------------------------------
-you have to compile libvorbis, libogg, libtheora
-configure ffmpeg like this:
-./configure --disable-encoder --enable-libogg --enable-vorbis --enable-theora \
- --enable-pp --enable-a52  --enable-gpl
-
-
 vhook suppport
 --------------
 
@@ -52,7 +44,6 @@
  undefined symbol: av_read_frame
 this is a known limitation of vhooks in ffmpeg.
 
-
 subtitles suppport
 ------------------
 

Modified: trunk/ffmpeg2theora/Makefile.am
===================================================================
--- trunk/ffmpeg2theora/Makefile.am	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/Makefile.am	2008-05-23 17:56:21 UTC (rev 14950)
@@ -8,9 +8,9 @@
 
 bin_PROGRAMS = ffmpeg2theora
 
-ffmpeg2theora_SOURCES = ffmpeg2theora.c theorautils.c subtitles.c \
-                        ffmpeg2theora.h theorautils.h subtitles.h
+ffmpeg2theora_SOURCES = src/ffmpeg2theora.c src/theorautils.c src/subtitles.c \
+                        src/ffmpeg2theora.h src/theorautils.h src/subtitles.h
 ffmpeg2theora_LDFLAGS = -L$(prefix)/lib @XIPH_LIBS@ @KATE_LIBS@ @FFMPEG_LIBS@
-ffmpeg2theora_CFLAGS = @XIPH_CFLAGS@ @KATE_CFLAGS@ @FFMPEG_CFLAGS@
+ffmpeg2theora_CFLAGS = -I./src @XIPH_CFLAGS@ @KATE_CFLAGS@ @FFMPEG_CFLAGS@
 
 man_MANS = ffmpeg2theora.1

Modified: trunk/ffmpeg2theora/README
===================================================================
--- trunk/ffmpeg2theora/README	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/README	2008-05-23 17:56:21 UTC (rev 14950)
@@ -6,7 +6,6 @@
 along sites like v2v.cc to enable as many people as possible
 to encode video clips with the same settings.
 
-
 usage right now:
  ./ffmpeg2theora clip.avi
  will produce clip.ogv

Modified: trunk/ffmpeg2theora/SConstruct
===================================================================
--- trunk/ffmpeg2theora/SConstruct	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/SConstruct	2008-05-23 17:56:21 UTC (rev 14950)
@@ -22,7 +22,6 @@
   '-DPACKAGE_VERSION=\\"%s\\"' %pkg_version,
   '-DPACKAGE_STRING=\\"%s-%s\\"' %(pkg_name, pkg_version),
   '-DPACKAGE=\\"%s\\"' % pkg_name,
-  '-DVERSION=\\"%s\\"' %pkg_version,
 ])
 #if env['CC'] == 'gcc':
 #  env.Append(CCFLAGS=["-g", "-O2", "-Wall"])
@@ -81,13 +80,13 @@
   env.Append(CCFLAGS=['-DHAVE_KATE', '-DHAVE_OGGKATE'])
 else:
   print """
-      Could not find %s.
-      update PKG_CONFIG_PATH to point to ffmpeg's source folder
-      or run ./get_libkate.sh (for more information see INSTALL)
-  """ % KATE_LIBS
+      Could not find libkate. Subtitles support will be disabled.
+      You can also run ./get_libkate.sh (for more information see INSTALL)
+      or update PKG_CONFIG_PATH to point to libkate's source folder
+  """
 env = conf.Finish()
 
 # ffmpeg2theora 
 ffmpeg2theora = env.Copy()
-ffmpeg2theora_sources = glob('*.c')
+ffmpeg2theora_sources = glob('src/*.c')
 ffmpeg2theora.Program('ffmpeg2theora', ffmpeg2theora_sources)

Modified: trunk/ffmpeg2theora/TODO
===================================================================
--- trunk/ffmpeg2theora/TODO	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/TODO	2008-05-23 17:56:21 UTC (rev 14950)
@@ -1,5 +1,4 @@
 - remove global variable info
 - more commandline options
-- think of adding noise reduction(best would be integration of denoise3d)
 - allow frame size not multiple of 16.
 - add option for pixel aspect ratio

Deleted: trunk/ffmpeg2theora/ffmpeg2theora.c
===================================================================
--- trunk/ffmpeg2theora/ffmpeg2theora.c	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/ffmpeg2theora.c	2008-05-23 17:56:21 UTC (rev 14950)
@@ -1,1769 +0,0 @@
-/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
-/*
- * ffmpeg2theora.c -- Convert ffmpeg supported a/v files to  Ogg Theora / Ogg Vorbis
- * Copyright (C) 2003-2008 <j at v2v.cc>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <getopt.h>
-#include <math.h>
-#include <errno.h>
-
-#include "libavformat/avformat.h"
-#include "libavdevice/avdevice.h"
-#include "libswscale/swscale.h"
-#include "libpostproc/postprocess.h"
-
-#include "theora/theora.h"
-#include "vorbis/codec.h"
-#include "vorbis/vorbisenc.h"
-
-#ifdef WIN32
-#include "fcntl.h"
-#endif
-
-#include "theorautils.h"
-#include "subtitles.h"
-#include "ffmpeg2theora.h"
-
-#ifdef __linux__
-  #define VIDEO4LINUX_ENABLED
-#endif
-
-enum {
-  NULL_FLAG,
-  DEINTERLACE_FLAG,
-  OPTIMIZE_FLAG,
-  SYNC_FLAG,
-  NOSOUND_FLAG,
-  CROPTOP_FLAG,
-  CROPBOTTOM_FLAG,
-  CROPRIGHT_FLAG,
-  CROPLEFT_FLAG,
-  ASPECT_FLAG,
-  INPUTFPS_FLAG,
-  AUDIOSTREAM_FLAG,
-  SUBTITLES_FLAG,
-  SUBTITLES_ENCODING_FLAG,
-  SUBTITLES_LANGUAGE_FLAG,
-  SUBTITLES_CATEGORY_FLAG,
-  VHOOK_FLAG,
-  FRONTEND_FLAG,
-  SPEEDLEVEL_FLAG,
-  PP_FLAG,
-  NOSKELETON
-} F2T_FLAGS;
-
-enum {
-  V2V_PRESET_NONE,
-  V2V_PRESET_PRO,
-  V2V_PRESET_PREVIEW,
-  V2V_PRESET_VIDEOBIN,
-  V2V_PRESET_PADMA,
-  V2V_PRESET_PADMASTREAM,
-} F2T_PRESETS;
-
-
-#define PAL_HALF_WIDTH 384
-#define PAL_HALF_HEIGHT 288
-#define NTSC_HALF_WIDTH 320
-#define NTSC_HALF_HEIGHT 240
-
-#define PAL_FULL_WIDTH 720
-#define PAL_FULL_HEIGHT 576
-#define NTSC_FULL_WIDTH 720
-#define NTSC_FULL_HEIGHT 480
-
-
-static int sws_flags = SWS_BICUBIC;
-
-oggmux_info info;
-
-static int using_stdin = 0;
-
-
-/**
- * Allocate and initialise an AVFrame.
- */
-AVFrame *frame_alloc (int pix_fmt, int width, int height) {
-    AVFrame *picture;
-    uint8_t *picture_buf;
-    int size;
-
-    picture = avcodec_alloc_frame ();
-    if (!picture)
-        return NULL;
-    size = avpicture_get_size (pix_fmt, width, height);
-    picture_buf = av_malloc (size);
-    if (!picture_buf){
-        av_free (picture);
-        return NULL;
-    }
-    avpicture_fill ((AVPicture *) picture, picture_buf,
-            pix_fmt, width, height);
-    return picture;
-}
-
-/**
- * initialize ff2theora with default values
- * @return ff2theora struct
- */
-ff2theora ff2theora_init (){
-    ff2theora this = calloc (1, sizeof (*this));
-    if (this != NULL){
-        this->disable_audio=0;
-        this->video_index = -1;
-        this->audio_index = -1;
-        this->start_time=0;
-        this->end_time=0; /* 0 denotes no end time set */
-
-        // audio
-        this->sample_rate = -1;  // samplerate hmhmhm
-        this->channels = -1;
-        this->audio_quality = 1.00;// audio quality 1
-        this->audio_bitrate=0;
-        this->audiostream = -1;
-
-        // video
-        this->picture_width=0;      // set to 0 to not resize the output
-        this->picture_height=0;      // set to 0 to not resize the output
-        this->video_quality=rint(5*6.3); // video quality 5
-        this->video_bitrate=0;
-        this->sharpness=0;
-        this->keyint=64;
-        this->force_input_fps=0;
-        this->sync=0;
-        this->aspect_numerator=0;
-        this->aspect_denominator=0;
-        this->frame_aspect=0;
-        this->deinterlace=0; // auto by default, if input is flaged as interlaced it will deinterlace.
-        this->vhook=0;
-        this->framerate_new.num = -1;
-        this->framerate_new.den = 1;
-
-        this->frame_topBand=0;
-        this->frame_bottomBand=0;
-        this->frame_leftBand=0;
-        this->frame_rightBand=0;
-
-        this->n_kate_streams=0;
-        this->kate_streams=NULL;
-
-        this->pix_fmt = PIX_FMT_YUV420P;
-
-        // ffmpeg2theora --nosound -f dv -H 32000 -S 0 -v 8 -x 384 -y 288 -G 1.5 input.dv
-        this->video_gamma  = 0.0;
-        this->video_bright = 0.0;
-        this->video_contr  = 0.0;
-        this->video_satur  = 1.0;
-
-        this->y_lut_used = 0;
-        this->uv_lut_used = 0;
-        this->y_lut[256];
-        this->uv_lut[256];
-    }
-    return this;
-}
-
-// gamma lookup table code
-
-static void y_lut_init(ff2theora this) {
-    int i;
-    double v;
-
-    double c = this->video_contr;
-    double b = this->video_bright;
-    double g = this->video_gamma;
- 
-    if ((g < 0.01) || (g > 100.0)) g = 1.0;
-    if ((c < 0.01) || (c > 100.0)) c = 1.0;
-    if ((b < -1.0) || (b > 1.0))   b = 0.0;
-
-    if (g == 1.0 && c == 1.0 && b == 0.0) return;
-    this->y_lut_used = 1;
-
-    printf("  Video correction: gamma=%g, contrast=%g, brightness=%g\n", g, c, b);
-
-    g = 1.0 / g;    // larger values shall make brighter video.
-
-    for (i = 0; i < 256; i++) {
-        v = (double) i / 255.0;
-        v = c * v + b * 0.1;
-        if (v < 0.0) v = 0.0;
-        v = pow(v, g) * 255.0;    // mplayer's vf_eq2.c multiplies with 256 here, strange...
-
-        if (v >= 255)
-            this->y_lut[i] = 255;
-        else
-            this->y_lut[i] = (unsigned char)(v+0.5);
-    }
-}
-
-
-static void uv_lut_init(ff2theora this) {
-    int i;
-    double v, s;
-    s = this->video_satur;
-
-    if ((s < 0.0) || (s > 100.0)) s = 1.0;
-
-    if (s == 1.0) return;
-    this->uv_lut_used = 1;
-
-    printf("  Color correction: saturation=%g\n", s);
-
-    for (i = 0; i < 256; i++) {
-        v = 127.0 + (s * ((double)i - 127.0));
-        if (v < 0.0) v = 0.0;
-
-        if (v >= 255.0)
-            this->uv_lut[i] = 255;
-        else
-            this->uv_lut[i] = (unsigned char)(v+0.5);
-    }
-}
-
-static void lut_init(ff2theora this) {
-    y_lut_init(this);
-    uv_lut_init(this);
-}
-
-static void lut_apply(unsigned char *lut, unsigned char *src, unsigned char *dst, int width, int height, int stride) {
-    int x, y;
-
-    for (y = 0; y < height; y++) {
-        for (x = 0; x < width; x++) {
-            dst[x] = lut[src[x]];
-        }
-        src += stride;
-        dst += stride;
-    }
-}
-
-static void prepare_yuv_buffer(ff2theora this, yuv_buffer *yuv, AVFrame *output_buffered) {
-    /* pysical pages */
-    yuv->y_width = this->frame_width;
-    yuv->y_height = this->frame_height;
-    yuv->y_stride = output_buffered->linesize[0];
-
-    yuv->uv_width = this->frame_width / 2;
-    yuv->uv_height = this->frame_height / 2;
-    yuv->uv_stride = output_buffered->linesize[1];
-
-    yuv->y = output_buffered->data[0];
-    yuv->u = output_buffered->data[1];
-    yuv->v = output_buffered->data[2];
-    if (this->y_lut_used) {
-        lut_apply(this->y_lut, yuv->y, yuv->y, yuv->y_width, yuv->y_height, yuv->y_stride);
-    }
-    if (this->uv_lut_used) {
-        lut_apply(this->uv_lut, yuv->u, yuv->u, yuv->uv_width, yuv->uv_height, yuv->uv_stride);
-        lut_apply(this->uv_lut, yuv->v, yuv->v, yuv->uv_width, yuv->uv_height, yuv->uv_stride);
-    }
-}
-
-void ff2theora_output(ff2theora this) {
-    int i;
-    AVCodecContext *aenc = NULL;
-    AVCodecContext *venc = NULL;
-    AVStream *astream = NULL;
-    AVStream *vstream = NULL;
-    AVCodec *acodec = NULL;
-    AVCodec *vcodec = NULL;
-    pp_mode_t *ppMode = NULL;
-    pp_context_t *ppContext = NULL;
-    float frame_aspect;
-    double fps = 0.0;
-
-    if(this->audiostream >= 0 && this->context->nb_streams > this->audiostream) {
-        AVCodecContext *enc = this->context->streams[this->audiostream]->codec;
-        if (enc->codec_type == CODEC_TYPE_AUDIO) {
-            this->audio_index = this->audiostream;
-            fprintf(stderr,"  Using stream #0.%d as audio input\n",this->audio_index);
-        }
-        else {
-            fprintf(stderr,"  The selected stream is not audio, falling back to automatic selection\n");
-        }
-    }
-
-    for (i = 0; i < this->context->nb_streams; i++){
-        AVCodecContext *enc = this->context->streams[i]->codec;
-        switch (enc->codec_type){
-            case CODEC_TYPE_VIDEO:
-              if (this->video_index < 0)
-                    this->video_index = i;
-                break;
-            case CODEC_TYPE_AUDIO:
-                if (this->audio_index < 0 && !this->disable_audio)
-                    this->audio_index = i;
-                break;
-            default:
-                break;
-        }
-    }
-
-    if (this->video_index >= 0){
-        vstream = this->context->streams[this->video_index];
-        venc = this->context->streams[this->video_index]->codec;
-        vcodec = avcodec_find_decoder (venc->codec_id);
-
-        fps = (double) vstream->r_frame_rate.num / vstream->r_frame_rate.den;
-        if (fps > 10000)
-            fps /= 1000;
-
-        if(this->force_input_fps)
-            fps=this->force_input_fps;
-        if (vcodec == NULL || avcodec_open (venc, vcodec) < 0) {
-            this->video_index = -1;
-        }
-        this->fps = fps;
-
-
-        if(this->preset == V2V_PRESET_PREVIEW){
-            if(abs(this->fps-30)<1 && (venc->width!=NTSC_HALF_WIDTH || venc->height!=NTSC_HALF_HEIGHT) ){
-                this->picture_width=NTSC_HALF_WIDTH;
-                this->picture_height=NTSC_HALF_HEIGHT;
-            }
-            else {
-                this->picture_width=PAL_HALF_WIDTH;
-                this->picture_height=PAL_HALF_HEIGHT;
-            }
-        }
-        else if(this->preset == V2V_PRESET_PRO){
-            if(abs(this->fps-30)<1 && (venc->width!=NTSC_FULL_WIDTH || venc->height!=NTSC_FULL_HEIGHT) ){
-                this->picture_width=NTSC_FULL_WIDTH;
-                this->picture_height=NTSC_FULL_HEIGHT;
-            }
-            else {
-                this->picture_width=PAL_FULL_WIDTH;
-                this->picture_height=PAL_FULL_HEIGHT;
-            }
-        }
-         else if(this->preset == V2V_PRESET_PADMA){
-             int width=venc->width-this->frame_leftBand-this->frame_rightBand;
-             int height=venc->height-this->frame_topBand-this->frame_bottomBand;
-             if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
-               height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
-             }
-             if(this->frame_aspect == 0)
-               this->frame_aspect = (float)width/height;
-             if(this->frame_aspect <= 1.5) {
-               if(width > 640 || height > 480) {
-                 //4:3 640 x 480
-                 this->picture_width=640;
-                 this->picture_height=480;
-               }
-               else {
-                 this->picture_width=width;
-                 this->picture_height=height;
-               }
-             }
-             else {
-               if(width > 640 || height > 360) {
-                 //16:9 640 x 360
-                 this->picture_width=640;
-                 this->picture_height=360;
-               }
-               else {
-                 this->picture_width=width;
-                 this->picture_height=height;
-               }
-             }
-
-         }
-         else if(this->preset == V2V_PRESET_PADMASTREAM){
-             int width=venc->width-this->frame_leftBand-this->frame_rightBand;
-             int height=venc->height-this->frame_topBand-this->frame_bottomBand;
-             if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
-               height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
-             }
-             if(this->frame_aspect == 0)
-               this->frame_aspect = (float)width/height;
-             if(this->frame_aspect <= 1.5) {
-                 this->picture_width=128;
-                 this->picture_height=96;
-             }
-             else {
-                 this->picture_width=128;
-                 this->picture_height=72;
-             }
-         }
-        else if(this->preset == V2V_PRESET_VIDEOBIN){
-            int width=venc->width-this->frame_leftBand-this->frame_rightBand;
-            int height=venc->height-this->frame_topBand-this->frame_bottomBand;
-            if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
-              height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
-            }
-            if( ((float)width /height) <= 1.5) {
-              if(width > 448) {
-                //4:3 448 x 336
-                this->picture_width=448;
-                this->picture_height=336;
-              }
-              else {
-                this->picture_width=width;
-                this->picture_height=height;
-              }
-            }
-            else {
-              if(width > 512) {
-                //16:9 512 x 288
-                this->picture_width=512;
-                this->picture_height=288;
-              }
-              else {
-                this->picture_width=width;
-                this->picture_height=height;
-              }
-            }
-
-        }
-        if(this->picture_height==0 &&
-            (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){
-            this->picture_height=venc->height-
-                    this->frame_topBand-this->frame_bottomBand;
-        }
-        if(this->picture_width==0 &&
-            (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){
-            this->picture_width=venc->width-
-                    this->frame_leftBand-this->frame_rightBand;
-        }
-        //so frame_aspect is set on the commandline
-        if(this->frame_aspect != 0){
-            if(this->picture_height){
-                this->aspect_numerator = 10000*this->frame_aspect*this->picture_height;
-                this->aspect_denominator = 10000*this->picture_width;
-            }
-            else{
-                this->aspect_numerator = 10000*this->frame_aspect*venc->height;
-                this->aspect_denominator = 10000*venc->width;
-            }
-            av_reduce(&this->aspect_numerator,&this->aspect_denominator,this->aspect_numerator,this->aspect_denominator,10000);
-            frame_aspect=this->frame_aspect;
-        }
-        if(venc->sample_aspect_ratio.num!=0 && this->frame_aspect==0){
-            // just use the ratio from the input
-            this->aspect_numerator=venc->sample_aspect_ratio.num;
-            this->aspect_denominator=venc->sample_aspect_ratio.den;
-            // or we use ratio for the output
-            if(this->picture_height){
-                int width=venc->width-this->frame_leftBand-this->frame_rightBand;
-                int height=venc->height-this->frame_topBand-this->frame_bottomBand;
-                av_reduce(&this->aspect_numerator,&this->aspect_denominator,
-                venc->sample_aspect_ratio.num*width*this->picture_height,
-                venc->sample_aspect_ratio.den*height*this->picture_width,10000);
-                frame_aspect=(float)(this->aspect_numerator*this->picture_width)/
-                                (this->aspect_denominator*this->picture_height);
-            }
-            else{
-                frame_aspect=(float)(this->aspect_numerator*venc->width)/
-                                (this->aspect_denominator*venc->height);
-            }
-        }
-        if((float)this->aspect_numerator/this->aspect_denominator < 1.09){
-          this->aspect_numerator = 1;
-          this->aspect_denominator = 1;
-          frame_aspect=(float)(this->aspect_numerator*this->picture_width)/
-                          (this->aspect_denominator*this->picture_height);
-        }
-        if(this->aspect_denominator && frame_aspect){
-            fprintf(stderr,"  Pixel Aspect Ratio: %.2f/1 ",(float)this->aspect_numerator/this->aspect_denominator);
-            fprintf(stderr,"  Frame Aspect Ratio: %.2f/1\n",frame_aspect);
-        }
-
-        if (this->deinterlace==1)
-            fprintf(stderr,"  Deinterlace: on\n");
-
-        if (strcmp(this->pp_mode, "")) {
-          ppContext = pp_get_context(venc->width, venc->height, PP_FORMAT_420);
-          ppMode = pp_get_mode_by_name_and_quality(this->pp_mode, PP_QUALITY_MAX);
-          fprintf(stderr,"  Postprocessing: %s\n", this->pp_mode);
-        }
-
-        if(!this->picture_width)
-            this->picture_width = venc->width;
-        if(!this->picture_height)
-            this->picture_height = venc->height;
-
-        /* Theora has a divisible-by-sixteen restriction for the encoded video size */
-        /* scale the frame size up to the nearest /16 and calculate offsets */
-        this->frame_width = ((this->picture_width + 15) >>4)<<4;
-        this->frame_height = ((this->picture_height + 15) >>4)<<4;
-
-        this->frame_x_offset = 0;
-        this->frame_y_offset = 0;
-
-        if(this->frame_width > 0 || this->frame_height > 0){
-            this->sws_colorspace_ctx = sws_getContext(
-                          venc->width, venc->height, venc->pix_fmt,
-                          venc->width, venc->height, this->pix_fmt,
-                          sws_flags, NULL, NULL, NULL
-            );
-            this->sws_scale_ctx = sws_getContext(
-                          venc->width  - (this->frame_leftBand + this->frame_rightBand),
-                          venc->height  - (this->frame_topBand + this->frame_bottomBand),
-                          this->pix_fmt,
-                          this->frame_width, this->frame_height, this->pix_fmt,
-                          sws_flags, NULL, NULL, NULL
-            );
-            fprintf(stderr,"  Resize: %dx%d",venc->width,venc->height);
-            if(this->frame_topBand || this->frame_bottomBand ||
-            this->frame_leftBand || this->frame_rightBand){
-                fprintf(stderr," => %dx%d",
-                    venc->width-this->frame_leftBand-this->frame_rightBand,
-                    venc->height-this->frame_topBand-this->frame_bottomBand);
-            }
-            if(this->picture_width != (venc->width-this->frame_leftBand - this->frame_rightBand)
-                || this->picture_height != (venc->height-this->frame_topBand-this->frame_bottomBand))
-                fprintf(stderr," => %dx%d",this->picture_width, this->picture_height);
-            fprintf(stderr,"\n");
-        }
-
-        lut_init(this);
-    }
-    if (this->framerate_new.num > 0) {
-        fprintf(stderr,"  Resample Framerate: %0.2f => %0.2f\n",
-                        this->fps,(double)this->framerate_new.num / this->framerate_new.den);
-    }
-    if (this->audio_index >= 0){
-        astream = this->context->streams[this->audio_index];
-        aenc = this->context->streams[this->audio_index]->codec;
-        acodec = avcodec_find_decoder (aenc->codec_id);
-        if (this->channels < 1) {
-            if (aenc->channels > 2)
-                this->channels = 2;
-            else
-                this->channels = aenc->channels;
-        }
-        if(this->sample_rate==-1) {
-            this->sample_rate = aenc->sample_rate;
-        }
-        if (this->channels != aenc->channels && aenc->codec_id == CODEC_ID_AC3)
-            aenc->channels = this->channels;
-
-        if (acodec != NULL && avcodec_open (aenc, acodec) >= 0){
-            if(this->sample_rate != aenc->sample_rate || this->channels != aenc->channels){
-                this->audio_resample_ctx = audio_resample_init (this->channels,aenc->channels,this->sample_rate,aenc->sample_rate);
-                if(this->sample_rate!=aenc->sample_rate)
-                    fprintf(stderr,"  Resample: %dHz => %dHz\n",aenc->sample_rate,this->sample_rate);
-                if(this->channels!=aenc->channels)
-                    fprintf(stderr,"  Channels: %d => %d\n",aenc->channels,this->channels);
-            }
-            else{
-                this->audio_resample_ctx=NULL;
-            }
-        }
-        else{
-            this->audio_index = -1;
-        }
-    }
-
-    if (this->video_index >= 0 || this->audio_index >=0){
-        AVFrame *frame=NULL;
-        AVFrame *output=NULL;
-        AVFrame *output_tmp=NULL;
-        AVFrame *output_resized=NULL;
-        AVFrame *output_buffered=NULL;
-
-        AVPacket pkt;
-        int len;
-        int len1;
-        int got_picture;
-        int first = 1;
-        int e_o_s = 0;
-        int ret;
-        uint8_t *ptr;
-        int16_t *audio_buf= av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE);
-        int16_t *resampled= av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE);
-        int no_frames;
-
-        double framerate_add;
-        double framerate_tmpcount = 0;
-
-        if(this->video_index >= 0)
-            info.audio_only=0;
-        else
-            info.audio_only=1;
-
-        if(this->audio_index>=0)
-            info.video_only=0;
-        else
-            info.video_only=1;
-
-        if(!info.audio_only){
-            frame = frame_alloc(vstream->codec->pix_fmt,
-                            vstream->codec->width,vstream->codec->height);
-            output_tmp =frame_alloc(this->pix_fmt,
-                            vstream->codec->width,vstream->codec->height);
-            output =frame_alloc(this->pix_fmt,
-                            vstream->codec->width,vstream->codec->height);
-            output_resized =frame_alloc(this->pix_fmt,
-                            this->frame_width, this->frame_height);
-            output_buffered =frame_alloc(this->pix_fmt,
-                            this->frame_width, this->frame_height);
-
-            /* video settings here */
-            /* config file? commandline options? v2v presets? */
-
-            theora_info_init (&info.ti);
-
-            info.ti.width = this->frame_width;
-            info.ti.height = this->frame_height;
-            info.ti.frame_width = this->picture_width;
-            info.ti.frame_height = this->picture_height;
-            info.ti.offset_x = this->frame_x_offset;
-            info.ti.offset_y = this->frame_y_offset;
-            if(this->force_input_fps) {
-                info.ti.fps_numerator = 1000000 * (this->fps);    /* fps= numerator/denominator */
-                info.ti.fps_denominator = 1000000;
-            }
-            else {
-                if (this->framerate_new.num > 0) {
-                    // new framerate is interger only right now,
-                    // so denominator is always 1
-                    info.ti.fps_numerator = this->framerate_new.num;
-                    info.ti.fps_denominator = this->framerate_new.den;
-                }
-                else {
-                    info.ti.fps_numerator=vstream->r_frame_rate.num;
-                    info.ti.fps_denominator = vstream->r_frame_rate.den;
-                }
-            }
-
-            /* this is pixel aspect ratio */
-            info.ti.aspect_numerator=this->aspect_numerator;
-            info.ti.aspect_denominator=this->aspect_denominator;
-            // FIXME: is all input material with fps==25 OC_CS_ITU_REC_470BG?
-            // guess not, commandline option to select colorspace would be the best.
-            if((this->fps-25)<1)
-                info.ti.colorspace = OC_CS_ITU_REC_470BG;
-            else if(abs(this->fps-30)<1)
-                info.ti.colorspace = OC_CS_ITU_REC_470M;
-            else
-                info.ti.colorspace = OC_CS_UNSPECIFIED;
-
-            info.ti.target_bitrate = this->video_bitrate;
-            info.ti.quality = this->video_quality;
-            info.ti.dropframes_p = 0;
-            info.ti.keyframe_auto_p = 1;
-            info.ti.keyframe_frequency = this->keyint;
-            info.ti.keyframe_frequency_force = this->keyint;
-            info.ti.keyframe_data_target_bitrate = info.ti.target_bitrate * 1.5;
-            info.ti.keyframe_auto_threshold = 80;
-            info.ti.keyframe_mindistance = 8;
-            info.ti.noise_sensitivity = 1;
-            // range 0-2, 0 sharp, 2 less sharp,less bandwidth
-            info.ti.sharpness = this->sharpness;
-
-        }
-        /* audio settings here */
-        info.channels = this->channels;
-        info.sample_rate = this->sample_rate;
-        info.vorbis_quality = this->audio_quality * 0.1;
-        info.vorbis_bitrate = this->audio_bitrate;
-        /* subtitles */
-#ifdef HAVE_KATE
-        for (i=0; i<this->n_kate_streams; ++i) {
-            ff2theora_kate_stream *ks = this->kate_streams+i;
-            kate_info *ki = &info.kate_streams[i].ki;
-            kate_info_init(ki);
-            if (ks->num_subtitles > 0) {
-                kate_info_set_language(ki, ks->subtitles_language);
-                kate_info_set_category(ki, ks->subtitles_category[0]?ks->subtitles_category:"subtitles");
-                if(this->force_input_fps) {
-                    ki->gps_numerator = 1000000 * (this->fps);    /* fps= numerator/denominator */
-                    ki->gps_denominator = 1000000;
-                }
-                else {
-                    if (this->framerate_new.num > 0) {
-                        // new framerate is interger only right now, 
-                        // so denominator is always 1
-                        ki->gps_numerator = this->framerate_new.num;
-                        ki->gps_denominator = this->framerate_new.den;
-                    } 
-                    else {
-                        ki->gps_numerator=vstream->r_frame_rate.num;
-                        ki->gps_denominator = vstream->r_frame_rate.den;
-                    }
-                }
-                ki->granule_shift = 32;
-            }
-        }
-#endif
-        oggmux_init (&info);
-        /*seek to start time*/
-        if(this->start_time) {
-          av_seek_frame( this->context, -1, (int64_t)AV_TIME_BASE*this->start_time, 1);
-          /* discard subtitles by their end time, so we still have those that start before the start time,
-             but end after it */
-          for (i=0; i<this->n_kate_streams; ++i) {
-              ff2theora_kate_stream *ks=this->kate_streams+i;
-              while (ks->subtitles_count < ks->num_subtitles && ks->subtitles[ks->subtitles_count].t1 <= this->start_time) {
-                  /* printf("skipping subtitle %u\n", ks->subtitles_count); */
-                  ks->subtitles_count++;
-              }
-          }
-        }
-
-        if(info.audio_only && (this->end_time>0 || this->start_time>0)){
-            fprintf(stderr,"Sorry, right now start/end time does not work for audio only files.\n");
-            exit(1);
-        }
-
-        if (this->framerate_new.num > 0) {
-            double framerate_new = (double)this->framerate_new.num / this->framerate_new.den;
-            framerate_add = framerate_new/this->fps;
-            //fprintf(stderr,"calculating framerate addition to %f\n",framerate_add);
-            this->fps = framerate_new;
-        }
-
-        /*check for end time and calculate number of frames to encode*/
-        no_frames = this->fps*(this->end_time - this->start_time);
-        if(this->end_time > 0 && no_frames <= 0){
-            fprintf(stderr,"End time has to be bigger than start time.\n");
-            exit(1);
-        }
-        /* main decoding loop */
-        do{
-            if(no_frames > 0){
-                if(this->frame_count > no_frames){
-                    break;
-                }
-            }
-            ret = av_read_frame(this->context,&pkt);
-            if(ret<0){
-                e_o_s=1;
-            }
-
-            ptr = pkt.data;
-            len = pkt.size;
-            if (e_o_s && !info.audio_only || (ret >= 0 && pkt.stream_index == this->video_index)){
-                if(len == 0 && !first && !e_o_s){
-                    fprintf (stderr, "no frame available\n");
-                }
-                while(e_o_s || len > 0){
-                    int dups = 0;
-                    yuv_buffer yuv;
-                    len1 = avcodec_decode_video(vstream->codec, frame, &got_picture, ptr, len);
-                    if(len1>=0) {
-                        if(got_picture){
-                            // this is disabled by default since it does not work
-                            // for all input formats the way it should.
-                            if(this->sync == 1) {
-                                double delta = ((double) pkt.dts /
-                                    AV_TIME_BASE - this->pts_offset) *
-                                    this->fps - this->frame_count;
-                                /* 0.7 is an arbitrary value */
-                                /* it should be larger than half a frame to
-                                 avoid excessive dropping and duplicating */
-                                if (delta < -0.7) {
-#ifdef DEBUG
-                                    fprintf(stderr,
-                                          "Frame dropped to maintain sync\n");
-#endif
-                                    break;
-                                }
-                                if (delta > 0.7) {
-                                    //dups = lrintf(delta);
-                                    dups = (int)delta;
-#ifdef DEBUG
-                                    fprintf(stderr,
-                                      "%d duplicate %s added to maintain sync\n",
-                                      dups, (dups == 1) ? "frame" : "frames");
-#endif
-                                }
-                            }
-
-                            if (this->framerate_new.num > 0) {
-                                framerate_tmpcount += framerate_add;
-                                if (framerate_tmpcount < (double)(this->frame_count+1)) {
-                                    got_picture = 0;
-                                }
-                                else {
-                                    dups = 0;
-                                    while (framerate_tmpcount >= (double)(this->frame_count+2+dups)) {
-                                        dups += 1;
-                                    }
-                                }
-                            }
-
-                            //For audio only files command line option"-e" will not work
-                            //as we don't increment frame_count in audio section.
-
-                            if(venc->pix_fmt != this->pix_fmt) {
-                               sws_scale(this->sws_colorspace_ctx,
-                                 frame->data, frame->linesize, 0, venc->height,
-                                 output_tmp->data, output_tmp->linesize);
-
-                            }
-                            else{
-                                output_tmp = frame;
-                            }
-                            if(frame->interlaced_frame || this->deinterlace){
-                                if(avpicture_deinterlace((AVPicture *)output,(AVPicture *)output_tmp,this->pix_fmt,venc->width,venc->height)<0){
-                                        fprintf(stderr,"Deinterlace failed.\n");
-                                        exit(1);
-                                }
-                            }
-                            else{
-                                output=output_tmp;
-                            }
-                            // now output
-                            if(ppMode)
-                                pp_postprocess(output->data, output->linesize,
-                                               output->data, output->linesize,
-                                               venc->width, venc->height,
-                                               output->qscale_table, output->qstride,
-                                               ppMode, ppContext, this->pix_fmt);
-                            if(this->vhook)
-                                frame_hook_process((AVPicture *)output, this->pix_fmt, venc->width,venc->height);
-
-                            if (this->frame_topBand || this->frame_leftBand) {
-                                if (av_picture_crop((AVPicture *)output_tmp, (AVPicture *)output,
-                                    this->pix_fmt, this->frame_topBand, this->frame_leftBand) < 0) {
-                                    av_log(NULL, AV_LOG_ERROR, "error cropping picture\n");
-                                }
-                                output = output_tmp;
-                            }
-                            if(this->sws_scale_ctx){
-                              sws_scale(this->sws_scale_ctx,
-                                output->data, output->linesize, 0, venc->height - (this->frame_topBand + this->frame_bottomBand),
-                                output_resized->data, output_resized->linesize);
-                            }
-                            else{
-                                output_resized=output;
-                            }
-
-                        }
-                        ptr += len1;
-                        len -= len1;
-                    }
-                    //now output_resized
-
-                    if(!first) {
-                      if(got_picture || e_o_s) {
-                        prepare_yuv_buffer(this, &yuv, output_buffered);
-                        do {
-                          oggmux_add_video(&info, &yuv, e_o_s);
-                          this->frame_count++;
-                        } while(dups--);
-                      }
-                    }
-                    if(got_picture) {
-                      first=0;
-                      av_picture_copy ((AVPicture *)output_buffered, (AVPicture *)output_resized, this->pix_fmt, this->frame_width, this->frame_height);
-                    }
-                    if(!got_picture){
-                        break;
-                    }
-                }
-
-            }
-            if(e_o_s && !info.video_only
-                     || (ret >= 0 && pkt.stream_index == this->audio_index)){
-                this->pts_offset = (double) pkt.pts / AV_TIME_BASE -
-                    (double) this->sample_count / this->sample_rate;
-                while(e_o_s || len > 0 ){
-                    int samples=0;
-                    int samples_out=0;
-                    int data_size = 4*AVCODEC_MAX_AUDIO_FRAME_SIZE;
-                    if(len > 0){
-                        len1 = avcodec_decode_audio2(astream->codec, audio_buf, &data_size, ptr, len);
-                        if (len1 < 0){
-                            /* if error, we skip the frame */
-                            break;
-                        }
-                        len -= len1;
-                        ptr += len1;
-                        if(data_size >0){
-                            samples =data_size / (aenc->channels * 2);
-
-                            samples_out = samples;
-                            if(this->audio_resample_ctx){
-                                samples_out = audio_resample(this->audio_resample_ctx, resampled, audio_buf, samples);
-                            }
-                            else
-                                resampled=audio_buf;
-                        }
-                    }
-                    oggmux_add_audio(&info, resampled,
-                        samples_out *(this->channels),samples_out,e_o_s);
-                    this->sample_count += samples_out;
-                    if(e_o_s && len <= 0){
-                        break;
-                    }
-                }
-
-            }
-
-            /* if we have subtitles starting before then, add it */
-            if (info.with_kate) {
-                double avtime = info.audio_only ? info.audiotime :
-                    info.video_only ? info.videotime :
-                    info.audiotime < info.videotime ? info.audiotime : info.videotime;
-                for (i=0; i<this->n_kate_streams; ++i) {
-                    ff2theora_kate_stream *ks = this->kate_streams+i;
-                    if (ks->num_subtitles > 0) {
-                        ff2theora_subtitle *sub = ks->subtitles+ks->subtitles_count;
-                        /* we encode a bit in advance so we're sure to hit the time, the packet will
-                           be held till the right time. If we don't do that, we can insert late and
-                           oggz-validate moans */
-                        while (ks->subtitles_count < ks->num_subtitles && sub->t0-1.0 <= avtime+this->start_time) {
-                            int eos = (ks->subtitles_count == ks->num_subtitles-1);
-                            oggmux_add_kate_text(&info, i, sub->t0, sub->t1, sub->text, sub->len, eos);
-                            ks->subtitles_count++;
-                            ++sub;
-                        }
-                    }
-                }
-            }
-
-            /* flush out the file */
-            oggmux_flush (&info, e_o_s);
-            av_free_packet (&pkt);
-        }
-        while (ret >= 0);
-
-        for (i=0; i<this->n_kate_streams; ++i) {
-            ff2theora_kate_stream *ks = this->kate_streams+i;
-            if (ks->num_subtitles > 0 && ks->subtitles_count<ks->num_subtitles) {
-                double t = (info.videotime<info.audiotime?info.audiotime:info.videotime)+this->start_time;
-                oggmux_add_kate_end_packet(&info, i, t);
-                oggmux_flush (&info, e_o_s);
-            }
-        }
-
-        oggmux_close (&info);
-        if(ppContext)
-            pp_free_context(ppContext);
-    }
-    else{
-        fprintf (stderr, "No video or audio stream found.\n");
-    }
-}
-
-void ff2theora_close (ff2theora this){
-    /* clear out state */
-    free_subtitles(this);
-    av_free (this);
-}
-
-double aspect_check(const char *arg)
-{
-    int x = 0, y = 0;
-    double ar = 0;
-    const char *p;
-
-    p = strchr(arg, ':');
-    if (!p) {
-      p = strchr(arg, '/');
-    }
-    if (p) {
-        x = strtol(arg, (char **)&arg, 10);
-        if (arg == p)
-            y = strtol(arg+1, (char **)&arg, 10);
-        if (x > 0 && y > 0)
-            ar = (double)x / (double)y;
-    } else
-        ar = strtod(arg, (char **)&arg);
-
-    if (!ar) {
-        fprintf(stderr, "Incorrect aspect ratio specification.\n");
-        exit(1);
-    }
-    return ar;
-}
-
-static void add_frame_hooker(const char *arg)
-{
-    int argc = 0;
-    char *argv[64];
-    int i;
-    char *args = av_strdup(arg);
-
-    argv[0] = strtok(args, " ");
-    while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) {
-    }
-
-    i = frame_hook_add(argc, argv);
-    if (i != 0) {
-        fprintf(stderr, "Failed to add video hook function: %s\n", arg);
-        exit(1);
-    }
-}
-
-AVRational get_framerate(const char* arg)
-{
-    const char *p;
-    AVRational framerate;
-
-    p = strchr(arg, ':');
-    if (!p) {
-      p = strchr(arg, '/');
-    }
-    if (p) {
-        framerate.num = strtol(arg, (char **)&arg, 10);
-        if (arg == p)
-            framerate.den = strtol(arg+1, (char **)&arg, 10);
-        if(framerate.num <= 0)
-            framerate.num = -1;
-        if(framerate.den <= 0)
-            framerate.den = 1;
-    } else {
-        framerate.num = strtol(arg, (char **)&arg,10);
-        framerate.den = 1;
-    }
-    return(framerate);
-}
-
-int crop_check(ff2theora this, char *name, const char *arg)
-{
-    int crop_value = atoi(arg);
-    if (crop_value < 0) {
-        fprintf(stderr, "Incorrect crop size `%s'.\n",name);
-        exit(1);
-    }
-    if ((crop_value % 2) != 0) {
-        fprintf(stderr, "Crop size `%s' must be a multiple of 2.\n",name);
-        exit(1);
-    }
-    /*
-    if ((crop_value) >= this->height){
-        fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
-        exit(1);
-    }
-    */
-    return crop_value;
-}
-
-
-
-void print_presets_info() {
-    fprintf (stdout,
-        //  "v2v presets - more info at http://wiki.v2v.cc/presets"
-        "v2v presets:\n"
-        "  preview        Video: 320x240 if fps ~ 30, 384x288 otherwise\n"
-        "                        Quality 5 - Sharpness 2\n"
-        "                 Audio: Max 2 channels - Quality 1\n"
-        "\n"
-        "  pro            Video: 720x480 if fps ~ 30, 720x576 otherwise\n"
-        "                        Quality 7 - Sharpness 0\n"
-        "                 Audio: Max 2 channels - Quality 3\n"
-        "\n"
-        "  videobin       Video: 512x288 for 16:9 material, 448x336 for 4:3 material\n"
-        "                        Bitrate 600kbs\n"
-        "                 Audio: Max 2 channels - Quality 3\n"
-        "\n"
-        "  padma          Video: 640x360 for 16:9 material, 640x480 for 4:3 material\n"
-        "                        Quality 5 - Sharpness 0\n"
-        "                 Audio: Max 2 channels - Quality 3\n"
-        "\n"
-        "  padma-stream   Video: 128x72 for 16:9 material, 128x96 for 4:3 material\n"
-        "                 Audio: mono quality -1\n"
-        "\n"
-        );
-}
-
-void print_usage (){
-    fprintf (stdout,
-        PACKAGE " " PACKAGE_VERSION "\n"
-        "\n"
-        "  Usage: " PACKAGE " [options] input\n"
-        "\n"
-        "General output options:\n"
-        "  -o, --output           alternative output filename\n"
-        "      --no-skeleton      disables ogg skeleton metadata output\n"
-        "  -s, --starttime        start encoding at this time (in sec.)\n"
-        "  -e, --endtime          end encoding at this time (in sec.)\n"
-        "  -p, --v2v-preset       encode file with v2v preset.\n"
-        "                          Right now there is preview, pro and videobin. Run\n"
-        "                          '"PACKAGE" -p info' for more informations\n"
-        "\n"
-        "Video output options:\n"
-        "  -v, --videoquality     [0 to 10] encoding quality for video (default: 5)\n"
-        "                                   use higher values for better quality\n"
-        "  -V, --videobitrate     [1 to 16778] encoding bitrate for video (kb/s)\n"
-        "      --optimize         optimize video output filesize (slower) (same as speedlevel 0)\n"
-        "      --speedlevel       [0 2] encoding is faster with higher values the cost is quality and bandwidth\n"
-        "  -x, --width            scale to given width (in pixels)\n"
-        "  -y, --height           scale to given height (in pixels)\n"
-        "      --aspect           define frame aspect ratio: i.e. 4:3 or 16:9\n"
-        "  -F, --framerate        output framerate e.g 25:2 or 16\n"
-        "      --croptop, --cropbottom, --cropleft, --cropright\n"
-        "                         crop input by given pixels before resizing\n"
-        "  -S, --sharpness        [0 to 2] sharpness of images (default: 0).\n"
-        "                          Note: lower values make the video sharper.\n"
-        "  -K, --keyint           [1 to 65536] keyframe interval (default: 64)\n"
-        "\n"
-        "Video transfer options:\n"
-        "  --pp                   Video Postprocessing, denoise, deblock, deinterlacer\n"
-            "                          use --pp help for a list of available filters.\n"
-        "  -C, --contrast         [0.1 to 10.0] contrast correction (default: 1.0)\n"
-            "                          Note: lower values make the video darker.\n"
-        "  -B, --brightness       [-1.0 to 1.0] brightness correction (default: 0.0)\n"
-            "                          Note: lower values make the video darker.\n"
-        "  -G, --gamma            [0.1 to 10.0] gamma correction (default: 1.0)\n"
-        "                          Note: lower values make the video darker.\n"
-        "  -Z, --saturation       [0.1 to 10.0] saturation correction (default: 1.0)\n"
-        "                          Note: lower values make the video grey.\n"
-        "\n"
-        "Audio output options:\n"
-        "  -a, --audioquality     [-2 to 10] encoding quality for audio (default: 1)\n"
-        "                                    use higher values for better quality\n"
-        "  -A, --audiobitrate     [32 to 500] encoding bitrate for audio (kb/s)\n"
-        "  -c, --channels         set number of output channels\n"
-        "  -H, --samplerate       set output samplerate (in Hz)\n"
-        "      --nosound          disable the sound from input\n"
-        "\n"
-        "Input options:\n"
-        "      --deinterlace      force deinterlace, otherwise only material\n"
-        "                          marked as interlaced will be deinterlaced\n"
-        "      --vhook            you can use ffmpeg's vhook system, example:\n"
-        "        ffmpeg2theora --vhook '/path/watermark.so -f wm.gif' input.dv\n"
-        "  -f, --format           specify input format\n"
-        "      --inputfps fps     override input fps\n"
-        "      --audiostream id   by default the last audio stream is selected,\n"
-        "                          use this to select another audio stream\n"
-        "      --sync             use A/V sync from input container. Since this does\n"
-        "                          not work with all input format you have to manually\n"
-        "                          enable it if you have issues with A/V sync\n"
-        "\n"
-#ifdef HAVE_KATE
-        "Subtitles options:\n"
-        "      --subtitles file                 use subtitles from the given file (SubRip (.srt) format)\n"
-        "      --subtitles-encoding encoding    set encoding of the subtitles file\n"
-        "             supported are " SUPPORTED_ENCODINGS "\n"
-        "      --subtitles-language language    set subtitles language (de, en_GB, etc)\n"
-        "      --subtitles-category category    set subtitles category (default \"subtitles\")\n"
-        "\n"
-#endif
-        "Metadata options:\n"
-        "      --artist           Name of artist (director)\n"
-        "      --title            Title\n"
-        "      --date             Date\n"
-        "      --location         Location\n"
-        "      --organization     Name of organization (studio)\n"
-        "      --copyright        Copyright\n"
-        "      --license          License\n"
-        "      --contact          Contact link\n"
-        "\n"
-        "Other options:\n"
-#ifndef _WIN32
-        "      --nice n           set niceness to n\n"
-#endif
-        "  -P, --pid fname        write the process' id to a file\n"
-        "  -h, --help             this message\n"
-        "\n"
-        "Examples:\n"
-        "  ffmpeg2theora videoclip.avi (will write output to videoclip.ogv)\n"
-        "\n"
-        "  ffmpeg2theora videoclip.avi --subtitles subtitles.srt (same, with subtitles)\n"
-        "\n"
-        "  cat something.dv | ffmpeg2theora -f dv -o output.ogv -\n"
-        "\n"
-        "  Encode a series of images:\n"
-        "    ffmpeg2theora -f image2 frame%%06d.png -o output.ogv\n"
-        "\n"
-#if 0
-        "  Live streaming from V4L Device:\n"
-        "    ffmpeg2theora  /dev/video0 -fps 15 -x 160 -y 128 -o - \\\n"
-        "     | oggfwd iccast2server 8000 password /theora.ogv\n"
-        "\n"
-#endif
-        "  Live encoding from a DV camcorder (needs a fast machine):\n"
-        "    dvgrab - | ffmpeg2theora -f dv -x 352 -y 288 -o output.ogv -\n"
-        "\n"
-        "  Live encoding and streaming to icecast server:\n"
-        "    dvgrab --format raw - \\\n"
-        "     | ffmpeg2theora -f dv -x 160 -y 128 -o /dev/stdout - \\\n"
-        "     | oggfwd iccast2server 8000 password /theora.ogv\n"
-        "\n"
-        );
-    exit (0);
-}
-
-int main (int argc, char **argv){
-    int  n;
-    int  outputfile_set=0;
-    char outputfile_name[255];
-    char inputfile_name[255];
-    char *str_ptr;
-
-    static int flag = -1;
-    static int metadata_flag = 0;
-
-    AVInputFormat *input_fmt = NULL;
-    AVFormatParameters *formatParams = NULL;
-
-    int c,long_option_index;
-    const char *optstring = "P:o:k:f:F:x:y:v:V:a:A:S:K:d:H:c:G:Z:C:B:p:N:s:e:D:h::";
-    struct option options [] = {
-      {"pid",required_argument,NULL, 'P'},
-      {"output",required_argument,NULL,'o'},
-      {"skeleton",no_argument,NULL,'k'},
-      {"no-skeleton",no_argument,&flag,NOSKELETON},
-      {"format",required_argument,NULL,'f'},
-      {"width",required_argument,NULL,'x'},
-      {"height",required_argument,NULL,'y'},
-      {"videoquality",required_argument,NULL,'v'},
-      {"videobitrate",required_argument,NULL,'V'},
-      {"audioquality",required_argument,NULL,'a'},
-      {"audiobitrate",required_argument,NULL,'A'},
-      {"sharpness",required_argument,NULL,'S'},
-      {"keyint",required_argument,NULL,'K'},
-      {"deinterlace",0,&flag,DEINTERLACE_FLAG},
-      {"pp",required_argument,&flag,PP_FLAG},
-      {"samplerate",required_argument,NULL,'H'},
-      {"channels",required_argument,NULL,'c'},
-      {"gamma",required_argument,NULL,'G'},
-      {"brightness",required_argument,NULL,'B'},
-      {"contrast",required_argument,NULL,'C'},
-      {"saturation",required_argument,NULL,'Z'},
-      {"nosound",0,&flag,NOSOUND_FLAG},
-      {"vhook",required_argument,&flag,VHOOK_FLAG},
-      {"framerate",required_argument,NULL,'F'},
-      {"aspect",required_argument,&flag,ASPECT_FLAG},
-      {"v2v-preset",required_argument,NULL,'p'},
-      {"nice",required_argument,NULL,'N'},
-      {"croptop",required_argument,&flag,CROPTOP_FLAG},
-      {"cropbottom",required_argument,&flag,CROPBOTTOM_FLAG},
-      {"cropright",required_argument,&flag,CROPRIGHT_FLAG},
-      {"cropleft",required_argument,&flag,CROPLEFT_FLAG},
-      {"inputfps",required_argument,&flag,INPUTFPS_FLAG},
-      {"audiostream",required_argument,&flag,AUDIOSTREAM_FLAG},
-      {"subtitles",required_argument,&flag,SUBTITLES_FLAG},
-      {"subtitles-encoding",required_argument,&flag,SUBTITLES_ENCODING_FLAG},
-      {"subtitles-language",required_argument,&flag,SUBTITLES_LANGUAGE_FLAG},
-      {"subtitles-category",required_argument,&flag,SUBTITLES_CATEGORY_FLAG},
-      {"starttime",required_argument,NULL,'s'},
-      {"endtime",required_argument,NULL,'e'},
-      {"sync",0,&flag,SYNC_FLAG},
-      {"optimize",0,&flag,OPTIMIZE_FLAG},
-      {"speedlevel",required_argument,&flag,SPEEDLEVEL_FLAG},
-      {"frontend",0,&flag,FRONTEND_FLAG},
-
-      {"artist",required_argument,&metadata_flag,10},
-      {"title",required_argument,&metadata_flag,11},
-      {"date",required_argument,&metadata_flag,12},
-      {"location",required_argument,&metadata_flag,13},
-      {"organization",required_argument,&metadata_flag,14},
-      {"copyright",required_argument,&metadata_flag,15},
-      {"license",required_argument,&metadata_flag,16},
-      {"contact",required_argument,&metadata_flag,17},
-      {"source-hash",required_argument,&metadata_flag,18},
-
-      {"help",0,NULL,'h'},
-      {NULL,0,NULL,0}
-    };
-
-    char pidfile_name[255] = { '\0' };
-    FILE *fpid = NULL;
-
-    ff2theora convert = ff2theora_init ();
-    avcodec_register_all();
-    avdevice_register_all();
-    av_register_all();
-
-    if (argc == 1){
-        print_usage ();
-    }
-    // set some variables;
-    init_info(&info);
-    theora_comment_init (&info.tc);
-
-    while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
-        switch(c)
-        {
-            case 0:
-                if (flag) {
-                    switch (flag)
-                    {
-                        case DEINTERLACE_FLAG:
-                            convert->deinterlace = 1;
-                            flag = -1;
-                            break;
-                        case PP_FLAG:
-                            if(!strcmp(optarg, "help")) {
-                                fprintf(stdout, pp_help);
-                                exit(1);
-                            }
-                            snprintf(convert->pp_mode,sizeof(convert->pp_mode),"%s",optarg);
-                            flag = -1;
-                            break;
-                        case VHOOK_FLAG:
-                            convert->vhook = 1;
-                            add_frame_hooker(optarg);
-                            flag = -1;
-                            break;
-
-                        case SYNC_FLAG:
-                            convert->sync = 1;
-                            flag = -1;
-                            break;
-                        case NOSOUND_FLAG:
-                            convert->disable_audio = 1;
-                            flag = -1;
-                            break;
-                        case OPTIMIZE_FLAG:
-                            info.speed_level = 0;
-                            flag = -1;
-                            break;
-                        case SPEEDLEVEL_FLAG:
-                          info.speed_level = atoi(optarg);
-                            flag = -1;
-                            break;
-                        case FRONTEND_FLAG:
-                            info.frontend = 1;
-                            flag = -1;
-                            break;
-                        /* crop */
-                        case CROPTOP_FLAG:
-                            convert->frame_topBand = crop_check(convert,"top",optarg);
-                            flag = -1;
-                            break;
-                        case CROPBOTTOM_FLAG:
-                            convert->frame_bottomBand = crop_check(convert,"bottom",optarg);
-                            flag = -1;
-                            break;
-                        case CROPRIGHT_FLAG:
-                            convert->frame_rightBand = crop_check(convert,"right",optarg);
-                            flag = -1;
-                            break;
-                        case CROPLEFT_FLAG:
-                            convert->frame_leftBand = crop_check(convert,"left",optarg);
-                            flag = -1;
-                            break;
-                        case ASPECT_FLAG:
-                            convert->frame_aspect = aspect_check(optarg);
-                            flag = -1;
-                            break;
-                        case INPUTFPS_FLAG:
-                            convert->force_input_fps = atof(optarg);
-                            flag = -1;
-                            break;
-                        case AUDIOSTREAM_FLAG:
-                            convert->audiostream = atoi(optarg);
-                            flag = -1;
-                            break;
-                        case NOSKELETON:
-                            info.with_skeleton=0;
-                            break;
-#ifdef HAVE_KATE
-                        case SUBTITLES_FLAG:
-                            set_subtitles_file(convert,optarg);
-                            flag = -1;
-                            info.with_kate=1;
-                            break;
-                        case SUBTITLES_ENCODING_FLAG:
-                            if (!strcmp(optarg,"utf-8")) set_subtitles_encoding(convert,ENC_UTF8);
-                            if (!strcmp(optarg,"utf8")) set_subtitles_encoding(convert,ENC_UTF8);
-                            else if (!strcmp(optarg,"iso-8859-1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
-                            else if (!strcmp(optarg,"latin1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
-                            else report_unknown_subtitle_encoding(optarg);
-                            flag = -1;
-                            break;
-                        case SUBTITLES_LANGUAGE_FLAG:
-                            if (strlen(optarg)>15) {
-                              fprintf(stderr, "WARNING - language is limited to 15 characters, and will be truncated\n");
-                            }
-                            set_subtitles_language(convert,optarg);
-                            flag = -1;
-                            break;
-                        case SUBTITLES_CATEGORY_FLAG:
-                            if (strlen(optarg)>15) {
-                              fprintf(stderr, "WARNING - category is limited to 15 characters, and will be truncated\n");
-                            }
-                            set_subtitles_category(convert,optarg);
-                            flag = -1;
-                            break;
-#else
-                        case SUBTITLES_FLAG:
-                        case SUBTITLES_ENCODING_FLAG:
-                        case SUBTITLES_LANGUAGE_FLAG:
-                        case SUBTITLES_CATEGORY_FLAG:
-                            fprintf(stderr, "WARNING - Kate support not compiled in, subtitles will not be output\n"
-                                            "        - install libkate and rebuild ffmpeg2theora for subtitle support\n");
-                            break;
-#endif
-                    }
-                }
-
-                /* metadata */
-                if (metadata_flag){
-                    switch(metadata_flag) {
-                        case 10:
-                            theora_comment_add_tag(&info.tc, "ARTIST", optarg);
-                            break;
-                        case 11:
-                            theora_comment_add_tag(&info.tc, "TITLE", optarg);
-                            break;
-                        case 12:
-                            theora_comment_add_tag(&info.tc, "DATE", optarg);
-                            break;
-                        case 13:
-                            theora_comment_add_tag(&info.tc, "LOCATION", optarg);
-                            break;
-                        case 14:
-                            theora_comment_add_tag(&info.tc, "ORGANIZATION", optarg);
-                            break;
-                        case 15:
-                            theora_comment_add_tag(&info.tc, "COPYRIGHT", optarg);
-                            break;
-                        case 16:
-                            theora_comment_add_tag(&info.tc, "LICENSE", optarg);
-                            break;
-                        case 17:
-                            theora_comment_add_tag(&info.tc, "CONTACT", optarg);
-                            break;
-                        case 18:
-                            theora_comment_add_tag(&info.tc, "SOURCE HASH", optarg);
-                            break;
-                    }
-                    metadata_flag=0;
-                }
-                break;
-            case 'e':
-                convert->end_time = atoi(optarg);
-                break;
-            case 's':
-                convert->start_time = atoi(optarg);
-                break;
-            case 'o':
-                snprintf(outputfile_name,sizeof(outputfile_name),"%s",optarg);
-                outputfile_set=1;
-                break;
-            case 'k':
-                info.with_skeleton=1;
-                break;
-            case 'P':
-                sprintf(pidfile_name,optarg);
-                break;
-            case 'f':
-                input_fmt=av_find_input_format(optarg);
-                break;
-            case 'x':
-                convert->picture_width=atoi(optarg);
-                break;
-            case 'y':
-                convert->picture_height=atoi(optarg);
-                break;
-            case 'v':
-                convert->video_quality = rint(atof(optarg)*6.3);
-                if(convert->video_quality <0 || convert->video_quality >63){
-                        fprintf(stderr,"Only values from 0 to 10 are valid for video quality.\n");
-                        exit(1);
-                }
-                convert->video_bitrate=0;
-                break;
-            case 'V':
-                convert->video_bitrate=rint(atof(optarg)*1000);
-                if (convert->video_bitrate < 1) {
-                    fprintf(stderr, "Only values from 1 to 16000 are valid for video bitrate (in kb/s).\n");
-                    exit(1);
-                }
-                convert->video_quality=0;
-                break;
-            case 'a':
-                convert->audio_quality=atof(optarg);
-                if(convert->audio_quality<-2 || convert->audio_quality>10){
-                    fprintf(stderr,"Only values from -2 to 10 are valid for audio quality.\n");
-                    exit(1);
-                }
-                convert->audio_bitrate=0;
-                break;
-            case 'A':
-                convert->audio_bitrate=atof(optarg)*1000;
-                if(convert->audio_bitrate<0){
-                    fprintf(stderr,"Only values >0 are valid for audio bitrate.\n");
-                    exit(1);
-                }
-                convert->audio_quality = -990;
-                break;
-            case 'G':
-                convert->video_gamma = atof(optarg);
-                break;
-            case 'C':
-                convert->video_contr = atof(optarg);
-                break;
-            case 'Z':
-                convert->video_satur = atof(optarg);
-                break;
-            case 'B':
-                convert->video_bright = atof(optarg);
-                break;
-            case 'S':
-                convert->sharpness = atoi(optarg);
-                if (convert->sharpness < 0 || convert->sharpness > 2) {
-                    fprintf (stderr, "Only values from 0 to 2 are valid for sharpness.\n");
-                    exit(1);
-                }
-                break;
-            case 'K':
-                convert->keyint = atoi(optarg);
-                if (convert->keyint < 1 || convert->keyint > 65536) {
-                    fprintf (stderr, "Only values from 1 to 65536 are valid for keyframe interval.\n");
-                    exit(1);
-                }
-                break;
-            case 'H':
-                convert->sample_rate=atoi(optarg);
-                break;
-            case 'F':
-                convert->framerate_new = get_framerate(optarg);
-                break;
-            case 'c':
-                convert->channels=atoi(optarg);
-                if(convert->channels <= 0) {
-                  fprintf (stderr, "You can not have less than one audio channel.\n");
-                  exit(1);
-                }
-                break;
-            case 'p':
-                //v2v presets
-                if(!strcmp(optarg, "info")){
-                    print_presets_info();
-                    exit(1);
-                }
-                else if(!strcmp(optarg, "pro")){
-                    //need a way to set resize here. and not later
-                    convert->preset=V2V_PRESET_PRO;
-                    convert->video_quality = rint(7*6.3);
-                    convert->audio_quality = 3.00;
-                    convert->sharpness = 0;
-                    info.speed_level = 0;
-                }
-                else if(!strcmp(optarg,"preview")){
-                    //need a way to set resize here. and not later
-                    convert->preset=V2V_PRESET_PREVIEW;
-                    convert->video_quality = rint(5*6.3);
-                    convert->audio_quality = 1.00;
-                    convert->sharpness = 2;
-                    info.speed_level = 0;
-                }
-                else if(!strcmp(optarg,"videobin")){
-                    convert->preset=V2V_PRESET_VIDEOBIN;
-                    convert->video_bitrate=rint(600*1000);
-                    convert->video_quality = 0;
-                    convert->audio_quality = 3.00;
-                    convert->sharpness = 2;
-                    info.speed_level = 0;
-                }
-                else if(!strcmp(optarg,"padma")){
-                    convert->preset=V2V_PRESET_PADMA;
-                    convert->video_quality = rint(5*6.3);
-                    convert->audio_quality = 3.00;
-                    convert->sharpness = 0;
-                    info.speed_level = 0;
-                }
-                else if(!strcmp(optarg,"padma-stream")){
-                    convert->preset=V2V_PRESET_PADMASTREAM;
-                    convert->video_bitrate=rint(180*1000);
-                    convert->video_quality = 0;
-                    convert->audio_quality = -1.00;
-                    convert->sample_rate=44100;
-                    convert->sharpness = 2;
-                    convert->keyint = 16;
-                    info.speed_level = 0;
-                }
-                else{
-                    fprintf(stderr,"\nUnknown preset.\n\n");
-                    print_presets_info();
-                    exit(1);
-                }
-                break;
-            case 'N':
-                n = atoi(optarg);
-                if (n) {
-#ifndef _WIN32
-                    if (nice(n)<0) {
-                        fprintf(stderr,"Error setting `%d' for niceness.", n);
-                    }
-#endif
-                }
-                break;
-            case 'h':
-                print_usage ();
-                exit(1);
-        }
-    }
-
-    while(optind<argc){
-        /* assume that anything following the options must be a filename */
-        snprintf(inputfile_name,sizeof(inputfile_name),"%s",argv[optind]);
-        if(!strcmp(inputfile_name,"-")){
-            snprintf(inputfile_name,sizeof(inputfile_name),"pipe:");
-        }
-        if(outputfile_set!=1){
-            /* reserve 4 bytes in the buffer for the `.ogv' extension */
-            snprintf(outputfile_name, sizeof(outputfile_name) - 4, "%s", argv[optind]);
-            if((str_ptr = strrchr(outputfile_name, '.'))) {
-              sprintf(str_ptr, ".ogv");
-              if(!strcmp(inputfile_name, outputfile_name)){
-                snprintf(outputfile_name, sizeof(outputfile_name), "%s.ogv", inputfile_name);
-              }
-            }
-            else {
-                 snprintf(outputfile_name, sizeof(outputfile_name), "%s.ogv", outputfile_name);
-            }
-            outputfile_set=1;
-        }
-        optind++;
-    }
-
-#ifdef VIDEO4LINUX_ENABLED
-    if(formatParams != NULL) {
-        formatParams->channel = 0;
-        formatParams->width = PAL_HALF_WIDTH;
-        formatParams->height = PAL_HALF_HEIGHT;
-        if(convert->picture_width)
-            formatParams->width = convert->picture_width;
-        if(convert->picture_height)
-            formatParams->height = convert->picture_height;
-
-        formatParams->time_base.den = 25;
-        formatParams->time_base.num = 1;
-        if(convert->force_input_fps) {
-
-            formatParams->time_base.den = convert->force_input_fps * 1000;
-            formatParams->time_base.num = 1000;
-
-        }
-        formatParams->standard = "pal";
-        input_fmt = av_find_input_format("video4linux");
-        sprintf(inputfile_name,"");
-    }
-#endif
-
-    //FIXME: is using_stdin still neded? is it needed as global variable?
-    using_stdin |= !strcmp(inputfile_name, "pipe:" ) ||
-                   !strcmp( inputfile_name, "/dev/stdin" );
-
-    if(outputfile_set!=1){
-        fprintf(stderr,"You have to specify an output file with -o output.ogv.\n");
-        exit(1);
-    }
-
-    /* could go, but so far no player supports offset_x/y */
-    if(convert->picture_width % 8 ||  convert->picture_height % 8){
-        fprintf(stderr,"Output size must be a multiple of 8 for now.\n");
-        exit(1);
-    }
-    /*
-    if(convert->picture_width % 4 ||  convert->picture_height % 4){
-        fprintf(stderr,"Output width and height size must be a multiple of 2.\n");
-        exit(1);
-    }
-    */
-    if(convert->end_time>0 && convert->end_time <= convert->start_time){
-        fprintf(stderr,"End time has to be bigger than start time.\n");
-        exit(1);
-    }
-
-    if (*pidfile_name)
-    {
-        fpid = fopen(pidfile_name, "w");
-        if (fpid != NULL)
-        {
-            fprintf(fpid, "%i", getpid());
-            fclose(fpid);
-        }
-    }
-
-    oggmux_setup_kate_streams(&info, convert->n_kate_streams);
-
-    for (n=0; n<convert->n_kate_streams; ++n) {
-        ff2theora_kate_stream *ks=convert->kate_streams+n;
-        if (load_subtitles(ks)>=0) {
-          printf("Muxing Kate stream %d from %s as %s %s\n",
-              n,ks->filename,
-              ks->subtitles_language[0]?ks->subtitles_language:"<unknown language>",
-              ks->subtitles_category[0]?ks->subtitles_category:"subtitles");
-        }
-    }
-
-    if (av_open_input_file(&convert->context, inputfile_name, input_fmt, 0, formatParams) >= 0){
-        if (av_find_stream_info (convert->context) >= 0){
-#ifdef WIN32
-                if(!strcmp(outputfile_name,"-") || !strcmp(outputfile_name,"/dev/stdout")){
-                    _setmode(_fileno(stdout), _O_BINARY);
-                    info.outfile = stdout;
-                }
-                else {
-                    info.outfile = fopen(outputfile_name,"wb");
-                }
-#else
-                if(!strcmp(outputfile_name,"-")){
-                    snprintf(outputfile_name,sizeof(outputfile_name),"/dev/stdout");
-                }
-                info.outfile = fopen(outputfile_name,"wb");
-#endif
-                if(info.frontend) {
-                  fprintf(stderr, "\nf2t ;duration: %d;\n", convert->context->duration / AV_TIME_BASE);
-                }
-                else {
-                  dump_format (convert->context, 0,inputfile_name, 0);
-                }
-                if(convert->disable_audio){
-                    fprintf(stderr,"  [audio disabled].\n");
-                }
-                if(convert->sync){
-                    fprintf(stderr,"  Use A/V Sync from input container.\n");
-                }
-
-                convert->pts_offset =
-                    (double) convert->context->start_time / AV_TIME_BASE;
-                if(!info.outfile) {
-                    if(info.frontend)
-                        fprintf(stderr, "\nf2t ;result: Unable to open output file.;\n");
-                    else
-                      fprintf (stderr,"\nUnable to open output file `%s'.\n", outputfile_name);
-                    return(1);
-                }
-                if (convert->context->duration != AV_NOPTS_VALUE) {
-                  info.duration = convert->context->duration / AV_TIME_BASE;
-                }
-                ff2theora_output (convert);
-                convert->audio_index =convert->video_index = -1;
-            }
-            else{
-              if(info.frontend)
-                  fprintf(stderr, "\nf2t ;result: input format not suported.;\n");
-              else
-                  fprintf (stderr,"\nUnable to decode input.\n");
-              return(1);
-            }
-            av_close_input_file (convert->context);
-        }
-        else{
-            fprintf (stderr, "\nFile `%s' does not exist or has an unknown data format.\n", inputfile_name);
-            return(1);
-        }
-    ff2theora_close (convert);
-    fprintf(stderr,"\n");
-
-    if (*pidfile_name)
-        unlink(pidfile_name);
-
-    if(info.frontend)
-        fprintf(stderr, "\nf2t ;result: ok;\n");
-
-    return(0);
-}

Modified: trunk/ffmpeg2theora/get_libkate.sh
===================================================================
--- trunk/ffmpeg2theora/get_libkate.sh	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/get_libkate.sh	2008-05-23 17:56:21 UTC (rev 14950)
@@ -6,12 +6,12 @@
 which wget >& /dev/null
 if [ $? -eq 0 ]
 then
-  wget "$baseurl"
+  test -e "libkate-$version.tar.gz" || wget "$baseurl"
 else
   which curl >& /dev/null
   if [ $? -eq 0 ]
   then
-    curl "$baseurl"
+    test -e "libkate-$version.tar.gz" || curl "$baseurl" -o "libkate-$version.tar.gz"
   else
     echo "Neither wget nor curl were found, cannot download libkate"
     exit 1

Copied: trunk/ffmpeg2theora/src/ffmpeg2theora.c (from rev 14949, trunk/ffmpeg2theora/ffmpeg2theora.c)
===================================================================
--- trunk/ffmpeg2theora/src/ffmpeg2theora.c	                        (rev 0)
+++ trunk/ffmpeg2theora/src/ffmpeg2theora.c	2008-05-23 17:56:21 UTC (rev 14950)
@@ -0,0 +1,1769 @@
+/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
+/*
+ * ffmpeg2theora.c -- Convert ffmpeg supported a/v files to  Ogg Theora / Ogg Vorbis
+ * Copyright (C) 2003-2008 <j at v2v.cc>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <math.h>
+#include <errno.h>
+
+#include "libavformat/avformat.h"
+#include "libavdevice/avdevice.h"
+#include "libswscale/swscale.h"
+#include "libpostproc/postprocess.h"
+
+#include "theora/theora.h"
+#include "vorbis/codec.h"
+#include "vorbis/vorbisenc.h"
+
+#ifdef WIN32
+#include "fcntl.h"
+#endif
+
+#include "theorautils.h"
+#include "subtitles.h"
+#include "ffmpeg2theora.h"
+
+#ifdef __linux__
+  #define VIDEO4LINUX_ENABLED
+#endif
+
+enum {
+  NULL_FLAG,
+  DEINTERLACE_FLAG,
+  OPTIMIZE_FLAG,
+  SYNC_FLAG,
+  NOSOUND_FLAG,
+  CROPTOP_FLAG,
+  CROPBOTTOM_FLAG,
+  CROPRIGHT_FLAG,
+  CROPLEFT_FLAG,
+  ASPECT_FLAG,
+  INPUTFPS_FLAG,
+  AUDIOSTREAM_FLAG,
+  SUBTITLES_FLAG,
+  SUBTITLES_ENCODING_FLAG,
+  SUBTITLES_LANGUAGE_FLAG,
+  SUBTITLES_CATEGORY_FLAG,
+  VHOOK_FLAG,
+  FRONTEND_FLAG,
+  SPEEDLEVEL_FLAG,
+  PP_FLAG,
+  NOSKELETON
+} F2T_FLAGS;
+
+enum {
+  V2V_PRESET_NONE,
+  V2V_PRESET_PRO,
+  V2V_PRESET_PREVIEW,
+  V2V_PRESET_VIDEOBIN,
+  V2V_PRESET_PADMA,
+  V2V_PRESET_PADMASTREAM,
+} F2T_PRESETS;
+
+
+#define PAL_HALF_WIDTH 384
+#define PAL_HALF_HEIGHT 288
+#define NTSC_HALF_WIDTH 320
+#define NTSC_HALF_HEIGHT 240
+
+#define PAL_FULL_WIDTH 720
+#define PAL_FULL_HEIGHT 576
+#define NTSC_FULL_WIDTH 720
+#define NTSC_FULL_HEIGHT 480
+
+
+static int sws_flags = SWS_BICUBIC;
+
+oggmux_info info;
+
+static int using_stdin = 0;
+
+
+/**
+ * Allocate and initialise an AVFrame.
+ */
+AVFrame *frame_alloc (int pix_fmt, int width, int height) {
+    AVFrame *picture;
+    uint8_t *picture_buf;
+    int size;
+
+    picture = avcodec_alloc_frame ();
+    if (!picture)
+        return NULL;
+    size = avpicture_get_size (pix_fmt, width, height);
+    picture_buf = av_malloc (size);
+    if (!picture_buf){
+        av_free (picture);
+        return NULL;
+    }
+    avpicture_fill ((AVPicture *) picture, picture_buf,
+            pix_fmt, width, height);
+    return picture;
+}
+
+/**
+ * initialize ff2theora with default values
+ * @return ff2theora struct
+ */
+ff2theora ff2theora_init (){
+    ff2theora this = calloc (1, sizeof (*this));
+    if (this != NULL){
+        this->disable_audio=0;
+        this->video_index = -1;
+        this->audio_index = -1;
+        this->start_time=0;
+        this->end_time=0; /* 0 denotes no end time set */
+
+        // audio
+        this->sample_rate = -1;  // samplerate hmhmhm
+        this->channels = -1;
+        this->audio_quality = 1.00;// audio quality 1
+        this->audio_bitrate=0;
+        this->audiostream = -1;
+
+        // video
+        this->picture_width=0;      // set to 0 to not resize the output
+        this->picture_height=0;      // set to 0 to not resize the output
+        this->video_quality=rint(5*6.3); // video quality 5
+        this->video_bitrate=0;
+        this->sharpness=0;
+        this->keyint=64;
+        this->force_input_fps=0;
+        this->sync=0;
+        this->aspect_numerator=0;
+        this->aspect_denominator=0;
+        this->frame_aspect=0;
+        this->deinterlace=0; // auto by default, if input is flaged as interlaced it will deinterlace.
+        this->vhook=0;
+        this->framerate_new.num = -1;
+        this->framerate_new.den = 1;
+
+        this->frame_topBand=0;
+        this->frame_bottomBand=0;
+        this->frame_leftBand=0;
+        this->frame_rightBand=0;
+
+        this->n_kate_streams=0;
+        this->kate_streams=NULL;
+
+        this->pix_fmt = PIX_FMT_YUV420P;
+
+        // ffmpeg2theora --nosound -f dv -H 32000 -S 0 -v 8 -x 384 -y 288 -G 1.5 input.dv
+        this->video_gamma  = 0.0;
+        this->video_bright = 0.0;
+        this->video_contr  = 0.0;
+        this->video_satur  = 1.0;
+
+        this->y_lut_used = 0;
+        this->uv_lut_used = 0;
+        this->y_lut[256];
+        this->uv_lut[256];
+    }
+    return this;
+}
+
+// gamma lookup table code
+
+static void y_lut_init(ff2theora this) {
+    int i;
+    double v;
+
+    double c = this->video_contr;
+    double b = this->video_bright;
+    double g = this->video_gamma;
+ 
+    if ((g < 0.01) || (g > 100.0)) g = 1.0;
+    if ((c < 0.01) || (c > 100.0)) c = 1.0;
+    if ((b < -1.0) || (b > 1.0))   b = 0.0;
+
+    if (g == 1.0 && c == 1.0 && b == 0.0) return;
+    this->y_lut_used = 1;
+
+    printf("  Video correction: gamma=%g, contrast=%g, brightness=%g\n", g, c, b);
+
+    g = 1.0 / g;    // larger values shall make brighter video.
+
+    for (i = 0; i < 256; i++) {
+        v = (double) i / 255.0;
+        v = c * v + b * 0.1;
+        if (v < 0.0) v = 0.0;
+        v = pow(v, g) * 255.0;    // mplayer's vf_eq2.c multiplies with 256 here, strange...
+
+        if (v >= 255)
+            this->y_lut[i] = 255;
+        else
+            this->y_lut[i] = (unsigned char)(v+0.5);
+    }
+}
+
+
+static void uv_lut_init(ff2theora this) {
+    int i;
+    double v, s;
+    s = this->video_satur;
+
+    if ((s < 0.0) || (s > 100.0)) s = 1.0;
+
+    if (s == 1.0) return;
+    this->uv_lut_used = 1;
+
+    printf("  Color correction: saturation=%g\n", s);
+
+    for (i = 0; i < 256; i++) {
+        v = 127.0 + (s * ((double)i - 127.0));
+        if (v < 0.0) v = 0.0;
+
+        if (v >= 255.0)
+            this->uv_lut[i] = 255;
+        else
+            this->uv_lut[i] = (unsigned char)(v+0.5);
+    }
+}
+
+static void lut_init(ff2theora this) {
+    y_lut_init(this);
+    uv_lut_init(this);
+}
+
+static void lut_apply(unsigned char *lut, unsigned char *src, unsigned char *dst, int width, int height, int stride) {
+    int x, y;
+
+    for (y = 0; y < height; y++) {
+        for (x = 0; x < width; x++) {
+            dst[x] = lut[src[x]];
+        }
+        src += stride;
+        dst += stride;
+    }
+}
+
+static void prepare_yuv_buffer(ff2theora this, yuv_buffer *yuv, AVFrame *output_buffered) {
+    /* pysical pages */
+    yuv->y_width = this->frame_width;
+    yuv->y_height = this->frame_height;
+    yuv->y_stride = output_buffered->linesize[0];
+
+    yuv->uv_width = this->frame_width / 2;
+    yuv->uv_height = this->frame_height / 2;
+    yuv->uv_stride = output_buffered->linesize[1];
+
+    yuv->y = output_buffered->data[0];
+    yuv->u = output_buffered->data[1];
+    yuv->v = output_buffered->data[2];
+    if (this->y_lut_used) {
+        lut_apply(this->y_lut, yuv->y, yuv->y, yuv->y_width, yuv->y_height, yuv->y_stride);
+    }
+    if (this->uv_lut_used) {
+        lut_apply(this->uv_lut, yuv->u, yuv->u, yuv->uv_width, yuv->uv_height, yuv->uv_stride);
+        lut_apply(this->uv_lut, yuv->v, yuv->v, yuv->uv_width, yuv->uv_height, yuv->uv_stride);
+    }
+}
+
+void ff2theora_output(ff2theora this) {
+    int i;
+    AVCodecContext *aenc = NULL;
+    AVCodecContext *venc = NULL;
+    AVStream *astream = NULL;
+    AVStream *vstream = NULL;
+    AVCodec *acodec = NULL;
+    AVCodec *vcodec = NULL;
+    pp_mode_t *ppMode = NULL;
+    pp_context_t *ppContext = NULL;
+    float frame_aspect;
+    double fps = 0.0;
+
+    if(this->audiostream >= 0 && this->context->nb_streams > this->audiostream) {
+        AVCodecContext *enc = this->context->streams[this->audiostream]->codec;
+        if (enc->codec_type == CODEC_TYPE_AUDIO) {
+            this->audio_index = this->audiostream;
+            fprintf(stderr,"  Using stream #0.%d as audio input\n",this->audio_index);
+        }
+        else {
+            fprintf(stderr,"  The selected stream is not audio, falling back to automatic selection\n");
+        }
+    }
+
+    for (i = 0; i < this->context->nb_streams; i++){
+        AVCodecContext *enc = this->context->streams[i]->codec;
+        switch (enc->codec_type){
+            case CODEC_TYPE_VIDEO:
+              if (this->video_index < 0)
+                    this->video_index = i;
+                break;
+            case CODEC_TYPE_AUDIO:
+                if (this->audio_index < 0 && !this->disable_audio)
+                    this->audio_index = i;
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (this->video_index >= 0){
+        vstream = this->context->streams[this->video_index];
+        venc = this->context->streams[this->video_index]->codec;
+        vcodec = avcodec_find_decoder (venc->codec_id);
+
+        fps = (double) vstream->r_frame_rate.num / vstream->r_frame_rate.den;
+        if (fps > 10000)
+            fps /= 1000;
+
+        if(this->force_input_fps)
+            fps=this->force_input_fps;
+        if (vcodec == NULL || avcodec_open (venc, vcodec) < 0) {
+            this->video_index = -1;
+        }
+        this->fps = fps;
+
+
+        if(this->preset == V2V_PRESET_PREVIEW){
+            if(abs(this->fps-30)<1 && (venc->width!=NTSC_HALF_WIDTH || venc->height!=NTSC_HALF_HEIGHT) ){
+                this->picture_width=NTSC_HALF_WIDTH;
+                this->picture_height=NTSC_HALF_HEIGHT;
+            }
+            else {
+                this->picture_width=PAL_HALF_WIDTH;
+                this->picture_height=PAL_HALF_HEIGHT;
+            }
+        }
+        else if(this->preset == V2V_PRESET_PRO){
+            if(abs(this->fps-30)<1 && (venc->width!=NTSC_FULL_WIDTH || venc->height!=NTSC_FULL_HEIGHT) ){
+                this->picture_width=NTSC_FULL_WIDTH;
+                this->picture_height=NTSC_FULL_HEIGHT;
+            }
+            else {
+                this->picture_width=PAL_FULL_WIDTH;
+                this->picture_height=PAL_FULL_HEIGHT;
+            }
+        }
+         else if(this->preset == V2V_PRESET_PADMA){
+             int width=venc->width-this->frame_leftBand-this->frame_rightBand;
+             int height=venc->height-this->frame_topBand-this->frame_bottomBand;
+             if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
+               height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
+             }
+             if(this->frame_aspect == 0)
+               this->frame_aspect = (float)width/height;
+             if(this->frame_aspect <= 1.5) {
+               if(width > 640 || height > 480) {
+                 //4:3 640 x 480
+                 this->picture_width=640;
+                 this->picture_height=480;
+               }
+               else {
+                 this->picture_width=width;
+                 this->picture_height=height;
+               }
+             }
+             else {
+               if(width > 640 || height > 360) {
+                 //16:9 640 x 360
+                 this->picture_width=640;
+                 this->picture_height=360;
+               }
+               else {
+                 this->picture_width=width;
+                 this->picture_height=height;
+               }
+             }
+
+         }
+         else if(this->preset == V2V_PRESET_PADMASTREAM){
+             int width=venc->width-this->frame_leftBand-this->frame_rightBand;
+             int height=venc->height-this->frame_topBand-this->frame_bottomBand;
+             if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
+               height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
+             }
+             if(this->frame_aspect == 0)
+               this->frame_aspect = (float)width/height;
+             if(this->frame_aspect <= 1.5) {
+                 this->picture_width=128;
+                 this->picture_height=96;
+             }
+             else {
+                 this->picture_width=128;
+                 this->picture_height=72;
+             }
+         }
+        else if(this->preset == V2V_PRESET_VIDEOBIN){
+            int width=venc->width-this->frame_leftBand-this->frame_rightBand;
+            int height=venc->height-this->frame_topBand-this->frame_bottomBand;
+            if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
+              height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
+            }
+            if( ((float)width /height) <= 1.5) {
+              if(width > 448) {
+                //4:3 448 x 336
+                this->picture_width=448;
+                this->picture_height=336;
+              }
+              else {
+                this->picture_width=width;
+                this->picture_height=height;
+              }
+            }
+            else {
+              if(width > 512) {
+                //16:9 512 x 288
+                this->picture_width=512;
+                this->picture_height=288;
+              }
+              else {
+                this->picture_width=width;
+                this->picture_height=height;
+              }
+            }
+
+        }
+        if(this->picture_height==0 &&
+            (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){
+            this->picture_height=venc->height-
+                    this->frame_topBand-this->frame_bottomBand;
+        }
+        if(this->picture_width==0 &&
+            (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){
+            this->picture_width=venc->width-
+                    this->frame_leftBand-this->frame_rightBand;
+        }
+        //so frame_aspect is set on the commandline
+        if(this->frame_aspect != 0){
+            if(this->picture_height){
+                this->aspect_numerator = 10000*this->frame_aspect*this->picture_height;
+                this->aspect_denominator = 10000*this->picture_width;
+            }
+            else{
+                this->aspect_numerator = 10000*this->frame_aspect*venc->height;
+                this->aspect_denominator = 10000*venc->width;
+            }
+            av_reduce(&this->aspect_numerator,&this->aspect_denominator,this->aspect_numerator,this->aspect_denominator,10000);
+            frame_aspect=this->frame_aspect;
+        }
+        if(venc->sample_aspect_ratio.num!=0 && this->frame_aspect==0){
+            // just use the ratio from the input
+            this->aspect_numerator=venc->sample_aspect_ratio.num;
+            this->aspect_denominator=venc->sample_aspect_ratio.den;
+            // or we use ratio for the output
+            if(this->picture_height){
+                int width=venc->width-this->frame_leftBand-this->frame_rightBand;
+                int height=venc->height-this->frame_topBand-this->frame_bottomBand;
+                av_reduce(&this->aspect_numerator,&this->aspect_denominator,
+                venc->sample_aspect_ratio.num*width*this->picture_height,
+                venc->sample_aspect_ratio.den*height*this->picture_width,10000);
+                frame_aspect=(float)(this->aspect_numerator*this->picture_width)/
+                                (this->aspect_denominator*this->picture_height);
+            }
+            else{
+                frame_aspect=(float)(this->aspect_numerator*venc->width)/
+                                (this->aspect_denominator*venc->height);
+            }
+        }
+        if((float)this->aspect_numerator/this->aspect_denominator < 1.09){
+          this->aspect_numerator = 1;
+          this->aspect_denominator = 1;
+          frame_aspect=(float)(this->aspect_numerator*this->picture_width)/
+                          (this->aspect_denominator*this->picture_height);
+        }
+        if(this->aspect_denominator && frame_aspect){
+            fprintf(stderr,"  Pixel Aspect Ratio: %.2f/1 ",(float)this->aspect_numerator/this->aspect_denominator);
+            fprintf(stderr,"  Frame Aspect Ratio: %.2f/1\n",frame_aspect);
+        }
+
+        if (this->deinterlace==1)
+            fprintf(stderr,"  Deinterlace: on\n");
+
+        if (strcmp(this->pp_mode, "")) {
+          ppContext = pp_get_context(venc->width, venc->height, PP_FORMAT_420);
+          ppMode = pp_get_mode_by_name_and_quality(this->pp_mode, PP_QUALITY_MAX);
+          fprintf(stderr,"  Postprocessing: %s\n", this->pp_mode);
+        }
+
+        if(!this->picture_width)
+            this->picture_width = venc->width;
+        if(!this->picture_height)
+            this->picture_height = venc->height;
+
+        /* Theora has a divisible-by-sixteen restriction for the encoded video size */
+        /* scale the frame size up to the nearest /16 and calculate offsets */
+        this->frame_width = ((this->picture_width + 15) >>4)<<4;
+        this->frame_height = ((this->picture_height + 15) >>4)<<4;
+
+        this->frame_x_offset = 0;
+        this->frame_y_offset = 0;
+
+        if(this->frame_width > 0 || this->frame_height > 0){
+            this->sws_colorspace_ctx = sws_getContext(
+                          venc->width, venc->height, venc->pix_fmt,
+                          venc->width, venc->height, this->pix_fmt,
+                          sws_flags, NULL, NULL, NULL
+            );
+            this->sws_scale_ctx = sws_getContext(
+                          venc->width  - (this->frame_leftBand + this->frame_rightBand),
+                          venc->height  - (this->frame_topBand + this->frame_bottomBand),
+                          this->pix_fmt,
+                          this->frame_width, this->frame_height, this->pix_fmt,
+                          sws_flags, NULL, NULL, NULL
+            );
+            fprintf(stderr,"  Resize: %dx%d",venc->width,venc->height);
+            if(this->frame_topBand || this->frame_bottomBand ||
+            this->frame_leftBand || this->frame_rightBand){
+                fprintf(stderr," => %dx%d",
+                    venc->width-this->frame_leftBand-this->frame_rightBand,
+                    venc->height-this->frame_topBand-this->frame_bottomBand);
+            }
+            if(this->picture_width != (venc->width-this->frame_leftBand - this->frame_rightBand)
+                || this->picture_height != (venc->height-this->frame_topBand-this->frame_bottomBand))
+                fprintf(stderr," => %dx%d",this->picture_width, this->picture_height);
+            fprintf(stderr,"\n");
+        }
+
+        lut_init(this);
+    }
+    if (this->framerate_new.num > 0) {
+        fprintf(stderr,"  Resample Framerate: %0.2f => %0.2f\n",
+                        this->fps,(double)this->framerate_new.num / this->framerate_new.den);
+    }
+    if (this->audio_index >= 0){
+        astream = this->context->streams[this->audio_index];
+        aenc = this->context->streams[this->audio_index]->codec;
+        acodec = avcodec_find_decoder (aenc->codec_id);
+        if (this->channels < 1) {
+            if (aenc->channels > 2)
+                this->channels = 2;
+            else
+                this->channels = aenc->channels;
+        }
+        if(this->sample_rate==-1) {
+            this->sample_rate = aenc->sample_rate;
+        }
+        if (this->channels != aenc->channels && aenc->codec_id == CODEC_ID_AC3)
+            aenc->channels = this->channels;
+
+        if (acodec != NULL && avcodec_open (aenc, acodec) >= 0){
+            if(this->sample_rate != aenc->sample_rate || this->channels != aenc->channels){
+                this->audio_resample_ctx = audio_resample_init (this->channels,aenc->channels,this->sample_rate,aenc->sample_rate);
+                if(this->sample_rate!=aenc->sample_rate)
+                    fprintf(stderr,"  Resample: %dHz => %dHz\n",aenc->sample_rate,this->sample_rate);
+                if(this->channels!=aenc->channels)
+                    fprintf(stderr,"  Channels: %d => %d\n",aenc->channels,this->channels);
+            }
+            else{
+                this->audio_resample_ctx=NULL;
+            }
+        }
+        else{
+            this->audio_index = -1;
+        }
+    }
+
+    if (this->video_index >= 0 || this->audio_index >=0){
+        AVFrame *frame=NULL;
+        AVFrame *output=NULL;
+        AVFrame *output_tmp=NULL;
+        AVFrame *output_resized=NULL;
+        AVFrame *output_buffered=NULL;
+
+        AVPacket pkt;
+        int len;
+        int len1;
+        int got_picture;
+        int first = 1;
+        int e_o_s = 0;
+        int ret;
+        uint8_t *ptr;
+        int16_t *audio_buf= av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE);
+        int16_t *resampled= av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE);
+        int no_frames;
+
+        double framerate_add;
+        double framerate_tmpcount = 0;
+
+        if(this->video_index >= 0)
+            info.audio_only=0;
+        else
+            info.audio_only=1;
+
+        if(this->audio_index>=0)
+            info.video_only=0;
+        else
+            info.video_only=1;
+
+        if(!info.audio_only){
+            frame = frame_alloc(vstream->codec->pix_fmt,
+                            vstream->codec->width,vstream->codec->height);
+            output_tmp =frame_alloc(this->pix_fmt,
+                            vstream->codec->width,vstream->codec->height);
+            output =frame_alloc(this->pix_fmt,
+                            vstream->codec->width,vstream->codec->height);
+            output_resized =frame_alloc(this->pix_fmt,
+                            this->frame_width, this->frame_height);
+            output_buffered =frame_alloc(this->pix_fmt,
+                            this->frame_width, this->frame_height);
+
+            /* video settings here */
+            /* config file? commandline options? v2v presets? */
+
+            theora_info_init (&info.ti);
+
+            info.ti.width = this->frame_width;
+            info.ti.height = this->frame_height;
+            info.ti.frame_width = this->picture_width;
+            info.ti.frame_height = this->picture_height;
+            info.ti.offset_x = this->frame_x_offset;
+            info.ti.offset_y = this->frame_y_offset;
+            if(this->force_input_fps) {
+                info.ti.fps_numerator = 1000000 * (this->fps);    /* fps= numerator/denominator */
+                info.ti.fps_denominator = 1000000;
+            }
+            else {
+                if (this->framerate_new.num > 0) {
+                    // new framerate is interger only right now,
+                    // so denominator is always 1
+                    info.ti.fps_numerator = this->framerate_new.num;
+                    info.ti.fps_denominator = this->framerate_new.den;
+                }
+                else {
+                    info.ti.fps_numerator=vstream->r_frame_rate.num;
+                    info.ti.fps_denominator = vstream->r_frame_rate.den;
+                }
+            }
+
+            /* this is pixel aspect ratio */
+            info.ti.aspect_numerator=this->aspect_numerator;
+            info.ti.aspect_denominator=this->aspect_denominator;
+            // FIXME: is all input material with fps==25 OC_CS_ITU_REC_470BG?
+            // guess not, commandline option to select colorspace would be the best.
+            if((this->fps-25)<1)
+                info.ti.colorspace = OC_CS_ITU_REC_470BG;
+            else if(abs(this->fps-30)<1)
+                info.ti.colorspace = OC_CS_ITU_REC_470M;
+            else
+                info.ti.colorspace = OC_CS_UNSPECIFIED;
+
+            info.ti.target_bitrate = this->video_bitrate;
+            info.ti.quality = this->video_quality;
+            info.ti.dropframes_p = 0;
+            info.ti.keyframe_auto_p = 1;
+            info.ti.keyframe_frequency = this->keyint;
+            info.ti.keyframe_frequency_force = this->keyint;
+            info.ti.keyframe_data_target_bitrate = info.ti.target_bitrate * 1.5;
+            info.ti.keyframe_auto_threshold = 80;
+            info.ti.keyframe_mindistance = 8;
+            info.ti.noise_sensitivity = 1;
+            // range 0-2, 0 sharp, 2 less sharp,less bandwidth
+            info.ti.sharpness = this->sharpness;
+
+        }
+        /* audio settings here */
+        info.channels = this->channels;
+        info.sample_rate = this->sample_rate;
+        info.vorbis_quality = this->audio_quality * 0.1;
+        info.vorbis_bitrate = this->audio_bitrate;
+        /* subtitles */
+#ifdef HAVE_KATE
+        for (i=0; i<this->n_kate_streams; ++i) {
+            ff2theora_kate_stream *ks = this->kate_streams+i;
+            kate_info *ki = &info.kate_streams[i].ki;
+            kate_info_init(ki);
+            if (ks->num_subtitles > 0) {
+                kate_info_set_language(ki, ks->subtitles_language);
+                kate_info_set_category(ki, ks->subtitles_category[0]?ks->subtitles_category:"subtitles");
+                if(this->force_input_fps) {
+                    ki->gps_numerator = 1000000 * (this->fps);    /* fps= numerator/denominator */
+                    ki->gps_denominator = 1000000;
+                }
+                else {
+                    if (this->framerate_new.num > 0) {
+                        // new framerate is interger only right now, 
+                        // so denominator is always 1
+                        ki->gps_numerator = this->framerate_new.num;
+                        ki->gps_denominator = this->framerate_new.den;
+                    } 
+                    else {
+                        ki->gps_numerator=vstream->r_frame_rate.num;
+                        ki->gps_denominator = vstream->r_frame_rate.den;
+                    }
+                }
+                ki->granule_shift = 32;
+            }
+        }
+#endif
+        oggmux_init (&info);
+        /*seek to start time*/
+        if(this->start_time) {
+          av_seek_frame( this->context, -1, (int64_t)AV_TIME_BASE*this->start_time, 1);
+          /* discard subtitles by their end time, so we still have those that start before the start time,
+             but end after it */
+          for (i=0; i<this->n_kate_streams; ++i) {
+              ff2theora_kate_stream *ks=this->kate_streams+i;
+              while (ks->subtitles_count < ks->num_subtitles && ks->subtitles[ks->subtitles_count].t1 <= this->start_time) {
+                  /* printf("skipping subtitle %u\n", ks->subtitles_count); */
+                  ks->subtitles_count++;
+              }
+          }
+        }
+
+        if(info.audio_only && (this->end_time>0 || this->start_time>0)){
+            fprintf(stderr,"Sorry, right now start/end time does not work for audio only files.\n");
+            exit(1);
+        }
+
+        if (this->framerate_new.num > 0) {
+            double framerate_new = (double)this->framerate_new.num / this->framerate_new.den;
+            framerate_add = framerate_new/this->fps;
+            //fprintf(stderr,"calculating framerate addition to %f\n",framerate_add);
+            this->fps = framerate_new;
+        }
+
+        /*check for end time and calculate number of frames to encode*/
+        no_frames = this->fps*(this->end_time - this->start_time);
+        if(this->end_time > 0 && no_frames <= 0){
+            fprintf(stderr,"End time has to be bigger than start time.\n");
+            exit(1);
+        }
+        /* main decoding loop */
+        do{
+            if(no_frames > 0){
+                if(this->frame_count > no_frames){
+                    break;
+                }
+            }
+            ret = av_read_frame(this->context,&pkt);
+            if(ret<0){
+                e_o_s=1;
+            }
+
+            ptr = pkt.data;
+            len = pkt.size;
+            if (e_o_s && !info.audio_only || (ret >= 0 && pkt.stream_index == this->video_index)){
+                if(len == 0 && !first && !e_o_s){
+                    fprintf (stderr, "no frame available\n");
+                }
+                while(e_o_s || len > 0){
+                    int dups = 0;
+                    yuv_buffer yuv;
+                    len1 = avcodec_decode_video(vstream->codec, frame, &got_picture, ptr, len);
+                    if(len1>=0) {
+                        if(got_picture){
+                            // this is disabled by default since it does not work
+                            // for all input formats the way it should.
+                            if(this->sync == 1) {
+                                double delta = ((double) pkt.dts /
+                                    AV_TIME_BASE - this->pts_offset) *
+                                    this->fps - this->frame_count;
+                                /* 0.7 is an arbitrary value */
+                                /* it should be larger than half a frame to
+                                 avoid excessive dropping and duplicating */
+                                if (delta < -0.7) {
+#ifdef DEBUG
+                                    fprintf(stderr,
+                                          "Frame dropped to maintain sync\n");
+#endif
+                                    break;
+                                }
+                                if (delta > 0.7) {
+                                    //dups = lrintf(delta);
+                                    dups = (int)delta;
+#ifdef DEBUG
+                                    fprintf(stderr,
+                                      "%d duplicate %s added to maintain sync\n",
+                                      dups, (dups == 1) ? "frame" : "frames");
+#endif
+                                }
+                            }
+
+                            if (this->framerate_new.num > 0) {
+                                framerate_tmpcount += framerate_add;
+                                if (framerate_tmpcount < (double)(this->frame_count+1)) {
+                                    got_picture = 0;
+                                }
+                                else {
+                                    dups = 0;
+                                    while (framerate_tmpcount >= (double)(this->frame_count+2+dups)) {
+                                        dups += 1;
+                                    }
+                                }
+                            }
+
+                            //For audio only files command line option"-e" will not work
+                            //as we don't increment frame_count in audio section.
+
+                            if(venc->pix_fmt != this->pix_fmt) {
+                               sws_scale(this->sws_colorspace_ctx,
+                                 frame->data, frame->linesize, 0, venc->height,
+                                 output_tmp->data, output_tmp->linesize);
+
+                            }
+                            else{
+                                output_tmp = frame;
+                            }
+                            if(frame->interlaced_frame || this->deinterlace){
+                                if(avpicture_deinterlace((AVPicture *)output,(AVPicture *)output_tmp,this->pix_fmt,venc->width,venc->height)<0){
+                                        fprintf(stderr,"Deinterlace failed.\n");
+                                        exit(1);
+                                }
+                            }
+                            else{
+                                output=output_tmp;
+                            }
+                            // now output
+                            if(ppMode)
+                                pp_postprocess(output->data, output->linesize,
+                                               output->data, output->linesize,
+                                               venc->width, venc->height,
+                                               output->qscale_table, output->qstride,
+                                               ppMode, ppContext, this->pix_fmt);
+                            if(this->vhook)
+                                frame_hook_process((AVPicture *)output, this->pix_fmt, venc->width,venc->height);
+
+                            if (this->frame_topBand || this->frame_leftBand) {
+                                if (av_picture_crop((AVPicture *)output_tmp, (AVPicture *)output,
+                                    this->pix_fmt, this->frame_topBand, this->frame_leftBand) < 0) {
+                                    av_log(NULL, AV_LOG_ERROR, "error cropping picture\n");
+                                }
+                                output = output_tmp;
+                            }
+                            if(this->sws_scale_ctx){
+                              sws_scale(this->sws_scale_ctx,
+                                output->data, output->linesize, 0, venc->height - (this->frame_topBand + this->frame_bottomBand),
+                                output_resized->data, output_resized->linesize);
+                            }
+                            else{
+                                output_resized=output;
+                            }
+
+                        }
+                        ptr += len1;
+                        len -= len1;
+                    }
+                    //now output_resized
+
+                    if(!first) {
+                      if(got_picture || e_o_s) {
+                        prepare_yuv_buffer(this, &yuv, output_buffered);
+                        do {
+                          oggmux_add_video(&info, &yuv, e_o_s);
+                          this->frame_count++;
+                        } while(dups--);
+                      }
+                    }
+                    if(got_picture) {
+                      first=0;
+                      av_picture_copy ((AVPicture *)output_buffered, (AVPicture *)output_resized, this->pix_fmt, this->frame_width, this->frame_height);
+                    }
+                    if(!got_picture){
+                        break;
+                    }
+                }
+
+            }
+            if(e_o_s && !info.video_only
+                     || (ret >= 0 && pkt.stream_index == this->audio_index)){
+                this->pts_offset = (double) pkt.pts / AV_TIME_BASE -
+                    (double) this->sample_count / this->sample_rate;
+                while(e_o_s || len > 0 ){
+                    int samples=0;
+                    int samples_out=0;
+                    int data_size = 4*AVCODEC_MAX_AUDIO_FRAME_SIZE;
+                    if(len > 0){
+                        len1 = avcodec_decode_audio2(astream->codec, audio_buf, &data_size, ptr, len);
+                        if (len1 < 0){
+                            /* if error, we skip the frame */
+                            break;
+                        }
+                        len -= len1;
+                        ptr += len1;
+                        if(data_size >0){
+                            samples =data_size / (aenc->channels * 2);
+
+                            samples_out = samples;
+                            if(this->audio_resample_ctx){
+                                samples_out = audio_resample(this->audio_resample_ctx, resampled, audio_buf, samples);
+                            }
+                            else
+                                resampled=audio_buf;
+                        }
+                    }
+                    oggmux_add_audio(&info, resampled,
+                        samples_out *(this->channels),samples_out,e_o_s);
+                    this->sample_count += samples_out;
+                    if(e_o_s && len <= 0){
+                        break;
+                    }
+                }
+
+            }
+
+            /* if we have subtitles starting before then, add it */
+            if (info.with_kate) {
+                double avtime = info.audio_only ? info.audiotime :
+                    info.video_only ? info.videotime :
+                    info.audiotime < info.videotime ? info.audiotime : info.videotime;
+                for (i=0; i<this->n_kate_streams; ++i) {
+                    ff2theora_kate_stream *ks = this->kate_streams+i;
+                    if (ks->num_subtitles > 0) {
+                        ff2theora_subtitle *sub = ks->subtitles+ks->subtitles_count;
+                        /* we encode a bit in advance so we're sure to hit the time, the packet will
+                           be held till the right time. If we don't do that, we can insert late and
+                           oggz-validate moans */
+                        while (ks->subtitles_count < ks->num_subtitles && sub->t0-1.0 <= avtime+this->start_time) {
+                            int eos = (ks->subtitles_count == ks->num_subtitles-1);
+                            oggmux_add_kate_text(&info, i, sub->t0, sub->t1, sub->text, sub->len, eos);
+                            ks->subtitles_count++;
+                            ++sub;
+                        }
+                    }
+                }
+            }
+
+            /* flush out the file */
+            oggmux_flush (&info, e_o_s);
+            av_free_packet (&pkt);
+        }
+        while (ret >= 0);
+
+        for (i=0; i<this->n_kate_streams; ++i) {
+            ff2theora_kate_stream *ks = this->kate_streams+i;
+            if (ks->num_subtitles > 0 && ks->subtitles_count<ks->num_subtitles) {
+                double t = (info.videotime<info.audiotime?info.audiotime:info.videotime)+this->start_time;
+                oggmux_add_kate_end_packet(&info, i, t);
+                oggmux_flush (&info, e_o_s);
+            }
+        }
+
+        oggmux_close (&info);
+        if(ppContext)
+            pp_free_context(ppContext);
+    }
+    else{
+        fprintf (stderr, "No video or audio stream found.\n");
+    }
+}
+
+void ff2theora_close (ff2theora this){
+    /* clear out state */
+    free_subtitles(this);
+    av_free (this);
+}
+
+double aspect_check(const char *arg)
+{
+    int x = 0, y = 0;
+    double ar = 0;
+    const char *p;
+
+    p = strchr(arg, ':');
+    if (!p) {
+      p = strchr(arg, '/');
+    }
+    if (p) {
+        x = strtol(arg, (char **)&arg, 10);
+        if (arg == p)
+            y = strtol(arg+1, (char **)&arg, 10);
+        if (x > 0 && y > 0)
+            ar = (double)x / (double)y;
+    } else
+        ar = strtod(arg, (char **)&arg);
+
+    if (!ar) {
+        fprintf(stderr, "Incorrect aspect ratio specification.\n");
+        exit(1);
+    }
+    return ar;
+}
+
+static void add_frame_hooker(const char *arg)
+{
+    int argc = 0;
+    char *argv[64];
+    int i;
+    char *args = av_strdup(arg);
+
+    argv[0] = strtok(args, " ");
+    while (argc < 62 && (argv[++argc] = strtok(NULL, " "))) {
+    }
+
+    i = frame_hook_add(argc, argv);
+    if (i != 0) {
+        fprintf(stderr, "Failed to add video hook function: %s\n", arg);
+        exit(1);
+    }
+}
+
+AVRational get_framerate(const char* arg)
+{
+    const char *p;
+    AVRational framerate;
+
+    p = strchr(arg, ':');
+    if (!p) {
+      p = strchr(arg, '/');
+    }
+    if (p) {
+        framerate.num = strtol(arg, (char **)&arg, 10);
+        if (arg == p)
+            framerate.den = strtol(arg+1, (char **)&arg, 10);
+        if(framerate.num <= 0)
+            framerate.num = -1;
+        if(framerate.den <= 0)
+            framerate.den = 1;
+    } else {
+        framerate.num = strtol(arg, (char **)&arg,10);
+        framerate.den = 1;
+    }
+    return(framerate);
+}
+
+int crop_check(ff2theora this, char *name, const char *arg)
+{
+    int crop_value = atoi(arg);
+    if (crop_value < 0) {
+        fprintf(stderr, "Incorrect crop size `%s'.\n",name);
+        exit(1);
+    }
+    if ((crop_value % 2) != 0) {
+        fprintf(stderr, "Crop size `%s' must be a multiple of 2.\n",name);
+        exit(1);
+    }
+    /*
+    if ((crop_value) >= this->height){
+        fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n");
+        exit(1);
+    }
+    */
+    return crop_value;
+}
+
+
+
+void print_presets_info() {
+    fprintf (stdout,
+        //  "v2v presets - more info at http://wiki.v2v.cc/presets"
+        "v2v presets:\n"
+        "  preview        Video: 320x240 if fps ~ 30, 384x288 otherwise\n"
+        "                        Quality 5 - Sharpness 2\n"
+        "                 Audio: Max 2 channels - Quality 1\n"
+        "\n"
+        "  pro            Video: 720x480 if fps ~ 30, 720x576 otherwise\n"
+        "                        Quality 7 - Sharpness 0\n"
+        "                 Audio: Max 2 channels - Quality 3\n"
+        "\n"
+        "  videobin       Video: 512x288 for 16:9 material, 448x336 for 4:3 material\n"
+        "                        Bitrate 600kbs\n"
+        "                 Audio: Max 2 channels - Quality 3\n"
+        "\n"
+        "  padma          Video: 640x360 for 16:9 material, 640x480 for 4:3 material\n"
+        "                        Quality 5 - Sharpness 0\n"
+        "                 Audio: Max 2 channels - Quality 3\n"
+        "\n"
+        "  padma-stream   Video: 128x72 for 16:9 material, 128x96 for 4:3 material\n"
+        "                 Audio: mono quality -1\n"
+        "\n"
+        );
+}
+
+void print_usage (){
+    fprintf (stdout,
+        PACKAGE " " PACKAGE_VERSION "\n"
+        "\n"
+        "  Usage: " PACKAGE " [options] input\n"
+        "\n"
+        "General output options:\n"
+        "  -o, --output           alternative output filename\n"
+        "      --no-skeleton      disables ogg skeleton metadata output\n"
+        "  -s, --starttime        start encoding at this time (in sec.)\n"
+        "  -e, --endtime          end encoding at this time (in sec.)\n"
+        "  -p, --v2v-preset       encode file with v2v preset.\n"
+        "                          Right now there is preview, pro and videobin. Run\n"
+        "                          '"PACKAGE" -p info' for more informations\n"
+        "\n"
+        "Video output options:\n"
+        "  -v, --videoquality     [0 to 10] encoding quality for video (default: 5)\n"
+        "                                   use higher values for better quality\n"
+        "  -V, --videobitrate     [1 to 16778] encoding bitrate for video (kb/s)\n"
+        "      --optimize         optimize video output filesize (slower) (same as speedlevel 0)\n"
+        "      --speedlevel       [0 2] encoding is faster with higher values the cost is quality and bandwidth\n"
+        "  -x, --width            scale to given width (in pixels)\n"
+        "  -y, --height           scale to given height (in pixels)\n"
+        "      --aspect           define frame aspect ratio: i.e. 4:3 or 16:9\n"
+        "  -F, --framerate        output framerate e.g 25:2 or 16\n"
+        "      --croptop, --cropbottom, --cropleft, --cropright\n"
+        "                         crop input by given pixels before resizing\n"
+        "  -S, --sharpness        [0 to 2] sharpness of images (default: 0).\n"
+        "                          Note: lower values make the video sharper.\n"
+        "  -K, --keyint           [1 to 65536] keyframe interval (default: 64)\n"
+        "\n"
+        "Video transfer options:\n"
+        "  --pp                   Video Postprocessing, denoise, deblock, deinterlacer\n"
+            "                          use --pp help for a list of available filters.\n"
+        "  -C, --contrast         [0.1 to 10.0] contrast correction (default: 1.0)\n"
+            "                          Note: lower values make the video darker.\n"
+        "  -B, --brightness       [-1.0 to 1.0] brightness correction (default: 0.0)\n"
+            "                          Note: lower values make the video darker.\n"
+        "  -G, --gamma            [0.1 to 10.0] gamma correction (default: 1.0)\n"
+        "                          Note: lower values make the video darker.\n"
+        "  -Z, --saturation       [0.1 to 10.0] saturation correction (default: 1.0)\n"
+        "                          Note: lower values make the video grey.\n"
+        "\n"
+        "Audio output options:\n"
+        "  -a, --audioquality     [-2 to 10] encoding quality for audio (default: 1)\n"
+        "                                    use higher values for better quality\n"
+        "  -A, --audiobitrate     [32 to 500] encoding bitrate for audio (kb/s)\n"
+        "  -c, --channels         set number of output channels\n"
+        "  -H, --samplerate       set output samplerate (in Hz)\n"
+        "      --nosound          disable the sound from input\n"
+        "\n"
+        "Input options:\n"
+        "      --deinterlace      force deinterlace, otherwise only material\n"
+        "                          marked as interlaced will be deinterlaced\n"
+        "      --vhook            you can use ffmpeg's vhook system, example:\n"
+        "        ffmpeg2theora --vhook '/path/watermark.so -f wm.gif' input.dv\n"
+        "  -f, --format           specify input format\n"
+        "      --inputfps fps     override input fps\n"
+        "      --audiostream id   by default the last audio stream is selected,\n"
+        "                          use this to select another audio stream\n"
+        "      --sync             use A/V sync from input container. Since this does\n"
+        "                          not work with all input format you have to manually\n"
+        "                          enable it if you have issues with A/V sync\n"
+        "\n"
+#ifdef HAVE_KATE
+        "Subtitles options:\n"
+        "      --subtitles file                 use subtitles from the given file (SubRip (.srt) format)\n"
+        "      --subtitles-encoding encoding    set encoding of the subtitles file\n"
+        "             supported are " SUPPORTED_ENCODINGS "\n"
+        "      --subtitles-language language    set subtitles language (de, en_GB, etc)\n"
+        "      --subtitles-category category    set subtitles category (default \"subtitles\")\n"
+        "\n"
+#endif
+        "Metadata options:\n"
+        "      --artist           Name of artist (director)\n"
+        "      --title            Title\n"
+        "      --date             Date\n"
+        "      --location         Location\n"
+        "      --organization     Name of organization (studio)\n"
+        "      --copyright        Copyright\n"
+        "      --license          License\n"
+        "      --contact          Contact link\n"
+        "\n"
+        "Other options:\n"
+#ifndef _WIN32
+        "      --nice n           set niceness to n\n"
+#endif
+        "  -P, --pid fname        write the process' id to a file\n"
+        "  -h, --help             this message\n"
+        "\n"
+        "Examples:\n"
+        "  ffmpeg2theora videoclip.avi (will write output to videoclip.ogv)\n"
+        "\n"
+        "  ffmpeg2theora videoclip.avi --subtitles subtitles.srt (same, with subtitles)\n"
+        "\n"
+        "  cat something.dv | ffmpeg2theora -f dv -o output.ogv -\n"
+        "\n"
+        "  Encode a series of images:\n"
+        "    ffmpeg2theora -f image2 frame%%06d.png -o output.ogv\n"
+        "\n"
+#if 0
+        "  Live streaming from V4L Device:\n"
+        "    ffmpeg2theora  /dev/video0 -fps 15 -x 160 -y 128 -o - \\\n"
+        "     | oggfwd iccast2server 8000 password /theora.ogv\n"
+        "\n"
+#endif
+        "  Live encoding from a DV camcorder (needs a fast machine):\n"
+        "    dvgrab - | ffmpeg2theora -f dv -x 352 -y 288 -o output.ogv -\n"
+        "\n"
+        "  Live encoding and streaming to icecast server:\n"
+        "    dvgrab --format raw - \\\n"
+        "     | ffmpeg2theora -f dv -x 160 -y 128 -o /dev/stdout - \\\n"
+        "     | oggfwd iccast2server 8000 password /theora.ogv\n"
+        "\n"
+        );
+    exit (0);
+}
+
+int main (int argc, char **argv){
+    int  n;
+    int  outputfile_set=0;
+    char outputfile_name[255];
+    char inputfile_name[255];
+    char *str_ptr;
+
+    static int flag = -1;
+    static int metadata_flag = 0;
+
+    AVInputFormat *input_fmt = NULL;
+    AVFormatParameters *formatParams = NULL;
+
+    int c,long_option_index;
+    const char *optstring = "P:o:k:f:F:x:y:v:V:a:A:S:K:d:H:c:G:Z:C:B:p:N:s:e:D:h::";
+    struct option options [] = {
+      {"pid",required_argument,NULL, 'P'},
+      {"output",required_argument,NULL,'o'},
+      {"skeleton",no_argument,NULL,'k'},
+      {"no-skeleton",no_argument,&flag,NOSKELETON},
+      {"format",required_argument,NULL,'f'},
+      {"width",required_argument,NULL,'x'},
+      {"height",required_argument,NULL,'y'},
+      {"videoquality",required_argument,NULL,'v'},
+      {"videobitrate",required_argument,NULL,'V'},
+      {"audioquality",required_argument,NULL,'a'},
+      {"audiobitrate",required_argument,NULL,'A'},
+      {"sharpness",required_argument,NULL,'S'},
+      {"keyint",required_argument,NULL,'K'},
+      {"deinterlace",0,&flag,DEINTERLACE_FLAG},
+      {"pp",required_argument,&flag,PP_FLAG},
+      {"samplerate",required_argument,NULL,'H'},
+      {"channels",required_argument,NULL,'c'},
+      {"gamma",required_argument,NULL,'G'},
+      {"brightness",required_argument,NULL,'B'},
+      {"contrast",required_argument,NULL,'C'},
+      {"saturation",required_argument,NULL,'Z'},
+      {"nosound",0,&flag,NOSOUND_FLAG},
+      {"vhook",required_argument,&flag,VHOOK_FLAG},
+      {"framerate",required_argument,NULL,'F'},
+      {"aspect",required_argument,&flag,ASPECT_FLAG},
+      {"v2v-preset",required_argument,NULL,'p'},
+      {"nice",required_argument,NULL,'N'},
+      {"croptop",required_argument,&flag,CROPTOP_FLAG},
+      {"cropbottom",required_argument,&flag,CROPBOTTOM_FLAG},
+      {"cropright",required_argument,&flag,CROPRIGHT_FLAG},
+      {"cropleft",required_argument,&flag,CROPLEFT_FLAG},
+      {"inputfps",required_argument,&flag,INPUTFPS_FLAG},
+      {"audiostream",required_argument,&flag,AUDIOSTREAM_FLAG},
+      {"subtitles",required_argument,&flag,SUBTITLES_FLAG},
+      {"subtitles-encoding",required_argument,&flag,SUBTITLES_ENCODING_FLAG},
+      {"subtitles-language",required_argument,&flag,SUBTITLES_LANGUAGE_FLAG},
+      {"subtitles-category",required_argument,&flag,SUBTITLES_CATEGORY_FLAG},
+      {"starttime",required_argument,NULL,'s'},
+      {"endtime",required_argument,NULL,'e'},
+      {"sync",0,&flag,SYNC_FLAG},
+      {"optimize",0,&flag,OPTIMIZE_FLAG},
+      {"speedlevel",required_argument,&flag,SPEEDLEVEL_FLAG},
+      {"frontend",0,&flag,FRONTEND_FLAG},
+
+      {"artist",required_argument,&metadata_flag,10},
+      {"title",required_argument,&metadata_flag,11},
+      {"date",required_argument,&metadata_flag,12},
+      {"location",required_argument,&metadata_flag,13},
+      {"organization",required_argument,&metadata_flag,14},
+      {"copyright",required_argument,&metadata_flag,15},
+      {"license",required_argument,&metadata_flag,16},
+      {"contact",required_argument,&metadata_flag,17},
+      {"source-hash",required_argument,&metadata_flag,18},
+
+      {"help",0,NULL,'h'},
+      {NULL,0,NULL,0}
+    };
+
+    char pidfile_name[255] = { '\0' };
+    FILE *fpid = NULL;
+
+    ff2theora convert = ff2theora_init ();
+    avcodec_register_all();
+    avdevice_register_all();
+    av_register_all();
+
+    if (argc == 1){
+        print_usage ();
+    }
+    // set some variables;
+    init_info(&info);
+    theora_comment_init (&info.tc);
+
+    while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
+        switch(c)
+        {
+            case 0:
+                if (flag) {
+                    switch (flag)
+                    {
+                        case DEINTERLACE_FLAG:
+                            convert->deinterlace = 1;
+                            flag = -1;
+                            break;
+                        case PP_FLAG:
+                            if(!strcmp(optarg, "help")) {
+                                fprintf(stdout, pp_help);
+                                exit(1);
+                            }
+                            snprintf(convert->pp_mode,sizeof(convert->pp_mode),"%s",optarg);
+                            flag = -1;
+                            break;
+                        case VHOOK_FLAG:
+                            convert->vhook = 1;
+                            add_frame_hooker(optarg);
+                            flag = -1;
+                            break;
+
+                        case SYNC_FLAG:
+                            convert->sync = 1;
+                            flag = -1;
+                            break;
+                        case NOSOUND_FLAG:
+                            convert->disable_audio = 1;
+                            flag = -1;
+                            break;
+                        case OPTIMIZE_FLAG:
+                            info.speed_level = 0;
+                            flag = -1;
+                            break;
+                        case SPEEDLEVEL_FLAG:
+                          info.speed_level = atoi(optarg);
+                            flag = -1;
+                            break;
+                        case FRONTEND_FLAG:
+                            info.frontend = 1;
+                            flag = -1;
+                            break;
+                        /* crop */
+                        case CROPTOP_FLAG:
+                            convert->frame_topBand = crop_check(convert,"top",optarg);
+                            flag = -1;
+                            break;
+                        case CROPBOTTOM_FLAG:
+                            convert->frame_bottomBand = crop_check(convert,"bottom",optarg);
+                            flag = -1;
+                            break;
+                        case CROPRIGHT_FLAG:
+                            convert->frame_rightBand = crop_check(convert,"right",optarg);
+                            flag = -1;
+                            break;
+                        case CROPLEFT_FLAG:
+                            convert->frame_leftBand = crop_check(convert,"left",optarg);
+                            flag = -1;
+                            break;
+                        case ASPECT_FLAG:
+                            convert->frame_aspect = aspect_check(optarg);
+                            flag = -1;
+                            break;
+                        case INPUTFPS_FLAG:
+                            convert->force_input_fps = atof(optarg);
+                            flag = -1;
+                            break;
+                        case AUDIOSTREAM_FLAG:
+                            convert->audiostream = atoi(optarg);
+                            flag = -1;
+                            break;
+                        case NOSKELETON:
+                            info.with_skeleton=0;
+                            break;
+#ifdef HAVE_KATE
+                        case SUBTITLES_FLAG:
+                            set_subtitles_file(convert,optarg);
+                            flag = -1;
+                            info.with_kate=1;
+                            break;
+                        case SUBTITLES_ENCODING_FLAG:
+                            if (!strcmp(optarg,"utf-8")) set_subtitles_encoding(convert,ENC_UTF8);
+                            if (!strcmp(optarg,"utf8")) set_subtitles_encoding(convert,ENC_UTF8);
+                            else if (!strcmp(optarg,"iso-8859-1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
+                            else if (!strcmp(optarg,"latin1")) set_subtitles_encoding(convert,ENC_ISO_8859_1);
+                            else report_unknown_subtitle_encoding(optarg);
+                            flag = -1;
+                            break;
+                        case SUBTITLES_LANGUAGE_FLAG:
+                            if (strlen(optarg)>15) {
+                              fprintf(stderr, "WARNING - language is limited to 15 characters, and will be truncated\n");
+                            }
+                            set_subtitles_language(convert,optarg);
+                            flag = -1;
+                            break;
+                        case SUBTITLES_CATEGORY_FLAG:
+                            if (strlen(optarg)>15) {
+                              fprintf(stderr, "WARNING - category is limited to 15 characters, and will be truncated\n");
+                            }
+                            set_subtitles_category(convert,optarg);
+                            flag = -1;
+                            break;
+#else
+                        case SUBTITLES_FLAG:
+                        case SUBTITLES_ENCODING_FLAG:
+                        case SUBTITLES_LANGUAGE_FLAG:
+                        case SUBTITLES_CATEGORY_FLAG:
+                            fprintf(stderr, "WARNING - Kate support not compiled in, subtitles will not be output\n"
+                                            "        - install libkate and rebuild ffmpeg2theora for subtitle support\n");
+                            break;
+#endif
+                    }
+                }
+
+                /* metadata */
+                if (metadata_flag){
+                    switch(metadata_flag) {
+                        case 10:
+                            theora_comment_add_tag(&info.tc, "ARTIST", optarg);
+                            break;
+                        case 11:
+                            theora_comment_add_tag(&info.tc, "TITLE", optarg);
+                            break;
+                        case 12:
+                            theora_comment_add_tag(&info.tc, "DATE", optarg);
+                            break;
+                        case 13:
+                            theora_comment_add_tag(&info.tc, "LOCATION", optarg);
+                            break;
+                        case 14:
+                            theora_comment_add_tag(&info.tc, "ORGANIZATION", optarg);
+                            break;
+                        case 15:
+                            theora_comment_add_tag(&info.tc, "COPYRIGHT", optarg);
+                            break;
+                        case 16:
+                            theora_comment_add_tag(&info.tc, "LICENSE", optarg);
+                            break;
+                        case 17:
+                            theora_comment_add_tag(&info.tc, "CONTACT", optarg);
+                            break;
+                        case 18:
+                            theora_comment_add_tag(&info.tc, "SOURCE HASH", optarg);
+                            break;
+                    }
+                    metadata_flag=0;
+                }
+                break;
+            case 'e':
+                convert->end_time = atoi(optarg);
+                break;
+            case 's':
+                convert->start_time = atoi(optarg);
+                break;
+            case 'o':
+                snprintf(outputfile_name,sizeof(outputfile_name),"%s",optarg);
+                outputfile_set=1;
+                break;
+            case 'k':
+                info.with_skeleton=1;
+                break;
+            case 'P':
+                sprintf(pidfile_name,optarg);
+                break;
+            case 'f':
+                input_fmt=av_find_input_format(optarg);
+                break;
+            case 'x':
+                convert->picture_width=atoi(optarg);
+                break;
+            case 'y':
+                convert->picture_height=atoi(optarg);
+                break;
+            case 'v':
+                convert->video_quality = rint(atof(optarg)*6.3);
+                if(convert->video_quality <0 || convert->video_quality >63){
+                        fprintf(stderr,"Only values from 0 to 10 are valid for video quality.\n");
+                        exit(1);
+                }
+                convert->video_bitrate=0;
+                break;
+            case 'V':
+                convert->video_bitrate=rint(atof(optarg)*1000);
+                if (convert->video_bitrate < 1) {
+                    fprintf(stderr, "Only values from 1 to 16000 are valid for video bitrate (in kb/s).\n");
+                    exit(1);
+                }
+                convert->video_quality=0;
+                break;
+            case 'a':
+                convert->audio_quality=atof(optarg);
+                if(convert->audio_quality<-2 || convert->audio_quality>10){
+                    fprintf(stderr,"Only values from -2 to 10 are valid for audio quality.\n");
+                    exit(1);
+                }
+                convert->audio_bitrate=0;
+                break;
+            case 'A':
+                convert->audio_bitrate=atof(optarg)*1000;
+                if(convert->audio_bitrate<0){
+                    fprintf(stderr,"Only values >0 are valid for audio bitrate.\n");
+                    exit(1);
+                }
+                convert->audio_quality = -990;
+                break;
+            case 'G':
+                convert->video_gamma = atof(optarg);
+                break;
+            case 'C':
+                convert->video_contr = atof(optarg);
+                break;
+            case 'Z':
+                convert->video_satur = atof(optarg);
+                break;
+            case 'B':
+                convert->video_bright = atof(optarg);
+                break;
+            case 'S':
+                convert->sharpness = atoi(optarg);
+                if (convert->sharpness < 0 || convert->sharpness > 2) {
+                    fprintf (stderr, "Only values from 0 to 2 are valid for sharpness.\n");
+                    exit(1);
+                }
+                break;
+            case 'K':
+                convert->keyint = atoi(optarg);
+                if (convert->keyint < 1 || convert->keyint > 65536) {
+                    fprintf (stderr, "Only values from 1 to 65536 are valid for keyframe interval.\n");
+                    exit(1);
+                }
+                break;
+            case 'H':
+                convert->sample_rate=atoi(optarg);
+                break;
+            case 'F':
+                convert->framerate_new = get_framerate(optarg);
+                break;
+            case 'c':
+                convert->channels=atoi(optarg);
+                if(convert->channels <= 0) {
+                  fprintf (stderr, "You can not have less than one audio channel.\n");
+                  exit(1);
+                }
+                break;
+            case 'p':
+                //v2v presets
+                if(!strcmp(optarg, "info")){
+                    print_presets_info();
+                    exit(1);
+                }
+                else if(!strcmp(optarg, "pro")){
+                    //need a way to set resize here. and not later
+                    convert->preset=V2V_PRESET_PRO;
+                    convert->video_quality = rint(7*6.3);
+                    convert->audio_quality = 3.00;
+                    convert->sharpness = 0;
+                    info.speed_level = 0;
+                }
+                else if(!strcmp(optarg,"preview")){
+                    //need a way to set resize here. and not later
+                    convert->preset=V2V_PRESET_PREVIEW;
+                    convert->video_quality = rint(5*6.3);
+                    convert->audio_quality = 1.00;
+                    convert->sharpness = 2;
+                    info.speed_level = 0;
+                }
+                else if(!strcmp(optarg,"videobin")){
+                    convert->preset=V2V_PRESET_VIDEOBIN;
+                    convert->video_bitrate=rint(600*1000);
+                    convert->video_quality = 0;
+                    convert->audio_quality = 3.00;
+                    convert->sharpness = 2;
+                    info.speed_level = 0;
+                }
+                else if(!strcmp(optarg,"padma")){
+                    convert->preset=V2V_PRESET_PADMA;
+                    convert->video_quality = rint(5*6.3);
+                    convert->audio_quality = 3.00;
+                    convert->sharpness = 0;
+                    info.speed_level = 0;
+                }
+                else if(!strcmp(optarg,"padma-stream")){
+                    convert->preset=V2V_PRESET_PADMASTREAM;
+                    convert->video_bitrate=rint(180*1000);
+                    convert->video_quality = 0;
+                    convert->audio_quality = -1.00;
+                    convert->sample_rate=44100;
+                    convert->sharpness = 2;
+                    convert->keyint = 16;
+                    info.speed_level = 0;
+                }
+                else{
+                    fprintf(stderr,"\nUnknown preset.\n\n");
+                    print_presets_info();
+                    exit(1);
+                }
+                break;
+            case 'N':
+                n = atoi(optarg);
+                if (n) {
+#ifndef _WIN32
+                    if (nice(n)<0) {
+                        fprintf(stderr,"Error setting `%d' for niceness.", n);
+                    }
+#endif
+                }
+                break;
+            case 'h':
+                print_usage ();
+                exit(1);
+        }
+    }
+
+    while(optind<argc){
+        /* assume that anything following the options must be a filename */
+        snprintf(inputfile_name,sizeof(inputfile_name),"%s",argv[optind]);
+        if(!strcmp(inputfile_name,"-")){
+            snprintf(inputfile_name,sizeof(inputfile_name),"pipe:");
+        }
+        if(outputfile_set!=1){
+            /* reserve 4 bytes in the buffer for the `.ogv' extension */
+            snprintf(outputfile_name, sizeof(outputfile_name) - 4, "%s", argv[optind]);
+            if((str_ptr = strrchr(outputfile_name, '.'))) {
+              sprintf(str_ptr, ".ogv");
+              if(!strcmp(inputfile_name, outputfile_name)){
+                snprintf(outputfile_name, sizeof(outputfile_name), "%s.ogv", inputfile_name);
+              }
+            }
+            else {
+                 snprintf(outputfile_name, sizeof(outputfile_name), "%s.ogv", outputfile_name);
+            }
+            outputfile_set=1;
+        }
+        optind++;
+    }
+
+#ifdef VIDEO4LINUX_ENABLED
+    if(formatParams != NULL) {
+        formatParams->channel = 0;
+        formatParams->width = PAL_HALF_WIDTH;
+        formatParams->height = PAL_HALF_HEIGHT;
+        if(convert->picture_width)
+            formatParams->width = convert->picture_width;
+        if(convert->picture_height)
+            formatParams->height = convert->picture_height;
+
+        formatParams->time_base.den = 25;
+        formatParams->time_base.num = 1;
+        if(convert->force_input_fps) {
+
+            formatParams->time_base.den = convert->force_input_fps * 1000;
+            formatParams->time_base.num = 1000;
+
+        }
+        formatParams->standard = "pal";
+        input_fmt = av_find_input_format("video4linux");
+        sprintf(inputfile_name,"");
+    }
+#endif
+
+    //FIXME: is using_stdin still neded? is it needed as global variable?
+    using_stdin |= !strcmp(inputfile_name, "pipe:" ) ||
+                   !strcmp( inputfile_name, "/dev/stdin" );
+
+    if(outputfile_set!=1){
+        fprintf(stderr,"You have to specify an output file with -o output.ogv.\n");
+        exit(1);
+    }
+
+    /* could go, but so far no player supports offset_x/y */
+    if(convert->picture_width % 8 ||  convert->picture_height % 8){
+        fprintf(stderr,"Output size must be a multiple of 8 for now.\n");
+        exit(1);
+    }
+    /*
+    if(convert->picture_width % 4 ||  convert->picture_height % 4){
+        fprintf(stderr,"Output width and height size must be a multiple of 2.\n");
+        exit(1);
+    }
+    */
+    if(convert->end_time>0 && convert->end_time <= convert->start_time){
+        fprintf(stderr,"End time has to be bigger than start time.\n");
+        exit(1);
+    }
+
+    if (*pidfile_name)
+    {
+        fpid = fopen(pidfile_name, "w");
+        if (fpid != NULL)
+        {
+            fprintf(fpid, "%i", getpid());
+            fclose(fpid);
+        }
+    }
+
+    oggmux_setup_kate_streams(&info, convert->n_kate_streams);
+
+    for (n=0; n<convert->n_kate_streams; ++n) {
+        ff2theora_kate_stream *ks=convert->kate_streams+n;
+        if (load_subtitles(ks)>=0) {
+          printf("Muxing Kate stream %d from %s as %s %s\n",
+              n,ks->filename,
+              ks->subtitles_language[0]?ks->subtitles_language:"<unknown language>",
+              ks->subtitles_category[0]?ks->subtitles_category:"subtitles");
+        }
+    }
+
+    if (av_open_input_file(&convert->context, inputfile_name, input_fmt, 0, formatParams) >= 0){
+        if (av_find_stream_info (convert->context) >= 0){
+#ifdef WIN32
+                if(!strcmp(outputfile_name,"-") || !strcmp(outputfile_name,"/dev/stdout")){
+                    _setmode(_fileno(stdout), _O_BINARY);
+                    info.outfile = stdout;
+                }
+                else {
+                    info.outfile = fopen(outputfile_name,"wb");
+                }
+#else
+                if(!strcmp(outputfile_name,"-")){
+                    snprintf(outputfile_name,sizeof(outputfile_name),"/dev/stdout");
+                }
+                info.outfile = fopen(outputfile_name,"wb");
+#endif
+                if(info.frontend) {
+                  fprintf(stderr, "\nf2t ;duration: %d;\n", convert->context->duration / AV_TIME_BASE);
+                }
+                else {
+                  dump_format (convert->context, 0,inputfile_name, 0);
+                }
+                if(convert->disable_audio){
+                    fprintf(stderr,"  [audio disabled].\n");
+                }
+                if(convert->sync){
+                    fprintf(stderr,"  Use A/V Sync from input container.\n");
+                }
+
+                convert->pts_offset =
+                    (double) convert->context->start_time / AV_TIME_BASE;
+                if(!info.outfile) {
+                    if(info.frontend)
+                        fprintf(stderr, "\nf2t ;result: Unable to open output file.;\n");
+                    else
+                      fprintf (stderr,"\nUnable to open output file `%s'.\n", outputfile_name);
+                    return(1);
+                }
+                if (convert->context->duration != AV_NOPTS_VALUE) {
+                  info.duration = convert->context->duration / AV_TIME_BASE;
+                }
+                ff2theora_output (convert);
+                convert->audio_index =convert->video_index = -1;
+            }
+            else{
+              if(info.frontend)
+                  fprintf(stderr, "\nf2t ;result: input format not suported.;\n");
+              else
+                  fprintf (stderr,"\nUnable to decode input.\n");
+              return(1);
+            }
+            av_close_input_file (convert->context);
+        }
+        else{
+            fprintf (stderr, "\nFile `%s' does not exist or has an unknown data format.\n", inputfile_name);
+            return(1);
+        }
+    ff2theora_close (convert);
+    fprintf(stderr,"\n");
+
+    if (*pidfile_name)
+        unlink(pidfile_name);
+
+    if(info.frontend)
+        fprintf(stderr, "\nf2t ;result: ok;\n");
+
+    return(0);
+}

Added: trunk/ffmpeg2theora/src/ffmpeg2theora.h
===================================================================
--- trunk/ffmpeg2theora/src/ffmpeg2theora.h	                        (rev 0)
+++ trunk/ffmpeg2theora/src/ffmpeg2theora.h	2008-05-23 17:56:21 UTC (rev 14950)
@@ -0,0 +1,101 @@
+#ifndef _F2T_FFMPEG2THEORA_H_
+#define _F2T_FFMPEG2THEORA_H_
+
+#include "subtitles.h"
+
+typedef enum {
+  ENC_UNSET,
+  ENC_UTF8,
+  ENC_ISO_8859_1,
+} F2T_ENCODING;
+
+
+typedef struct ff2theora_subtitle{
+    char *text;
+    size_t len;
+    double t0;
+    double t1;
+} ff2theora_subtitle;
+
+typedef struct ff2theora_kate_stream{
+    const char *filename;
+    size_t num_subtitles;
+    ff2theora_subtitle *subtitles;
+    size_t subtitles_count; /* total subtitles output so far */
+    F2T_ENCODING subtitles_encoding;
+    char subtitles_language[16];
+    char subtitles_category[16];
+} ff2theora_kate_stream;
+
+typedef struct ff2theora{
+    AVFormatContext *context;
+    int video_index;
+    int audio_index;
+
+    int deinterlace;
+    int vhook;
+    int audiostream;
+    int sample_rate;
+    int channels;
+    int disable_audio;
+    float audio_quality;
+    int audio_bitrate;
+    int preset;
+
+    int picture_width;
+    int picture_height;
+    double fps;
+    struct SwsContext *sws_colorspace_ctx; /* for image resampling/resizing */
+    struct SwsContext *sws_scale_ctx; /* for image resampling/resizing */
+    ReSampleContext *audio_resample_ctx;
+    ogg_int32_t aspect_numerator;
+    ogg_int32_t aspect_denominator;
+    double    frame_aspect;
+
+    int pix_fmt;
+    int video_quality;
+    int video_bitrate;
+    int sharpness;
+    int keyint;
+    char pp_mode[255];
+
+    double force_input_fps;
+    int sync;
+
+    /* cropping */
+    int frame_topBand;
+    int frame_bottomBand;
+    int frame_leftBand;
+    int frame_rightBand;
+
+    int frame_width;
+    int frame_height;
+    int frame_x_offset;
+    int frame_y_offset;
+
+    /* In seconds */
+    int start_time;
+    int end_time;
+
+    AVRational framerate_new;
+
+    double pts_offset; /* between given input pts and calculated output pts */
+    int64_t frame_count; /* total video frames output so far */
+    int64_t sample_count; /* total audio samples output so far */
+
+    size_t n_kate_streams;
+    ff2theora_kate_stream *kate_streams;
+    
+    // ffmpeg2theora --nosound -f dv -H 32000 -S 0 -v 8 -x 384 -y 288 -G 1.5 input.dv
+    double video_gamma;
+    double video_bright;
+    double video_contr;
+    double video_satur;
+    int y_lut_used;
+    int uv_lut_used;
+    unsigned char y_lut[256];
+    unsigned char uv_lut[256];
+}
+*ff2theora;
+
+#endif

Copied: trunk/ffmpeg2theora/src/subtitles.c (from rev 14949, trunk/ffmpeg2theora/subtitles.c)
===================================================================
--- trunk/ffmpeg2theora/src/subtitles.c	                        (rev 0)
+++ trunk/ffmpeg2theora/src/subtitles.c	2008-05-23 17:56:21 UTC (rev 14950)
@@ -0,0 +1,293 @@
+/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
+/*
+ * subtitles.c -- Kate Subtitles
+ * Copyright (C) 2007-2008 <j at v2v.cc>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <math.h>
+#include <errno.h>
+
+#include "libavformat/avformat.h"
+
+#ifdef WIN32
+#include "fcntl.h"
+#endif
+
+#include "theorautils.h"
+#include "subtitles.h"
+
+
+/**
+  * adds a new kate stream structure
+  */
+static void add_kate_stream(ff2theora this){
+    ff2theora_kate_stream *ks;
+    this->kate_streams=(ff2theora_kate_stream*)realloc(this->kate_streams,(this->n_kate_streams+1)*sizeof(ff2theora_kate_stream));
+    ks=&this->kate_streams[this->n_kate_streams++];
+    ks->filename = NULL;
+    ks->num_subtitles = 0;
+    ks->subtitles = 0;
+    ks->subtitles_count = 0; /* denotes not set yet */
+    ks->subtitles_encoding = ENC_UNSET;
+    strcpy(ks->subtitles_language, "");
+    strcpy(ks->subtitles_category, "");
+}
+
+/*
+ * sets the filename of the next subtitles file
+ */
+void set_subtitles_file(ff2theora this,const char *filename){
+  size_t n;
+  for (n=0; n<this->n_kate_streams;++n) {
+    if (!this->kate_streams[n].filename) break;
+  }
+  if (n==this->n_kate_streams) add_kate_stream(this);
+  this->kate_streams[n].filename = filename;
+}
+
+/*
+ * sets the language of the next subtitles file
+ */
+void set_subtitles_language(ff2theora this,const char *language){
+  size_t n;
+  for (n=0; n<this->n_kate_streams;++n) {
+    if (!this->kate_streams[n].subtitles_language[0]) break;
+  }
+  if (n==this->n_kate_streams) add_kate_stream(this);
+  strncpy(this->kate_streams[n].subtitles_language, language, 16);
+  this->kate_streams[n].subtitles_language[15] = 0;
+}
+
+/*
+ * sets the category of the next subtitles file
+ */
+void set_subtitles_category(ff2theora this,const char *category){
+  size_t n;
+  for (n=0; n<this->n_kate_streams;++n) {
+    if (!this->kate_streams[n].subtitles_category[0]) break;
+  }
+  if (n==this->n_kate_streams) add_kate_stream(this);
+  strncpy(this->kate_streams[n].subtitles_category, category, 16);
+  this->kate_streams[n].subtitles_category[15] = 0;
+}
+
+/**
+  * sets the encoding of the next subtitles file
+  */
+void set_subtitles_encoding(ff2theora this,F2T_ENCODING encoding){
+  size_t n;
+  for (n=0; n<this->n_kate_streams;++n) {
+    if (this->kate_streams[n].subtitles_encoding==ENC_UNSET) break;
+  }
+  if (n==this->n_kate_streams) add_kate_stream(this);
+  this->kate_streams[n].subtitles_encoding = encoding;
+}
+
+
+void report_unknown_subtitle_encoding(const char *name)
+{
+  fprintf(stderr, "Unknown character encoding: %s\n",name);
+  fprintf(stderr, "Valid character encodings are:\n");
+  fprintf(stderr, "  " SUPPORTED_ENCODINGS "\n");
+}
+
+static char *fgets2(char *s,size_t sz,FILE *f)
+{
+    char *ret = fgets(s, sz, f);
+    /* fixup DOS newline character */
+    char *ptr=strchr(s, '\r');
+    if (ptr) *ptr='\n';
+    return ret;
+}
+
+static double hmsms2s(int h,int m,int s,int ms)
+{
+    return h*3600+m*60+s+ms/1000.0;
+}
+
+/* very simple implementation when no iconv */
+static void convert_subtitle_to_utf8(F2T_ENCODING encoding,unsigned char *text)
+{
+  size_t nbytes;
+  unsigned char *ptr,*newtext;
+
+  if (!text || !*text) return;
+
+  switch (encoding) {
+    case ENC_UNSET:
+      /* we don't know what encoding this is, assume utf-8 and we'll yell if it ain't */
+      break;
+    case ENC_UTF8:
+      /* nothing to do, already in utf-8 */
+      break;
+    case ENC_ISO_8859_1:
+      /* simple, characters above 0x7f are broken in two,
+         and code points map to the iso-8859-1 8 bit codes */
+      nbytes=0;
+      for (ptr=text;*ptr;++ptr) {
+        nbytes++;
+        if (0x80&*ptr) nbytes++;
+      }
+      newtext=(unsigned char*)malloc(1+nbytes);
+      if (!newtext) {
+        fprintf(stderr, "Memory allocation failed - cannot convert text\n");
+        return;
+      }
+      nbytes=0;
+      for (ptr=text;*ptr;++ptr) {
+        if (0x80&*ptr) {
+          newtext[nbytes++]=0xc0|((*ptr)>>6);
+          newtext[nbytes++]=0x80|((*ptr)&0x3f);
+        }
+        else {
+          newtext[nbytes++]=*ptr;
+        }
+      }
+      newtext[nbytes++]=0;
+      memcpy(text,newtext,nbytes);
+      free(newtext);
+      break;
+    default:
+      fprintf(stderr, "ERROR: encoding %d not handled in conversion!\n", encoding);
+      break;
+  }
+}
+
+int load_subtitles(ff2theora_kate_stream *this)
+{
+#ifdef HAVE_KATE
+    enum { need_id, need_timing, need_text };
+    int need = need_id;
+    int last_seen_id=0;
+    int ret;
+    int id;
+    static char text[4096];
+    int h0,m0,s0,ms0,h1,m1,s1,ms1;
+    double t0,t1;
+    static char str[4096];
+    int warned=0;
+
+    FILE *f = fopen(this->filename, "r");
+    if (!f) {
+        fprintf(stderr,"WARNING - Failed to open subtitles file %s (%s)\n", this->filename, strerror(errno));
+        return -1;
+    }
+
+    /* first, check for a BOM */
+    ret=fread(str,1,3,f);
+    if (ret<3 || memcmp(str,"\xef\xbb\xbf",3)) {
+      /* No BOM, rewind */
+      fseek(f,0,SEEK_SET);
+    }
+
+    fgets2(str,sizeof(str),f);
+    while (!feof(f)) {
+      switch (need) {
+        case need_id:
+          ret=sscanf(str,"%d\n",&id);
+          if (ret!=1) {
+            fprintf(stderr,"WARNING - Syntax error: %s\n",str);
+            fclose(f);
+            return -1;
+          }
+          if (id!=last_seen_id+1) {
+            fprintf(stderr,"WARNING - non consecutive ids: %s - pretending not to have noticed\n",str);
+          }
+          last_seen_id=id;
+          need=need_timing;
+          strcpy(text,"");
+          break;
+        case need_timing:
+          ret=sscanf(str,"%d:%d:%d%*[.,]%d --> %d:%d:%d%*[.,]%d\n",&h0,&m0,&s0,&ms0,&h1,&m1,&s1,&ms1);
+          if (ret!=8) {
+            fprintf(stderr,"WARNING - Syntax error: %s\n",str);
+            fclose(f);
+            return -1;
+          }
+          else {
+            t0=hmsms2s(h0,m0,s0,ms0);
+            t1=hmsms2s(h1,m1,s1,ms1);
+          }
+          need=need_text;
+          break;
+        case need_text:
+          if (*str=='\n') {
+            convert_subtitle_to_utf8(this->subtitles_encoding,(unsigned char*)text);
+            size_t len = strlen(text);
+            this->subtitles = (ff2theora_subtitle*)realloc(this->subtitles, (this->num_subtitles+1)*sizeof(ff2theora_subtitle));
+            if (!this->subtitles) {
+              fprintf(stderr, "Out of memory\n");
+              fclose(f);
+              return -1;
+            }
+            ret=kate_text_validate(kate_utf8,text,len+1);
+            if (ret<0) {
+              if (!warned) {
+                fprintf(stderr,"WARNING: subtitle %s is not valid utf-8\n",text);
+                fprintf(stderr,"  further invalid subtitles will NOT be flagged\n");
+                warned=1;
+              }
+            }
+            else {
+              /* kill off trailing \n characters */
+              while (len>0) {
+                if (text[len-1]=='\n') text[--len]=0; else break;
+              }
+              this->subtitles[this->num_subtitles].text = (char*)malloc(len+1);
+              memcpy(this->subtitles[this->num_subtitles].text, text, len+1);
+              this->subtitles[this->num_subtitles].len = len;
+              this->subtitles[this->num_subtitles].t0 = t0;
+              this->subtitles[this->num_subtitles].t1 = t1;
+              this->num_subtitles++;
+            }
+            need=need_id;
+          }
+          else {
+            strcat(text,str);
+          }
+          break;
+      }
+      fgets2(str,sizeof(str),f);
+    }
+
+    fclose(f);
+
+    /* fprintf(stderr,"  %u subtitles loaded.\n", this->num_subtitles); */
+
+    return this->num_subtitles;
+#else
+    return 0;
+#endif
+}
+
+void free_subtitles(ff2theora this)
+{
+    size_t i,n;
+    for (i=0; i<this->n_kate_streams; ++i) {
+        ff2theora_kate_stream *ks=this->kate_streams+i;
+        for (n=0; n<ks->num_subtitles; ++n) free(ks->subtitles[n].text);
+        free(ks->subtitles);
+    }
+    free(this->kate_streams);
+}
+

Copied: trunk/ffmpeg2theora/src/subtitles.h (from rev 14949, trunk/ffmpeg2theora/subtitles.h)
===================================================================
--- trunk/ffmpeg2theora/src/subtitles.h	                        (rev 0)
+++ trunk/ffmpeg2theora/src/subtitles.h	2008-05-23 17:56:21 UTC (rev 14950)
@@ -0,0 +1,32 @@
+#ifndef _F2T_SUBTITLES_H_
+#define _F2T_SUBTITLES_H_
+
+#ifdef HAVE_KATE
+#include "kate/kate.h"
+#endif
+#include "ffmpeg2theora.h"
+
+#ifndef __GNUC__
+/* Windows doesn't have strcasecmp but stricmp (at least, DOS had)
+   (or was that strcmpi ? Might have been Borland C) */
+#define strcasecmp(s1, s2) stricmp(s1, s2)
+#endif
+
+
+#define SUPPORTED_ENCODINGS "utf-8, utf8, iso-8859-1, latin1"
+
+static void add_kate_stream(ff2theora this);
+extern int load_subtitles(ff2theora_kate_stream *this);
+extern void free_subtitles(ff2theora this);
+
+extern void set_subtitles_file(ff2theora this,const char *filename);
+extern void set_subtitles_language(ff2theora this,const char *language);
+extern void set_subtitles_category(ff2theora this,const char *category);
+extern void set_subtitles_encoding(ff2theora this,F2T_ENCODING encoding);
+extern void report_unknown_subtitle_encoding(const char *name);
+
+static char *fgets2(char *s,size_t sz,FILE *f);
+static double hmsms2s(int h,int m,int s,int ms);
+static void convert_subtitle_to_utf8(F2T_ENCODING encoding,unsigned char *text);
+#endif
+

Copied: trunk/ffmpeg2theora/src/theorautils.c (from rev 14949, trunk/ffmpeg2theora/theorautils.c)
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.c	                        (rev 0)
+++ trunk/ffmpeg2theora/src/theorautils.c	2008-05-23 17:56:21 UTC (rev 14950)
@@ -0,0 +1,924 @@
+/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
+/*
+ * theorautils.c - Ogg Theora/Ogg Vorbis Abstraction and Muxing
+ * Copyright (C) 2003-2008 <j at v2v.cc>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#include "theora/theora.h"
+#include "vorbis/codec.h"
+#include "vorbis/vorbisenc.h"
+#ifdef HAVE_OGGKATE
+#include "kate/oggkate.h"
+#endif
+
+#include "theorautils.h"
+
+
+
+static double rint(double x)
+{
+  if (x < 0.0)
+    return (double)(int)(x - 0.5);
+  else
+    return (double)(int)(x + 0.5);
+}
+
+void init_info(oggmux_info *info) {
+    info->with_skeleton = 1; /* skeleton is enabled by default    */
+    info->frontend = 0; /*frontend mode*/
+    info->videotime =  0;
+    info->audiotime = 0;
+    info->audio_bytesout = 0;
+    info->video_bytesout = 0;
+    info->kate_bytesout = 0;
+
+    info->videopage_valid = 0;
+    info->audiopage_valid = 0;
+    info->audiopage_buffer_length = 0;
+    info->videopage_buffer_length = 0;
+    info->audiopage = NULL;
+    info->videopage = NULL;
+    info->start_time = time(NULL);
+    info->duration = -1;
+    info->speed_level = -1;
+
+    info->v_pkg=0;
+    info->a_pkg=0;
+    info->k_pkg=0;
+#ifdef OGGMUX_DEBUG
+    info->a_page=0;
+    info->v_page=0;
+    info->k_page=0;
+#endif
+
+    info->with_kate = 0;
+    info->n_kate_streams = 0;
+}
+
+void oggmux_setup_kate_streams(oggmux_info *info, int n_kate_streams)
+{
+    int n;
+
+    info->n_kate_streams = n_kate_streams;
+    if (n_kate_streams == 0) return;
+    info->kate_streams = (oggmux_kate_stream*)malloc(n_kate_streams*sizeof(oggmux_kate_stream));
+    for (n=0; n<n_kate_streams; ++n) {
+        oggmux_kate_stream *ks=info->kate_streams+n;
+        ks->katepage_valid = 0;
+        ks->katepage_buffer_length = 0;
+        ks->katepage = NULL;
+        ks->katetime = 0;
+    }
+}
+
+static void write16le(unsigned char *ptr,ogg_uint16_t v)
+{
+  ptr[0]=v&0xff;
+  ptr[1]=(v>>8)&0xff;
+}
+
+static void write32le(unsigned char *ptr,ogg_uint32_t v)
+{
+  ptr[0]=v&0xff;
+  ptr[1]=(v>>8)&0xff;
+  ptr[2]=(v>>16)&0xff;
+  ptr[3]=(v>>24)&0xff;
+}
+
+static void write64le(unsigned char *ptr,ogg_int64_t v)
+{
+  ogg_uint32_t hi=v>>32;
+  ptr[0]=v&0xff;
+  ptr[1]=(v>>8)&0xff;
+  ptr[2]=(v>>16)&0xff;
+  ptr[3]=(v>>24)&0xff;
+  ptr[4]=hi&0xff;
+  ptr[5]=(hi>>8)&0xff;
+  ptr[6]=(hi>>16)&0xff;
+  ptr[7]=(hi>>24)&0xff;
+}
+
+void add_fishead_packet (oggmux_info *info) {
+    ogg_packet op;
+
+    memset (&op, 0, sizeof (op));
+
+    op.packet = _ogg_calloc (64, sizeof(unsigned char));
+    if (op.packet == NULL) return;
+
+    memset (op.packet, 0, 64);
+    memcpy (op.packet, FISHEAD_IDENTIFIER, 8); /* identifier */
+    write16le(op.packet+8, SKELETON_VERSION_MAJOR); /* version major */
+    write16le(op.packet+10, SKELETON_VERSION_MINOR); /* version minor */
+    write64le(op.packet+12, (ogg_int64_t)0); /* presentationtime numerator */
+    write64le(op.packet+20, (ogg_int64_t)1000); /* presentationtime denominator */
+    write64le(op.packet+28, (ogg_int64_t)0); /* basetime numerator */
+    write64le(op.packet+36, (ogg_int64_t)1000); /* basetime denominator */
+    /* both the numerator are zero hence handled by the memset */
+    write32le(op.packet+44, 0); /* UTC time, set to zero for now */
+
+    op.b_o_s = 1; /* its the first packet of the stream */
+    op.e_o_s = 0; /* its not the last packet of the stream */
+    op.bytes = 64; /* length of the packet in bytes */
+
+    ogg_stream_packetin (&info->so, &op); /* adding the packet to the skeleton stream */
+    _ogg_free (op.packet);
+}
+
+/*
+ * Adds the fishead packets in the skeleton output stream along with the e_o_s packet
+ */
+void add_fisbone_packet (oggmux_info *info) {
+    ogg_packet op;
+    int n;
+
+    if (!info->audio_only) {
+        memset (&op, 0, sizeof (op));
+        op.packet = _ogg_calloc (80, sizeof(unsigned char));
+        if (op.packet == NULL) return;
+
+        memset (op.packet, 0, 80);
+        /* it will be the fisbone packet for the theora video */
+        memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */
+        write32le(op.packet+8, FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */
+        write32le(op.packet+12, info->to.serialno); /* serialno of the theora stream */
+        write32le(op.packet+16, 3); /* number of header packets */
+        /* granulerate, temporal resolution of the bitstream in samples/microsecond */
+        write64le(op.packet+20, info->ti.fps_numerator); /* granulrate numerator */
+        write64le(op.packet+28, info->ti.fps_denominator); /* granulrate denominator */
+        write64le(op.packet+36, 0); /* start granule */
+        write32le(op.packet+44, 0); /* preroll, for theora its 0 */
+        *(op.packet+48) = theora_granule_shift (&info->ti); /* granule shift */
+        memcpy(op.packet+FISBONE_SIZE, "Content-Type: video/theora\r\n", 28); /* message header field, Content-Type */
+
+        op.b_o_s = 0;
+        op.e_o_s = 0;
+        op.bytes = 80; /* size of the packet in bytes */
+
+        ogg_stream_packetin (&info->so, &op);
+        _ogg_free (op.packet);
+    }
+
+    if (!info->video_only) {
+        memset (&op, 0, sizeof (op));
+        op.packet = _ogg_calloc (80, sizeof(unsigned char));
+        if (op.packet == NULL) return;
+
+        memset (op.packet, 0, 80);
+        /* it will be the fisbone packet for the vorbis audio */
+        memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */
+        write32le(op.packet+8, FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */
+        write32le(op.packet+12, info->vo.serialno); /* serialno of the vorbis stream */
+        write32le(op.packet+16, 3); /* number of header packet */
+        /* granulerate, temporal resolution of the bitstream in Hz */
+        write64le(op.packet+20, info->sample_rate); /* granulerate numerator */
+        write64le(op.packet+28, (ogg_int64_t)1); /* granulerate denominator */
+        write64le(op.packet+36, 0); /* start granule */
+        write32le(op.packet+44, 2); /* preroll, for vorbis its 2 */
+        *(op.packet+48) = 0; /* granule shift, always 0 for vorbis */
+        memcpy (op.packet+FISBONE_SIZE, "Content-Type: audio/vorbis\r\n", 28);
+        /* Important: Check the case of Content-Type for correctness */
+
+        op.b_o_s = 0;
+        op.e_o_s = 0;
+        op.bytes = 80;
+
+        ogg_stream_packetin (&info->so, &op);
+        _ogg_free (op.packet);
+    }
+
+#ifdef HAVE_KATE
+    if (info->with_kate) {
+        for (n=0; n<info->n_kate_streams; ++n) {
+            oggmux_kate_stream *ks=info->kate_streams+n;
+	    memset (&op, 0, sizeof (op));
+	    op.packet = _ogg_calloc (86, sizeof(unsigned char));
+	    memset (op.packet, 0, 86);
+            /* it will be the fisbone packet for the kate stream */
+	    memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */
+            write32le(op.packet+8, FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */
+	    write32le(op.packet+12, ks->ko.serialno); /* serialno of the vorbis stream */
+            write32le(op.packet+16, ks->ki.num_headers); /* number of header packet */
+	    /* granulerate, temporal resolution of the bitstream in Hz */
+	    write64le(op.packet+20, ks->ki.gps_numerator); /* granulerate numerator */
+            write64le(op.packet+28, ks->ki.gps_denominator); /* granulerate denominator */
+	    write64le(op.packet+36, 0); /* start granule */
+            write32le(op.packet+44, 0); /* preroll, for kate it's 0 */
+	    *(op.packet+48) = ks->ki.granule_shift; /* granule shift */
+            memcpy (op.packet+FISBONE_SIZE, "Content-Type: application/x-kate\r\n", 34);
+	    /* Important: Check the case of Content-Type for correctness */
+	
+	    op.b_o_s = 0;
+	    op.e_o_s = 0;
+	    op.bytes = 86;
+	
+            ogg_stream_packetin (&info->so, &op);
+	    _ogg_free (op.packet);
+        }
+    }
+#endif
+}
+
+void oggmux_init (oggmux_info *info){
+    ogg_page og;
+    ogg_packet op;
+
+    /* yayness.  Set up Ogg output stream */
+    srand (time (NULL));
+    ogg_stream_init (&info->vo, rand ());
+
+    if(!info->audio_only){
+        ogg_stream_init (&info->to, rand ());    /* oops, add one ot the above */
+        theora_encode_init (&info->td, &info->ti);
+
+        if(info->speed_level >= 0) {
+          int max_speed_level;
+          theora_control(&info->td, TH_ENCCTL_GET_SPLEVEL_MAX, &max_speed_level, sizeof(int));
+          if(info->speed_level > max_speed_level)
+            info->speed_level = max_speed_level;
+          theora_control(&info->td, TH_ENCCTL_SET_SPLEVEL, &info->speed_level, sizeof(int));
+        }
+    }
+    /* init theora done */
+
+    /* initialize Vorbis too, if we have audio. */
+    if(!info->video_only){
+        int ret;
+        vorbis_info_init (&info->vi);
+        /* Encoding using a VBR quality mode.  */
+        if(info->vorbis_quality>-99)
+            ret =vorbis_encode_init_vbr (&info->vi, info->channels,info->sample_rate,info->vorbis_quality);
+        else
+            ret=vorbis_encode_init(&info->vi,info->channels,info->sample_rate,-1,info->vorbis_bitrate,-1);
+
+        if (ret){
+            fprintf (stderr,
+                 "The Vorbis encoder could not set up a mode according to\n"
+                 "the requested quality or bitrate.\n\n");
+            exit (1);
+        }
+
+        vorbis_comment_init (&info->vc);
+        vorbis_comment_add_tag (&info->vc, "ENCODER",PACKAGE_STRING);
+        /* set up the analysis state and auxiliary encoding storage */
+        vorbis_analysis_init (&info->vd, &info->vi);
+        vorbis_block_init (&info->vd, &info->vb);
+
+    }
+    /* audio init done */
+
+    /* initialize kate if we have subtitles */
+    if (info->with_kate) {
+        int ret, n;
+#ifdef HAVE_KATE
+        for (n=0; n<info->n_kate_streams; ++n) {
+            oggmux_kate_stream *ks=info->kate_streams+n;
+            ogg_stream_init (&ks->ko, rand ());    /* oops, add one ot the above */
+            ret = kate_encode_init (&ks->k, &ks->ki);
+            if (ret<0) fprintf(stderr, "kate_encode_init: %d\n",ret);
+            ret = kate_comment_init(&ks->kc);
+            if (ret<0) fprintf(stderr, "kate_comment_init: %d\n",ret);
+            kate_comment_add_tag (&ks->kc, "ENCODER",PACKAGE_STRING);
+        }
+#endif
+    }
+    /* kate init done */
+
+    /* first packet should be skeleton fishead packet, if skeleton is used */
+
+    if (info->with_skeleton) {
+    ogg_stream_init (&info->so, rand());
+    add_fishead_packet (info);
+    if (ogg_stream_pageout (&info->so, &og) != 1){
+            fprintf (stderr, "Internal Ogg library error.\n");
+            exit (1);
+        }
+        fwrite (og.header, 1, og.header_len, info->outfile);
+        fwrite (og.body, 1, og.body_len, info->outfile);
+    }
+
+    /* write the bitstream header packets with proper page interleave */
+
+    /* first packet will get its own page automatically */
+    if(!info->audio_only){
+        theora_encode_header (&info->td, &op);
+        ogg_stream_packetin (&info->to, &op);
+        if (ogg_stream_pageout (&info->to, &og) != 1){
+            fprintf (stderr, "Internal Ogg library error.\n");
+            exit (1);
+        }
+        fwrite (og.header, 1, og.header_len, info->outfile);
+        fwrite (og.body, 1, og.body_len, info->outfile);
+
+        /* create the remaining theora headers */
+        /* theora_comment_init (&info->tc); is called in main() prior to parsing options */
+        theora_comment_add_tag (&info->tc, "ENCODER",PACKAGE_STRING);
+        theora_encode_comment (&info->tc, &op);
+        ogg_stream_packetin (&info->to, &op);
+        _ogg_free (op.packet);
+
+        theora_encode_tables (&info->td, &op);
+        ogg_stream_packetin (&info->to, &op);
+    }
+    if(!info->video_only){
+        ogg_packet header;
+        ogg_packet header_comm;
+        ogg_packet header_code;
+
+        vorbis_analysis_headerout (&info->vd, &info->vc, &header,
+                       &header_comm, &header_code);
+        ogg_stream_packetin (&info->vo, &header);    /* automatically placed in its own
+                                 * page */
+        if (ogg_stream_pageout (&info->vo, &og) != 1){
+            fprintf (stderr, "Internal Ogg library error.\n");
+            exit (1);
+        }
+        fwrite (og.header, 1, og.header_len, info->outfile);
+        fwrite (og.body, 1, og.body_len, info->outfile);
+
+        /* remaining vorbis header packets */
+        ogg_stream_packetin (&info->vo, &header_comm);
+        ogg_stream_packetin (&info->vo, &header_code);
+    }
+
+#ifdef HAVE_KATE
+    if (info->with_kate) {
+        int n;
+        for (n=0; n<info->n_kate_streams; ++n) {
+            oggmux_kate_stream *ks=info->kate_streams+n;
+            int ret;
+            while (1) {
+                ret=kate_ogg_encode_headers(&ks->k,&ks->kc,&op);
+                if (ret==0) {
+                  ogg_stream_packetin(&ks->ko,&op);
+                  ogg_packet_clear(&op);
+                }
+                if (ret<0) fprintf(stderr, "kate_encode_headers: %d\n",ret);
+                if (ret>0) break;
+            }
+
+            /* first header is on a separate page - libogg will do it automatically */
+            ret=ogg_stream_pageout (&ks->ko, &og);
+            if (ret!=1) {
+                fprintf (stderr, "Internal Ogg library error.\n");
+                exit (1);
+            }
+            fwrite (og.header, 1, og.header_len, info->outfile);
+            fwrite (og.body, 1, og.body_len, info->outfile);
+        }
+    }
+#endif
+
+    /* output the appropriate fisbone packets */
+    if (info->with_skeleton) {
+    add_fisbone_packet (info);
+    while (1) {
+        int result = ogg_stream_flush (&info->so, &og);
+            if (result < 0){
+            /* can't get here */
+            fprintf (stderr, "Internal Ogg library error.\n");
+        exit (1);
+            }
+        if (result == 0)
+            break;
+            fwrite (og.header, 1, og.header_len, info->outfile);
+        fwrite (og.body, 1, og.body_len, info->outfile);
+    }
+    }
+
+    if (!info->audio_only) {
+    theora_info_clear(&info->ti);
+    }
+
+    /* Flush the rest of our headers. This ensures
+     * the actual data in each stream will start
+     * on a new page, as per spec. */
+    while (1 && !info->audio_only){
+        int result = ogg_stream_flush (&info->to, &og);
+        if (result < 0){
+            /* can't get here */
+            fprintf (stderr, "Internal Ogg library error.\n");
+            exit (1);
+        }
+        if (result == 0)
+            break;
+        fwrite (og.header, 1, og.header_len, info->outfile);
+        fwrite (og.body, 1, og.body_len, info->outfile);
+    }
+    while (1 && !info->video_only){
+        int result = ogg_stream_flush (&info->vo, &og);
+        if (result < 0){
+            /* can't get here */
+            fprintf (stderr, "Internal Ogg library error.\n");
+            exit (1);
+        }
+        if (result == 0)
+            break;
+        fwrite (og.header, 1, og.header_len,info->outfile);
+        fwrite (og.body, 1, og.body_len, info->outfile);
+    }
+    if (info->with_kate) {
+        int n;
+        for (n=0; n<info->n_kate_streams; ++n) {
+            oggmux_kate_stream *ks=info->kate_streams+n;
+            while (1) {
+                int result = ogg_stream_flush (&ks->ko, &og);
+                if (result < 0){
+                    /* can't get here */
+                    fprintf (stderr, "Internal Ogg library error.\n");
+                    exit (1);
+                }
+                if (result == 0)
+                    break;
+                fwrite (og.header, 1, og.header_len,info->outfile);
+                fwrite (og.body, 1, og.body_len, info->outfile);
+            }
+        }
+    }
+
+    if (info->with_skeleton) {
+    int result;
+
+    /* build and add the e_o_s packet */
+    memset (&op, 0, sizeof (op));
+        op.b_o_s = 0;
+    op.e_o_s = 1; /* its the e_o_s packet */
+        op.granulepos = 0;
+    op.bytes = 0; /* e_o_s packet is an empty packet */
+        ogg_stream_packetin (&info->so, &op);
+
+    result = ogg_stream_flush (&info->so, &og);
+        if (result < 0){
+            /* can't get here */
+            fprintf (stderr, "Internal Ogg library error.\n");
+            exit (1);
+        }
+        fwrite (og.header, 1, og.header_len,info->outfile);
+        fwrite (og.body, 1, og.body_len, info->outfile);
+    }
+}
+
+/**
+ * adds a video frame to the encoding sink
+ * if e_o_s is 1 the end of the logical bitstream will be marked.
+ * @param this ff2theora struct
+ * @param info oggmux_info
+ * @param yuv_buffer
+ * @param e_o_s 1 indicates ond of stream
+ */
+void oggmux_add_video (oggmux_info *info, yuv_buffer *yuv, int e_o_s){
+    ogg_packet op;
+    theora_encode_YUVin (&info->td, yuv);
+    while(theora_encode_packetout (&info->td, e_o_s, &op)) {
+      ogg_stream_packetin (&info->to, &op);
+      info->v_pkg++;
+    }
+}
+
+/**
+ * adds audio samples to encoding sink
+ * @param buffer pointer to buffer
+ * @param bytes bytes in buffer
+ * @param samples samples in buffer
+ * @param e_o_s 1 indicates end of stream.
+ */
+void oggmux_add_audio (oggmux_info *info, int16_t * buffer, int bytes, int samples, int e_o_s){
+    ogg_packet op;
+
+    int i,j, count = 0;
+    float **vorbis_buffer;
+    if (bytes <= 0 && samples <= 0){
+        /* end of audio stream */
+        if(e_o_s)
+            vorbis_analysis_wrote (&info->vd, 0);
+    }
+    else{
+        vorbis_buffer = vorbis_analysis_buffer (&info->vd, samples);
+        /* uninterleave samples */
+        for (i = 0; i < samples; i++){
+            for(j=0;j<info->channels;j++){
+                vorbis_buffer[j][i] = buffer[count++] / 32768.f;
+            }
+        }
+        vorbis_analysis_wrote (&info->vd, samples);
+    }
+    while(vorbis_analysis_blockout (&info->vd, &info->vb) == 1){
+        /* analysis, assume we want to use bitrate management */
+        vorbis_analysis (&info->vb, NULL);
+        vorbis_bitrate_addblock (&info->vb);
+
+        /* weld packets into the bitstream */
+        while (vorbis_bitrate_flushpacket (&info->vd, &op)){
+            ogg_stream_packetin (&info->vo, &op);
+            info->a_pkg++;
+        }
+    }
+}
+
+/**    
+ * adds a subtitles text to the encoding sink
+ * if e_o_s is 1 the end of the logical bitstream will be marked.
+ * @param info oggmux_info
+ * @param idx which kate stream to output to
+ * @param t0 the show time of the text
+ * @param t1 the hide time of the text
+ * @param text the utf-8 text
+ * @param len the number of bytes in the text
+ * @param e_o_s 1 indicates end of stream
+ */
+void oggmux_add_kate_text (oggmux_info *info, int idx, double t0, double t1, const char *text, size_t len, int e_o_s){
+#ifdef HAVE_KATE
+    ogg_packet op;
+    oggmux_kate_stream *ks=info->kate_streams+idx;
+    int ret;
+    ret = kate_ogg_encode_text(&ks->k, t0, t1, text, len, &op);
+    if (ret>=0) {
+        ogg_stream_packetin (&ks->ko, &op);
+        info->k_pkg++;
+    }
+    else {
+        fprintf(stderr, "Failed to encode kate data packet (%f --> %f, [%s]): %d",
+            t0, t1, text, ret);
+    }
+    if(e_o_s) {
+        ret = kate_ogg_encode_finish(&ks->k, -1, &op);
+        if (ret>=0) {
+            ogg_stream_packetin (&ks->ko, &op);
+            info->k_pkg++;
+        }
+        else {
+            fprintf(stderr, "Failed to encode kate end packet: %d", ret);
+        }
+    }
+#endif
+}
+    
+/**    
+ * adds a kate end packet to the encoding sink
+ * @param info oggmux_info
+ * @param idx which kate stream to output to
+ * @param t the time of the end packet
+ */
+void oggmux_add_kate_end_packet (oggmux_info *info, int idx, double t){
+#ifdef HAVE_KATE
+    ogg_packet op;
+    oggmux_kate_stream *ks=info->kate_streams+idx;
+    int ret;
+    ret = kate_ogg_encode_finish(&ks->k, t, &op);
+    if (ret>=0) {
+        ogg_stream_packetin (&ks->ko, &op);
+        info->k_pkg++;
+    }
+    else {
+        fprintf(stderr, "Failed to encode kate end packet: %d", ret);
+    }
+#endif
+}
+    
+static double get_remaining(oggmux_info *info, double timebase) {
+  double remaining = 0;
+  double to_encode, time_so_far;
+
+  if(info->duration != -1 && timebase > 0) {
+    time_so_far = time(NULL) - info->start_time;
+    to_encode = info->duration - timebase;
+    if(to_encode > 0) {
+      remaining = (time_so_far / timebase) * to_encode;
+    }
+  }
+  return remaining;
+}
+
+static void print_stats(oggmux_info *info, double timebase){
+    int hundredths = timebase * 100 - (long) timebase * 100;
+    int seconds = (long) timebase % 60;
+    int minutes = ((long) timebase / 60) % 60;
+    int hours = (long) timebase / 3600;
+    double remaining = get_remaining(info, timebase);
+    int remaining_seconds = (long) remaining % 60;
+    int remaining_minutes = ((long) remaining / 60) % 60;
+    int remaining_hours = (long) remaining / 3600;
+    if(info->frontend) {
+        fprintf (stderr,"\nf2t ;position: %.02lf;audio_kbps: %d;video_kbps: %d;remaining: %.02lf\n",
+           timebase,
+           info->akbps, info->vkbps,
+           remaining
+           );
+
+    }
+    else {
+      if(!remaining) {
+          remaining = time(NULL) - info->start_time;
+          remaining_seconds = (long) remaining % 60;
+          remaining_minutes = ((long) remaining / 60) % 60;
+          remaining_hours = (long) remaining / 3600;
+          fprintf (stderr,"\r      %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time elapsed: %02d:%02d:%02d      ",
+           hours, minutes, seconds, hundredths,
+           info->akbps, info->vkbps,
+           remaining_hours, remaining_minutes, remaining_seconds
+           );
+      }
+      else {
+          fprintf (stderr,"\r      %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time remaining: %02d:%02d:%02d      ",
+           hours, minutes, seconds, hundredths,
+           info->akbps, info->vkbps,
+           remaining_hours, remaining_minutes, remaining_seconds
+           );
+      }
+    }
+}
+
+static void write_audio_page(oggmux_info *info)
+{
+  int ret;
+
+  ret = fwrite(info->audiopage, 1, info->audiopage_len, info->outfile);
+  if(ret < info->audiopage_len) {
+    fprintf(stderr,"error writing audio page\n");
+  }
+  else {
+    info->audio_bytesout += ret;
+  }
+  info->audiopage_valid = 0;
+  info->a_pkg -=ogg_page_packets((ogg_page *)&info->audiopage);
+#ifdef OGGMUX_DEBUG
+  info->a_page++;
+  info->v_page=0;
+  fprintf(stderr,"\naudio page %d (%d pkgs) | pkg remaining %d\n",info->a_page,ogg_page_packets((ogg_page *)&info->audiopage),info->a_pkg);
+#endif
+
+  info->akbps = rint (info->audio_bytesout * 8. / info->audiotime * .001);
+  if(info->akbps<0)
+    info->akbps=0;
+  print_stats(info, info->audiotime);
+}
+
+static void write_video_page(oggmux_info *info)
+{
+  int ret;
+
+  ret = fwrite(info->videopage, 1, info->videopage_len, info->outfile);
+  if(ret < info->videopage_len) {
+    fprintf(stderr,"error writing video page\n");
+  }
+  else {
+    info->video_bytesout += ret;
+  }
+  info->videopage_valid = 0;
+  info->v_pkg -= ogg_page_packets((ogg_page *)&info->videopage);
+#ifdef OGGMUX_DEBUG
+  info->v_page++;
+  info->a_page=0;
+  fprintf(stderr,"\nvideo page %d (%d pkgs) | pkg remaining %d\n",info->v_page,ogg_page_packets((ogg_page *)&info->videopage),info->v_pkg);
+#endif
+
+
+  info->vkbps = rint (info->video_bytesout * 8. / info->videotime * .001);
+  if(info->vkbps<0)
+    info->vkbps=0;
+  print_stats(info, info->videotime);
+}
+
+static void write_kate_page(oggmux_info *info, int idx)
+{
+  int ret;
+  oggmux_kate_stream *ks=info->kate_streams+idx;
+
+  ret = fwrite(ks->katepage, 1, ks->katepage_len, info->outfile);
+  if(ret < ks->katepage_len) {
+    fprintf(stderr,"error writing kate page\n");
+  }
+  else {
+    info->kate_bytesout += ret;
+  }
+  ks->katepage_valid = 0;
+  info->k_pkg -= ogg_page_packets((ogg_page *)&ks->katepage);
+#ifdef OGGMUX_DEBUG
+  ks->k_page++;
+  fprintf(stderr,"\nkate page %d (%d pkgs) | pkg remaining %d\n",ks->k_page,ogg_page_packets((ogg_page *)&info->katepage),info->k_pkg);
+#endif
+
+
+  /*
+  info->kkbps = rint (info->kate_bytesout * 8. / info->katetime * .001);
+  if(info->kkbps<0)
+    info->kkbps=0;
+  print_stats(info, info->katetime);
+  */
+}
+
+static int find_best_valid_kate_page(oggmux_info *info)
+{
+  int n;
+  double t=0.0;
+  int best=-1;
+  if (info->with_kate) for (n=0; n<info->n_kate_streams;++n) {
+    oggmux_kate_stream *ks=info->kate_streams+n;
+    if (ks->katepage_valid) {
+      if (best==-1 || ks->katetime<t) {
+        t=ks->katetime;
+        best=n;
+      }
+    }
+  }
+  return best;
+}
+
+void oggmux_flush (oggmux_info *info, int e_o_s)
+{
+    int n,len;
+    ogg_page og;
+    int best;
+
+    /* flush out the ogg pages to info->outfile */
+    while(1) {
+      /* Get pages for both streams, if not already present, and if available.*/
+      if(!info->audio_only && !info->videopage_valid) {
+        // this way seeking is much better,
+        // not sure if 23 packets  is a good value. it works though
+        int v_next=0;
+        if(info->v_pkg>22 && ogg_stream_flush(&info->to, &og) > 0) {
+          v_next=1;
+        }
+        else if(ogg_stream_pageout(&info->to, &og) > 0) {
+          v_next=1;
+        }
+        if(v_next) {
+          len = og.header_len + og.body_len;
+          if(info->videopage_buffer_length < len) {
+            info->videopage = realloc(info->videopage, len);
+            info->videopage_buffer_length = len;
+          }
+          info->videopage_len = len;
+          memcpy(info->videopage, og.header, og.header_len);
+          memcpy(info->videopage+og.header_len , og.body, og.body_len);
+
+          info->videopage_valid = 1;
+          if(ogg_page_granulepos(&og)>0) {
+            info->videotime = theora_granule_time (&info->td,
+                  ogg_page_granulepos(&og));
+          }
+        }
+      }
+      if(!info->video_only && !info->audiopage_valid) {
+        // this way seeking is much better,
+        // not sure if 23 packets  is a good value. it works though
+        int a_next=0;
+        if(info->a_pkg>22 && ogg_stream_flush(&info->vo, &og) > 0) {
+          a_next=1;
+        }
+        else if(ogg_stream_pageout(&info->vo, &og) > 0) {
+          a_next=1;
+        }
+        if(a_next) {
+          len = og.header_len + og.body_len;
+          if(info->audiopage_buffer_length < len) {
+            info->audiopage = realloc(info->audiopage, len);
+            info->audiopage_buffer_length = len;
+          }
+          info->audiopage_len = len;
+          memcpy(info->audiopage, og.header, og.header_len);
+          memcpy(info->audiopage+og.header_len , og.body, og.body_len);
+
+          info->audiopage_valid = 1;
+          if(ogg_page_granulepos(&og)>0) {
+            info->audiotime= vorbis_granule_time (&info->vd,
+                  ogg_page_granulepos(&og));
+          }
+        }
+      }
+
+#ifdef HAVE_KATE
+      if (info->with_kate) for (n=0; n<info->n_kate_streams; ++n) {
+        oggmux_kate_stream *ks=info->kate_streams+n;
+        if (!ks->katepage_valid) {
+          int k_next=0;
+          /* always flush kate stream */
+          if (ogg_stream_flush(&ks->ko, &og) > 0) {
+            k_next = 1;
+          }
+          if (k_next) {
+            len = og.header_len + og.body_len;
+            if(ks->katepage_buffer_length < len) {
+              ks->katepage = realloc(ks->katepage, len);
+              ks->katepage_buffer_length = len;
+            }
+            ks->katepage_len = len;
+            memcpy(ks->katepage, og.header, og.header_len);
+            memcpy(ks->katepage+og.header_len , og.body, og.body_len);
+
+            ks->katepage_valid = 1;
+            if(ogg_page_granulepos(&og)>0) {
+              ks->katetime= kate_granule_time (&ks->ki,
+                    ogg_page_granulepos(&og));
+            }
+          }
+        }
+      }
+#endif
+
+#ifdef HAVE_KATE
+#define CHECK_KATE_OUTPUT(which) \
+        if (best>=0 && info->kate_streams[best].katetime/*-1.0*/<=info->which##time) { \
+          write_kate_page(info, best); \
+          continue; \
+        }
+#else
+#define CHECK_KATE_OUTPUT(which) ((void)0)
+#endif
+
+      best=find_best_valid_kate_page(info);
+
+      if(info->video_only && info->videopage_valid) {
+        CHECK_KATE_OUTPUT(video);
+        write_video_page(info);
+      }
+      else if(info->audio_only && info->audiopage_valid) {
+        CHECK_KATE_OUTPUT(audio);
+        write_audio_page(info);
+      }
+      /* We're using both. We can output only:
+       *  a) If we have valid pages for both
+       *  b) At EOS, for the remaining stream.
+       */
+      else if(info->videopage_valid && info->audiopage_valid) {
+        /* Make sure they're in the right order. */
+        if(info->videotime <= info->audiotime) {
+          CHECK_KATE_OUTPUT(video);
+          write_video_page(info);
+        }
+        else {
+          CHECK_KATE_OUTPUT(audio);
+          write_audio_page(info);
+        }
+      }
+      else if(e_o_s && best>=0) {
+          write_kate_page(info, best);
+      }
+      else if(e_o_s && info->videopage_valid) {
+          write_video_page(info);
+      }
+      else if(e_o_s && info->audiopage_valid) {
+          write_audio_page(info);
+      }
+      else {
+        break; /* Nothing more writable at the moment */
+      }
+    }
+}
+
+void oggmux_close (oggmux_info *info){
+    int n;
+
+    ogg_stream_clear (&info->vo);
+    vorbis_block_clear (&info->vb);
+    vorbis_dsp_clear (&info->vd);
+    vorbis_comment_clear (&info->vc);
+    vorbis_info_clear (&info->vi);
+
+    ogg_stream_clear (&info->to);
+    theora_clear (&info->td);
+
+#ifdef HAVE_KATE
+    for (n=0; n<info->n_kate_streams; ++n) {
+        ogg_stream_clear (&info->kate_streams[n].ko);
+        kate_comment_clear (&info->kate_streams[n].kc);
+        kate_info_clear (&info->kate_streams[n].ki);
+        kate_clear (&info->kate_streams[n].k);
+    }
+#endif
+
+    if (info->outfile && info->outfile != stdout)
+        fclose (info->outfile);
+
+    if(info->videopage)
+      free(info->videopage);
+    if(info->audiopage)
+      free(info->audiopage);
+
+    for (n=0; n<info->n_kate_streams; ++n) {
+        if(info->kate_streams[n].katepage)
+          free(info->kate_streams[n].katepage);
+    }
+}

Copied: trunk/ffmpeg2theora/src/theorautils.h (from rev 14949, trunk/ffmpeg2theora/theorautils.h)
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.h	                        (rev 0)
+++ trunk/ffmpeg2theora/src/theorautils.h	2008-05-23 17:56:21 UTC (rev 14950)
@@ -0,0 +1,143 @@
+/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
+/*
+ * theorautils.h -- Ogg Theora/Ogg Vorbis Abstraction and Muxing
+ * Copyright (C) 2003-2005 <j at v2v.cc>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef _F2T_THEORAUTILS_H_
+#define _F2T_THEORAUTILS_H_
+
+#include <stdint.h>
+#include "theora/theora.h"
+#include "vorbis/codec.h"
+#include "vorbis/vorbisenc.h"
+#ifdef HAVE_KATE
+#include "kate/kate.h"
+#endif
+#include "ogg/ogg.h"
+
+// #define OGGMUX_DEBUG
+
+#define SKELETON_VERSION_MAJOR 3
+#define SKELETON_VERSION_MINOR 0
+#define FISHEAD_IDENTIFIER "fishead\0"
+#define FISBONE_IDENTIFIER "fisbone\0"
+#define FISBONE_SIZE 52
+#define FISBONE_MESSAGE_HEADER_OFFSET 44
+
+typedef struct
+{
+#ifdef HAVE_KATE
+    kate_state k;
+    kate_info ki;
+    kate_comment kc;
+#endif
+    ogg_stream_state ko;    /* take physical pages, weld into a logical
+                             * stream of packets */
+    int katepage_valid;
+    unsigned char *katepage;
+    int katepage_len;
+    int katepage_buffer_length;
+    double katetime;
+}
+oggmux_kate_stream;
+
+typedef struct
+{
+    /* the file the mixed ogg stream is written to */
+    FILE *outfile;
+
+    int audio_only;
+    int video_only;
+    int with_skeleton;
+    int frontend;
+    /* vorbis settings */
+    int sample_rate;
+    int channels;
+    double vorbis_quality;
+    int vorbis_bitrate;
+
+    vorbis_info vi;       /* struct that stores all the static vorbis bitstream settings */
+    vorbis_comment vc;    /* struct that stores all the user comments */
+
+    /* theora settings */
+    theora_info ti;
+    theora_comment tc;
+    int speed_level;
+
+    /* state info */
+    theora_state td;
+    vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
+    vorbis_block vb;     /* local working space for packet->PCM decode */
+
+    int with_kate;
+
+    /* used for muxing */
+    ogg_stream_state to;    /* take physical pages, weld into a logical
+                             * stream of packets */
+    ogg_stream_state vo;    /* take physical pages, weld into a logical
+                             * stream of packets */
+    ogg_stream_state so;    /* take physical pages, weld into a logical
+                             * stream of packets, used for skeleton stream */
+
+    int audiopage_valid;
+    int videopage_valid;
+    unsigned char *audiopage;
+    unsigned char *videopage;
+    int videopage_len;
+    int audiopage_len;
+    int videopage_buffer_length;
+    int audiopage_buffer_length;
+
+    /* some stats */
+    double audiotime;
+    double videotime;
+    double duration;
+
+    int vkbps;
+    int akbps;
+    ogg_int64_t audio_bytesout;
+    ogg_int64_t video_bytesout;
+    ogg_int64_t kate_bytesout;
+    time_t start_time;
+
+    //to do some manual page flusing
+    int v_pkg;
+    int a_pkg;
+    int k_pkg;
+#ifdef OGGMUX_DEBUG
+    int a_page;
+    int v_page;
+    int k_page;
+#endif
+
+    int n_kate_streams;
+    oggmux_kate_stream *kate_streams;
+}
+oggmux_info;
+
+void init_info(oggmux_info *info);
+extern void oggmux_setup_kate_streams(oggmux_info *info, int n_kate_streams);
+extern void oggmux_init (oggmux_info *info);
+extern void oggmux_add_video (oggmux_info *info, yuv_buffer *yuv, int e_o_s);
+extern void oggmux_add_audio (oggmux_info *info, int16_t * readbuffer, int bytesread, int samplesread,int e_o_s);
+extern void oggmux_add_kate_text (oggmux_info *info, int idx, double t0, double t1, const char *text, size_t len,int e_o_s);
+extern void oggmux_add_kate_end_packet (oggmux_info *info, int idx, double t);
+extern void oggmux_flush (oggmux_info *info, int e_o_s);
+extern void oggmux_close (oggmux_info *info);
+
+
+#endif

Deleted: trunk/ffmpeg2theora/subtitles.c
===================================================================
--- trunk/ffmpeg2theora/subtitles.c	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/subtitles.c	2008-05-23 17:56:21 UTC (rev 14950)
@@ -1,293 +0,0 @@
-/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
-/*
- * subtitles.c -- Kate Subtitles
- * Copyright (C) 2007-2008 <j at v2v.cc>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <getopt.h>
-#include <math.h>
-#include <errno.h>
-
-#include "libavformat/avformat.h"
-
-#ifdef WIN32
-#include "fcntl.h"
-#endif
-
-#include "theorautils.h"
-#include "subtitles.h"
-
-
-/**
-  * adds a new kate stream structure
-  */
-static void add_kate_stream(ff2theora this){
-    ff2theora_kate_stream *ks;
-    this->kate_streams=(ff2theora_kate_stream*)realloc(this->kate_streams,(this->n_kate_streams+1)*sizeof(ff2theora_kate_stream));
-    ks=&this->kate_streams[this->n_kate_streams++];
-    ks->filename = NULL;
-    ks->num_subtitles = 0;
-    ks->subtitles = 0;
-    ks->subtitles_count = 0; /* denotes not set yet */
-    ks->subtitles_encoding = ENC_UNSET;
-    strcpy(ks->subtitles_language, "");
-    strcpy(ks->subtitles_category, "");
-}
-
-/*
- * sets the filename of the next subtitles file
- */
-void set_subtitles_file(ff2theora this,const char *filename){
-  size_t n;
-  for (n=0; n<this->n_kate_streams;++n) {
-    if (!this->kate_streams[n].filename) break;
-  }
-  if (n==this->n_kate_streams) add_kate_stream(this);
-  this->kate_streams[n].filename = filename;
-}
-
-/*
- * sets the language of the next subtitles file
- */
-void set_subtitles_language(ff2theora this,const char *language){
-  size_t n;
-  for (n=0; n<this->n_kate_streams;++n) {
-    if (!this->kate_streams[n].subtitles_language[0]) break;
-  }
-  if (n==this->n_kate_streams) add_kate_stream(this);
-  strncpy(this->kate_streams[n].subtitles_language, language, 16);
-  this->kate_streams[n].subtitles_language[15] = 0;
-}
-
-/*
- * sets the category of the next subtitles file
- */
-void set_subtitles_category(ff2theora this,const char *category){
-  size_t n;
-  for (n=0; n<this->n_kate_streams;++n) {
-    if (!this->kate_streams[n].subtitles_category[0]) break;
-  }
-  if (n==this->n_kate_streams) add_kate_stream(this);
-  strncpy(this->kate_streams[n].subtitles_category, category, 16);
-  this->kate_streams[n].subtitles_category[15] = 0;
-}
-
-/**
-  * sets the encoding of the next subtitles file
-  */
-void set_subtitles_encoding(ff2theora this,F2T_ENCODING encoding){
-  size_t n;
-  for (n=0; n<this->n_kate_streams;++n) {
-    if (this->kate_streams[n].subtitles_encoding==ENC_UNSET) break;
-  }
-  if (n==this->n_kate_streams) add_kate_stream(this);
-  this->kate_streams[n].subtitles_encoding = encoding;
-}
-
-
-void report_unknown_subtitle_encoding(const char *name)
-{
-  fprintf(stderr, "Unknown character encoding: %s\n",name);
-  fprintf(stderr, "Valid character encodings are:\n");
-  fprintf(stderr, "  " SUPPORTED_ENCODINGS "\n");
-}
-
-static char *fgets2(char *s,size_t sz,FILE *f)
-{
-    char *ret = fgets(s, sz, f);
-    /* fixup DOS newline character */
-    char *ptr=strchr(s, '\r');
-    if (ptr) *ptr='\n';
-    return ret;
-}
-
-static double hmsms2s(int h,int m,int s,int ms)
-{
-    return h*3600+m*60+s+ms/1000.0;
-}
-
-/* very simple implementation when no iconv */
-static void convert_subtitle_to_utf8(F2T_ENCODING encoding,unsigned char *text)
-{
-  size_t nbytes;
-  unsigned char *ptr,*newtext;
-
-  if (!text || !*text) return;
-
-  switch (encoding) {
-    case ENC_UNSET:
-      /* we don't know what encoding this is, assume utf-8 and we'll yell if it ain't */
-      break;
-    case ENC_UTF8:
-      /* nothing to do, already in utf-8 */
-      break;
-    case ENC_ISO_8859_1:
-      /* simple, characters above 0x7f are broken in two,
-         and code points map to the iso-8859-1 8 bit codes */
-      nbytes=0;
-      for (ptr=text;*ptr;++ptr) {
-        nbytes++;
-        if (0x80&*ptr) nbytes++;
-      }
-      newtext=(unsigned char*)malloc(1+nbytes);
-      if (!newtext) {
-        fprintf(stderr, "Memory allocation failed - cannot convert text\n");
-        return;
-      }
-      nbytes=0;
-      for (ptr=text;*ptr;++ptr) {
-        if (0x80&*ptr) {
-          newtext[nbytes++]=0xc0|((*ptr)>>6);
-          newtext[nbytes++]=0x80|((*ptr)&0x3f);
-        }
-        else {
-          newtext[nbytes++]=*ptr;
-        }
-      }
-      newtext[nbytes++]=0;
-      memcpy(text,newtext,nbytes);
-      free(newtext);
-      break;
-    default:
-      fprintf(stderr, "ERROR: encoding %d not handled in conversion!\n", encoding);
-      break;
-  }
-}
-
-int load_subtitles(ff2theora_kate_stream *this)
-{
-#ifdef HAVE_KATE
-    enum { need_id, need_timing, need_text };
-    int need = need_id;
-    int last_seen_id=0;
-    int ret;
-    int id;
-    static char text[4096];
-    int h0,m0,s0,ms0,h1,m1,s1,ms1;
-    double t0,t1;
-    static char str[4096];
-    int warned=0;
-
-    FILE *f = fopen(this->filename, "r");
-    if (!f) {
-        fprintf(stderr,"WARNING - Failed to open subtitles file %s (%s)\n", this->filename, strerror(errno));
-        return -1;
-    }
-
-    /* first, check for a BOM */
-    ret=fread(str,1,3,f);
-    if (ret<3 || memcmp(str,"\xef\xbb\xbf",3)) {
-      /* No BOM, rewind */
-      fseek(f,0,SEEK_SET);
-    }
-
-    fgets2(str,sizeof(str),f);
-    while (!feof(f)) {
-      switch (need) {
-        case need_id:
-          ret=sscanf(str,"%d\n",&id);
-          if (ret!=1) {
-            fprintf(stderr,"WARNING - Syntax error: %s\n",str);
-            fclose(f);
-            return -1;
-          }
-          if (id!=last_seen_id+1) {
-            fprintf(stderr,"WARNING - non consecutive ids: %s - pretending not to have noticed\n",str);
-          }
-          last_seen_id=id;
-          need=need_timing;
-          strcpy(text,"");
-          break;
-        case need_timing:
-          ret=sscanf(str,"%d:%d:%d%*[.,]%d --> %d:%d:%d%*[.,]%d\n",&h0,&m0,&s0,&ms0,&h1,&m1,&s1,&ms1);
-          if (ret!=8) {
-            fprintf(stderr,"WARNING - Syntax error: %s\n",str);
-            fclose(f);
-            return -1;
-          }
-          else {
-            t0=hmsms2s(h0,m0,s0,ms0);
-            t1=hmsms2s(h1,m1,s1,ms1);
-          }
-          need=need_text;
-          break;
-        case need_text:
-          if (*str=='\n') {
-            convert_subtitle_to_utf8(this->subtitles_encoding,(unsigned char*)text);
-            size_t len = strlen(text);
-            this->subtitles = (ff2theora_subtitle*)realloc(this->subtitles, (this->num_subtitles+1)*sizeof(ff2theora_subtitle));
-            if (!this->subtitles) {
-              fprintf(stderr, "Out of memory\n");
-              fclose(f);
-              return -1;
-            }
-            ret=kate_text_validate(kate_utf8,text,len+1);
-            if (ret<0) {
-              if (!warned) {
-                fprintf(stderr,"WARNING: subtitle %s is not valid utf-8\n",text);
-                fprintf(stderr,"  further invalid subtitles will NOT be flagged\n");
-                warned=1;
-              }
-            }
-            else {
-              /* kill off trailing \n characters */
-              while (len>0) {
-                if (text[len-1]=='\n') text[--len]=0; else break;
-              }
-              this->subtitles[this->num_subtitles].text = (char*)malloc(len+1);
-              memcpy(this->subtitles[this->num_subtitles].text, text, len+1);
-              this->subtitles[this->num_subtitles].len = len;
-              this->subtitles[this->num_subtitles].t0 = t0;
-              this->subtitles[this->num_subtitles].t1 = t1;
-              this->num_subtitles++;
-            }
-            need=need_id;
-          }
-          else {
-            strcat(text,str);
-          }
-          break;
-      }
-      fgets2(str,sizeof(str),f);
-    }
-
-    fclose(f);
-
-    /* fprintf(stderr,"  %u subtitles loaded.\n", this->num_subtitles); */
-
-    return this->num_subtitles;
-#else
-    return 0;
-#endif
-}
-
-void free_subtitles(ff2theora this)
-{
-    size_t i,n;
-    for (i=0; i<this->n_kate_streams; ++i) {
-        ff2theora_kate_stream *ks=this->kate_streams+i;
-        for (n=0; n<ks->num_subtitles; ++n) free(ks->subtitles[n].text);
-        free(ks->subtitles);
-    }
-    free(this->kate_streams);
-}
-

Deleted: trunk/ffmpeg2theora/subtitles.h
===================================================================
--- trunk/ffmpeg2theora/subtitles.h	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/subtitles.h	2008-05-23 17:56:21 UTC (rev 14950)
@@ -1,32 +0,0 @@
-#ifndef _F2T_SUBTITLES_H_
-#define _F2T_SUBTITLES_H_
-
-#ifdef HAVE_KATE
-#include "kate/kate.h"
-#endif
-#include "ffmpeg2theora.h"
-
-#ifndef __GNUC__
-/* Windows doesn't have strcasecmp but stricmp (at least, DOS had)
-   (or was that strcmpi ? Might have been Borland C) */
-#define strcasecmp(s1, s2) stricmp(s1, s2)
-#endif
-
-
-#define SUPPORTED_ENCODINGS "utf-8, utf8, iso-8859-1, latin1"
-
-static void add_kate_stream(ff2theora this);
-extern int load_subtitles(ff2theora_kate_stream *this);
-extern void free_subtitles(ff2theora this);
-
-extern void set_subtitles_file(ff2theora this,const char *filename);
-extern void set_subtitles_language(ff2theora this,const char *language);
-extern void set_subtitles_category(ff2theora this,const char *category);
-extern void set_subtitles_encoding(ff2theora this,F2T_ENCODING encoding);
-extern void report_unknown_subtitle_encoding(const char *name);
-
-static char *fgets2(char *s,size_t sz,FILE *f);
-static double hmsms2s(int h,int m,int s,int ms);
-static void convert_subtitle_to_utf8(F2T_ENCODING encoding,unsigned char *text);
-#endif
-

Deleted: trunk/ffmpeg2theora/theorautils.c
===================================================================
--- trunk/ffmpeg2theora/theorautils.c	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/theorautils.c	2008-05-23 17:56:21 UTC (rev 14950)
@@ -1,924 +0,0 @@
-/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
-/*
- * theorautils.c - Ogg Theora/Ogg Vorbis Abstraction and Muxing
- * Copyright (C) 2003-2008 <j at v2v.cc>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-
-#include "theora/theora.h"
-#include "vorbis/codec.h"
-#include "vorbis/vorbisenc.h"
-#ifdef HAVE_OGGKATE
-#include "kate/oggkate.h"
-#endif
-
-#include "theorautils.h"
-
-
-
-static double rint(double x)
-{
-  if (x < 0.0)
-    return (double)(int)(x - 0.5);
-  else
-    return (double)(int)(x + 0.5);
-}
-
-void init_info(oggmux_info *info) {
-    info->with_skeleton = 1; /* skeleton is enabled by default    */
-    info->frontend = 0; /*frontend mode*/
-    info->videotime =  0;
-    info->audiotime = 0;
-    info->audio_bytesout = 0;
-    info->video_bytesout = 0;
-    info->kate_bytesout = 0;
-
-    info->videopage_valid = 0;
-    info->audiopage_valid = 0;
-    info->audiopage_buffer_length = 0;
-    info->videopage_buffer_length = 0;
-    info->audiopage = NULL;
-    info->videopage = NULL;
-    info->start_time = time(NULL);
-    info->duration = -1;
-    info->speed_level = -1;
-
-    info->v_pkg=0;
-    info->a_pkg=0;
-    info->k_pkg=0;
-#ifdef OGGMUX_DEBUG
-    info->a_page=0;
-    info->v_page=0;
-    info->k_page=0;
-#endif
-
-    info->with_kate = 0;
-    info->n_kate_streams = 0;
-}
-
-void oggmux_setup_kate_streams(oggmux_info *info, int n_kate_streams)
-{
-    int n;
-
-    info->n_kate_streams = n_kate_streams;
-    if (n_kate_streams == 0) return;
-    info->kate_streams = (oggmux_kate_stream*)malloc(n_kate_streams*sizeof(oggmux_kate_stream));
-    for (n=0; n<n_kate_streams; ++n) {
-        oggmux_kate_stream *ks=info->kate_streams+n;
-        ks->katepage_valid = 0;
-        ks->katepage_buffer_length = 0;
-        ks->katepage = NULL;
-        ks->katetime = 0;
-    }
-}
-
-static void write16le(unsigned char *ptr,ogg_uint16_t v)
-{
-  ptr[0]=v&0xff;
-  ptr[1]=(v>>8)&0xff;
-}
-
-static void write32le(unsigned char *ptr,ogg_uint32_t v)
-{
-  ptr[0]=v&0xff;
-  ptr[1]=(v>>8)&0xff;
-  ptr[2]=(v>>16)&0xff;
-  ptr[3]=(v>>24)&0xff;
-}
-
-static void write64le(unsigned char *ptr,ogg_int64_t v)
-{
-  ogg_uint32_t hi=v>>32;
-  ptr[0]=v&0xff;
-  ptr[1]=(v>>8)&0xff;
-  ptr[2]=(v>>16)&0xff;
-  ptr[3]=(v>>24)&0xff;
-  ptr[4]=hi&0xff;
-  ptr[5]=(hi>>8)&0xff;
-  ptr[6]=(hi>>16)&0xff;
-  ptr[7]=(hi>>24)&0xff;
-}
-
-void add_fishead_packet (oggmux_info *info) {
-    ogg_packet op;
-
-    memset (&op, 0, sizeof (op));
-
-    op.packet = _ogg_calloc (64, sizeof(unsigned char));
-    if (op.packet == NULL) return;
-
-    memset (op.packet, 0, 64);
-    memcpy (op.packet, FISHEAD_IDENTIFIER, 8); /* identifier */
-    write16le(op.packet+8, SKELETON_VERSION_MAJOR); /* version major */
-    write16le(op.packet+10, SKELETON_VERSION_MINOR); /* version minor */
-    write64le(op.packet+12, (ogg_int64_t)0); /* presentationtime numerator */
-    write64le(op.packet+20, (ogg_int64_t)1000); /* presentationtime denominator */
-    write64le(op.packet+28, (ogg_int64_t)0); /* basetime numerator */
-    write64le(op.packet+36, (ogg_int64_t)1000); /* basetime denominator */
-    /* both the numerator are zero hence handled by the memset */
-    write32le(op.packet+44, 0); /* UTC time, set to zero for now */
-
-    op.b_o_s = 1; /* its the first packet of the stream */
-    op.e_o_s = 0; /* its not the last packet of the stream */
-    op.bytes = 64; /* length of the packet in bytes */
-
-    ogg_stream_packetin (&info->so, &op); /* adding the packet to the skeleton stream */
-    _ogg_free (op.packet);
-}
-
-/*
- * Adds the fishead packets in the skeleton output stream along with the e_o_s packet
- */
-void add_fisbone_packet (oggmux_info *info) {
-    ogg_packet op;
-    int n;
-
-    if (!info->audio_only) {
-        memset (&op, 0, sizeof (op));
-        op.packet = _ogg_calloc (80, sizeof(unsigned char));
-        if (op.packet == NULL) return;
-
-        memset (op.packet, 0, 80);
-        /* it will be the fisbone packet for the theora video */
-        memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */
-        write32le(op.packet+8, FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */
-        write32le(op.packet+12, info->to.serialno); /* serialno of the theora stream */
-        write32le(op.packet+16, 3); /* number of header packets */
-        /* granulerate, temporal resolution of the bitstream in samples/microsecond */
-        write64le(op.packet+20, info->ti.fps_numerator); /* granulrate numerator */
-        write64le(op.packet+28, info->ti.fps_denominator); /* granulrate denominator */
-        write64le(op.packet+36, 0); /* start granule */
-        write32le(op.packet+44, 0); /* preroll, for theora its 0 */
-        *(op.packet+48) = theora_granule_shift (&info->ti); /* granule shift */
-        memcpy(op.packet+FISBONE_SIZE, "Content-Type: video/theora\r\n", 28); /* message header field, Content-Type */
-
-        op.b_o_s = 0;
-        op.e_o_s = 0;
-        op.bytes = 80; /* size of the packet in bytes */
-
-        ogg_stream_packetin (&info->so, &op);
-        _ogg_free (op.packet);
-    }
-
-    if (!info->video_only) {
-        memset (&op, 0, sizeof (op));
-        op.packet = _ogg_calloc (80, sizeof(unsigned char));
-        if (op.packet == NULL) return;
-
-        memset (op.packet, 0, 80);
-        /* it will be the fisbone packet for the vorbis audio */
-        memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */
-        write32le(op.packet+8, FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */
-        write32le(op.packet+12, info->vo.serialno); /* serialno of the vorbis stream */
-        write32le(op.packet+16, 3); /* number of header packet */
-        /* granulerate, temporal resolution of the bitstream in Hz */
-        write64le(op.packet+20, info->sample_rate); /* granulerate numerator */
-        write64le(op.packet+28, (ogg_int64_t)1); /* granulerate denominator */
-        write64le(op.packet+36, 0); /* start granule */
-        write32le(op.packet+44, 2); /* preroll, for vorbis its 2 */
-        *(op.packet+48) = 0; /* granule shift, always 0 for vorbis */
-        memcpy (op.packet+FISBONE_SIZE, "Content-Type: audio/vorbis\r\n", 28);
-        /* Important: Check the case of Content-Type for correctness */
-
-        op.b_o_s = 0;
-        op.e_o_s = 0;
-        op.bytes = 80;
-
-        ogg_stream_packetin (&info->so, &op);
-        _ogg_free (op.packet);
-    }
-
-#ifdef HAVE_KATE
-    if (info->with_kate) {
-        for (n=0; n<info->n_kate_streams; ++n) {
-            oggmux_kate_stream *ks=info->kate_streams+n;
-	    memset (&op, 0, sizeof (op));
-	    op.packet = _ogg_calloc (86, sizeof(unsigned char));
-	    memset (op.packet, 0, 86);
-            /* it will be the fisbone packet for the kate stream */
-	    memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */
-            write32le(op.packet+8, FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */
-	    write32le(op.packet+12, ks->ko.serialno); /* serialno of the vorbis stream */
-            write32le(op.packet+16, ks->ki.num_headers); /* number of header packet */
-	    /* granulerate, temporal resolution of the bitstream in Hz */
-	    write64le(op.packet+20, ks->ki.gps_numerator); /* granulerate numerator */
-            write64le(op.packet+28, ks->ki.gps_denominator); /* granulerate denominator */
-	    write64le(op.packet+36, 0); /* start granule */
-            write32le(op.packet+44, 0); /* preroll, for kate it's 0 */
-	    *(op.packet+48) = ks->ki.granule_shift; /* granule shift */
-            memcpy (op.packet+FISBONE_SIZE, "Content-Type: application/x-kate\r\n", 34);
-	    /* Important: Check the case of Content-Type for correctness */
-	
-	    op.b_o_s = 0;
-	    op.e_o_s = 0;
-	    op.bytes = 86;
-	
-            ogg_stream_packetin (&info->so, &op);
-	    _ogg_free (op.packet);
-        }
-    }
-#endif
-}
-
-void oggmux_init (oggmux_info *info){
-    ogg_page og;
-    ogg_packet op;
-
-    /* yayness.  Set up Ogg output stream */
-    srand (time (NULL));
-    ogg_stream_init (&info->vo, rand ());
-
-    if(!info->audio_only){
-        ogg_stream_init (&info->to, rand ());    /* oops, add one ot the above */
-        theora_encode_init (&info->td, &info->ti);
-
-        if(info->speed_level >= 0) {
-          int max_speed_level;
-          theora_control(&info->td, TH_ENCCTL_GET_SPLEVEL_MAX, &max_speed_level, sizeof(int));
-          if(info->speed_level > max_speed_level)
-            info->speed_level = max_speed_level;
-          theora_control(&info->td, TH_ENCCTL_SET_SPLEVEL, &info->speed_level, sizeof(int));
-        }
-    }
-    /* init theora done */
-
-    /* initialize Vorbis too, if we have audio. */
-    if(!info->video_only){
-        int ret;
-        vorbis_info_init (&info->vi);
-        /* Encoding using a VBR quality mode.  */
-        if(info->vorbis_quality>-99)
-            ret =vorbis_encode_init_vbr (&info->vi, info->channels,info->sample_rate,info->vorbis_quality);
-        else
-            ret=vorbis_encode_init(&info->vi,info->channels,info->sample_rate,-1,info->vorbis_bitrate,-1);
-
-        if (ret){
-            fprintf (stderr,
-                 "The Vorbis encoder could not set up a mode according to\n"
-                 "the requested quality or bitrate.\n\n");
-            exit (1);
-        }
-
-        vorbis_comment_init (&info->vc);
-        vorbis_comment_add_tag (&info->vc, "ENCODER",PACKAGE_STRING);
-        /* set up the analysis state and auxiliary encoding storage */
-        vorbis_analysis_init (&info->vd, &info->vi);
-        vorbis_block_init (&info->vd, &info->vb);
-
-    }
-    /* audio init done */
-
-    /* initialize kate if we have subtitles */
-    if (info->with_kate) {
-        int ret, n;
-#ifdef HAVE_KATE
-        for (n=0; n<info->n_kate_streams; ++n) {
-            oggmux_kate_stream *ks=info->kate_streams+n;
-            ogg_stream_init (&ks->ko, rand ());    /* oops, add one ot the above */
-            ret = kate_encode_init (&ks->k, &ks->ki);
-            if (ret<0) fprintf(stderr, "kate_encode_init: %d\n",ret);
-            ret = kate_comment_init(&ks->kc);
-            if (ret<0) fprintf(stderr, "kate_comment_init: %d\n",ret);
-            kate_comment_add_tag (&ks->kc, "ENCODER",PACKAGE_STRING);
-        }
-#endif
-    }
-    /* kate init done */
-
-    /* first packet should be skeleton fishead packet, if skeleton is used */
-
-    if (info->with_skeleton) {
-    ogg_stream_init (&info->so, rand());
-    add_fishead_packet (info);
-    if (ogg_stream_pageout (&info->so, &og) != 1){
-            fprintf (stderr, "Internal Ogg library error.\n");
-            exit (1);
-        }
-        fwrite (og.header, 1, og.header_len, info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
-    }
-
-    /* write the bitstream header packets with proper page interleave */
-
-    /* first packet will get its own page automatically */
-    if(!info->audio_only){
-        theora_encode_header (&info->td, &op);
-        ogg_stream_packetin (&info->to, &op);
-        if (ogg_stream_pageout (&info->to, &og) != 1){
-            fprintf (stderr, "Internal Ogg library error.\n");
-            exit (1);
-        }
-        fwrite (og.header, 1, og.header_len, info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
-
-        /* create the remaining theora headers */
-        /* theora_comment_init (&info->tc); is called in main() prior to parsing options */
-        theora_comment_add_tag (&info->tc, "ENCODER",PACKAGE_STRING);
-        theora_encode_comment (&info->tc, &op);
-        ogg_stream_packetin (&info->to, &op);
-        _ogg_free (op.packet);
-
-        theora_encode_tables (&info->td, &op);
-        ogg_stream_packetin (&info->to, &op);
-    }
-    if(!info->video_only){
-        ogg_packet header;
-        ogg_packet header_comm;
-        ogg_packet header_code;
-
-        vorbis_analysis_headerout (&info->vd, &info->vc, &header,
-                       &header_comm, &header_code);
-        ogg_stream_packetin (&info->vo, &header);    /* automatically placed in its own
-                                 * page */
-        if (ogg_stream_pageout (&info->vo, &og) != 1){
-            fprintf (stderr, "Internal Ogg library error.\n");
-            exit (1);
-        }
-        fwrite (og.header, 1, og.header_len, info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
-
-        /* remaining vorbis header packets */
-        ogg_stream_packetin (&info->vo, &header_comm);
-        ogg_stream_packetin (&info->vo, &header_code);
-    }
-
-#ifdef HAVE_KATE
-    if (info->with_kate) {
-        int n;
-        for (n=0; n<info->n_kate_streams; ++n) {
-            oggmux_kate_stream *ks=info->kate_streams+n;
-            int ret;
-            while (1) {
-                ret=kate_ogg_encode_headers(&ks->k,&ks->kc,&op);
-                if (ret==0) {
-                  ogg_stream_packetin(&ks->ko,&op);
-                  ogg_packet_clear(&op);
-                }
-                if (ret<0) fprintf(stderr, "kate_encode_headers: %d\n",ret);
-                if (ret>0) break;
-            }
-
-            /* first header is on a separate page - libogg will do it automatically */
-            ret=ogg_stream_pageout (&ks->ko, &og);
-            if (ret!=1) {
-                fprintf (stderr, "Internal Ogg library error.\n");
-                exit (1);
-            }
-            fwrite (og.header, 1, og.header_len, info->outfile);
-            fwrite (og.body, 1, og.body_len, info->outfile);
-        }
-    }
-#endif
-
-    /* output the appropriate fisbone packets */
-    if (info->with_skeleton) {
-    add_fisbone_packet (info);
-    while (1) {
-        int result = ogg_stream_flush (&info->so, &og);
-            if (result < 0){
-            /* can't get here */
-            fprintf (stderr, "Internal Ogg library error.\n");
-        exit (1);
-            }
-        if (result == 0)
-            break;
-            fwrite (og.header, 1, og.header_len, info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
-    }
-    }
-
-    if (!info->audio_only) {
-    theora_info_clear(&info->ti);
-    }
-
-    /* Flush the rest of our headers. This ensures
-     * the actual data in each stream will start
-     * on a new page, as per spec. */
-    while (1 && !info->audio_only){
-        int result = ogg_stream_flush (&info->to, &og);
-        if (result < 0){
-            /* can't get here */
-            fprintf (stderr, "Internal Ogg library error.\n");
-            exit (1);
-        }
-        if (result == 0)
-            break;
-        fwrite (og.header, 1, og.header_len, info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
-    }
-    while (1 && !info->video_only){
-        int result = ogg_stream_flush (&info->vo, &og);
-        if (result < 0){
-            /* can't get here */
-            fprintf (stderr, "Internal Ogg library error.\n");
-            exit (1);
-        }
-        if (result == 0)
-            break;
-        fwrite (og.header, 1, og.header_len,info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
-    }
-    if (info->with_kate) {
-        int n;
-        for (n=0; n<info->n_kate_streams; ++n) {
-            oggmux_kate_stream *ks=info->kate_streams+n;
-            while (1) {
-                int result = ogg_stream_flush (&ks->ko, &og);
-                if (result < 0){
-                    /* can't get here */
-                    fprintf (stderr, "Internal Ogg library error.\n");
-                    exit (1);
-                }
-                if (result == 0)
-                    break;
-                fwrite (og.header, 1, og.header_len,info->outfile);
-                fwrite (og.body, 1, og.body_len, info->outfile);
-            }
-        }
-    }
-
-    if (info->with_skeleton) {
-    int result;
-
-    /* build and add the e_o_s packet */
-    memset (&op, 0, sizeof (op));
-        op.b_o_s = 0;
-    op.e_o_s = 1; /* its the e_o_s packet */
-        op.granulepos = 0;
-    op.bytes = 0; /* e_o_s packet is an empty packet */
-        ogg_stream_packetin (&info->so, &op);
-
-    result = ogg_stream_flush (&info->so, &og);
-        if (result < 0){
-            /* can't get here */
-            fprintf (stderr, "Internal Ogg library error.\n");
-            exit (1);
-        }
-        fwrite (og.header, 1, og.header_len,info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
-    }
-}
-
-/**
- * adds a video frame to the encoding sink
- * if e_o_s is 1 the end of the logical bitstream will be marked.
- * @param this ff2theora struct
- * @param info oggmux_info
- * @param yuv_buffer
- * @param e_o_s 1 indicates ond of stream
- */
-void oggmux_add_video (oggmux_info *info, yuv_buffer *yuv, int e_o_s){
-    ogg_packet op;
-    theora_encode_YUVin (&info->td, yuv);
-    while(theora_encode_packetout (&info->td, e_o_s, &op)) {
-      ogg_stream_packetin (&info->to, &op);
-      info->v_pkg++;
-    }
-}
-
-/**
- * adds audio samples to encoding sink
- * @param buffer pointer to buffer
- * @param bytes bytes in buffer
- * @param samples samples in buffer
- * @param e_o_s 1 indicates end of stream.
- */
-void oggmux_add_audio (oggmux_info *info, int16_t * buffer, int bytes, int samples, int e_o_s){
-    ogg_packet op;
-
-    int i,j, count = 0;
-    float **vorbis_buffer;
-    if (bytes <= 0 && samples <= 0){
-        /* end of audio stream */
-        if(e_o_s)
-            vorbis_analysis_wrote (&info->vd, 0);
-    }
-    else{
-        vorbis_buffer = vorbis_analysis_buffer (&info->vd, samples);
-        /* uninterleave samples */
-        for (i = 0; i < samples; i++){
-            for(j=0;j<info->channels;j++){
-                vorbis_buffer[j][i] = buffer[count++] / 32768.f;
-            }
-        }
-        vorbis_analysis_wrote (&info->vd, samples);
-    }
-    while(vorbis_analysis_blockout (&info->vd, &info->vb) == 1){
-        /* analysis, assume we want to use bitrate management */
-        vorbis_analysis (&info->vb, NULL);
-        vorbis_bitrate_addblock (&info->vb);
-
-        /* weld packets into the bitstream */
-        while (vorbis_bitrate_flushpacket (&info->vd, &op)){
-            ogg_stream_packetin (&info->vo, &op);
-            info->a_pkg++;
-        }
-    }
-}
-
-/**    
- * adds a subtitles text to the encoding sink
- * if e_o_s is 1 the end of the logical bitstream will be marked.
- * @param info oggmux_info
- * @param idx which kate stream to output to
- * @param t0 the show time of the text
- * @param t1 the hide time of the text
- * @param text the utf-8 text
- * @param len the number of bytes in the text
- * @param e_o_s 1 indicates end of stream
- */
-void oggmux_add_kate_text (oggmux_info *info, int idx, double t0, double t1, const char *text, size_t len, int e_o_s){
-#ifdef HAVE_KATE
-    ogg_packet op;
-    oggmux_kate_stream *ks=info->kate_streams+idx;
-    int ret;
-    ret = kate_ogg_encode_text(&ks->k, t0, t1, text, len, &op);
-    if (ret>=0) {
-        ogg_stream_packetin (&ks->ko, &op);
-        info->k_pkg++;
-    }
-    else {
-        fprintf(stderr, "Failed to encode kate data packet (%f --> %f, [%s]): %d",
-            t0, t1, text, ret);
-    }
-    if(e_o_s) {
-        ret = kate_ogg_encode_finish(&ks->k, -1, &op);
-        if (ret>=0) {
-            ogg_stream_packetin (&ks->ko, &op);
-            info->k_pkg++;
-        }
-        else {
-            fprintf(stderr, "Failed to encode kate end packet: %d", ret);
-        }
-    }
-#endif
-}
-    
-/**    
- * adds a kate end packet to the encoding sink
- * @param info oggmux_info
- * @param idx which kate stream to output to
- * @param t the time of the end packet
- */
-void oggmux_add_kate_end_packet (oggmux_info *info, int idx, double t){
-#ifdef HAVE_KATE
-    ogg_packet op;
-    oggmux_kate_stream *ks=info->kate_streams+idx;
-    int ret;
-    ret = kate_ogg_encode_finish(&ks->k, t, &op);
-    if (ret>=0) {
-        ogg_stream_packetin (&ks->ko, &op);
-        info->k_pkg++;
-    }
-    else {
-        fprintf(stderr, "Failed to encode kate end packet: %d", ret);
-    }
-#endif
-}
-    
-static double get_remaining(oggmux_info *info, double timebase) {
-  double remaining = 0;
-  double to_encode, time_so_far;
-
-  if(info->duration != -1 && timebase > 0) {
-    time_so_far = time(NULL) - info->start_time;
-    to_encode = info->duration - timebase;
-    if(to_encode > 0) {
-      remaining = (time_so_far / timebase) * to_encode;
-    }
-  }
-  return remaining;
-}
-
-static void print_stats(oggmux_info *info, double timebase){
-    int hundredths = timebase * 100 - (long) timebase * 100;
-    int seconds = (long) timebase % 60;
-    int minutes = ((long) timebase / 60) % 60;
-    int hours = (long) timebase / 3600;
-    double remaining = get_remaining(info, timebase);
-    int remaining_seconds = (long) remaining % 60;
-    int remaining_minutes = ((long) remaining / 60) % 60;
-    int remaining_hours = (long) remaining / 3600;
-    if(info->frontend) {
-        fprintf (stderr,"\nf2t ;position: %.02lf;audio_kbps: %d;video_kbps: %d;remaining: %.02lf\n",
-           timebase,
-           info->akbps, info->vkbps,
-           remaining
-           );
-
-    }
-    else {
-      if(!remaining) {
-          remaining = time(NULL) - info->start_time;
-          remaining_seconds = (long) remaining % 60;
-          remaining_minutes = ((long) remaining / 60) % 60;
-          remaining_hours = (long) remaining / 3600;
-          fprintf (stderr,"\r      %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time elapsed: %02d:%02d:%02d      ",
-           hours, minutes, seconds, hundredths,
-           info->akbps, info->vkbps,
-           remaining_hours, remaining_minutes, remaining_seconds
-           );
-      }
-      else {
-          fprintf (stderr,"\r      %d:%02d:%02d.%02d audio: %dkbps video: %dkbps, time remaining: %02d:%02d:%02d      ",
-           hours, minutes, seconds, hundredths,
-           info->akbps, info->vkbps,
-           remaining_hours, remaining_minutes, remaining_seconds
-           );
-      }
-    }
-}
-
-static void write_audio_page(oggmux_info *info)
-{
-  int ret;
-
-  ret = fwrite(info->audiopage, 1, info->audiopage_len, info->outfile);
-  if(ret < info->audiopage_len) {
-    fprintf(stderr,"error writing audio page\n");
-  }
-  else {
-    info->audio_bytesout += ret;
-  }
-  info->audiopage_valid = 0;
-  info->a_pkg -=ogg_page_packets((ogg_page *)&info->audiopage);
-#ifdef OGGMUX_DEBUG
-  info->a_page++;
-  info->v_page=0;
-  fprintf(stderr,"\naudio page %d (%d pkgs) | pkg remaining %d\n",info->a_page,ogg_page_packets((ogg_page *)&info->audiopage),info->a_pkg);
-#endif
-
-  info->akbps = rint (info->audio_bytesout * 8. / info->audiotime * .001);
-  if(info->akbps<0)
-    info->akbps=0;
-  print_stats(info, info->audiotime);
-}
-
-static void write_video_page(oggmux_info *info)
-{
-  int ret;
-
-  ret = fwrite(info->videopage, 1, info->videopage_len, info->outfile);
-  if(ret < info->videopage_len) {
-    fprintf(stderr,"error writing video page\n");
-  }
-  else {
-    info->video_bytesout += ret;
-  }
-  info->videopage_valid = 0;
-  info->v_pkg -= ogg_page_packets((ogg_page *)&info->videopage);
-#ifdef OGGMUX_DEBUG
-  info->v_page++;
-  info->a_page=0;
-  fprintf(stderr,"\nvideo page %d (%d pkgs) | pkg remaining %d\n",info->v_page,ogg_page_packets((ogg_page *)&info->videopage),info->v_pkg);
-#endif
-
-
-  info->vkbps = rint (info->video_bytesout * 8. / info->videotime * .001);
-  if(info->vkbps<0)
-    info->vkbps=0;
-  print_stats(info, info->videotime);
-}
-
-static void write_kate_page(oggmux_info *info, int idx)
-{
-  int ret;
-  oggmux_kate_stream *ks=info->kate_streams+idx;
-
-  ret = fwrite(ks->katepage, 1, ks->katepage_len, info->outfile);
-  if(ret < ks->katepage_len) {
-    fprintf(stderr,"error writing kate page\n");
-  }
-  else {
-    info->kate_bytesout += ret;
-  }
-  ks->katepage_valid = 0;
-  info->k_pkg -= ogg_page_packets((ogg_page *)&ks->katepage);
-#ifdef OGGMUX_DEBUG
-  ks->k_page++;
-  fprintf(stderr,"\nkate page %d (%d pkgs) | pkg remaining %d\n",ks->k_page,ogg_page_packets((ogg_page *)&info->katepage),info->k_pkg);
-#endif
-
-
-  /*
-  info->kkbps = rint (info->kate_bytesout * 8. / info->katetime * .001);
-  if(info->kkbps<0)
-    info->kkbps=0;
-  print_stats(info, info->katetime);
-  */
-}
-
-static int find_best_valid_kate_page(oggmux_info *info)
-{
-  int n;
-  double t=0.0;
-  int best=-1;
-  if (info->with_kate) for (n=0; n<info->n_kate_streams;++n) {
-    oggmux_kate_stream *ks=info->kate_streams+n;
-    if (ks->katepage_valid) {
-      if (best==-1 || ks->katetime<t) {
-        t=ks->katetime;
-        best=n;
-      }
-    }
-  }
-  return best;
-}
-
-void oggmux_flush (oggmux_info *info, int e_o_s)
-{
-    int n,len;
-    ogg_page og;
-    int best;
-
-    /* flush out the ogg pages to info->outfile */
-    while(1) {
-      /* Get pages for both streams, if not already present, and if available.*/
-      if(!info->audio_only && !info->videopage_valid) {
-        // this way seeking is much better,
-        // not sure if 23 packets  is a good value. it works though
-        int v_next=0;
-        if(info->v_pkg>22 && ogg_stream_flush(&info->to, &og) > 0) {
-          v_next=1;
-        }
-        else if(ogg_stream_pageout(&info->to, &og) > 0) {
-          v_next=1;
-        }
-        if(v_next) {
-          len = og.header_len + og.body_len;
-          if(info->videopage_buffer_length < len) {
-            info->videopage = realloc(info->videopage, len);
-            info->videopage_buffer_length = len;
-          }
-          info->videopage_len = len;
-          memcpy(info->videopage, og.header, og.header_len);
-          memcpy(info->videopage+og.header_len , og.body, og.body_len);
-
-          info->videopage_valid = 1;
-          if(ogg_page_granulepos(&og)>0) {
-            info->videotime = theora_granule_time (&info->td,
-                  ogg_page_granulepos(&og));
-          }
-        }
-      }
-      if(!info->video_only && !info->audiopage_valid) {
-        // this way seeking is much better,
-        // not sure if 23 packets  is a good value. it works though
-        int a_next=0;
-        if(info->a_pkg>22 && ogg_stream_flush(&info->vo, &og) > 0) {
-          a_next=1;
-        }
-        else if(ogg_stream_pageout(&info->vo, &og) > 0) {
-          a_next=1;
-        }
-        if(a_next) {
-          len = og.header_len + og.body_len;
-          if(info->audiopage_buffer_length < len) {
-            info->audiopage = realloc(info->audiopage, len);
-            info->audiopage_buffer_length = len;
-          }
-          info->audiopage_len = len;
-          memcpy(info->audiopage, og.header, og.header_len);
-          memcpy(info->audiopage+og.header_len , og.body, og.body_len);
-
-          info->audiopage_valid = 1;
-          if(ogg_page_granulepos(&og)>0) {
-            info->audiotime= vorbis_granule_time (&info->vd,
-                  ogg_page_granulepos(&og));
-          }
-        }
-      }
-
-#ifdef HAVE_KATE
-      if (info->with_kate) for (n=0; n<info->n_kate_streams; ++n) {
-        oggmux_kate_stream *ks=info->kate_streams+n;
-        if (!ks->katepage_valid) {
-          int k_next=0;
-          /* always flush kate stream */
-          if (ogg_stream_flush(&ks->ko, &og) > 0) {
-            k_next = 1;
-          }
-          if (k_next) {
-            len = og.header_len + og.body_len;
-            if(ks->katepage_buffer_length < len) {
-              ks->katepage = realloc(ks->katepage, len);
-              ks->katepage_buffer_length = len;
-            }
-            ks->katepage_len = len;
-            memcpy(ks->katepage, og.header, og.header_len);
-            memcpy(ks->katepage+og.header_len , og.body, og.body_len);
-
-            ks->katepage_valid = 1;
-            if(ogg_page_granulepos(&og)>0) {
-              ks->katetime= kate_granule_time (&ks->ki,
-                    ogg_page_granulepos(&og));
-            }
-          }
-        }
-      }
-#endif
-
-#ifdef HAVE_KATE
-#define CHECK_KATE_OUTPUT(which) \
-        if (best>=0 && info->kate_streams[best].katetime/*-1.0*/<=info->which##time) { \
-          write_kate_page(info, best); \
-          continue; \
-        }
-#else
-#define CHECK_KATE_OUTPUT(which) ((void)0)
-#endif
-
-      best=find_best_valid_kate_page(info);
-
-      if(info->video_only && info->videopage_valid) {
-        CHECK_KATE_OUTPUT(video);
-        write_video_page(info);
-      }
-      else if(info->audio_only && info->audiopage_valid) {
-        CHECK_KATE_OUTPUT(audio);
-        write_audio_page(info);
-      }
-      /* We're using both. We can output only:
-       *  a) If we have valid pages for both
-       *  b) At EOS, for the remaining stream.
-       */
-      else if(info->videopage_valid && info->audiopage_valid) {
-        /* Make sure they're in the right order. */
-        if(info->videotime <= info->audiotime) {
-          CHECK_KATE_OUTPUT(video);
-          write_video_page(info);
-        }
-        else {
-          CHECK_KATE_OUTPUT(audio);
-          write_audio_page(info);
-        }
-      }
-      else if(e_o_s && best>=0) {
-          write_kate_page(info, best);
-      }
-      else if(e_o_s && info->videopage_valid) {
-          write_video_page(info);
-      }
-      else if(e_o_s && info->audiopage_valid) {
-          write_audio_page(info);
-      }
-      else {
-        break; /* Nothing more writable at the moment */
-      }
-    }
-}
-
-void oggmux_close (oggmux_info *info){
-    int n;
-
-    ogg_stream_clear (&info->vo);
-    vorbis_block_clear (&info->vb);
-    vorbis_dsp_clear (&info->vd);
-    vorbis_comment_clear (&info->vc);
-    vorbis_info_clear (&info->vi);
-
-    ogg_stream_clear (&info->to);
-    theora_clear (&info->td);
-
-#ifdef HAVE_KATE
-    for (n=0; n<info->n_kate_streams; ++n) {
-        ogg_stream_clear (&info->kate_streams[n].ko);
-        kate_comment_clear (&info->kate_streams[n].kc);
-        kate_info_clear (&info->kate_streams[n].ki);
-        kate_clear (&info->kate_streams[n].k);
-    }
-#endif
-
-    if (info->outfile && info->outfile != stdout)
-        fclose (info->outfile);
-
-    if(info->videopage)
-      free(info->videopage);
-    if(info->audiopage)
-      free(info->audiopage);
-
-    for (n=0; n<info->n_kate_streams; ++n) {
-        if(info->kate_streams[n].katepage)
-          free(info->kate_streams[n].katepage);
-    }
-}

Deleted: trunk/ffmpeg2theora/theorautils.h
===================================================================
--- trunk/ffmpeg2theora/theorautils.h	2008-05-23 17:55:53 UTC (rev 14949)
+++ trunk/ffmpeg2theora/theorautils.h	2008-05-23 17:56:21 UTC (rev 14950)
@@ -1,143 +0,0 @@
-/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
-/*
- * theorautils.h -- Ogg Theora/Ogg Vorbis Abstraction and Muxing
- * Copyright (C) 2003-2005 <j at v2v.cc>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#ifndef _F2T_THEORAUTILS_H_
-#define _F2T_THEORAUTILS_H_
-
-#include <stdint.h>
-#include "theora/theora.h"
-#include "vorbis/codec.h"
-#include "vorbis/vorbisenc.h"
-#ifdef HAVE_KATE
-#include "kate/kate.h"
-#endif
-#include "ogg/ogg.h"
-
-// #define OGGMUX_DEBUG
-
-#define SKELETON_VERSION_MAJOR 3
-#define SKELETON_VERSION_MINOR 0
-#define FISHEAD_IDENTIFIER "fishead\0"
-#define FISBONE_IDENTIFIER "fisbone\0"
-#define FISBONE_SIZE 52
-#define FISBONE_MESSAGE_HEADER_OFFSET 44
-
-typedef struct
-{
-#ifdef HAVE_KATE
-    kate_state k;
-    kate_info ki;
-    kate_comment kc;
-#endif
-    ogg_stream_state ko;    /* take physical pages, weld into a logical
-                             * stream of packets */
-    int katepage_valid;
-    unsigned char *katepage;
-    int katepage_len;
-    int katepage_buffer_length;
-    double katetime;
-}
-oggmux_kate_stream;
-
-typedef struct
-{
-    /* the file the mixed ogg stream is written to */
-    FILE *outfile;
-
-    int audio_only;
-    int video_only;
-    int with_skeleton;
-    int frontend;
-    /* vorbis settings */
-    int sample_rate;
-    int channels;
-    double vorbis_quality;
-    int vorbis_bitrate;
-
-    vorbis_info vi;       /* struct that stores all the static vorbis bitstream settings */
-    vorbis_comment vc;    /* struct that stores all the user comments */
-
-    /* theora settings */
-    theora_info ti;
-    theora_comment tc;
-    int speed_level;
-
-    /* state info */
-    theora_state td;
-    vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
-    vorbis_block vb;     /* local working space for packet->PCM decode */
-
-    int with_kate;
-
-    /* used for muxing */
-    ogg_stream_state to;    /* take physical pages, weld into a logical
-                             * stream of packets */
-    ogg_stream_state vo;    /* take physical pages, weld into a logical
-                             * stream of packets */
-    ogg_stream_state so;    /* take physical pages, weld into a logical
-                             * stream of packets, used for skeleton stream */
-
-    int audiopage_valid;
-    int videopage_valid;
-    unsigned char *audiopage;
-    unsigned char *videopage;
-    int videopage_len;
-    int audiopage_len;
-    int videopage_buffer_length;
-    int audiopage_buffer_length;
-
-    /* some stats */
-    double audiotime;
-    double videotime;
-    double duration;
-
-    int vkbps;
-    int akbps;
-    ogg_int64_t audio_bytesout;
-    ogg_int64_t video_bytesout;
-    ogg_int64_t kate_bytesout;
-    time_t start_time;
-
-    //to do some manual page flusing
-    int v_pkg;
-    int a_pkg;
-    int k_pkg;
-#ifdef OGGMUX_DEBUG
-    int a_page;
-    int v_page;
-    int k_page;
-#endif
-
-    int n_kate_streams;
-    oggmux_kate_stream *kate_streams;
-}
-oggmux_info;
-
-void init_info(oggmux_info *info);
-extern void oggmux_setup_kate_streams(oggmux_info *info, int n_kate_streams);
-extern void oggmux_init (oggmux_info *info);
-extern void oggmux_add_video (oggmux_info *info, yuv_buffer *yuv, int e_o_s);
-extern void oggmux_add_audio (oggmux_info *info, int16_t * readbuffer, int bytesread, int samplesread,int e_o_s);
-extern void oggmux_add_kate_text (oggmux_info *info, int idx, double t0, double t1, const char *text, size_t len,int e_o_s);
-extern void oggmux_add_kate_end_packet (oggmux_info *info, int idx, double t);
-extern void oggmux_flush (oggmux_info *info, int e_o_s);
-extern void oggmux_close (oggmux_info *info);
-
-
-#endif



More information about the commits mailing list