📄 videoenc.c
字号:
mblk_set_timestamp_info(packet,timestamp); ms_queue_put(f->outputs[0],packet); rptr+=len; } /*set marker bit on last packet*/ mblk_set_marker_info(packet,TRUE);}static void rfc4629_generate_follow_on_packets(MSFilter *f, EncState *s, mblk_t *frame, uint32_t timestamp, uint8_t *psc, uint8_t *end, bool_t last_packet){ mblk_t *packet; int len=end-psc; packet=dupb(frame); packet->b_rptr=psc; packet->b_wptr=end; /*ms_message("generating packet of size %i",end-psc);*/ rfc2429_set_P(psc,1); mblk_set_timestamp_info(packet,timestamp); if (len>s->mtu){ /*need to slit the packet using "follow-on" packets */ /*compute the number of packets need (rounded up)*/ int num=(len+s->mtu-1)/s->mtu; int i; uint8_t *pos; /*adjust the first packet generated*/ pos=packet->b_wptr=packet->b_rptr+s->mtu; ms_queue_put(f->outputs[0],packet); ms_debug("generating %i follow-on packets",num); for (i=1;i<num;++i){ mblk_t *header; packet=dupb(frame); packet->b_rptr=pos; pos=packet->b_wptr=MIN(pos+s->mtu,end); header=allocb(2,0); header->b_wptr[0]=0; header->b_wptr[1]=0; header->b_wptr+=2; /*no P bit is set */ header->b_cont=packet; packet=header; mblk_set_timestamp_info(packet,timestamp); ms_queue_put(f->outputs[0],packet); } }else ms_queue_put(f->outputs[0],packet); /* the marker bit is set on the last packet, if any.*/ mblk_set_marker_info(packet,last_packet);}/* returns the last psc position just below packet_size */static uint8_t *get_psc(uint8_t *begin,uint8_t *end, int packet_size){ int i; uint8_t *ret=NULL; uint8_t *p; if (begin==end) return NULL; for(i=1,p=begin+1;p<end && i<packet_size;++i,++p){ if (p[-1]==0 && p[0]==0){ ret=p-1; } p++;/* to skip possible 0 after the PSC that would make a double detection */ } return ret;}static void split_and_send(MSFilter *f, EncState *s, mblk_t *frame){ uint8_t *lastpsc; uint8_t *psc; uint32_t timestamp=f->ticker->time*90LL; if (s->codec==CODEC_ID_MPEG4 || s->codec==CODEC_ID_SNOW) { mpeg4_fragment_and_send(f,s,frame,timestamp); return; } ms_debug("processing frame of size %i",frame->b_wptr-frame->b_rptr); if (f->desc->id==MS_H263_ENC_ID){ lastpsc=frame->b_rptr; while(1){ psc=get_psc(lastpsc+2,frame->b_wptr,s->mtu); if (psc!=NULL){ rfc4629_generate_follow_on_packets(f,s,frame,timestamp,lastpsc,psc,FALSE); lastpsc=psc; }else break; } /* send the end of frame */ rfc4629_generate_follow_on_packets(f,s,frame, timestamp,lastpsc,frame->b_wptr,TRUE); }else if (f->desc->id==MS_H263_OLD_ENC_ID){ rfc2190_generate_packets(f,s,frame,timestamp); }else{ ms_fatal("Ca va tres mal."); }}static void process_frame(MSFilter *f, mblk_t *inm){ EncState *s=(EncState*)f->data; AVFrame pict; AVCodecContext *c=&s->av_context; int error; mblk_t *comp_buf=s->comp_buf; int comp_buf_sz=comp_buf->b_datap->db_lim-comp_buf->b_datap->db_base; /* convert image if necessary */ avcodec_get_frame_defaults(&pict); avpicture_fill((AVPicture*)&pict,(uint8_t*)inm->b_rptr,c->pix_fmt,c->width,c->height); /* timestamp used by ffmpeg, unset here */ pict.pts=AV_NOPTS_VALUE; if (s->req_vfu){ pict.pict_type=FF_I_TYPE; s->req_vfu=FALSE; } comp_buf->b_rptr=comp_buf->b_wptr=comp_buf->b_datap->db_base; if (s->codec==CODEC_ID_SNOW){ //prepend picture size uint32_t header=((s->vsize.width&0xffff)<<16) | (s->vsize.height&0xffff); *(uint32_t*)comp_buf->b_wptr=htonl(header); comp_buf->b_wptr+=4; comp_buf_sz-=4; } error=avcodec_encode_video(c, (uint8_t*)comp_buf->b_wptr,comp_buf_sz, &pict); if (error<=0) ms_warning("ms_AVencoder_process: error %i.",error); else{ if (c->coded_frame->pict_type==FF_I_TYPE){ ms_message("Emitting I-frame"); } comp_buf->b_wptr+=error; split_and_send(f,s,comp_buf); } freemsg(inm);}static void enc_process(MSFilter *f){ mblk_t *inm; EncState *s=(EncState*)f->data; if (s->av_context.codec==NULL) { ms_queue_flush(f->inputs[0]); return; } ms_filter_lock(f); while((inm=ms_queue_get(f->inputs[0]))!=0){ process_frame(f,inm); } ms_filter_unlock(f);}static int enc_get_br(MSFilter *f, void *arg){ EncState *s=(EncState*)f->data; *(int*)arg=s->maxbr; return 0;}static int enc_set_br(MSFilter *f, void *arg){ EncState *s=(EncState*)f->data; bool_t snow=s->codec==CODEC_ID_SNOW; s->maxbr=*(int*)arg; if (s->maxbr>=1024000 && s->codec!=CODEC_ID_H263P){ s->vsize.width = MS_VIDEO_SIZE_4CIF_W; s->vsize.height = MS_VIDEO_SIZE_4CIF_H; s->fps=17; }else if (s->maxbr>=512000){ s->vsize.width=MS_VIDEO_SIZE_CIF_W; s->vsize.height=MS_VIDEO_SIZE_CIF_H; s->fps=17; }else if (s->maxbr>=256000){ s->vsize.width=MS_VIDEO_SIZE_CIF_W; s->vsize.height=MS_VIDEO_SIZE_CIF_H; s->fps=10; s->qmin=3; }else if (s->maxbr>=128000){ s->vsize.width=MS_VIDEO_SIZE_QCIF_W; s->vsize.height=MS_VIDEO_SIZE_QCIF_H; s->fps=10; s->qmin=3; }else if (s->maxbr>=64000){ s->vsize.width=MS_VIDEO_SIZE_QCIF_W; s->vsize.height=MS_VIDEO_SIZE_QCIF_H; s->fps=snow ? 7 : 5; s->qmin=snow ? 4 : 5; }else{ s->vsize.width=MS_VIDEO_SIZE_QCIF_W; s->vsize.height=MS_VIDEO_SIZE_QCIF_H; s->fps=5; s->qmin=5; } if (s->av_context.codec!=NULL){ /*apply new settings dynamically*/ ms_filter_lock(f); enc_postprocess(f); enc_preprocess(f); ms_filter_lock(f); } return 0;}static MSFilterMethod methods[]={ { MS_FILTER_SET_FPS , enc_set_fps }, { MS_FILTER_GET_FPS , enc_get_fps }, { MS_FILTER_SET_VIDEO_SIZE , enc_set_vsize }, { MS_FILTER_GET_VIDEO_SIZE , enc_get_vsize }, { MS_FILTER_ADD_FMTP , enc_add_fmtp }, { MS_FILTER_SET_BITRATE , enc_set_br }, { MS_FILTER_GET_BITRATE , enc_get_br }, { MS_FILTER_SET_MTU , enc_set_mtu }, { MS_FILTER_REQ_VFU , enc_req_vfu }, { 0 , NULL }};#ifdef _MSC_VERMSFilterDesc ms_h263_enc_desc={ MS_H263_ENC_ID, "MSH263Enc", "A video H.263 encoder using ffmpeg library.", MS_FILTER_ENCODER, "H263-1998", 1, /*MS_YUV420P is assumed on this input */ 1, enc_h263_init, enc_preprocess, enc_process, enc_postprocess, enc_uninit, methods};MSFilterDesc ms_h263_old_enc_desc={ MS_H263_OLD_ENC_ID, "MSH263OldEnc", "A video H.263 encoder using ffmpeg library. It is compliant with old RFC2190 spec.", MS_FILTER_ENCODER, "H263", 1, /*MS_YUV420P is assumed on this input */ 1, enc_h263_init, enc_preprocess, enc_process, enc_postprocess, enc_uninit, methods};MSFilterDesc ms_mpeg4_enc_desc={ MS_MPEG4_ENC_ID, "MSMpeg4Enc", "A video MPEG4 encoder using ffmpeg library.", MS_FILTER_ENCODER, "MP4V-ES", 1, /*MS_YUV420P is assumed on this input */ 1, enc_mpeg4_init, enc_preprocess, enc_process, enc_postprocess, enc_uninit, methods};MSFilterDesc ms_snow_enc_desc={ MS_SNOW_ENC_ID, "MSSnowEnc", "A video snow encoder using ffmpeg library.", MS_FILTER_ENCODER, "x-snow", 1, /*MS_YUV420P is assumed on this input */ 1, enc_snow_init, enc_preprocess, enc_process, enc_postprocess, enc_uninit, methods};#elseMSFilterDesc ms_h263_enc_desc={ .id=MS_H263_ENC_ID, .name="MSH263Enc", .text="A video H.263 encoder using ffmpeg library.", .category=MS_FILTER_ENCODER, .enc_fmt="H263-1998", .ninputs=1, /*MS_YUV420P is assumed on this input */ .noutputs=1, .init=enc_h263_init, .preprocess=enc_preprocess, .process=enc_process, .postprocess=enc_postprocess, .uninit=enc_uninit, .methods=methods};MSFilterDesc ms_h263_old_enc_desc={ .id=MS_H263_OLD_ENC_ID, .name="MSH263Enc", .text="A video H.263 encoder using ffmpeg library, compliant with old RFC2190 spec.", .category=MS_FILTER_ENCODER, .enc_fmt="H263", .ninputs=1, /*MS_YUV420P is assumed on this input */ .noutputs=1, .init=enc_h263_init, .preprocess=enc_preprocess, .process=enc_process, .postprocess=enc_postprocess, .uninit=enc_uninit, .methods=methods};MSFilterDesc ms_mpeg4_enc_desc={ .id=MS_MPEG4_ENC_ID, .name="MSMpeg4Enc", .text="A video MPEG4 encoder using ffmpeg library.", .category=MS_FILTER_ENCODER, .enc_fmt="MP4V-ES", .ninputs=1, /*MS_YUV420P is assumed on this input */ .noutputs=1, .init=enc_mpeg4_init, .preprocess=enc_preprocess, .process=enc_process, .postprocess=enc_postprocess, .uninit=enc_uninit, .methods=methods};MSFilterDesc ms_snow_enc_desc={ .id=MS_SNOW_ENC_ID, .name="MSSnowEnc", .text="The snow codec is royalty-free and is open-source. \n" "It uses innovative techniques that makes it one of the best video " "codec. It is implemented within the ffmpeg project.\n" "However it is under development and compatibility with other versions " "cannot be guaranteed.", .category=MS_FILTER_ENCODER, .enc_fmt="x-snow", .ninputs=1, /*MS_YUV420P is assumed on this input */ .noutputs=1, .init=enc_snow_init, .preprocess=enc_preprocess, .process=enc_process, .postprocess=enc_postprocess, .uninit=enc_uninit, .methods=methods};#endifMS_FILTER_DESC_EXPORT(ms_mpeg4_enc_desc)MS_FILTER_DESC_EXPORT(ms_h263_enc_desc)MS_FILTER_DESC_EXPORT(ms_h263_old_enc_desc)MS_FILTER_DESC_EXPORT(ms_snow_enc_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -