mpeg_extractor.c (5537B)
1 /* 2 This file is part of libextractor. 3 Copyright (C) 2004, 2005, 2006, 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 21 /** 22 * @file plugins/mpeg_extractor.c 23 * @brief plugin to support MPEG files 24 * @author Christian Grothoff 25 */ 26 #include "platform.h" 27 #include "extractor.h" 28 #include <mpeg2dec/mpeg2.h> 29 30 31 /** 32 * Give meta data to extractor. 33 * 34 * @param t type of the meta data 35 * @param s meta data value in utf8 format 36 */ 37 #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "mpeg", t, \ 38 EXTRACTOR_METAFORMAT_UTF8, \ 39 "text/plain", s, strlen (s) \ 40 + 1)) goto EXIT; \ 41 } while (0) 42 43 44 /** 45 * Main entry method for the 'video/mpeg' extraction plugin. 46 * 47 * @param ec extraction context provided to the plugin 48 */ 49 void 50 EXTRACTOR_mpeg_extract_method (struct EXTRACTOR_ExtractContext *ec) 51 { 52 mpeg2dec_t *handle; 53 const mpeg2_info_t *info; 54 void *buf; 55 ssize_t avail; 56 mpeg2_state_t state; 57 char format[256]; 58 char lformat[256]; 59 char gop_format[256]; 60 int have_gop; 61 uint64_t fsize; 62 unsigned int fail_count; 63 int did_seek; 64 int fmt1; 65 int fmt2; 66 int mime; 67 int fpal; 68 int fntsc; 69 int fsecam; 70 int fmac; 71 72 if (NULL == (handle = mpeg2_init ())) 73 return; 74 if (NULL == (info = mpeg2_info (handle))) 75 { 76 mpeg2_close (handle); 77 return; 78 } 79 fsize = ec->get_size (ec->cls); 80 buf = NULL; 81 have_gop = 0; 82 fail_count = 0; 83 did_seek = 0; 84 fmt1 = 0; 85 fmt2 = 0; 86 mime = 0; 87 fpal = 0; 88 fntsc = 0; 89 fsecam = 0; 90 fmac = 0; 91 lformat[0] = '\0'; 92 while (1) 93 { 94 state = mpeg2_parse (handle); 95 switch (state) 96 { 97 case STATE_BUFFER: 98 if (fail_count > 16) 99 goto EXIT; /* do not read large non-mpeg files */ 100 fail_count++; 101 if (0 >= (avail = ec->read (ec->cls, 102 &buf, 103 16 * 1024))) 104 goto EXIT; 105 mpeg2_buffer (handle, buf, buf + avail); 106 break; 107 case STATE_SEQUENCE: 108 fail_count = 0; 109 format[0] = fsize; 110 format[0]++; 111 if (0 == mime) 112 { 113 mime = 1; 114 ADD ("video/mpeg", EXTRACTOR_METATYPE_MIMETYPE); 115 } 116 snprintf (format, 117 sizeof(format), "%ux%u", 118 info->sequence->width, info->sequence->height); 119 if (0 != strcmp (lformat, 120 format)) 121 { 122 strcpy (lformat, 123 format); 124 ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS); 125 } 126 switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED) 127 { 128 case SEQ_VIDEO_FORMAT_PAL: 129 if (0 == fpal) 130 { 131 fpal = 1; 132 ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 133 } 134 break; 135 case SEQ_VIDEO_FORMAT_NTSC: 136 if (0 == fntsc) 137 { 138 fntsc = 1; 139 ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 140 } 141 break; 142 case SEQ_VIDEO_FORMAT_SECAM: 143 if (0 == fsecam) 144 { 145 fsecam = 1; 146 ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 147 } 148 break; 149 case SEQ_VIDEO_FORMAT_MAC: 150 if (0 == fmac) 151 { 152 fmac = 1; 153 ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 154 } 155 break; 156 default: 157 break; 158 } 159 if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0) 160 { 161 if (0 == fmt1) 162 { 163 fmt1 = 1; 164 ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION); 165 } 166 } 167 else 168 { 169 if (0 == fmt2) 170 { 171 fmt2 = 1; 172 ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION); 173 } 174 } 175 if ( (0 == did_seek) && 176 (fsize != -1) && 177 (fsize > 1024 * 256 * 2) ) 178 { 179 /* skip to the end of the mpeg for speed */ 180 did_seek = 1; 181 ec->seek (ec->cls, 182 fsize - 256 * 1024, 183 SEEK_SET); 184 } 185 break; 186 case STATE_GOP: 187 fail_count = 0; 188 if ( (NULL != info->gop) && 189 (0 != info->gop->pictures) ) 190 { 191 snprintf (gop_format, 192 sizeof (gop_format), 193 "%02u:%02u:%02u (%u frames)", 194 info->gop->hours, 195 info->gop->minutes, 196 info->gop->seconds, 197 info->gop->pictures); 198 have_gop = 1; 199 } 200 break; 201 case STATE_SLICE: 202 fail_count = 0; 203 break; 204 case STATE_END: 205 fail_count = 0; 206 break; 207 case STATE_INVALID: 208 goto EXIT; 209 default: 210 break; 211 } 212 } 213 EXIT: 214 if (1 == have_gop) 215 ADD (gop_format, EXTRACTOR_METATYPE_DURATION); 216 mpeg2_close (handle); 217 } 218 219 220 /* end of mpeg_extractor.c */