zoukankan      html  css  js  c++  java
  • Live555 直播源 以及MediaSubsession

    /*
     * H264DeviceSource.hh
     *
     *  Created on: 2014年7月19日
     *      Author: zjzhang
     */
    
    #ifndef H264DEVICESOURCE_HH_
    #define H264DEVICESOURCE_HH_
    #include<DeviceSource.hh>
    
    class 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 stub
    
    	delete[] 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 yet
    
    	unsigned 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 class
      DeviceServerMediaSubsession(UsageEnvironment& env,
    			    Boolean reuseFirstSource);
      virtual ~DeviceServerMediaSubsession();
    
      void setDoneFlag() { fDoneFlag = ~0; }
    
    protected: // redefined virtual functions
      virtual 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 ms
    		nextTask() = 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;
    }
    




  • 相关阅读:
    glog下载、安装、使用
    VS所需插件
    Qt 实现动态调整流程指令顺序(通过鼠标事件实现)
    QComboBox实现复选框功能
    QString string char* int互相转化
    Qt 滚动区域显示下拉框
    模式对话框,非模式对话框,reject和accept()槽函数确定对话框的返回值
    QT递归搜索文件(entryList)
    QT中foreach的使用
    Qstring格式化字符串
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7058028.html
Copyright © 2011-2022 走看看