| | |
| | | #include <liveMedia.hh>
|
| | | #include <BasicUsageEnvironment.hh>
|
| | |
|
| | | class MyH264FramedSource : public FramedSource
|
| | | class MyH264FramedSource;
|
| | |
|
| | | struct RTSPServer_Internal
|
| | | {
|
| | | public:
|
| | | static MyH264FramedSource* createNew(UsageEnvironment& env);
|
| | |
|
| | | protected:
|
| | | MyH264FramedSource(UsageEnvironment& env)
|
| | | virtual ~MyH264FramedSource()
|
| | |
|
| | | // overide FramedSource
|
| | | virtual void doGetNextFrame()
|
| | | {
|
| | | // deliverFrame
|
| | | //if (fFrameSize > 0)
|
| | | //{
|
| | | // // send Frame to the consumer
|
| | | // FramedSource::afterGetting(this); |
| | | //}
|
| | | |
| | | |
| | | // isCurrentlyAwaitingData
|
| | | //if (frame->m_size > fMaxSize) |
| | | //{
|
| | | // fFrameSize = fMaxSize;
|
| | | // fNumTruncatedBytes = frame->m_size - fMaxSize;
|
| | | //} |
| | | //else |
| | | //{
|
| | | // fFrameSize = frame->m_size;
|
| | | //}
|
| | | //memcpy(fTo, frame->m_buffer, fFrameSize);
|
| | | //if (fFrameSize > 0)
|
| | | // FramedSource::afterGetting(this);
|
| | | }
|
| | | |
| | | virtual void doStopGettingFrames()
|
| | | {
|
| | | FramedSource::doStopGettingFrames();
|
| | | }
|
| | | };
|
| | |
|
| | | struct PL_RTSPServer_Internal
|
| | | {
|
| | | //uint8_t buffer[1920*1080*4];
|
| | | //size_t buffSize;
|
| | | //size_t buffSizeMax;
|
| | | uint8_t* buffer;
|
| | | size_t buffSize;
|
| | |
|
| | | bool payError;
|
| | | pthread_t live_daemon_thid;
|
| | |
| | |
|
| | | char descriptionString[1024];
|
| | |
|
| | | PL_RTSPServer_Internal() : |
| | | //buffSize(0), buffSizeMax(sizeof(buffer)), |
| | | MyH264FramedSource* pMyH264FramedSource;
|
| | | |
| | | RTSPServer_Internal() : |
| | | buffer(nullptr), buffSize(0), |
| | | payError(true), live_daemon_thid(0), frame_mutex(nullptr), live_daemon_running(false),
|
| | | env(nullptr), reuseFirstSource(False), iFramesOnly(False), authDB(nullptr),
|
| | | rtspServer(nullptr);
|
| | | rtspServer(nullptr)
|
| | | {
|
| | | pthread_mutex_init(frame_mutex, NULL);
|
| | | }
|
| | |
|
| | | ~PL_RTSPServer_Internal()
|
| | | ~RTSPServer_Internal()
|
| | | {
|
| | | if (frame_mutex != nullptr)
|
| | | {
|
| | |
| | |
|
| | | void reset()
|
| | | {
|
| | | //buffSize = 0;
|
| | | buffer = nullptr;
|
| | | buffSize = 0;
|
| | |
|
| | | payError = true;
|
| | |
|
| | |
| | | rtspServer = nullptr;
|
| | |
|
| | | strcpy(descriptionString, "Session streamed by \"testOnDemandRTSPServer\"");
|
| | | |
| | | pMyH264FramedSource = nullptr;
|
| | | }
|
| | | };
|
| | |
|
| | |
|
| | | class MyH264FramedSource : public FramedSource
|
| | | {
|
| | | public:
|
| | | static MyH264FramedSource* createNew(UsageEnvironment& _env, RTSPServer_Internal& _in)
|
| | | {
|
| | | return new MyH264FramedSource(_env, _in);
|
| | | }
|
| | | |
| | | // deliver frame to the sink
|
| | | bool deliverFrame()
|
| | | {
|
| | | int ret = false;
|
| | | if (isCurrentlyAwaitingData()) |
| | | {
|
| | | fDurationInMicroseconds = 0;
|
| | | fFrameSize = 0;
|
| | | |
| | | if (in.buffSize > fMaxSize) |
| | | {
|
| | | fFrameSize = fMaxSize;
|
| | | fNumTruncatedBytes = in.buffSize - fMaxSize;
|
| | | } |
| | | else |
| | | {
|
| | | fFrameSize = in.buffSize;
|
| | | }
|
| | | |
| | | if (fFrameSize > 0)
|
| | | {
|
| | | memcpy(fTo, in.buffer, fFrameSize);
|
| | | |
| | | int ret = pthread_mutex_unlock(in.frame_mutex);
|
| | | if(ret != 0)
|
| | | {
|
| | | printf("pthread_mutex_unlock frame_mutex: %s/n", strerror(ret));
|
| | | return false;
|
| | | }
|
| | | |
| | | ret = true;
|
| | | }
|
| | | }
|
| | |
|
| | | return ret;
|
| | | }
|
| | |
|
| | | protected:
|
| | | MyH264FramedSource(UsageEnvironment& _env, RTSPServer_Internal& _in) : |
| | | FramedSource(_env), env(_env), in(_in)
|
| | | {
|
| | | }
|
| | | |
| | | virtual ~MyH264FramedSource()
|
| | | {
|
| | | }
|
| | |
|
| | | // overide FramedSource
|
| | | virtual void doGetNextFrame()
|
| | | {
|
| | | printf("MyH264FramedSource::doGetNextFrame\n");
|
| | | |
| | | int ret = pthread_mutex_lock(in.frame_mutex);
|
| | | if(ret != 0)
|
| | | {
|
| | | printf("pthread_mutex_lock frame_mutex: %s/n", strerror(ret));
|
| | | return;
|
| | | }
|
| | |
|
| | | // deliverFrame
|
| | | //if (fFrameSize > 0)
|
| | | //{
|
| | | // send Frame to the consumer
|
| | | FramedSource::afterGetting(this); |
| | | //}
|
| | | }
|
| | | |
| | | virtual void doStopGettingFrames()
|
| | | {
|
| | | FramedSource::doStopGettingFrames();
|
| | | }
|
| | | |
| | | private:
|
| | | UsageEnvironment& env;
|
| | | RTSPServer_Internal& in;
|
| | | };
|
| | |
|
| | | PipeLineElem* create_PL_RTSPServer()
|
| | |
| | | return new PL_RTSPServer;
|
| | | }
|
| | |
|
| | | PL_RTSPServer::PL_RTSPServer() : internal(new PL_RTSPServer_Internal)
|
| | | PL_RTSPServer::PL_RTSPServer() : internal(new RTSPServer_Internal)
|
| | | {
|
| | | }
|
| | |
|
| | | PL_RTSPServer::~PL_RTSPServer()
|
| | | {
|
| | | delete (PL_RTSPServer_Internal*)internal;
|
| | | delete (RTSPServer_Internal*)internal;
|
| | | internal= nullptr;
|
| | | }
|
| | |
|
| | | void* live_daemon_thd(void* arg)
|
| | | {
|
| | | RTSPClient_Internal* in = (RTSPClient_Internal*)arg;
|
| | | RTSPServer_Internal* in = (RTSPServer_Internal*)arg;
|
| | |
|
| | | // Begin by setting up our usage environment:
|
| | | TaskScheduler* scheduler = BasicTaskScheduler::createNew();
|
| | |
| | | #endif
|
| | |
|
| | | // Create the RTSP server:
|
| | | in->rtspServer = RTSPServer::createNew(*env, 8554, authDB);
|
| | | if (rtspServer == NULL)
|
| | | in->rtspServer = RTSPServer::createNew(*(in->env), 8554, in->authDB);
|
| | | if (in->rtspServer == NULL)
|
| | | {
|
| | | *(in->env) << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
|
| | | return;
|
| | | *(in->env) << "Failed to create RTSP server: " << in->env->getResultMsg() << "\n";
|
| | | return nullptr;
|
| | | }
|
| | |
|
| | | // Set up each of the possible streams that can be served by the
|
| | |
| | |
|
| | | char const* streamName = "plH264Encoder";
|
| | | ServerMediaSession* sms = ServerMediaSession::createNew(*(in->env), streamName, streamName, in->descriptionString);
|
| | | sms->addSubsession(MyH264FramedSource::createNew(*(in->env), in));
|
| | | in->pMyH264FramedSource = MyH264FramedSource::createNew(*(in->env), *in);
|
| | | sms->addSubsession(in->pMyH264FramedSource);
|
| | | in->rtspServer->addServerMediaSession(sms);
|
| | |
|
| | | // announceStream
|
| | | char* url = rtspServer->rtspURL(sms);
|
| | | *(in->env) << "\n\"" << streamName << "\" stream, from the file \"" << inputFileName << "\"\n";
|
| | | *(in->env) << "Play this stream using the URL \"" << url << "\"\n";
|
| | | char* url = in->rtspServer->rtspURL(sms);
|
| | | *(in->env) << "Play this stream using the URL " << url << "\n";
|
| | | delete[] url;
|
| | |
|
| | | // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.
|
| | | // Try first with the default HTTP port (80), and then with the alternative HTTP
|
| | | // port numbers (8000 and 8080).
|
| | |
|
| | | if (rtspServer->setUpTunnelingOverHTTP(80))
|
| | | *(in->env) << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
|
| | | if (in->rtspServer->setUpTunnelingOverHTTP(80))
|
| | | *(in->env) << "\n(We use port " << in->rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
|
| | | else
|
| | | *(in->env) << "\n(RTSP-over-HTTP tunneling is not available.)\n";
|
| | |
|
| | | in->live_daemon_running = true;
|
| | | env->taskScheduler().doEventLoop(); // does not return
|
| | | in->env->taskScheduler().doEventLoop(); // does not return
|
| | | in->live_daemon_running = false;
|
| | | }
|
| | |
|
| | | bool PL_RTSPServer::init(void* args)
|
| | | {
|
| | | PL_RTSPServer_Internal* in = (PL_RTSPServer_Internal*)internal;
|
| | | RTSPServer_Internal* in = (RTSPServer_Internal*)internal;
|
| | | in->reset();
|
| | |
|
| | | int ret = pthread_mutex_lock(in->frame_mutex);
|
| | |
| | |
|
| | | void PL_RTSPServer::finit()
|
| | | {
|
| | | RTSPClient_Internal* in = (RTSPClient_Internal*)internal;
|
| | | RTSPServer_Internal* in = (RTSPServer_Internal*)internal;
|
| | |
|
| | | pthread_join(in->live_daemon_thid, NULL);
|
| | | }
|
| | |
|
| | | bool PL_RTSPServer::pay(const PipeMaterial& pm)
|
| | | {
|
| | | PL_RTSPServer_Internal* in = (PL_RTSPServer_Internal*)internal;
|
| | | RTSPServer_Internal* in = (RTSPServer_Internal*)internal;
|
| | |
|
| | | return true;
|
| | | in->buffer = pm.buffer;
|
| | | in->buffSize = pm.buffSize;
|
| | | |
| | | return in->pMyH264FramedSource->deliverFrame();
|
| | | }
|
| | |
|
| | | bool PL_RTSPServer::gain(PipeMaterial& pm)
|
| | | {
|
| | | PL_RTSPServer_Internal* in = (PL_RTSPServer_Internal*)internal;
|
| | | RTSPServer_Internal* in = (RTSPServer_Internal*)internal;
|
| | |
|
| | | pm.buffer = nullptr;
|
| | | pm.buffSize = 0;
|