📄 zzlfilereader.cpp
字号:
#include "stdafx.h"
#include "ZZLFileReader.h"
#ifndef SAFE_ARRAYDELETE
#define SAFE_ARRAYDELETE( x ) \
if( NULL != x ) \
{ \
delete [] x; \
x = NULL; \
}
#endif
ZZLFileReader::ZZLFileReader() :
FILE_VERSION(1.0f),
MAX_HEADER_SIZE(1024),
LIMIT_DOWN_SPEED(150.0f),
m_VideoEndTime(0),
m_AudioEndTime(0)
{
m_hFile = INVALID_HANDLE_VALUE;
m_iHeaderSize = 0;
m_iFileSize = 0;
m_iDownloadedSize = 0;
//
m_pAudioFormat = NULL;
m_pVideoFormat = NULL;
m_startTime = 0;
m_endTime = 0;
A_currBlockID = 0;
V_currBlockID = 0;
m_hDownThread = NULL;
m_isStopped = FALSE;
//
A_iLeftDataInCurrBlock = 0;
V_iLeftDataInCurrBlock = 0;
}
ZZLFileReader::~ZZLFileReader(void)
{
m_iHeaderSize = 0;
m_isStopped = TRUE; // stop thread
if (INVALID_HANDLE_VALUE != m_hFile )
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
//
//
SAFE_ARRAYDELETE(m_pAudioFormat);
SAFE_ARRAYDELETE(m_pVideoFormat);
}
bool ZZLFileReader::Init(const char* filename)
{
CAutoLock l(&m_pLock);
//
if(!filename)
{
ASSERT(FALSE);
return false;
}
//
if(m_hFile != INVALID_HANDLE_VALUE)
return true;
// 打开文件句柄
m_hFile = CreateFile(filename, GENERIC_READ,
FILE_SHARE_READ, NULL,
OPEN_EXISTING, // 本地文件
FILE_ATTRIBUTE_NORMAL, NULL);
//
if(m_hFile == INVALID_HANDLE_VALUE)
{
int xxx = GetLastError();
return false;
}
m_iFileSize = GetFileSize(m_hFile, NULL);
m_iDownloadedSize = m_iFileSize; // 本地文件!当然数据是全的
// 本地文件,直接读取文件头
if(!ReadFileHeader())
{
ASSERT(FALSE);
return false;
}
//
return true;
}
void __stdcall ZZLFileReader::RunHttpDownload(ZZLFileReader* reader)
{
return;
}
bool ZZLFileReader::ReadFileHeader()
{
CAutoLock l(&m_pLock);
if(m_iDownloadedSize < MAX_HEADER_SIZE)
{
return false;
}
//
if(IsInited())
{
return true;
}
//
DWORD readBytes = 0;
float version;
// 1. check "ZZLD"
char fcc[5] = "";
fcc[4] = 0;
//
if(INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile, 0, 0, FILE_BEGIN))
{
return false;
}
//
if(!ReadFile(m_hFile, fcc, 4, &readBytes, NULL))
{
return false;
}
//
if(readBytes != 4 || stricmp(fcc, "ZZLD") != 0)
{
return false;
}
// 2. check file version
if(!ReadFile(m_hFile, &version, sizeof(version), &readBytes, NULL))
{
return false;
}
//
if(readBytes != sizeof(version) || version > FILE_VERSION)
{
return false;
}
// 3. read video type
if(!ReadFile(m_hFile, &m_VideoType, sizeof(m_VideoType), &readBytes, NULL))
{
return false;
}
//
if(readBytes != sizeof(m_VideoType) && m_VideoType.cbFormat > 1024)
{
return false;
}
//
SAFE_ARRAYDELETE(m_pVideoFormat);
//
m_pVideoFormat = new BYTE[m_VideoType.cbFormat];
//
if(!ReadFile(m_hFile, m_pVideoFormat, m_VideoType.cbFormat, &readBytes, NULL))
{
return false;
}
//
if(readBytes != m_VideoType.cbFormat)
{
return false;
}
// 4. read audio type
if(!ReadFile(m_hFile, &m_AudioType, sizeof(m_AudioType), &readBytes, NULL))
{
return false;
}
//
if(readBytes != sizeof(m_AudioType) && m_AudioType.cbFormat > 1024)
{
return false;
}
//
SAFE_ARRAYDELETE(m_pAudioFormat);
//
m_pAudioFormat = new BYTE[m_AudioType.cbFormat];
//
if(!ReadFile(m_hFile, m_pAudioFormat, m_AudioType.cbFormat, &readBytes, NULL))
{
return false;
}
//
if(readBytes != m_AudioType.cbFormat)
{
return false;
}
// 5. read start time, end time
time_t temp = 0;
if(!ReadFile(m_hFile, &temp, sizeof(temp), &readBytes, NULL))
{
return false;
}
//
if(readBytes != sizeof(temp))
{
return false;
}
//
m_startTime = temp;
m_startTime *= 10000000;
if(!ReadFile(m_hFile, &temp, sizeof(temp), &readBytes, NULL))
{
return false;
}
//
if(readBytes != sizeof(temp))
{
return false;
}
//
m_endTime = temp;
m_endTime *= 10000000;
//
if(m_endTime < m_startTime || m_endTime == 0)
{
return false;
}
m_iHeaderSize = 4 + sizeof(version) + sizeof(m_AudioType) +
m_AudioType.cbFormat + sizeof(m_VideoType) +
m_VideoType.cbFormat +
sizeof(temp) +
sizeof(temp);
//
//m_pFilter->SetBaseRef(m_startTime);
//
return true;
}
// 获取媒体类型
int ZZLFileReader::GetMediaType(TVMEDIATYPESECTION& mediatype, BOOL isAudio)
{
CAutoLock l(&m_pLock);
//
if(!IsInited())
{
if(!ReadFileHeader())
{
return FALSE;
}
}
//
if(isAudio)
{
if(!m_pAudioFormat)
{
return FALSE;
}
//
mediatype = m_AudioType;
}
else
{
if(!m_pVideoFormat)
{
return FALSE;
}
//
mediatype = m_VideoType;
}
//
return TRUE;
}
// 获取媒体数据
int ZZLFileReader::GetMediaData(PBYTE data, BOOL isAudio)
{
CAutoLock l(&m_pLock);
//
if(!data)
{
ASSERT(NULL != data);
return FALSE;
}
//
if(!IsInited())
{
if(!ReadFileHeader())
{
ASSERT(FALSE);
return FALSE;
}
}
//
if(isAudio)
{
if(!m_pAudioFormat)
{
ASSERT(NULL != m_pAudioFormat);
return FALSE;
}
//
memcpy(data, m_pAudioFormat, m_AudioType.cbFormat);
}
else
{
if(!m_pVideoFormat)
{
return FALSE;
}
//
memcpy(data, m_pVideoFormat, m_VideoType.cbFormat);
}
//
return TRUE;
}
STDMETHODIMP ZZLFileReader::GetAvailable(LONGLONG& pEarliest,LONGLONG& pLatest)
{
CAutoLock l(&m_pLock);
//
if(!IsInited())
{
if(!ReadFileHeader())
{
ASSERT(FALSE);
return S_FALSE;
}
}
//
pEarliest = 0;
pLatest = m_endTime - m_startTime;
//
return S_OK;
}
STDMETHODIMP ZZLFileReader::GetDuration(LONGLONG& pDuration)
{
CAutoLock l(&m_pLock);
//
if(!IsInited())
{
if(!ReadFileHeader())
{
ASSERT(FALSE);
return S_FALSE;
}
}
//
pDuration = m_endTime - m_startTime;
//
return S_OK;
}
//
STDMETHODIMP ZZLFileReader::GetStopPosition(LONGLONG& pStop)
{
CAutoLock l(&m_pLock);
//
if(!IsInited())
{
if(!ReadFileHeader())
{
ASSERT(FALSE);
return S_FALSE;
}
}
//
pStop = m_endTime-m_startTime;
return S_OK;
}
// Seek到某个时间
bool ZZLFileReader::SeekTo(LONGLONG& seekTime, int pin)
{
CAutoLock l(&m_pLock);
if(!IsInited())
{
if(!ReadFileHeader())
{
ASSERT(FALSE);
return false;
}
}
//
if(seekTime > m_endTime)
{
seekTime = m_endTime;
}
//
if(seekTime <= m_startTime)
{
seekTime = m_startTime;
}
// TODO: 使用二分查找
UINT targetBlockID = (UINT)(((double)(seekTime - m_startTime)/(m_endTime - m_startTime)*(m_iFileSize-m_iHeaderSize))/BLOCK_SIZE);
//
if((pin & 1) == 1)
{
A_currBlockID = targetBlockID;
A_iLeftDataInCurrBlock = 0;
}
if((pin & 2) == 2)
{
V_currBlockID = targetBlockID;
V_iLeftDataInCurrBlock = 0;
}
//
//
return true;
}
bool ZZLFileReader::SeekVideoTo(LONGLONG& seekTime)
{
return SeekTo(seekTime, 2);
}
bool ZZLFileReader::SeekAudioTo(LONGLONG& seekTime)
{
return SeekTo(seekTime, 1);
}
// 获取Sample.
// m_startTime != _I64_MAX的话,寻找m_startTime之后的第一个Sample,
// 视频Sample的话还要满足是关键帧的条件
P2P_RETURN_TYPE ZZLFileReader::GetSample(SampleHeader& header, // Sample头
PBYTE& pData, // Sample数据
const UINT maxSize, // Sample的最大值
LONGLONG seekTime) // Seek的目标时间
{
CAutoLock l(&m_pLock);
if(!IsInited())
{
if(!ReadFileHeader())
return PRT_NOT_INIT;
}
//
if(seekTime != _I64_MAX)
{
SeekTo(seekTime);
}
//
bool isAudio = header.bAudioSample;
for(;;)
{
for(;;)
{
P2P_RETURN_TYPE ret = LoadSample(header, pData, 0, maxSize, isAudio);
if(ret < PRT_OK)
return ret;
// 节目开始的标志Sample,在ZZL文件中略过,不用处理
if(header.length == 0xffffffff || header.start == 0xffffffffffffffff)
continue;
//
//if (header.start < m_startTime)
// continue;
// 如果是目标类型,则完成寻找
if(isAudio == header.bAudioSample)
{
if (seekTime != _I64_MAX) //seeking
{
// Seek时,获取视频关键帧
if(!isAudio && header.bSyncPoint)
{
m_llSeekTo = header.start;
break;
}
}else
{
break;
}
}
}
if (header.start >= m_llSeekTo)
{
break;
}
}
//
//header.start -= m_startTime;//m_llSeekTo;
if(header.start != -1)
{
LONGLONG tmp = header.start + header.length;
if(isAudio)
{
if(tmp > m_AudioEndTime)
m_AudioEndTime = tmp;
}
else
{
if(tmp > m_VideoEndTime)
m_VideoEndTime = tmp;
}
}
DbgLog((LOG_TRACE, 1, TEXT("Deliver sample, baudio is %d, start at %I64d, length is %d, size is %d"), header.bAudioSample,
header.start, header.length, header.size));
//
return PRT_OK;
}
//
P2P_RETURN_TYPE ZZLFileReader::LoadSample(SampleHeader& header, // Sample头
PBYTE& sampleData, // Sample数据
UINT sampleOff, // 已经读取的长度
const UINT maxSize, // Sample最大长度
const bool isAudio) // 视频还是音频
{
UINT& currBlockID = isAudio ? A_currBlockID : V_currBlockID;
BYTE *currBlock = isAudio ? A_currBlock : V_currBlock;
//
UINT& leftDataInCurrBlock = isAudio ? A_iLeftDataInCurrBlock : V_iLeftDataInCurrBlock;
DWORD readBytes = 0;
//
UINT iCurrentPos = m_iHeaderSize + currBlockID*BLOCK_SIZE;
//
while(0 == leftDataInCurrBlock)
{ // not data in current block, load next
// 读取当前块数据
if(iCurrentPos == m_iFileSize) //文件已经读到头了
{
return PRT_ENDOFFILE;
}
if(INVALID_SET_FILE_POINTER == SetFilePointer(m_hFile, iCurrentPos, NULL, FILE_BEGIN))
{
ASSERT(FALSE);
return PRT_SYS;
}
if(iCurrentPos + BLOCK_SIZE > m_iFileSize)
{
//ASSERT(FALSE);
return PRT_SYS; // 超出了文件大小,不正常
}
//
if(iCurrentPos + BLOCK_SIZE > m_iDownloadedSize)
{
ASSERT(FALSE);
return PRT_BLOCK_NOTFOUND; // 尚未下载到这里呢
}
//
if(!ReadFile(m_hFile, currBlock, BLOCK_SIZE, &readBytes, NULL))
{
ASSERT(FALSE);
return PRT_SYS;
}
//
currBlockID++;
//
// 第4~8个字节是first sample offset
UINT sampleOffset = *((UINT*)currBlock+1);
// 注意:8是keySampleOffset和sampleOffset占用的空间大小
if(sampleOffset != UINT_MAX &&
(sampleOffset < 8 || sampleOffset > BLOCK_SIZE))
{
assert(0);
continue; // 错误的SampleOffset,抛弃当前块
}
// 由于CaptureServer的一个BUG,这里作一个修正,随着所有CaptureServer的更新,这里可以去除。 2005.04.18
if(sampleOffset == BLOCK_SIZE)
{
sampleOffset = UINT_MAX;
}
//
if(sampleOff == 0)
{ // 开始读取新的Sample
if(sampleOffset == UINT_MAX)
{
iCurrentPos += BLOCK_SIZE;
continue; // 新的Sample不在当前Block中,继续寻找下一个
}
else
{
leftDataInCurrBlock = BLOCK_SIZE-sampleOffset; // 新的Sample位置
}
}
else
{
// 继续读取剩余的数据
leftDataInCurrBlock = BLOCK_SIZE-8;
assert(sampleOffset==UINT_MAX || sampleOff < sizeof(SampleHeader) || sampleOffset == 8+header.size-sampleOff);
}
//
assert(leftDataInCurrBlock <= BLOCK_SIZE);
break;
}
//
BYTE* startOff = currBlock + (BLOCK_SIZE - leftDataInCurrBlock);
// 尝试读取SampleHeader,直到读取了sizeof(SampleHeader)个字节,即dataOff == sizeof(SampleHeader)
if(sampleOff < sizeof(SampleHeader))
{
if(leftDataInCurrBlock < sizeof(SampleHeader)-sampleOff)
{
// 数据仍然不足sizeof(SampleHeader),继续读取下一个块
memcpy((BYTE*)&header + sampleOff, startOff, leftDataInCurrBlock);
sampleOff += leftDataInCurrBlock;
leftDataInCurrBlock = 0;
//
return LoadSample(header, sampleData, sampleOff, maxSize, isAudio);
}else
{
// 数据已经足够,读取完整的sample header
memcpy((BYTE*)&header + sampleOff, startOff, sizeof(SampleHeader)-sampleOff);
assert(header.size >= sizeof(SampleHeader) && header.size <= maxSize);
//
if(header.size < sizeof(SampleHeader) || header.size > maxSize)
{
// 错误的Header,抛弃当前块,重新读取新的Sample
sampleOff = 0;
leftDataInCurrBlock = 0;
return LoadSample(header, sampleData, sampleOff, maxSize, isAudio);
}
//
leftDataInCurrBlock -= (sizeof(SampleHeader)-sampleOff);
sampleOff = sizeof(SampleHeader);
}
}
startOff = currBlock+(BLOCK_SIZE - leftDataInCurrBlock);
// 读取SampleHeader之外的数据
if(sampleOff >= sizeof(SampleHeader))
{
if(leftDataInCurrBlock < header.size-sampleOff)
{
// 当前块中剩下的数据不足,继续读取下一块
memcpy(sampleData+sampleOff-sizeof(SampleHeader), startOff, leftDataInCurrBlock);
sampleOff += leftDataInCurrBlock;
leftDataInCurrBlock = 0;
return LoadSample(header, sampleData, sampleOff, maxSize, isAudio);
}else
{
// 读取到完整的Sample
memcpy(sampleData+sampleOff-sizeof(SampleHeader), startOff, header.size-sampleOff);
leftDataInCurrBlock -= (header.size-sampleOff);
}
}
//
assert(leftDataInCurrBlock <= BLOCK_SIZE);
return PRT_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -