source: gs2-extensions/video-and-audio/trunk/src/perllib/plugins/MultimediaPlugin.pm@ 28369

Last change on this file since 28369 was 28369, checked in by davidb, 11 years ago

Changes to work with newer version of ffmpeg

File size: 9.2 KB
Line 
1######################################################################
2#
3# MultimediaPlugin.pm -- internal plugin to support processing audio and video
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26# -- Largely modeled on how ImagePlugin works
27
28package MultimediaPlugin;
29
30use strict;
31no strict 'refs'; # allow filehandles to be variables and viceversa
32no strict 'subs';
33
34use gsprintf;
35
36use BasePlugin;
37
38sub BEGIN {
39 @MultimediaPlugin::ISA = ('BasePlugin');
40
41 if (!defined $ENV{'GEXTVIDEO'}) {
42 print STDERR "Warning: Greenstone Video extension not detected.\n";
43 }
44
45}
46
47
48
49 # do later the description
50my $arguments =
51 [ { 'name' => "use_ascii_only_filenames",
52 'desc' => "{VideoPlug.use_ascii_only_filenames}",
53 'type' => "flag",
54 'reqd' => "no" },
55 { 'name' => "excerpt_duration",
56 'desc' => "{MultimediaPlug.excerpt_duration}",
57 'type' => "string",
58 'deft' => "",
59 'reqd' => "no" },
60 { 'name' => "converttotype",
61 'desc' => "{MultimediaPlug.converttotype}",
62 'type' => "string",
63 'deft' => "",
64 'reqd' => "no" },
65 { 'name' => "enable_streaming",
66 'desc' => "{MultimediaPlug.enable_streaming}",
67 'type' => "enum",
68 'list' => [{'name' => "disabled", 'desc' => "Do not create any video file optimised for streaming over the Internet."},
69 {'name' => "flv", 'desc' => "Uses the FLV format for streaming media. Better to target old computers."},
70 {'name' => "mp4", 'desc' => "Uses the MP4 container with H264 and AAC codecs. Better quality at very low bitrates but more ressources intensive."},
71 {'name' => "direct", 'desc' => "Uses the original video file for direct streaming. The video player should be compatible with the format used!"}],
72 'deft' => "disabled",
73 'reqd' => "no" }];
74
75my $options = { 'name' => "MultimediaPlugin",
76 'desc' => "{MultimediaPlug.desc}",
77 'abstract' => "yes",
78 'inherits' => "yes",
79 'args' => $arguments };
80
81
82sub new {
83 my ($class) = shift (@_);
84 my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
85 push(@$pluginlist, $class);
86
87 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
88 push(@{$hashArgOptLists->{"OptList"}},$options);
89
90 my $self = new BasePlugin($pluginlist, $inputargs, $hashArgOptLists);
91
92 # Check that ffmpeg is installed and available on the path (except for Windows 95/98)
93 # This test is "inherited" from ImagePlugin where ImageMagick support
94 # for building cannot be used on these two versions of Windows as they
95 # do not have enough flexablity in the use of stdout and stderr to
96 # support how our code works. It seems reasonable to assume the
97 # same is true for MultimediaPlugin work using ffmpeg.
98
99 if (($ENV{'GSDLOS'} ne "windows" || Win32::IsWinNT())) {
100
101## my $result = `ffmpeg -h 2>&1`;
102 my $result = `ffmpeg -version 2>&1`;
103
104 if (!defined $result || $result !~ m/^FFmpeg\s+version/mi) {
105 $self->{'ffmpeg_installed'} = 0;
106 if (defined $result) {
107 print STDERR "Problem detecting ffmpeg:\n";
108 print STDERR $result;
109 }
110 else {
111 print STDERR "Unable to find ffmpeg\n";
112 }
113 }
114 else {
115 $self->{'ffmpeg_installed'} = 1;
116 }
117
118 }
119
120 return bless $self, $class;
121}
122
123
124
125sub begin {
126 my $self = shift (@_);
127 my ($pluginfo, $base_dir, $processor, $maxdocs) = @_;
128
129 $self->SUPER::begin(@_);
130
131 $self->{'base_dir'} = $base_dir;
132}
133
134
135sub init {
136 my $self = shift (@_);
137 my ($verbosity, $outhandle, $failhandle) = @_;
138
139 $self->SUPER::init(@_);
140}
141
142# Want to hash on doc.xml rather than original file which in the case of
143# audio and video can be HUGE
144
145sub get_oid_hash_type {
146
147 my $self = shift (@_);
148
149 return "hash_on_ga_xml";
150}
151
152
153
154# Create the keyframes, thumbnail and screenview images, and discover
155# the Video's size, width, and height using the ffmpeg utility.
156
157sub run_convert {
158 my $self = shift (@_);
159
160 die "$self The inheriting class must implement run_convert method";
161}
162
163
164sub read_into_doc_obj {
165 my $self = shift (@_);
166 my ($pluginfo, $base_dir, $file, $block_hash, $metadata, $processor, $maxdocs, $total_count, $gli) = @_;
167
168 my $outhandle = $self->{'outhandle'};
169
170 # should we move this to read? What about secondary plugins?
171 print STDERR "<Processing n='$file' p='$self->{'plugin_type'}'>\n" if ($gli);
172 print $outhandle "$self->{'plugin_type'} processing $file\n"
173 if $self->{'verbosity'} > 1;
174
175 my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);
176
177 # create a new document
178 my $doc_obj = new doc ($filename_full_path, "indexed_doc", $self->{'file_rename_method'});
179
180
181 my $top_section = $doc_obj->get_top_section();
182
183
184 $doc_obj->add_utf8_metadata($top_section, "Plugin", "$self->{'plugin_type'}");
185 $doc_obj->add_utf8_metadata($top_section, "FileSize", (-s $filename_full_path));
186
187 # sets the UTF8 filename (Source) for display and sets the url ref to URL encoded version
188 # of the UTF8 filename (SourceFile) for generated files
189 $self->set_Source_metadata($doc_obj, $filename_no_path);
190
191
192 # plugin specific stuff - what args do we need here??
193 unless (defined ($self->process($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli))) {
194 print STDERR "<ProcessingError n='$file'>\n" if ($gli);
195 return (-1,undef);
196 }
197
198 # include any metadata passed in from previous plugins
199 # note that this metadata is associated with the top level section
200 my $section = $doc_obj->get_top_section();
201 # can we merge these two methods??
202 $self->add_associated_files($doc_obj, $filename_full_path);
203 $self->extra_metadata ($doc_obj, $section, $metadata);
204 $self->auto_extract_metadata($doc_obj);
205
206 # if we haven't found any Title so far, assign one
207 # this was shifted to here from inside read()
208 $self->title_fallback($doc_obj,$section,$filename_no_path);
209
210 $self->add_OID($doc_obj);
211
212 $self->post_process_doc_obj($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli);
213
214 return (1,$doc_obj);
215}
216
217sub add_dummy_text {
218 my $self = shift(@_);
219 my ($doc_obj, $section) = @_;
220
221 # add NoText metadata so we can hide this dummy text in format statements
222 $doc_obj->add_metadata($section, "NoText", "1");
223 $doc_obj->add_text($section, &gsprintf::lookup_string("{BasePlugin.dummy_text}",1));
224
225}
226
227
228
229
230# do plugin specific processing of doc_obj
231sub process {
232 my $self = shift (@_);
233 # options??
234 my ($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli) = @_;
235
236 my $outhandle = $self->{'outhandle'};
237
238 my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);
239
240
241 if ($self->{'ffmpeg_installed'}) {
242 my $utf8_filename_no_path = $self->filepath_to_utf8($filename_no_path);
243 my $url_encoded_filename = &util::rename_file($utf8_filename_no_path, $self->{'file_rename_method'});
244
245
246 #run convert to get the thumbnail and extract size and type info
247 my $result = $self->run_convert($base_dir, $filename_full_path,
248 $url_encoded_filename, $doc_obj);
249
250 if (!defined $result) {
251 if ($gli) {
252 print STDERR "<ProcessingError n='$file'>\n";
253 }
254 print $outhandle "MultimediaPlugin: couldn't process \"$filename_full_path\"\n";
255 return (-1,undef); # error during processing
256 }
257 }
258 else {
259 if ($gli) {
260 &gsprintf(STDERR, "<Warning p='MultimediaPlugin' r='{MultimediaConverter.noconversionavailable}: {MultimediaConverter.".$self->{'no_multimedia_conversion_reason'}."}'>");
261 }
262 # all we do is add the original video file as an associated file, and set up srclink etc
263 my $assoc_file = $doc_obj->get_assocfile_from_sourcefile();
264 my $section = $doc_obj->get_top_section();
265
266 $doc_obj->associate_file($filename_full_path, $assoc_file, "", $section);
267
268 $doc_obj->add_metadata ($section, "srclink", "<a href=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[SourceFile]\">");
269 $doc_obj->add_metadata ($section, "/srclink", "</a>");
270 $doc_obj->add_metadata ($section, "srcicon", "<img src=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[SourceFile]\" width=\"100\">");
271
272 }
273 #we have no text - adds dummy text and NoText metadata
274 $self->add_dummy_text($doc_obj, $doc_obj->get_top_section());
275
276 return 1;
277
278}
279
280
281
2821;
283
284
285
286
287
288
289
290
291
292
293
Note: See TracBrowser for help on using the repository browser.