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
EXTRACTOR_mpeg_extract_method(struct EXTRACTOR_ExtractContext * ec)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 */
221