live555-让你的h264文件支持seek

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;

}


你可能感兴趣的:(C/C++,development)