Esempio n. 1
0
MF_API void MFHeap_Free(void *pMem)
{
	MFCALLSTACK;

	if(!pMem)
	{
		MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer.");
		return;
	}

	MFThread_LockMutex(gAllocMutex);

	MFAllocHeader *pHeader = GetAllocHeader(pMem);
	MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(" MFFMT_SIZE_T ")", pHeader->pFile, pHeader->line));

	MFHeap *pHeap = pHeader->pHeap;
#if !defined(_RETAIL)
	size_t extra;
	size_t allocBytes = GetAllocSize(pHeader->size, extra);

	pHeap->totalAllocated -= allocBytes;
	pHeap->totalWaste -= extra;
	--pHeap->allocCount;

//	MFDebug_Log(2, MFStr("Free: %p, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line));
#endif

	MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes);
#if defined(USE_PRE_MUNGWALL)
	MFCopyMemory((char*)pMem - MFHeap_MungwallBytes, "eerfeerfeerfeerf", MFHeap_MungwallBytes);
#endif
	MFMemSet(pMem, 0xFE, pHeader->size);

	pHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pHeap->pHeapData);

#if defined(_USE_TRACKING_HASH_TABLE)
	FreeAlloc(pMem);
#endif

	MFThread_ReleaseMutex(gAllocMutex);
}
//刷新视频解码线程
void *RenderVideo(void *arg)
{
	if(!arg)
		return NULL;

	AvManager *manager = (AvManager*)arg;
	MediaPacket spkt;
	int size = 0,ret = 0;
	long avsize = 0;

	//只有在没有停止信号下,才能不断地读取数据
	for(;manager->avState != STOP;)
	{
		if(ParseQueueBufferLength(manager->MediaPicture) > CACHE_PICTURE_BUFFER_NUM)
		{
			usSleep(DEFAULT_AV_WAIT);
			continue;
		}

		if(manager->avState == PAUSE && !manager->avSeek)
		{
			usSleep(DEFAULT_AV_WAIT);
			continue;
		}

		memset(&spkt,0,sizeof(MediaPacket));

		ret = RecvDataFromAvQueue(manager->MediaVideo,&spkt);

		if(ret < 0)
		{
			usSleep(DEFAULT_AV_WAIT);
			continue;			
		}

		if(manager->avSeek && !IsHardWareAccel())
		{
			FlushBuffers(VIDEO);
		}

		if(spkt.data && spkt.size > 0)
		{
			void *vbuf = DecodeVideoYUVStream(&spkt,&avsize);

			if(vbuf && avsize > 0)
			{
				vbuf = StartScale(vbuf,avsize,&size,VideoOutPyaddr(),NULL);

				if(vbuf && size > 0)
				{
					MediaPacket mpkt;
					memset(&mpkt,0,sizeof(MediaPacket));
			
					mpkt.data = UseAlloc(size);

					if(!mpkt.data)
						continue;

					memcpy(mpkt.data,vbuf,size);
					mpkt.size = size;

					//时间戳部分

					double v_pts = 0;

					if(spkt.pts != AV_NOPTS_VALUE)
						v_pts = AVTimeToSecond(spkt.pts,manager->videoTimeBase);
					else if(spkt.dts != AV_NOPTS_VALUE)
						v_pts = AVTimeToSecond(spkt.dts,manager->videoTimeBase);
					else 
						v_pts = 0;

					double pts = SynVideo(manager,v_pts);

					mpkt.pts = AVTimeToPts(pts,manager->videoTimeBase);

					PutDataToTail(manager->MediaPicture,&mpkt);
				}
			}
		}
		else
			FreeAlloc(spkt.data);

		if(!manager->playAudio)
			manager->playerClock = manager->videoClock;
	}

	return NULL;
}
//刷新显示线程
void *RenderAudio(void *arg)
{
	if(!arg)
		return NULL;

	AvManager *manager = (AvManager*)arg;
	MediaPacket spkt;
	long avsize = 0;
	int ret = 0;

	//只有在没有停止信号下,才能不断地读取数据
	for(;manager->avState != STOP;)
	{
		//如果是暂停且没有快进时,才可以不断等待
		if(manager->avState == PAUSE && !manager->avSeek)
		{
			usSleep(DEFAULT_AV_WAIT);
			continue;
		}

		ret = RecvDataFromAvQueue(manager->MediaAudio,&spkt);

		if(ret < 0)
		{
			usSleep(DEFAULT_AV_WAIT);
			continue;			
		}

		if(manager->avSeek && !IsHardWareAccel())
		{
			FlushBuffers(AUDIO);
			DestroyPacket(&spkt);
			continue;
		}

		if(manager->audioDelay)
		{
			usSleep(manager->audioDelay);
			manager->audioDelay = 0;
		}

		if(spkt.data && spkt.size > 0)
		{
			void *abuf = DecodeAudioStream(&spkt,&avsize);

			//播放音乐
			if(abuf && avsize > 0)
			{
				PlayWave(abuf,avsize);

				//声音时间戳部分
				manager->audioClock = (double)avsize/(double)manager->audioBasePara;

				if(spkt.pts != AV_NOPTS_VALUE)
					manager->playerClock = AVTimeToSecond(spkt.pts,manager->audioTimeBase) + manager->audioClock;
				else
					manager->playerClock += manager->audioClock;

				manager->last_audio_pts = manager->playerClock;

			}
		}
		else
			FreeAlloc(spkt.data);		
	}

	return NULL;
}
//同步线程
void *SynProcess(void *arg)
{
	if(!arg)
		return NULL;

	AvManager *manager = (AvManager*)arg;
	double av_diff,delay;
	MediaPacket Packet;
		
	for(;manager->avState != STOP;)
	{
		memset(&Packet,0,sizeof(MediaPacket));

		int ret = RecvDataFromAvQueue(manager->MediaPicture,&Packet);
		
		if(ret < 0)
		{	
			usSleep(DEFAULT_AV_WAIT);
			continue;
		}

		if(manager->playAudio)
		{
			manager->last_video_pts = AVTimeToSecond(Packet.pts,manager->videoTimeBase);
			av_diff = manager->last_video_pts - manager->last_audio_pts;

			delay = manager->last_video_pts - manager->last_pts;

			if(delay < 0)
				delay = manager->last_delay;

			if(av_diff < -AV_NOSYNC_THRESHOLD)
			{
				delay = 0;
				goto video_end;
			}
			else if(av_diff > AV_NOSYNC_THRESHOLD)
			{
				delay *= 2;
				SynWait(manager,delay,VIDEO);
			}

		}
		else 
		{
			int onlydelay = (int)(manager->delayWithoutAudioTime*AV_TIME_BASE);
			usSleep(onlydelay);
		}

video_end:
		if(Packet.data && Packet.size > 0 && manager->avParams.callFunc)
		{
			//显示图片,这个方法由用户填写
			manager->avParams.callFunc(Packet.data,Packet.size,manager->avParams.arg);
		}

		printf("avdiff=%f\n",av_diff);
		manager->last_delay = delay;
		manager->last_pts = manager->last_video_pts;
		//释放视频包
		if(Packet.data)
			FreeAlloc(Packet.data);
	}

	return NULL;
}