📄 videoout.c
字号:
ReleaseDC(NULL,hdc);}static void win_display_uninit(MSDisplay *obj){ WinDisplay *wd=(WinDisplay*)obj->data; if (wd==NULL) return; if (wd->window && !obj->window_id) DestroyWindow(wd->window); if (wd->ddh) DrawDibClose(wd->ddh); if (wd->fb.y) ms_free(wd->fb.y); if (wd->rgb) ms_free(wd->rgb); ms_free(wd);}#ifdef _MSC_VERextern MSDisplayDesc ms_win_display_desc={ win_display_init, NULL, NULL, win_display_update, win_display_uninit};#elseMSDisplayDesc ms_win_display_desc={ .init=win_display_init, .update=win_display_update, .uninit=win_display_uninit};#endif#endifMSDisplay *ms_display_new(MSDisplayDesc *desc){ MSDisplay *obj=(MSDisplay *)ms_new0(MSDisplay,1); obj->desc=desc; obj->data=NULL; return obj;}void ms_display_set_window_id(MSDisplay *d, long id){ d->window_id=id;}void ms_display_destroy(MSDisplay *obj){ obj->desc->uninit(obj); ms_free(obj);}typedef struct VideoOut{ MSVideoSize size; MSVideoSize local_size; /*size of local preview */ MSFrameBuffer fbuf; mblk_t *smallb; int scale_factor; MSDisplay *display; bool_t lsize_init; bool_t own_display;} VideoOut;#define SCALE_FACTOR 6static void video_out_init(MSFilter *f){ VideoOut *obj=(VideoOut *)ms_new(VideoOut,1); obj->size.width = MS_VIDEO_SIZE_CIF_W; obj->size.height = MS_VIDEO_SIZE_CIF_H; obj->local_size.width = MS_VIDEO_SIZE_CIF_W; obj->local_size.height = MS_VIDEO_SIZE_CIF_H; obj->lsize_init=FALSE; obj->scale_factor=SCALE_FACTOR; obj->smallb=NULL; obj->display=NULL; obj->own_display=FALSE; f->data=obj;}static void video_out_uninit(MSFilter *f){ VideoOut *s=(VideoOut*)f->data; if (s->smallb!=NULL) freemsg(s->smallb); if (s->display!=NULL && s->own_display) ms_display_destroy(s->display); ms_free(s);}static mblk_t * resize_yuv_small(unsigned char *pict, int w, int h, int scale){ int i,j,id,jd; int nh,nw; unsigned char *smallpict; int ysize,usize,ydsize,udsize; int smallpict_sz; unsigned char *dptr,*sptr; mblk_t *smallb; nw=w/scale; nh=h/scale; ysize=w*h; usize=ysize/4; ydsize=nw*nh; udsize=ydsize/4; smallpict_sz=(ydsize*3)/2; smallb=allocb(smallpict_sz,0); smallpict=smallb->b_wptr; smallb->b_wptr+=smallpict_sz; dptr=smallpict; sptr=pict; for (j=0,jd=0;j<nh;j++,jd+=scale){ for (i=0,id=0;i<nw;i++,id+=scale){ dptr[(j*nw) + i]=sptr[(jd*w)+id]; } } nh=nh/2; nw=nw/2; w=w/2; h=h/2; dptr+=ydsize; sptr+=ysize; for (j=0,jd=0;j<nh;j++,jd+=scale){ for (i=0,id=0;i<nw;i++,id+=scale){ dptr[(j*nw) + i]=sptr[(jd*w)+id]; } } dptr+=udsize; sptr+=usize; for (j=0,jd=0;j<nh;j++,jd+=scale){ for (i=0,id=0;i<nw;i++,id+=scale){ dptr[(j*nw) + i]=sptr[(jd*w)+id]; } } return smallb;}static void fill_overlay_at_pos(VideoOut *obj, mblk_t *m, int x, int y, int w, int h){ MSFrameBuffer *lay=&obj->fbuf; unsigned char *data=m->b_rptr; int i,j; int jlim,ilim; int off; unsigned char *dptr; ilim=MIN(x+w,lay->w); jlim=MIN(y+h,lay->h); ms_display_lock(obj->display); /* set Y */ dptr=lay->y; for (j=y;j<jlim;j++){ off=j*lay->w; for (i=x;i<ilim;i++){ dptr[off + i]=*data; data++; } } /*set U and V*/ ilim=ilim/2; jlim=jlim/2; dptr=lay->u; for (j=y/2;j<jlim;j++){ off=j*(lay->w/2); for (i=x/2;i<ilim;i++){ dptr[off + i]=*data; data++; } } dptr=lay->v; for (j=y/2;j<jlim;j++){ off=j*(lay->w/2); for (i=x/2;i<ilim;i++){ dptr[off + i]=*data; data++; } } ms_display_unlock(obj->display);}static void fill_overlay(VideoOut *obj ,mblk_t *m){ MSFrameBuffer *lay=&obj->fbuf; int w2,h2; char *data=(char*)m->b_rptr; int ysize=lay->w*lay->h; int usize; w2=lay->w/2; h2=lay->h/2; usize=w2*h2; ms_display_lock(obj->display); memcpy(lay->y,data,ysize); memcpy(lay->u,data+ysize,usize); memcpy(lay->v,data+ysize+usize,usize); ms_display_unlock(obj->display);}static void video_out_preprocess(MSFilter *f){ VideoOut *obj=(VideoOut*)f->data; obj->fbuf.w=obj->size.width; obj->fbuf.h=obj->size.height; if (obj->display==NULL){#ifndef WIN32 obj->display=ms_display_new(&ms_sdl_display_desc);#else obj->display=ms_display_new(&ms_win_display_desc);#endif obj->own_display=TRUE; } if (!ms_display_init(obj->display,&obj->fbuf)){ if (obj->own_display) ms_display_destroy(obj->display); obj->display=NULL; }}static void video_out_postprocess(MSFilter *f){}static void video_out_process(MSFilter *f){ VideoOut *obj=(VideoOut*)f->data; mblk_t *inm0=NULL; mblk_t *inm1=NULL; MSRect smallrect, rect; bool_t got_preview=FALSE; rect.w=obj->size.width; rect.h=obj->size.height; rect.x=0; rect.y=0; smallrect.w=obj->size.width/SCALE_FACTOR; smallrect.h=obj->size.height/SCALE_FACTOR; smallrect.x=obj->size.width - smallrect.w ; smallrect.y=obj->size.height -smallrect.h; if (obj->display==NULL){ ms_queue_flush(f->inputs[0]); ms_queue_flush(f->inputs[1]); return; } while (f->inputs[0]!=NULL && (inm0=ms_queue_get(f->inputs[0]))!=NULL){ fill_overlay(obj,inm0); freemsg(inm0); } while (f->inputs[1]!=NULL && (inm1=ms_queue_get(f->inputs[1]))!=NULL){ /* this message is blitted on the right,bottom corner of the screen */ got_preview=TRUE; if (!obj->lsize_init){ /*attempt to guess the video size of the local preview buffer*/ int bsize=msgdsize(inm1); if (obj->size.width==MS_VIDEO_SIZE_CIF_W){ if (bsize<(MS_VIDEO_SIZE_CIF_W*MS_VIDEO_SIZE_CIF_H*3/2)){ /*surely qcif ?*/ obj->local_size.width=MS_VIDEO_SIZE_QCIF_W; obj->local_size.height=MS_VIDEO_SIZE_QCIF_H; ms_message("preview is in QCIF."); obj->scale_factor=SCALE_FACTOR/2; } } else if (obj->local_size.width==MS_VIDEO_SIZE_QCIF_W){ if (bsize==(MS_VIDEO_SIZE_CIF_W*MS_VIDEO_SIZE_CIF_H*3/2)){ /*surely cif ?*/ obj->local_size.width=MS_VIDEO_SIZE_CIF_W; obj->local_size.height=MS_VIDEO_SIZE_CIF_H; ms_message("preview is in CIF."); obj->scale_factor=SCALE_FACTOR*2; } } obj->lsize_init=TRUE; } if (obj->smallb!=NULL) { freemsg(obj->smallb); } obj->smallb=resize_yuv_small(inm1->b_rptr,obj->local_size.width,obj->local_size.height,obj->scale_factor); fill_overlay_at_pos(obj,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h); freemsg(inm1); } if (!got_preview){ /* this is the case were we have only inm0, we have to redisplay inm1 */ if (obj->smallb!=NULL){ fill_overlay_at_pos(obj,obj->smallb,smallrect.x, smallrect.y, smallrect.w, smallrect.h); } } ms_display_update(obj->display);}static int video_out_set_vsize(MSFilter *f,void *arg){ VideoOut *s=(VideoOut*)f->data; s->size=*(MSVideoSize*)arg; s->local_size=*(MSVideoSize*)arg; return 0;}static int video_out_set_display(MSFilter *f,void *arg){ VideoOut *s=(VideoOut*)f->data; s->display=(MSDisplay*)arg; return 0;}static MSFilterMethod methods[]={ { MS_FILTER_SET_VIDEO_SIZE , video_out_set_vsize }, { MS_VIDEO_OUT_SET_DISPLAY , video_out_set_display}, { 0 ,NULL}};#ifdef _MSC_VERMSFilterDesc ms_video_out_desc={ MS_VIDEO_OUT_ID, "MSVideoOut", "A generic video display", MS_FILTER_OTHER, NULL, 2, 0, video_out_init, video_out_preprocess, video_out_process, video_out_postprocess, video_out_uninit, methods};#elseMSFilterDesc ms_video_out_desc={ .id=MS_VIDEO_OUT_ID, .name="MSVideoOut", .text="A generic video display", .category=MS_FILTER_OTHER, .ninputs=2, .noutputs=0, .init=video_out_init, .preprocess=video_out_preprocess, .process=video_out_process, .postprocess=video_out_postprocess, .uninit=video_out_uninit, .methods=methods};#endifMS_FILTER_DESC_EXPORT(ms_video_out_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -