1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Copyright (c) 2013 Frank Karlitschek [email protected] |
4
|
|
|
* Copyright (c) 2013 Georg Ehrke [email protected] |
5
|
|
|
* This file is licensed under the Affero General Public License version 3 or |
6
|
|
|
* later. |
7
|
|
|
* See the COPYING-README file. |
8
|
|
|
*/ |
9
|
|
|
namespace OC\Preview; |
10
|
|
|
|
11
|
|
View Code Duplication |
function findBinaryPath($program) { |
|
|
|
|
12
|
|
|
exec('command -v ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode); |
13
|
|
|
if ($returnCode === 0 && count($output) > 0) { |
14
|
|
|
return escapeshellcmd($output[0]); |
15
|
|
|
} |
16
|
|
|
return null; |
17
|
|
|
} |
18
|
|
|
|
19
|
|
|
// movie preview is currently not supported on Windows |
20
|
|
|
if (!\OC_Util::runningOnWindows()) { |
21
|
|
|
$isExecEnabled = \OC_Helper::is_function_enabled('exec'); |
22
|
|
|
$ffmpegBinary = null; |
23
|
|
|
$avconvBinary = null; |
24
|
|
|
|
25
|
|
|
if ($isExecEnabled) { |
26
|
|
|
$avconvBinary = findBinaryPath('avconv'); |
27
|
|
|
if (!$avconvBinary) { |
28
|
|
|
$ffmpegBinary = findBinaryPath('ffmpeg'); |
29
|
|
|
} |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
if($isExecEnabled && ( $avconvBinary || $ffmpegBinary )) { |
33
|
|
|
|
34
|
|
|
class Movie extends Provider { |
35
|
|
|
public static $avconvBinary; |
36
|
|
|
public static $ffmpegBinary; |
37
|
|
|
|
38
|
|
|
public function getMimeType() { |
39
|
|
|
return '/video\/.*/'; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { |
43
|
|
|
// TODO: use proc_open() and stream the source file ? |
44
|
|
|
|
45
|
|
|
$fileInfo = $fileview->getFileInfo($path); |
46
|
|
|
$useFileDirectly = (!$fileInfo->isEncrypted() && !$fileInfo->isMounted()); |
47
|
|
|
|
48
|
|
|
if ($useFileDirectly) { |
49
|
|
|
$absPath = $fileview->getLocalFile($path); |
50
|
|
View Code Duplication |
} else { |
|
|
|
|
51
|
|
|
$absPath = \OC_Helper::tmpFile(); |
52
|
|
|
|
53
|
|
|
$handle = $fileview->fopen($path, 'rb'); |
54
|
|
|
|
55
|
|
|
// we better use 5MB (1024 * 1024 * 5 = 5242880) instead of 1MB. |
56
|
|
|
// in some cases 1MB was no enough to generate thumbnail |
57
|
|
|
$firstmb = stream_get_contents($handle, 5242880); |
58
|
|
|
file_put_contents($absPath, $firstmb); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
$result = $this->generateThumbNail($maxX, $maxY, $absPath, 5); |
62
|
|
|
if ($result === false) { |
63
|
|
|
$result = $this->generateThumbNail($maxX, $maxY, $absPath, 1); |
64
|
|
|
if ($result === false) { |
65
|
|
|
$result = $this->generateThumbNail($maxX, $maxY, $absPath, 0); |
66
|
|
|
} |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
if (!$useFileDirectly) { |
70
|
|
|
unlink($absPath); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
return $result; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @param int $maxX |
78
|
|
|
* @param int $maxY |
79
|
|
|
* @param string $absPath |
80
|
|
|
* @param string $tmpPath |
|
|
|
|
81
|
|
|
* @param int $second |
82
|
|
|
* @return bool|\OC_Image |
83
|
|
|
*/ |
84
|
|
|
private function generateThumbNail($maxX, $maxY, $absPath, $second) |
85
|
|
|
{ |
86
|
|
|
$tmpPath = \OC_Helper::tmpFile(); |
87
|
|
|
|
88
|
|
|
if (self::$avconvBinary) { |
89
|
|
|
$cmd = self::$avconvBinary . ' -an -y -ss ' . escapeshellarg($second) . |
90
|
|
|
' -i ' . escapeshellarg($absPath) . |
91
|
|
|
' -f mjpeg -vframes 1 -vsync 1 ' . escapeshellarg($tmpPath) . |
92
|
|
|
' > /dev/null 2>&1'; |
93
|
|
|
} else { |
94
|
|
|
$cmd = self::$ffmpegBinary . ' -y -ss ' . escapeshellarg($second) . |
95
|
|
|
' -i ' . escapeshellarg($absPath) . |
96
|
|
|
' -f mjpeg -vframes 1' . |
97
|
|
|
' -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) . |
98
|
|
|
' ' . escapeshellarg($tmpPath) . |
99
|
|
|
' > /dev/null 2>&1'; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
exec($cmd, $output, $returnCode); |
103
|
|
|
|
104
|
|
|
if ($returnCode === 0) { |
105
|
|
|
$image = new \OC_Image(); |
106
|
|
|
$image->loadFromFile($tmpPath); |
107
|
|
|
unlink($tmpPath); |
108
|
|
|
return $image->valid() ? $image : false; |
109
|
|
|
} |
110
|
|
|
unlink($tmpPath); |
111
|
|
|
return false; |
112
|
|
|
} |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
// a bit hacky but didn't want to use subclasses |
116
|
|
|
Movie::$avconvBinary = $avconvBinary; |
117
|
|
|
Movie::$ffmpegBinary = $ffmpegBinary; |
118
|
|
|
|
119
|
|
|
\OC\Preview::registerProvider('OC\Preview\Movie'); |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.