⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stitcher.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
字号:
/** Copyright 2007 Simon Morlat, all rights reserved **/#include <mediastreamer2/msfilter.h>#include <mediastreamer2/msvideo.h>#include <mediastreamer2/msticker.h>#ifdef HAVE_LIBAVCODEC_AVCODEC_H#include <libswscale/swscale.h>#else#include <ffmpeg/swscale.h>#ifdef _MSC_VER /* missing on windows? */#include <ffmpeg/avutil.h>#endif#endif#define STITCHER_MAX_INPUTS 4#define STITCHER_INPUT_TIMEOUT 5000#define AMD_MODE#include "stitcher.h"extern Layout msstitcher_default_layout[];typedef struct _InputInfo{	uint64_t last_frame_time;	struct SwsContext *sws_ctx;	bool_t active;	int counter;} InputInfo;static void input_info_reset_sws(InputInfo *info){	if (info->sws_ctx!=NULL){		sws_freeContext(info->sws_ctx);		info->sws_ctx=NULL;	}}static void input_info_update(InputInfo *info, uint64_t curtime, bool_t has_data){	if (has_data){		info->active=TRUE;		info->last_frame_time=curtime;	}else if (curtime-info->last_frame_time>STITCHER_INPUT_TIMEOUT){			input_info_reset_sws(info);		info->active=FALSE;	}}static void input_info_process(InputInfo *info, mblk_t *im, YuvBuf *dstframe, Region *pos){	YuvBuf inbuf,dest;	int x,y,w,h;	//AMD float ratio;	if (yuv_buf_init_from_mblk(&inbuf,im)!=0) return;	w=(float)dstframe->w*pos->w;	x=((float)dstframe->w*pos->x)-((float)w/2);		//AMDratio=(float)w/(float)inbuf.w;	//AMDh=(float)inbuf.h*ratio;	//AMD y=((float)dstframe->h*pos->y)-((float)h/2);	h=(float)dstframe->h*pos->w;	y=((float)dstframe->h*pos->y)-((float)h/2);	dest.w=w;	dest.h=h;	dest.planes[0]=dstframe->planes[0]+(y*dstframe->strides[0])+x;	dest.planes[1]=dstframe->planes[1]+((y/2)*dstframe->strides[1])+(x/2);	dest.planes[2]=dstframe->planes[2]+((y/2)*dstframe->strides[2])+(x/2);	if (info->sws_ctx==NULL){		info->sws_ctx=sws_getContext(inbuf.w,inbuf.h,PIX_FMT_YUV420P,		dest.w,dest.h,PIX_FMT_YUV420P,SWS_FAST_BILINEAR,                NULL, NULL, NULL);	}	if (sws_scale(info->sws_ctx,inbuf.planes,inbuf.strides, 0,              0, dest.planes, dstframe->strides)!=0){		ms_error("Error in sws_scale().");	}}typedef struct _StitcherData{	Layout *layout_table;	Region *regions;	InputInfo inputinfo[STITCHER_MAX_INPUTS];	int counter;	int nregions;	MSVideoSize vsize;	mblk_t *frame_msg;	YuvBuf frame;#ifdef AMD_MODE	mblk_t *frame_msg_amd_mode;	YuvBuf frame_amd_mode;#endif	int pin_controller;}StitcherData;static void stitcher_init(MSFilter *f){	StitcherData *s=ms_new0(StitcherData,1);	s->vsize.width=MS_VIDEO_SIZE_CIF_W;	s->vsize.height=MS_VIDEO_SIZE_CIF_H;	s->layout_table=msstitcher_default_layout;	f->data=s;}static void stitcher_reset_all(MSFilter *f, StitcherData *d){	int i;	for (i=0;i<f->desc->ninputs;++i){		input_info_reset_sws(&d->inputinfo[i]);    /* ms_message("nb of incoming image on pin %i: %i", i, d->inputinfo[i].counter); */    d->inputinfo[i].counter=0;	}  d->pin_controller=0;  ms_message("nb of outgoing images %i", d->counter);  d->counter=0;	/* put frame black */	if (d->frame_msg!=NULL){		int ysize=d->frame.strides[0]*d->frame.h;		memset(d->frame.planes[0],16,ysize);		memset(d->frame.planes[1],128,ysize/4);		memset(d->frame.planes[2],128,ysize/4);	}#ifdef AMD_MODE	/* put frame black */	if (d->frame_msg_amd_mode!=NULL){		int ysize=d->frame_amd_mode.strides[0]*d->frame_amd_mode.h;		memset(d->frame_amd_mode.planes[0],16,ysize);		memset(d->frame_amd_mode.planes[1],128,ysize/4);		memset(d->frame_amd_mode.planes[2],128,ysize/4);	}#endif}static void stitcher_uninit(MSFilter *f){	StitcherData *d=(StitcherData*)f->data;	stitcher_reset_all(f,d);	ms_free(f->data);}static int check_inputs(MSFilter *f, StitcherData *d){	int i;	int active=0;	uint64_t curtime=f->ticker->time;	for (i=0;i<f->desc->ninputs;++i){		if (f->inputs[i]!=NULL){			input_info_update(&d->inputinfo[i],				curtime,				!ms_queue_empty(f->inputs[i]));			if (d->inputinfo[i].active)				++active;		}	}	return active;}static void stitcher_update_layout(StitcherData *d, int nregions){	Layout *it;	for(it=d->layout_table;it->regions!=NULL;++it){		if (it->nregions==nregions){			/*found a layout for this number of regions*/			d->nregions=nregions;			d->regions=it->regions;			return;			}	}	ms_error("No layout defined for %i regions",nregions);}static void stitcher_preprocess(MSFilter *f){	StitcherData *d=(StitcherData*)f->data;	d->frame_msg=yuv_buf_alloc(&d->frame,d->vsize.width,d->vsize.height);#ifdef AMD_MODE	d->frame_msg_amd_mode=yuv_buf_alloc(&d->frame_amd_mode,d->vsize.width,d->vsize.height);	#endif}static void stitcher_process(MSFilter *f){#ifdef AMD_MODE  int update_pin0=-1;  int update_pin1=-1;#endif  int i,found;	mblk_t *im;	StitcherData *d=(StitcherData*)f->data;	int nregions=check_inputs(f,d);	if (d->nregions!=nregions){		stitcher_update_layout(d,nregions);		stitcher_reset_all(f,d);    d->pin_controller=0;	}#ifdef AMD_MODE	if (d->nregions==2)	{		/* special mode to enable video conference with 1 guy:		DO NOT send him his own picture. */		/* First INPUT has local SOURCE connected */		if (f->inputs[0]!=NULL && (im=ms_queue_peek_last(f->inputs[0]))!=NULL ){			Region *pos=&msstitcher_default_layout->regions[0];			input_info_process(&d->inputinfo[0],im,&d->frame,pos);			ms_queue_flush(f->inputs[0]);      //ms_message("WINDS: new image on pin0");      update_pin0=1;		}		/* second INPUT is some RTP connected */		for (i=1,found=0;i<f->desc->ninputs;++i){			if (f->inputs[i]!=NULL && (im=ms_queue_peek_last(f->inputs[i]))!=NULL ){				Region *pos=&msstitcher_default_layout->regions[0];				input_info_process(&d->inputinfo[i],im,&d->frame_amd_mode,pos);				ms_queue_flush(f->inputs[i]);        update_pin1=1;				break; /* only one in this case */			}		}	}	else	{    int max=0;    update_pin0=1;    update_pin1=1;    /* select the fastest pin */    d->pin_controller=0;		for (i=0,found=0;i<f->desc->ninputs;++i){			if (f->inputs[i]!=NULL && (im=ms_queue_peek_last(f->inputs[i]))!=NULL ){				Region *pos=&d->regions[found];				input_info_process(&d->inputinfo[i],im,&d->frame,pos);				ms_queue_flush(f->inputs[i]);        d->inputinfo[i].counter++;			}      if (d->inputinfo[i].counter>max){        max=d->inputinfo[i].counter;        d->pin_controller=i;		  }      if (f->inputs[i]!=NULL && d->inputinfo[i].active)				++found;		}    if (max>20) /* reset */    {	    for (i=0,found=0;i<f->desc->ninputs;++i){        /* ms_message("nb of incoming image on pin %i: %i", i, d->inputinfo[i].counter); */        if (i==d->pin_controller)          d->inputinfo[i].counter=3; /* keep this one advanced to avoid changing too often */        else          d->inputinfo[i].counter=0;	    }      /* ms_message("nb of outgoing images %i", d->counter); */      d->counter=0;    }	}#else	for (i=0,found=0;i<f->desc->ninputs;++i){		if (f->inputs[i]!=NULL && (im=ms_queue_peek_last(f->inputs[i]))!=NULL ){			Region *pos=&d->regions[found];			input_info_process(&d->inputinfo[i],im,&d->frame,pos);			ms_queue_flush(f->inputs[i]);		}		if (f->inputs[i]!=NULL && d->inputinfo[i].active)			++found;	}#endif#ifdef AMD_MODE	if (d->nregions==2)	{    if (update_pin1==1) /* new frame_msg_amd_mode */    {		  if (f->outputs[0]!=NULL){			  ms_queue_put(f->outputs[0],dupb(d->frame_msg_amd_mode));		  }    }    if (update_pin0==1) /* new frame_msg */    {		  for(i=1;i<f->desc->noutputs;++i){			  if (f->outputs[i]!=NULL){				  ms_queue_put(f->outputs[i],dupb(d->frame_msg));			  }		  }    }	}	else	{    if (d->inputinfo[d->pin_controller].last_frame_time==f->ticker->time) /* the pin controller was updated */    {      d->counter++;		  for(i=0;i<f->desc->noutputs;++i){			  if (f->outputs[i]!=NULL){				  ms_queue_put(f->outputs[i],dupb(d->frame_msg));			  }		  }    }	}#else	for(i=0;i<f->desc->noutputs;++i){		if (f->outputs[i]!=NULL){			ms_queue_put(f->outputs[i],dupb(d->frame_msg));		}	}#endif}static void stitcher_postprocess(MSFilter *f){	StitcherData *d=(StitcherData*)f->data;	stitcher_reset_all(f,d);	freemsg(d->frame_msg);	d->frame_msg=NULL;#ifdef AMD_MODE	freemsg(d->frame_msg_amd_mode);	d->frame_msg_amd_mode=NULL;#endif}static int stitcher_set_vsize(MSFilter *f, void *data){	StitcherData *d=(StitcherData*)f->data;	MSVideoSize *sz=(MSVideoSize*)data;	d->vsize=*sz;	return 0;}static MSFilterMethod methods[]={	{MS_FILTER_SET_VIDEO_SIZE,	stitcher_set_vsize},	{0,NULL}};#ifdef _MSC_VERMSFilterDesc ms_video_stitcher_desc={	MS_FILTER_PLUGIN_ID,	"MSVideoStitcher",	"A video stitching (mixing) filter",	MS_FILTER_OTHER,	NULL,	STITCHER_MAX_INPUTS,	STITCHER_MAX_INPUTS,	stitcher_init,	stitcher_preprocess,	stitcher_process,	stitcher_postprocess,	stitcher_uninit,	methods};#elseMSFilterDesc ms_video_stitcher_desc={	MS_FILTER_PLUGIN_ID,	"MSVideoStitcher",	"A video stitching (mixing) filter",	MS_FILTER_OTHER,	NULL,	STITCHER_MAX_INPUTS,	STITCHER_MAX_INPUTS,	stitcher_init,	stitcher_preprocess,	stitcher_process,	stitcher_postprocess,	stitcher_uninit,	methods};#endif#ifdef WIN32#define GLOBAL_LINKAGE __declspec(dllexport)#else#define GLOBAL_LINKAGE#endifGLOBAL_LINKAGE void libmsvideostitcher_init(void){	ms_filter_register(&ms_video_stitcher_desc);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -