From 635d8e1daddd5d02a7899ff488905d56aa5d4048 Mon Sep 17 00:00:00 2001 From: jaidhar Date: Thu, 18 Nov 2010 19:09:51 +0000 Subject: [PATCH] Grab FFMPEG from ZM_PATH_FFMPEG (if available), more robust error checking against codecs and paths Signed-off-by: Jai Dhar git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@3203 e3e1d417-86f3-4887-817a-d78f3d33393f --- web/skins/xml/includes/functions.php | 93 ++++++++++++++-------------- web/skins/xml/views/actions.php | 41 +++++++----- web/skins/xml/views/console.php | 2 +- 3 files changed, 75 insertions(+), 61 deletions(-) diff --git a/web/skins/xml/includes/functions.php b/web/skins/xml/includes/functions.php index c6985ba72..74212d7c9 100644 --- a/web/skins/xml/includes/functions.php +++ b/web/skins/xml/includes/functions.php @@ -119,58 +119,59 @@ body { /dev/null | grep mpeg4"); - if ($res == "") { - logXml("FFMPEG doesn't support MPEG-4"); - return 0; - } - return 1; -} -/** Returns whether necessary components for H264 event-generation are present */ -function canGenerateH264() { - /* Check for ffmpeg */ - $res = shell_exec("which ffmpeg"); - if ($res == "") { - logXml("ZMSTREAMER not installed, cannot stream H264"); - return 0; - } - /* Check for libx264 support */ - $res = shell_exec("ffmpeg -codecs 2> /dev/null | grep libx264"); - if ($res == "") { - logXml("FFMPEG doesn't support libx264"); - return 0; - } - return 1; -} /** Returns whether necessary components for H264 streaming * are present */ -function canStream264() { +function canStream264($sup = 0) { + if (!ffmpegSupportsCodec("libx264")) { + if (!$sup) logXmlErr("FFMPEG not installed, accessible in path/ZM_PATH_FFMPEG, or doesn't support libx264"); + return FALSE; + } /* Make sure segmenter exists */ - $res = shell_exec("which segmenter"); - if ($res == "") { - logXml("H264 Requested, but segmenter not installed."); - return 0; + if (!exeExists(shell_exec("which segmenter"))) { + if (!$sup) logXmlErr("HTTP segmenter not installed or not accessible in path"); + return FALSE; } /* Check for zmstreamer */ - $res = shell_exec("which zmstreamer"); - if ($res == "") { - logXml("ZMSTREAMER not installed, cannot stream H264"); - return 0; + if (!exeExists(shell_exec("which zmstreamer"))) { + if (!$sup) logXmlErr("ZMSTREAMER not installed or not accessible in path"); + return FALSE; } - if (!canGenerateH264()) { - return 0; - } - return 1; + return TRUE; } +/* Returns the path of ffmpeg by using define */ +function getFfmpegPath() +{ + if (defined("ZM_PATH_FFMPEG")) { + return ZM_PATH_FFMPEG; + } else { + /* Not defined, get it from using 'which' */ + return shell_exec("which ffmpeg"); + } +} +/* Returns whether ffmpeg supports a given codec. Takes into account + * whether FFMPEG exists or not */ +function ffmpegSupportsCodec($codec) +{ + if (!ffmpegExists()) return FALSE; + /* FFMPEG exists */ + if (preg_match("/\b".$codec."\b/", shell_exec(getFfmpegPath()." -codecs 2> /dev/null")) > 0) { + /* More than one match */ + return TRUE; + } else { + return FALSE; + } +} +function exeExists($exepath) +{ + $path = trim($exepath); + return (file_exists($path) && is_readable($path) && ($path != "")); +} +/* Returns whether ffmpeg exists or not */ +function ffmpegExists() +{ + return exeExists(getFfmpegPath()); +} + function getFfmpeg264FoutParms($br, $fout) { $ffparms = "-analyzeduration 0 -acodec copy -s 320x240"; @@ -187,7 +188,7 @@ function getFfmpeg264FoutParms($br, $fout) function getFfmpeg264Str($width, $height, $br, $fin, $fout) { $ffparms = getFfmpeg264FoutParms($br, $fout); - $ffstr = "ffmpeg -t ".ZM_XML_H264_MAX_DURATION." -analyzeduration 0 -i "; + $ffstr = getFfmpegPath()." -t ".ZM_XML_H264_MAX_DURATION." -analyzeduration 0 -i "; $ffstr .= $fin." -f mpegts ".$ffparms; return $ffstr; } diff --git a/web/skins/xml/views/actions.php b/web/skins/xml/views/actions.php index f920ecc25..9cc112603 100644 --- a/web/skins/xml/views/actions.php +++ b/web/skins/xml/views/actions.php @@ -41,6 +41,11 @@ if (isset($_GET['action'])) { $width = getset('width', $dims['Width']); $height = getset('height', $dims['Height']); $br = getset('br', ZM_XML_H264_DEFAULT_BR); + /* Check that we can stream first */ + if (!canStream264()) { + /* canStream264 will print out error */ + exit; + } $streamUrl = stream264fn($monitor, $width, $height, $br); logXml("Using H264 Pipe Function: ".$streamUrl); $pid = shell_exec($streamUrl); @@ -111,11 +116,20 @@ if (isset($_GET['action'])) { $fps = getset('fps', ZM_WEB_VIDEO_MAXFPS); $scale = getset('scale', 100); $vcodec = getset('vcodec', ZM_XML_FEED_VCODEC); - /* Only allow H264 as of v1.2 and greater */ - if (!requireVer("1","2") && !strcmp($vcodec,"h264")) { - logXml("Version 1.2 required for H264 Streaming"); - } - if (!strcmp($vcodec, "h264") && canStream264() && requireVer("1","2")) { + /* Select which codec we want */ + if (!strcmp($vcodec, "h264")) { + /* Validate that we can in fact stream H264 */ + if (!canStream264()) { + /* canStream264 will print out error if + * there is one */ + echo "Server cannot stream H264. Check XML log for details"; + exit; + } + if (!requireVer("1", "2")) { + echo "H264 Streaming requires eyeZm v1.2 or above"; + logXmlErr("H264 Streaming requires eyeZm v1.2 or above"); + exit; + } $br = getset('br', ZM_XML_H264_DEFAULT_BR); /* H264 processing */ noCacheHeaders(); @@ -150,6 +164,7 @@ if (isset($_GET['action'])) { logXml("Streaming MJPEG on Monitor ".$monitor.", ".$width."x".$height." @".$fps."fps"); echo "\n"; echo "
\n"; + logXml("Using stream source: ".$streamSrc); outputImageStream("liveStream", $streamSrc, $width, $height, "stream"); echo "
"; } else { @@ -176,21 +191,19 @@ if (isset($_GET['action'])) { $vcodec = getset('vcodec', ZM_XML_EVENT_VCODEC); $baseURL = ZM_PATH_WEB."/".getEventPathSafe($event); /* Here we validate the codec. - * MPEG-4 requires canGenerateMpeg4 and v1.1 - * H264 requires canGenerateH264 and v1.2 */ + * Check that FFMPEG exists and supports codecs */ if (!strcmp($vcodec, "mpeg4")) { - if (!canGenerateMpeg4()) { - logXmlErr("Selected MPEG-4 for event, but determined system cannot generate MPEG-4 with FFMPEG"); + if (!ffmpegSupportsCodec("mpeg4")) { + logXmlErr("FFMPEG not installed, accessible in path/ZM_PATH_FFMPEG, or doesn't support mpeg4"); exit; } /* Can generate, we are good to go */ - logXml("Selected MPEG-4 for viewing event ".$event['Id']); $fname = "capture.mov"; $ffparms = "-vcodec mpeg4 -r ".ZM_XML_EVENT_FPS." ".$baseURL."/".$fname." 2> /dev/null"; } else if (!strcmp($vcodec, "h264")) { - if (!canGenerateH264()) { - logXmlErr("Selected H264 for event, but determined system cannot generate H-264 with FFMPEG"); + if (!ffmpegSupportsCodec("libx264")) { + logXmlErr("FFMPEG not installed, accessible in path/ZM_PATH_FFMPEG, or doesn't support H264"); exit; } if (!requireVer("1","2")) { @@ -198,7 +211,6 @@ if (isset($_GET['action'])) { exit; } /* Good to go */ - logXml("Selected H264 for viewing event ".$event['Id']); $fname = "capture.mp4"; $ffparms = getFfmpeg264FoutParms( getset('br',ZM_XML_H264_DEFAULT_EVBR), @@ -208,8 +220,9 @@ if (isset($_GET['action'])) { logXmlErr("Unknown codec ".$vcodec." selected for event viewing"); exit; } + logXml("Selected ".$vcodec." for viewing event ".$event['Id']); $fnameOut = $baseURL."/".$fname; - $shellCmd = "ffmpeg -y -r ".$fps." -i ".$baseURL."/%03d-capture.jpg"; + $shellCmd = getFfmpegPath()." -y -r ".$fps." -i ".$baseURL."/%03d-capture.jpg"; $shellCmd .= " ".$ffparms; logXml("Encoding event with command: ".$shellCmd); $shellOutput = shell_exec($shellCmd); diff --git a/web/skins/xml/views/console.php b/web/skins/xml/views/console.php index e70100c0b..286a7f03c 100644 --- a/web/skins/xml/views/console.php +++ b/web/skins/xml/views/console.php @@ -153,7 +153,7 @@ xml_tag_val("RUNNING", $running); xml_tag_val("PROTOVER", ZM_XML_PROTOCOL_VERSION); xml_tag_val("FEATURESET", ZM_XML_FEATURE_SET); xml_tag_val("VERSION", ZM_VERSION); -xml_tag_val("CANSTR264", canStream264()); +xml_tag_val("CANSTR264", canStream264(1)); xml_tag_val("FVCODEC", ZM_XML_FEED_VCODEC); xml_tag_val("FVTMT", ZM_XML_H264_TIMEOUT); xml_tag_val("USER", $user['Username']);