[xiph-commits] r14943 - trunk/ffmpeg2theora

j at svn.xiph.org j at svn.xiph.org
Fri May 23 02:50:12 PDT 2008


Author: j
Date: 2008-05-23 02:50:11 -0700 (Fri, 23 May 2008)
New Revision: 14943

Added:
   trunk/ffmpeg2theora/subtitles.c
   trunk/ffmpeg2theora/subtitles.h
Modified:
   trunk/ffmpeg2theora/
   trunk/ffmpeg2theora/Makefile.am
   trunk/ffmpeg2theora/ffmpeg2theora.c
   trunk/ffmpeg2theora/theorautils.h
Log:
* move subtitle functions into extra files subtitles.[ch]
* contrast/brightnes/gama/saturation should not use global variables



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

   + timestamp: 2008-05-23 11:24:20.065999985 +0200
committer: j
properties: 
	branch-nick: ffmpeg2theora

Name: bzr:file-ids
   - 
   + subtitles.c	subtitles.c-20080523092315-berdpbqhudpfrkh7-1
subtitles.h	subtitles.h-20080523092316-79y08zf0g4v687h5-1

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

   + 191 j-20080517230830-he5x8v2m8yrfiw35
192 j-20080518224037-pkmoctzf4qce7tog
193 j-20080518224409-6hbfp3k2ssn6egqa
194 j-20080520111939-dhi52qwbqe7a47cu
195 j-20080523092252-gj9k9db0s67vl7dw
196 j-20080523092420-l0850yrq1qkgz9t0


Modified: trunk/ffmpeg2theora/Makefile.am
===================================================================
--- trunk/ffmpeg2theora/Makefile.am	2008-05-23 09:49:49 UTC (rev 14942)
+++ trunk/ffmpeg2theora/Makefile.am	2008-05-23 09:50:11 UTC (rev 14943)
@@ -2,12 +2,12 @@
 
 SUBDIRS = kino_export
 
-EXTRA_DIST = Makefile.mingw32 theorautils.h get_ffmpeg_svn.sh ffmpeg2theora.1 \
-             get_libkate.sh subtitles.txt 
+EXTRA_DIST = Makefile.mingw32 ffmpeg2theora.h theorautils.h get_ffmpeg_svn.sh ffmpeg2theora.1 \
+             get_libkate.sh subtitles.h subtitles.txt
 
 bin_PROGRAMS = ffmpeg2theora
 
-ffmpeg2theora_SOURCES = ffmpeg2theora.c  theorautils.c
+ffmpeg2theora_SOURCES = ffmpeg2theora.c theorautils.c subtitles.c
 ffmpeg2theora_LDFLAGS = -L$(prefix)/lib @XIPH_LIBS@ @KATE_LIBS@ @FFMPEG_LIBS@
 ffmpeg2theora_CFLAGS = @XIPH_CFLAGS@ @KATE_CFLAGS@ @FFMPEG_CFLAGS@
 

Modified: trunk/ffmpeg2theora/ffmpeg2theora.c
===================================================================
--- trunk/ffmpeg2theora/ffmpeg2theora.c	2008-05-23 09:49:49 UTC (rev 14942)
+++ trunk/ffmpeg2theora/ffmpeg2theora.c	2008-05-23 09:50:11 UTC (rev 14943)
@@ -36,15 +36,13 @@
 #include "vorbis/codec.h"
 #include "vorbis/vorbisenc.h"
 
-#ifdef HAVE_KATE
-#include "kate/kate.h"
-#endif
-
 #ifdef WIN32
 #include "fcntl.h"
 #endif
 
 #include "theorautils.h"
+#include "subtitles.h"
+#include "ffmpeg2theora.h"
 
 #ifdef __linux__
   #define VIDEO4LINUX_ENABLED
@@ -83,11 +81,6 @@
   V2V_PRESET_PADMASTREAM,
 } F2T_PRESETS;
 
-typedef enum {
-  ENC_UNSET,
-  ENC_UTF8,
-  ENC_ISO_8859_1,
-} F2T_ENCODING;
 
 #define PAL_HALF_WIDTH 384
 #define PAL_HALF_HEIGHT 288
@@ -102,361 +95,6 @@
 
 static int sws_flags = SWS_BICUBIC;
 
