ZZLFileReader.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:13k
源码类别:
P2P编程
开发平台:
Visual C++
- #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;
- }