📄 zzlfilewriter.cpp
字号:
memcpy(newBlock+newBlockSize, sampleBuffer+dataOff, allSize-dataOff);
newBlockSize += allSize-dataOff;
}
return true;
}
bool ZZLFileWriter::PutSample(const SampleHeader& header, BYTE* pData) {
if(header.size > 1024*1024)
return false;
bool ret = true;
EnterCriticalSection(&zzlfile_cs);
char tmpStr[96];
_i64toa(header.start, tmpStr, 10);
_i64toa(header.length+header.start, tmpStr+32, 10);
DbgLog((LOG_TRACE, 5, TEXT("start: %s end: %s"), tmpStr, tmpStr+32));
// record first sample time
if(firstSampleTime == 0)
firstSampleTime = (time_t)(header.start/10000000);
// record first keysample time
//区分单音频和视频的情况
if (firstKeySampleTime == 0 && TRUE == mbIsSingleAudio && header.start != 0xffffffffffffffff/*非节目起始标志Sample*/)
{
firstKeySampleTime = (time_t)(header.start/10000000);
}
else if(firstKeySampleTime == 0 && header.bSyncPoint && header.start != 0xffffffffffffffff/*非节目起始标志Sample*/)
{
firstKeySampleTime = (time_t)(header.start/10000000);
}
if(header.size > sampleBufferSize) {
SAFE_ARRAYDELETE(sampleBuffer);
sampleBuffer = new BYTE[header.size];
sampleBufferSize = header.size;
}
// copy sample header into sample buffer
memcpy(sampleBuffer, &header, sizeof(SampleHeader));
// copy sample data into sample buffer;
if(header.size-sizeof(SampleHeader)) {
assert(pData);
memcpy(sampleBuffer+sizeof(SampleHeader), pData, header.size-sizeof(SampleHeader));
}
#ifndef GENERATE_SMALL_ZZL
if(header.start > 0 && header.start != 0xffffffffffffffff/*非节目起始标志Sample*/) {
if(header.bAudioSample) {
//检查音频时间是否回滚
if (header.start > mLLMaxAudioTime)
{
mLLMaxAudioTime = header.start;
}
else
{
//char lstr[1024];
//sprintf(lstr, "这段音频的数据应该已经播放过了,不能进行直播%I64D",header.start);
MessageBox(NULL,"这段音频的数据应该已经播放过了,不能进行直播", "错误", MB_OK|MB_ICONSTOP);
return FALSE;
}
// calculate total size of audio samples
audioDataSize += header.size;
// set start&end time of audio samples
if(header.start > audioEndTime || header.start < audioStartTime) {
if(audioStartTime == 0 || header.start < audioStartTime) {
audioStartTime = header.start;
}
if(header.start+header.length > audioEndTime)
audioEndTime = header.start+header.length;
}
assert(audioStartTime <= header.start);
}
else {
//检查视频时间是否回滚
if (header.start > mLLMaxVideoTime)
{
mLLMaxVideoTime = header.start;
}
else
{
MessageBox(NULL,"这段视频的数据应该已经播放过了,不能进行直播", "错误", MB_OK|MB_ICONSTOP);
return FALSE;
}
// calculate total size of video samples
videoDataSize += header.size;
// set start&end time of video samples
if(header.start > videoEndTime || header.start < videoStartTime) {
if(videoStartTime == 0 || header.start < videoStartTime) {
videoStartTime = header.start;
}
if(header.start+header.length > videoEndTime)
videoEndTime = header.start+header.length;
}
assert(videoStartTime <= header.start);
// 检查video sample和audio sample是否时间相差过多,相差过多的节目不适合进行直播!
if(videoEndTime > 0 && audioEndTime > 0)
{
if(videoEndTime > audioEndTime+10*10000000
|| audioEndTime > videoEndTime+10*10000000)
{
::MessageBox(NULL,
"现在视频和音频已经不同步,相差超过10s,这样压缩出来的节目是不能进行直播的!",
"错误", MB_OK|MB_ICONSTOP);
ret = false;
}
}
}
}
#endif
if(ret)
ret = SaveSample(0, header.size);
LeaveCriticalSection(&zzlfile_cs);
return ret;
}
bool ZZLFileWriter::SaveBlock(const PBYTE data, const UINT size) {
if(zzlHandle == INVALID_HANDLE_VALUE)
return false;
DWORD writenBytes = 0;
if(INVALID_SET_FILE_POINTER == SetFilePointer(zzlHandle, dataOffset + blockCount*BLOCK_SIZE, 0, FILE_BEGIN))
return false;
if(!WriteFile(zzlHandle, data, size, &writenBytes, NULL))
return false;
if(writenBytes != size)
return false;
// write min&max keySample to zzl file
if(firstSampleTime > 0) {
if(firstSampleTime > endTime || firstSampleTime < startTime) {
if(startTime == 0 || firstSampleTime < startTime) {
startTime = firstSampleTime;
}
if(firstSampleTime > endTime)
endTime = firstSampleTime;
if(INVALID_SET_FILE_POINTER == SetFilePointer(zzlHandle, dataOffset-sizeof(startTime)-sizeof(endTime), 0, FILE_BEGIN))
return false;
// write start & end Time
if(!WriteFile(zzlHandle, &startTime, sizeof(startTime), &writenBytes, NULL))
return false;
if(writenBytes != sizeof(startTime))
return false;
if(!WriteFile(zzlHandle, &endTime, sizeof(endTime), &writenBytes, NULL))
return false;
if(writenBytes != sizeof(endTime))
return false;
}
assert(startTime <= firstSampleTime);
}
if(firstKeySampleTime > 0) {
// write keysample to keysample file
if(INVALID_SET_FILE_POINTER == SetFilePointer(keySampleHandle, 0, 0, FILE_END)) // seek to end of file
return false;
// write blockID
if(!WriteFile(keySampleHandle, &blockCount, sizeof(blockCount), &writenBytes, NULL))
return false;
if(writenBytes != sizeof(blockCount))
return false;
// write keysample
if(!WriteFile(keySampleHandle, &firstKeySampleTime, sizeof(firstKeySampleTime), &writenBytes, NULL))
return false;
if(writenBytes != sizeof(firstKeySampleTime))
return false;
}
// write block data to data file
if(blockCount/BLOCK_OF_DATA_FILE > dataFileCount) {
dataFileCount = blockCount/BLOCK_OF_DATA_FILE;
CloseHandle(dataHandle);
char temp[16];
itoa(dataFileCount, temp, 10);
dataHandle = CreateFile((savePath+"\\"+temp).data(),
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(dataHandle == INVALID_HANDLE_VALUE)
return false;
}
if(INVALID_SET_FILE_POINTER == SetFilePointer(dataHandle, (blockCount%BLOCK_OF_DATA_FILE)*BLOCK_SIZE, 0, FILE_BEGIN))
return false;
if(!WriteFile(dataHandle, data, size, &writenBytes, NULL))
return false;
if(writenBytes != size)
return false;
firstKeySampleTime = 0;
firstSampleTime = 0;
blockCount++;
// 将最新的码率统计写入配置文件
if(!SaveBitRate())
return false;
return true;
}
double ZZLFileWriter::GetBitRate() {
// 根据起始Sample和最近一个Sample的时间戳以及数据的大小,分别计算视频音频的码率,然后加起来就是总的码率
double bitRate = 0.0f;
if(videoEndTime-videoStartTime > 0)
bitRate += ((double)videoDataSize)/1024/((videoEndTime-videoStartTime)/10000000);
if(audioEndTime-audioStartTime > 0)
bitRate += ((double)audioDataSize)/1024/((audioEndTime-audioStartTime)/10000000);
return bitRate;
}
//设置是否是单音频
void ZZLFileWriter::SetIsSingleAudio(BOOL abAudio)
{
mbIsSingleAudio = abAudio;
}
bool ZZLFileWriter::SaveBitRate() {
if(configHandle == INVALID_HANDLE_VALUE)
return false;
DWORD writenBytes = 0;
char temp[64];
if(INVALID_SET_FILE_POINTER == SetFilePointer(configHandle, 0, 0, FILE_BEGIN))
return false;
sprintf(temp, "BitRate=%.4f", GetBitRate());
// 注意:配置文件中所留的空间是“BitRate=000000000”,所以要防止超过这个长度
temp[strlen("BitRate=000000000")-1] = 0;
// 检查一下,某些情况下,最后码率是0,很奇怪
if(blockCount > 20) {
assert(strcmp(temp, "BitRate=000000000") != 0);
}
if(!WriteFile(configHandle, temp, strlen(temp), &writenBytes, NULL))
return false;
if(writenBytes != strlen(temp))
return false;
return true;
}
bool ZZLFileWriter::RemoveOldTmpFile(string path) {
WIN32_FIND_DATA fileData;
string match = path;
match.append("\\*");
HANDLE hFind = FindFirstFile(match.data(), &fileData);
if(hFind == INVALID_HANDLE_VALUE)
return true;
bool firstDeleteFile = true;
while(1) {
bool shouldDelete = false;
if(stricmp(fileData.cFileName, "config") == 0) // 配置文件
shouldDelete = true;
else if(stricmp(fileData.cFileName, "keysample") == 0) // 关键帧文件
shouldDelete = true;
else if(stricmp(fileData.cFileName, (chnlName+".zzl").data()) == 0) // zzl文件
shouldDelete = true;
else {
// 如果是纯数字,说明是数据文件
int itemp = atoi(fileData.cFileName);
char stemp[64];
itoa(itemp, stemp, 10);
if(itemp >= 0 && stricmp(fileData.cFileName, stemp) == 0)
shouldDelete = true;
}
if(shouldDelete) {
if(firstDeleteFile) {
firstDeleteFile = false;
TCHAR temp[1024];
//sprintf(temp, "名字是 %s 的节目已经存在于目录 %s ,请问要删除旧的节目数据吗?(可能是被遗忘的有用数据)", chnlName.data(), path.data());
//int answer = MessageBox(NULL, temp, "警告", MB_YESNO|MB_ICONQUESTION);
int answer = IDYES;
if(answer != IDNO) {
//MessageBox(NULL, "你选择删除旧的节目数据,新的节目开始压缩!", "通知", MB_OK|MB_ICONINFORMATION);
TraceLog1("现在覆盖旧的节目数据,新的节目开始压缩!\n");
}
else {
sprintf(temp, "你选择保存旧的节目数据,此次压缩将被取消,请在转移目录 %s 下的数据之后,重新开始压缩。", path.data());
MessageBox(NULL, temp, "通知", MB_OK|MB_ICONINFORMATION);
return false;
}
}
string temp = path+"\\";
temp.append(fileData.cFileName);
DeleteFile(temp.data());
}
if(!FindNextFile(hFind, &fileData)) {
if(GetLastError() == ERROR_NO_MORE_FILES)
break;
else {
assert(0);
return true;
}
}
}
FindClose(hFind);
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -