Commit 884af01e authored by unknown's avatar unknown
Browse files

add external window support

parent 9a942e1e
......@@ -23,7 +23,8 @@ mediastreamer2_include_HEADERS= ice.h \
mswebcam.h \
dsptools.h \
msequalizer.h \
msspeexec.h
msspeexec.h \
msinterfaces.h
EXTRA_DIST=$(mediastreamer2_include_HEADERS)
......@@ -41,4 +41,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
MS_FILTER_METHOD(MSFilterVideoDisplayInterface,3,long)
/**Sets an external native window id where the video is to be drawn */
#define MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID \
MS_FILTER_METHOD(MSFilterVideoDisplayInterface,4,long)
#endif
......@@ -75,11 +75,11 @@ static void yuv2rgb_prepare(Yuv2RgbCtx *ctx, MSVideoSize src, MSVideoSize dst){
ctx->rgb=ms_malloc0(ctx->rgblen+dst.width);
}
/*
this function resizes the original pictures to the destination size and converts to rgb.
It takes care of reallocating a new SwsContext and rgb buffer if the source/destination sizes have
changed.
/*
this function resizes the original pictures to the destination size and converts to rgb.
It takes care of reallocating a new SwsContext and rgb buffer if the source/destination sizes have
changed.
*/
static void yuv2rgb_process(Yuv2RgbCtx *ctx, MSPicture *src, MSVideoSize dstsize, bool_t mirroring){
MSVideoSize srcsize;
......@@ -121,16 +121,17 @@ static void yuv2rgb_draw(Yuv2RgbCtx *ctx, HDRAWDIB ddh, HDC hdc, int dstx, int d
typedef struct _DDDisplay{
HWND window;
HDRAWDIB ddh;
HDRAWDIB ddh;
MSVideoSize wsize; /*the initial requested window size*/
MSVideoSize vsize; /*the video size received for main input*/
MSVideoSize lsize; /*the video size received for local display */
Yuv2RgbCtx mainview;
Yuv2RgbCtx locview;
Yuv2RgbCtx locview;
int corner;
bool_t need_repaint;
bool_t autofit;
bool_t mirroring;
bool_t own_window;
}DDDisplay;
static LRESULT CALLBACK window_proc(
......@@ -209,7 +210,7 @@ static HWND create_window(int w, int h)
}
static void dd_display_init(MSFilter *f){
DDDisplay *obj=(DDDisplay*)ms_new0(DDDisplay,1);
DDDisplay *obj=(DDDisplay*)ms_new0(DDDisplay,1);
obj->wsize.width=MS_VIDEO_SIZE_CIF_W;
obj->wsize.height=MS_VIDEO_SIZE_CIF_H;
obj->vsize.width=MS_VIDEO_SIZE_CIF_W;
......@@ -217,11 +218,12 @@ static void dd_display_init(MSFilter *f){
obj->lsize.width=MS_VIDEO_SIZE_CIF_W;
obj->lsize.height=MS_VIDEO_SIZE_CIF_H;
yuv2rgb_init(&obj->mainview);
yuv2rgb_init(&obj->locview);
yuv2rgb_init(&obj->locview);
obj->corner=0; /* bottom right*/
obj->need_repaint=FALSE;
obj->autofit=TRUE;
obj->mirroring=FALSE;
obj->own_window=TRUE;
f->data=obj;
}
......@@ -230,13 +232,14 @@ static void dd_display_prepare(MSFilter *f){
if (dd->window==NULL){
dd->window=create_window(dd->wsize.width,dd->wsize.height);
SetWindowLong(dd->window,GWL_USERDATA,(long)dd);
dd->ddh=DrawDibOpen();
}
if (dd->ddh==NULL)
dd->ddh=DrawDibOpen();
}
static void dd_display_unprepare(MSFilter *f){
DDDisplay *dd=(DDDisplay*)f->data;
if (dd->window!=NULL){
if (dd->own_window && dd->window!=NULL){
DestroyWindow(dd->window);
dd->window=NULL;
}
......@@ -275,20 +278,20 @@ static void center_with_ratio(MSVideoSize wsize, MSVideoSize vsize, MSRect *rect
rect->w=w;
rect->h=h;
}
#define LOCAL_BORDER_SIZE 2
#define LOCAL_POS_OFFSET 10
#define LOCAL_BORDER_SIZE 2
#define LOCAL_POS_OFFSET 10
static void compute_layout(MSVideoSize wsize, MSVideoSize vsize, MSVideoSize orig_psize, MSRect *mainrect, MSRect *localrect, int localrect_pos){
MSVideoSize psize;
center_with_ratio(wsize,vsize,mainrect);
center_with_ratio(wsize,vsize,mainrect);
if (localrect_pos!=-1){
psize.width=wsize.width*SCALE_FACTOR;
psize.height=wsize.height*SCALE_FACTOR;
center_with_ratio(psize,orig_psize,localrect);
localrect->x=wsize.width-localrect->w-LOCAL_POS_OFFSET;
localrect->y=wsize.height-localrect->h-LOCAL_POS_OFFSET;
localrect->y=wsize.height-localrect->h-LOCAL_POS_OFFSET;
}
/*
ms_message("Compute layout result for\nwindow size=%ix%i\nvideo orig size=%ix%i\nlocal size=%ix%i\nlocal orig size=%ix%i\n"
......@@ -300,13 +303,13 @@ static void compute_layout(MSVideoSize wsize, MSVideoSize vsize, MSVideoSize ori
}
static void draw_local_view_frame(HDC hdc, MSVideoSize wsize, MSRect localrect){
Rectangle(hdc, localrect.x-LOCAL_BORDER_SIZE, localrect.y-LOCAL_BORDER_SIZE,
Rectangle(hdc, localrect.x-LOCAL_BORDER_SIZE, localrect.y-LOCAL_BORDER_SIZE,
localrect.x+localrect.w+LOCAL_BORDER_SIZE, localrect.y+localrect.h+LOCAL_BORDER_SIZE);
}
/*
* Draws a background, that is the black rectangles at top, bottom or left right sides of the video display.
* It is normally invoked only when a full redraw is needed (notified by Windows).
/*
* Draws a background, that is the black rectangles at top, bottom or left right sides of the video display.
* It is normally invoked only when a full redraw is needed (notified by Windows).
*/
static void draw_background(HDC hdc, MSVideoSize wsize, MSRect mainrect){
HBRUSH brush;
......@@ -359,16 +362,16 @@ static void dd_display_process(MSFilter *f){
MSPicture mainpic;
MSPicture localpic;
mblk_t *main_im=NULL;
mblk_t *local_im=NULL;
HDC hdc2;
HBITMAP tmp_bmp=NULL;
HGDIOBJ old_object=NULL;
bool_t repainted=FALSE;
mblk_t *local_im=NULL;
HDC hdc2;
HBITMAP tmp_bmp=NULL;
HGDIOBJ old_object=NULL;
bool_t repainted=FALSE;
int corner=obj->corner;
GetClientRect(obj->window,&rect);
wsize.width=rect.right;
wsize.height=rect.bottom;
wsize.height=rect.bottom;
obj->wsize=wsize;
/*get most recent message and draw it*/
if (corner!=-1 && f->inputs[1]!=NULL && (local_im=ms_queue_peek_last(f->inputs[1]))!=NULL) {
......@@ -393,7 +396,7 @@ static void dd_display_process(MSFilter *f){
obj->vsize.width=mainpic.w;
obj->vsize.height=mainpic.h;
}
}
}
if (main_im!=NULL || local_im!=NULL || obj->need_repaint){
compute_layout(wsize,obj->vsize,obj->lsize,&mainrect,&localrect,corner);
......@@ -412,50 +415,50 @@ static void dd_display_process(MSFilter *f){
if (hdc==NULL) {
ms_error("Could not get window dc");
return;
}
/*handle the case where local view is disabled*/
if (corner==-1 && obj->locview.rgb!=NULL){
yuv2rgb_uninit(&obj->locview);
}
if (obj->locview.rgb==NULL){
/*One layer: we can draw directly on the displayed surface*/
}
/*handle the case where local view is disabled*/
if (corner==-1 && obj->locview.rgb!=NULL){
yuv2rgb_uninit(&obj->locview);
}
if (obj->locview.rgb==NULL){
/*One layer: we can draw directly on the displayed surface*/
hdc2=hdc;
}else{
/* in this case we need to stack several layers*/
/*Create a second DC and bitmap to draw to a buffer that will be blitted to screen
once all drawing is finished. This avoids some blinking while composing the image*/
hdc2=CreateCompatibleDC(hdc);
tmp_bmp=CreateCompatibleBitmap(hdc,wsize.width,wsize.height);
old_object = SelectObject(hdc2, tmp_bmp);
}
}else{
/* in this case we need to stack several layers*/
/*Create a second DC and bitmap to draw to a buffer that will be blitted to screen
once all drawing is finished. This avoids some blinking while composing the image*/
hdc2=CreateCompatibleDC(hdc);
tmp_bmp=CreateCompatibleBitmap(hdc,wsize.width,wsize.height);
old_object = SelectObject(hdc2, tmp_bmp);
}
if (obj->need_repaint){
draw_background(hdc2,wsize,mainrect);
draw_background(hdc2,wsize,mainrect);
repainted=TRUE;
obj->need_repaint=FALSE;
}
if (main_im!=NULL || obj->locview.rgb!=NULL){
}
if (main_im!=NULL || obj->locview.rgb!=NULL){
yuv2rgb_draw(&obj->mainview,obj->ddh,hdc2,mainrect.x,mainrect.y);
}
if (obj->locview.rgb!=NULL){
draw_local_view_frame(hdc2,wsize,localrect);
yuv2rgb_draw(&obj->locview,obj->ddh,hdc2,localrect.x,localrect.y);
}
if (hdc!=hdc2){
if (main_im==NULL && !repainted){
/* Blitting local rect only */
BitBlt(hdc,localrect.x-LOCAL_BORDER_SIZE,localrect.y-LOCAL_BORDER_SIZE,
localrect.w+LOCAL_BORDER_SIZE,localrect.h+LOCAL_BORDER_SIZE,hdc2,
localrect.x-LOCAL_BORDER_SIZE,localrect.y-LOCAL_BORDER_SIZE,SRCCOPY);
}else{
}
if (hdc!=hdc2){
if (main_im==NULL && !repainted){
/* Blitting local rect only */
BitBlt(hdc,localrect.x-LOCAL_BORDER_SIZE,localrect.y-LOCAL_BORDER_SIZE,
localrect.w+LOCAL_BORDER_SIZE,localrect.h+LOCAL_BORDER_SIZE,hdc2,
localrect.x-LOCAL_BORDER_SIZE,localrect.y-LOCAL_BORDER_SIZE,SRCCOPY);
}else{
/*Blitting the entire window */
BitBlt(hdc, 0, 0, wsize.width, wsize.height, hdc2, 0, 0, SRCCOPY);
}
SelectObject(hdc2,old_object);
DeleteObject(tmp_bmp);
DeleteDC(hdc2);
}
/*else using direct blitting to screen*/
BitBlt(hdc, 0, 0, wsize.width, wsize.height, hdc2, 0, 0, SRCCOPY);
}
SelectObject(hdc2,old_object);
DeleteObject(tmp_bmp);
DeleteDC(hdc2);
}
/*else using direct blitting to screen*/
ReleaseDC(NULL,hdc);
if (main_im!=NULL)
......@@ -471,6 +474,13 @@ static int get_native_window_id(MSFilter *f, void *data){
return 0;
}
static int set_native_window_id(MSFilter *f, void *data){
DDDisplay *obj=(DDDisplay*)f->data;
obj->window=(HANDLE)(*(long*)data);
obj->own_window=FALSE;
return 0;
}
static int enable_autofit(MSFilter *f, void *data){
DDDisplay *obj=(DDDisplay*)f->data;
obj->autofit=*(int*)data;
......@@ -481,34 +491,35 @@ static int enable_mirroring(MSFilter *f, void *data){
DDDisplay *obj=(DDDisplay*)f->data;
obj->mirroring=*(int*)data;
return 0;
}
static int set_corner(MSFilter *f, void *data){
}
static int set_corner(MSFilter *f, void *data){
DDDisplay *obj=(DDDisplay*)f->data;
obj->corner=*(int*)data;
obj->corner=*(int*)data;
obj->need_repaint=TRUE;
return 0;
return 0;
}
static int get_vsize(MSFilter *f, void *data){
DDDisplay *obj=(DDDisplay*)f->data;
*(MSVideoSize*)data=obj->wsize;
return 0;
}
}
static int set_vsize(MSFilter *f, void *data){
DDDisplay *obj=(DDDisplay*)f->data;
obj->wsize=*(MSVideoSize*)data;
return 0;
}
}
static MSFilterMethod methods[]={
{ MS_FILTER_GET_VIDEO_SIZE , get_vsize },
static MSFilterMethod methods[]={
{ MS_FILTER_GET_VIDEO_SIZE , get_vsize },
{ MS_FILTER_SET_VIDEO_SIZE , set_vsize },
{ MS_VIDEO_DISPLAY_GET_NATIVE_WINDOW_ID, get_native_window_id },
{ MS_VIDEO_DISPLAY_SET_NATIVE_WINDOW_ID, set_native_window_id },
{ MS_VIDEO_DISPLAY_ENABLE_AUTOFIT , enable_autofit },
{ MS_VIDEO_DISPLAY_ENABLE_MIRRORING , enable_mirroring},
{ MS_VIDEO_DISPLAY_ENABLE_MIRRORING , enable_mirroring},
{ MS_VIDEO_DISPLAY_SET_LOCAL_VIEW_CORNER , set_corner },
{ 0 ,NULL}
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment