Live555 直播源 以及MediaSubsession

/** H264DeviceSource.hh**  Created on: 2014年7月19日*      Author: zjzhang*/#ifndef H264DEVICESOURCE_HH_
#define H264DEVICESOURCE_HH_
#includeclass H264DeviceSource: public DeviceSource {
public:static DeviceSource* createNew(UsageEnvironment& env,u_int8_t index=1,u_int width=352,u_int height=288,u_int fps=15,u_int kbps=100);
protected:H264DeviceSource(UsageEnvironment& env,u_int8_t index,u_int width,u_int height,u_int fps,u_int kbps);virtual ~H264DeviceSource();
private:virtual void doGetNextFrame();virtual unsigned maxFrameSize() const;int fHeight;int fWidth;void *fH264Encoder;u_int8_t * fBuffer;u_int fBufferSize;
};#endif /* H264DEVICESOURCE_HH_ */

/** H264DeviceSource.cpp**  Created on: 2014年7月19日*      Author: zjzhang*/#include "H264DeviceSource.hh"
#ifdef __cplusplus
extern "C" {
#endif
#include "H264Stream.h"
#ifdef __cplusplus
}
#endif
DeviceSource*
H264DeviceSource::createNew(UsageEnvironment& env, u_int8_t index, u_int width,u_int height, u_int fps, u_int kbps) {return new H264DeviceSource(env, index, width, height, fps, kbps);
}H264DeviceSource::H264DeviceSource(UsageEnvironment& env, u_int8_t index,u_int width, u_int height, u_int fps, u_int kbps) :DeviceSource(env, DeviceParameters()) {openCamera(1);getFrame(1);fHeight = getHeight(1);fWidth = getWidth(1);openH264Encoder(fWidth, fHeight, fps, kbps, &fH264Encoder);fBufferSize = fHeight * fWidth * 3 / 2;fBuffer = new uint8_t[fBufferSize];}H264DeviceSource::~H264DeviceSource() {// TODO Auto-generated destructor stubdelete[] fBuffer;closeH264Encoder(fH264Encoder);closeCamera(1);
}
unsigned H264DeviceSource::maxFrameSize() const {// By default, this source has no maximum frame size.return 4096;
}
void H264DeviceSource::doGetNextFrame() {if (!isCurrentlyAwaitingData())return; // we're not ready for the data yetunsigned char * rgbBuffer = getFrame(1);ConvertRGB2YUV(fWidth, fHeight, rgbBuffer, fBuffer);int newFrameSize = encodeFrame(fH264Encoder, fBuffer, fBufferSize);// Deliver the data here:if (newFrameSize < 0) {handleClosure();return;}if (newFrameSize > fMaxSize) {fFrameSize = fMaxSize;fNumTruncatedBytes = newFrameSize - fMaxSize;} else {fFrameSize = newFrameSize;}if (fFrameSize > 0) {int result = 0;int p = 0;do {unsigned long len = 0;result = getNextPacket(fH264Encoder, fBuffer + p, &len);p += len;} while (result > 0);}gettimeofday(&fPresentationTime, NULL); // If you have a more accurate time - e.g., from an encoder - then use that instead.// If the device is *not* a 'live source' (e.g., it comes instead from a file or buffer), then set "fDurationInMicroseconds" here.memmove(fTo, fBuffer, fFrameSize);FramedSource::afterGetting(this);
}



