⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zzlfilewriter.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -