From 34c6654bbdf8850419c35a681a7aae5787aec63b Mon Sep 17 00:00:00 2001 From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674> Date: 星期五, 23 十二月 2016 10:07:30 +0800 Subject: [PATCH] add rtsp server --- RtspFace/live555/testProgs/testOnDemandRTSPServer.hpp | 0 RtspFace/PL_RTSPServer.cpp | 2 RtspFace/live555/testProgs/testH264VideoStreamer.hpp | 132 ++++++++++++++++++++++++++ RtspFace/PL_H264Encoder.cpp | 86 +++++++++++++++++ RtspFace/live555/testProgs/testRTSPClient.hpp | 0 RtspFace/PL_RTSPClient.cpp | 2 RtspFace/PL_H264Encoder.h | 24 ++++ 7 files changed, 245 insertions(+), 1 deletions(-) diff --git a/RtspFace/PL_H264Encoder.cpp b/RtspFace/PL_H264Encoder.cpp new file mode 100644 index 0000000..ebdfb7f --- /dev/null +++ b/RtspFace/PL_H264Encoder.cpp @@ -0,0 +1,86 @@ +#include "PL_H264Encoder.h" + +extern "C" +{ + #include <libyuv.h> +} + +struct PL_H264Encoder_Internal +{ + uint8_t buffer[1920*1080*4]; + size_t buffSize; + size_t buffSizeMax; + + bool payError; + + PL_H264Encoder_Internal() : + buffSize(0), buffSizeMax(sizeof(buffer)), + payError(true) + { + } + + ~PL_H264Encoder_Internal() + { + } + + void reset() + { + buffSize = 0; + payError = true; + } +}; + +PipeLineElem* create_PL_H264Encoder() +{ + return new PL_H264Encoder; +} + +PL_H264Encoder::PL_H264Encoder() : internal(new PL_H264Encoder_Internal) +{ +} + +PL_H264Encoder::~PL_H264Encoder() +{ + delete (PL_H264Encoder_Internal*)internal; + internal= nullptr; +} + +bool PL_H264Encoder::init(void* args) +{ + PL_H264Encoder_Internal* in = (PL_H264Encoder_Internal*)internal; + in->reset(); + + return true; +} + +void PL_H264Encoder::finit() +{ + PL_H264Encoder_Internal* in = (PL_H264Encoder_Internal*)internal; + +} + +bool PL_H264Encoder::pay(const PipeMaterial& pm) +{ + PL_H264Encoder_Internal* in = (PL_H264Encoder_Internal*)internal; + + //in->buffer readly + + //static size_t f=0; + //char fname[50]; + //sprintf(fname, "%u.bgra", ++f); + //FILE * pFile = fopen (fname,"wb"); + //fwrite (in->buffer , sizeof(char), in->buffSize, pFile); + //fclose(pFile); + + return true; +} + +bool PL_H264Encoder::gain(PipeMaterial& pm) +{ + PL_H264Encoder_Internal* in = (PL_H264Encoder_Internal*)internal; + + pm.buffer = in->buffer; + pm.buffSize = in->buffSize; + pm.former = this; + return true; +} diff --git a/RtspFace/PL_H264Encoder.h b/RtspFace/PL_H264Encoder.h new file mode 100644 index 0000000..9c85662 --- /dev/null +++ b/RtspFace/PL_H264Encoder.h @@ -0,0 +1,24 @@ +#ifndef _PL_H264Encoder_H_ +#define _PL_H264Encoder_H_ + +#include "PipeLine.h" + +class PL_H264Encoder : public PipeLineElem +{ +public: + PL_H264Encoder(); + virtual ~PL_H264Encoder(); + + virtual bool init(void* args); + virtual void finit(); + + virtual bool pay(const PipeMaterial& pm); + virtual bool gain(PipeMaterial& pm); + +private: + void* internal; +}; + +PipeLineElem* create_PL_H264Encoder(); + +#endif diff --git a/RtspFace/PL_RTSPClient.cpp b/RtspFace/PL_RTSPClient.cpp index 1ed98ee..b83ec88 100644 --- a/RtspFace/PL_RTSPClient.cpp +++ b/RtspFace/PL_RTSPClient.cpp @@ -5,7 +5,7 @@ void rtsp_client_fmtp_callback(void* arg, const char* val); void rtsp_client_frame_callback(void* arg, uint8_t* buffer, size_t buffSize); void rtsp_client_continue_callback(void* arg); -#include "testRTSPClient.hpp" +#include "live555/testProgs/testRTSPClient.hpp" struct RTSPClient_Internal { diff --git a/RtspFace/PL_RTSPServer.cpp b/RtspFace/PL_RTSPServer.cpp index be0807b..ad27c00 100644 --- a/RtspFace/PL_RTSPServer.cpp +++ b/RtspFace/PL_RTSPServer.cpp @@ -1,5 +1,7 @@ #include "PL_RTSPServer.h" +#include "testOnDemandRTSPServer.hpp" + struct PL_RTSPServer_Internal { uint8_t buffer[1920*1080*4]; diff --git a/RtspFace/live555/testProgs/testH264VideoStreamer.hpp b/RtspFace/live555/testProgs/testH264VideoStreamer.hpp new file mode 100644 index 0000000..74fe461 --- /dev/null +++ b/RtspFace/live555/testProgs/testH264VideoStreamer.hpp @@ -0,0 +1,132 @@ +/********** +This library is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for +more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +**********/ +// Copyright (c) 1996-2017, Live Networks, Inc. All rights reserved +// A test program that reads a H.264 Elementary Stream video file +// and streams it using RTP +// main program +// +// NOTE: For this application to work, the H.264 Elementary Stream video file *must* contain SPS and PPS NAL units, +// ideally at or near the start of the file. These SPS and PPS NAL units are used to specify 'configuration' information +// that is set in the output stream's SDP description (by the RTSP server that is built in to this application). +// Note also that - unlike some other "*Streamer" demo applications - the resulting stream can be received only using a +// RTSP client (such as "openRTSP") + +#include <liveMedia.hh> +#include <BasicUsageEnvironment.hh> +#include <GroupsockHelper.hh> + +UsageEnvironment* env; +char const* inputFileName = "test.264"; +H264VideoStreamFramer* videoSource; +RTPSink* videoSink; + +void play(); // forward + +int main(int argc, char** argv) { + // Begin by setting up our usage environment: + TaskScheduler* scheduler = BasicTaskScheduler::createNew(); + env = BasicUsageEnvironment::createNew(*scheduler); + + // Create 'groupsocks' for RTP and RTCP: + struct in_addr destinationAddress; + destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env); + // Note: This is a multicast address. If you wish instead to stream + // using unicast, then you should use the "testOnDemandRTSPServer" + // test program - not this test program - as a model. + + const unsigned short rtpPortNum = 18888; + const unsigned short rtcpPortNum = rtpPortNum+1; + const unsigned char ttl = 255; + + const Port rtpPort(rtpPortNum); + const Port rtcpPort(rtcpPortNum); + + Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl); + rtpGroupsock.multicastSendOnly(); // we're a SSM source + Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl); + rtcpGroupsock.multicastSendOnly(); // we're a SSM source + + // Create a 'H264 Video RTP' sink from the RTP 'groupsock': + OutPacketBuffer::maxSize = 100000; + videoSink = H264VideoRTPSink::createNew(*env, &rtpGroupsock, 96); + + // Create (and start) a 'RTCP instance' for this RTP sink: + const unsigned estimatedSessionBandwidth = 500; // in kbps; for RTCP b/w share + const unsigned maxCNAMElen = 100; + unsigned char CNAME[maxCNAMElen+1]; + gethostname((char*)CNAME, maxCNAMElen); + CNAME[maxCNAMElen] = '\0'; // just in case + RTCPInstance* rtcp + = RTCPInstance::createNew(*env, &rtcpGroupsock, + estimatedSessionBandwidth, CNAME, + videoSink, NULL /* we're a server */, + True /* we're a SSM source */); + // Note: This starts RTCP running automatically + + RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554); + if (rtspServer == NULL) { + *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n"; + exit(1); + } + ServerMediaSession* sms + = ServerMediaSession::createNew(*env, "testStream", inputFileName, + "Session streamed by \"testH264VideoStreamer\"", + True /*SSM*/); + sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp)); + rtspServer->addServerMediaSession(sms); + + char* url = rtspServer->rtspURL(sms); + *env << "Play this stream using the URL \"" << url << "\"\n"; + delete[] url; + + // Start the streaming: + *env << "Beginning streaming...\n"; + play(); + + env->taskScheduler().doEventLoop(); // does not return + + return 0; // only to prevent compiler warning +} + +void afterPlaying(void* /*clientData*/) { + *env << "...done reading from file\n"; + videoSink->stopPlaying(); + Medium::close(videoSource); + // Note that this also closes the input file that this source read from. + + // Start playing once again: + play(); +} + +void play() { + // Open the input file as a 'byte-stream file source': + ByteStreamFileSource* fileSource + = ByteStreamFileSource::createNew(*env, inputFileName); + if (fileSource == NULL) { + *env << "Unable to open file \"" << inputFileName + << "\" as a byte-stream file source\n"; + exit(1); + } + + FramedSource* videoES = fileSource; + + // Create a framer for the Video Elementary Stream: + videoSource = H264VideoStreamFramer::createNew(*env, videoES); + + // Finally, start playing: + *env << "Beginning to read from file...\n"; + videoSink->startPlaying(*videoSource, afterPlaying, videoSink); +} diff --git a/RtspFace/testOnDemandRTSPServer.cpp b/RtspFace/live555/testProgs/testOnDemandRTSPServer.hpp similarity index 100% rename from RtspFace/testOnDemandRTSPServer.cpp rename to RtspFace/live555/testProgs/testOnDemandRTSPServer.hpp diff --git a/RtspFace/testRTSPClient.hpp b/RtspFace/live555/testProgs/testRTSPClient.hpp similarity index 100% rename from RtspFace/testRTSPClient.hpp rename to RtspFace/live555/testProgs/testRTSPClient.hpp -- Gitblit v1.8.0