#ifndef _DEVIC_SERVER_MEDIA_SUBSESSION_HH
#define _DEVICE_SERVER_MEDIA_SUBSESSION_HH#ifndef _ON_DEMAND_SERVER_MEDIA_SUBSESSION_HH
#include "OnDemandServerMediaSubsession.hh"
#endif
class  DeviceSource;
class DeviceServerMediaSubsession: public OnDemandServerMediaSubsession {
public:static DeviceServerMediaSubsession*createNew(UsageEnvironment& env,Boolean reuseFirstSource);// Used to implement "getAuxSDPLine()":void checkForAuxSDPLine1();void afterPlayingDummy1();
protected: // we're a virtual base classDeviceServerMediaSubsession(UsageEnvironment& env,Boolean reuseFirstSource);virtual ~DeviceServerMediaSubsession();void setDoneFlag() { fDoneFlag = ~0; }protected: // redefined virtual functionsvirtual char const* getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource);virtual FramedSource* createNewStreamSource(unsigned clientSessionId,unsigned& estBitrate);virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,unsigned char rtpPayloadTypeIfDynamic,FramedSource* inputSource);private:char* fAuxSDPLine;char fDoneFlag; // used when setting up "fAuxSDPLine"RTPSink* fDummyRTPSink; // ditto
};#endif

#include "DeviceServerMediaSubsession.hh"
#include "H264VideoRTPSink.hh"
#include "DeviceSource.hh"
#include "H264VideoStreamFramer.hh"
#include "H264DeviceSource.hh"DeviceServerMediaSubsession*
DeviceServerMediaSubsession::createNew(UsageEnvironment& env,Boolean reuseFirstSource) {return new DeviceServerMediaSubsession(env, reuseFirstSource);
}
DeviceServerMediaSubsession::DeviceServerMediaSubsession(UsageEnvironment& env,Boolean reuseFirstSource) :OnDemandServerMediaSubsession(env, reuseFirstSource) {
}DeviceServerMediaSubsession::~DeviceServerMediaSubsession() {
}FramedSource* DeviceServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {DeviceSource* source = H264DeviceSource::createNew(envir());return H264VideoStreamFramer::createNew(envir(), source);
}RTPSink* DeviceServerMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock,unsigned char rtpPayloadTypeIfDynamic, FramedSource* /*inputSource*/) {return H264VideoRTPSink::createNew(envir(), rtpGroupsock,rtpPayloadTypeIfDynamic);
}static void afterPlayingDummy(void* clientData) {DeviceServerMediaSubsession* subsess =(DeviceServerMediaSubsession*) clientData;subsess->afterPlayingDummy1();
}void DeviceServerMediaSubsession::afterPlayingDummy1() {// Unschedule any pending 'checking' task:envir().taskScheduler().unscheduleDelayedTask(nextTask());// Signal the event loop that we're done:setDoneFlag();
}static void checkForAuxSDPLine(void* clientData) {DeviceServerMediaSubsession* subsess =(DeviceServerMediaSubsession*) clientData;subsess->checkForAuxSDPLine1();
}void DeviceServerMediaSubsession::checkForAuxSDPLine1() {char const* dasl;if (fAuxSDPLine != NULL) {// Signal the event loop that we're done:setDoneFlag();} else if (fDummyRTPSink != NULL&& (dasl = fDummyRTPSink->auxSDPLine()) != NULL) {fAuxSDPLine = strDup(dasl);fDummyRTPSink = NULL;// Signal the event loop that we're done:setDoneFlag();} else if (!fDoneFlag) {// try again after a brief delay:int uSecsToDelay = 100000; // 100 msnextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,(TaskFunc*) checkForAuxSDPLine, this);}
}
char const* DeviceServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink,FramedSource* inputSource) {if (fAuxSDPLine != NULL)return fAuxSDPLine; // it's already been set up (for a previous client)if (fDummyRTPSink == NULL) { // we're not already setting it up for another, concurrent stream// Note: For H264 video files, the 'config' information ("profile-level-id" and "sprop-parameter-sets") isn't known// until we start reading the file.  This means that "rtpSink"s "auxSDPLine()" will be NULL initially,// and we need to start reading data from our file until this changes.fDummyRTPSink = rtpSink;// Start reading the file:fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);// Check whether the sink's 'auxSDPLine()' is ready:checkForAuxSDPLine(this);}envir().taskScheduler().doEventLoop(&fDoneFlag);return fAuxSDPLine;
}





本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部