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; }