📄 avsync.c
字号:
#include "avsync.h"static volatile AVSYNC_TIMER_S g_strTimer ={ .system_time = 0, .audio_pts = 0,};static volatile HI_U32 g_u32AudioRecheckCount;static volatile HI_S32 s32f2vothreadflag;static pthread_t thread_frame2vo;/*******目前只支持线程互斥*******/static pthread_mutex_t thread_mutex;static inline void AVSYNC_Init_Lock(){ pthread_mutex_init(&thread_mutex, NULL);}static inline void AVSYNC_Get_Lock(){ pthread_mutex_lock(&thread_mutex);}static inline void AVSYNC_Free_Lock(){ pthread_mutex_unlock(&thread_mutex);}static inline void AVSYNC_Destroy_Lock(){ pthread_mutex_destroy(&thread_mutex);}/******************************************/void AVSYNC_Start(void){ AVSYNC_Init_Lock(); g_u32AudioRecheckCount = 0;}void AVSYNC_Stop(void){ AVSYNC_Destroy_Lock();}/*设置音频pts和对应的系统时间*/static inline void AVSYNC_Set_Timer(HI_U32 audio_pts, HI_U64 system_time){ AVSYNC_Get_Lock(); //printf("oldpts %u oldsys %llu pts %lu sys %llu\n", //g_strTimer.audio_pts,g_strTimer.system_time,audio_pts,system_time);fflush(stdout); g_strTimer.audio_pts = audio_pts; g_strTimer.system_time = system_time; AVSYNC_Free_Lock();}/*获取音频pts和对应的系统时间*/static inline void AVSYNC_Get_Timer(HI_U32 *paudio_pts, HI_U64 *psystem_time){ AVSYNC_Get_Lock(); *paudio_pts = g_strTimer.audio_pts; *psystem_time = g_strTimer.system_time; AVSYNC_Free_Lock();}/*获取当前基准播放时间,单位us*/static inline HI_U32 AVSYNC_Get_CurrentPlayPts(void){ struct timeval tv; HI_U32 current_audiopts; HI_U32 audio_pts; HI_U64 current_systime; HI_U64 system_time; gettimeofday(&tv, NULL); current_systime = AVSYNC_Get_Time_Inusec(tv); AVSYNC_Get_Timer(&audio_pts, &system_time); current_audiopts = audio_pts +(HI_U32)((current_systime-system_time)/1000); return current_audiopts;}HI_S32 audio_onrecv(IN struct hiRTP_RECV_S * pRtpStream, unsigned char * pBuff, unsigned int len, int *ext_args){ HI_S32 ret; ADEC_CHN decChnID = *(ADEC_CHN *)ext_args; AENC_STREAM_S AencStream; RTP_HDR_S *pheader = (RTP_HDR_S *)pBuff; struct timeval tv; HI_U32 audio_pts; HI_U64 system_time; HI_U64 audio_delay = AUDIO_DECODE_TIME; audio_pts = ntohl(pheader->ts);; AencStream.ps16Addr = (HI_S16 *)(pBuff + RTP_HDR_LEN); AencStream.u32Len = (HI_U32)(len - RTP_HDR_LEN); AencStream.u64TimeStamp = (HI_U64)audio_pts; /* Send stream to decoder channel 0 and play */ ret = HI_ADEC_SendStream(decChnID, &AencStream); ASSERT_RETURN((HI_SUCCESS==ret), ret); if(0 == g_u32AudioRecheckCount) { /*设定基准音频pts和对应的系统时间*/ gettimeofday(&tv, NULL); system_time = AVSYNC_Get_Time_Inusec(tv); //printf("\nsec %u usec %u sys %llu\n",tv.tv_sec,tv.tv_usec, system_time);#if 0 /*考虑ao中剩余待播放数据产生的延时*/ audio_delay += ...#endif AVSYNC_Set_Timer(audio_pts, system_time+audio_delay); g_u32AudioRecheckCount = AUDIO_RECHECK_COUNT; } g_u32AudioRecheckCount--; return 1;}/*判断视频帧与基准时间是否同步*/AVSYNC_STATUS_E AVSYNC_Video_CHECK(HI_U32 video_pts){ HI_S32 avtimeshift; HI_U32 basepts; AVSYNC_STATUS_E status; basepts = AVSYNC_Get_CurrentPlayPts(); /*计算如果现在送vo,到图像显示时的时钟偏移*/ avtimeshift = (HI_S32)(video_pts - (basepts+VO_DISPLAY_TIME)); //printf("v1 %u %u %d\n",video_pts, basepts+VO_DISPLAY_TIME, avtimeshift); if(MIN_V2A_OUTSYNC > avtimeshift) { status = VIDEO_OUTSYNC_SLOW; //printf("VIDEO_OUTSYNC_SLOW video %lu base %lu shift %lu\n",video_pts //, basepts+VO_DISPLAY_TIME, avtimeshift);fflush(stdout); } else if(MIN_V2A_SYNC >= avtimeshift ) { status = VIDEO_SLIGHT_SLOW; //printf("VIDEO_SLIGHT_SLOW video %lu base %lu shift %lu\n",video_pts //, basepts+VO_DISPLAY_TIME, avtimeshift);fflush(stdout); } else if(MAX_V2A_SYNC > avtimeshift) { status = VIDEO_SYNC; } else if(MAX_V2A_OUTSYNC >= avtimeshift) { status = VIDEO_SLIGHT_QUICK; //printf("VIDEO_SLIGHT_QUICK video %lu base %lu shift %lu\n",video_pts //, basepts+VO_DISPLAY_TIME, avtimeshift);fflush(stdout); } else { status = VIDEO_OUTSYNC_QUICK; //printf("VIDEO_OUTSYNC_QUICK video %lu base %lu shift %lu\n",video_pts //, basepts+VO_DISPLAY_TIME, avtimeshift);fflush(stdout); } return status;}/*receive frame data , it receive data and send to VO for real time frame presentation,if send vo failed,discard this frame*/void* frame2vo_thread(void *args){ VDEC_THTREAD_ARGS *parg = args; HI_S32 ret; HI_BOOL bBlock = HI_FALSE; AVSYNC_STATUS_E status; HI_U32 frame_discard_interval_count = 0; VDEC_FRAMEINFO_S frameinfo; frameinfo.value = HI_FALSE; printf("frame2vo_thread pid %d\n",getpid()); while(s32f2vothreadflag) { if(HI_FALSE == frameinfo.value) { ret = HI_VDEC_Receive(parg->ChanID, &frameinfo, NULL, bBlock); } else { ret = HI_SUCCESS; } if (HI_SUCCESS == ret && frameinfo.value) { status = AVSYNC_Video_CHECK((HI_U32)frameinfo.pts); switch(status) { case VIDEO_OUTSYNC_SLOW: //printf("\nOUTSYNC_SLOW:don't know how to do yet!\n"); case VIDEO_SLIGHT_SLOW: /*尝试丢弃该帧*/ if(0 == frame_discard_interval_count) { HI_VDEC_ReleaseVideoBuf(parg->ChanID, &frameinfo); frameinfo.value = HI_FALSE; frame_discard_interval_count = MIN_FRAME_DISCARD_INTERVAL; printf("+");fflush(stdout); break; } /*否则按正常帧处理*/ case VIDEO_SYNC: /*直接送vo,如果失败,下次判断*/ ret = HI_VO_SendData(VO_CHN0, &frameinfo); if(HI_SUCCESS == ret) { frameinfo.value = HI_FALSE; if(0 != frame_discard_interval_count) frame_discard_interval_count--; } break; case VIDEO_OUTSYNC_QUICK: //printf("\OUTSYNC_QUICK:don't know how to do yet!\n"); case VIDEO_SLIGHT_QUICK: /*不送该帧*/ printf("-");fflush(stdout); break; default: printf("\ncan't go there!\n"); abort(); break; }#if 0 /*VO will release the data, user not need to care it. if the data isn't send to VO, user need call HI_VDEC_ReleaseVideoBuf to release buffer*/ ret = HI_VO_SendData(VO_CHN0, &frameinfo); if(HI_SUCCESS != ret) { /*if send vo failed , discard this frame*/ HI_VDEC_ReleaseVideoBuf(parg->ChanID, &frameinfo); }#endif } usleep(5); } pthread_exit(NULL);}void AVSYNC_Frame2Vo_Start(VDEC_CHN ChanID){ VDEC_THTREAD_ARGS arg; s32f2vothreadflag = 1; arg.ChanID = ChanID; /*start thread to receive frame, and send it to vo*/ pthread_create(&thread_frame2vo, NULL, frame2vo_thread, &arg);}void AVSYNC_Frame2Vo_Stop(){ s32f2vothreadflag = 0; pthread_join(thread_frame2vo, NULL); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -