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

📄 videoenc.c

📁 基于osip、eXosip、speex、ffmpeg的VoIP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*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 HAVE_CONFIG_H#include "mediastreamer-config.h"#endif#ifdef HAVE_LIBAVCODEC_AVCODEC_H#include <libavcodec/avcodec.h>#else#include <ffmpeg/avcodec.h>#endif#include "mediastreamer2/msfilter.h"#include "mediastreamer2/msvideo.h"#include "mediastreamer2/msticker.h"#ifdef _WIN32#include <ws2tcpip.h>#else#include <netinet/in.h>			/* ntohl(3) */#endif#include "rfc2429.h"static bool_t avcodec_initialized=FALSE;void ms_ffmpeg_check_init(){	if(!avcodec_initialized){		avcodec_init();		avcodec_register_all();		avcodec_initialized=TRUE;	}}typedef struct EncState{	AVCodecContext av_context;	AVCodec *av_codec;	enum CodecID codec;	mblk_t *comp_buf;	MSVideoSize vsize;	int mtu;	/* network maximum transmission unit in bytes */	int profile;	float fps;	int maxbr;	int qmin;	bool_t req_vfu;}EncState;static int enc_set_fps(MSFilter *f, void *arg){	EncState *s=(EncState*)f->data;	s->fps=*(float*)arg;	return 0;}static int enc_get_fps(MSFilter *f, void *arg){	EncState *s=(EncState*)f->data;	*(float*)arg=s->fps;	return 0;}static int enc_set_vsize(MSFilter *f,void *arg){	EncState *s=(EncState*)f->data;	s->vsize=*(MSVideoSize*)arg;	return 0;}static int enc_get_vsize(MSFilter *f,void *arg){	EncState *s=(EncState*)f->data;	*(MSVideoSize*)arg=s->vsize;	return 0;}static int enc_set_mtu(MSFilter *f,void *arg){	EncState *s=(EncState*)f->data;	s->mtu=*(int*)arg;	return 0;}static bool_t parse_video_fmtp(const char *fmtp, float *fps, MSVideoSize *vsize){	char *tmp=ms_strdup(fmtp);	char *semicolon;	char *equal;	bool_t ret=TRUE;	ms_message("parsing %s",fmtp);	/*extract fisrt pair */	if ((semicolon=strchr(tmp,';'))!=NULL){		*semicolon='\0';	}	if ((equal=strchr(tmp,'='))!=NULL){		int divider;		*equal='\0';		if (strcasecmp(tmp,"CIF")==0){			if (vsize->width>=MS_VIDEO_SIZE_CIF_W){				vsize->width=MS_VIDEO_SIZE_CIF_W;				vsize->height=MS_VIDEO_SIZE_CIF_H;			}		}else if (strcasecmp(tmp,"QCIF")==0){			vsize->width=MS_VIDEO_SIZE_QCIF_W;			vsize->height=MS_VIDEO_SIZE_QCIF_H;		}else{			ms_warning("unsupported video size %s",tmp);			ret=FALSE;		}		divider=atoi(equal+1);		if (divider!=0){			float newfps=29.97/divider;			if (*fps>newfps) *fps=newfps;		}else{			ms_warning("Could not find video fps");			ret=FALSE;		}	}else ret=FALSE;	ms_free(tmp);	return ret;}static int enc_add_fmtp(MSFilter *f,void *arg){	EncState *s=(EncState*)f->data;	const char *fmtp=(const char*)arg;	char val[10];	if (fmtp_get_value(fmtp,"profile",val,sizeof(val))){		s->profile=atoi(val);	}else parse_video_fmtp(fmtp,&s->fps,&s->vsize);	return 0;}static int enc_req_vfu(MSFilter *f, void *unused){	EncState *s=(EncState*)f->data;	s->req_vfu=TRUE;	return 0;}static void enc_init(MSFilter *f, enum CodecID codec){	EncState *s=(EncState *)ms_new(EncState,1);	f->data=s;	ms_ffmpeg_check_init();	s->profile=0;/*always default to profile 0*/	s->comp_buf=allocb(32000,0);	s->fps=15;	s->mtu=ms_get_payload_max_size()-2;/*-2 for the H263 payload header*/	s->maxbr=500000;	s->codec=codec;	s->vsize.width=MS_VIDEO_SIZE_CIF_W;	s->vsize.height=MS_VIDEO_SIZE_CIF_H;	s->qmin=2;	s->req_vfu=FALSE;	s->av_context.codec=NULL;}static void enc_h263_init(MSFilter *f){	enc_init(f,CODEC_ID_H263P);}static void enc_mpeg4_init(MSFilter *f){	enc_init(f,CODEC_ID_MPEG4);}static void enc_snow_init(MSFilter *f){	enc_init(f,CODEC_ID_SNOW);}static void prepare(EncState *s){	AVCodecContext *c=&s->av_context;	avcodec_get_context_defaults(c);	/* put codec parameters */	c->bit_rate=(float)s->maxbr*0.7;	c->bit_rate_tolerance=(float)c->bit_rate/(s->fps-1);	if (s->codec!=CODEC_ID_SNOW && s->maxbr<256000){		/*snow does not like 1st pass rate control*/		/*and rate control eats too much cpu with CIF high fps pictures*/		c->rc_max_rate=(float)s->maxbr*0.8;		c->rc_min_rate=c->bit_rate;		c->rc_buffer_size=c->rc_max_rate;	}else{		/*use qmin instead*/		c->qmin=s->qmin;	}	ms_message("Codec bitrate set to %i",c->bit_rate);	c->width = s->vsize.width;  	c->height = s->vsize.height;	c->time_base.num = 1;	c->time_base.den = (int)s->fps;	c->gop_size=(int)s->fps*5; /*emit I frame every 5 seconds*/	c->pix_fmt=PIX_FMT_YUV420P;		if (s->codec==CODEC_ID_SNOW){		c->strict_std_compliance=-2;	}	}static void prepare_h263(EncState *s){	AVCodecContext *c=&s->av_context;	/* we don't use the rtp_callback but use rtp_mode that forces ffmpeg to insert	Start Codes as much as possible in the bitstream */#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)        c->rtp_mode = 1;#endif	c->rtp_payload_size = s->mtu/2;	if (s->profile==0){		s->codec=CODEC_ID_H263;	}else{		c->flags|=CODEC_FLAG_H263P_UMV;		c->flags|=CODEC_FLAG_AC_PRED;		c->flags|=CODEC_FLAG_H263P_SLICE_STRUCT;		/*		c->flags|=CODEC_FLAG_OBMC;		c->flags|=CODEC_FLAG_AC_PRED;		*/		s->codec=CODEC_ID_H263P;	}}static void prepare_mpeg4(EncState *s){	AVCodecContext *c=&s->av_context;	c->max_b_frames=0; /*don't use b frames*/	c->flags|=CODEC_FLAG_AC_PRED;	c->flags|=CODEC_FLAG_H263P_UMV;	/*c->flags|=CODEC_FLAG_QPEL;*/ /*don't enable this one: this forces profile_level to advanced simple profile */	c->flags|=CODEC_FLAG_4MV;	c->flags|=CODEC_FLAG_GMC;	c->flags|=CODEC_FLAG_LOOP_FILTER;	c->flags|=CODEC_FLAG_H263P_SLICE_STRUCT;}static void enc_uninit(MSFilter  *f){	EncState *s=(EncState*)f->data;	if (s->comp_buf!=NULL)	freemsg(s->comp_buf);	ms_free(s);}#if 0static void enc_set_rc(EncState *s, AVCodecContext *c){	int factor=c->width/MS_VIDEO_SIZE_QCIF_W;	c->rc_min_rate=0;	c->bit_rate=400; /* this value makes around 100kbit/s at QCIF=2 */	c->rc_max_rate=c->bit_rate+1;	c->rc_buffer_size=20000*factor;	/* food recipe */}#endifstatic void enc_preprocess(MSFilter *f){	EncState *s=(EncState*)f->data;	int error;	prepare(s);	if (s->codec==CODEC_ID_H263P || s->codec==CODEC_ID_H263)		prepare_h263(s);	else if (s->codec==CODEC_ID_MPEG4)		prepare_mpeg4(s);	else if (s->codec==CODEC_ID_SNOW){		/**/	}else {		ms_error("Unsupported codec id %i",s->codec);		return;	}	s->av_codec=avcodec_find_encoder(s->codec);	if (s->av_codec==NULL){		ms_error("could not find encoder for codec id %i",s->codec);		return;	}	error=avcodec_open(&s->av_context, s->av_codec);	if (error!=0) {		ms_error("avcodec_open() failed: %i",error);		return;	}	ms_debug("image format is %i.",s->av_context.pix_fmt);	ms_message("qmin=%i qmax=%i",s->av_context.qmin,s->av_context.qmax);}static void enc_postprocess(MSFilter *f){	EncState *s=(EncState*)f->data;	if (s->av_context.codec!=NULL){		avcodec_close(&s->av_context);		s->av_context.codec=NULL;	}}static void add_rfc2190_header(mblk_t **packet, AVCodecContext *context){	mblk_t *header;	header = allocb(4, 0);	memset(header->b_wptr, 0, 4);	// assume video size is CIF or QCIF	if (context->width == 352 && context->height == 288) header->b_wptr[1] = 0x60;	else header->b_wptr[1] = 0x40;	if (context->coded_frame->pict_type != FF_I_TYPE) header->b_wptr[1] |= 0x10;	header->b_wptr += 4;	header->b_cont = *packet;	*packet = header;}static int get_gbsc(uint8_t *psc, uint8_t *end){	int len = end-psc;	uint32_t buf;	int i, j, k;	k = len;	for (i = 2; i < len-4; i++) {		buf = *((uint32_t *)(psc+i));		for (j = 0; j < 8; j++) {			if (((buf >> j) & 0x00FCFFFF) == 0x00800000) {/*PSC*/				i += 2;				k=i;				break;			} else if (((buf >> j) & 0x0080FFFF) == 0x00800000) {/*GBSC*/				i += 2;				k = i;				break;			}		}	}	return k;}static void rfc2190_generate_packets(MSFilter *f, EncState *s, mblk_t *frame, uint32_t timestamp){	mblk_t *packet=NULL;		while (frame->b_rptr<frame->b_wptr){		packet=dupb(frame);		frame->b_rptr=packet->b_wptr=packet->b_rptr+get_gbsc(packet->b_rptr, MIN(packet->b_rptr+s->mtu,frame->b_wptr));		add_rfc2190_header(&packet, &s->av_context);		mblk_set_timestamp_info(packet,timestamp);		ms_queue_put(f->outputs[0],packet);	}	/* the marker bit is set on the last packet, if any.*/	mblk_set_marker_info(packet,TRUE);}static void mpeg4_fragment_and_send(MSFilter *f,EncState *s,mblk_t *frame, uint32_t timestamp){	uint8_t *rptr;	mblk_t *packet=NULL;	int len;	for (rptr=frame->b_rptr;rptr<frame->b_wptr;){		len=MIN(s->mtu,(frame->b_wptr-rptr));		packet=dupb(frame);		packet->b_rptr=rptr;		packet->b_wptr=rptr+len;

⌨️ 快捷键说明

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