📄 videoout.c
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "mediastreamer2/msfilter.h"#include "mediastreamer2/msvideo.h"#include "mediastreamer2/msvideoout.h"#ifndef WIN32#include <SDL/SDL.h>#include <SDL/SDL_video.h>static bool_t sdl_initialized=FALSE;static SDL_Surface *sdl_screen=0;static SDL_Overlay * sdl_create_window(int w, int h){ SDL_Overlay *lay; sdl_screen = SDL_SetVideoMode(w,h, 0,SDL_SWSURFACE); if (sdl_screen == NULL ) { ms_warning("Couldn't set video mode: %s\n", SDL_GetError()); return NULL; } if (sdl_screen->flags & SDL_HWSURFACE) ms_message("SDL surface created in hardware"); SDL_WM_SetCaption("Linphone Video", NULL); ms_message("Using yuv overlay."); lay=SDL_CreateYUVOverlay(w,h,SDL_YV12_OVERLAY,sdl_screen); if (lay==NULL){ ms_warning("Couldn't create yuv overlay: %s\n", SDL_GetError()); return NULL; }else{ if (lay->hw_overlay) ms_message("YUV overlay using hardware acceleration."); } return lay;}static bool_t sdl_display_init(MSDisplay *obj, MSFrameBuffer *fbuf){ SDL_Overlay *lay; if (!sdl_initialized){ /* Initialize the SDL library */ if( SDL_Init(SDL_INIT_VIDEO) < 0 ) { ms_error("Couldn't initialize SDL: %s", SDL_GetError()); return FALSE; } /* Clean up on exit */ atexit(SDL_Quit); sdl_initialized=TRUE; } if (obj->data!=NULL) SDL_FreeYUVOverlay((SDL_Overlay*)obj->data); lay=sdl_create_window(fbuf->w, fbuf->h); if (lay){ fbuf->y=lay->pixels[0]; fbuf->u=lay->pixels[2]; fbuf->v=lay->pixels[1]; obj->data=lay; return TRUE; } return FALSE;}static void sdl_display_lock(MSDisplay *obj){ SDL_LockYUVOverlay((SDL_Overlay*)obj->data);}static void sdl_display_unlock(MSDisplay *obj){ SDL_Overlay *lay=(SDL_Overlay*)obj->data; SDL_UnlockYUVOverlay(lay);}static void sdl_display_update(MSDisplay *obj){ SDL_Rect rect; SDL_Overlay *lay=(SDL_Overlay*)obj->data; rect.x=0; rect.y=0; rect.w=lay->w; rect.h=lay->h; SDL_DisplayYUVOverlay(lay,&rect);}static void sdl_display_uninit(MSDisplay *obj){ SDL_Overlay *lay=(SDL_Overlay*)obj->data; if (lay==NULL) return; if (lay!=NULL) SDL_FreeYUVOverlay(lay); if (sdl_screen!=NULL){ SDL_FreeSurface(sdl_screen); sdl_screen=NULL; }}MSDisplayDesc ms_sdl_display_desc={ .init=sdl_display_init, .lock=sdl_display_lock, .unlock=sdl_display_unlock, .update=sdl_display_update, .uninit=sdl_display_uninit};#else#include <Vfw.h>typedef struct _WinDisplay{ HWND window; HDRAWDIB ddh; MSFrameBuffer fb; uint8_t *rgb; int rgb_len;}WinDisplay;static LRESULT CALLBACK window_proc( HWND hwnd, // handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam) // second message parameter{ switch(uMsg){ case WM_DESTROY: break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0;}static HWND create_window(int w, int h){ WNDCLASS wc; HINSTANCE hInstance = GetModuleHandle(NULL); HWND hwnd; RECT rect; wc.style = 0 ; wc.lpfnWndProc = window_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = NULL; wc.hIcon = NULL; wc.hCursor = LoadCursor(hInstance, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "Video Window"; if(!RegisterClass(&wc)) { /* already registred! */ } rect.left=100; rect.top=100; rect.right=rect.left+w; rect.bottom=rect.top+h; if (!AdjustWindowRect(&rect,WS_CAPTION ,FALSE)){ ms_error("AdjustWindowRect failed."); } ms_message("AdjustWindowRect: %li,%li %li,%li",rect.left,rect.top,rect.right,rect.bottom); hwnd=CreateWindow("Video Window", "Video window", WS_OVERLAPPEDWINDOW|WS_VISIBLE , CW_USEDEFAULT, CW_USEDEFAULT, rect.right-rect.left,rect.bottom-rect.top, NULL, NULL, hInstance, NULL); if (hwnd==NULL){ ms_error("Fail to create video window"); } return hwnd;}static bool_t win_display_init(MSDisplay *obj, MSFrameBuffer *fbuf){ WinDisplay *wd=(WinDisplay*)obj->data; int ysize,usize; if (wd!=NULL) { if (wd->window && !obj->window_id) DestroyWindow(wd->window); if (wd->ddh) DrawDibClose(wd->ddh); wd->ddh=NULL; if (wd->fb.y) ms_free(wd->fb.y); wd->fb.y=NULL; wd->fb.u=NULL; wd->fb.v=NULL; if (wd->rgb) ms_free(wd->rgb); wd->rgb=NULL; wd->rgb_len=0; wd->window=NULL; } else wd=(WinDisplay*)ms_new0(WinDisplay,1); obj->data=wd; wd->fb.w=fbuf->w; wd->fb.h=fbuf->h; wd->window=(HWND)obj->window_id; if (wd->window==NULL) { wd->window=create_window(wd->fb.w,wd->fb.h); } if (wd->window==NULL) return FALSE; if (wd->ddh==NULL) wd->ddh=DrawDibOpen(); if (wd->ddh==NULL){ ms_error("DrawDibOpen() failed."); return FALSE; } /*allocate yuv and rgb buffers*/ if (wd->fb.y) ms_free(wd->fb.y); if (wd->rgb) ms_free(wd->rgb); ysize=wd->fb.w*wd->fb.h; usize=ysize/4; fbuf->y=wd->fb.y=(uint8_t*)ms_malloc0(ysize+2*usize); fbuf->u=wd->fb.u=wd->fb.y+ysize; fbuf->v=wd->fb.v=wd->fb.u+usize; wd->rgb_len=ysize*3; wd->rgb=(uint8_t*)ms_malloc0(wd->rgb_len); return TRUE;}typedef struct rgb{ uint8_t r,g,b;} rgb_t;typedef struct yuv{ uint8_t y,u,v;} yuv_t;#if 1static inline uint8_t ms_clip_uint8(int a){ if (a&(~255)) return (-a)>>31; else return a;}/* R = Y + 1.140V G = Y - 0.395U - 0.581V B = Y + 2.032U or R = Y + 1.403V' G = Y - 0.344U' - 0.714V' B = Y + 1.770U'*/static void yuv_to_rgb_pixel(const yuv_t *yuv, rgb_t *rgb){ int c,d,e; c=yuv->y-16; e=yuv->u-128; d=yuv->v-128; rgb->r=ms_clip_uint8((float)c + 1.403*e); rgb->g=ms_clip_uint8((float)c - 0.344*d - 0.714*e ); rgb->b=ms_clip_uint8((float)c + 1.77*d );}static void yuv420p_to_rgb(uint8_t *yuv, uint8_t *rgb, int w, int h){ int i,j,k,l; yuv_t yuv_pix; uint8_t *y,*u,*v; int upos; int ypos; y=yuv; u=yuv + w*h; v=u + (w*h/4); for(i=h-1,k=(h/2)-1;i>=0;i-=2,--k){ ypos=i*w; upos=k*w/2; for(j=0,l=0;j<w;j+=2,++l){ yuv_pix.y=y[ypos+j]; yuv_pix.u=u[upos+l]; yuv_pix.v=v[upos+l]; yuv_to_rgb_pixel(&yuv_pix,(rgb_t*)rgb); rgb+=3; yuv_pix.y=y[ypos+j+1]; yuv_to_rgb_pixel(&yuv_pix,(rgb_t*)rgb); rgb+=3; } ypos=(i-1)*w; for(j=0,l=0;j<w;j+=2,++l){ yuv_pix.y=y[ypos+j]; yuv_pix.u=u[upos+l]; yuv_pix.v=v[upos+l]; yuv_to_rgb_pixel(&yuv_pix,(rgb_t*)rgb); rgb+=3; yuv_pix.y=y[ypos+j+1]; yuv_to_rgb_pixel(&yuv_pix,(rgb_t*)rgb); rgb+=3; } }}#else#include <ffmpeg/avcodec.h>static void yuv420p_to_rgb(uint8_t *yuv, uint8_t *rgb, int w, int h){ AVPicture src,dst; avpicture_fill(&dst,rgb,PIX_FMT_RGB24,w,h); avpicture_fill(&src,yuv,PIX_FMT_YUV420P,w,h); if (img_convert(&dst,PIX_FMT_RGB24,&src,PIX_FMT_YUV420P,w,h)<0){ ms_error("videout.c: img_convert failed !"); }}#endifstatic void win_display_update(MSDisplay *obj){ WinDisplay *wd=(WinDisplay*)obj->data; HDC hdc; BITMAPINFOHEADER bi; bool_t ret; if (wd->window==NULL) return; hdc=GetDC(wd->window); if (hdc==NULL) { ms_error("Could not get window dc"); return; } yuv420p_to_rgb(wd->fb.y, wd->rgb, wd->fb.w, wd->fb.h); memset(&bi,0,sizeof(bi)); bi.biSize=sizeof(bi); /* bi.biWidth=wd->fb.w; bi.biHeight=wd->fb.h; bi.biPlanes=3; bi.biBitCount=12; bi.biCompression=MAKEFOURCC('I','4','2','0'); bi.biSizeImage=(wd->fb.w*wd->fb.h*3)/2; */ bi.biWidth=wd->fb.w; bi.biHeight=wd->fb.h; bi.biPlanes=1; bi.biBitCount=24; bi.biCompression=BI_RGB; bi.biSizeImage=wd->rgb_len; ret=DrawDibDraw(wd->ddh,hdc,0,0,wd->fb.w,wd->fb.h,&bi,wd->rgb, 0,0,wd->fb.w,wd->fb.h,0); if (!ret) ms_error("DrawDibDraw failed.");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -