響應(yīng)式pos機(jī)源碼,ffplay源碼分析06

 新聞資訊2  |   2023-06-11 12:39  |  投稿人:pos機(jī)之家

網(wǎng)上有很多關(guān)于響應(yīng)式pos機(jī)源碼,ffplay源碼分析06 的知識(shí),也有很多人為大家解答關(guān)于響應(yīng)式pos機(jī)源碼的問(wèn)題,今天pos機(jī)之家(m.afbey.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來(lái)看下吧!

本文目錄一覽:

1、響應(yīng)式pos機(jī)源碼

響應(yīng)式pos機(jī)源碼

初始化

View Code

初始化主要在main里面,主要做了如下幾件事:

1. SDL_Init,主要是SDL_INIT_VIDEO的?持2. SDL_CreateWindow,創(chuàng)建主窗?3. SDL_CreateRender,基于主窗?創(chuàng)建renderer,?于渲染輸出。4. stream_open5. event_loop,播放控制事件響應(yīng)循環(huán),但也負(fù)責(zé)了video顯示輸出。

video_refresh()

/* called to display each frame *//* 非暫?;驈?qiáng)制刷新的時(shí)候,循環(huán)調(diào)用video_refresh */static void video_refresh(void *opaque, double *remaining_time){ VideoState *is = opaque; double time; Frame *sp, *sp2; if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime) check_external_clock_speed(is); if (!display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) { time = av_gettime_relative() / 1000000.0; if (is->force_refresh || is->last_vis_time + rdftspeed < time) { video_display(is); is->last_vis_time = time; } *remaining_time = FFMIN(*remaining_time, is->last_vis_time + rdftspeed - time); } if (is->video_st) {retry: if (frame_queue_nb_remaining(&is->pictq) == 0) {// 幀隊(duì)列是否為空 // nothing to do, no picture to display in the queue // 什么都不做,隊(duì)列中沒(méi)有圖像可顯示 } else { // 重點(diǎn)是音視頻同步 double last_duration, duration, delay; Frame *vp, *lastvp; /* dequeue the picture */ // 從隊(duì)列取出上一個(gè)Frame lastvp = frame_queue_peek_last(&is->pictq);//讀取上一幀 vp = frame_queue_peek(&is->pictq); // 讀取待顯示幀 // lastvp 上一幀(正在顯示的幀) // vp 等待顯示的幀 if (vp->serial != is->videoq.serial) { // 如果不是最新的播放序列,則將其出隊(duì)列,以盡快讀取最新序列的幀 frame_queue_next(&is->pictq); goto retry; } if (lastvp->serial != vp->serial) { // 新的播放序列重置當(dāng)前時(shí)間 is->frame_timer = av_gettime_relative() / 1000000.0; } if (is->paused) { goto display; printf("視頻暫停is->paused"); } /* compute nominal last_duration */ //lastvp上一幀,vp當(dāng)前幀 ,nextvp下一幀 //last_duration 計(jì)算上一幀應(yīng)顯示的時(shí)長(zhǎng) last_duration = vp_duration(is, lastvp, vp); // 經(jīng)過(guò)compute_target_delay方法,計(jì)算出待顯示幀vp需要等待的時(shí)間 // 如果以video同步,則delay直接等于last_duration。 // 如果以audio或外部時(shí)鐘同步,則需要比對(duì)主時(shí)鐘調(diào)整待顯示幀vp要等待的時(shí)間。 delay = compute_target_delay(last_duration, is); time= av_gettime_relative()/1000000.0; // is->frame_timer 實(shí)際上就是上一幀lastvp的播放時(shí)間, // is->frame_timer + delay 是待顯示幀vp該播放的時(shí)間 if (time < is->frame_timer + delay) { //判斷是否繼續(xù)顯示上一幀 // 當(dāng)前系統(tǒng)時(shí)刻還未到達(dá)上一幀的結(jié)束時(shí)刻,那么還應(yīng)該繼續(xù)顯示上一幀。 // 計(jì)算出最小等待時(shí)間 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time); goto display; } // 走到這一步,說(shuō)明已經(jīng)到了或過(guò)了該顯示的時(shí)間,待顯示幀vp的狀態(tài)變更為當(dāng)前要顯示的幀 is->frame_timer += delay; // 更新當(dāng)前幀播放的時(shí)間 if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX) { is->frame_timer = time; //如果和系統(tǒng)時(shí)間差距太大,就糾正為系統(tǒng)時(shí)間 } SDL_LockMutex(is->pictq.mutex); if (!isnan(vp->pts)) update_video_pts(is, vp->pts, vp->pos, vp->serial); // 更新video時(shí)鐘 SDL_UnlockMutex(is->pictq.mutex); //丟幀邏輯 if (frame_queue_nb_remaining(&is->pictq) > 1) {//有nextvp才會(huì)檢測(cè)是否該丟幀 Frame *nextvp = frame_queue_peek_next(&is->pictq); duration = vp_duration(is, vp, nextvp); if(!is->step // 非逐幀模式才檢測(cè)是否需要丟幀 is->step==1 為逐幀播放 && (framedrop>0 || // cpu解幀過(guò)慢 (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) // 非視頻同步方式 && time > is->frame_timer + duration // 確實(shí)落后了一幀數(shù)據(jù) ) { printf("%s(%d) dif:%lfs, drop frame\", __FUNCTION__, __LINE__, (is->frame_timer + duration) - time); is->frame_drops_late++; // 統(tǒng)計(jì)丟幀情況 frame_queue_next(&is->pictq); // 這里實(shí)現(xiàn)真正的丟幀 //(這里不能直接while丟幀,因?yàn)楹芸赡躠udio clock重新對(duì)時(shí)了,這樣delay值需要重新計(jì)算) goto retry; //回到函數(shù)開(kāi)始位置,繼續(xù)重試 } } if (is->subtitle_st) { while (frame_queue_nb_remaining(&is->subpq) > 0) { sp = frame_queue_peek(&is->subpq); if (frame_queue_nb_remaining(&is->subpq) > 1) sp2 = frame_queue_peek_next(&is->subpq); else sp2 = NULL; if (sp->serial != is->subtitleq.serial || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000))) || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000)))) { if (sp->uploaded) { int i; for (i = 0; i < sp->sub.num_rects; i++) { AVSubtitleRect *sub_rect = sp->sub.rects[i]; uint8_t *pixels; int pitch, j; if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) { for (j = 0; j < sub_rect->h; j++, pixels += pitch) memset(pixels, 0, sub_rect->w << 2); SDL_UnlockTexture(is->sub_texture); } } } frame_queue_next(&is->subpq); } else { break; } } } frame_queue_next(&is->pictq); // 當(dāng)前vp幀出隊(duì)列 is->force_refresh = 1; /* 說(shuō)明需要刷新視頻幀 */ if (is->step && !is->paused) stream_toggle_pause(is); }display: /* display picture */ if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown) video_display(is); // 重點(diǎn)是顯示 } is->force_refresh = 0; if (show_status) { static int64_t last_time; int64_t cur_time; int aqsize, vqsize, sqsize; double av_diff; cur_time = av_gettime_relative(); if (!last_time || (cur_time - last_time) >= 30000) { aqsize = 0; vqsize = 0; sqsize = 0; if (is->audio_st) aqsize = is->audioq.size; if (is->video_st) vqsize = is->videoq.size; if (is->subtitle_st) sqsize = is->subtitleq.size; av_diff = 0; if (is->audio_st && is->video_st) av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk); else if (is->video_st) av_diff = get_master_clock(is) - get_clock(&is->vidclk); else if (is->audio_st) av_diff = get_master_clock(is) - get_clock(&is->audclk); av_log(NULL, AV_LOG_INFO, "%7.2f %s:%7.3f fd=M aq=]KB vq=]KB sq=]B f=%"PRId64"/%"PRId64" \", get_master_clock(is), (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")), av_diff, is->frame_drops_early + is->frame_drops_late, aqsize / 1024, vqsize / 1024, sqsize, is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0, is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0); fflush(stdout); last_time = cur_time; } }}

video_image_display()

static void video_image_display(VideoState *is){ Frame *vp; Frame *sp = NULL; SDL_Rect rect; // keep_last的作用就出來(lái)了,我們是有調(diào)用frame_queue_next, 但最近出隊(duì)列的幀并沒(méi)有真正銷毀 // 所以這里可以讀取出來(lái)顯示 vp = frame_queue_peek_last(&is->pictq); if (is->subtitle_st) { if (frame_queue_nb_remaining(&is->subpq) > 0) { sp = frame_queue_peek(&is->subpq); if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) { if (!sp->uploaded) { uint8_t* pixels[4]; int pitch[4]; int i; if (!sp->width="360px",height="auto" />

convert_ctx = sws_getCachedContext(is->sub_convert_ctx, sub_rect->w, sub_rect->h, AV_PIX_FMT_PAL8, sub_rect->w, sub_rect->h, AV_PIX_FMT_BGRA, 0, NULL, NULL, NULL); if (!is->sub_convert_ctx) { av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\"); return; } if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)pixels, pitch)) { sws_scale(is->sub_convert_ctx, (const uint8_t * const *)sub_rect->data, sub_rect->linesize, 0, sub_rect->h, pixels, pitch); SDL_UnlockTexture(is->sub_texture); } } sp->uploaded = 1; } } else sp = NULL; } } //將幀寬高按照sar最大適配到窗口,并通過(guò)rect返回視頻幀在窗口的顯示位置和寬高 calculate_display_rect(&rect, is->xleft, is->ytop, is->width="360px",height="auto" />

以上就是關(guān)于響應(yīng)式pos機(jī)源碼,ffplay源碼分析06 的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于響應(yīng)式pos機(jī)源碼的知識(shí),希望能夠幫助到大家!

轉(zhuǎn)發(fā)請(qǐng)帶上網(wǎng)址:http://m.afbey.com/newsone/66285.html

你可能會(huì)喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 babsan@163.com 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。