libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

riff_extractor.c (4533B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2004, 2009, 2012 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 
     20      This code was based on AVInfo 1.0 alpha 11
     21      (c) George Shuklin, gs]AT[shounen.ru, 2002-2004
     22      http://shounen.ru/soft/avinfo/
     23 
     24      and bitcollider 0.6.0
     25      (PD) 2004 The Bitzi Corporation
     26      http://bitzi.com/
     27  */
     28 /**
     29  * @file plugins/riff_extractor.c
     30  * @brief plugin to support RIFF files (ms-video)
     31  * @author Christian Grothoff
     32  */
     33 #include "platform.h"
     34 #include "extractor.h"
     35 #include <math.h>
     36 
     37 
     38 /**
     39  * Read an uint32_t as a little-endian (least
     40  * significant byte first) integer from @a data.
     41  *
     42  * @param data input data
     43  * @return integer read
     44  */
     45 static uint32_t
     46 fread_le (const char *data)
     47 {
     48   unsigned int x;
     49   uint32_t result = 0;
     50 
     51   for (x = 0; x < 4; x++)
     52     result |= ((unsigned char) data[x]) << (x * 8);
     53   return result;
     54 }
     55 
     56 
     57 /**
     58  * We implement our own rounding function, because the availability of
     59  * C99's round(), nearbyint(), rint(), etc. seems to be spotty, whereas
     60  * floor() is available in math.h on all C compilers.
     61  *
     62  * @param num value to round
     63  * @return rounded-to-nearest value
     64  */
     65 static double
     66 round_double (double num)
     67 {
     68   return floor (num + 0.5);
     69 }
     70 
     71 
     72 /**
     73  * Pass the given UTF-8 string to the 'proc' callback using
     74  * the given type.  Uses 'return' if 'proc' returns non-0.
     75  *
     76  * @param s 0-terminated UTF8 string value with the meta data
     77  * @param t libextractor type for the meta data
     78  */
     79 #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "riff", t, \
     80                                          EXTRACTOR_METAFORMAT_UTF8, \
     81                                          "text/plain", s, strlen (s) \
     82                                          + 1)) return; \
     83 } while (0)
     84 
     85 
     86 /**
     87  * Main entry method for the 'video/x-msvideo' extraction plugin.
     88  *
     89  * @param ec extraction context provided to the plugin
     90  */
     91 void
     92 EXTRACTOR_riff_extract_method (struct EXTRACTOR_ExtractContext *ec)
     93 {
     94   ssize_t xsize;
     95   void *data;
     96   char *xdata;
     97   uint32_t blockLen;
     98   unsigned int fps;
     99   unsigned int duration;
    100   uint64_t pos;
    101   uint32_t width;
    102   uint32_t height;
    103   char codec[5];
    104   char format[256];
    105 
    106   /* read header */
    107   if (72 > (xsize = ec->read (ec->cls, &data, 72)))
    108     return;
    109   xdata = data;
    110 
    111   /* check magic values */
    112   if ( (0 != memcmp (&xdata[0],
    113                      "RIFF", 4)) ||
    114        (0 != memcmp (&xdata[8], "AVI ", 4)) ||
    115        (0 != memcmp (&xdata[12], "LIST", 4)) ||
    116        (0 != memcmp (&xdata[20], "hdrlavih", 8)) )
    117     return;
    118 
    119   blockLen = fread_le (&xdata[28]);
    120 
    121   /* begin of AVI header at 32 */
    122   fps = (unsigned int) round_double ((double) 1.0e6 / fread_le (&xdata[32]));
    123   duration = (unsigned int) round_double ((double) fread_le (&xdata[48])
    124                                           * 1000 / fps);
    125   width = fread_le (&xdata[64]);
    126   height = fread_le (&xdata[68]);
    127 
    128   /* pos: begin of video stream header */
    129   pos = blockLen + 32;
    130 
    131   if (pos !=
    132       ec->seek (ec->cls, pos, SEEK_SET))
    133     return;
    134   if (32 > ec->read (ec->cls, &data, 32))
    135     return;
    136   xdata = data;
    137 
    138   /* check magic */
    139   if ( (0 != memcmp (xdata, "LIST", 4)) ||
    140        (0 != memcmp (&xdata[8], "strlstrh", 8)) ||
    141        (0 != memcmp (&xdata[20], "vids", 4)) )
    142     return;
    143 
    144   /* pos + 24: video stream header with codec */
    145   memcpy (codec, &xdata[24], 4);
    146   codec[4] = '\0';
    147   snprintf (format,
    148             sizeof (format),
    149             _ ("codec: %s, %u fps, %u ms"),
    150             codec, fps, duration);
    151   ADD (format, EXTRACTOR_METATYPE_FORMAT);
    152   snprintf (format,
    153             sizeof (format),
    154             "%ux%u",
    155             (unsigned int) width,
    156             (unsigned int) height);
    157   ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS);
    158   ADD ("video/x-msvideo", EXTRACTOR_METATYPE_MIMETYPE);
    159 }
    160 
    161 
    162 /* end of riff_extractor.c */