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

📄 avsync.c

📁 sample on embedded linux
💻 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 + -