live555学习-FramedSource详解

来源:互联网 发布:java web高级编程 pdf 编辑:程序博客网 时间:2024/06/06 16:56

FramedSource讲解

FramedSource是一个抽象类,继承自mediaSource继承自medium,里面有纯虚函数virtual void doGetNextFrame() = 0;

主要作用就是从文件中获得数据,只是获得数据,交给分析H264or5VideoStreamParser分析获得NALU

关于有关牵涉到文件操作的基本都是直接或者间接继承自该类:例如H26VideoFileSourceMediaSubsession

主要函数流程:获得下一包数据getNextFrame

void FramedSource::getNextFrame(unsigned char* to, unsigned maxSize,afterGettingFunc* afterGettingFunc,void* afterGettingClientData,onCloseFunc* onCloseFunc,void* onCloseClientData) {  // Make sure we're not already being read:  if (fIsCurrentlyAwaitingData) {    envir() << "FramedSource[" << this << "]::getNextFrame(): attempting to read more than once at the same time!\n";    envir().internalError();  }  fTo = to;//存放读取到数据的内存指针  fMaxSize = maxSize;//允许的最大数据量,即fTo指针指向的内存区间的大小  fNumTruncatedBytes = 0; // by default; could be changed by doGetNextFrame()   表示实际读取数据大于<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">fMaxSize的时候,多了多少字节</span>  fDurationInMicroseconds = 0; // by default; could be changed by doGetNextFrame()  fAfterGettingFunc = afterGettingFunc;  fAfterGettingClientData = afterGettingClientData;  fOnCloseFunc = onCloseFunc;  fOnCloseClientData = onCloseClientData;  fIsCurrentlyAwaitingData = True;  doGetNextFrame();}

由此可见,此函数初始化了几个必要参数,并调用了纯虚函数doGetNextFrame();此函数留给派生类实现,例如ByteStreamFileSource类实现如下

void ByteStreamFileSource::doGetNextFrame() {  if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && fNumBytesToStream == 0)) {    handleClosure();    return;  }#ifdef READ_FROM_FILES_SYNCHRONOUSLY  doReadFromFile();#else  if (!fHaveStartedReading) {    // Await readable data from the file:    envir().taskScheduler().turnOnBackgroundReadHandling(fileno(fFid),       (TaskScheduler::BackgroundHandlerProc*)&fileReadableHandler, this);    fHaveStartedReading = True;  }#endif}
void ByteStreamFileSource::doReadFromFile() {  // Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)  if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {    fMaxSize = (unsigned)fNumBytesToStream;  }  if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {    fMaxSize = fPreferredFrameSize;  }#ifdef READ_FROM_FILES_SYNCHRONOUSLY  fFrameSize = fread(fTo, 1, fMaxSize, fFid);#else  if (fFidIsSeekable) {    fFrameSize = fread(fTo, 1, fMaxSize, fFid);  } else {    // For non-seekable files (e.g., pipes), call "read()" rather than "fread()", to ensure that the read doesn't block:    fFrameSize = read(fileno(fFid), fTo, fMaxSize);  }#endif  if (fFrameSize == 0) {    handleClosure();    return;  }  fNumBytesToStream -= fFrameSize;  // Set the 'presentation time':  if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) {    if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {      // This is the first frame, so use the current time:      gettimeofday(&fPresentationTime, NULL);    } else {      // Increment by the play time of the previous data:      unsigned uSeconds= fPresentationTime.tv_usec + fLastPlayTime;      fPresentationTime.tv_sec += uSeconds/1000000;      fPresentationTime.tv_usec = uSeconds%1000000;    }    // Remember the play time of this data:    fLastPlayTime = (fPlayTimePerFrame*fFrameSize)/fPreferredFrameSize;    fDurationInMicroseconds = fLastPlayTime;  } else {    // We don't know a specific play time duration for this data,    // so just record the current time as being the 'presentation time':    gettimeofday(&fPresentationTime, NULL);  }  // Inform the reader that he has data:#ifdef READ_FROM_FILES_SYNCHRONOUSLY  // To avoid possible infinite recursion, we need to return to the event loop to do this:  nextTask() = envir().taskScheduler().scheduleDelayedTask(0,(TaskFunc*)FramedSource::afterGetting, this);#else  // Because the file read was done from the event loop, we can call the  // 'after getting' function directly, without risk of infinite recursion:  FramedSource::afterGetting(this);#endif}

在以上函数中关于几个重要参数主要是通过这里传送的nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
(TaskFunc*)FramedSource::afterGetting, this);

FramedSource::afterGetting 再回到FramedSource中,发现afterGetting是个静态函数,所以在这里可以直接的调用,FramedSource中定义如下

void FramedSource::afterGetting(FramedSource* source) {  source->fIsCurrentlyAwaitingData = False;      // indicates that we can be read again      // Note that this needs to be done here, in case the "fAfterFunc"      // called below tries to read another frame (which it usually will)  if (source->fAfterGettingFunc != NULL) {    (*(source->fAfterGettingFunc))(source->fAfterGettingClientData,   source->fFrameSize, source->fNumTruncatedBytes,   source->fPresentationTime,   source->fDurationInMicroseconds);  }}

由上可见,afterGetting实际上就是把getNextFrame和doGetNextFrame();中初始化或者改变的参数包装了一下,用nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
(TaskFunc*)FramedSource::afterGetting, this);传递下去

关于参数还有一个叫fFrameSize的,此参数代表实际读取的字节数,肯定这个数值要小于fMaxSize





  





1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 冒险岛遇见超能力者全屏挂机怎么办 当危险来临时该怎么办作文400字 生气把孩子手掌内侧打肿了怎么办 驾驶证未满一年扣12分怎么办 在高速上超速百分之10以下怎么办 中兴手机重启死机开不了机怎么办 太胖了太自卑了该怎么办 儿子因为长的胖特别自卑怎么办? 苹果ld叫我检查身份信息怎么办 我家墙让对面给漂水了怎么办 如果你流落到荒岛上你会怎么办 手机迅雷下载版权方不给下载怎么办 白色有彩色花纹的衣服染色了怎么办 载兰花假如下雪和打霜怎么办 皇室战争你的队友离开了对战怎么办 海岛奇兵发现求救信号第三个怎么办 海岛奇兵勋章太多对手太强怎么办 鱼为什么换缸鱼翅黑了怎么办 鱼丸捕鱼大作战换手机了怎么办 2o岁j'j小怎么办 为什么小米5s指纹不能用怎么办 cs录屏软件运行内存太大了怎么办 可是没有他我怎么办啊是什么电视剧 可是没有他我怎么办啊是哪个电视剧 手机太卡了打字打不了了怎么办 梦幻西游的将军令没有电了怎么办 将军令全部的序列号都忘记了怎么办 船员证被公司压着想自己换证怎么办 电子录入系统中无法打开影像怎么办 火车票退票后说银行退款失败怎么办 苹果4s玩游戏闪退怎么办 买了二手房原房主不迁户口怎么办 苹果禁反忘记工id密码了怎么办 玩英雄联盟用腾讯游戏平台卡怎么办 游戏代练接单了没有给我账号怎么办 华为手机进入设置立即闪退怎么办 股东发现公司有做假账现象怎么办 中国在服役期间有纹身被发现怎么办 脚碰了肿了紫了怎么办 外阴出血了怎么办去医院检查没问题 三个半月宝宝体检脚有的紧怎么办