gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r9826 - in Extractor: . src/include src/main src/plugins


From: gnunet
Subject: [GNUnet-SVN] r9826 - in Extractor: . src/include src/main src/plugins
Date: Sun, 20 Dec 2009 20:55:40 +0100

Author: grothoff
Date: 2009-12-20 20:55:40 +0100 (Sun, 20 Dec 2009)
New Revision: 9826

Modified:
   Extractor/TODO
   Extractor/configure.ac
   Extractor/src/include/extractor.h
   Extractor/src/main/extract.c
   Extractor/src/main/extractor.c
   Extractor/src/plugins/Makefile.am
   Extractor/src/plugins/mime_extractor.c
   Extractor/src/plugins/thumbnailffmpeg_extractor.c
Log:
ffmpeg and related fixes

Modified: Extractor/TODO
===================================================================
--- Extractor/TODO      2009-12-20 15:27:04 UTC (rev 9825)
+++ Extractor/TODO      2009-12-20 19:55:40 UTC (rev 9826)
@@ -10,6 +10,11 @@
 * use "-" in config not to append plugin, but to remove one!
 * document
 * port test cases
+* document special options; we have:
+  - force-kill: plugin process committs suicide after each file
+  - oop-only: plugin is never run in-process 
+  - close-stdout: stdout is closed for the (external) plugin process
+  - close-stderr: stderr is closed for the (external) plugin process
 
 'Unclean' code:
 * ASF

Modified: Extractor/configure.ac
===================================================================
--- Extractor/configure.ac      2009-12-20 15:27:04 UTC (rev 9825)
+++ Extractor/configure.ac      2009-12-20 19:55:40 UTC (rev 9826)
@@ -505,7 +505,7 @@
 if test "x$gn_cv_export_symbols_regex_works" = "xyes"
 then
  LE_LIB_LDFLAGS="$LE_LIB_LDFLAGS -export-symbols-regex 
\"EXTRACTOR_@<:@a-zA-Z0-9_@:>@*\""
- LE_PLUGIN_LDFLAGS="$LE_PLUGIN_LDFLAGS -export-symbols-regex 
\"EXTRACTOR_@<:@a-zA-Z0-9_@:>@*_extract\""
+ LE_PLUGIN_LDFLAGS="$LE_PLUGIN_LDFLAGS -export-symbols-regex 
\"EXTRACTOR_@<:@a-zA-Z0-9_@:>@*_.......\""
 fi
 AC_SUBST(LE_LIB_LDFLAGS)
 AC_SUBST(LE_PLUGIN_LDFLAGS)

Modified: Extractor/src/include/extractor.h
===================================================================
--- Extractor/src/include/extractor.h   2009-12-20 15:27:04 UTC (rev 9825)
+++ Extractor/src/include/extractor.h   2009-12-20 19:55:40 UTC (rev 9826)
@@ -42,26 +42,32 @@
  */
 enum EXTRACTOR_Options
   {
+
     /**
-     * Run plugins in-process.
+     * Run plugin out-of-process, starting the process once the plugin
+     * is to be run.  If a plugin crashes, automatically restart the
+     * respective process for the same file and try once more
+     * (since the crash may be caused by the previous file).  If
+     * the process crashes immediately again, it is not restarted
+     * until the next file.
      */
-    EXTRACTOR_OPTION_NONE = 0,
+    EXTRACTOR_OPTION_DEFAULT_POLICY = 0,
 
     /**
      * Run plugins out-of-process, starting the process
      * once at the time the plugin is loaded.  This will
      * prevent the main process crashing if a plugin dies.
      * Ignored on platforms where out-of-process starts
-     * are not supported.
+     * are not supported (in-process execution will be
+     * attempted, unless the plugin itself forbids it).
      */
-    EXTRACTOR_OPTION_OUT_OF_PROCESS = 1,
+    EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART = 1,
 
     /**
-     * If a plugin crashes, automatically restart the respective
-     * process for the next file.  Implies
-     * EXTRACTOR_OPTION_OUT_OF_PROCESS.
+     * Run plugins in-process.  Unsafe, not recommended,
+     * can be nice for debugging.
      */
-    EXTRACTOR_OPTION_AUTO_RESTART = 2,
+    EXTRACTOR_OPTION_IN_PROCESS = 2,
 
     /**
      * Internal value for plugins that have been disabled.
@@ -478,24 +484,7 @@
                      const char *options,
                      enum EXTRACTOR_Options flags);
 
-
 /**
- * Add a library for keyword extraction at the END of the list.
- * @param prev the previous list of libraries, may be NULL
- * @param library the name of the library (full path)
- * @param options options to give to the library
- * @param flags options to use
- * @return the new list of libraries, always equal to prev
- *         except if prev was NULL and no error occurs
- */
-struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_add_last(struct EXTRACTOR_PluginList *prev,
-                         const char *library,
-                         const char *options,
-                         enum EXTRACTOR_Options flags);
-
-
-/**
  * Load multiple libraries as specified by the user.
  *
  * @param config a string given by the user that defines which
@@ -503,8 +492,8 @@
  *        "[[-]LIBRARYNAME[(options)][:[-]LIBRARYNAME[(options)]]]*".
  *        For example, 'mp3:ogg' loads the
  *        mp3 and the ogg plugins. The '-' before the LIBRARYNAME
- *        indicates that the library should be added to the end
- *        of the library list (addLibraryLast).
+ *        indicates that the library should be removed from
+ *        the library list.
  * @param prev the  previous list of libraries, may be NULL
  * @param flags options to use
  * @return the new list of libraries, equal to prev iff an error occured

Modified: Extractor/src/main/extract.c
===================================================================
--- Extractor/src/main/extract.c        2009-12-20 15:27:04 UTC (rev 9825)
+++ Extractor/src/main/extract.c        2009-12-20 19:55:40 UTC (rev 9826)
@@ -170,8 +170,6 @@
   static Help help[] = {
     { 'b', "bibtex", NULL,
       gettext_noop("print output in bibtex format") },
-    { 'B', "binary", "LANG",
-      gettext_noop("use the generic plaintext extractor for the language with 
the 2-letter language code LANG") },
     { 'g', "grep-friendly", NULL,
       gettext_noop("produce grep-friendly output (all results on one line per 
file)") },
     { 'h', "help", NULL,
@@ -557,7 +555,6 @@
   int defaultAll = YES;
   int bibtex = NO;
   int grepfriendly = NO;
-  char * binary = NULL;
   char * name;
   int ret = 0;
   EXTRACTOR_MetaDataProcessor processor = NULL;
@@ -574,7 +571,6 @@
   while (1)
     {
       static struct option long_options[] = {
-       {"binary", 1, 0, 'B'},
        {"bibtex", 0, 0, 'b'},
        {"grep-friendly", 0, 0, 'g'},
        {"help", 0, 0, 'h'},
@@ -610,9 +606,6 @@
            }
          processor = &print_bibtex;
          break;
-       case 'B':
-         binary = optarg;
-         break;
        case 'g':
          grepfriendly = YES;
          if (processor != NULL)
@@ -729,40 +722,27 @@
   /* build list of libraries */
   if (nodefault == NO)
     plugins = EXTRACTOR_plugin_add_defaults (in_process
-                                            ? EXTRACTOR_OPTION_NONE
-                                            : EXTRACTOR_OPTION_AUTO_RESTART);
+                                            ? EXTRACTOR_OPTION_IN_PROCESS
+                                            : EXTRACTOR_OPTION_DEFAULT_POLICY);
   else
     plugins = NULL;
   if (libraries != NULL)
     plugins = EXTRACTOR_plugin_add_config (plugins, 
                                           libraries,
                                           in_process
-                                          ? EXTRACTOR_OPTION_NONE
-                                          : EXTRACTOR_OPTION_AUTO_RESTART);
-  if (binary != NULL) 
-    {
-      name = malloc(strlen(binary) + strlen("printable_") + 1);
-      strcpy(name, "libextractor_printable_");
-      strcat(name, binary);
-      plugins = EXTRACTOR_plugin_add_last(plugins,
-                                         name,
-                                         NULL,
-                                         in_process 
-                                         ? EXTRACTOR_OPTION_NONE
-                                         : EXTRACTOR_OPTION_AUTO_RESTART);
-      free(name);
-    }
+                                          ? EXTRACTOR_OPTION_IN_PROCESS
+                                          : EXTRACTOR_OPTION_DEFAULT_POLICY);
   if (hash != NULL) 
     {
       name = malloc(strlen(hash) + strlen("hash_") + 1);
       strcpy(name, "libextractor_hash_");
       strcat(name, hash);
-      plugins = EXTRACTOR_plugin_add_last(plugins,
-                                         name,
-                                         NULL,
-                                         in_process
-                                         ? EXTRACTOR_OPTION_NONE
-                                         : EXTRACTOR_OPTION_AUTO_RESTART);
+      plugins = EXTRACTOR_plugin_add(plugins,
+                                    name,
+                                    NULL,
+                                    in_process
+                                    ? EXTRACTOR_OPTION_IN_PROCESS
+                                    : EXTRACTOR_OPTION_DEFAULT_POLICY);
       free(name);
     }
 

Modified: Extractor/src/main/extractor.c
===================================================================
--- Extractor/src/main/extractor.c      2009-12-20 15:27:04 UTC (rev 9825)
+++ Extractor/src/main/extractor.c      2009-12-20 19:55:40 UTC (rev 9826)
@@ -105,6 +105,13 @@
   char * plugin_options;
 
   /**
+   * Special options for the plugin
+   * (as returned by the plugin's "options" method;
+   * typically NULL).
+   */
+  const char *specials;
+
+  /**
    * Flags to control how the plugin is executed.
    */
   enum EXTRACTOR_Options flags;
@@ -587,18 +594,22 @@
  * @param lib_handle library to search for the symbol
  * @param prefix prefix to add
  * @param sym_name base name for the symbol
+ * @param options set to special options requested by the plugin
  * @return NULL on error, otherwise pointer to the symbol
  */
 static void *
 get_symbol_with_prefix(void *lib_handle,
-                      const char *prefix)
+                      const char *prefix,
+                      const char **options)
 {
   char *name;
   void *symbol;
   const char *sym_name;
   char *sym;
   char *dot;
+  const char *(*opt_fun)(void);
 
+  *options = NULL;
   sym_name = strstr (prefix, "_");
   if (sym_name == NULL)
     return NULL;
@@ -611,7 +622,6 @@
   sprintf(name,
          "_EXTRACTOR_%s_extract",
          sym);
-  free (sym);
   /* try without '_' first */
   symbol = lt_dlsym(lib_handle, name + 1);
   if (symbol==NULL) 
@@ -636,7 +646,23 @@
       free(first_error);
 #endif
     }
+
+  if (symbol != NULL)
+    {
+      /* get special options */
+      sprintf(name,
+             "_EXTRACTOR_%s_options",
+             sym);
+      /* try without '_' first */
+      opt_fun = lt_dlsym(lib_handle, name + 1);
+      if (opt_fun == NULL) 
+       opt_fun = lt_dlsym(lib_handle, name);
+      if (opt_fun != NULL)     
+       *options = opt_fun ();
+    }
+  free (sym);
   free(name);
+
   return symbol;
 }
 
@@ -652,8 +678,9 @@
 {
   lt_dladvise advise;
 
-  plugin->libname = find_plugin (plugin->short_libname);
   if (plugin->libname == NULL)
+    plugin->libname = find_plugin (plugin->short_libname);
+  if (plugin->libname == NULL)
     {
 #if DEBUG
       fprintf (stderr,
@@ -683,7 +710,8 @@
       return -1;
     }
   plugin->extractMethod = get_symbol_with_prefix (plugin->libraryHandle,
-                                                 plugin->libname);
+                                                 plugin->libname,
+                                                 &plugin->specials);
   if (plugin->extractMethod == NULL) 
     {
 #if DEBUG
@@ -738,47 +766,6 @@
 
 
 /**
- * Add a library for keyword extraction at the END of the list.
- * @param prev the previous list of libraries, may be NULL
- * @param library the name of the library
- * @param options options to give to the library
- * @param flags options to use
- * @return the new list of libraries, always equal to prev
- *         except if prev was NULL and no error occurs
- */
-struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_add_last(struct EXTRACTOR_PluginList *prev,
-                         const char *library,
-                         const char *options,
-                         enum EXTRACTOR_Options flags)
-{
-  struct EXTRACTOR_PluginList *result;
-  struct EXTRACTOR_PluginList *pos;
-  char *libname;
-
-  libname = find_plugin (library);
-  if (libname == NULL)
-    return prev;
-  result = calloc (1, sizeof (struct EXTRACTOR_PluginList));
-  result->next = prev;
-  result->short_libname = strdup (library);
-  result->libname = libname;
-  result->flags = flags;
-  if( options )
-    result->plugin_options = strdup (options);
-  else
-    result->plugin_options = NULL;
-  if (prev == NULL)
-    return result;
-  pos = prev;
-  while (pos->next != NULL)
-    pos = pos->next;
-  pos->next = result;
-  return prev;
-}
-
-
-/**
  * Load multiple libraries as specified by the user.
  *
  * @param config a string given by the user that defines which
@@ -786,8 +773,8 @@
  *        "[[-]LIBRARYNAME[(options)][:[-]LIBRARYNAME[(options)]]]*".
  *        For example, 'mp3:ogg.so' loads the
  *        mp3 and the ogg library. The '-' before the LIBRARYNAME
- *        indicates that the library should be added to the end
- *        of the library list (addLibraryLast).
+ *        indicates that the library should be removed from
+ *        the library list.
  * @param prev the  previous list of libraries, may be NULL
  * @param flags options to use
  * @return the new list of libraries, equal to prev iff an error occured
@@ -836,10 +823,8 @@
       if (cpy[last] == '-')
        {
          last++;
-         prev = EXTRACTOR_plugin_add_last (prev, 
-                                           &cpy[last],
-                                           (lastconf != -1) ? &cpy[lastconf] : 
NULL,
-                                           flags);
+         prev = EXTRACTOR_plugin_remove (prev, 
+                                         &cpy[last]);
        }
       else
        {
@@ -1049,8 +1034,6 @@
 }
 
 
-
-
 /**
  * 'main' function of the child process.
  * Reads shm-filenames from 'in' (line-by-line) and
@@ -1084,6 +1067,19 @@
 #endif
       return;
     }  
+  if ( (plugin->specials != NULL) &&
+       (NULL != strstr (plugin->specials,
+                       "close-stderr")) )
+    {
+      close (2);
+    }
+  if ( (plugin->specials != NULL) &&
+       (NULL != strstr (plugin->specials,
+                       "close-stdout")) )
+    {
+      close (1);
+    }
+
   memset (&hdr, 0, sizeof (hdr));
   fin = fdopen (in, "r");
   while (NULL != fgets (fn, sizeof(fn), fin))
@@ -1109,6 +1105,14 @@
        munmap (ptr, size);
       if (-1 != shmid)
        close (shmid);
+      if ( (plugin->specials != NULL) &&
+          (NULL != strstr (plugin->specials,
+                           "force-kill")) )
+       {
+         /* we're required to die after each file since this
+            plugin only supports a single file at a time */
+         _exit (0);
+       }
     }
   fclose (fin);
   close (out);
@@ -1195,7 +1199,7 @@
     {
       stop_process (plugin);
       plugin->cpid = -1;
-      if (plugin->flags != EXTRACTOR_OPTION_AUTO_RESTART)
+      if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
        plugin->flags = EXTRACTOR_OPTION_DISABLED;
       return 0;
     }
@@ -1208,7 +1212,7 @@
        {
          stop_process (plugin);
          plugin->cpid = -1;
-         if (plugin->flags != EXTRACTOR_OPTION_AUTO_RESTART)
+         if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
            plugin->flags = EXTRACTOR_OPTION_DISABLED;
          return 0;
        }
@@ -1221,7 +1225,7 @@
        {
          stop_process (plugin);          
          plugin->cpid = -1;
-         if (plugin->flags != EXTRACTOR_OPTION_AUTO_RESTART)
+         if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
            plugin->flags = EXTRACTOR_OPTION_DISABLED;
          return 0;
        }
@@ -1241,7 +1245,7 @@
          stop_process (plugin);
          plugin->cpid = -1;
          free (data);
-         if (plugin->flags != EXTRACTOR_OPTION_AUTO_RESTART)
+         if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
            plugin->flags = EXTRACTOR_OPTION_DISABLED;
          return 0;
        }          
@@ -1294,19 +1298,19 @@
     {      
       switch (ppos->flags)
        {
-       case EXTRACTOR_OPTION_NONE:
-         break;
-       case EXTRACTOR_OPTION_OUT_OF_PROCESS:
-         if (0 == ppos->cpid)
+       case EXTRACTOR_OPTION_DEFAULT_POLICY:
+         if ( (0 == ppos->cpid) ||
+              (-1 == ppos->cpid) )
            start_process (ppos);
          want_shm = 1;
          break;
-       case EXTRACTOR_OPTION_AUTO_RESTART:
-         if ( (0 == ppos->cpid) ||
-              (-1 == ppos->cpid) )
+       case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+         if (0 == ppos->cpid)
            start_process (ppos);
          want_shm = 1;
          break;
+       case EXTRACTOR_OPTION_IN_PROCESS:
+         break;
        case EXTRACTOR_OPTION_DISABLED:
          break;
        }      
@@ -1342,13 +1346,30 @@
     {
       flags = ppos->flags;
       if (shmid == -1)
-       flags = EXTRACTOR_OPTION_NONE;
+       flags = EXTRACTOR_OPTION_IN_PROCESS;
       switch (flags)
        {
-       case EXTRACTOR_OPTION_NONE:       
+       case EXTRACTOR_OPTION_DEFAULT_POLICY:
+         if (0 != extract_oop (ppos, fn, proc, proc_cls))
+           return;
+         if (ppos->cpid == -1)
+           {
+             start_process (ppos);
+             if (0 != extract_oop (ppos, fn, proc, proc_cls))
+               return;
+           }
+         break;
+       case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+         if (0 != extract_oop (ppos, fn, proc, proc_cls))
+           return;
+         break;
+       case EXTRACTOR_OPTION_IN_PROCESS:                 
          if (NULL == ppos->extractMethod)  
            plugin_load (ppos);     
-         if ( (NULL != ppos->extractMethod) &&
+         if ( ( (ppos->specials == NULL) ||
+                (NULL == strstr (ppos->specials,
+                                 "oop-only")) ) &&
+              (NULL != ppos->extractMethod) &&
               (0 != ppos->extractMethod (data, 
                                          size, 
                                          proc, 
@@ -1356,11 +1377,6 @@
                                          ppos->plugin_options)) )
            return;
          break;
-       case EXTRACTOR_OPTION_OUT_OF_PROCESS:
-       case EXTRACTOR_OPTION_AUTO_RESTART:
-         if (0 != extract_oop (ppos, fn, proc, proc_cls))
-           return;
-         break;
        case EXTRACTOR_OPTION_DISABLED:
          break;
        }      

Modified: Extractor/src/plugins/Makefile.am
===================================================================
--- Extractor/src/plugins/Makefile.am   2009-12-20 15:27:04 UTC (rev 9825)
+++ Extractor/src/plugins/Makefile.am   2009-12-20 19:55:40 UTC (rev 9826)
@@ -394,23 +394,3 @@
   $(PLUGINFLAGS)
 
 EXTRA_DIST = template_extractor.c 
-
-
-install-exec-hook:
-       mkdir -p $(DESTDIR)$(plugindir) &> /dev/null || true
-       rm -f $(DESTDIR)$(plugindir)/libextractor_thumbnail$(LIBEXT)
-       rm -f $(DESTDIR)$(plugindir)/libextractor_thumbnail.la
-       if test "$(thumbgtk)" != ""; then \
-               $(LN_S) $(plugindir)/libextractor_thumbnailgtk$(LIBEXT) \
-                       $(DESTDIR)$(plugindir)/libextractor_thumbnail$(LIBEXT); 
\
-       else \
-               if test "$(thumbqt)" != ""; then \
-                       $(LN_S) $(plugindir)/libextractor_thumbnailqt$(LIBEXT) \
-                               
$(DESTDIR)$(plugindir)/libextractor_thumbnail$(LIBEXT); \
-               else \
-                       if test "$(thumbffmpeg)" != ""; then \
-                               $(LN_S) 
$(plugindir)/libextractor_thumbnailffmpeg$(LIBEXT) \
-                                       
$(DESTDIR)$(plugindir)/libextractor_thumbnail$(LIBEXT); \
-                       fi \
-               fi \
-       fi

Modified: Extractor/src/plugins/mime_extractor.c
===================================================================
--- Extractor/src/plugins/mime_extractor.c      2009-12-20 15:27:04 UTC (rev 
9825)
+++ Extractor/src/plugins/mime_extractor.c      2009-12-20 19:55:40 UTC (rev 
9826)
@@ -265,7 +265,7 @@
   {"moov", 4, "video/quicktime", DEFAULT},
   {"mdat", 4, "video/quicktime", DEFAULT},
   {"\x8aMNG", 4, "video/x-mng", DEFAULT},
-  {"\x30\x26\xb2\x75\x8e\x66", 6, "video/asf", DEFAULT},        /* same as 
.wmv ? */
+  {"\x30\x26\xb2\x75\x8e\x66", 6, "video/x-ms-asf", DEFAULT},        /* same 
as .wmv ? */
   {"FWS", 3, "application/x-shockwave-flash", DEFAULT},
   {"MThd", 4, "audio/midi", DEFAULT},
   {"ID3", 3, "audio/mpeg", DEFAULT},

Modified: Extractor/src/plugins/thumbnailffmpeg_extractor.c
===================================================================
--- Extractor/src/plugins/thumbnailffmpeg_extractor.c   2009-12-20 15:27:04 UTC 
(rev 9825)
+++ Extractor/src/plugins/thumbnailffmpeg_extractor.c   2009-12-20 19:55:40 UTC 
(rev 9826)
@@ -44,290 +44,28 @@
 
 #define DEBUG 0
 
-struct StreamDescriptor
-{
-  const uint8_t *data;
-  size_t offset;
-  size_t size;
-};
-
-
 void __attribute__ ((constructor)) ffmpeg_lib_init (void)
 {
-#if DEBUG
-  printf ("av_register_all()\n");
-#endif
   av_register_all ();
 }
 
-static int
-stream_read (void *opaque, uint8_t * buf, int buf_size)
-{
-  struct StreamDescriptor *rs = (struct StreamDescriptor *) opaque;
-  size_t len;
-#if DEBUG
-  printf ("read_packet: %zu\n", buf_size);
-#endif
-  if (rs)
-    {
-      if (rs->data == NULL)
-        return -1;
-      if (rs->offset >= rs->size)
-        return 0;
-      len = buf_size;
-      if (rs->offset + len > rs->size)
-        len = rs->size - rs->offset;
-
-      memcpy (buf, rs->data + rs->offset, len);
-      rs->offset += len;
-#if DEBUG
-      printf ("read_packet: len: %zu\n", len);
-#endif
-      return len;
-    }
-  return -1;
-}
-
-static int64_t
-stream_seek (void *opaque, int64_t offset, int whence)
-{
-  struct StreamDescriptor *rs = (struct StreamDescriptor *) opaque;
-  int64_t off_abs;
-#if DEBUG
-  printf ("my_seek: %lld %d\n", offset, whence);
-#endif
-  if (rs)
-    {
-      if (whence == AVSEEK_SIZE)
-        return (int64_t) rs->size;
-      else if (whence == SEEK_CUR)
-        off_abs = (int64_t) rs->offset + offset;
-      else if (whence == SEEK_SET)
-        off_abs = offset;
-      else if (whence == SEEK_END)
-        off_abs = (int64_t) rs->size + offset;
-      else
-        {
-          printf ("whence error %d\n", whence);
-          abort ();
-          return AVERROR (EINVAL);
-        }
-      if (off_abs >= 0 && off_abs < (int64_t) rs->size)
-        rs->offset = (size_t) off_abs;
-      else
-        off_abs = AVERROR (EINVAL);
-      return off_abs;
-    }
-  return -1;
-}
-
-struct MimeToDecoderMapping
-{
-  const char *mime_type;
-  enum CodecID codec_id;
-};
-
-/* map mime image types to a decoder */
-static const struct MimeToDecoderMapping m2d_map[] = {
-  {"image/x-bmp", CODEC_ID_BMP},
-  {"image/gif", CODEC_ID_GIF},
-  {"image/jpeg", CODEC_ID_MJPEG},
-  {"image/jpeg-proprietary", CODEC_ID_MJPEG},
-  {"image/png", CODEC_ID_PNG},
-  {"image/x-png", CODEC_ID_PNG},
-  {"image/tiff", CODEC_ID_TIFF},
-  {"image/x-portable-pixmap", CODEC_ID_PPM},
-#if DOES_THIS_WORK
-  { "video/mpeg", CODEC_ID_MPEG2VIDEO },
-  { "video/x-flv", CODEC_ID_FLV1 },
-  { "video/x-msvideo", CODEC_ID_MSVIDEO1 },
-  { "video/asf", CODEC_ID_WMV1 /* or is this WMV2? */ },
-#endif
-  {NULL, CODEC_ID_NONE}
-};
-
-#define PROBE_MAX (1<<20)
-#define BIOBUF_SIZE (64*1024)
 #define THUMBSIZE 128           /* max dimension in pixels */
 #define MAX_THUMB_SIZE (100*1024)       /* in bytes */
 
 
-/* ******** mime type detection code (copied from mime_extractor) 
************* */
-
-
-/**
- * Detect a file-type.
- * @param data the contents of the file
- * @param len the length of the file
- * @param arg closure...
- * @return 0 if the file does not match, 1 if it does
- **/
-typedef int (*Detector) (const char *data, size_t len, void *arg);
-
-/**
- * Detect a file-type.
- * @param data the contents of the file
- * @param len the length of the file
- * @return always 1
- **/
-static int
-defaultDetector (const char *data, size_t len, void *arg)
+const char *
+EXTRACTOR_thumbnailffmpeg_options ()
 {
-  return 1;
+  return "force-kill;oop-only;close-stderr";
 }
 
-/**
- * Detect a file-type.
- * @param data the contents of the file
- * @param len the length of the file
- * @return always 0
- **/
-static int
-disableDetector (const char *data, size_t len, void *arg)
+const char *
+EXTRACTOR_thumbnail_options ()
 {
-  return 0;
+  return "force-kill;oop-only;close-stderr";
 }
 
-typedef struct ExtraPattern
-{
-  int pos;
-  int len;
-  const char *pattern;
-} ExtraPattern;
 
-/**
- * Define special matching rules for complicated formats...
- **/
-static ExtraPattern xpatterns[] = {
-#define AVI_XPATTERN 0
-  {8, 4, "AVI "},
-  {0, 0, NULL},
-#define WAVE_XPATTERN 2
-  {8, 4, "WAVE"},
-  {0, 0, NULL},
-#define ACON_XPATTERN 12
-  {8, 4, "ACON"},
-  {0, 0, NULL},
-#define CR2_PATTERN 14
-  {8, 3, "CR\x02"},
-  {0, 0, NULL},
-};
-
-/**
- * Detect AVI. A pattern matches if all XPatterns until the next {0,
- * 0, NULL} slot match. OR-ing patterns can be achieved using multiple
- * entries in the main table, so this "AND" (all match) semantics are
- * the only reasonable answer.
- **/
-static int
-xPatternMatcher (const char *data, size_t len, void *cls)
-{
-  ExtraPattern *arg = cls;
-
-  while (arg->pattern != NULL)
-    {
-      if (arg->pos + arg->len > len)
-        return 0;
-      if (0 != memcmp (&data[arg->pos], arg->pattern, arg->len))
-        return 0;
-      arg++;
-    }
-  return 1;
-}
-
-/**
- * Use this detector, if the simple header-prefix matching is
- * sufficient.
- */
-#define DEFAULT &defaultDetector, NULL
-
-/**
- * Use this detector, to disable the mime-type (effectively comment it
- * out).
- */
-#define DISABLED &disableDetector, NULL
-
-/**
- * Select an entry in xpatterns for matching
- */
-#define XPATTERN(a) &xPatternMatcher, &xpatterns[(a)]
-
-
-typedef struct Pattern
-{
-  const char *pattern;
-  int size;
-  const char *mimetype;
-  Detector detector;
-  void *arg;
-} Pattern;
-
-
-static Pattern patterns[] = {
-  /* FIXME: add patterns for other mime-types
-     supported by ffmpeg (also add those to 
-     the mime extractor itself!) */
-  {"\xFF\xD8", 2, "image/jpeg", DEFAULT},
-  {"\211PNG\r\n\032\n", 8, "image/png", DEFAULT},
-  {"/* XPM */", 9, "image/x-xpm", DEFAULT},
-  {"GIF8", 4, "image/gif", DEFAULT},
-  {"P1", 2, "image/x-portable-bitmap", DEFAULT},
-  {"P2", 2, "image/x-portable-graymap", DEFAULT},
-  {"P3", 2, "image/x-portable-pixmap", DEFAULT},
-  {"P4", 2, "image/x-portable-bitmap", DEFAULT},
-  {"P5", 2, "image/x-portable-graymap", DEFAULT},
-  {"P6", 2, "image/x-portable-pixmap", DEFAULT},
-  {"P7", 2, "image/x-portable-anymap", DEFAULT},
-  {"BM", 2, "image/x-bmp", DEFAULT},
-  {"\x89PNG", 4, "image/x-png", DEFAULT},
-  {"hsi1", 4, "image/x-jpeg-proprietary", DEFAULT},
-  {"FLV", 3, "video/x-flv", DEFAULT},
-  {"\x2E\x52\x4d\x46", 4, "video/real", DEFAULT},
-  {"IIN1", 4, "image/tiff", DEFAULT},
-  {"MM\x00\x2a", 4, "image/tiff", DEFAULT},     /* big-endian */
-  {"II\x2a\x00", 4, "image/tiff", DEFAULT},     /* little-endian */
-  {"RIFF", 4, "video/x-msvideo", XPATTERN (AVI_XPATTERN)},
-  {"RIFX", 4, "video/x-msvideo", XPATTERN (AVI_XPATTERN)},
-  {"\x00\x00\x01\xb3", 4, "video/mpeg", DEFAULT},
-  {"\x00\x00\x01\xba", 4, "video/mpeg", DEFAULT},
-
-  /* FIXME: find out if ffmpeg actually makes sense for those below,
-     and add those for which it does make sense to the m2d_map! */
-  {"moov", 4, "video/quicktime", DEFAULT},
-  {"mdat", 4, "video/quicktime", DEFAULT},
-  {"\x8aMNG", 4, "video/x-mng", DEFAULT},
-  {"\x30\x26\xb2\x75\x8e\x66", 6, "video/asf", DEFAULT},  /* same as .wmv ? */
-  {"FWS", 3, "application/x-shockwave-flash", DEFAULT},
-  {NULL, 0, NULL, DISABLED}
-};
-
-
-
-static const char *
-find_mime (const char *data,
-          size_t size)
-{
-  int i;
-
-  i = 0;
-  while (patterns[i].pattern != NULL)
-    {
-      if (size < patterns[i].size)
-        {
-          i++;
-          continue;
-        }
-      if (0 == memcmp (patterns[i].pattern, data, patterns[i].size))
-        {
-          if (patterns[i].detector (data, size, patterns[i].arg))
-           return patterns[i].mimetype;
-       }
-      i++;
-    }
-  return NULL;
-}
-
-
 int 
 EXTRACTOR_thumbnailffmpeg_extract (const unsigned char *data,
                                   size_t size,
@@ -335,210 +73,131 @@
                                   void *proc_cls,
                                   const char *options)
 {
-  int score;
-  AVInputFormat *fmt;
-  AVProbeData pdat;
-  ByteIOContext *bio_ctx = NULL;
-  uint8_t *bio_buffer;
-  struct StreamDescriptor reader_state;
-  AVFormatContext *format_ctx = NULL;
-  AVCodecContext *codec_ctx = NULL;
+  AVProbeData pd; 
   AVPacket packet;
-  int video_stream_index;
-  AVCodec *codec;
+  AVInputFormat *m_pInputFormat;
+  ByteIOContext *bio;
+  struct AVFormatContext *fmt;
+  AVCodecContext *codec_ctx;
+  AVCodec *codec = NULL;
   AVFrame *frame = NULL;
   AVFrame *thumb_frame = NULL;
-  int64_t ts;
-
-  struct SwsContext *scaler_ctx;
+  uint8_t *encoder_output_buffer = NULL;
+  AVCodecContext *enc_codec_ctx = NULL;
+  AVCodec *enc_codec = NULL;
+  const AVFrame *tframe;
+  struct SwsContext *scaler_ctx = NULL;
+  uint8_t *thumb_buffer = NULL;
   int sws_flags = SWS_BILINEAR;
-  uint8_t *thumb_buffer;
-  int thumb_width, thumb_height;
-  int sar_num, sar_den;
-
-  uint8_t *encoder_output_buffer;
+  int64_t ts;
   size_t encoder_output_buffer_size;
-  AVCodecContext *enc_codec_ctx;
-  AVCodec *enc_codec;
-
+  int video_stream_index;
+  int thumb_width;
+  int thumb_height;
+  int sar_num;
+  int sar_den;
   int i;
   int err;
-  int ret = 0;
   int frame_finished;
+  int ret = 0;
 
-  const char *mime;
-  int is_image;
-  enum CodecID image_codec_id;
-
-  bio_ctx = NULL;
-  bio_buffer = NULL;
-  format_ctx = NULL;
-  codec = NULL;
-  frame = NULL;
-  thumb_frame = NULL;
-  thumb_buffer = NULL;
-  scaler_ctx = NULL;
-  encoder_output_buffer = NULL;
-  enc_codec = NULL;
-  enc_codec_ctx = NULL;
-
-  is_image = 0;
-
-  mime = find_mime ((const char*) data, size);
-  if (mime == NULL)
-    return 0;
-  if (mime != NULL)
-    {
-      i = 0;
-      while (m2d_map[i].mime_type != NULL)
-        {
-          if (!strcmp (m2d_map[i].mime_type, mime))
-            {
-              is_image = 1;
-              image_codec_id = m2d_map[i].codec_id;
-              break;
-            }
-          i++;
-        }
-    }
-
 #if DEBUG
-  printf ("is_image: %d codec:%d\n", is_image, image_codec_id);
+  fprintf (stderr,
+          "ffmpeg starting\n");
 #endif
-  if (!is_image)
+  pd.buf_size = size;
+  pd.buf = (void *) data; 
+  pd.filename = "__url_prot";
+ 
+  if (NULL == (m_pInputFormat = av_probe_input_format(&pd, 1))) 
     {
-      pdat.filename = NULL;
-      pdat.buf = (unsigned char *) data;
-      pdat.buf_size = (size > PROBE_MAX) ? PROBE_MAX : size;
-
-      fmt = av_probe_input_format (&pdat, 1);
-      if (fmt == NULL)
-        return 0;
 #if DEBUG
-      printf ("format %p [%s] [%s]\n", fmt, fmt->name, fmt->long_name);
+      fprintf (stderr,
+              "Failed to probe input format\n");
 #endif
-      pdat.buf = (unsigned char *) data;
-      pdat.buf_size = size > PROBE_MAX ? PROBE_MAX : size;
-      score = fmt->read_probe (&pdat);
-#if DEBUG
-      printf ("score: %d\n", score);
-#endif
-      /*if (score < 50) return 0; */
+      return 0;
     }
-
-  if (is_image)
+  m_pInputFormat->flags |= AVFMT_NOFILE;
+  bio = NULL; 
+  url_open_buf(&bio, pd.buf, pd.buf_size, URL_RDONLY);
+  bio->is_streamed = 1;  
+  if ((av_open_input_stream(&fmt, bio, pd.filename, m_pInputFormat, NULL)) < 0)
     {
-      codec_ctx = avcodec_alloc_context ();
-      codec = avcodec_find_decoder (image_codec_id);
-      if (codec != NULL)
-        {
-          if (avcodec_open (codec_ctx, codec) != 0)
-            {
-#if DEBUG
-              printf ("open codec failed\n");
-#endif
-              codec = NULL;
-            }
-        }
+      url_close_buf (bio);
+      fprintf (stderr,
+              "Failed to open input stream\n");
+      return 0;
     }
-  else
+  if (0 > av_find_stream_info (fmt))
     {
-      bio_ctx = malloc (sizeof (ByteIOContext));
-      bio_buffer = malloc (BIOBUF_SIZE);
-
-      reader_state.data = data;
-      reader_state.offset = 0;
-      reader_state.size = size;
-
-      init_put_byte (bio_ctx, bio_buffer,
-                     BIOBUF_SIZE, 0, &reader_state,
-                     stream_read, NULL, stream_seek);
-
-      fmt->flags |= AVFMT_NOFILE;
-      err = av_open_input_stream (&format_ctx, bio_ctx, "", fmt, NULL);
-      if (err < 0)
-        {
-#if DEBUG
-          printf ("couldn't open input stream\n");
-#endif
-          goto out;
-        }
-
-      err = av_find_stream_info (format_ctx);
-      if (err < 0)
-        {
-#if DEBUG
-          printf ("couldn't find codec params\n");
-#endif
-          goto out;
-        }
-
-      for (i = 0; i < format_ctx->nb_streams; i++)
-        {
-          codec_ctx = format_ctx->streams[i]->codec;
-          if (codec_ctx->codec_type == CODEC_TYPE_VIDEO)
-            {
-              video_stream_index = i;
-              codec = avcodec_find_decoder (codec_ctx->codec_id);
-              if (codec == NULL)
-                {
-#if DEBUG
-                  printf ("find_decoder failed\n");
-#endif
-                  break;
-                }
-              err = avcodec_open (codec_ctx, codec);
-              if (err != 0)
-                {
-#if DEBUG
-                  printf ("failed to open codec\n");
-#endif
-                  codec = NULL;
-                }
-              break;
-            }
-        }
+      av_close_input_stream (fmt);
+      url_close_buf (bio);
+      fprintf (stderr,
+              "Failed to read stream info\n");
+      return 0;
     }
 
-  if (codec_ctx == NULL || codec == NULL)
+  codec_ctx = NULL;
+  for (i=0; i<fmt->nb_streams; i++)
     {
-#if DEBUG
-      printf ("failed to open codec");
-#endif
-      goto out;
+      codec_ctx = fmt->streams[i]->codec;
+      if (codec_ctx->codec_type != CODEC_TYPE_VIDEO)
+       continue;
+      codec = avcodec_find_decoder (codec_ctx->codec_id);
+      if (codec == NULL)
+       continue;
+      err = avcodec_open (codec_ctx, codec);
+      if (err != 0)
+       {
+         codec = NULL;
+         continue;
+       }
+      video_stream_index = i;
+      break;
+    } 
+  if ( (codec_ctx == NULL) || 
+       (codec == NULL) ||
+       (codec_ctx->width == 0) || 
+       (codec_ctx->height == 0) )
+    {
+      if (codec_ctx != NULL)
+       avcodec_close (codec_ctx);
+      av_close_input_stream (fmt);
+      url_close_buf (bio);
+      fprintf (stderr,
+              "No video codec found\n");
+      return 0;
     }
+
   frame = avcodec_alloc_frame ();
   if (frame == NULL)
     {
-#if DEBUG
-      printf ("failed to alloc frame");
-#endif
-      goto out;
+      if (codec != NULL)
+       avcodec_close (codec_ctx);
+      av_close_input_stream (fmt);
+      url_close_buf (bio);
+      fprintf (stderr,
+              "Failed to allocate frame\n");
+      return 0;
     }
-
-  if (!is_image)
-    {
 #if DEBUG
-      printf ("duration: %lld\n", format_ctx->duration);
-      if (format_ctx->duration == AV_NOPTS_VALUE)
-        printf ("duration unknown\n");
+  if (fmt->duration == AV_NOPTS_VALUE)
+    fprintf (stderr,
+            "duration unknown\n");
+  else
+    fprintf (stderr,
+            "duration: %lld\n", 
+            fmt->duration);      
 #endif
-      /* TODO: if duration is known seek to to some better place(?) */
-      ts = 10;                  // s
-      ts = ts * AV_TIME_BASE;
-      err = av_seek_frame (format_ctx, -1, ts, 0);
-      if (err >= 0)
-        {
-          avcodec_flush_buffers (codec_ctx);
-        }
-#if DEBUG
-      else
-        printf ("seeking failed %d\n", err);
-#endif
-    }
-
+  /* TODO: if duration is known seek to to some better place(?) */
+  ts = 10;                  /* s */
+  ts = ts * AV_TIME_BASE;
+  err = av_seek_frame (fmt, -1, ts, 0);
+  if (err >= 0)        
+    avcodec_flush_buffers (codec_ctx);        
   frame_finished = 0;
-  if (is_image)
+
+  if (0 /* is_image */)
     {
       avcodec_decode_video (codec_ctx, frame, &frame_finished, data, size);
     }
@@ -546,7 +205,7 @@
     {
       while (1)
         {
-          err = av_read_frame (format_ctx, &packet);
+          err = av_read_frame (fmt, &packet);
           if (err < 0)
             break;
           if (packet.stream_index == video_stream_index)
@@ -564,10 +223,17 @@
           av_free_packet (&packet);
         }
     }
+  if (!frame_finished)
+    {
+      if (frame != NULL)
+       av_free (frame);
+      av_close_input_stream (fmt);
+      free (bio);
+      fprintf (stderr,
+              "Failed to seek to frame\n");
+      return 0;
+    }
 
-  if (!frame_finished || codec_ctx->width == 0 || codec_ctx->height == 0)
-    goto out;
-
   sar_num = codec_ctx->sample_aspect_ratio.num;
   sar_den = codec_ctx->sample_aspect_ratio.den;
   if (sar_num <= 0 || sar_den <= 0)
@@ -575,61 +241,83 @@
       sar_num = 1;
       sar_den = 1;
     }
-  if ((codec_ctx->width * sar_num) / sar_den > codec_ctx->height)
+  if ( (codec_ctx->width < THUMBSIZE) &&
+       (codec_ctx->height < THUMBSIZE) )
     {
-      thumb_width = THUMBSIZE;
-      thumb_height = (thumb_width * codec_ctx->height) /
-        ((codec_ctx->width * sar_num) / sar_den);
+      /* no resize */
+      thumb_width = codec_ctx->width;
+      thumb_height = codec_ctx->height;
+      tframe = frame;
     }
   else
     {
-      thumb_height = THUMBSIZE;
-      thumb_width = (thumb_height *
-                     ((codec_ctx->width * sar_num) / sar_den)) /
-        codec_ctx->height;
-    }
-  if (thumb_width < 8)
-    thumb_width = 8;
-  if (thumb_height < 1)
-    thumb_height = 1;
+      /* need resize */
+      if ((codec_ctx->width * sar_num) / sar_den > codec_ctx->height)
+       {
+         thumb_width = THUMBSIZE;
+         thumb_height = (thumb_width * codec_ctx->height) /
+           ((codec_ctx->width * sar_num) / sar_den);
+       }
+      else
+       {
+         thumb_height = THUMBSIZE;
+         thumb_width = (thumb_height *
+                        ((codec_ctx->width * sar_num) / sar_den)) /
+           codec_ctx->height;
+       }
+      if (thumb_width < 8)
+       thumb_width = 8;
+      if (thumb_height < 1)
+       thumb_height = 1;
 #if DEBUG
-  printf ("thumb dim: %d %d\n", thumb_width, thumb_height);
+      fprintf (stderr,
+              "thumb dim: %d %d\n", 
+              thumb_width,
+              thumb_height);
 #endif
 
-  scaler_ctx =
-    sws_getContext (codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
-                    thumb_width, thumb_height, PIX_FMT_RGB24, sws_flags, NULL,
-                    NULL, NULL);
-  if (scaler_ctx == NULL)
-    {
+      scaler_ctx =
+       sws_getContext (codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
+                       thumb_width, thumb_height, PIX_FMT_RGB24, sws_flags, 
NULL,
+                       NULL, NULL);
+      if (scaler_ctx == NULL)
+       {
 #if DEBUG
-      printf ("failed to alloc scaler\n");
+         fprintf (stderr,
+                  "failed to alloc scaler\n");
 #endif
-      goto out;
-    }
-  thumb_frame = avcodec_alloc_frame ();
-  thumb_buffer =
-    av_malloc (avpicture_get_size (PIX_FMT_RGB24, thumb_width, thumb_height));
-  if (thumb_frame == NULL || thumb_buffer == NULL)
-    {
+         goto out;
+       }
+      thumb_frame = avcodec_alloc_frame ();
+      thumb_buffer =
+       av_malloc (avpicture_get_size (PIX_FMT_RGB24, thumb_width, 
thumb_height));
+      if (thumb_frame == NULL || thumb_buffer == NULL)
+       {
 #if DEBUG
-      printf ("failed to alloc thumb frame\n");
+         fprintf (stderr,
+                  "failed to alloc thumb frame\n");
 #endif
-      goto out;
+         goto out;
+       }
+      avpicture_fill ((AVPicture *) thumb_frame, thumb_buffer,
+                     PIX_FMT_RGB24, thumb_width, thumb_height);
+      
+      sws_scale (scaler_ctx,
+                frame->data, 
+                frame->linesize,
+                0, codec_ctx->height, 
+                thumb_frame->data, 
+                thumb_frame->linesize);
+      tframe = thumb_frame;  
     }
-  avpicture_fill ((AVPicture *) thumb_frame, thumb_buffer,
-                  PIX_FMT_RGB24, thumb_width, thumb_height);
 
-  sws_scale (scaler_ctx,
-             frame->data, frame->linesize,
-             0, codec_ctx->height, thumb_frame->data, thumb_frame->linesize);
-
   encoder_output_buffer_size = MAX_THUMB_SIZE;
   encoder_output_buffer = av_malloc (encoder_output_buffer_size);
   if (encoder_output_buffer == NULL)
     {
 #if DEBUG
-      printf ("couldn't alloc encoder output buf\n");
+      fprintf (stderr,
+              "couldn't alloc encoder output buf\n");
 #endif
       goto out;
     }
@@ -638,7 +326,8 @@
   if (enc_codec == NULL)
     {
 #if DEBUG
-      printf ("couldn't find encoder\n");
+      fprintf (stderr,
+              "couldn't find encoder\n");
 #endif
       goto out;
     }
@@ -650,7 +339,8 @@
   if (avcodec_open (enc_codec_ctx, enc_codec) < 0)
     {
 #if DEBUG
-      printf ("couldn't open encoder\n");
+      fprintf (stderr,
+              "couldn't open encoder\n");
 #endif
       enc_codec = NULL;
       goto out;
@@ -658,7 +348,7 @@
 
   err = avcodec_encode_video (enc_codec_ctx,
                               encoder_output_buffer,
-                              encoder_output_buffer_size, thumb_frame);
+                              encoder_output_buffer_size, tframe);
   if (err > 0)
     ret = proc (proc_cls,
                "thumbnailffmpeg",
@@ -676,21 +366,18 @@
     av_free (encoder_output_buffer);
   if (scaler_ctx != NULL)
     sws_freeContext(scaler_ctx);
-  if (codec != NULL)
+  if (codec_ctx != NULL)
     avcodec_close (codec_ctx);
-  if (format_ctx != NULL)
-    av_close_input_file (format_ctx);
+  if (fmt != NULL)
+    av_close_input_stream (fmt);
   if (frame != NULL)
     av_free (frame);
   if (thumb_buffer != NULL)
     av_free (thumb_buffer);
   if (thumb_frame != NULL)
     av_free (thumb_frame);
-  if (bio_ctx != NULL)
-    free (bio_ctx);
-  if (bio_buffer != NULL)
-    free (bio_buffer);
-
+  if (bio != NULL)
+    url_close_buf (bio);
   return ret;
 }
 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]