前一篇文章对mpg文件处理的分析中,有个一个比较严重的错误,因为有些重要的细节没有注意到。mpg文件是音视频交错排列的,如果需要读取的是视频数据,但当前文件位置却是音频数据该怎么办?前面分析时说,将把遇到的音频数据保存到缓存中,直到读取到视频数据,live555中并非如此处理的。
先简单的说明一下mpg处理过程涉及的几个类的作用
MPEG1or2Demux, 对应一个session,完成文件的解复用操作。其读取文件的过程是通过ByteStreamFileSource实现的
MPEG1or2DemuxedElementaryStream,作为source,对应一个流,一个或多个实例对应一个MPEG1or2Demux
MPEG1or2DemuxedServerMediaSubsession,作为subsession
MPEG1or2FileServerDemux, 一个服务类,整个程序只有一个实例,MPEG1or2Demux、MPEG1or2DemuxedElementaryStream、MPEG1or2DemuxedServerMediaSubsession三个类将通过本类进行联系。完成的工作如下:
1)创建subsession实例(MPEG1or2DemuxedServerMediaSubsession);
2)为每一个session创建MPEG1or2Demux实例,用于解复用。
3)创建source实例(MPEG1or2DemuxedElementaryStream), subsession中
再来看一个重要的结构体OutputDescriptor,它被定义在MPEG1or2Demux类中,文件中的每一个流对应一个OutputDescriptor实例
需要注意以下3个成员:
isPotentiallyReadable,对应的流存在,即存在对应流的MPEG1or2DemuxedElementaryStream实例
isCurrentlyActive,对应的流是活动的,当从第一次从这个流中读取数据时就置为True, 停止读取后置为False
isCurrentlyAwaitingData,当前正需要从对应的流中读取数据。从文件中读取数据并分析后,通过此标志判断读取到的数据是否是当前需要的流数据,如果不是则需要数据存在到缓存中
我们来看MPEG1or2Demux::getNextFrame函数
先简单的说明一下mpg处理过程涉及的几个类的作用
MPEG1or2Demux, 对应一个session,完成文件的解复用操作。其读取文件的过程是通过ByteStreamFileSource实现的
MPEG1or2DemuxedElementaryStream,作为source,对应一个流,一个或多个实例对应一个MPEG1or2Demux
MPEG1or2DemuxedServerMediaSubsession,作为subsession
MPEG1or2FileServerDemux, 一个服务类,整个程序只有一个实例,MPEG1or2Demux、MPEG1or2DemuxedElementaryStream、MPEG1or2DemuxedServerMediaSubsession三个类将通过本类进行联系。完成的工作如下:
1)创建subsession实例(MPEG1or2DemuxedServerMediaSubsession);
2)为每一个session创建MPEG1or2Demux实例,用于解复用。
3)创建source实例(MPEG1or2DemuxedElementaryStream), subsession中
再来看一个重要的结构体OutputDescriptor,它被定义在MPEG1or2Demux类中,文件中的每一个流对应一个OutputDescriptor实例
// A descriptor for each possible stream id tag:
typedef struct OutputDescriptor {
// input parameters
unsigned char* to; unsigned maxSize;
FramedSource::afterGettingFunc* fAfterGettingFunc;
void* afterGettingClientData;
FramedSource::onCloseFunc* fOnCloseFunc;
void* onCloseClientData;
// output parameters
unsigned frameSize; struct timeval presentationTime;
class SavedData; // forward
SavedData* savedDataHead;
SavedData* savedDataTail;
unsigned savedDataTotalSize;
// status parameters
Boolean isPotentiallyReadable;
Boolean isCurrentlyActive;
Boolean isCurrentlyAwaitingData;
} OutputDescriptor_t;
OutputDescriptor_t fOutput[256];
需要注意以下3个成员:
isPotentiallyReadable,对应的流存在,即存在对应流的MPEG1or2DemuxedElementaryStream实例
isCurrentlyActive,对应的流是活动的,当从第一次从这个流中读取数据时就置为True, 停止读取后置为False
isCurrentlyAwaitingData,当前正需要从对应的流中读取数据。从文件中读取数据并分析后,通过此标志判断读取到的数据是否是当前需要的流数据,如果不是则需要数据存在到缓存中
我们来看MPEG1or2Demux::getNextFrame函数
void MPEG1or2Demux::getNextFrame(u_int8_t streamIdTag,
unsigned char* to, unsigned maxSize,
FramedSource::afterGettingFunc* afterGettingFunc,
void* afterGettingClie