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

📄 msv4m.c

📁 基于osip、eXosip、speex、ffmpeg的VoIP源代码
💻 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.*/#ifdef __APPLE__#include "mediastreamer-config.h"#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>#include <errno.h>#include <string.h>#include "mediastreamer2/msvideo.h"#include "mediastreamer2/msticker.h"#include "mediastreamer2/msv4l.h"#include "nowebcam.h"// build for carbon#define TARGET_API_MAC_CARBON 1#if __APPLE_CC__  #include <Carbon/Carbon.h>  #include <QuicKTime/QuickTime.h>#else  #include <ConditionalMacros.h>  #include <QuickTimeComponents.h>  #include <TextUtils.h>  #include <stdio.h>#endiftypedef struct V4lState{  SeqGrabComponent seqgrab;  SGChannel sgchanvideo;  GWorldPtr pgworld;  ImageSequence   decomseq;  char *mmapdbuf;  int msize;/*mmapped size*/  MSVideoSize vsize;  MSVideoSize got_vsize;  int pix_fmt;  int int_pix_fmt; /*internal pixel format */  mblk_t *mire;  queue_t rq;  ms_mutex_t mutex;  int frame_ind;  int frame_max;  float fps;  float start_time;  int frame_count;  int queued;  bool_t run;  bool_t usemire;}V4lState;static void v4m_init(MSFilter *f){	V4lState *s=ms_new0(V4lState,1);	s->seqgrab=NULL;	s->sgchanvideo=NULL;	s->pgworld=NULL;	s->decomseq=0;	s->run=FALSE;	s->mmapdbuf=NULL;	s->vsize.width=MS_VIDEO_SIZE_CIF_W;	s->vsize.height=MS_VIDEO_SIZE_CIF_H;	s->pix_fmt=MS_RGB24;	qinit(&s->rq);	s->mire=NULL;	ms_mutex_init(&s->mutex,NULL);	s->start_time=0;	s->frame_count=-1;	s->fps=15;	s->usemire=(getenv("DEBUG")!=NULL);	s->queued=0;	f->data=s;}#define BailErr(x) {err = x; if(err != noErr) goto bail;}pascal OSErr sgdata_callback(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon);pascal OSErr sgdata_callback(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon){#pragma unused(offset,chRefCon,time,writeType)        CodecFlags     ignore;    V4lState *s=(V4lState *)refCon;    ComponentResult err = noErr;        if (!s) goto bail;       Rect boundsRect = {0, 0, s->vsize.height, s->vsize.width}; /* 240 , 320*/    if (s->pgworld) {      if (s->decomseq == 0) {	Rect sourceRect = { 0, 0 };	MatrixRecord scaleMatrix;	ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(0);		err = SGGetChannelSampleDescription(c,(Handle)imageDesc);	BailErr(err);		// make a scaling matrix for the sequence	sourceRect.right = (**imageDesc).width;	sourceRect.bottom = (**imageDesc).height;	RectMatrix(&scaleMatrix, &sourceRect, &boundsRect);            	err = DecompressSequenceBegin(&s->decomseq,  // pointer to field to receive unique ID for sequence				      imageDesc,        // handle to image description structure				      s->pgworld,    // port for the DESTINATION image				      NULL,            // graphics device handle, if port is set, set to NULL				      NULL,            // source rectangle defining the portion of the image to decompress				      &scaleMatrix,        // transformation matrix				      srcCopy,          // transfer mode specifier				      NULL,            // clipping region in dest. coordinate system to use as a mask				      0,            // flags				      codecNormalQuality,    // accuracy in decompression				      bestSpeedCodec);      // compressor identifier or special identifiers ie. bestSpeedCodec	BailErr(err);		DisposeHandle((Handle)imageDesc);	imageDesc = NULL;      }            // decompress a frame into the GWorld - can queue a frame for async decompression when passed in a completion proc      // once the image is in the GWorld it can be manipulated at will      err = DecompressSequenceFrameS(s->decomseq,  // sequence ID returned by DecompressSequenceBegin				     p,            // pointer to compressed image data				     len,          // size of the buffer				     0,            // in flags				     &ignore,        // out flags				     NULL);          // async completion proc        BailErr(err);            {      unsigned line;      mblk_t *buf;      int size = s->vsize.width * s->vsize.height * 3;      buf=allocb(size,0);            PixMap * pixmap = *GetGWorldPixMap(s->pgworld);      uint8_t * data;      unsigned rowBytes = pixmap->rowBytes & (((unsigned short) 0xFFFF) >> 2);      unsigned pixelSize = pixmap->pixelSize / 8; // Pixel size in bytes      unsigned lineOffset = rowBytes - s->vsize.width * pixelSize;            data = (uint8_t *) GetPixBaseAddr(GetGWorldPixMap(s->pgworld));            for (line = 0 ; line < s->vsize.height ; line++) {	unsigned offset = line * (s->vsize.width * pixelSize + lineOffset);	memcpy(buf->b_wptr + ((line * s->vsize.width) * pixelSize), data + offset, (rowBytes - lineOffset));      }      if (s->pix_fmt==MS_RGB24)	{	  /* Conversion from top down bottom up (BGR to RGB and flip) */	  unsigned long Index,nPixels;	  unsigned char *blue;	  unsigned char tmp;	  short iPixelSize;	  blue=buf->b_wptr;	  nPixels=s->vsize.width*s->vsize.height;	  iPixelSize=24/8;	  for(Index=0;Index!=nPixels;Index++)  // For each pixel	    {	      tmp=*blue;	      *blue=*(blue+2);	      *(blue+2)=tmp;	      blue+=iPixelSize;	    }	}      buf->b_wptr+=size;      //ms_mutex_lock(&s->mutex); /* called during SGIdle? */      putq(&s->rq, buf);      //ms_mutex_unlock(&s->mutex);    }  }bail:  return err;}static int v4m_close(V4lState *s){  if(s->seqgrab)    CloseComponent(s->seqgrab);  s->seqgrab=NULL;  if (s->decomseq)    CDSequenceEnd(s->decomseq);  s->decomseq=NULL;  if (s->pgworld!=NULL)    DisposeGWorld(s->pgworld);  s->pgworld=NULL;  return 0;}static int sequence_grabber_start(V4lState *s){  int err;  Rect        theRect = {0, 0, s->vsize.height, s->vsize.width};  err = QTNewGWorld(&(s->pgworld),  // returned GWorld		    k24BGRPixelFormat,		    &theRect,      // bounding rectangle		    0,             // color table		    NULL,          // graphic device handle		    0);            // flags  if (err!=noErr)    {      return -1;    }  if(!LockPixels(GetPortPixMap(s->pgworld)))    {      v4m_close(s);      return -1;    }  s->seqgrab = OpenDefaultComponent(SeqGrabComponentType, 0);  err = SGInitialize(s->seqgrab);  if (err!=noErr)    {      v4m_close(s);      return -1;    }  err = SGSetDataRef(s->seqgrab, 0, 0, seqGrabDontMakeMovie);  if (err!=noErr)    {      v4m_close(s);      return -1;    }  err = SGSetGWorld(s->seqgrab, s->pgworld, GetMainDevice());  if (err!=noErr)    {      v4m_close(s);      return -1;    }  err = SGNewChannel(s->seqgrab, VideoMediaType, &s->sgchanvideo);  if (err!=noErr)    {      v4m_close(s);      return -1;    }  err = SGSetChannelBounds(s->sgchanvideo, &theRect);  if (err!=noErr)    {      v4m_close(s);      return -1;    }  err = SGSetChannelUsage(s->sgchanvideo, seqGrabRecord);  if (err!=noErr)    {      v4m_close(s);      return -1;    }  err = SGSetDataProc(s->seqgrab,NewSGDataUPP(sgdata_callback),(long)s);  if (err!=noErr)    {      v4m_close(s);      return -1;    }  err = SGStartRecord(s->seqgrab);  if (err!=noErr)    {      v4m_close(s);      return -1;    }  return 0;}static int v4m_start(MSFilter *f, void *arg){	V4lState *s=(V4lState*)f->data;	int err=0;	err = sequence_grabber_start(s);	if (err!=0)	  {	    s->pix_fmt=MS_YUV420P;	    s->vsize.width=MS_VIDEO_SIZE_CIF_W;	    s->vsize.height=MS_VIDEO_SIZE_CIF_H;	    return 0;	  }	ms_message("v4m video device opened.");	s->pix_fmt=MS_RGB24;	return 0;}static void v4m_start_capture(V4lState *s){	if (s->seqgrab!=NULL){		s->run=TRUE;	}}static int v4m_stop(MSFilter *f, void *arg){	V4lState *s=(V4lState*)f->data;	if (s->seqgrab!=NULL){	  ms_mutex_lock(&s->mutex);	  SGStop(s->seqgrab);	  v4m_close(s);	  flushq(&s->rq,0);	  ms_mutex_unlock(&s->mutex);	}	return 0;}static void v4m_stop_capture(V4lState *s){	if (s->run){		s->run=FALSE;		ms_message("v4m capture stopped.");	}}static void v4m_uninit(MSFilter *f){	V4lState *s=(V4lState*)f->data;	if (s->seqgrab!=NULL) v4m_stop(f,NULL);	//ms_free(s->dev);	flushq(&s->rq,0);	ms_mutex_destroy(&s->mutex);	freemsg(s->mire);	ms_free(s);}static mblk_t * v4m_make_mire(V4lState *s){	unsigned char *data;	int i,j,line,pos;	int patternw=s->vsize.width/6; 	int patternh=s->vsize.height/6;	int red,green=0,blue=0;	if (s->mire==NULL){		s->mire=allocb(s->vsize.width*s->vsize.height*3,0);		s->mire->b_wptr=s->mire->b_datap->db_lim;	}	data=s->mire->b_rptr;	for (i=0;i<s->vsize.height;++i){		line=i*s->vsize.width*3;		if ( ((i+s->frame_ind)/patternh) & 0x1) red=255;		else red= 0;		for (j=0;j<s->vsize.width;++j){			pos=line+(j*3);						if ( ((j+s->frame_ind)/patternw) & 0x1) blue=255;			else blue= 0;						data[pos]=red;			data[pos+1]=green;			data[pos+2]=blue;		}	}	s->frame_ind++;	return s->mire;}static mblk_t * v4m_make_nowebcam(V4lState *s){	if (s->mire==NULL && s->frame_ind==0){		s->mire=ms_load_nowebcam(&s->vsize, -1);	}	s->frame_ind++;	return s->mire;}static void v4m_process(MSFilter * obj){	V4lState *s=(V4lState*)obj->data;	uint32_t timestamp;	int cur_frame;	if (s->frame_count==-1){		s->start_time=obj->ticker->time;		s->frame_count=0;	}	ms_mutex_lock(&s->mutex);	if (s->seqgrab!=NULL)	{	  SGIdle(s->seqgrab);	}	cur_frame=((obj->ticker->time-s->start_time)*s->fps/1000.0);	if (cur_frame>=s->frame_count){		mblk_t *om=NULL;		/*keep the most recent frame if several frames have been captured */		if (s->seqgrab!=NULL){			om=getq(&s->rq);		}else{		  if (s->pix_fmt==MS_YUV420P		      && s->vsize.width==MS_VIDEO_SIZE_CIF_W		      && s->vsize.height==MS_VIDEO_SIZE_CIF_H)		    {			if (s->usemire){				om=dupmsg(v4m_make_mire(s));			}else {				mblk_t *tmpm=v4m_make_nowebcam(s);				if (tmpm) om=dupmsg(tmpm);			}		    }		}		if (om!=NULL){			timestamp=obj->ticker->time*90;/* rtp uses a 90000 Hz clockrate for video*/			mblk_set_timestamp_info(om,timestamp);			mblk_set_marker_info(om,TRUE);			ms_queue_put(obj->outputs[0],om);			/*ms_message("picture sent");*/			s->frame_count++;		}	}else flushq(&s->rq,0);	ms_mutex_unlock(&s->mutex);}static void v4m_preprocess(MSFilter *f){	V4lState *s=(V4lState*)f->data;	v4m_start_capture(s);}static void v4m_postprocess(MSFilter *f){	V4lState *s=(V4lState*)f->data;	v4m_stop_capture(s);}static int v4m_set_fps(MSFilter *f, void *arg){	V4lState *s=(V4lState*)f->data;	s->fps=*((float*)arg);	s->frame_count=-1;	return 0;}static int v4m_get_pix_fmt(MSFilter *f,void *arg){	V4lState *s=(V4lState*)f->data;	*((MSPixFmt*)arg) = s->pix_fmt;	return 0;}static int v4m_set_vsize(MSFilter *f, void *arg){	V4lState *s=(V4lState*)f->data;	s->vsize=*((MSVideoSize*)arg);	return 0;}static int v4m_get_vsize(MSFilter *f, void *arg){	V4lState *s=(V4lState*)f->data;	*(MSVideoSize*)arg=s->vsize;	return 0;}static MSFilterMethod methods[]={	{	MS_FILTER_SET_FPS	,	v4m_set_fps	},	{	MS_FILTER_GET_PIX_FMT	,	v4m_get_pix_fmt	},	{	MS_FILTER_SET_VIDEO_SIZE, 	v4m_set_vsize	},	{	MS_V4L_START			,	v4m_start	},	{	MS_V4L_STOP			,	v4m_stop	},	{	MS_FILTER_GET_VIDEO_SIZE,	v4m_get_vsize },	{	0	,	NULL			}};MSFilterDesc ms_v4l_desc={	.id=MS_V4L_ID,	.name="MSV4m",	.text="A video for macosx compatible source filter to stream pictures.",	.ninputs=0,	.noutputs=1,	.category=MS_FILTER_OTHER,	.init=v4m_init,	.preprocess=v4m_preprocess,	.process=v4m_process,	.postprocess=v4m_postprocess,	.uninit=v4m_uninit,	.methods=methods};MS_FILTER_DESC_EXPORT(ms_v4l_desc)#endif

⌨️ 快捷键说明

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