gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r9896 - Extractor/src/plugins


From: gnunet
Subject: [GNUnet-SVN] r9896 - Extractor/src/plugins
Date: Fri, 25 Dec 2009 13:47:56 +0100

Author: holindho
Date: 2009-12-25 13:47:56 +0100 (Fri, 25 Dec 2009)
New Revision: 9896

Modified:
   Extractor/src/plugins/thumbnailffmpeg_extractor.c
Log:
re-add single image thumbnailing


Modified: Extractor/src/plugins/thumbnailffmpeg_extractor.c
===================================================================
--- Extractor/src/plugins/thumbnailffmpeg_extractor.c   2009-12-25 07:14:55 UTC 
(rev 9895)
+++ Extractor/src/plugins/thumbnailffmpeg_extractor.c   2009-12-25 12:47:56 UTC 
(rev 9896)
@@ -42,6 +42,8 @@
 #include <libavcodec/avcodec.h>
 #include <libswscale/swscale.h>
 
+#include "mime_extractor.c"
+
 #define DEBUG 0
 
 static void thumbnailffmpeg_av_log_callback(void* ptr, 
@@ -200,13 +202,190 @@
   return err < 0 ? 0 : err;
 }
 
-int 
-EXTRACTOR_thumbnailffmpeg_extract (const unsigned char *data,
-                                  size_t size,
-                                  EXTRACTOR_MetaDataProcessor proc,
-                                  void *proc_cls,
-                                  const char *options)
+struct MIMEToDecoderMapping
 {
+ const char *mime_type;
+ enum CodecID codec_id;
+};
+
+/* map MIME image types to an ffmpeg decoder */
+static const struct MIMEToDecoderMapping m2d_map[] = {
+  {"image/x-bmp", CODEC_ID_BMP},
+  {"image/gif", CODEC_ID_GIF},
+  {"image/jpeg", CODEC_ID_MJPEG},
+  {"image/png", CODEC_ID_PNG},
+  {"image/x-portable-pixmap", CODEC_ID_PPM},
+  {NULL, CODEC_ID_NONE}
+};
+
+static char *mime_type;
+
+static int
+mime_processor (void *cls,
+                        const char *plugin_name,
+                        enum EXTRACTOR_MetaType type,
+                        enum EXTRACTOR_MetaFormat format,
+                        const char *data_mime_type,
+                        const char *data,
+                        size_t data_len)
+{ 
+  switch (format)
+    {
+    case EXTRACTOR_METAFORMAT_UTF8:
+      mime_type = strdup(data);
+      break;
+    default:
+      break;
+    }
+  return 0;
+}
+
+/* calculate the thumbnail dimensions, taking pixel aspect into account */
+static void calculate_thumbnail_dimensions(int src_width,
+                                           int src_height,
+                                           int src_sar_num,
+                                           int src_sar_den,
+                                           int *dst_width,
+                                           int *dst_height)
+{
+  if (src_sar_num <= 0 || src_sar_den <= 0)
+    {
+      src_sar_num = 1;
+      src_sar_den = 1;
+    }
+  if ((src_width * src_sar_num) / src_sar_den > src_height)
+    {
+      *dst_width = THUMBSIZE;
+      *dst_height = (*dst_width * src_height) /
+                     ((src_width * src_sar_num) / src_sar_den);
+    }
+  else
+    {
+      *dst_height = THUMBSIZE;
+      *dst_width = (*dst_height *
+                    ((src_width * src_sar_num) / src_sar_den)) /
+                    src_height;
+    }
+  if (*dst_width < 8)
+    *dst_width = 8;
+  if (*dst_height < 1)
+    *dst_height = 1;
+#if DEBUG
+  fprintf (stderr,
+           "Thumbnail dimensions: %d %d\n", 
+           *dst_width, *dst_height);
+#endif
+}
+
+static int 
+extract_image (enum CodecID image_codec_id,
+               const unsigned char *data,
+               size_t size,
+               EXTRACTOR_MetaDataProcessor proc,
+               void *proc_cls,
+               const char *options)
+{
+  AVCodecContext *codec_ctx;
+  AVCodec *codec = NULL;
+  AVFrame *frame = NULL;
+  uint8_t *encoded_thumbnail;
+  int thumb_width;
+  int thumb_height;
+  int err;
+  int frame_finished;
+  int ret = 0;
+
+  codec_ctx = avcodec_alloc_context ();
+  if (codec_ctx == NULL)
+    {
+#if DEBUG
+      fprintf (stderr,
+               "Failed to allocate codec context\n");
+#endif
+      return 0;
+    }
+
+  codec = avcodec_find_decoder (image_codec_id);
+  if (codec != NULL)
+    {
+      if (avcodec_open (codec_ctx, codec) != 0)
+        {
+#if DEBUG
+          fprintf (stderr,
+                   "Failed to open image codec\n");
+#endif
+          av_free (codec_ctx);
+          return 0;
+        }
+    }
+  else
+    {
+#if DEBUG
+      fprintf (stderr,
+               "No suitable codec found\n");
+#endif
+      av_free (codec_ctx);
+      return 0;
+    }
+
+  frame = avcodec_alloc_frame ();
+  if (frame == NULL)
+    {
+#if DEBUG
+      fprintf (stderr,
+               "Failed to allocate frame\n");
+#endif
+      avcodec_close (codec_ctx);
+      av_free (codec_ctx);
+      return 0;
+    }
+
+  avcodec_decode_video (codec_ctx, frame, &frame_finished, data, size);
+
+  if (!frame_finished)
+    {
+      fprintf (stderr,
+              "Failed to decode a complete frame\n");
+      av_free (frame);
+      avcodec_close (codec_ctx);
+      av_free (codec_ctx);
+      return 0;
+    }
+
+  calculate_thumbnail_dimensions (codec_ctx->width, codec_ctx->height,
+                                  codec_ctx->sample_aspect_ratio.num,
+                                  codec_ctx->sample_aspect_ratio.den,
+                                  &thumb_width, &thumb_height);
+
+  err = create_thumbnail (codec_ctx->width, codec_ctx->height,
+                          frame->linesize, codec_ctx->pix_fmt, frame->data,
+                          thumb_width, thumb_height,
+                          &encoded_thumbnail, MAX_THUMB_SIZE);
+
+  if (err > 0)
+    {
+      ret = proc (proc_cls,
+                  "thumbnailffmpeg",
+                  EXTRACTOR_METATYPE_THUMBNAIL,
+                  EXTRACTOR_METAFORMAT_BINARY,
+                  "image/png",
+                  (const char*) encoded_thumbnail,
+                  err);
+      av_free (encoded_thumbnail);
+    }
+
+  av_free (frame);
+  avcodec_close (codec_ctx);
+  return ret;
+}
+
+static int 
+extract_video (const unsigned char *data,
+               size_t size,
+               EXTRACTOR_MetaDataProcessor proc,
+               void *proc_cls,
+               const char *options)
+{
   AVProbeData pd; 
   AVPacket packet;
   AVInputFormat *input_format;
@@ -220,8 +399,6 @@
   int video_stream_index;
   int thumb_width;
   int thumb_height;
-  int sar_num;
-  int sar_den;
   int i;
   int err;
   int frame_finished;
@@ -241,11 +418,11 @@
     {
 #if DEBUG
       fprintf (stderr,
-              "Failed to probe input format\n");
+               "Failed to probe input format\n");
 #endif
       if (pd.buf_size != size) /* retry probe once with full data size */
         {
-         pd.buf_size = size;
+          pd.buf_size = size;
           goto RETRY_PROBE;
         }
       return 0;
@@ -260,7 +437,7 @@
     {
  #if DEBUG
       fprintf (stderr,
-              "Failed to open input stream\n");
+               "Failed to open input stream\n");
 #endif
       url_close_buf (bio_ctx);
       if (!input_format_nofileflag)
@@ -285,19 +462,20 @@
     {
       codec_ctx = format_ctx->streams[i]->codec;
       if (codec_ctx->codec_type != CODEC_TYPE_VIDEO)
-       continue;
+        continue;
       codec = avcodec_find_decoder (codec_ctx->codec_id);
       if (codec == NULL)
-       continue;
+        continue;
       err = avcodec_open (codec_ctx, codec);
       if (err != 0)
-       {
-         codec = NULL;
-         continue;
-       }
+        {
+          codec = NULL;
+          continue;
+        }
       video_stream_index = i;
       break;
-    } 
+    }
+
   if ( (codec_ctx == NULL) || 
        (codec == NULL) ||
        (codec_ctx->width == 0) || 
@@ -307,8 +485,8 @@
       fprintf (stderr,
                "No video streams or no suitable codec found\n");
 #endif
-      if (codec_ctx != NULL)
-       avcodec_close (codec_ctx);
+      if (codec != NULL)
+        avcodec_close (codec_ctx);
       av_close_input_stream (format_ctx);
       url_close_buf (bio_ctx);
       if (!input_format_nofileflag)
@@ -323,8 +501,7 @@
       fprintf (stderr,
                "Failed to allocate frame\n");
 #endif
-      if (codec != NULL)
-       avcodec_close (codec_ctx);
+      avcodec_close (codec_ctx);
       av_close_input_stream (format_ctx);
       url_close_buf (bio_ctx);
       if (!input_format_nofileflag)
@@ -347,75 +524,42 @@
     avcodec_flush_buffers (codec_ctx);        
   frame_finished = 0;
 
-  if (0 /* is_image */)
+  while (1)
     {
-      avcodec_decode_video (codec_ctx, frame, &frame_finished, data, size);
-    }
-  else
-    {
-      while (1)
+      err = av_read_frame (format_ctx, &packet);
+      if (err < 0)
+        break;
+      if (packet.stream_index == video_stream_index)
         {
-          err = av_read_frame (format_ctx, &packet);
-          if (err < 0)
-            break;
-          if (packet.stream_index == video_stream_index)
+          avcodec_decode_video (codec_ctx,
+                                frame,
+                                &frame_finished,
+                                packet.data, packet.size);
+          if (frame_finished && frame->key_frame)
             {
-              avcodec_decode_video (codec_ctx,
-                                    frame,
-                                    &frame_finished,
-                                    packet.data, packet.size);
-              if (frame_finished && frame->key_frame)
-                {
-                  av_free_packet (&packet);
-                  break;
-                }
+              av_free_packet (&packet);
+              break;
             }
-          av_free_packet (&packet);
         }
+      av_free_packet (&packet);
     }
   if (!frame_finished)
     {
       fprintf (stderr,
               "Failed to decode a complete frame\n");
-      if (frame != NULL)
-       av_free (frame);
+      av_free (frame);
+      avcodec_close (codec_ctx);
       av_close_input_stream (format_ctx);
-      free (bio_ctx);
+      url_close_buf (bio_ctx);
       if (!input_format_nofileflag)
         input_format->flags ^= AVFMT_NOFILE;
       return 0;
     }
 
-  /* calculate the thumbnail dimensions, taking pixel aspect into account */
-  sar_num = codec_ctx->sample_aspect_ratio.num;
-  sar_den = codec_ctx->sample_aspect_ratio.den;
-  if (sar_num <= 0 || sar_den <= 0)
-    {
-      sar_num = 1;
-      sar_den = 1;
-    }
-  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
-  fprintf (stderr,
-           "Thumbnail dimensions: %d %d\n", 
-           thumb_width, thumb_height);
-#endif
+  calculate_thumbnail_dimensions (codec_ctx->width, codec_ctx->height,
+                                  codec_ctx->sample_aspect_ratio.num,
+                                  codec_ctx->sample_aspect_ratio.den,
+                                  &thumb_width, &thumb_height);
 
   err = create_thumbnail (codec_ctx->width, codec_ctx->height,
                           frame->linesize, codec_ctx->pix_fmt, frame->data,
@@ -434,16 +578,51 @@
       av_free (encoded_thumbnail);
     }
 
+  av_free (frame);
   avcodec_close (codec_ctx);
   av_close_input_stream (format_ctx);
+  url_close_buf (bio_ctx);
   if (!input_format_nofileflag)
     input_format->flags ^= AVFMT_NOFILE;
-  av_free (frame);
-  url_close_buf (bio_ctx);
   return ret;
 }
 
 int 
+EXTRACTOR_thumbnailffmpeg_extract (const unsigned char *data,
+                                  size_t size,
+                                  EXTRACTOR_MetaDataProcessor proc,
+                                  void *proc_cls,
+                                  const char *options)
+{
+  enum CodecID image_codec_id;
+  int is_image = 0;
+  int i;
+
+  mime_type = NULL;
+  EXTRACTOR_mime_extract(data, size, mime_processor, NULL, NULL);
+  if (mime_type != NULL) 
+    {
+      i = 0;
+      while (m2d_map[i].mime_type != NULL)
+        {
+          if (!strcmp (m2d_map[i].mime_type, mime_type))
+            {
+              is_image = 1;
+              image_codec_id = m2d_map[i].codec_id;
+              break;
+            }
+          i++;
+        }
+      free(mime_type);
+    }
+
+  if (is_image)
+    return extract_image (image_codec_id, data, size, proc, proc_cls, options);
+  else
+    return extract_video (data, size, proc, proc_cls, options);
+}
+
+int 
 EXTRACTOR_thumbnail_extract (const unsigned char *data,
                             size_t size,
                             EXTRACTOR_MetaDataProcessor proc,





reply via email to

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