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 */