[xiph-commits] r16672 - trunk/ffmpeg2theora/src

j at svn.xiph.org j at svn.xiph.org
Thu Oct 29 21:52:14 PDT 2009


Author: j
Date: 2009-10-29 21:52:14 -0700 (Thu, 29 Oct 2009)
New Revision: 16672

Modified:
   trunk/ffmpeg2theora/src/theorautils.c
   trunk/ffmpeg2theora/src/theorautils.h
Log:
Wrap writing encoded ogg pages to disk in a function which determines whether the output file is seekable the first time you write a page.
(patch by Chris Pearce)


Modified: trunk/ffmpeg2theora/src/theorautils.c
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.c	2009-10-30 04:47:28 UTC (rev 16671)
+++ trunk/ffmpeg2theora/src/theorautils.c	2009-10-30 04:52:14 UTC (rev 16672)
@@ -19,11 +19,35 @@
  *
  */
 
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#endif
+#if !defined(_LARGEFILE_SOURCE)
+#define _LARGEFILE_SOURCE
+#endif
+#if !defined(_LARGEFILE64_SOURCE)
+#define _LARGEFILE64_SOURCE
+#endif
+#if !defined(_FILE_OFFSET_BITS)
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#if !defined(off64_t)
+#define off64_t off_t
+#endif
+
+#ifdef WIN32
+#define fseeko fseeko64
+#define ftello ftello64
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <time.h>
+#include <sys/stat.h>
+#include <assert.h>
 
 #include "theora/theoraenc.h"
 #include "vorbis/codec.h"
@@ -44,6 +68,7 @@
 }
 
 void init_info(oggmux_info *info) {
+    info->output_seekable = MAYBE_SEEKABLE;
     info->with_skeleton = 1; /* skeleton is enabled by default    */
     info->frontend = NULL; /*frontend mode*/
     info->videotime =  0;
@@ -124,6 +149,45 @@
     ptr[7]=(hi>>24)&0xff;
 }
 
+/* Write an ogg page to the output file. The first time this is called, we
+   determine the seekable-ness of the output stream, and store the result
+   in info->output_seekable. */
+static void
+write_page(oggmux_info* info, ogg_page* page)
+{
+    int x;
+    assert(page->header_len > 0);
+    x = fwrite(page->header, 1, page->header_len, info->outfile);
+    if (x != page->header_len) {
+        fprintf(stderr, "FAILURE: Failed to write page header to disk!\n");
+        exit(1);
+    }
+    x = fwrite(page->body, 1, page->body_len, info->outfile);
+    if (x != page->body_len) {
+        fprintf(stderr, "FAILURE: Failed to write page body to disk!\n");
+        exit(1);
+    }
+    if (info->output_seekable == MAYBE_SEEKABLE) {
+        /* This is our first page write. Determine if the output
+           is seekable. */
+        ogg_int64_t offset = ftello(info->outfile);
+        if (offset == -1 || fseeko(info->outfile, 0, SEEK_SET) < 0) {
+            info->output_seekable = NOT_SEEKABLE;
+        } else {
+            /* Output appears to be seekable, seek the write cursor back
+               to previous position. */
+            info->output_seekable = SEEKABLE;
+            assert(info->output_seekable > 0);
+            if (fseeko(info->outfile, offset, SEEK_SET) < 0) {
+                fprintf(stderr, "ERROR: failed to seek in seekable output file!?!\n");
+                exit (1);
+            }  
+        }
+    }
+    /* We should know the seekableness by now... */
+    assert(info->output_seekable != MAYBE_SEEKABLE);
+}
+
 void add_fishead_packet (oggmux_info *info) {
     ogg_packet op;
 
@@ -321,8 +385,7 @@
             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_page (info, &og);
     }
 
     /* write the bitstream header packets with proper page interleave */
@@ -341,8 +404,7 @@
                 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_page (info, &og);
         }
 
         /* create the remaining theora headers */
@@ -370,8 +432,7 @@
             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_page (info, &og);
 
         /* remaining vorbis header packets */
         ogg_stream_packetin (&info->vo, &header_comm);
@@ -400,8 +461,7 @@
                 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_page (info, &og);
         }
     }
 #endif
@@ -418,8 +478,7 @@
                 }
             if (result == 0)
                 break;
-                fwrite (og.header, 1, og.header_len, info->outfile);
-            fwrite (og.body, 1, og.body_len, info->outfile);
+            write_page (info, &og);
         }
     }
 
@@ -435,8 +494,7 @@
         }
         if (result == 0)
             break;
-        fwrite (og.header, 1, og.header_len, info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
+        write_page (info, &og);
     }
     while (1 && !info->video_only && info->passno!=1) {
         int result = ogg_stream_flush (&info->vo, &og);
@@ -447,8 +505,7 @@
         }
         if (result == 0)
             break;
-        fwrite (og.header, 1, og.header_len,info->outfile);
-        fwrite (og.body, 1, og.body_len, info->outfile);
+        write_page (info, &og);
     }
 #ifdef HAVE_KATE
     if (info->with_kate && info->passno!=1) {
@@ -464,8 +521,7 @@
                 }
                 if (result == 0)
                     break;
-                fwrite (og.header, 1, og.header_len,info->outfile);
-                fwrite (og.body, 1, og.body_len, info->outfile);
+                write_page (info, &og);
             }
         }
     }
@@ -488,8 +544,7 @@
             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_page (info, &og);
     }
     if (!info->audio_only) {
         th_info_clear(&info->ti);

Modified: trunk/ffmpeg2theora/src/theorautils.h
===================================================================
--- trunk/ffmpeg2theora/src/theorautils.h	2009-10-30 04:47:28 UTC (rev 16671)
+++ trunk/ffmpeg2theora/src/theorautils.h	2009-10-30 04:52:14 UTC (rev 16672)
@@ -55,10 +55,19 @@
 }
 oggmux_kate_stream;
 
+enum SeekableState {
+    MAYBE_SEEKABLE = -1,
+    NOT_SEEKABLE = 0,
+    SEEKABLE = 1,
+};
+
 typedef struct
 {
     /* the file the mixed ogg stream is written to */
     FILE *outfile;
+    /* Greather than zero if outfile is seekable.
+       Value one of SeekableState. */
+    int output_seekable;
 
     char oshash[32];
     int audio_only;



More information about the commits mailing list