📄 ffplay.c
字号:
int y, u, v, a, u1, v1, a1, w, h; uint8_t *lum, *cb, *cr; const uint8_t *p; const uint32_t *pal; int dstx, dsty, dstw, dsth; dstx = FFMIN(FFMAX(rect->x, 0), imgw); dstw = FFMIN(FFMAX(rect->w, 0), imgw - dstx); dsty = FFMIN(FFMAX(rect->y, 0), imgh); dsth = FFMIN(FFMAX(rect->h, 0), imgh - dsty); lum = dst->data[0] + dsty * dst->linesize[0]; cb = dst->data[1] + (dsty >> 1) * dst->linesize[1]; cr = dst->data[2] + (dsty >> 1) * dst->linesize[2]; width2 = (dstw + 1) >> 1; skip2 = dstx >> 1; wrap = dst->linesize[0]; wrap3 = rect->linesize; p = rect->bitmap; pal = rect->rgba_palette; /* Now in YCrCb! */ if (dsty & 1) { lum += dstx; cb += skip2; cr += skip2; if (dstx & 1) { YUVA_IN(y, u, v, a, p, pal); lum[0] = ALPHA_BLEND(a, lum[0], y, 0); cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0); cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0); cb++; cr++; lum++; p += BPP; } for(w = dstw - (dstx & 1); w >= 2; w -= 2) { YUVA_IN(y, u, v, a, p, pal); u1 = u; v1 = v; a1 = a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); YUVA_IN(y, u, v, a, p + BPP, pal); u1 += u; v1 += v; a1 += a; lum[1] = ALPHA_BLEND(a, lum[1], y, 0); cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1); cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1); cb++; cr++; p += 2 * BPP; lum += 2; } if (w) { YUVA_IN(y, u, v, a, p, pal); lum[0] = ALPHA_BLEND(a, lum[0], y, 0); cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0); cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0); } p += wrap3 + (wrap3 - dstw * BPP); lum += wrap + (wrap - dstw - dstx); cb += dst->linesize[1] - width2 - skip2; cr += dst->linesize[2] - width2 - skip2; } for(h = dsth - (dsty & 1); h >= 2; h -= 2) { lum += dstx; cb += skip2; cr += skip2; if (dstx & 1) { YUVA_IN(y, u, v, a, p, pal); u1 = u; v1 = v; a1 = a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); p += wrap3; lum += wrap; YUVA_IN(y, u, v, a, p, pal); u1 += u; v1 += v; a1 += a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1); cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1); cb++; cr++; p += -wrap3 + BPP; lum += -wrap + 1; } for(w = dstw - (dstx & 1); w >= 2; w -= 2) { YUVA_IN(y, u, v, a, p, pal); u1 = u; v1 = v; a1 = a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); YUVA_IN(y, u, v, a, p, pal); u1 += u; v1 += v; a1 += a; lum[1] = ALPHA_BLEND(a, lum[1], y, 0); p += wrap3; lum += wrap; YUVA_IN(y, u, v, a, p, pal); u1 += u; v1 += v; a1 += a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); YUVA_IN(y, u, v, a, p, pal); u1 += u; v1 += v; a1 += a; lum[1] = ALPHA_BLEND(a, lum[1], y, 0); cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 2); cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 2); cb++; cr++; p += -wrap3 + 2 * BPP; lum += -wrap + 2; } if (w) { YUVA_IN(y, u, v, a, p, pal); u1 = u; v1 = v; a1 = a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); p += wrap3; lum += wrap; YUVA_IN(y, u, v, a, p, pal); u1 += u; v1 += v; a1 += a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u1, 1); cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v1, 1); cb++; cr++; p += -wrap3 + BPP; lum += -wrap + 1; } p += wrap3 + (wrap3 - dstw * BPP); lum += wrap + (wrap - dstw - dstx); cb += dst->linesize[1] - width2 - skip2; cr += dst->linesize[2] - width2 - skip2; } /* handle odd height */ if (h) { lum += dstx; cb += skip2; cr += skip2; if (dstx & 1) { YUVA_IN(y, u, v, a, p, pal); lum[0] = ALPHA_BLEND(a, lum[0], y, 0); cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0); cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0); cb++; cr++; lum++; p += BPP; } for(w = dstw - (dstx & 1); w >= 2; w -= 2) { YUVA_IN(y, u, v, a, p, pal); u1 = u; v1 = v; a1 = a; lum[0] = ALPHA_BLEND(a, lum[0], y, 0); YUVA_IN(y, u, v, a, p + BPP, pal); u1 += u; v1 += v; a1 += a; lum[1] = ALPHA_BLEND(a, lum[1], y, 0); cb[0] = ALPHA_BLEND(a1 >> 2, cb[0], u, 1); cr[0] = ALPHA_BLEND(a1 >> 2, cr[0], v, 1); cb++; cr++; p += 2 * BPP; lum += 2; } if (w) { YUVA_IN(y, u, v, a, p, pal); lum[0] = ALPHA_BLEND(a, lum[0], y, 0); cb[0] = ALPHA_BLEND(a >> 2, cb[0], u, 0); cr[0] = ALPHA_BLEND(a >> 2, cr[0], v, 0); } }}static void free_subpicture(SubPicture *sp){ int i; for (i = 0; i < sp->sub.num_rects; i++) { av_free(sp->sub.rects[i].bitmap); av_free(sp->sub.rects[i].rgba_palette); } av_free(sp->sub.rects); memset(&sp->sub, 0, sizeof(AVSubtitle));}static void video_image_display(VideoState *is){ VideoPicture *vp; SubPicture *sp; AVPicture pict; float aspect_ratio; int width, height, x, y; SDL_Rect rect; int i; vp = &is->pictq[is->pictq_rindex]; if (vp->bmp) { /* XXX: use variable in the frame */ if (is->video_st->codec->sample_aspect_ratio.num == 0) aspect_ratio = 0; else aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio) * is->video_st->codec->width / is->video_st->codec->height;; if (aspect_ratio <= 0.0) aspect_ratio = (float)is->video_st->codec->width / (float)is->video_st->codec->height; /* if an active format is indicated, then it overrides the mpeg format */#if 0 if (is->video_st->codec->dtg_active_format != is->dtg_active_format) { is->dtg_active_format = is->video_st->codec->dtg_active_format; printf("dtg_active_format=%d\n", is->dtg_active_format); }#endif#if 0 switch(is->video_st->codec->dtg_active_format) { case FF_DTG_AFD_SAME: default: /* nothing to do */ break; case FF_DTG_AFD_4_3: aspect_ratio = 4.0 / 3.0; break; case FF_DTG_AFD_16_9: aspect_ratio = 16.0 / 9.0; break; case FF_DTG_AFD_14_9: aspect_ratio = 14.0 / 9.0; break; case FF_DTG_AFD_4_3_SP_14_9: aspect_ratio = 14.0 / 9.0; break; case FF_DTG_AFD_16_9_SP_14_9: aspect_ratio = 14.0 / 9.0; break; case FF_DTG_AFD_SP_4_3: aspect_ratio = 4.0 / 3.0; break; }#endif if (is->subtitle_st) { if (is->subpq_size > 0) { sp = &is->subpq[is->subpq_rindex]; if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) { SDL_LockYUVOverlay (vp->bmp); pict.data[0] = vp->bmp->pixels[0]; pict.data[1] = vp->bmp->pixels[2]; pict.data[2] = vp->bmp->pixels[1]; pict.linesize[0] = vp->bmp->pitches[0]; pict.linesize[1] = vp->bmp->pitches[2]; pict.linesize[2] = vp->bmp->pitches[1]; for (i = 0; i < sp->sub.num_rects; i++) blend_subrect(&pict, &sp->sub.rects[i], vp->bmp->w, vp->bmp->h); SDL_UnlockYUVOverlay (vp->bmp); } } } /* XXX: we suppose the screen has a 1.0 pixel ratio */ height = is->height; width = ((int)rint(height * aspect_ratio)) & -3; if (width > is->width) { width = is->width; height = ((int)rint(width / aspect_ratio)) & -3; } x = (is->width - width) / 2; y = (is->height - height) / 2; if (!is->no_background) { /* fill the background */ // fill_border(is, x, y, width, height, QERGB(0x00, 0x00, 0x00)); } else { is->no_background = 0; } rect.x = is->xleft + x; rect.y = is->ytop + y; rect.w = width; rect.h = height; SDL_DisplayYUVOverlay(vp->bmp, &rect); } else {#if 0 fill_rectangle(screen, is->xleft, is->ytop, is->width, is->height, QERGB(0x00, 0x00, 0x00));#endif }}static inline int compute_mod(int a, int b){ a = a % b; if (a >= 0) return a; else return a + b;}static void video_audio_display(VideoState *s){ int i, i_start, x, y1, y, ys, delay, n, nb_display_channels; int ch, channels, h, h2, bgcolor, fgcolor; int16_t time_diff; /* compute display index : center on currently output samples */ channels = s->audio_st->codec->channels; nb_display_channels = channels; if (!s->paused) { n = 2 * channels; delay = audio_write_get_buf_size(s); delay /= n; /* to be more precise, we take into account the time spent since the last buffer computation */ if (audio_callback_time) { time_diff = av_gettime() - audio_callback_time; delay += (time_diff * s->audio_st->codec->sample_rate) / 1000000; } delay -= s->width / 2; if (delay < s->width) delay = s->width; i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE); h= INT_MIN; for(i=0; i<1000; i+=channels){ int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE; int a= s->sample_array[idx]; int b= s->sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE]; int c= s->sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE]; int d= s->sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE]; int score= a-d; if(h<score && (b^c)<0){ h= score; i_start= idx; } } s->last_i_start = i_start; } else { i_start = s->last_i_start; } bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00); fill_rectangle(screen, s->xleft, s->ytop, s->width, s->height, bgcolor); fgcolor = SDL_MapRGB(screen->format, 0xff, 0xff, 0xff); /* total height for one channel */ h = s->height / nb_display_channels; /* graph height / 2 */ h2 = (h * 9) / 20; for(ch = 0;ch < nb_display_channels; ch++) { i = i_start + ch; y1 = s->ytop + ch * h + (h / 2); /* position of center line */ for(x = 0; x < s->width; x++) { y = (s->sample_array[i] * h2) >> 15; if (y < 0) { y = -y; ys = y1 - y; } else { ys = y1; } fill_rectangle(screen, s->xleft + x, ys, 1, y, fgcolor); i += channels; if (i >= SAMPLE_ARRAY_SIZE) i -= SAMPLE_ARRAY_SIZE; } } fgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0xff); for(ch = 1;ch < nb_display_channels; ch++) { y = s->ytop + ch * h; fill_rectangle(screen, s->xleft, y, s->width, 1, fgcolor); } SDL_UpdateRect(screen, s->xleft, s->ytop, s->width, s->height);}static int video_open(VideoState *is){ int flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; int w,h; if(is_full_screen) flags |= SDL_FULLSCREEN; else flags |= SDL_RESIZABLE; if (is_full_screen && fs_screen_width) { w = fs_screen_width; h = fs_screen_height; } else if(!is_full_screen && screen_width){ w = screen_width;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -