Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* This file is part of Strigi Desktop Search
2 *
3 * Copyright (C) 2009 Evgeny Egorochkin <phreedom.stdin@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#define STRIGI_IMPORT_API
22#include <strigi/analyzerplugin.h>
23#include <strigi/streamendanalyzer.h>
24#include <strigi/analysisresult.h>
25#include <strigi/fieldtypes.h>
26#include <strigi/textutils.h>
27#include <strigi/rdfnamespaces.h>
28#include <xine.h>
29#include <cstring>
30#include <iostream>
31using namespace Strigi;
32using namespace std;
33
34class XineEndAnalyzerFactory;
35
36class STRIGI_PLUGIN_API XineEndAnalyzer : public StreamEndAnalyzer {
37private:
38 AnalysisResult* result;
39 const XineEndAnalyzerFactory* factory;
40 xine_t *engine;
41 xine_audio_port_t *audiodrv;
42 xine_video_port_t *videodrv;
43
44public:
45 XineEndAnalyzer(const XineEndAnalyzerFactory* f) :factory(f) {
46 if ((engine = xine_new())) {
47 xine_init(engine);
48
49 audiodrv = xine_open_audio_driver(engine, NULL, NULL);
50 videodrv = xine_open_video_driver(engine, NULL, XINE_VISUAL_TYPE_NONE, NULL);
51
52 if (!audiodrv || !videodrv)
53 xine_exit (engine);
54 }
55 }
56
57 ~XineEndAnalyzer() {
58 if (engine) {
59 if (audiodrv)
60 xine_close_audio_driver(engine, audiodrv);
61 if (videodrv)
62 xine_close_video_driver(engine, videodrv);
63 xine_exit(engine);
64 }
65 }
66
67 const char* name() const {
68 return "XineEndAnalyzer";
69 }
70 bool checkHeader(const char* header, int32_t headersize) const;
71 signed char analyze(AnalysisResult& idx, ::InputStream* in);
72};
73
74class STRIGI_PLUGIN_API XineEndAnalyzerFactory : public StreamEndAnalyzerFactory {
75friend class XineEndAnalyzer;
76private:
77 StreamEndAnalyzer* newInstance() const {
78 return new XineEndAnalyzer(this);
79 }
80 const char* name() const {
81 return "XineEndAnalyzer";
82 }
83 void registerFields(FieldRegister& );
84
85 const RegisteredField* durationProperty;
86 const RegisteredField* widthProperty;
87 const RegisteredField* heightProperty;
88 const RegisteredField* frameRateProperty;
89 const RegisteredField* codecProperty;
90 const RegisteredField* bitrateProperty;
91 const RegisteredField* channelsProperty;
92 const RegisteredField* samplerateProperty;
93 const RegisteredField* titleProperty;
94 const RegisteredField* commentProperty;
95 const RegisteredField* typeProperty;
96};
97
98const string
99 videoClassName =
100 NFO "Video",
101 audioClassName =
102 NFO "Audio",
103 musicPieceClassName =
104 NMM_DRAFT "MusicPiece",
105
106 titlePropertyName =
107 NIE "title",
108 commentPropertyName =
109 NIE "comment",
110
111 sampleratePropertyName =
112 NFO "sampleRate",
113 codecPropertyName =
114 NFO "codec",
115 channelsPropertyName =
116 NFO "channels",
117 bitratePropertyName =
118 NFO "averageBitrate",
119 durationPropertyName =
120 NFO "duration",
121 widthPropertyName =
122 NFO "width",
123 heightPropertyName =
124 NFO "height",
125 frameRatePropertyName =
126 NFO "frameRate";
127
128void
129XineEndAnalyzerFactory::registerFields(FieldRegister& r) {
130 durationProperty = r.registerField(durationPropertyName);
131 widthProperty = r.registerField(widthPropertyName);
132 heightProperty = r.registerField(heightPropertyName);
133 frameRateProperty = r.registerField(frameRatePropertyName);
134 codecProperty = r.registerField(codecPropertyName);
135 bitrateProperty = r.registerField(bitratePropertyName);
136 typeProperty = r.typeField;
137 channelsProperty = r.registerField(channelsPropertyName);
138 samplerateProperty = r.registerField(sampleratePropertyName);
139 titleProperty = r.registerField(titlePropertyName);
140 commentProperty = r.registerField(commentPropertyName);
141}
142
143//Have to detect here all supported formats because there's no way to pass this to xine
144bool
145XineEndAnalyzer::checkHeader(const char* header, int32_t headersize) const {
146 return headersize>=12 && (
147 !strncmp(header, "FLV", 3) // FLV
148 || readLittleEndianUInt32(header) == 0x75b22630 // ASF/WMA/WMV
149 || (!strncmp(header, "RIFF", 4) && !strncmp(header+8, "AVI ", 4)) // AVI
150 || readLittleEndianUInt32(header) == 0xa3df451a // Matroska/MKV/MKA
151 || !strncmp(header+4, "ftyp3gp", 7) // 3GPP
152 || !strncmp(header+4, "ftypisom", 8) || !strncmp(header+4, "ftypmp42", 8) // MOV
153 || !strncmp(header+4, "ftypMSNV", 8) || !strncmp(header+4, "ftypM4", 6) // MOV
154 || (!strncmp(header, "OggS", 4) && strncmp(header+29, "vorbis", 6)) // Any ogg apart from Vorbis, which is handled by an internal analyzer
155 || readLittleEndianUInt32(header) == 0x10ff3f47 // MPG
156 || readLittleEndianUInt32(header) == 0xb3010000 // MPG
157 || readLittleEndianUInt32(header) == 0xba010000 // MPG
158 );
159}
160
161/*
162Left unused:
163 XINE_STREAM_INFO_SEEKABLE
164 XINE_STREAM_INFO_VIDEO_RATIO
165 XINE_STREAM_INFO_VIDEO_CHANNELS
166 XINE_STREAM_INFO_VIDEO_STREAMS
167 XINE_STREAM_INFO_VIDEO_FOURCC
168 XINE_STREAM_INFO_VIDEO_HANDLED
169 XINE_STREAM_INFO_AUDIO_BITS
170 XINE_STREAM_INFO_AUDIO_FOURCC
171 XINE_STREAM_INFO_AUDIO_HANDLED
172 XINE_STREAM_INFO_HAS_CHAPTERS
173 XINE_STREAM_INFO_IGNORE_VIDEO
174 XINE_STREAM_INFO_IGNORE_AUDIO
175 XINE_STREAM_INFO_IGNORE_SPU
176 XINE_STREAM_INFO_VIDEO_HAS_STILL
177 XINE_STREAM_INFO_MAX_AUDIO_CHANNEL
178 XINE_STREAM_INFO_MAX_SPU_CHANNEL
179 XINE_STREAM_INFO_AUDIO_MODE
180 XINE_STREAM_INFO_SKIPPED_FRAMES
181 XINE_STREAM_INFO_DISCARDED_FRAMES
182 XINE_STREAM_INFO_VIDEO_AFD
183 XINE_STREAM_INFO_DVD_TITLE_NUMBER
184 XINE_STREAM_INFO_DVD_TITLE_COUNT
185 XINE_STREAM_INFO_DVD_CHAPTER_NUMBER
186 XINE_STREAM_INFO_DVD_CHAPTER_COUNT
187 XINE_STREAM_INFO_DVD_ANGLE_NUMBER
188 XINE_STREAM_INFO_DVD_ANGLE_COUNT
189
190 XINE_META_INFO_ARTIST
191 XINE_META_INFO_GENRE
192 XINE_META_INFO_ALBUM
193 XINE_META_INFO_YEAR
194 XINE_META_INFO_SYSTEMLAYER
195 XINE_META_INFO_INPUT_PLUGIN
196 XINE_META_INFO_CDINDEX_DISCID
197 XINE_META_INFO_TRACK_NUMBER
198*/
199
200signed char
201XineEndAnalyzer::analyze(AnalysisResult& ar, ::InputStream* in) {
202
203 xine_stream_t *stream;
204
205 int posstream, postime, lengthtime;
206
207 string filename;
208
209 if ((ar.depth()==0) && (ar.path().substr(0,7) == "file://"))
210 filename = ar.path().substr(7);
211 else
212 filename = ar.path();
213
214 if (!(stream = xine_stream_new(engine, audiodrv, videodrv)))
215 return -1;
216
217 if (!xine_open(stream, filename.c_str())) {
218 xine_dispose(stream);
219 return 0;
220 }
221
222 bool audio = xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_AUDIO);
223
224 if (xine_get_pos_length(stream, &posstream, &postime, &lengthtime)) {
225 if (lengthtime > 0)
226 ar.addValue(factory->durationProperty, lengthtime / 1000); //duration in seconds
227 }
228
229 int bitrate = xine_get_stream_info (stream, XINE_STREAM_INFO_BITRATE);
230 if (bitrate > 0)
231 ar.addValue(factory->bitrateProperty, bitrate);
232
233// video properties
234
235 if ( xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_VIDEO) ) {
236 ar.addValue(factory->typeProperty, videoClassName);
237
238 int width = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_WIDTH);
239 int height = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_HEIGHT);
240 if (width > 0 && height > 0) {
241 ar.addValue(factory->widthProperty, width);
242 ar.addValue(factory->heightProperty, height);
243 }
244
245 int duration = xine_get_stream_info(stream, XINE_STREAM_INFO_FRAME_DURATION);
246 if ( duration > 0)
247 ar.addValue(factory->frameRateProperty, 90000 / duration);
248
249 const char *videocodec = xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC);
250 if (videocodec)
251 ar.addValue(factory->codecProperty, videocodec, strlen(videocodec));
252
253 // Somehow bitrate always ends up being 0 :(
254 int bitrate = xine_get_stream_info (stream, XINE_STREAM_INFO_VIDEO_BITRATE);
255 if (bitrate > 0)
256 ar.addValue(factory->bitrateProperty, bitrate);
257 } else if (audio) {
258 ar.addValue(factory->typeProperty, musicPieceClassName);
259 ar.addValue(factory->typeProperty, audioClassName);
260 }
261
262// audio properties
263
264 if (audio) {
265 // Somehow bitrate always ends up being 0 :(
266 int bitrate = xine_get_stream_info (stream, XINE_STREAM_INFO_AUDIO_BITRATE);
267 if (bitrate > 0)
268 ar.addValue(factory->bitrateProperty, bitrate);
269
270 const char *audiocodec = xine_get_meta_info(stream, XINE_META_INFO_AUDIOCODEC);
271 if (audiocodec)
272 ar.addValue(factory->codecProperty, audiocodec, strlen(audiocodec));
273
274 int channels = xine_get_stream_info(stream, XINE_STREAM_INFO_AUDIO_CHANNELS);
275 if (channels>0)
276 ar.addValue(factory->channelsProperty, channels);
277
278 int samplerate = xine_get_stream_info(stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE);
279 if (samplerate>0)
280 ar.addValue(factory->samplerateProperty, samplerate);
281 }
282
283// tags
284
285 const char *title = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
286 if (title)
287 ar.addValue(factory->titleProperty, title);
288
289 const char *comment = xine_get_meta_info(stream, XINE_META_INFO_COMMENT);
290 if (comment)
291 ar.addValue(factory->commentProperty, comment);
292
293 xine_dispose(stream);
294 return 0;
295}
296
297/*
298 For plugins, we need to have a way to find out which plugins are defined in a
299 plugin. One instance of AnalyzerFactoryFactory per plugin profides this
300 information.
301*/
302class Factory : public AnalyzerFactoryFactory {
303public:
304 list<StreamEndAnalyzerFactory*>
305 streamEndAnalyzerFactories() const {
306 list<StreamEndAnalyzerFactory*> af;
307 af.push_back(new XineEndAnalyzerFactory());
308 return af;
309 }
310};
311
312/*
313 Register the AnalyzerFactoryFactory
314*/
315STRIGI_ANALYZER_FACTORY(Factory)
316

Warning: That file was not part of the compilation database. It may have many parsing errors.