-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;
-}
-*ff2theora;
-
-
-// gamma lookup table code
-
-// ffmpeg2theora --nosound -f dv -H 32000 -S 0 -v 8 -x 384 -y 288 -G 1.5 input.dv
-static double video_gamma  = 0.0;
-static double video_bright = 0.0;
-static double video_contr  = 0.0;
-static double video_satur  = 1.0;
-static int y_lut_used = 0;
-static int uv_lut_used = 0;
-static unsigned char y_lut[256];
-static unsigned char uv_lut[256];
-
-#define SUPPORTED_ENCODINGS "utf-8, utf8, iso-8859-1, latin1"
-
-static 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;
-}
-
-#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
-
-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;
-  }
-}
-
-static 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
-}
-
-static 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);
-}
-
-static void y_lut_init(unsigned char *lut, double c, double b, double g) {
-    int i;
-    double v;
-
-    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;
-    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)
-            lut[i] = 255;
-        else
-            lut[i] = (unsigned char)(v+0.5);
-    }
-}
-
-
-static void uv_lut_init(unsigned char *lut, double s) {
-    int i;
-    double v;
-
-    if ((s < 0.0) || (s > 100.0)) s = 1.0;
-
-    if (s == 1.0) return;
-    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)
-            lut[i] = 255;
-        else
-            lut[i] = (unsigned char)(v+0.5);
-    }
-}
-
-static void lut_init(double c, double b, double g, double s) {
-  y_lut_init(y_lut, c, b, g);
-  uv_lut_init(uv_lut, s);
-}
-
-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;
-    }
-}
-
-
 oggmux_info info;
 
 static int using_stdin = 0;
@@ -485,72 +123,6 @@
 }
 
 /**
-  * 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
- */
-static 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
- */
-static 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
- */
-static 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
-  */
-static 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;
-}
-
-/**
  * initialize ff2theora with default values
  * @return ff2theora struct
  */
@@ -596,11 +168,97 @@
         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;
 }
 
-void prepare_yuv_buffer(ff2theora this, yuv_buffer *yuv, AVFrame *output_buffered) {
+// 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;
@@ -613,12 +271,12 @@
     yuv->y = output_buffered->data[0];
     yuv->u = output_buffered->data[1];
     yuv->v = output_buffered->data[2];
-    if (y_lut_used) {
-        lut_apply(y_lut, yuv->y, yuv->y, yuv->y_width, yuv->y_height, yuv->y_stride);
+    if (this->y_lut_used) {
+        lut_apply(this->y_lut, yuv->y, yuv->y, yuv->y_width, yuv->y_height, yuv->y_stride);
     }
-    if (uv_lut_used) {
-        lut_apply(uv_lut, yuv->u, yuv->u, yuv->uv_width, yuv->uv_height, yuv->uv_stride);
-        lut_apply(uv_lut, yuv->v, yuv->v, yuv->uv_width, yuv->uv_height, yuv->uv_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);
     }
 }
 
@@ -879,8 +537,7 @@
             fprintf(stderr,"\n");
         }
 
-        if (video_gamma != 0.0 || video_bright != 0.0 || video_contr != 0.0 || video_satur != 1.0)
-            lut_init(video_contr, video_bright, video_gamma, video_satur);
+        lut_init(this);
     }
     if (this->framerate_new.num > 0) {
         fprintf(stderr,"  Resample Framerate: %0.2f => %0.2f\n",
@@ -1841,16 +1498,16 @@
                 convert->audio_quality = -990;
                 break;
             case 'G':
-                video_gamma = atof(optarg);
+                convert->video_gamma = atof(optarg);
                 break;
             case 'C':
-                video_contr = atof(optarg);
+                convert->video_contr = atof(optarg);
                 break;
             case 'Z':
-                video_satur = atof(optarg);
+                convert->video_satur = atof(optarg);
                 break;
             case 'B':
-                video_bright = atof(optarg);
+                convert->video_bright = atof(optarg);
                 break;
             case 'S':
                 convert->sharpness = atoi(optarg);

Added: trunk/ffmpeg2theora/subtitles.c
===================================================================
--- trunk/ffmpeg2theora/subtitles.c	                        (rev 0)
+++ trunk/ffmpeg2theora/subtitles.c	2008-05-23 09:50:11 UTC (rev 14943)
@@ -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
+ */
+static 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
+ */
+static 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
+ */
+static 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
+  */
+static 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;
+}
+
+
+static 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);
+}
+

Added: trunk/ffmpeg2theora/subtitles.h
===================================================================
--- trunk/ffmpeg2theora/subtitles.h	                        (rev 0)
+++ trunk/ffmpeg2theora/subtitles.h	2008-05-23 09:50:11 UTC (rev 14943)
@@ -0,0 +1,29 @@
+#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);
+static void set_subtitles_file(ff2theora this,const char *filename);
+static void set_subtitles_language(ff2theora this,const char *language);
+
+extern int load_subtitles(ff2theora_kate_stream *this);
+extern void free_subtitles(ff2theora this);
+static 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
+

Modified: trunk/ffmpeg2theora/theorautils.h
===================================================================
--- trunk/ffmpeg2theora/theorautils.h	2008-05-23 09:49:49 UTC (rev 14942)
+++ trunk/ffmpeg2theora/theorautils.h	2008-05-23 09:50:11 UTC (rev 14943)
@@ -17,6 +17,8 @@
  * 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"
@@ -127,7 +129,7 @@
 }
 oggmux_info;
 
-extern void init_info(oggmux_info *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);
@@ -136,3 +138,6 @@
 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