live555-让你的h264文件支持seek

来源:互联网 发布:网页淘宝分享到微信 编辑:程序博客网 时间:2024/06/16 12:58

1 live555 当前对trick play mode 支持的说明:

'Trick play' functionality

The server supports RTSP 'trick play' operations for some, but not all, media types:
  • Pausing: All media types
  • Seeking: MPEG Transport Streams; DV video; WAV (PCM) audio; MPEG-1 or 2 audio; MPEG-1 or 2 Program Streams (partially working); Matroska orWebM files
  • Fast forward: MPEG Transport Streams; WAV (PCM) audio; MPEG-1 or 2 audio
  • Reverse play: MPEG Transport Streams; WAV (PCM) audio
Note that in order to provide 'trick play' operations for a streamed MPEG Transport Stream file, a special 'index file' must created for each such file, using our "MPEG2TransportStreamIndexer" tool.

没有看到h264支持。

2 live555有对如何支持trick play也有说明:

To add 'trick play' support for a media type (that does not already support it), changes need to be made to the corresponding subclass of "ServerMediaSubsession":

  1. To add support for seeking within a stream, you will need to implement the following virtual functions:
    • virtual float duration() const;
      Returns the file's duration, in seconds
    • virtual void seekStreamSource(FramedSource* inputSource, double& seekNPT, double streamDuration, u_int64_t& numBytes);
      (Attempts to) seek within the input source.
  2. To add support for 'fast forward' and/or 'reverse play', you will also need to implement the following virtual functions:
    • virtual void testScaleFactor(float& scale);
      Inspects the input value of "scale", and, if necessary, changes it to a nearby value that we support. (E.g., if the input value of "scale" is 3.3, you might change it to 3 (an integer).) If there's no 'nearby' value that you support, just set "scale" to 1 (the default value).
    • virtual void setStreamSourceScale(FramedSource* inputSource, float scale);
      Actually sets the scale factor for a specific input source. (The value of "scale" will previously have been passed in and out of "testScaleFactor()", so we know that it is a value that we support.)
3 支持seek相对简单,这里举例说明如何支持h264文件点播的seek:
class MxH264VideoFileServerMediaSubsession:public H264VideoFileServerMediaSubsession{public:static MxH264VideoFileServerMediaSubsession*MxH264VideoFileServerMediaSubsession::createNew(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource);protected:MxH264VideoFileServerMediaSubsession(UsageEnvironment& env,char const* fileName, Boolean reuseFirstSource);// called only by createNew();virtual ~MxH264VideoFileServerMediaSubsession();virtual float duration() const;virtual void seekStreamSource(FramedSource* inputSource, double& seekNPT, double streamDuration, u_int64_t& numBytes);u_int64_t findSeekPosition(u_int64_t iSeek);protected:float fDuration;};MxH264VideoFileServerMediaSubsession* MxH264VideoFileServerMediaSubsession::createNew(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource){return new MxH264VideoFileServerMediaSubsession(env,fileName,reuseFirstSource);}MxH264VideoFileServerMediaSubsession::MxH264VideoFileServerMediaSubsession(UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource):H264VideoFileServerMediaSubsession(env,fileName,reuseFirstSource),fDuration(1800.0){}MxH264VideoFileServerMediaSubsession::~MxH264VideoFileServerMediaSubsession(){}float MxH264VideoFileServerMediaSubsession::duration() const{return fDuration;}u_int64_t MxH264VideoFileServerMediaSubsession::findSeekPosition(u_int64_t iPos){FILE* hFile = fopen(fFileName,"rb");if (!hFile)return 0;fseek(hFile,iPos,SEEK_SET);string strBuf;char buffer[5000];int curPos ;do{curPos = ftell(hFile);curPos =curPos - strBuf.size();int iSize = fread(buffer,1,5000,hFile);if (iSize > 0){strBuf.append(buffer,iSize);}else{break;}int i = 0;for (;i <= (strBuf.size() - 5); i++){if (strBuf[i] == 0x00 &&strBuf[i+1] == 0x00 &&strBuf[i+2] == 0x00 &&strBuf[i+3] == 0x01 &&strBuf[i+4] == 0x67 ){//printf("the h264 config position is %X\r\n",curPos + i);return curPos + i;}}if (i <= strBuf.size()){strBuf = strBuf.substr(i);}} while (1);return 0;}void MxH264VideoFileServerMediaSubsession::seekStreamSource(FramedSource* inputSource, double& seekNPT, double streamDuration, u_int64_t& numBytes){if (seekNPT > fDuration)return ;if (seekNPT < 1.0){ByteStreamFileSource* pFileSource = (ByteStreamFileSource*)(((FramedFilter*)inputSource)->inputSource());pFileSource->seekToByteAbsolute(0);seekNPT = 0.0;return;}u_int64_t pos = fFileSize * seekNPT / fDuration;u_int64_t seekPos = findSeekPosition(pos);ByteStreamFileSource* pFileSource = NULL;pFileSource = (ByteStreamFileSource*)(((FramedFilter*)inputSource)->inputSource());pFileSource->seekToByteAbsolute(seekPos);seekNPT = fDuration * seekPos / fFileSize;}


0 0