]> sjero.net Git - linphone/blob - linphone/mediastreamer2/src/videoenc.c
remote ortp and add it as a submodule instead.
[linphone] / linphone / mediastreamer2 / src / videoenc.c
1 /*
2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "mediastreamer-config.h"
22 #endif
23
24 #ifdef HAVE_LIBAVCODEC_AVCODEC_H
25 #include <libavcodec/avcodec.h>
26 #else
27 #include <ffmpeg/avcodec.h>
28 #endif
29
30 #include "mediastreamer2/msfilter.h"
31 #include "mediastreamer2/msvideo.h"
32 #include "mediastreamer2/msticker.h"
33
34 #ifdef _WIN32
35 #include <ws2tcpip.h>
36 #else
37 #include <netinet/in.h>                 /* ntohl(3) */
38 #endif
39
40 #include "rfc2429.h"
41
42 static bool_t avcodec_initialized=FALSE;
43
44 #ifdef ENABLE_LOG_FFMPEG
45
46 void ms_ffmpeg_log_callback(void* ptr, int level, const char* fmt, va_list vl)
47 {
48         static char message[8192];
49
50     vsnprintf(message, sizeof message, fmt, vl);
51         ms_message(message);
52 }
53
54 #endif
55
56 void ms_ffmpeg_check_init(){
57         if(!avcodec_initialized){
58                 avcodec_init();
59                 avcodec_register_all();
60                 avcodec_initialized=TRUE;
61 #ifdef ENABLE_LOG_FFMPEG
62                 av_log_set_level(AV_LOG_WARNING);
63                 av_log_set_callback(&ms_ffmpeg_log_callback);
64 #endif
65         }
66 }
67
68 typedef struct EncState{
69         AVCodecContext av_context;
70         AVCodec *av_codec;
71         enum CodecID codec;
72         mblk_t *comp_buf;
73         MSVideoSize vsize;
74         int mtu;        /* network maximum transmission unit in bytes */
75         int profile;
76         float fps;
77         int maxbr;
78         int qmin;
79         uint32_t framenum;
80         bool_t req_vfu;
81 }EncState;
82
83 static int enc_set_fps(MSFilter *f, void *arg){
84         EncState *s=(EncState*)f->data;
85         s->fps=*(float*)arg;
86         return 0;
87 }
88
89 static int enc_get_fps(MSFilter *f, void *arg){
90         EncState *s=(EncState*)f->data;
91         *(float*)arg=s->fps;
92         return 0;
93 }
94
95 static int enc_set_vsize(MSFilter *f,void *arg){
96         EncState *s=(EncState*)f->data;
97         s->vsize=*(MSVideoSize*)arg;
98         return 0;
99 }
100
101 static int enc_get_vsize(MSFilter *f,void *arg){
102         EncState *s=(EncState*)f->data;
103         *(MSVideoSize*)arg=s->vsize;
104         return 0;
105 }
106
107 static int enc_set_mtu(MSFilter *f,void *arg){
108         EncState *s=(EncState*)f->data;
109         s->mtu=*(int*)arg;
110         return 0;
111 }
112
113 static bool_t parse_video_fmtp(const char *fmtp, float *fps, MSVideoSize *vsize){
114         char *tmp=ms_strdup(fmtp);
115         char *semicolon;
116         char *equal;
117         bool_t ret=TRUE;
118
119         ms_message("parsing %s",fmtp);
120         /*extract fisrt pair */
121         if ((semicolon=strchr(tmp,';'))!=NULL){
122                 *semicolon='\0';
123         }
124         if ((equal=strchr(tmp,'='))!=NULL){
125                 int divider;
126                 *equal='\0';
127                 if (strcasecmp(tmp,"CIF")==0){
128                         if (vsize->width>=MS_VIDEO_SIZE_CIF_W){
129                                 vsize->width=MS_VIDEO_SIZE_CIF_W;
130                                 vsize->height=MS_VIDEO_SIZE_CIF_H;
131                         }
132                 }else if (strcasecmp(tmp,"QCIF")==0){
133                         vsize->width=MS_VIDEO_SIZE_QCIF_W;
134                         vsize->height=MS_VIDEO_SIZE_QCIF_H;
135                 }else{
136                         ms_warning("unsupported video size %s",tmp);
137                         ret=FALSE;
138                 }
139                 divider=atoi(equal+1);
140                 if (divider!=0){
141                         float newfps=29.97/divider;
142                         if (*fps>newfps) *fps=newfps;
143                 }else{
144                         ms_warning("Could not find video fps");
145                         ret=FALSE;
146                 }
147         }else ret=FALSE;
148         ms_free(tmp);
149         return ret;
150 }
151
152 static int enc_add_fmtp(MSFilter *f,void *arg){
153         EncState *s=(EncState*)f->data;
154         const char *fmtp=(const char*)arg;
155         char val[10];
156         if (fmtp_get_value(fmtp,"profile",val,sizeof(val))){
157                 s->profile=atoi(val);
158         }else parse_video_fmtp(fmtp,&s->fps,&s->vsize);
159         return 0;
160 }
161
162 static int enc_req_vfu(MSFilter *f, void *unused){
163         EncState *s=(EncState*)f->data;
164         s->req_vfu=TRUE;
165         return 0;
166 }
167
168 static void enc_init(MSFilter *f, enum CodecID codec)
169 {
170         EncState *s=(EncState *)ms_new(EncState,1);
171         f->data=s;
172         ms_ffmpeg_check_init();
173         s->profile=0;/*always default to profile 0*/
174         s->comp_buf=NULL;
175         s->fps=15;
176         s->mtu=ms_get_payload_max_size()-2;/*-2 for the H263 payload header*/
177         s->maxbr=500000;
178         s->codec=codec;
179         s->vsize.width=MS_VIDEO_SIZE_CIF_W;
180         s->vsize.height=MS_VIDEO_SIZE_CIF_H;
181         s->qmin=2;
182         s->req_vfu=FALSE;
183         s->framenum=0;
184         s->av_context.codec=NULL;
185 }
186
187 static void enc_h263_init(MSFilter *f){
188         enc_init(f,CODEC_ID_H263P);
189 }
190
191 static void enc_mpeg4_init(MSFilter *f){
192         enc_init(f,CODEC_ID_MPEG4);
193 }
194
195 static void enc_snow_init(MSFilter *f){
196         enc_init(f,CODEC_ID_SNOW);
197 }
198
199 static void enc_mjpeg_init(MSFilter *f){
200         enc_init(f,CODEC_ID_MJPEG);
201 }
202
203 static void prepare(EncState *s){
204         AVCodecContext *c=&s->av_context;
205         avcodec_get_context_defaults(c);
206         if (s->codec==CODEC_ID_MJPEG)
207         {
208                 ms_message("Codec bitrate set to %i",c->bit_rate);
209                 c->width = s->vsize.width;  
210                 c->height = s->vsize.height;
211                 c->time_base.num = 1;
212                 c->time_base.den = (int)s->fps;
213                 c->gop_size=(int)s->fps*5; /*emit I frame every 5 seconds*/
214                 c->pix_fmt=PIX_FMT_YUVJ420P;
215                 s->comp_buf=allocb(c->bit_rate*2,0);
216                 return;
217         }
218
219         /* put codec parameters */
220         c->bit_rate=(float)s->maxbr*0.7;
221         c->bit_rate_tolerance=s->fps!=1?(float)c->bit_rate/(s->fps-1):c->bit_rate;
222
223         if (s->codec!=CODEC_ID_SNOW && s->maxbr<256000){
224                 /*snow does not like 1st pass rate control*/
225                 /*and rate control eats too much cpu with CIF high fps pictures*/
226                 c->rc_max_rate=(float)s->maxbr*0.8;
227                 c->rc_min_rate=0;
228                 c->rc_buffer_size=c->rc_max_rate;
229         }else{
230                 /*use qmin instead*/
231                 c->qmin=s->qmin;
232         }
233
234         ms_message("Codec bitrate set to %i",c->bit_rate);
235         c->width = s->vsize.width;  
236         c->height = s->vsize.height;
237         c->time_base.num = 1;
238         c->time_base.den = (int)s->fps;
239         c->gop_size=(int)s->fps*5; /*emit I frame every 5 seconds*/
240         c->pix_fmt=PIX_FMT_YUV420P;
241         s->comp_buf=allocb(c->bit_rate*2,0);
242         if (s->codec==CODEC_ID_SNOW){
243                 c->strict_std_compliance=-2;
244         }
245         
246 }
247
248 static void prepare_h263(EncState *s){
249         AVCodecContext *c=&s->av_context;
250         /* we don't use the rtp_callback but use rtp_mode that forces ffmpeg to insert
251         Start Codes as much as possible in the bitstream */
252 #if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
253         c->rtp_mode = 1;
254 #endif
255         c->rtp_payload_size = s->mtu/2;
256         if (s->profile==0){
257                 s->codec=CODEC_ID_H263;
258         }else{
259                 c->flags|=CODEC_FLAG_H263P_UMV;
260                 c->flags|=CODEC_FLAG_AC_PRED;
261                 c->flags|=CODEC_FLAG_H263P_SLICE_STRUCT;
262                 /*
263                 c->flags|=CODEC_FLAG_OBMC;
264                 c->flags|=CODEC_FLAG_AC_PRED;
265                 */
266                 s->codec=CODEC_ID_H263P;
267         }
268 }
269
270 static void prepare_mpeg4(EncState *s){
271         AVCodecContext *c=&s->av_context;
272         c->max_b_frames=0; /*don't use b frames*/
273         c->flags|=CODEC_FLAG_AC_PRED;
274         c->flags|=CODEC_FLAG_H263P_UMV;
275         /*c->flags|=CODEC_FLAG_QPEL;*/ /*don't enable this one: this forces profile_level to advanced simple profile */
276         c->flags|=CODEC_FLAG_4MV;
277         c->flags|=CODEC_FLAG_GMC;
278         c->flags|=CODEC_FLAG_LOOP_FILTER;
279         c->flags|=CODEC_FLAG_H263P_SLICE_STRUCT;
280 }
281
282 static void enc_uninit(MSFilter  *f){
283         EncState *s=(EncState*)f->data;
284         ms_free(s);
285 }
286 #if 0
287 static void enc_set_rc(EncState *s, AVCodecContext *c){
288         int factor=c->width/MS_VIDEO_SIZE_QCIF_W;
289         c->rc_min_rate=0;
290         c->bit_rate=400; /* this value makes around 100kbit/s at QCIF=2 */
291         c->rc_max_rate=c->bit_rate+1;
292         c->rc_buffer_size=20000*factor; /* food recipe */
293 }
294 #endif
295
296 static void enc_preprocess(MSFilter *f){
297         EncState *s=(EncState*)f->data;
298         int error;
299         prepare(s);
300         if (s->codec==CODEC_ID_H263P || s->codec==CODEC_ID_H263)
301                 prepare_h263(s);
302         else if (s->codec==CODEC_ID_MPEG4)
303                 prepare_mpeg4(s);
304         else if (s->codec==CODEC_ID_SNOW){
305                 /**/
306         }else if (s->codec==CODEC_ID_MJPEG){
307                 /**/
308         }else {
309                 ms_error("Unsupported codec id %i",s->codec);
310                 return;
311         }
312         s->av_codec=avcodec_find_encoder(s->codec);
313         if (s->av_codec==NULL){
314                 ms_error("could not find encoder for codec id %i",s->codec);
315                 return;
316         }
317         error=avcodec_open(&s->av_context, s->av_codec);
318         if (error!=0) {
319                 ms_error("avcodec_open() failed: %i",error);
320                 return;
321         }
322         ms_debug("image format is %i.",s->av_context.pix_fmt);
323         ms_message("qmin=%i qmax=%i",s->av_context.qmin,s->av_context.qmax);
324 }
325
326 static void enc_postprocess(MSFilter *f){
327         EncState *s=(EncState*)f->data;
328         if (s->av_context.codec!=NULL){
329                 avcodec_close(&s->av_context);
330                 s->av_context.codec=NULL;
331         }
332         if (s->comp_buf!=NULL)  {
333                 freemsg(s->comp_buf);
334                 s->comp_buf=NULL;
335         }
336 }
337
338 static void add_rfc2190_header(mblk_t **packet, AVCodecContext *context){
339         mblk_t *header;
340         header = allocb(4, 0);
341         memset(header->b_wptr, 0, 4);
342         // assume video size is CIF or QCIF
343         if (context->width == 352 && context->height == 288) header->b_wptr[1] = 0x60;
344         else header->b_wptr[1] = 0x40;
345         if (context->coded_frame->pict_type != FF_I_TYPE) header->b_wptr[1] |= 0x10;
346         header->b_wptr += 4;
347         header->b_cont = *packet;
348         *packet = header;
349 }
350
351 #if 0
352 static int get_gbsc(uint8_t *psc, uint8_t *end)
353 {
354         int len = end-psc;
355         uint32_t buf;
356         int i, j, k;
357         k = len;
358         for (i = 2; i < len-4; i++) {
359                 buf = *((uint32_t *)(psc+i));
360                 for (j = 0; j < 8; j++) {
361                         if (((buf >> j) & 0x00FCFFFF) == 0x00800000) {/*PSC*/
362                                 i += 2;
363                                 k=i;
364                                 break;
365                         } else if (((buf >> j) & 0x0080FFFF) == 0x00800000) {/*GBSC*/
366                                 i += 2;
367                                 k = i;
368                                 break;
369                         }
370                 }
371         }
372         return k;
373 }
374 #else
375 static int get_gbsc_bytealigned(uint8_t *begin, uint8_t *end){
376         int i;
377         int len = end - begin;
378         for (i = len - 2;  /*len + length of scan window*/
379            i > 2 + 2; /*length of scan window + 2 avoidance of 1st gob or psc*/
380            i--){
381                 if(*(begin + i) == 0 &&
382                    *(begin + i+1) == 0 &&
383                    (*(begin + i+2) & 0x80) == 0x80){
384                   /*ms_message("JV psc/gob found! %2x %2x %2x", *(begin + i), *(begin + i+1), *(begin + i + 2));*/
385                   return i;
386                 }
387         }
388         /*ms_message("JV no psc or gob found!");*/
389         return len;
390 }
391 #endif
392
393 static void rfc2190_generate_packets(MSFilter *f, EncState *s, mblk_t *frame, uint32_t timestamp){
394         mblk_t *packet=NULL;
395         
396         while (frame->b_rptr<frame->b_wptr){
397                 packet=dupb(frame);
398                 /*frame->b_rptr=packet->b_wptr=packet->b_rptr+get_gbsc(packet->b_rptr, MIN(packet->b_rptr+s->mtu,frame->b_wptr));*/
399                 frame->b_rptr = packet->b_wptr =
400                         packet->b_rptr + get_gbsc_bytealigned(packet->b_rptr, MIN(packet->b_rptr+s->mtu,frame->b_wptr));
401                 add_rfc2190_header(&packet, &s->av_context);
402                 mblk_set_timestamp_info(packet,timestamp);
403                 ms_queue_put(f->outputs[0],packet);
404         }
405         /* the marker bit is set on the last packet, if any.*/
406         mblk_set_marker_info(packet,TRUE);
407 }
408
409 static void mpeg4_fragment_and_send(MSFilter *f,EncState *s,mblk_t *frame, uint32_t timestamp){
410         uint8_t *rptr;
411         mblk_t *packet=NULL;
412         int len;
413         for (rptr=frame->b_rptr;rptr<frame->b_wptr;){
414                 len=MIN(s->mtu,(frame->b_wptr-rptr));
415                 packet=dupb(frame);
416                 packet->b_rptr=rptr;
417                 packet->b_wptr=rptr+len;
418                 mblk_set_timestamp_info(packet,timestamp);
419                 ms_queue_put(f->outputs[0],packet);
420                 rptr+=len;
421         }
422         /*set marker bit on last packet*/
423         mblk_set_marker_info(packet,TRUE);
424 }
425
426 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){
427         mblk_t *packet;
428         int len=end-psc;
429         
430         packet=dupb(frame);     
431         packet->b_rptr=psc;
432         packet->b_wptr=end;
433         /*ms_message("generating packet of size %i",end-psc);*/
434         rfc2429_set_P(psc,1);
435         mblk_set_timestamp_info(packet,timestamp);
436
437         
438         if (len>s->mtu){
439                 /*need to slit the packet using "follow-on" packets */
440                 /*compute the number of packets need (rounded up)*/
441                 int num=(len+s->mtu-1)/s->mtu;
442                 int i;
443                 uint8_t *pos;
444                 /*adjust the first packet generated*/
445                 pos=packet->b_wptr=packet->b_rptr+s->mtu;
446                 ms_queue_put(f->outputs[0],packet);
447                 ms_debug("generating %i follow-on packets",num);
448                 for (i=1;i<num;++i){
449                         mblk_t *header;
450                         packet=dupb(frame);
451                         packet->b_rptr=pos;
452                         pos=packet->b_wptr=MIN(pos+s->mtu,end);
453                         header=allocb(2,0);
454                         header->b_wptr[0]=0;
455                         header->b_wptr[1]=0;
456                         header->b_wptr+=2;
457                         /*no P bit is set */
458                         header->b_cont=packet;
459                         packet=header;
460                         mblk_set_timestamp_info(packet,timestamp);
461                         ms_queue_put(f->outputs[0],packet);
462                 }
463         }else ms_queue_put(f->outputs[0],packet);
464         /* the marker bit is set on the last packet, if any.*/
465         mblk_set_marker_info(packet,last_packet);
466 }
467
468 /* returns the last psc position just below packet_size */
469 static uint8_t *get_psc(uint8_t *begin,uint8_t *end, int packet_size){
470         int i;
471         uint8_t *ret=NULL;
472         uint8_t *p;
473         if (begin==end) return NULL;
474         for(i=1,p=begin+1;p<end && i<packet_size;++i,++p){
475                 if (p[-1]==0 && p[0]==0){
476                         ret=p-1;
477                 }
478                 p++;/* to skip possible 0 after the PSC that would make a double detection */
479         }
480         return ret;
481 }
482
483
484 struct jpeghdr {
485         //unsigned int tspec:8;   /* type-specific field */
486         unsigned int off:32;    /* fragment byte offset */
487         uint8_t type;            /* id of jpeg decoder params */
488         uint8_t q;               /* quantization factor (or table id) */
489         uint8_t width;           /* frame width in 8 pixel blocks */
490         uint8_t height;          /* frame height in 8 pixel blocks */
491 };
492
493 struct jpeghdr_rst {
494         uint16_t dri;
495         unsigned int f:1;
496         unsigned int l:1;
497         unsigned int count:14;
498 };
499
500 struct jpeghdr_qtable {
501         uint8_t  mbz;
502         uint8_t  precision;
503         uint16_t length;
504 };
505
506 #define RTP_JPEG_RESTART           0x40
507
508 /* Procedure SendFrame:
509  *
510  *  Arguments:
511  *    start_seq: The sequence number for the first packet of the current
512  *               frame.
513  *    ts: RTP timestamp for the current frame
514  *    ssrc: RTP SSRC value
515  *    jpeg_data: Huffman encoded JPEG scan data
516  *    len: Length of the JPEG scan data
517  *    type: The value the RTP/JPEG type field should be set to
518  *    typespec: The value the RTP/JPEG type-specific field should be set
519  *              to
520  *    width: The width in pixels of the JPEG image
521  *    height: The height in pixels of the JPEG image
522  *    dri: The number of MCUs between restart markers (or 0 if there
523  *         are no restart markers in the data
524  *    q: The Q factor of the data, to be specified using the Independent
525  *       JPEG group's algorithm if 1 <= q <= 99, specified explicitly
526  *       with lqt and cqt if q >= 128, or undefined otherwise.
527  *    lqt: The quantization table for the luminance channel if q >= 128
528  *    cqt: The quantization table for the chrominance channels if
529  *         q >= 128
530  *
531  *  Return value:
532  *    the sequence number to be sent for the first packet of the next
533  *    frame.
534  *
535  * The following are assumed to be defined:
536  *
537  * PACKET_SIZE                         - The size of the outgoing packet
538  * send_packet(u_int8 *data, int len)  - Sends the packet to the network
539  */
540
541 static void mjpeg_fragment_and_send(MSFilter *f,EncState *s,mblk_t *frame, uint32_t timestamp,
542                                                          uint8_t type,  uint8_t typespec, int dri,
543                                                          uint8_t q, mblk_t *lqt, mblk_t *cqt) {
544         struct jpeghdr jpghdr;
545         struct jpeghdr_rst rsthdr;
546         struct jpeghdr_qtable qtblhdr;
547         int bytes_left = msgdsize(frame);
548         int data_len;
549         
550         mblk_t *packet;
551         
552         /* Initialize JPEG header
553          */
554         //jpghdr.tspec = typespec;
555         jpghdr.off = 0;
556         jpghdr.type = type | ((dri != 0) ? RTP_JPEG_RESTART : 0);
557         jpghdr.q = q;
558         jpghdr.width = s->vsize.width / 8;
559         jpghdr.height = s->vsize.height / 8;
560
561         /* Initialize DRI header
562          */
563         if (dri != 0) {
564                 rsthdr.dri = htons(dri);
565                 rsthdr.f = 1;        /* This code does not align RIs */
566                 rsthdr.l = 1;
567                 rsthdr.count = 0x3fff;
568         }
569
570         /* Initialize quantization table header
571          */
572         if (q >= 128) {
573                 qtblhdr.mbz = 0;
574                 qtblhdr.precision = 0; /* This code uses 8 bit tables only */
575                 qtblhdr.length = htons(msgdsize(lqt)+msgdsize(cqt));  /* 2 64-byte tables */
576         }
577
578         while (bytes_left > 0) {
579                 packet = allocb(s->mtu, 0);
580
581                 jpghdr.off = htonl(jpghdr.off);
582                 memcpy(packet->b_wptr, &jpghdr, sizeof(jpghdr));
583                 jpghdr.off = ntohl(jpghdr.off);
584                 packet->b_wptr += sizeof(jpghdr);
585
586                 if (dri != 0) {
587                         memcpy(packet->b_wptr, &rsthdr, sizeof(rsthdr));
588                         packet->b_wptr += sizeof(rsthdr);
589                 }
590
591                 if (q >= 128 && jpghdr.off == 0) {
592                         memcpy(packet->b_wptr, &qtblhdr, sizeof(qtblhdr));
593                         packet->b_wptr += sizeof(qtblhdr);
594                         if (msgdsize(lqt)){
595                                 memcpy(packet->b_wptr, lqt->b_rptr, msgdsize(lqt));
596                                 packet->b_wptr += msgdsize(lqt);
597                         }
598                         if (msgdsize(cqt)){
599                                 memcpy(packet->b_wptr, cqt->b_rptr, msgdsize(cqt));
600                                 packet->b_wptr += msgdsize(cqt);
601                         }
602                 }
603
604                 data_len = s->mtu - (packet->b_wptr - packet->b_rptr);
605                 if (data_len >= bytes_left) {
606                         data_len = bytes_left;
607                         mblk_set_marker_info(packet,TRUE);
608                 }
609
610                 memcpy(packet->b_wptr, frame->b_rptr + jpghdr.off, data_len);   
611                 packet->b_wptr=packet->b_wptr + data_len;
612                                 
613                 mblk_set_timestamp_info(packet,timestamp);
614                 ms_queue_put(f->outputs[0],packet);
615
616                 jpghdr.off += data_len;
617                 bytes_left -= data_len;
618         }
619 }
620
621 static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end){
622
623         uint8_t *buf_ptr;
624         unsigned int v, v2;
625         int val;
626
627         buf_ptr = *pbuf_ptr;
628         while (buf_ptr < buf_end) {
629                 v = *buf_ptr++;
630                 v2 = *buf_ptr;
631                 if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) {
632                         val = *buf_ptr++;
633                         *pbuf_ptr = buf_ptr;
634                         return val;
635                 }
636         }
637         val = -1;
638         return val;
639 }
640
641 static mblk_t *skip_jpeg_headers(mblk_t *full_frame, mblk_t **lqt, mblk_t **cqt){
642         int err;
643         uint8_t *pbuf_ptr=full_frame->b_rptr;
644         uint8_t *buf_end=full_frame->b_wptr;    
645
646         ms_message("image size: %i)", buf_end-pbuf_ptr);
647
648         *lqt=NULL;
649         *cqt=NULL;
650
651         err = find_marker(&pbuf_ptr, buf_end);
652         while (err!=-1)
653         {
654                 ms_message("marker found: %x (offset from beginning%i)", err, pbuf_ptr-full_frame->b_rptr);
655                 if (err==0xdb)
656                 {
657                         /* copy DQT table */
658                         int len = ntohs(*(uint16_t*)(pbuf_ptr));
659                         if (*lqt==NULL)
660                         {
661                                 mblk_t *_lqt = allocb(len-3, 0);
662                                 memcpy(_lqt->b_rptr, pbuf_ptr+3, len-3);
663                                 _lqt->b_wptr += len-3;
664                                 *lqt = _lqt;
665                                 //*cqt = dupb(*lqt);
666                         }
667                         else
668                         {
669                                 mblk_t *_cqt = allocb(len-3, 0);
670                                 memcpy(_cqt->b_rptr, pbuf_ptr+3, len-3);
671                                 _cqt->b_wptr += len-3;
672                                 *cqt = _cqt;
673                         }
674                 }
675                 if (err==0xda)
676                 {
677                         uint16_t *bistream=(uint16_t *)pbuf_ptr;
678                         uint16_t len = ntohs(*bistream);
679                         full_frame->b_rptr = pbuf_ptr+len;
680                 }
681                 err = find_marker(&pbuf_ptr, buf_end);
682         }
683         return full_frame;
684 }
685
686 static void split_and_send(MSFilter *f, EncState *s, mblk_t *frame){
687         uint8_t *lastpsc;
688         uint8_t *psc;
689         uint32_t timestamp=f->ticker->time*90LL;
690         
691         if (s->codec==CODEC_ID_MPEG4 || s->codec==CODEC_ID_SNOW)
692         {
693                 mpeg4_fragment_and_send(f,s,frame,timestamp);
694                 return;
695         }
696         else if (s->codec==CODEC_ID_MJPEG)
697         {
698                 mblk_t *lqt=NULL;
699                 mblk_t *cqt=NULL;
700                 skip_jpeg_headers(frame, &lqt, &cqt);
701                 mjpeg_fragment_and_send(f,s,frame,timestamp,
702                                                                 1, /* 420? */
703                                                                 0,
704                                                                 0, /* dri ?*/
705                                                                 255, /* q */
706                                                                 lqt,
707                                                                 cqt);
708                 return;
709         }
710
711         ms_debug("processing frame of size %i",frame->b_wptr-frame->b_rptr);
712         if (f->desc->id==MS_H263_ENC_ID){
713                 lastpsc=frame->b_rptr;
714                 while(1){
715                         psc=get_psc(lastpsc+2,frame->b_wptr,s->mtu);
716                         if (psc!=NULL){
717                                 rfc4629_generate_follow_on_packets(f,s,frame,timestamp,lastpsc,psc,FALSE);
718                                 lastpsc=psc;
719                         }else break;
720                 }
721                 /* send the end of frame */
722                 rfc4629_generate_follow_on_packets(f,s,frame, timestamp,lastpsc,frame->b_wptr,TRUE);
723         }else if (f->desc->id==MS_H263_OLD_ENC_ID){
724                 rfc2190_generate_packets(f,s,frame,timestamp);
725         }else{
726                 ms_fatal("Ca va tres mal.");
727         }
728 }
729
730 static void process_frame(MSFilter *f, mblk_t *inm){
731         EncState *s=(EncState*)f->data;
732         AVFrame pict;
733         AVCodecContext *c=&s->av_context;
734         int error;
735         mblk_t *comp_buf=s->comp_buf;
736         int comp_buf_sz=comp_buf->b_datap->db_lim-comp_buf->b_datap->db_base;
737
738         /* convert image if necessary */
739         avcodec_get_frame_defaults(&pict);
740         avpicture_fill((AVPicture*)&pict,(uint8_t*)inm->b_rptr,c->pix_fmt,c->width,c->height);
741         
742         /* timestamp used by ffmpeg, unset here */
743         pict.pts=AV_NOPTS_VALUE;
744                 
745         if (s->framenum==(int)(s->fps*2.0) || s->framenum==(int)(s->fps*4.0)){
746                 /*sends an I frame at 2 seconds and 4 seconds after the beginning of the call*/
747                 s->req_vfu=TRUE;
748         }
749         if (s->req_vfu){
750                 pict.pict_type=FF_I_TYPE;
751                 s->req_vfu=FALSE;
752         }
753         comp_buf->b_rptr=comp_buf->b_wptr=comp_buf->b_datap->db_base;
754         if (s->codec==CODEC_ID_SNOW){
755                 //prepend picture size
756                 uint32_t header=((s->vsize.width&0xffff)<<16) | (s->vsize.height&0xffff);
757                 *(uint32_t*)comp_buf->b_wptr=htonl(header);
758                 comp_buf->b_wptr+=4;
759                 comp_buf_sz-=4;
760         }
761         error=avcodec_encode_video(c, (uint8_t*)comp_buf->b_wptr,comp_buf_sz, &pict);
762         if (error<=0) ms_warning("ms_AVencoder_process: error %i.",error);
763         else{
764                 s->framenum++;
765                 if (c->coded_frame->pict_type==FF_I_TYPE){
766                         ms_message("Emitting I-frame");
767                 }
768                 comp_buf->b_wptr+=error;
769                 split_and_send(f,s,comp_buf);
770         }
771         freemsg(inm);
772 }
773
774 static void enc_process(MSFilter *f){
775         mblk_t *inm;
776         EncState *s=(EncState*)f->data;
777         if (s->av_context.codec==NULL) {
778                 ms_queue_flush(f->inputs[0]);
779                 return;
780         }
781         ms_filter_lock(f);
782         while((inm=ms_queue_get(f->inputs[0]))!=0){
783                 process_frame(f,inm);
784         }
785         ms_filter_unlock(f);
786 }
787
788
789 static int enc_get_br(MSFilter *f, void *arg){
790         EncState *s=(EncState*)f->data;
791         *(int*)arg=s->maxbr;
792         return 0;
793 }
794
795 static int enc_set_br(MSFilter *f, void *arg){
796         EncState *s=(EncState*)f->data;
797         bool_t snow=s->codec==CODEC_ID_SNOW;
798         s->maxbr=*(int*)arg;
799         if (s->maxbr>=1024000 && s->codec!=CODEC_ID_H263P){
800                 s->vsize.width = MS_VIDEO_SIZE_SVGA_W;
801                 s->vsize.height = MS_VIDEO_SIZE_SVGA_H;
802                 s->fps=17;
803         }else if (s->maxbr>=800000 && s->codec!=CODEC_ID_H263P){
804                 s->vsize.width = MS_VIDEO_SIZE_VGA_W;
805                 s->vsize.height = MS_VIDEO_SIZE_VGA_H;
806                 s->fps=17;
807         }else if (s->maxbr>=512000){
808                 s->vsize.width=MS_VIDEO_SIZE_CIF_W;
809                 s->vsize.height=MS_VIDEO_SIZE_CIF_H;
810                 s->fps=17;
811         }else if (s->maxbr>=256000){
812                 s->vsize.width=MS_VIDEO_SIZE_CIF_W;
813                 s->vsize.height=MS_VIDEO_SIZE_CIF_H;
814                 s->fps=10;
815                 s->qmin=3;
816         }else if (s->maxbr>=128000){
817                 s->vsize.width=MS_VIDEO_SIZE_QCIF_W;
818                 s->vsize.height=MS_VIDEO_SIZE_QCIF_H;
819                 s->fps=10;
820                 s->qmin=3;
821         }else if (s->maxbr>=64000){
822                 s->vsize.width=MS_VIDEO_SIZE_QCIF_W;
823                 s->vsize.height=MS_VIDEO_SIZE_QCIF_H;
824                 s->fps=snow ? 7 : 5;
825                 s->qmin=snow ? 4 : 5;
826         }else{
827                 s->vsize.width=MS_VIDEO_SIZE_QCIF_W;
828                 s->vsize.height=MS_VIDEO_SIZE_QCIF_H;
829                 s->fps=5;
830                 s->qmin=5;
831         }
832         if (s->av_context.codec!=NULL){
833                 /*apply new settings dynamically*/
834                 ms_filter_lock(f);
835                 enc_postprocess(f);
836                 enc_preprocess(f);
837                 ms_filter_unlock(f);
838         }
839         return 0;
840 }
841
842
843 static MSFilterMethod methods[]={
844         {       MS_FILTER_SET_FPS       ,       enc_set_fps     },
845         {       MS_FILTER_GET_FPS       ,       enc_get_fps     },
846         {       MS_FILTER_SET_VIDEO_SIZE ,      enc_set_vsize },
847         {       MS_FILTER_GET_VIDEO_SIZE ,      enc_get_vsize },
848         {       MS_FILTER_ADD_FMTP      ,       enc_add_fmtp },
849         {       MS_FILTER_SET_BITRATE   ,       enc_set_br      },
850         {       MS_FILTER_GET_BITRATE   ,       enc_get_br      },
851         {       MS_FILTER_SET_MTU       ,       enc_set_mtu     },
852         {       MS_FILTER_REQ_VFU       ,       enc_req_vfu     },
853         {       0                       ,       NULL    }
854 };
855
856 #ifdef _MSC_VER
857
858 MSFilterDesc ms_h263_enc_desc={
859         MS_H263_ENC_ID,
860         "MSH263Enc",
861         N_("A video H.263 encoder using ffmpeg library."),
862         MS_FILTER_ENCODER,
863         "H263-1998",
864         1, /*MS_YUV420P is assumed on this input */
865         1,
866         enc_h263_init,
867         enc_preprocess,
868         enc_process,
869         enc_postprocess,
870         enc_uninit,
871         methods
872 };
873
874 MSFilterDesc ms_h263_old_enc_desc={
875         MS_H263_OLD_ENC_ID,
876         "MSH263OldEnc",
877         N_("A video H.263 encoder using ffmpeg library. It is compliant with old RFC2190 spec."),
878         MS_FILTER_ENCODER,
879         "H263",
880         1, /*MS_YUV420P is assumed on this input */
881         1,
882         enc_h263_init,
883         enc_preprocess,
884         enc_process,
885         enc_postprocess,
886         enc_uninit,
887         methods
888 };
889
890 MSFilterDesc ms_mpeg4_enc_desc={
891         MS_MPEG4_ENC_ID,
892         "MSMpeg4Enc",
893         N_("A video MPEG4 encoder using ffmpeg library."),
894         MS_FILTER_ENCODER,
895         "MP4V-ES",
896         1, /*MS_YUV420P is assumed on this input */
897         1,
898         enc_mpeg4_init,
899         enc_preprocess,
900         enc_process,
901         enc_postprocess,
902         enc_uninit,
903         methods
904 };
905
906 MSFilterDesc ms_snow_enc_desc={
907         MS_SNOW_ENC_ID,
908         "MSSnowEnc",
909         N_("A video snow encoder using ffmpeg library."),
910         MS_FILTER_ENCODER,
911         "x-snow",
912         1, /*MS_YUV420P is assumed on this input */
913         1,
914         enc_snow_init,
915         enc_preprocess,
916         enc_process,
917         enc_postprocess,
918         enc_uninit,
919         methods
920 };
921
922 MSFilterDesc ms_mjpeg_enc_desc={
923         MS_JPEG_ENC_ID,
924         "MSJpegEnc",
925         N_("A RTP/MJPEG encoder using ffmpeg library."),
926         MS_FILTER_ENCODER,
927         "JPEG",
928         1, /*MS_YUV420P is assumed on this input */
929         1,
930         enc_mjpeg_init,
931         enc_preprocess,
932         enc_process,
933         enc_postprocess,
934         enc_uninit,
935         methods
936 };
937
938 #else
939
940 MSFilterDesc ms_h263_enc_desc={
941         .id=MS_H263_ENC_ID,
942         .name="MSH263Enc",
943         .text=N_("A video H.263 encoder using ffmpeg library."),
944         .category=MS_FILTER_ENCODER,
945         .enc_fmt="H263-1998",
946         .ninputs=1, /*MS_YUV420P is assumed on this input */
947         .noutputs=1,
948         .init=enc_h263_init,
949         .preprocess=enc_preprocess,
950         .process=enc_process,
951         .postprocess=enc_postprocess,
952         .uninit=enc_uninit,
953         .methods=methods
954 };
955
956 MSFilterDesc ms_h263_old_enc_desc={
957         .id=MS_H263_OLD_ENC_ID,
958         .name="MSH263Enc",
959         .text=N_("A video H.263 encoder using ffmpeg library, compliant with old RFC2190 spec."),
960         .category=MS_FILTER_ENCODER,
961         .enc_fmt="H263",
962         .ninputs=1, /*MS_YUV420P is assumed on this input */
963         .noutputs=1,
964         .init=enc_h263_init,
965         .preprocess=enc_preprocess,
966         .process=enc_process,
967         .postprocess=enc_postprocess,
968         .uninit=enc_uninit,
969         .methods=methods
970 };
971
972 MSFilterDesc ms_mpeg4_enc_desc={
973         .id=MS_MPEG4_ENC_ID,
974         .name="MSMpeg4Enc",
975         .text=N_("A video MPEG4 encoder using ffmpeg library."),
976         .category=MS_FILTER_ENCODER,
977         .enc_fmt="MP4V-ES",
978         .ninputs=1, /*MS_YUV420P is assumed on this input */
979         .noutputs=1,
980         .init=enc_mpeg4_init,
981         .preprocess=enc_preprocess,
982         .process=enc_process,
983         .postprocess=enc_postprocess,
984         .uninit=enc_uninit,
985         .methods=methods
986 };
987
988 MSFilterDesc ms_snow_enc_desc={
989         .id=MS_SNOW_ENC_ID,
990         .name="MSSnowEnc",
991         .text=N_("The snow codec is royalty-free and is open-source. \n"
992                 "It uses innovative techniques that makes it one of most promising video "
993                 "codec. It is implemented within the ffmpeg project.\n"
994                 "However it is under development, quite unstable and compatibility with other versions "
995                 "cannot be guaranteed."),
996         .category=MS_FILTER_ENCODER,
997         .enc_fmt="x-snow",
998         .ninputs=1, /*MS_YUV420P is assumed on this input */
999         .noutputs=1,
1000         .init=enc_snow_init,
1001         .preprocess=enc_preprocess,
1002         .process=enc_process,
1003         .postprocess=enc_postprocess,
1004         .uninit=enc_uninit,
1005         .methods=methods
1006 };
1007
1008 MSFilterDesc ms_mjpeg_enc_desc={
1009         .id=MS_JPEG_ENC_ID,
1010         .name="MSMJpegEnc",
1011         .text=N_("A MJPEG encoder using ffmpeg library."),
1012         .category=MS_FILTER_ENCODER,
1013         .enc_fmt="JPEG",
1014         .ninputs=1, /*MS_YUV420P is assumed on this input */
1015         .noutputs=1,
1016         .init=enc_mjpeg_init,
1017         .preprocess=enc_preprocess,
1018         .process=enc_process,
1019         .postprocess=enc_postprocess,
1020         .uninit=enc_uninit,
1021         .methods=methods
1022 };
1023
1024 #endif
1025
1026 void __register_ffmpeg_encoders_if_possible(void){
1027         ms_ffmpeg_check_init();
1028         if (avcodec_find_encoder(CODEC_ID_MPEG4))
1029                 ms_filter_register(&ms_mpeg4_enc_desc);
1030         if (avcodec_find_encoder(CODEC_ID_H263)){
1031                 ms_filter_register(&ms_h263_enc_desc);
1032                 ms_filter_register(&ms_h263_old_enc_desc);
1033         }
1034         if (avcodec_find_encoder(CODEC_ID_SNOW))
1035                 ms_filter_register(&ms_snow_enc_desc);
1036         if (avcodec_find_encoder(CODEC_ID_MJPEG))
1037         {
1038                 ms_filter_register(&ms_mjpeg_enc_desc);
1039         }
1040 }
1041