Exemplo n.º 1
0
static void bb10display_fillWindowBuffer(BB10Display *d, MSPicture *yuvbuf) {
    uint8_t *ptr = NULL;
    screen_get_buffer_property_pv(d->pixmap_buffer, SCREEN_PROPERTY_POINTER, (void **)&ptr);

    if (ptr) {
        uint8_t *dest_planes[3];
        int dest_strides[3];
        MSVideoSize roi = {0};

        uint8_t *y = ptr;
        uint8_t *u = y + (d->vsize.height * d->stride);
        uint8_t *v = u + (d->vsize.height * d->stride) / 4;

        dest_planes[0] = y;
        dest_planes[1] = u;
        dest_planes[2] = v;
        dest_strides[0] = d->stride;
        dest_strides[1] = d->stride / 2;
        dest_strides[2] = d->stride / 2;

        roi.width = yuvbuf->w;
        roi.height = yuvbuf->h;

        ms_yuv_buf_copy(yuvbuf->planes, yuvbuf->strides, dest_planes, dest_strides, roi);

        screen_buffer_t buffer;
        screen_get_window_property_pv(d->window, SCREEN_PROPERTY_RENDER_BUFFERS, (void**) &buffer);

        MSRect rect;
        ms_layout_center_rectangle(d->wsize, d->vsize, &rect);
        int attributes[] = {
            SCREEN_BLIT_SOURCE_WIDTH, d->vsize.width, SCREEN_BLIT_SOURCE_HEIGHT, d->vsize.height,
            SCREEN_BLIT_DESTINATION_X, rect.x, SCREEN_BLIT_DESTINATION_Y, rect.y,
            SCREEN_BLIT_DESTINATION_WIDTH, rect.w, SCREEN_BLIT_DESTINATION_HEIGHT, rect.h,
            SCREEN_BLIT_END
        };
        screen_blit(d->context, buffer, d->pixmap_buffer, attributes);

        int dirty_rect[4] = { 0, 0, d->wsize.width, d->wsize.height };
        screen_post_window(d->window, buffer, 1, dirty_rect, 0);
    }
}
Exemplo n.º 2
0
static void x11video_process(MSFilter *f){
	X11Video *obj=(X11Video*)f->data;
	mblk_t *inm;
	int update=0;
	MSPicture lsrc={0};
	MSPicture src={0};
	MSRect mainrect,localrect;
	bool_t precious=FALSE;
	bool_t local_precious=FALSE;
	XWindowAttributes wa;
	MSTickerLateEvent late_info;

	ms_filter_lock(f);

	if ((obj->window_id == 0) || (x11_error == TRUE)) goto end;

	XGetWindowAttributes(obj->display,obj->window_id,&wa);
	if (x11_error == TRUE) {
		ms_error("Could not get window attributes for window %lu", obj->window_id);
		goto end;
	}
	if (wa.width!=obj->wsize.width || wa.height!=obj->wsize.height){
		ms_warning("Resized to %ix%i", wa.width,wa.height);
		obj->wsize.width=wa.width;
		obj->wsize.height=wa.height;
		XClearWindow(obj->display,obj->window_id);
	}

	ms_ticker_get_last_late_tick(f->ticker, &late_info);
	if(late_info.current_late_ms > 100) {
		ms_warning("Dropping frames because we're late");
		goto end;
	}

	if (!obj->show) {
		goto end;
	}
	if (!obj->ready){
		goto end;
	}

	if (f->inputs[0]!=NULL && (inm=ms_queue_peek_last(f->inputs[0]))!=0) {
		if (ms_yuv_buf_init_from_mblk(&src,inm)==0){
			MSVideoSize newsize;
			newsize.width=src.w;
			newsize.height=src.h;
			precious=mblk_get_precious_flag(inm);
			if (!ms_video_size_equal(newsize,obj->vsize) ) {
				ms_message("received size is %ix%i",newsize.width,newsize.height);
				obj->vsize=newsize;
				if (obj->autofit){
					MSVideoSize new_window_size;
					static const MSVideoSize min_size=MS_VIDEO_SIZE_QVGA;
					/*don't resize less than QVGA, it is too small*/
					if (min_size.width*min_size.height>newsize.width*newsize.height){
						new_window_size.width=newsize.width*2;
						new_window_size.height=newsize.height*2;
					}else new_window_size=newsize;
					obj->wsize=new_window_size;
					ms_message("autofit: new window size should be %ix%i",new_window_size.width,new_window_size.height);
					XResizeWindow(obj->display,obj->window_id,new_window_size.width,new_window_size.height);
					XSync(obj->display,FALSE);
				}
				x11video_unprepare(f);
				x11video_prepare(f);
				if (!obj->ready) goto end;
			}
		}
		update=1;
	}
	/*process last video message for local preview*/
	if (obj->corner!=-1 && f->inputs[1]!=NULL && (inm=ms_queue_peek_last(f->inputs[1]))!=0) {
		if (ms_yuv_buf_init_from_mblk(&lsrc,inm)==0){
			obj->lsize.width=lsrc.w;
			obj->lsize.height=lsrc.h;
			local_precious=mblk_get_precious_flag(inm);
			update=1;
		}
	}

	ms_layout_compute(obj->vsize, obj->vsize,obj->lsize,obj->corner,obj->scale_factor,&mainrect,&localrect);

	if (lsrc.w!=0 && obj->corner!=-1){
		/* first reduce the local preview image into a temporary image*/
		if (obj->local_msg==NULL){
			obj->local_msg=ms_yuv_buf_alloc(&obj->local_pic,localrect.w,localrect.h);
		}
		if (obj->sws2==NULL){
			obj->sws2=ms_scaler_create_context(lsrc.w,lsrc.h,MS_YUV420P,localrect.w,localrect.h,MS_YUV420P,
			                             MS_SCALER_METHOD_BILINEAR);
		}
		ms_scaler_process(obj->sws2,lsrc.planes,lsrc.strides,obj->local_pic.planes,obj->local_pic.strides);
		if (!local_precious) ms_yuv_buf_mirror(&obj->local_pic);
	}

	if (update && src.w!=0){
		ms_yuv_buf_copy(src.planes,src.strides,obj->fbuf.planes,obj->fbuf.strides,obj->vsize);
		if (obj->mirror && !precious) ms_yuv_buf_mirror(&obj->fbuf);
	}

	/*copy resized local view into a corner:*/
	if (update && obj->local_msg!=NULL && obj->corner!=-1){
		MSPicture corner=obj->fbuf;
		MSVideoSize roi;
		roi.width=obj->local_pic.w;
		roi.height=obj->local_pic.h;
		corner.w=obj->local_pic.w;
		corner.h=obj->local_pic.h;
		corner.planes[0]+=localrect.x+(localrect.y*corner.strides[0]);
		corner.planes[1]+=(localrect.x/2)+((localrect.y/2)*corner.strides[1]);
		corner.planes[2]+=(localrect.x/2)+((localrect.y/2)*corner.strides[2]);
		corner.planes[3]=0;
		ms_yuv_buf_copy(obj->local_pic.planes,obj->local_pic.strides,
				corner.planes,corner.strides,roi);
	}
	if (update){
		MSRect rect;
		ms_layout_center_rectangle(obj->wsize,obj->vsize,&rect);
		//ms_message("XvShmPutImage() %ix%i --> %ix%i",obj->fbuf.w,obj->fbuf.h,obj->wsize.width,obj->wsize.height);

		XvShmPutImage(obj->display,obj->port,obj->window_id,obj->gc, obj->xv_image,
		              0,0,obj->fbuf.w,obj->fbuf.h,
		              rect.x,rect.y,rect.w,rect.h,TRUE);
		XSync(obj->display,FALSE);
	}

end:
	ms_filter_unlock(f);
	if (f->inputs[0]!=NULL)
		ms_queue_flush(f->inputs[0]);
	if (f->inputs[1]!=NULL)
		ms_queue_flush(f->inputs[1]);
}
Exemplo n.º 3
0
/**
 * This function is used to compute placement of video and local preview video within a window.
 * It is used by display filters such as MSDrawDibDisplay and MSX11Video.
 * @arg wsize the size of the window
 * @arg vsize the size of the main video to display
 * @arg orig_psize the size of the preview video
 * @arg localrect_pos tells which corner is to be used to preview placement
 * @arg scalefactor ratio of the window size over the whished preview video size , ex: 4.0 
 * @arg mainrect is a return value describing the main video placement
 * @arg localrect is a return value describing the preview video placement
 * @arg localrect_pos
**/
void ms_layout_compute(MSVideoSize wsize, MSVideoSize vsize, MSVideoSize orig_psize,  int localrect_pos, float scalefactor, MSRect *mainrect, MSRect *localrect){
	MSVideoSize psize;

	ms_layout_center_rectangle(wsize,vsize,mainrect);
	if (localrect_pos!=-1){
		psize.width=(int)(wsize.width/scalefactor);
		psize.height=(int)(wsize.height/scalefactor);
		ms_layout_center_rectangle(psize,orig_psize,localrect);
		if ((wsize.height - mainrect->h < mainrect->h/scalefactor && wsize.width - mainrect->w < mainrect->w/scalefactor) || localrect_pos<=3)
		{
			int x_sv;
			int y_sv;
			if (localrect_pos%4==1)
			{
				/* top left corner */
				x_sv = LOCAL_POS_OFFSET;
				y_sv = LOCAL_POS_OFFSET;
			}
			else if (localrect_pos%4==2)
			{
				/* top right corner */
				x_sv = (wsize.width-localrect->w-LOCAL_POS_OFFSET);
				y_sv = LOCAL_POS_OFFSET;
			}
			else if (localrect_pos%4==3)
			{
				/* bottom left corner */
				x_sv = LOCAL_POS_OFFSET;
				y_sv = (wsize.height-localrect->h-LOCAL_POS_OFFSET);
			}
			else /* corner = 0: default */
			{
				/* bottom right corner */
				x_sv = (wsize.width-localrect->w-LOCAL_POS_OFFSET);
				y_sv = (wsize.height-localrect->h-LOCAL_POS_OFFSET);
			}
			localrect->x=x_sv; //wsize.width-localrect->w-LOCAL_POS_OFFSET;
			localrect->y=y_sv; //wsize.height-localrect->h-LOCAL_POS_OFFSET;
		}
		else
		{
			int x_sv;
			int y_sv;

			if (wsize.width - mainrect->w < mainrect->w/scalefactor)
			{
				// recalculate so we have a selfview taking as
				// much available space as possible
				psize.width=wsize.width;
				psize.height=wsize.height-mainrect->h;
				ms_layout_center_rectangle(psize,orig_psize,localrect);

				if (localrect_pos%4==1 || localrect_pos%4==2)
				{
					//Self View on Top
					x_sv = (wsize.width-localrect->w)/2;
					y_sv = LOCAL_POS_OFFSET;

					mainrect->y = wsize.height-mainrect->h-LOCAL_POS_OFFSET;
				}
				else
				{
					//Self View on Bottom
					x_sv = (wsize.width-localrect->w)/2;
					y_sv = (wsize.height-localrect->h-LOCAL_POS_OFFSET);

					mainrect->y = LOCAL_POS_OFFSET;
				}
			}
			else
			{
				// recalculate so we have a selfview taking as
				// much available space as possible
				psize.width=wsize.width-mainrect->w;
				psize.height=wsize.height;
				ms_layout_center_rectangle(psize,orig_psize,localrect);

				if (localrect_pos%4==1 || localrect_pos%4==3)
				{
					//Self View on left
					x_sv = LOCAL_POS_OFFSET;
					y_sv = (wsize.height-localrect->h)/2;

					mainrect->x = wsize.width-mainrect->w-LOCAL_POS_OFFSET;
				}
				else
				{
					//Self View on right
					x_sv = (wsize.width-localrect->w-LOCAL_POS_OFFSET);
					y_sv = (wsize.height-localrect->h)/2;

					mainrect->x = LOCAL_POS_OFFSET;
				}
			}

			localrect->x=x_sv; //wsize.width-localrect->w-LOCAL_POS_OFFSET;
			localrect->y=y_sv; //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"
		"mainrect=%i,%i,%i,%i\tlocalrect=%i,%i,%i,%i",
		wsize.width,wsize.height,vsize.width,vsize.height,psize.width,psize.height,orig_psize.width,orig_psize.height,
		mainrect->x,mainrect->y,mainrect->w,mainrect->h,
		localrect->x,localrect->y,localrect->w,localrect->h);
*/
}