【live555】MediaSink类分析
来源:互联网 发布:godaddy域名优惠 编辑:程序博客网 时间:2024/06/05 08:53
MediaSink是Medium的子类。
是所有sink类的基类。
(一)MediaSink
1. 需要他的子类实现:
(1)停止播放 stopPlaying()。(虚函数)。
在MediaSink的虚函数中,会调用这个函数,停止播放。
(2)继续播放 continuePlaying()(纯虚函数)。
(3) 这个函数仅仅支持FramedSource类型的输入源。 (虚函数)
virtual Boolean sourceIsCompatibleWithUs(MediaSource& source);
// called by startPlaying()
(4) (虚函数),如果子类直接继承的话,就是false。
// Test for specific types of sink:
virtual Boolean isRTPSink() const;
(5) 虚函数,如果子类直接继承的话就是ture。
// redefined virtual functions:
virtual Boolean isSink() const;
2. 需要子类继承
开始播放 startPlaying 函数。
Boolean startPlaying(MediaSource& source,
afterPlayingFunc* afterFunc,
void* afterClientData);
处理的参数是 MediaSource 类型的。
处理完数据之后,要用传入的afterPlayingFunc 函数处理afterClientData 数据。
这俩都是作为private的变量存在这个类中的:
// The following fields are used when we're being played:
afterPlayingFunc* fAfterFunc; //一个函数
void* fAfterClientData;
startPlaying会调用另外两个protect的虚函数:
sourceIsCompatibleWithUs 和 continuePlaying()
MediaSink的构造函数和析构函数是protect的:
MediaSink(UsageEnvironment& env); // abstract base class
virtual ~MediaSink();
3. MediaSink有一个static的方法:
static void onSourceClosure(void* clientData); // can be used in "getNextFrame()" calls
这个 静态的方法,是被getNextFrame调用 的。
同时,还有一个非static的同名重载方法:
void onSourceClosure();
注释说,这个函数是被continuePlaying 这个唯一的虚函数调用的,用来当检测到正在播放的source已经关闭的时候,调用。
// should be called (on ourselves) by continuePlaying() when it
// discovers that the source we're playing from has closed.
根据实现,可以看出:
静态的方法实际是在调用非静态的方法,并且,静态方法的所谓的参数clientData是一个MediaSInk类型的对象。
void MediaSink::onSourceClosure(void* clientData) { MediaSink* sink = (MediaSink*)clientData; sink->onSourceClosure();}
那这个非静态的,实际执行关闭输入源的方法,是怎么做的呢?
【1】 取消所有的等待任务。
【2】输入源域设置为NULL
【3】执行函数指针 (这个是关键过程)
if (fAfterFunc != NULL) { (*fAfterFunc)(fAfterClientData); }
void MediaSink::onSourceClosure() { // Cancel any pending tasks: envir().taskScheduler().unscheduleDelayedTask(nextTask()); fSource = NULL; // indicates that we can be played again if (fAfterFunc != NULL) { (*fAfterFunc)(fAfterClientData); }}
(2)记录着FramedSource类型的输入源。
FramedSource* fSource;
输入源是public的。
也有一个public的方法,来返回这个输入源。
FramedSource* source() const {return fSource;}
在构造函数中,输入源会默认置为NULL。
======
class MediaSink: public Medium {
public:
static Boolean lookupByName(UsageEnvironment& env, char const* sinkName,
MediaSink*& resultSink);
typedef void (afterPlayingFunc)(void* clientData); //一个函数指针类型
Boolean startPlaying(MediaSource& source,
afterPlayingFunc* afterFunc,
void* afterClientData);
virtual void stopPlaying();
// Test for specific types of sink:
virtual Boolean isRTPSink() const;
FramedSource* source() const {return fSource;}
protected:
MediaSink(UsageEnvironment& env); // abstract base class
virtual ~MediaSink();
virtual Boolean sourceIsCompatibleWithUs(MediaSource& source);
// called by startPlaying()
virtual Boolean continuePlaying() = 0;
// called by startPlaying()
static void onSourceClosure(void* clientData); // can be used in "getNextFrame()" calls
void onSourceClosure();
// should be called (on ourselves) by continuePlaying() when it
// discovers that the source we're playing from has closed.
FramedSource* fSource;
private:
// redefined virtual functions:
virtual Boolean isSink() const;
private:
// The following fields are used when we're being played:
afterPlayingFunc* fAfterFunc; //一个函数
void* fAfterClientData;
};
class MediaSink: public Medium {public: static Boolean lookupByName(UsageEnvironment& env, char const* sinkName, MediaSink*& resultSink); typedef void (afterPlayingFunc)(void* clientData); //一个函数指针类型 Boolean startPlaying(MediaSource& source, afterPlayingFunc* afterFunc, void* afterClientData); virtual void stopPlaying(); // Test for specific types of sink: virtual Boolean isRTPSink() const; FramedSource* source() const {return fSource;}protected: MediaSink(UsageEnvironment& env); // abstract base class virtual ~MediaSink(); virtual Boolean sourceIsCompatibleWithUs(MediaSource& source); // called by startPlaying() virtual Boolean continuePlaying() = 0; // called by startPlaying() static void onSourceClosure(void* clientData); // can be used in "getNextFrame()" calls void onSourceClosure(); // should be called (on ourselves) by continuePlaying() when it // discovers that the source we're playing from has closed. FramedSource* fSource;private: // redefined virtual functions: virtual Boolean isSink() const;private: // The following fields are used when we're being played: afterPlayingFunc* fAfterFunc; //一个函数 void* fAfterClientData;};
====
===========================
(二)MediaSink的实现:
1 。 可以看到,sourceIsCompatibleWithUs 是检查是不是FramedSourc类型的源。
Boolean MediaSink::sourceIsCompatibleWithUs(MediaSource& source) {
// We currently support only framed sources.
return source.isFramedSource(); //是不是FramedSource
}
2. 当开始播放之后,记录在MediaSink中的FramedSource是被赋值的。
动用了强制类型转换,将MediaSource变为FrameSource。
fSource = (FramedSource*)&source;
也就是说fSource 非空。
同时, 这俩非常重要的私有属性,也要被赋值。
fAfterFunc = afterFunc; fAfterClientData = afterClientData;
可以看到,实际执行功能的方法是,唯一的纯虚函数
continuePlaying();
Boolean MediaSink::startPlaying(MediaSource& source,afterPlayingFunc* afterFunc,void* afterClientData) { // Make sure we're not already being played: if (fSource != NULL) { envir().setResultMsg("This sink is already being played"); return False; } // Make sure our source is compatible: if (!sourceIsCompatibleWithUs(source)) { envir().setResultMsg("MediaSink::startPlaying(): source is not compatible!"); return False; } fSource = (FramedSource*)&source; fAfterFunc = afterFunc; fAfterClientData = afterClientData; return continuePlaying();}
3. 停止播放
(1)可以推测出,
获取每一帧,是由FramedSource的对象来控制的,比如说停止获取帧,就是调用 stopGettingFrames();
// First, tell the source that we're no longer interested: if (fSource != NULL) fSource->stopGettingFrames();
(2)MediaSink 会要求调度器停止调度其余的等待的任务。
// Cancel any pending tasks: envir().taskScheduler().unscheduleDelayedTask(nextTask());
(3)某个source可以再次被播放???
把fSource置为NULL,我觉得只能是让一个sink自由吧,不能改变source吧。
fSource = NULL; // indicates that we can be played again fAfterFunc = NULL;
4. 关闭输入源。
参见(一)3.
////////// MediaSink //////////MediaSink::MediaSink(UsageEnvironment& env) : Medium(env), fSource(NULL) {}MediaSink::~MediaSink() { stopPlaying();}Boolean MediaSink::isSink() const { return True;}Boolean MediaSink::lookupByName(UsageEnvironment& env, char const* sinkName,MediaSink*& resultSink) { resultSink = NULL; // unless we succeed Medium* medium; if (!Medium::lookupByName(env, sinkName, medium)) return False; if (!medium->isSink()) { env.setResultMsg(sinkName, " is not a media sink"); return False; } resultSink = (MediaSink*)medium; return True;}Boolean MediaSink::sourceIsCompatibleWithUs(MediaSource& source) { // We currently support only framed sources. return source.isFramedSource(); //是不是FramedSource}Boolean MediaSink::startPlaying(MediaSource& source,afterPlayingFunc* afterFunc,void* afterClientData) { // Make sure we're not already being played: if (fSource != NULL) { envir().setResultMsg("This sink is already being played"); return False; } // Make sure our source is compatible: if (!sourceIsCompatibleWithUs(source)) { envir().setResultMsg("MediaSink::startPlaying(): source is not compatible!"); return False; } fSource = (FramedSource*)&source; fAfterFunc = afterFunc; fAfterClientData = afterClientData; return continuePlaying();}void MediaSink::stopPlaying() { // First, tell the source that we're no longer interested: if (fSource != NULL) fSource->stopGettingFrames(); // Cancel any pending tasks: envir().taskScheduler().unscheduleDelayedTask(nextTask()); fSource = NULL; // indicates that we can be played again fAfterFunc = NULL;}void MediaSink::onSourceClosure(void* clientData) { MediaSink* sink = (MediaSink*)clientData; sink->onSourceClosure();}void MediaSink::onSourceClosure() { // Cancel any pending tasks: envir().taskScheduler().unscheduleDelayedTask(nextTask()); fSource = NULL; // indicates that we can be played again if (fAfterFunc != NULL) { (*fAfterFunc)(fAfterClientData); }}Boolean MediaSink::isRTPSink() const { return False; // default implementation}void MediaSink::stopPlaying() { // First, tell the source that we're no longer interested: if (fSource != NULL) fSource->stopGettingFrames(); // Cancel any pending tasks: envir().taskScheduler().unscheduleDelayedTask(nextTask()); fSource = NULL; // indicates that we can be played again fAfterFunc = NULL;}
(三)总结一下
(1)作为所有sink基类的MediaSink ,其父类是livemedia库的基类Medium。
(2)MediaSink类的主要功能是 开始播放、停止播放,这俩是MediaSink的使命。
(3)开始播放的实际执行者叫做”继续播放“,这是一个必须由子类实现的纯虚函数。
(4)停止播放时要调用FramedSource的”停止获取帧“函数。
(5)关闭输入源这个功能
【1】静态方法:好像是一种响应,是被"getNextFrame()" 所调用的。(这个 "getNextFrame()" 是来自哪里的???)
【2】实际要调用一个非静态的方法,该方法的核心过程是
if (fAfterFunc != NULL) { (*fAfterFunc)(fAfterClientData); }这俩都是指针吧,是在”开始播放“方法中传递进来的。
看起来牵扯到了很多,source 、 sink 都有涉及,sink主要是跟source打交道的啊???!!!肿么没见session呢?
- 【live555】MediaSink类分析
- 【live555】WISInput类分析
- live555 类图结构分析
- live555 分析
- live555 分析
- Live555 分析(一):类介绍
- live555代码分析
- live555 源码分析
- live555 模块分析
- Live555 RTSPServer 分析
- live555 分析- openRtsp
- live555源代码分析
- 【live555】UsageEnvrionment分析
- live555 分析- openRtsp
- 【live555】FramedFilter粗浅分析
- 【live555】MPEGVideoStreamFramer简要分析
- 【live555】OnDemandServerMediaSubsession 粗浅分析
- 【live555】OutPacketBuffer粗浅分析
- c++中日期转换
- android浏览器插件
- yii zii.widgets.grid.CGridView 时间插件查询
- 小记,android 手机不显示百度地图,全白网格
- 判断程序实例是否已经运行的N种方法
- 【live555】MediaSink类分析
- 黑马程序员_008_Map 的两种取出方式
- Error And Bias
- Oracle数据类型浅析:varchar2
- 睡眠--TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE
- Windows 下 AnacondaCE 安装 Theano 0.6.0rc3 问题
- Navicat for Oracle的安装配置过程
- Oracle中的Raw类型
- 黑马程序员_009_TreeSet的两种排序方式和HashSet保持元素唯一性的方式