如何解决php实现rtsp协议
1. 环境要求
使用php7在cli模式下运行。
2. 安装插件
使用插件 composer require phpbg/rtsp
3. 问题描述?
使用php编写rtsp协议,推流没有报错,但是拉流的时候没有数据,客户端会自动断开连接,没有搞明白拉流这里除了什么问题。
4. 业务源代码
<?php
require __DIR__ . '/vendor/autoload.php';
use PhpBg\Rtsp\Session;
$loop = React\EventLoop\Factory::create();
//Normal port is 554 but we use 5540 instead to avoid root required
$socket = new \React\Socket\TcpServer('tcp://0.0.0.0:5540', $loop);
$logger=new \PhpBg\MiniHttpd\Logger\Console(\Psr\Log\LogLevel::DEBUG, 'php://stderr', new \PhpBg\MiniHttpd\Logger\ConsoleFormatter(false));
global $sessions;
$middlewares = [
//$logger,
new \PhpBg\Rtsp\Middleware\AutoCseq(),
new \PhpBg\Rtsp\Middleware\AutoContentLength(),
function (\PhpBg\Rtsp\Message\Request $request, \React\Socket\ConnectionInterface $connection)use($loop,$logger,$sessions) {
static $sessions;
var_dump($request);
$method=$request->method;
$response = \PhpBg\Rtsp\Message\MessageFactory::response();
$response->setHeader('cseq', $request->getHeader('cseq'));
switch ($method){
case "SETUP":
$response->setHeader('transport', $request->getHeader('transport').';server_port=');
$transport=$request->getHeader('transport');
$first=explode(';',$transport);
$array=[];
$rtpPort='';
$rtcpPort='';
foreach ($first as $k=>$v){
list($key,$val)=explode('=',$v);
$array[$key]=$val;
if ($key=='client_port'){
echo "获取播放器的端口\r\n";
var_dump($val);
$ports = explode('-', $val);
$rtpPort = $ports[0];
$rtcpPort = $ports[1];
}
}
$sessionId = rand(10000000, 99999999);
$session = new Session($sessionId, $loop, $connection, $logger);
$session->proto = 'UDP';
$session->ports = [$rtpPort, $rtcpPort];
$address = $connection->getRemoteAddress();
$session->clientIp = trim(parse_url($address, PHP_URL_HOST), '[]');
$session->isInterleaved = false;
$session->transport = $request->getHeader('transport');
$uri = trim($request->uri, '/');
$resourcePath = explode('/', $uri);
$channelServiceId = array_pop($resourcePath);
$session->uri = $uri;
//var_dump($session);
$sessions[$sessionId]=$session;
$response->setHeader('session', $sessionId);
$response->setHeader('rtp-info', 'url=rtsp://127.0.0.1:5540/live/streamid=1;url=rtsp://127.0.0.1:5540/live/streamid=0;');
return $response;
break;
case "PLAY":
$sessionId=$request->getHeader('session');
$response->setHeader('rtp-info', 'url=rtsp://127.0.0.1:5540/live/streamid=1;url=rtsp://127.0.0.1:5540/live/streamid=0;');
$session = $sessions[$sessionId];
$session->play();
return $response;
case "DESCRIBE":
$startTime = time() + 2208988800;
$response->body = "v=0\r\no=- 0 $startTime IN IP4 0.0.0.0\r\ns=bar\r\nt=$startTime 0\r\nm=video 0 udp 33\r\n";
$response->setHeader('content-type', 'application/sdp');
return $response;
case "OPTIONS":
if ($request->hasHeader('session')) {
$sessionId = (int)$request->getHeader('session');
if (!isset($sessions[$sessionId])) {
$response->statusCode = 454;
$response->reasonPhrase = 'Session Not Found';
return $response;
}
$session = $sessions[$sessionId];
$session->keepAlive();
}
$response->setHeader('public', 'SETUP, TEARDOWN, PLAY');
return $response;
case "TEARDOWN":
$sessionId = (int)$request->getHeader('session');
var_dump("客户端要求关闭TEARDOWN");
var_dump($sessionId);
$session = $sessions[$sessionId];
if ($session!=null){
$session->teardown();
}
return $response;
break;
default:
//todo 本项目实现了rtsp协议,但是不能正常推流和拉流,根据猜测,还应该创建一个管道,将数据放入到管道,推流就是将数据存入到管道,拉流就是将数据取出,
//todo 难点是推流的数据在哪里接收,知道了数据的位置才知道怎么处理数据
return $response;
}
}
];
$server = new \PhpBg\Rtsp\Server(new \PhpBg\Rtsp\Middleware\MiddlewareStack($middlewares));
$server->on('error', function (\Exception $e) {
echo $e->getMessage() . "\r\n";
echo $e->getTraceAsString() . "\r\n";
});
$server->listen($socket);
echo "Server started\r\n";
echo "Open any decent video player (e.g. vlc, mpv) and open rtsp://localhost:5540\r\n";
$loop->run();