static void *sillyThreadFn(void *args) { int *sleepTime = (int *)args; assert(sleepTime); /* we don't want you sleeping forever, so arg > 20 is tossed */ assert(*sleepTime >= 0 && *sleepTime <= 20); sleep(*sleepTime); /* make sure we let the Thread manager know we're gone */ ThreadExit(ThreadSelf()); }
Lock* _TakeLock(char* file, int line, Lock* lock) { #ifndef AIO4C_WIN32 ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER; #endif /* AIO4C_WIN32 */ Thread* current = ThreadSelf(); ProbeTimeStart(AIO4C_TIME_PROBE_BLOCK); if (current != NULL) { ThreadSetState(current, AIO4C_THREAD_STATE_BLOCKED); } dthread("%s:%d: %s lock %p\n", file, line, (current!=NULL)?ThreadGetName(current):NULL, (void*)lock); #ifndef AIO4C_WIN32 if ((code.error = pthread_mutex_lock(&lock->mutex)) != 0) { code.lock = lock; if (current != NULL) { ThreadSetState(current, AIO4C_THREAD_STATE_RUNNING); } Raise(AIO4C_LOG_LEVEL_ERROR, AIO4C_THREAD_LOCK_ERROR_TYPE, AIO4C_THREAD_LOCK_TAKE_ERROR, &code); return NULL; } #else /* AIO4C_WIN32 */ EnterCriticalSection(&lock->mutex); #endif /* AIO4C_WIN32 */ lock->owner = current; lock->state = AIO4C_LOCK_STATE_LOCKED; if (current != NULL) { ThreadSetState(current, AIO4C_THREAD_STATE_RUNNING); } ProbeTimeEnd(AIO4C_TIME_PROBE_BLOCK); return lock; }
Lock* _ReleaseLock(char* file, int line, Lock* lock) { Thread* current = ThreadSelf(); #ifndef AIO4C_WIN32 ErrorCode code = AIO4C_ERROR_CODE_INITIALIZER; #endif /* AIO4C_WIN32 */ dthread("%s:%d: %s unlock %p\n", file, line, (current!=NULL)?ThreadGetName(current):NULL, (void*)lock); lock->state = AIO4C_LOCK_STATE_FREE; lock->owner = NULL; #ifndef AIO4C_WIN32 if ((code.error = pthread_mutex_unlock(&lock->mutex)) != 0) { code.lock = lock; Raise(AIO4C_LOG_LEVEL_WARN, AIO4C_THREAD_LOCK_ERROR_TYPE, AIO4C_THREAD_LOCK_RELEASE_ERROR, &code); return NULL; } #else /* AIO4C_WIN32 */ LeaveCriticalSection(&lock->mutex); #endif /* AIO4C_WIN32 */ return lock; }
static void *DcpRecDownloadThread( void *args ) { int ret; int readLen = MAX_RECORD_DATA_SEND_PACKET_SIZE; REC_DOWNLOAD_T *pRecDownload = (REC_DOWNLOAD_T *)args; ThreadDetach( ThreadSelf() ); SVPrint( "%s start!\r\n", __FUNCTION__ ); while( 1 ) { ret = Read( pRecDownload->fd, pRecDownload->sendPack.dataBuf, readLen ); if( ret > 0 ) { pRecDownload->sendPack.packHead.len = ret; pRecDownload->len = pRecDownload->sendPack.packHead.len + sizeof(pRecDownload->sendPack.packHead); ret = Sendn( pRecDownload->socket, &pRecDownload->sendPack.packHead, pRecDownload->len ); if( ret != 0 ) { break; } } else { break; } } ReleaseRecDownload( pRecDownload ); SVPrint( "%s stop!\r\n", __FUNCTION__ ); return NULL; }
//////////////////////////////////////////////////// // 功能: // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static void JzThreadRecordFile(DWORD p) { PAK_OBJECT obj; PAK_VFILE vfile; PMEDIA_TASK task; MESSAGE msg; int recsize; int samp_size; void *buf_in; BYTE *fade_buf; int msgid; int wsize,samp_time; int obj_del = 1; int fade_len; int fade_record = RECORD_FADE; // 获取打开信息 obj = (PAK_OBJECT)p; task = &obj->Task; vfile = &obj->File; if(!task->AChannels) task->AChannels = 1; if(!task->ASamplerate) task->ASamplerate = 8000; // 写入头信息 samp_size = 8192 * 2; msgid = 0; WaveFileHead.bytes_per_samp = task->AChannels * 2; WaveFileHead.bytes_per_sec = WaveFileHead.bytes_per_samp * task->ASamplerate; WaveFileHead.num_chans = task->AChannels; WaveFileHead.sample_rate = task->ASamplerate; if( task->MediaType == AK_REC_TYPE_WAVE) { if(JzCbFileWrite(&WaveFileHead, sizeof(WAVE_HEADER),1,vfile) != sizeof(WAVE_HEADER)) { *obj->bReady = -1; goto ThreadEnd; } } // 打开音频编码库 buf_in = kmalloc(samp_size); if(buf_in == NULL) { *obj->bReady = -1; goto ThreadEnd; } // 打开ADC设备 obj->hDac = AdcOpen(task->ASamplerate, task->AChannels); if(obj->hDac == NULL) { kdebug(mod_audio, PRINT_ERROR, "ADC device open failed! CH: %d, %dHz\n", task->AChannels, task->ASamplerate); kfree(buf_in); *obj->bReady = -1; goto ThreadEnd; } AdcSetVolume(obj->hDac, obj->Task.Volume); AdcSetEq(obj->hDac, obj->Task.Eq); // 发送WM_MEDIA_OPEN消息 if(task->hWnd) { msg.hWnd = task->hWnd; msg.Data.v = 0; msg.hWndSrc = 0; msg.MsgId = WM_MEDIA_OPEN; msg.Param = 0; #if defined(STC_EXP) sGuiMsgPutMsg(&msg); #else GuiMsgPutMsg(&msg); #endif } // 等待条件,写入数据 *obj->bReady = 1; recsize = 0; fRecodeWav = 1; while(!obj->bClose && !obj->bTerminate) { int i; // 从DA读取PCM数据 for(i=0; i<8; i++) { JzSrvProcMsg(obj); wsize = AdcRead(obj->hDac, (short*)((DWORD)buf_in+(i*samp_size)/8), samp_size/8); samp_time = (samp_size * 1000 / 8) / (task->ASamplerate * task->AChannels * sizeof(short)) ; if( fade_record ) { //fade时,不进行时间计算,递减fade时间 if( fade_record > samp_time ) fade_record -= samp_time; else fade_record = 0; } else //fade结束,可以进行时间计算 obj->RecDuration += samp_time; } if( !fade_record ) recsize += samp_size; // 检查录音时间是否结束 if(obj->Task.Duration && (obj->RecDuration >= obj->Task.Duration)) { recsize -= samp_size; obj->bClose = 1; break; } // 直接把PCM数据写入文件 if( !fade_record ) { wsize = JzCbFileWrite(buf_in, samp_size,1,vfile); if(wsize != samp_size) { if(wsize > 0) recsize -= samp_size - wsize; else recsize -= samp_size; obj->bClose = 2; break; } } // 处理控制消息 JzSrvProcMsg(obj); while(obj->bRecPause && !obj->bClose && !obj->bTerminate) { JzSrvProcMsg(obj); sTimerSleep(100, NULL); } } //fade时,不保存文件 if( !fade_record ) { fade_len = (task->ASamplerate * task->AChannels * sizeof(short) * RECODE_SKIP_LEN) / 1000; if( task->MediaType == AK_REC_TYPE_WAVE) { // 录音结束,写入头/尾信息 JzCbFileSeek(vfile, 0, SEEK_SET); WaveFileHead.file_size = recsize + sizeof(WaveFileHead) - 8; WaveFileHead.data_length = recsize; JzCbFileWrite(&WaveFileHead, sizeof(WAVE_HEADER),1,vfile); if( vfile->PlayLength > (fade_len + sizeof(WaveFileHead)) && fade_len ) { fade_buf = (BYTE*)kmalloc(fade_len); kmemset(fade_buf,0,fade_len); JzCbFileSeek(vfile, recsize + sizeof(WaveFileHead) - fade_len , SEEK_SET); JzCbFileWrite(fade_buf, fade_len,1,vfile); kfree(fade_buf); kdebug(mod_audio, PRINT_INFO, "recode fade: skip wav len = %d\n",fade_len); } } else { if( vfile->PlayLength > fade_len && fade_len ) { fade_buf = (BYTE*)kmalloc(fade_len); kmemset(fade_buf,0,fade_len); JzCbFileSeek(vfile, recsize - fade_len, SEEK_SET); JzCbFileWrite(fade_buf, fade_len,1,vfile); kfree(fade_buf); kdebug(mod_audio, PRINT_INFO, "recode fade: skip pcm len = %d\n",fade_len); } } } JzCbFileWriteFlush(vfile); fRecodeWav = 0; // 线程结束, 关闭文件和设备 AdcClose(obj->hDac); // 设置线程结束标志 if(obj->bTerminate || (obj->bClose == 2)) { msgid = WM_MEDIA_TERMINATE; msg.MsgId = msgid; msg.hWnd = task->hWnd; } else if(obj->bClose) { msgid = WM_MEDIA_CLOSE; msg.MsgId = msgid; msg.hWnd = task->hWnd; } else { // 非正常结束 msgid = 0; *obj->bReady = -1; } // 设置返回消息参数 if(obj->bTerminate == 2) msg.Data.v = 1; else if(obj->bClose == 2) msg.Data.v = 2; else msg.Data.v = 0; // 删除对象 if(obj->bTerminate == 1) obj_del = 0; else JzSrvDestroyNotify(task); // 发送WM_MEDIA_CLOSE消息 if(msgid) { msg.hWndSrc = 0; msg.Param = 0; #if defined(STC_EXP) sGuiMsgPutMsg(&msg); #else GuiMsgPutMsg(&msg); #endif } if(buf_in) kfree(buf_in); ThreadEnd: // 设置线程结束标志 if(!obj_del) obj->bTerminate++; #if defined(STC_EXP) sThreadTerminate(sThreadSelf()); #else ThreadTerminate(ThreadSelf()); #endif }
//////////////////////////////////////////////////// // 功能: // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static void JzThreadPlayFile(DWORD p) { PAK_VFILE vfile; PAK_OBJECT obj; PMEDIA_TASK task; VIDEO_PARAM video; MEDIALIB_STATUS player_status; MESSAGE msg; int cur_time; int duration; int msgid; int ret,jmp_ret; int max_wsize; int max_time; short *pcm,*pData; int fade,begin_time; int obj_del = 1; int wlen; int block_num; int time_out; DWORD init_start_time,init_end_time; #ifdef MPLAYER_PRINTF_ENABEL syslog_set_global_level(PRINT_INFO); #endif // 获取打开信息 obj = (PAK_OBJECT)p; task = &obj->Task; vfile = &obj->File; init_start_time = TimerCount(); kdebug(mod_audio, PRINT_INFO, "mplayer init player time = %d\n",init_start_time); obj->PlayerType = task->ExterdType; #ifdef CONFIG_MAKE_BIOS task->ExterdType = 0; #endif pcm = NULL; obj->hDac = NULL; video.hMutex = NULL; //初始化mplayer使用变量 nMplayerDelay = 0; nMplayerSamplerate = 0; nMplayerChannels = 0; nMplayerAudioStart = 0; //初始化回调函数 if( (ret = MediaLibInit(obj)) < 0 ) { kdebug(mod_audio, PRINT_ERROR, "MediaLibInit failed\n"); *obj->bReady = -1; if( ret != -2 ) MediaLibClose(obj); goto ThreadEnd; } kdebug(mod_audio, PRINT_INFO, "mplayer MediaLibInit end = %d\n",TimerCount()); if( task->ExterdType ) { //防止SD卡播放时,拔出SD卡,导致MPLAYER在初始化阶段死机 obj->JzAvDecoder->fMplayerInit = 1; kdebug(mod_audio, PRINT_INFO, "set jump error addr\n"); jmp_ret = ksetjmp(obj->JzAvDecoder->AudioJumpBuf); if( jmp_ret == 1 ) { kdebug(mod_audio, PRINT_ERROR, "audio error, jump to end\n"); *obj->bReady = -1; if( pcm ) kfree(pcm); if( obj->hDac ) DacClose(obj->hDac); if(video.hMutex) kMutexDestroy(video.hMutex); MediaLibClose(obj); goto ThreadEnd; } } //打开音频库 if( MediaLibOpen(obj, 0) < 0 ) { //音频库打开失败 kdebug(mod_audio, PRINT_ERROR, "MediaLibOpen failed\n"); *obj->bReady = -1; MediaLibClose(obj); goto ThreadEnd; } kdebug(mod_audio, PRINT_INFO, "mplayer MediaLibOpen end = %d\n",TimerCount()); //得到音频库信息 if( MediaLibGetInfo(obj) < 0 ) { //得到音频库信息失败 kdebug(mod_audio, PRINT_ERROR, "MediaLibGetInfo failed\n"); *obj->bReady = -1; MediaLibClose(obj); goto ThreadEnd; } if( !obj->Info.bHasAudio ) { //没有音频数据,直接退出 *obj->bReady = -1; MediaLibClose(obj); goto ThreadEnd; } if(obj->Info.bHasVideo) { //有视频,但是播放区域为空,直接退出(MP3里面播放改名的RMVB等。。。。) if( !(task->ShowRect.w && task->ShowRect.h) ) { *obj->bReady = -1; MediaLibClose(obj); goto ThreadEnd; } } kdebug(mod_audio, PRINT_INFO, "mplayer MediaLibGetInfo end = %d\n",TimerCount()); if( obj->PlayerType ) { //设置视频的显示区域以及位置 if( task->ShowRect.w && task->ShowRect.h ) MplayerResizeVideo(obj,task); else { kdebug(mod_audio, PRINT_WARNING, "can't play video\n"); obj->JzAvDecoder->fIpuEnable = 1; } } else { obj->StartTime = task->ShowRect.x; obj->EndTime = task->ShowRect.y; } //申请播放PCM的内存 block_num = MAX_PCM_GET_LEN; pcm = (short*)kmalloc(block_num); if( pcm == NULL ) { kdebug(mod_audio, PRINT_ERROR, "memory lose pcm == null\n"); *obj->bReady = -1; MediaLibClose(obj); goto ThreadEnd; } kdebug(mod_audio, PRINT_INFO, "mplayer kmalloc pcm end = %d\n",TimerCount()); //MPLAYER播放器使用,用来设置从MPLAYER读到的PCM数据以及长度 if( obj->PlayerType ) { //外部播放器使用变量 pMediaPcmData = (BYTE*)pcm; nMediaPcmLen = 0; } // 打开DAC设备,并设置DAC设备采样率、声道 *obj->bReady = 1; obj->hDac = DacOpen(); if(obj->hDac == NULL) { kdebug(mod_audio, PRINT_ERROR, "dac open error\n"); kfree(pcm); MediaLibClose(obj); goto ThreadEnd; } if(DacSetSamplerate(obj->hDac, obj->Info.AudioSamplerate, obj->Info.AudioChannels) < 0) { kdebug(mod_audio, PRINT_ERROR, "set samplerate error\n"); kfree(pcm); DacClose(obj->hDac); MediaLibClose(obj); goto ThreadEnd; } kdebug(mod_audio, PRINT_INFO, "mplayer dacopen end = %d\n",TimerCount()); DacSetTempo(obj->hDac, obj->Task.Tempo); DacSetVolume(obj->hDac, obj->Task.Volume); kdebug(mod_audio, PRINT_INFO, "volume = %d, tempo=%d\n",obj->Task.Volume, obj->Task.Tempo); // 计算每次写入PCM数据最大值(1K的整数倍) max_wsize = 50 * (obj->Info.AudioSamplerate * obj->Info.AudioChannels * sizeof(short)) / 1000; max_wsize = ((max_wsize + 1023) / 1024) * 1024; max_time = (max_wsize * 1000) / (obj->Info.AudioSamplerate * obj->Info.AudioChannels * sizeof(short)); begin_time = MediaLibPlay(obj); if( begin_time < 0 ) { kdebug(mod_audio, PRINT_ERROR, "MediaLibPlay failed\n"); if(video.hMutex) kMutexDestroy(video.hMutex); *obj->bReady = -1; DacClose(obj->hDac); MediaLibClose(obj); kfree(pcm); goto ThreadEnd; } // 设置视频输出 if (obj->Info.bHasVideo) { // 启动视频解码线程 video.obj = obj; video.fPlayVideo = 1; video.hMutex = kMutexCreate(); video.audio_frame_time = 0; video.video_frame_time = 0; kdebug(mod_audio, PRINT_INFO, "create video thread\n"); KernelThread(PRIO_USER+2, AkThreadVideoPlay, (DWORD)&video, 0x8000); } else { video.obj = obj; video.hMutex = NULL; video.fPlayVideo = 0; video.audio_frame_time = 0; video.video_frame_time = 0; } // 发送WM_MEDIA_OPEN消息 if(task->hWnd) { msg.hWnd = task->hWnd; msg.Data.v = 0; msg.hWndSrc = 0; msg.MsgId = WM_MEDIA_OPEN; msg.Param = 0; #if defined(STC_EXP) sGuiMsgPutMsg(&msg); #else GuiMsgPutMsg(&msg); #endif } // 循环解压并播放 fade = 0; duration = 0; fPlayMedia = 1; obj->RecDuration = 0; if( task->ExterdType ) obj->JzAvDecoder->fMplayerInit = 0; init_end_time = TimerCount(); kdebug(mod_audio, PRINT_INFO, "mplayer start play time = %d\n",init_end_time); kdebug(mod_audio, PRINT_INFO, "playe init time = %dms\n",(init_end_time-init_start_time)*10); kdebug(mod_audio,PRINT_INFO,"obj->StartTime = %d, Obj->EndTime = %d\n",obj->StartTime,obj->EndTime); while(!obj->bClose && !obj->bTerminate) { // 解码音频数据 if(video.hMutex) kMutexWait(video.hMutex); //得到PCM数据 player_status = MediaLibGetStatus(obj); wlen = MediaLibGetPcm(obj,(BYTE*)pcm,block_num); // kprintf("wlen = %d\n",wlen); if((wlen<0) || (player_status==MEDIALIB_END) || (player_status==MEDIALIB_ERR)) { DacWriteEnd(obj->hDac, 0); if(MEDIALIB_ERR == player_status) { kdebug(mod_media, PRINT_ERROR, "media lib error!\n"); obj->bClose = 2; } else obj->bClose = 1; if(video.hMutex) kMutexRelease(video.hMutex); kdebug(mod_audio, PRINT_INFO, "wlen = %d, player_status = %d\n",wlen,player_status); break; } // 获取当前音频解码时间 cur_time = MediaLibGetAudioCurTime(obj); // kprintf("cur time = %d\n",cur_time); if( obj->StartTime ) { MediaLibSeek(obj,obj->StartTime); obj->StartTime = 0; wlen = 0; } if( obj->EndTime && cur_time >= obj->EndTime ) { //定时播放,如果播放时间到,则直接播放结束 DacWriteEnd(obj->hDac, 0); obj->bClose = 1; if(video.hMutex) kMutexRelease(video.hMutex); kprintf("play seek end: cur time = %d, end time = %d\n",cur_time,obj->EndTime); break; } if(video.hMutex) kMutexRelease(video.hMutex); if( nMplayerAudioStart == 0 && video.hMutex) { time_out = 100; nMplayerAudioStart = 1; while( nMplayerAudioStart != 3 && time_out--) sTimerSleep(10,NULL); if( !time_out ) kprintf("!!!!!!!! WARNNING : wait video time out !!!!!!!!\n"); nMplayerAudioStart = 4; } // 输出音频数据到DA pData = pcm; obj->RecDuration = cur_time; while(wlen > 0) { DWORD wsize; int ctl_code; // 写入PCM数据到DAC设备 wsize = (wlen > max_wsize) ? max_wsize : wlen; if(fade) { int s; short pcms; pcms = wsize / sizeof(short); for(s=0; s<pcms; s++) { int tmp; tmp = (int)pData[s]; tmp = (tmp * (pcms - s)) / pcms; pData[s] = (short)tmp; } DacWrite(obj->hDac, pData, wsize); DacWriteEnd(obj->hDac, 0); break; } else { if( DacWrite(obj->hDac, pData, wsize) == 0 ) { //出错,返回值为0 kdebug(mod_audio, PRINT_ERROR, "dac write is 0 \n"); obj->bClose = 1; break; } } // 提高当前时间精度 if( wsize == max_wsize ) obj->RecDuration += max_time; else obj->RecDuration += (wsize * 1000) / (obj->Info.AudioSamplerate * obj->Info.AudioChannels * sizeof(short)); pData += wsize / sizeof(short); wlen -= wsize; // 控制动作处理 if(video.hMutex) kMutexWait(video.hMutex); ctl_code = JzSrvProcMsg(obj); player_status = MediaLibGetStatus(obj); if(video.hMutex) kMutexRelease(video.hMutex); // 等待退出暂停状态 while( MEDIALIB_PAUSE == player_status && !obj->bClose && !obj->bTerminate) { sTimerSleep(100, NULL); if(video.hMutex) kMutexWait(video.hMutex); ctl_code = JzSrvProcMsg(obj); player_status = MediaLibGetStatus(obj); if(video.hMutex) kMutexRelease(video.hMutex); } // 检查是否退出 if(obj->bTerminate) { // if(fade == 0 && wlen == 0) // { // wlen = MediaLibGetPcm(obj,(BYTE*)pcm,block_num); // pData = pcm; // if(wlen < 0) // { // wlen = 0; // } // } kdebug(mod_audio, PRINT_INFO, "fade len:%d\n", wlen); fade = 1; } } } //如果是强行退出,则直接关闭MOS管,方式喀嚓声 if( obj->bTerminate && GetDacChannel() <= 1 ) { kdebug(mod_audio, PRINT_INFO, "terminate media, close mute mos\n"); } init_start_time = TimerCount(); kdebug(mod_audio, PRINT_INFO, "close meidia start : %d\n",init_start_time); // 是否用于视频的互斥量 if(video.hMutex) { //等待视频结束 while( 1 ) { if( !video.fPlayVideo ) break; sTimerSleep(10, NULL); } kMutexDestroy(video.hMutex); } // 关闭DAC设备 DacClose(obj->hDac); MediaLibClose(obj); kfree(pcm); init_end_time = TimerCount(); kdebug(mod_audio, PRINT_INFO, "close meidia end : %d - %dms\n",init_end_time, (init_end_time - init_start_time)*10); ThreadEnd: fPlayMedia = 0; WinClipMask(NULL); //MPLAYER播放器使用,用来设置从MPLAYER读到的PCM数据以及长度 if( obj->PlayerType ) { //外部播放器使用变量 pMediaPcmData = NULL; nMediaPcmLen = 0; } // 设置线程结束标志 msgid = 0; if(obj->bTerminate || (obj->bClose == 2)) { msgid = WM_MEDIA_TERMINATE; msg.MsgId = msgid; msg.hWnd = task->hWnd; } else if(obj->bClose) { msgid = WM_MEDIA_CLOSE; msg.MsgId = msgid; msg.hWnd = task->hWnd; } else { // 未启动播放即结束 msgid = 0; *obj->bReady = -1; } // 设置返回消息参数 if((obj->bTerminate == 2)) msg.Data.v = 1; else if(obj->bClose == 2) msg.Data.v = 2; else msg.Data.v = 0; // 删除对象 if(obj->bTerminate == 1) obj_del = 0; else JzSrvDestroyNotify(task); // 发送WM_MEDIA_CLOSE消息 if(msgid) { msg.hWndSrc = 0; msg.Param = 0; #if defined(STC_EXP) sGuiMsgPutMsg(&msg); #else GuiMsgPutMsg(&msg); #endif } // 增加Terminate标记,方便退出 if(!obj_del) obj->bTerminate++; kdebug(mod_audio, PRINT_INFO, "medialib close finish\n"); #ifdef MPLAYER_PRINTF_ENABEL syslog_set_global_level(PRINT_NOTICE); #endif #if defined(STC_EXP) sThreadTerminate(sThreadSelf()); #else ThreadTerminate(ThreadSelf()); #endif }
//////////////////////////////////////////////////// // 功能: // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static void AkThreadVideoPlay(DWORD p) { PVIDEO_PARAM video = (PVIDEO_PARAM)p; PAK_OBJECT obj; DWORD pre_audio_time; DWORD audio_time; DWORD frame_time; DWORD delay_time; DWORD totle_time; DWORD totle_fps; RECT *show_rect; int pts; int pass_frame; MEDIALIB_STATUS player_status; frame_time = 0; audio_time = 0; pre_audio_time = 0; pass_frame = 0; delay_time = 0; totle_time = 0; totle_fps = 0; video->fPlayVideo = 1; frame_time = TimerCount(); obj = video->obj; MxuEnable(); show_rect = &obj->Task.ShowRect; WinClipMask(show_rect); while(!obj->bClose && !obj->bTerminate) { kMutexWait(video->hMutex); if( !nMplayerAudioStart || nMplayerAudioStart == 3 ) { kMutexRelease(video->hMutex); sTimerSleep(10, NULL); continue; } if( nMplayerAudioStart == 1 ) nMplayerAudioStart = 2; // 获取音频时间 audio_time = obj->RecDuration; // 矫正同步时间 { DWORD tick; tick = TimerCount(); pts = MediaLibGetYuv(obj); totle_time += TimerCount() - tick; totle_fps++; } if( nMplayerAudioStart == 2 ) nMplayerAudioStart = 3; // kprintf("%d,%d\n",pts,audio_time); if(pts < 0) { player_status = MediaLibGetStatus(obj); if (MEDIALIB_ERR == player_status) { kdebug(mod_video, PRINT_ERROR, "video decode error!\n"); obj->bClose = 2; kMutexRelease(video->hMutex); break; } else if(MEDIALIB_PAUSE == player_status) { kMutexRelease(video->hMutex); // 等待退出暂停状态 do { sTimerSleep(100, NULL); kMutexWait(video->hMutex); player_status = MediaLibGetStatus(obj); kMutexRelease(video->hMutex); }while((MEDIALIB_PAUSE == player_status) && !obj->bClose && !obj->bTerminate); // 重新设置系数 frame_time = 0; audio_time = 0; pre_audio_time = 0; frame_time = TimerCount(); // 继续解压循环 continue; } else { obj->bClose = 1; kMutexRelease(video->hMutex); break; } } player_status = MediaLibGetStatus(obj); if(player_status == MEDIALIB_ERR) { kdebug(mod_video, PRINT_ERROR, "video decode error!\n"); obj->bClose = 2; kMutexRelease(video->hMutex); break; } kMutexRelease(video->hMutex); // 等待退出暂停状态 while( MEDIALIB_PAUSE == player_status && !obj->bClose && !obj->bTerminate) { sTimerSleep(100, NULL); kMutexWait(video->hMutex); player_status = MediaLibGetStatus(obj); kMutexRelease(video->hMutex); } } WinClipMask(NULL); kdebug(mod_video, PRINT_INFO, "totle_fps = %d, total_time = %d\n",totle_fps,totle_time); kdebug(mod_video, PRINT_INFO, "video thread close\n"); video->fPlayVideo = 0; #if defined(STC_EXP) sThreadTerminate(sThreadSelf()); #else ThreadTerminate(ThreadSelf()); #endif }
//////////////////////////////////////////////////// // 功能: // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static void JzThreadGetInfo(DWORD p) { PAK_VFILE vfile; PAK_OBJECT obj; PMEDIA_TASK task; int ret; // 获取打开信息 obj = (PAK_OBJECT)p; vfile = &obj->File; task = &obj->Task; vfile = &obj->File; #ifdef CONFIG_MAKE_BIOS task->ExterdType = 0; #endif obj->PlayerType = task->ExterdType; //初始化回调函数 if((ret = MediaLibInit(obj)) < 0 ) { kdebug(mod_media, PRINT_ERROR, "MediaLibInit failed.\n"); *obj->bReady = -1; if( ret == -2 ) goto ThreadEnd1; else goto ThreadEnd; } //打开音频库 if( MediaLibOpen(obj, 1) < 0 ) { //音频库打开失败 kdebug(mod_media, PRINT_ERROR, "MediaLibOpen failed.\n"); *obj->bReady = -1; goto ThreadEnd; } //得到音频库信息 if( MediaLibGetInfo(obj) < 0 ) { //得到音频库信息失败 kdebug(mod_media, PRINT_ERROR, "MediaLibGetInfo failed.\n"); *obj->bReady = -1; goto ThreadEnd; } if( obj->Info.bHasVideo ) { //视频文件,需要计算视频的显示尺寸 SetVideoPosAndSize(obj,task); } obj->bGetInfo = 0; *obj->bReady = 1; ThreadEnd: MediaLibClose(obj); ThreadEnd1: // 设置线程结束标志 if(obj->bTerminate) obj->bTerminate++; #if defined(STC_EXP) sThreadTerminate(sThreadSelf()); #else ThreadTerminate(ThreadSelf()); #endif }
static void *WriteRecordFileThread(void *arg) { static unsigned int stopCount = 0; PCP_NODE_T *pRecPcp = NULL; int channel = (int)arg; time_t utc = 0; uint recordType = 0; uint writeSize = 0; uchar frameType = 0; RECORD_THREAD *p_rec = NULL; int recordCtlFlag = REC_SLEEP; int ret = 0; SVPrint("ch(%d) WriteRecordFileThread:%d!\r\n",channel,ThreadSelf()); p_rec = &rec_thread[channel]; while(p_rec->recordThreadRunFlag) { recordCtlFlag = GetRecordCtlFlag(channel); switch(recordCtlFlag) { case REC_START: stopCount = 0; recordType = 0; CloseRecLed(channel); StartH264Stream(channel); pRecPcp = RecordPoolRead( channel ); if( NULL == pRecPcp ) { RecordPoolWait( channel ); } else { AnalysisFrameData( channel, pRecPcp, &utc, &recordType, &writeSize, &frameType ); FiPrint2( "wait I frame,frameType(%d)!\r\n", pRecPcp->pcpHead.type); if( FI_FRAME_TYPE_VIDEO_I != pRecPcp->pcpHead.type ) { FiPrint2( "start record but no I frame(%d)!\r\n", pRecPcp->pcpHead.type); RecordPoolFree( pRecPcp ); continue; } ret = CreateRecordAndIndexFile( channel, utc ); if(FI_SUCCESS == ret) { ResetIndexStruct( channel ); ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc ); if(FI_SUCCESS == ret) { SetRecordCtlFlag( channel, REC_WRITE ); OpenRecLed( channel ); } } RecordPoolFree( pRecPcp ); if(FI_SUCCESS != ret) { sleep(1); } } break; case REC_WRITE: RecordPoolWait( channel ); while( 1 ) { if( NULL == (pRecPcp=RecordPoolRead(channel)) ) { break; } AnalysisFrameData( channel, pRecPcp, &utc, &recordType, &writeSize, &frameType ); ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc ); if( FI_SUCCESS != ret ) { SetRecordCtlFlag( channel, REC_START ); } RecordPoolFree( pRecPcp ); } break; case REC_SWITCH: stopCount = 0; RecordPoolWait( channel ); while( 1 ) { if( NULL == (pRecPcp=RecordPoolRead(channel)) ) { break; } AnalysisFrameData( channel, pRecPcp, &utc, &recordType, &writeSize, &frameType ); if( FI_FRAME_TYPE_VIDEO_I != pRecPcp->pcpHead.type ) { ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc ); if( FI_SUCCESS != ret ) { SetRecordCtlFlag( channel, REC_START ); } } else { CloseRecordAndIndexFile( channel ); utc = time( NULL ); ret = CreateRecordAndIndexFile( channel, utc ); if( FI_SUCCESS == ret ) { ResetIndexStruct( channel ); ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc ); if( FI_SUCCESS == ret ) { SetRecordCtlFlag( channel, REC_WRITE ); } } else //if(FI_SUCCESS != ret) { SetRecordCtlFlag( channel, REC_START ); Usleep(1000); } } RecordPoolFree( pRecPcp ); } break; case REC_STOP: while( 1 ) { pRecPcp = RecordPoolRead( channel ); SVPrint( "ql debug -ch(%d), pRecPcp(0x%X), stopCount(%u)!\r\n", channel, pRecPcp, stopCount ); if( NULL == pRecPcp || ++stopCount >= (MAX_RECORD_DATA_NODE << 1) ) { break; // while( 1 ) } AnalysisFrameData( channel, pRecPcp, &utc, &recordType, &writeSize, &frameType ); ret = WriteDataToDisk( channel, pRecPcp, writeSize, recordType, utc ); RecordPoolFree( pRecPcp ); if( FI_SUCCESS != ret ) { break; // while( 1 ) } } CloseRecordAndIndexFile( channel ); SetRecordCtlFlag( channel, REC_SLEEP ); CloseH264Stream( channel ); CloseRecLed( channel ); break; case REC_SLEEP: default: Usleep( 500000 ); break; } //switch } //while(1) SVPrint("quit ch(%d) WriteRecordFileThread!\r\n",channel); return NULL; }
/********************************************************* 录像监视线程,该线程与系统时间有关, 请在启动应用线程后再启动该线程 并在启动此次线程再启动录像线程 ***********************************************************/ static void *ManageRecordThread(void *arg) { int chNum = REAL_CHANNEL_NUM; int i,j; int real_time[chNum]; int base_time[REAL_CHANNEL_NUM] = {-1}; int real_year[chNum],real_month[chNum],real_day[chNum]; int base_year[chNum],base_month[chNum],base_day[chNum]; uint base_rec_type[REAL_CHANNEL_NUM]; uint real_rec_type[REAL_CHANNEL_NUM]; int alarm_real_time[REAL_CHANNEL_NUM]; int alarm_base_time[REAL_CHANNEL_NUM]; char real_parh[RECORD_FILENAME_LEN] = {0}; char base_path[RECORD_FILENAME_LEN] = {0}; SVPrint("start ManageRecordThread:%d!\r\n",ThreadSelf()); while(rec_manage.recordManageRunFlag) { FiRecStartAutoDelOldFile(); /*录像分区改变切换文件,优先级最高*/ if(FI_FAIL == FiHddGetUsingPartition(real_parh)) { for(i=0;i<chNum;i++) { if(REC_SLEEP != GetRecordCtlFlag(i)) SetRecordCtlFlag(i,REC_STOP); } sleep(1); continue; } else { if(0 != strcmp(base_path,real_parh)) { strcpy(base_path,real_parh); for(i=0;i<chNum;i++) { if(REC_WRITE == GetRecordCtlFlag(i)) { SVPrint("record switch partition.\r\n"); RefrechAlarmBaseTimeCursor(i); RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i], &base_time[i],&base_year[i],&base_month[i],&base_day[i]); SetRecordCtlFlag(i,REC_SWITCH); //仅仅录像分区,不做任何时间检测 } } } } if(-1 == manage_init_flag) { for(j=0;j<chNum;j++) { /*初始化定时录像监测*/ real_time[j] = time(NULL); base_time[j] = real_time[j]; FiTimeUtcToHuman(base_time[j],&base_year[j],&base_month[j],&base_day[j],NULL,NULL,NULL); /*初始化录像类型切换监测*/ real_rec_type[j] = GetRecordType(j); base_rec_type[j] = real_rec_type[j]; RefrechAlarmBaseTimeCursor(j); alarm_real_time[j] = SysRunTimeGet(); } manage_init_flag = 0; } /*监测手动和定时录像*/ for(i=0;i<chNum;i++) { ManageHandRecord(i); ManageTimerRecordTime(i); } /*定时录像切文件*/ for(i=0;i<chNum;i++) { real_time[i] = time(NULL); FiTimeUtcToHuman(real_time[i],&real_year[i],&real_month[i],&real_day[i],NULL,NULL,NULL); if(( real_time[i] - base_time[i] >= FiRecGetRecFileSwitchTime() ) || (real_time[i] - base_time[i] < 0 && base_time[i] - real_time[i] > RECORD_TIME_ERROR_RANGE) || (real_year[i] != base_year[i]) || (real_month[i] != base_month[i]) || (real_day[i] != base_day[i])) { SVPrint("ch(%d),%d-%d=%d\r\n",i,real_time[i],base_time[i],real_time[i]-base_time[i]); RefrechAlarmBaseTimeCursor(i); RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i], &base_time[i],&base_year[i],&base_month[i],&base_day[i]); if(REC_WRITE == GetRecordCtlFlag(i)) { SetRecordCtlFlag(i,REC_SWITCH); } } } /*报警录像情况的录像类型改变从而切换文件*/ for(i=0;i<chNum;i++) { real_rec_type[i] = GetRecordType(i); if(real_rec_type[i] & RECORD_TYPE_ALARM_ALL) { alarm_base_time[i] = getAlarmBaseTimeCursor(i); alarm_real_time[i] = SysRunTimeGet(); if( alarm_real_time[i] - alarm_base_time[i] >= FiRecGetRecFileSwitchTimeAlarm() ) { SVPrint("%d-%d=%d\r\n",alarm_real_time[i] , alarm_base_time[i],alarm_real_time[i] - alarm_base_time[i]); FiRecStopRecord(i,RECORD_TYPE_ALARM_ALL); RefrechAlarmBaseTimeCursor(i); RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i], &base_time[i],&base_year[i],&base_month[i],&base_day[i]); if(real_rec_type[i] & (RECORD_TYPE_ALL&(~RECORD_TYPE_ALARM_ALL))) { SetRecordCtlFlag(i,REC_SWITCH); } } } } /* 控制录像线程启动录像 ,是否启动录像*/ for(i=0;i<chNum;i++) { real_rec_type[i] = GetRecordType(i); if(real_rec_type[i] & RECORD_TYPE_ALL) { if(FI_TRUE == ControlRecordThreadStartRecord(i)) { RefrechAlarmBaseTimeCursor(i); RefrechTimerBaseTimeCursor(&real_time[i],&real_year[i],&real_month[i],&real_day[i], &base_time[i],&base_year[i],&base_month[i],&base_day[i]); } } else { ControlRecordThreadStopRecord(i); } } Usleep(500000); //500ms } //while(rec_manage.recordManageRunFlag) SVPrint("quit ManageRecordThread!\r\n"); return NULL; }