mpeg_extractor.c (5506B)
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 if (0 == mime) 110 { 111 mime = 1; 112 ADD ("video/mpeg", 113 EXTRACTOR_METATYPE_MIMETYPE); 114 } 115 snprintf (format, 116 sizeof(format), "%ux%u", 117 info->sequence->width, info->sequence->height); 118 if (0 != strcmp (lformat, 119 format)) 120 { 121 strcpy (lformat, 122 format); 123 ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS); 124 } 125 switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED) 126 { 127 case SEQ_VIDEO_FORMAT_PAL: 128 if (0 == fpal) 129 { 130 fpal = 1; 131 ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 132 } 133 break; 134 case SEQ_VIDEO_FORMAT_NTSC: 135 if (0 == fntsc) 136 { 137 fntsc = 1; 138 ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 139 } 140 break; 141 case SEQ_VIDEO_FORMAT_SECAM: 142 if (0 == fsecam) 143 { 144 fsecam = 1; 145 ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 146 } 147 break; 148 case SEQ_VIDEO_FORMAT_MAC: 149 if (0 == fmac) 150 { 151 fmac = 1; 152 ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); 153 } 154 break; 155 default: 156 break; 157 } 158 if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0) 159 { 160 if (0 == fmt1) 161 { 162 fmt1 = 1; 163 ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION); 164 } 165 } 166 else 167 { 168 if (0 == fmt2) 169 { 170 fmt2 = 1; 171 ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION); 172 } 173 } 174 if ( (0 == did_seek) && 175 (fsize != -1) && 176 (fsize > 1024 * 256 * 2) ) 177 { 178 /* skip to the end of the mpeg for speed */ 179 did_seek = 1; 180 ec->seek (ec->cls, 181 fsize - 256 * 1024, 182 SEEK_SET); 183 } 184 break; 185 case STATE_GOP: 186 fail_count = 0; 187 if ( (NULL != info->gop) && 188 (0 != info->gop->pictures) ) 189 { 190 snprintf (gop_format, 191 sizeof (gop_format), 192 "%02u:%02u:%02u (%u frames)", 193 info->gop->hours, 194 info->gop->minutes, 195 info->gop->seconds, 196 info->gop->pictures); 197 have_gop = 1; 198 } 199 break; 200 case STATE_SLICE: 201 fail_count = 0; 202 break; 203 case STATE_END: 204 fail_count = 0; 205 break; 206 case STATE_INVALID: 207 goto EXIT; 208 default: 209 break; 210 } 211 } 212 EXIT: 213 if (1 == have_gop) 214 ADD (gop_format, EXTRACTOR_METATYPE_DURATION); 215 mpeg2_close (handle); 216 } 217 218 219 /* end of mpeg_extractor.c */