首页 > 代码库 > ffplay on SDL2 之二

ffplay on SDL2 之二

本阶段完成把ffplay移植到sdl2, PC上基本测试:图片,视频OK。

api 1.2
SDL_Surface *screen;
 screen = SDL_SetVideoMode(w, h, 0, flags);
 SDL_WM_SetCaption
 SDL_FillRect
 screen->format, w, h
 SDL_UpdateRect
 
SDL_Overlay *bmp;
SDL_CreateYUVOverlay(screen);
SDL_LockYUVOverlay
bmp->pixels[i],pitches[i] //video_thread-->queue_picture; video_image_display-->blend_subrect
//video_refresh-->video_display-->video_image_display
SDL_DisplayYUVOverlay

api 2.0
SDL_Window *win;
  SDL_CreateWindow, SDL_SetWindowSize, SDL_SetWindowTitle,
  SDL_GetWindowSurface(win)->format,w,h
SDL_Renderer *render;
  SDL_CreateRenderer(win), SDL_RenderClear, SDL_RenderCopy, SDL_RenderPresent
SDL_Texture *texture;
  SDL_CreateTexture(render), SDL_LockTexture/transform/SDL_UnlockTexture, SDL_UpdateYUVTexture,
 
问题
Q. YUV格式转换。
A. LockTexture得到的pixel/pitch指向Y。YUV是紧凑排列,没有align,从而可推出U,V的data/pitch。
Q. ffplay a.png输出也是yuv420p ?
A. 是的。在configure_video_filters()设置filt_out的"pix_fmts"。调了vf_scale.c?
avfilter_graph_config-->
graph_config_formats-->query_formats-->"auto-inserted scaler %d"
SDL_Window -- physical pixels you see, 对应多个
SDL_Renderer -- store settings and context,对应多个
SDL_Texture -- resource, element。

Q: texture放到另一个视图显示。
main view -- composited layers
layer view -- individual layer

A:src = http://www.mamicode.com/SDL_GetWindowSurface(src_win);
fmt = SDL_GetWindowPixelFormat(src_win);
SDL_RenderReadPixels(src_render, 0, fmt, src->pixels, src->pitch);
SDL_UpdateTexture(dst_render, src->pixels, src->pitch);

Q: resize,blend,colorkey?
A: SDL_RenderSetScale(sx, sy)/SDL_RenderCopy with diff rect, 
   SDL_SetTextureAlphaMod(a)/SDL_SetRenderDrawBlendMode(blend),

Q: 绿边处理duplicate_right_border_pixels().
A: SDL2是否还存在该问题? 
render to texture
direct pixels operation

Q: 使用SDL2_Image,
SDL_Surface *s = IMG_Load("in.png");
SDL_Texture *t = SDL_CreateTextureFromSurface(render, s);
SDL_FreeSurface(s);
能不能直接操作纹理?
A: [1]的例子是针对ARGB,使用SDL_UpdateTexture(t,rect, pixels, pitch);
写像素,如果想读像素呢?
SDL_LockTexture(t, rect, &pixels, &pitch);
提供一个只写的像素指针。
而SDL_LockSurface(s)可以对s->pixels进行读写。
针对render的像素读取:
SDL_RenderReadPixels(r, rect, fmt, pixels, pitch);

Q: 因为视频宽高比和窗口宽高不同,四周留黑边,要fill_border-->fill_rectangle-->SDL_Fill/UpdateRect
A: SDL_SetRenderDrawColor(render, a,r,g,b);
   4次SDL_RenderFillRect(render, rect);
   1次SDL_RenderPresent(render);
跟据SDL2里面的注记,SDL_RenderPresent(render) 把backbuffer显示之后,
backbuffer不再有效,因此建议在新的绘制开始前SDL_RenderClear(),即使每个像素都重写。
于是fill_border代码完全可以省略。

改造计划
====
有人说LockTexture比UpdateYUVTexture慢。
那这里引入Lock是为了直接修改像素,字幕混合blend_subrect用的。
我们不必Lock,只要把字幕当成texture即可!
其实sdl2底层对YUV的处理也是用三个纹理来搞的。
screen --> win
bmp --> texture
blend_subrect --> SDL_UpdateYUVTexture(t,rect, Ydata, Ypitch,...);
剩下的事情是考虑graphics memory 有多大,
VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE配置多少。

调试
====
Q. SDL_CreateRenderer flag =SDL_RENDERER_SOFTWARE 没死, 0死在glEnable()。
A. 只能在主线程render。
把 
video_thread-->queue_picture-->SDL_UpdateYUVTexture_REAL
移到主线程:
refresh_loop_wait_event-->video_refresh-->video_display-->video_image_display
实际上为了简单起见,在alloc_picture时就Update。

代码放在

https://github.com/DeYangLiu/ffmpeg-streaming/blob/master/ffplay2.c


TODO
全屏后左右两边是红边。

测试带字幕的视频。

ref
====
[1] http://www.programmersranch.com/2014/02/sdl2-pixel-drawing.html


ffplay on SDL2 之二