Split console_video.c so that video codecs and gui functions
[asterisk/asterisk.git] / channels / console_video.c
1 /*
2  * Experimental support for video sessions. We use SDL for rendering, ffmpeg
3  * as the codec library for encoding and decoding, and Video4Linux and X11
4  * to generate the local video stream.
5  *
6  * If one of these pieces is not available, either at compile time or at
7  * runtime, we do our best to run without it. Of course, no codec library
8  * means we can only deal with raw data, no SDL means we cannot do rendering,
9  * no V4L or X11 means we cannot generate data (but in principle we could
10  * stream from or record to a file).
11  *
12  * We need a recent (2007.07.12 or newer) version of ffmpeg to avoid warnings.
13  * Older versions might give 'deprecated' messages during compilation,
14  * thus not compiling in AST_DEVMODE, or don't have swscale, in which case
15  * you can try to compile #defining OLD_FFMPEG here.
16  *
17  * $Revision$
18  */
19
20 //#define DROP_PACKETS 5       /* if set, drop this % of video packets */
21 //#define OLD_FFMPEG    1       /* set for old ffmpeg with no swscale */
22
23 #include "asterisk.h"
24 #include <sys/ioctl.h>
25 #include <math.h>       /* sqrt */
26 #include "asterisk/cli.h"
27 #include "asterisk/file.h"
28 #include "asterisk/channel.h"
29
30 #include "console_video.h"
31
32 /*
33 The code is structured as follows.
34
35 When a new console channel is created, we call console_video_start()
36 to initialize SDL, the source, and the encoder/ decoder for the
37 formats in use (XXX the latter two should be done later, once the
38 codec negotiation is complete).  Also, a thread is created to handle
39 the video source and generate frames.
40
41 While communication is on, the local source is generated by the
42 video thread, which wakes up periodically, generates frames and
43 enqueues them in chan->readq.  Incoming rtp frames are passed to
44 console_write_video(), decoded and passed to SDL for display.
45
46 For as unfortunate and confusing as it can be, we need to deal with a
47 number of different video representations (size, codec/pixel format,
48 codec parameters), as follows:
49
50  loc_src        is the data coming from the camera/X11/etc.
51         The format is typically constrained by the video source.
52
53  enc_in         is the input required by the encoder.
54         Typically constrained in size by the encoder type.
55
56  enc_out        is the bitstream transmitted over RTP.
57         Typically negotiated while the call is established.
58
59  loc_dpy        is the format used to display the local video source.
60         Depending on user preferences this can have the same size as
61         loc_src_fmt, or enc_in_fmt, or thumbnail size (e.g. PiP output)
62
63  dec_in         is the incoming RTP bitstream. Negotiated
64         during call establishment, it is not necessarily the same as
65         enc_in_fmt
66
67  dec_out        the output of the decoder.
68         The format is whatever the other side sends, and the
69         buffer is allocated by avcodec_decode_... so we only
70         copy the data here.
71
72  rem_dpy        the format used to display the remote stream
73
74 We store the format info together with the buffer storing the data.
75 As a future optimization, a format/buffer may reference another one
76 if the formats are equivalent. This will save some unnecessary format
77 conversion.
78
79
80 In order to handle video you need to add to sip.conf (and presumably
81 iax.conf too) the following:
82
83         [general](+)
84                 videosupport=yes
85                 allow=h263      ; this or other video formats
86                 allow=h263p     ; this or other video formats
87
88  */
89
90 /*
91  * Codecs are absolutely necessary or we cannot do anything.
92  * In principle SDL is optional too (used for rendering only, but we
93  * could still source data withouth it), however at the moment it is required.
94  */
95 #if !defined(HAVE_VIDEO_CONSOLE) || !defined(HAVE_FFMPEG) || !defined(HAVE_SDL)
96 /* stubs if required pieces are missing */
97 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
98 {
99         return 0;       /* writing video not supported */
100 }
101
102 int console_video_cli(struct video_desc *env, const char *var, int fd)
103 {
104         return 1;       /* nothing matched */
105 }
106
107 int console_video_config(struct video_desc **penv, const char *var, const char *val)
108 {
109         return 1;       /* no configuration */
110 }
111
112 void console_video_start(struct video_desc *env, struct ast_channel *owner)
113 {
114         ast_log(LOG_NOTICE, "voice only, console video support not present\n");
115 }
116
117 void console_video_uninit(struct video_desc *env)
118 {
119 }
120
121 int console_video_formats = 0;
122
123 #else /* defined(HAVE_FFMPEG) && defined(HAVE_SDL) */
124
125 /*! The list of video formats we support. */
126 int console_video_formats = 
127         AST_FORMAT_H263_PLUS | AST_FORMAT_H263 |
128         AST_FORMAT_MP4_VIDEO | AST_FORMAT_H264 | AST_FORMAT_H261 ;
129
130 #ifdef HAVE_X11
131 #include <X11/Xlib.h>           /* this should be conditional */
132 #endif
133
134 #include <ffmpeg/avcodec.h>
135 #ifndef OLD_FFMPEG
136 #include <ffmpeg/swscale.h>     /* requires a recent ffmpeg */
137 #endif
138
139 #include <SDL/SDL.h>
140 #ifdef HAVE_SDL_IMAGE
141 #include <SDL/SDL_image.h>      /* for loading images */
142 #endif
143 #ifdef HAVE_SDL_TTF
144 #include <SDL/SDL_ttf.h>        /* render text on sdl surfaces */
145 #endif
146
147 /*
148  * In many places we use buffers to store the raw frames (but not only),
149  * so here is a structure to keep all the info. data = NULL means the
150  * structure is not initialized, so the other fields are invalid.
151  * size = 0 means the buffer is not malloc'ed so we don't have to free it.
152  */
153 struct fbuf_t {         /* frame buffers, dynamically allocated */
154         uint8_t *data;  /* memory, malloced if size > 0, just reference
155                          * otherwise */
156         int     size;   /* total size in bytes */
157         int     used;   /* space used so far */
158         int     ebit;   /* bits to ignore at the end */
159         int     x;      /* origin, if necessary */
160         int     y;
161         int     w;      /* size */ 
162         int     h;
163         int     pix_fmt;
164 };
165
166 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
167         struct fbuf_t *out, AVPicture *p_out);
168
169 struct video_codec_desc;        /* forward declaration */
170 /*
171  * Descriptor of the local source, made of the following pieces:
172  *  + configuration info (geometry, device name, fps...). These are read
173  *    from the config file and copied here before calling video_out_init();
174  *  + the frame buffer (buf) and source pixel format, allocated at init time;
175  *  + the encoding and RTP info, including timestamps to generate
176  *    frames at the correct rate;
177  *  + source-specific info, i.e. fd for /dev/video, dpy-image for x11, etc,
178  *    filled in by video_open
179  * NOTE: loc_src.data == NULL means the rest of the struct is invalid, and
180  *      the video source is not available.
181  */
182 struct video_out_desc {
183         /* video device support.
184          * videodevice and geometry are read from the config file.
185          * At the right time we try to open it and allocate a buffer.
186          * If we are successful, webcam_bufsize > 0 and we can read.
187          */
188         /* all the following is config file info copied from the parent */
189         char            videodevice[64];
190         int             fps;
191         int             bitrate;
192         int             qmin;
193
194         int sendvideo;
195
196         struct fbuf_t   loc_src;        /* local source buffer, allocated in video_open() */
197         struct fbuf_t   enc_in;         /* encoder input buffer, allocated in video_out_init() */
198         struct fbuf_t   enc_out;        /* encoder output buffer, allocated in video_out_init() */
199         struct fbuf_t   loc_dpy;        /* display source buffer, no buffer (managed by SDL in bmp[1]) */
200         struct fbuf_t   keypad_dpy;     /* keypad source buffer, XXX */
201
202         struct video_codec_desc *enc;   /* encoder */
203         void            *enc_ctx;       /* encoding context */
204         AVCodec         *codec;
205         AVFrame         *enc_in_frame;  /* enc_in mapped into avcodec format. */
206                                         /* The initial part of AVFrame is an AVPicture */
207         int             mtu;
208         struct timeval  last_frame;     /* when we read the last frame ? */
209
210         /* device specific info */
211         int             fd;             /* file descriptor, for webcam */
212 #ifdef HAVE_X11
213         Display         *dpy;                   /* x11 grabber info */
214         XImage          *image;
215         int             screen_width;   /* width of X screen */
216         int             screen_height;  /* height of X screen */
217 #endif
218 };
219
220 /*
221  * Descriptor for the incoming stream, with a buffer for the bitstream
222  * extracted by the RTP packets, RTP reassembly info, and a frame buffer
223  * for the decoded frame (buf).
224  * and store the result in a suitable frame buffer for later display.
225  * NOTE: dec_ctx == NULL means the rest is invalid (e.g. because no
226  *      codec, no memory, etc.) and we must drop all incoming frames.
227  *
228  * Incoming payload is stored in one of the dec_in[] buffers, which are
229  * emptied by the video thread. These buffers are organized in a circular
230  * queue, with dec_in_cur being the buffer in use by the incoming stream,
231  * and dec_in_dpy is the one being displayed. When the pointers need to
232  * be changed, we synchronize the access to them with dec_in_lock.
233  * When the list is full dec_in_cur = NULL (we cannot store new data),
234  * when the list is empty dec_in_dpy is NULL (we cannot display frames).
235  */
236 struct video_in_desc {
237         struct video_codec_desc *dec;   /* decoder */
238         AVCodecContext          *dec_ctx;       /* information about the codec in the stream */
239         AVCodec                 *codec;         /* reference to the codec */
240         AVFrame                 *d_frame;       /* place to store the decoded frame */
241         AVCodecParserContext    *parser;
242         uint16_t                next_seq;       /* must be 16 bit */
243         int                     discard;        /* flag for discard status */
244 #define N_DEC_IN        3       /* number of incoming buffers */
245         struct fbuf_t           *dec_in_cur;    /* buffer being filled in */
246         struct fbuf_t           *dec_in_dpy;    /* buffer to display */
247         ast_mutex_t             dec_in_lock;
248         struct fbuf_t dec_in[N_DEC_IN]; /* incoming bitstream, allocated/extended in fbuf_append() */
249         struct fbuf_t dec_out;  /* decoded frame, no buffer (data is in AVFrame) */
250         struct fbuf_t rem_dpy;  /* display remote image, no buffer (it is in win[WIN_REMOTE].bmp) */
251 };
252
253 /* our representation of a displayed window. SDL can only do one main
254  * window so we map everything within that one
255  */
256 enum { WIN_LOCAL, WIN_REMOTE, WIN_KEYPAD, WIN_MAX };
257
258 struct display_window   {
259         SDL_Overlay             *bmp;
260         SDL_Rect                rect;   /* loc. of images */
261 };
262
263 #define GUI_BUFFER_LEN 256                      /* buffer lenght used for input buffers */
264
265 enum kp_type { KP_NONE, KP_RECT, KP_CIRCLE };
266 struct keypad_entry {
267         int c;  /* corresponding character */
268         int x0, y0, x1, y1, h;  /* arguments */
269         enum kp_type type;
270 };
271
272 /*! \brief info related to the gui: button status, mouse coords, etc. */
273 struct gui_info {
274         char                    inbuf[GUI_BUFFER_LEN];  /* buffer for to-dial buffer */
275         int                     inbuf_pos;      /* next free position in inbuf */
276         char                    msgbuf[GUI_BUFFER_LEN]; /* buffer for text-message buffer */
277         int                     msgbuf_pos;     /* next free position in msgbuf */
278         int                     text_mode;      /* switch to-dial and text-message mode */
279         int                     drag_mode;      /* switch phone and drag-source mode */
280         int                     x_drag;         /* x coordinate where the drag starts */
281         int                     y_drag;         /* y coordinate where the drag starts */
282 #ifdef HAVE_SDL_TTF
283         TTF_Font                *font;          /* font to be used */ 
284 #endif
285         int                     outfd;          /* fd for output */
286         SDL_Surface             *keypad;        /* the pixmap for the keypad */
287         int kp_size, kp_used;
288         struct keypad_entry *kp;
289 };
290
291 /*
292  * The overall descriptor, with room for config info, video source and
293  * received data descriptors, SDL info, etc.
294  */
295 struct video_desc {
296         char                    codec_name[64]; /* the codec we use */
297
298         pthread_t               vthread;        /* video thread */
299         int                     shutdown;       /* set to shutdown vthread */
300         struct ast_channel      *owner;         /* owner channel */
301
302         struct video_in_desc    in;             /* remote video descriptor */
303         struct video_out_desc   out;            /* local video descriptor */
304
305         struct gui_info         gui;
306
307         /* support for display. */
308         int                     sdl_ok;
309         int                     gui_ok;
310         SDL_Surface             *screen;        /* the main window */
311         char                    keypad_file[256];       /* image for the keypad */
312         char                    keypad_font[256];       /* font for the keypad */
313
314         char                    sdl_videodriver[256];
315         struct display_window   win[WIN_MAX];
316 };
317
318 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
319
320 static void fbuf_free(struct fbuf_t *b)
321 {
322         struct fbuf_t x = *b;
323
324         if (b->data && b->size)
325                 ast_free(b->data);
326         bzero(b, sizeof(*b));
327         /* restore some fields */
328         b->w = x.w;
329         b->h = x.h;
330         b->pix_fmt = x.pix_fmt;
331 }
332
333 /*
334  * Append a chunk of data to a buffer taking care of bit alignment
335  * Return 0 on success, != 0 on failure
336  */
337 static int fbuf_append(struct fbuf_t *b, uint8_t *src, int len,
338         int sbit, int ebit)
339 {
340         /*
341          * Allocate buffer. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE,
342          * and also wants 0 as a buffer terminator to prevent trouble.
343          */
344         int need = len + FF_INPUT_BUFFER_PADDING_SIZE;
345         int i;
346         uint8_t *dst, mask;
347
348         if (b->data == NULL) {
349                 b->size = need;
350                 b->used = 0;
351                 b->ebit = 0;
352                 b->data = ast_calloc(1, b->size);
353         } else if (b->used + need > b->size) {
354                 b->size = b->used + need;
355                 b->data = ast_realloc(b->data, b->size);
356         }
357         if (b->data == NULL) {
358                 ast_log(LOG_WARNING, "alloc failure for %d, discard\n",
359                         b->size);
360                 return 1;
361         }
362         if (b->used == 0 && b->ebit != 0) {
363                 ast_log(LOG_WARNING, "ebit not reset at start\n");
364                 b->ebit = 0;
365         }
366         dst = b->data + b->used;
367         i = b->ebit + sbit;     /* bits to ignore around */
368         if (i == 0) {   /* easy case, just append */
369                 /* do everything in the common block */
370         } else if (i == 8) { /* easy too, just handle the overlap byte */
371                 mask = (1 << b->ebit) - 1;
372                 /* update the last byte in the buffer */
373                 dst[-1] &= ~mask;       /* clear bits to ignore */
374                 dst[-1] |= (*src & mask);       /* append new bits */
375                 src += 1;       /* skip and prepare for common block */
376                 len --;
377         } else {        /* must shift the new block, not done yet */
378                 ast_log(LOG_WARNING, "must handle shift %d %d at %d\n",
379                         b->ebit, sbit, b->used);
380                 return 1;
381         }
382         memcpy(dst, src, len);
383         b->used += len;
384         b->ebit = ebit;
385         b->data[b->used] = 0;   /* padding */
386         return 0;
387 }
388
389 /*!
390  * Build an ast_frame for a given chunk of data, and link it into
391  * the queue, with possibly 'head' bytes at the beginning to
392  * fill in some fields later.
393  */
394 static struct ast_frame *create_video_frame(uint8_t *start, uint8_t *end,
395                        int format, int head, struct ast_frame *prev)
396 {
397         int len = end-start;
398         uint8_t *data;
399         struct ast_frame *f;
400
401         data = ast_calloc(1, len+head);
402         f = ast_calloc(1, sizeof(*f));
403         if (f == NULL || data == NULL) {
404                 ast_log(LOG_WARNING, "--- frame error f %p data %p len %d format %d\n",
405                                 f, data, len, format);
406                 if (f)
407                         ast_free(f);
408                 if (data)
409                         ast_free(data);
410                 return NULL;
411         }
412         memcpy(data+head, start, len);
413         f->data = data;
414         f->mallocd = AST_MALLOCD_DATA | AST_MALLOCD_HDR;
415         //f->has_timing_info = 1;
416         //f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
417         f->datalen = len+head;
418         f->frametype = AST_FRAME_VIDEO;
419         f->subclass = format;
420         f->samples = 0;
421         f->offset = 0;
422         f->src = "Console";
423         f->delivery.tv_sec = 0;
424         f->delivery.tv_usec = 0;
425         f->seqno = 0;
426         AST_LIST_NEXT(f, frame_list) = NULL;
427
428         if (prev)
429                 AST_LIST_NEXT(prev, frame_list) = f;
430
431         return f;
432 }
433
434 #include "vcodecs.c"
435 #include "console_gui.c"
436
437 /*------ end codec specific code -----*/
438
439
440 /* Video4Linux stuff is only used in video_open() */
441 #ifdef HAVE_VIDEODEV_H
442 #include <linux/videodev.h>
443 #endif
444
445 /*!
446  * Open the local video source and allocate a buffer
447  * for storing the image. Return 0 on success, -1 on error
448  */
449 static int video_open(struct video_out_desc *v)
450 {
451         struct fbuf_t *b = &v->loc_src;
452         if (b->data)    /* buffer allocated means device already open */
453                 return v->fd;
454         v->fd = -1;
455         /*
456          * if the device is "X11", then open the x11 grabber
457          */
458     if (!strcasecmp(v->videodevice, "X11")) {
459         XImage *im;
460         int screen_num;
461
462         /* init the connection with the X server */
463         v->dpy = XOpenDisplay(NULL);
464         if (v->dpy == NULL) {
465                 ast_log(LOG_WARNING, "error opening display\n");
466                 goto error;
467         }
468
469         /* find width and height of the screen */
470         screen_num = DefaultScreen(v->dpy);
471         v->screen_width = DisplayWidth(v->dpy, screen_num);
472         v->screen_height = DisplayHeight(v->dpy, screen_num);
473
474         v->image = im = XGetImage(v->dpy,
475                 RootWindow(v->dpy, DefaultScreen(v->dpy)),
476                 b->x, b->y, b->w, b->h, AllPlanes, ZPixmap);
477         if (v->image == NULL) {
478                 ast_log(LOG_WARNING, "error creating Ximage\n");
479                 goto error;
480         }
481         switch (im->bits_per_pixel) {
482         case 32:
483                 b->pix_fmt = PIX_FMT_RGBA32;
484                 break;
485         case 16:
486                 b->pix_fmt = (im->green_mask == 0x7e0) ? PIX_FMT_RGB565 : PIX_FMT_RGB555;
487                 break;
488         }
489
490         ast_log(LOG_NOTICE, "image: data %p %d bpp fmt %d, mask 0x%lx 0x%lx 0x%lx\n",
491                 im->data,
492                 im->bits_per_pixel,
493                 b->pix_fmt,
494                 im->red_mask, im->green_mask, im->blue_mask);
495
496         /* set the pointer but not the size as this is not malloc'ed */
497         b->data = (uint8_t *)im->data;
498         v->fd = -2;
499     }
500 #ifdef HAVE_VIDEODEV_H
501     else {
502         /* V4L specific */
503         struct video_window vw = { 0 }; /* camera attributes */
504         struct video_picture vp;
505         int i;
506         const char *dev = v->videodevice;
507
508         v->fd = open(dev, O_RDONLY | O_NONBLOCK);
509         if (v->fd < 0) {
510                 ast_log(LOG_WARNING, "error opening camera %s\n", v->videodevice);
511                 return v->fd;
512         }
513
514         i = fcntl(v->fd, F_GETFL);
515         if (-1 == fcntl(v->fd, F_SETFL, i | O_NONBLOCK)) {
516                 /* non fatal, just emit a warning */
517                 ast_log(LOG_WARNING, "error F_SETFL for %s [%s]\n",
518                         dev, strerror(errno));
519         }
520         /* set format for the camera.
521          * In principle we could retry with a different format if the
522          * one we are asking for is not supported.
523          */
524         vw.width = v->loc_src.w;
525         vw.height = v->loc_src.h;
526         vw.flags = v->fps << 16;
527         if (ioctl(v->fd, VIDIOCSWIN, &vw) == -1) {
528                 ast_log(LOG_WARNING, "error setting format for %s [%s]\n",
529                         dev, strerror(errno));
530                 goto error;
531         }
532         if (ioctl(v->fd, VIDIOCGPICT, &vp) == -1) {
533                 ast_log(LOG_WARNING, "error reading picture info\n");
534                 goto error;
535         }
536         ast_log(LOG_WARNING,
537                 "contrast %d bright %d colour %d hue %d white %d palette %d\n",
538                 vp.contrast, vp.brightness,
539                 vp.colour, vp.hue,
540                 vp.whiteness, vp.palette);
541         /* set the video format. Here again, we don't necessary have to
542          * fail if the required format is not supported, but try to use
543          * what the camera gives us.
544          */
545         b->pix_fmt = vp.palette;
546         vp.palette = VIDEO_PALETTE_YUV420P;
547         if (ioctl(v->fd, VIDIOCSPICT, &vp) == -1) {
548                 ast_log(LOG_WARNING, "error setting palette, using %d\n",
549                         b->pix_fmt);
550         } else
551                 b->pix_fmt = vp.palette;
552         /* allocate the source buffer.
553          * XXX, the code here only handles yuv411, for other formats
554          * we need to look at pix_fmt and set size accordingly
555          */
556         b->size = (b->w * b->h * 3)/2;  /* yuv411 */
557         ast_log(LOG_WARNING, "videodev %s opened, size %dx%d %d\n",
558                 dev, b->w, b->h, b->size);
559         v->loc_src.data = ast_calloc(1, b->size);
560         if (!b->data) {
561                 ast_log(LOG_WARNING, "error allocating buffer %d bytes\n",
562                         b->size);
563                 goto error;
564         }
565         ast_log(LOG_WARNING, "success opening camera\n");
566     }
567 #endif /* HAVE_VIDEODEV_H */
568
569         if (v->image == NULL && v->fd < 0)
570                 goto error;
571         b->used = 0;
572         return 0;
573
574 error:
575         ast_log(LOG_WARNING, "fd %d dpy %p img %p data %p\n",
576                 v->fd, v->dpy, v->image, v->loc_src.data);
577         /* XXX maybe XDestroy (v->image) ? */
578         if (v->dpy)
579                 XCloseDisplay(v->dpy);
580         v->dpy = NULL;
581         if (v->fd >= 0)
582                 close(v->fd);
583         v->fd = -1;
584         fbuf_free(&v->loc_src);
585         return -1;
586 }
587
588 /*! \brief complete a buffer from the local video source.
589  * Called by get_video_frames(), in turn called by the video thread.
590  */
591 static int video_read(struct video_out_desc *v)
592 {
593         struct timeval now = ast_tvnow();
594         struct fbuf_t *b = &v->loc_src;
595
596         if (b->data == NULL)    /* not initialized */
597                 return 0;
598
599         /* check if it is time to read */
600         if (ast_tvzero(v->last_frame))
601                 v->last_frame = now;
602         if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
603                 return 0;       /* too early */
604         v->last_frame = now; /* XXX actually, should correct for drift */
605
606 #ifdef HAVE_X11
607         if (v->image) {
608                 /* read frame from X11 */
609                 AVPicture p;
610                 XGetSubImage(v->dpy,
611                     RootWindow(v->dpy, DefaultScreen(v->dpy)),
612                         b->x, b->y, b->w, b->h, AllPlanes, ZPixmap, v->image, 0, 0);
613
614                 b->data = (uint8_t *)v->image->data;
615                 fill_pict(b, &p);
616                 return p.linesize[0] * b->h;
617         }
618 #endif
619         if (v->fd < 0)                  /* no other source */
620                 return 0;
621         for (;;) {
622                 int r, l = v->loc_src.size - v->loc_src.used;
623                 r = read(v->fd, v->loc_src.data + v->loc_src.used, l);
624                 // ast_log(LOG_WARNING, "read %d of %d bytes from webcam\n", r, l);
625                 if (r < 0)      /* read error */
626                         return 0;
627                 if (r == 0)     /* no data */
628                         return 0;
629                 v->loc_src.used += r;
630                 if (r == l) {
631                         v->loc_src.used = 0; /* prepare for next frame */
632                         return v->loc_src.size;
633                 }
634         }
635 }
636
637 /* Helper function to process incoming video.
638  * For each incoming video call invoke ffmpeg_init() to intialize
639  * the decoding structure then incoming video frames are processed
640  * by write_video() which in turn calls pre_process_data(), to extract
641  * the bitstream; accumulates data into a buffer within video_desc. When
642  * a frame is complete (determined by the marker bit in the RTP header)
643  * call decode_video() to decoding and if it successful call show_frame()
644  * to display the frame.
645  */
646
647 /*
648  * Map the codec name to the library. If not recognised, use a default.
649  * This is useful in the output path where we decide by name, presumably.
650  */
651 static struct video_codec_desc *map_config_video_format(char *name)
652 {
653         int i;
654
655         for (i = 0; supported_codecs[i]; i++)
656                 if (!strcasecmp(name, supported_codecs[i]->name))
657                         break;
658         if (supported_codecs[i] == NULL) {
659                 ast_log(LOG_WARNING, "Cannot find codec for '%s'\n", name);
660                 i = 0;
661                 strcpy(name, supported_codecs[i]->name);
662         }
663         ast_log(LOG_WARNING, "Using codec '%s'\n", name);
664         return supported_codecs[i];
665 }
666
667 /*! \brief uninitialize the descriptor for remote video stream */
668 static int video_in_uninit(struct video_in_desc *v)
669 {
670         int i;
671
672         if (v->parser) {
673                 av_parser_close(v->parser);
674                 v->parser = NULL;
675         }
676         if (v->dec_ctx) {
677                 avcodec_close(v->dec_ctx);
678                 av_free(v->dec_ctx);
679                 v->dec_ctx = NULL;
680         }
681         if (v->d_frame) {
682                 av_free(v->d_frame);
683                 v->d_frame = NULL;
684         }
685         v->codec = NULL;        /* only a reference */
686         v->dec = NULL;          /* forget the decoder */
687         v->discard = 1;         /* start in discard mode */
688         for (i = 0; i < N_DEC_IN; i++)
689                 fbuf_free(&v->dec_in[i]);
690         fbuf_free(&v->dec_out);
691         fbuf_free(&v->rem_dpy);
692         return -1;      /* error, in case someone cares */
693 }
694
695 /*
696  * initialize ffmpeg resources used for decoding frames from the network.
697  */
698 static int video_in_init(struct video_in_desc *v, uint32_t format)
699 {
700         enum CodecID codec;
701
702         /* XXX should check that these are already set */
703         v->codec = NULL;
704         v->dec_ctx = NULL;
705         v->d_frame = NULL;
706         v->parser = NULL;
707         v->discard = 1;
708
709         codec = map_video_format(format, CM_RD);
710
711         v->codec = avcodec_find_decoder(codec);
712         if (!v->codec) {
713                 ast_log(LOG_WARNING, "Unable to find the decoder for format %d\n", codec);
714                 return video_in_uninit(v);
715         }
716         /*
717         * Initialize the codec context.
718         */
719         v->dec_ctx = avcodec_alloc_context();
720         /* XXX call dec_init() ? */
721         if (avcodec_open(v->dec_ctx, v->codec) < 0) {
722                 ast_log(LOG_WARNING, "Cannot open the codec context\n");
723                 av_free(v->dec_ctx);
724                 v->dec_ctx = NULL;
725                 return video_in_uninit(v);
726         }
727
728         v->parser = av_parser_init(codec);
729         if (!v->parser) {
730                 ast_log(LOG_WARNING, "Cannot initialize the decoder parser\n");
731                 return video_in_uninit(v);
732         }
733
734         v->d_frame = avcodec_alloc_frame();
735         if (!v->d_frame) {
736                 ast_log(LOG_WARNING, "Cannot allocate decoding video frame\n");
737                 return video_in_uninit(v);
738         }
739         return 0;       /* ok */
740 }
741
742 /*! \brief uninitialize the descriptor for local video stream */
743 static int video_out_uninit(struct video_out_desc *v)
744 {
745         /* XXX this should be a codec callback */
746         if (v->enc_ctx) {
747                 AVCodecContext *enc_ctx = (AVCodecContext *)v->enc_ctx;
748                 avcodec_close(enc_ctx);
749                 av_free(enc_ctx);
750                 v->enc_ctx = NULL;
751         }
752         if (v->enc_in_frame) {
753                 av_free(v->enc_in_frame);
754                 v->enc_in_frame = NULL;
755         }
756         v->codec = NULL;        /* only a reference */
757         
758         fbuf_free(&v->loc_src);
759         fbuf_free(&v->enc_in);
760         fbuf_free(&v->enc_out);
761         fbuf_free(&v->loc_dpy);
762         if (v->image) { /* X11 grabber */
763                 XCloseDisplay(v->dpy);
764                 v->dpy = NULL;
765                 v->image = NULL;
766         }
767         if (v->fd >= 0) {
768                 close(v->fd);
769                 v->fd = -1;
770         }
771         return -1;
772 }
773
774 /*
775  * Initialize the encoder for the local source:
776  * - AVCodecContext, AVCodec, AVFrame are used by ffmpeg for encoding;
777  * - encbuf is used to store the encoded frame (to be sent)
778  * - mtu is used to determine the max size of video fragment
779  * NOTE: we enter here with the video source already open.
780  */
781 static int video_out_init(struct video_desc *env)
782 {
783         int codec;
784         int size;
785         struct fbuf_t *enc_in;
786         struct video_out_desc *v = &env->out;
787
788         v->enc_ctx              = NULL;
789         v->codec                = NULL;
790         v->enc_in_frame         = NULL;
791         v->enc_out.data         = NULL;
792
793         if (v->loc_src.data == NULL) {
794                 ast_log(LOG_WARNING, "No local source active\n");
795                 return video_out_uninit(v);
796         }
797         codec = map_video_format(v->enc->format, CM_WR);
798         v->codec = avcodec_find_encoder(codec);
799         if (!v->codec) {
800                 ast_log(LOG_WARNING, "Cannot find the encoder for format %d\n",
801                         codec);
802                 return video_out_uninit(v);
803         }
804
805         v->mtu = 1400;  /* set it early so the encoder can use it */
806
807         /* allocate the input buffer for encoding.
808          * ffmpeg only supports PIX_FMT_YUV420P for the encoding.
809          */
810         enc_in = &v->enc_in;
811         enc_in->pix_fmt = PIX_FMT_YUV420P;
812         enc_in->size = (enc_in->w * enc_in->h * 3)/2;
813         enc_in->data = ast_calloc(1, enc_in->size);
814         if (!enc_in->data) {
815                 ast_log(LOG_WARNING, "Cannot allocate encoder input buffer\n");
816                 return video_out_uninit(v);
817         }
818         /* construct an AVFrame that points into buf_in */
819         v->enc_in_frame = avcodec_alloc_frame();
820         if (!v->enc_in_frame) {
821                 ast_log(LOG_WARNING, "Unable to allocate the encoding video frame\n");
822                 return video_out_uninit(v);
823         }
824
825         /* parameters for PIX_FMT_YUV420P */
826         size = enc_in->w * enc_in->h;
827         v->enc_in_frame->data[0] = enc_in->data;
828         v->enc_in_frame->data[1] = v->enc_in_frame->data[0] + size;
829         v->enc_in_frame->data[2] = v->enc_in_frame->data[1] + size/4;
830         v->enc_in_frame->linesize[0] = enc_in->w;
831         v->enc_in_frame->linesize[1] = enc_in->w/2;
832         v->enc_in_frame->linesize[2] = enc_in->w/2;
833
834         /* now setup the parameters for the encoder.
835          * XXX should be codec-specific
836          */
837     {
838         AVCodecContext *enc_ctx = avcodec_alloc_context();
839         v->enc_ctx = enc_ctx;
840         enc_ctx->pix_fmt = enc_in->pix_fmt;
841         enc_ctx->width = enc_in->w;
842         enc_ctx->height = enc_in->h;
843         /* XXX rtp_callback ?
844          * rtp_mode so ffmpeg inserts as many start codes as possible.
845          */
846         enc_ctx->rtp_mode = 1;
847         enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2
848         enc_ctx->bit_rate = v->bitrate;
849         enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
850         enc_ctx->qmin = v->qmin;        /* should be configured */
851         enc_ctx->time_base = (AVRational){1, v->fps};
852         enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
853
854         v->enc->enc_init(v->enc_ctx);
855  
856         if (avcodec_open(enc_ctx, v->codec) < 0) {
857                 ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n",
858                         codec);
859                 av_free(enc_ctx);
860                 v->enc_ctx = NULL;
861                 return video_out_uninit(v);
862         }
863     }
864         /*
865          * Allocate enough for the encoded bitstream. As we are compressing,
866          * we hope that the output is never larger than the input size.
867          */
868         v->enc_out.data = ast_calloc(1, enc_in->size);
869         v->enc_out.size = enc_in->size;
870         v->enc_out.used = 0;
871
872         return 0;
873 }
874
875 /*! \brief uninitialize the entire environment.
876  * In practice, signal the thread and give it a bit of time to
877  * complete, giving up if it gets stuck. Because uninit
878  * is called from hangup with the channel locked, and the thread
879  * uses the chan lock, we need to unlock here. This is unsafe,
880  * and we should really use refcounts for the channels.
881  */
882 void console_video_uninit(struct video_desc *env)
883 {
884         int i, t = 100; /* initial wait is shorter, than make it longer */
885         env->shutdown = 1;
886         for (i=0; env->shutdown && i < 10; i++) {
887                 ast_channel_unlock(env->owner);
888                 usleep(t);
889                 t = 1000000;
890                 ast_channel_lock(env->owner);
891         }
892         env->owner = NULL;
893 }
894
895 /*! fill an AVPicture from our fbuf info, as it is required by
896  * the image conversion routines in ffmpeg.
897  * XXX This depends on the format.
898  */
899 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p)
900 {
901         /* provide defaults for commonly used formats */
902         int l4 = b->w * b->h/4; /* size of U or V frame */
903         int len = b->w;         /* Y linesize, bytes */
904         int luv = b->w/2;       /* U/V linesize, bytes */
905
906         bzero(p, sizeof(*p));
907         switch (b->pix_fmt) {
908         case PIX_FMT_RGB555:
909         case PIX_FMT_RGB565:
910                 len *= 2;
911                 luv = 0;
912                 break;
913         case PIX_FMT_RGBA32:
914                 len *= 4;
915                 luv = 0;
916                 break;
917         case PIX_FMT_YUYV422:   /* Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr */
918                 len *= 2;       /* all data in first plane, probably */
919                 luv = 0;
920                 break;
921         }
922         p->data[0] = b->data;
923         p->linesize[0] = len;
924         /* these are only valid for component images */
925         p->data[1] = luv ? b->data + 4*l4 : b->data+len;
926         p->data[2] = luv ? b->data + 5*l4 : b->data+len;
927         p->linesize[1] = luv;
928         p->linesize[2] = luv;
929         return p;
930 }
931
932 /*! convert/scale between an input and an output format.
933  * Old version of ffmpeg only have img_convert, which does not rescale.
934  * New versions use sws_scale which does both.
935  */
936 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
937         struct fbuf_t *out, AVPicture *p_out)
938 {
939         AVPicture my_p_in, my_p_out;
940
941         if (p_in == NULL)
942                 p_in = fill_pict(in, &my_p_in);
943         if (p_out == NULL)
944                 p_out = fill_pict(out, &my_p_out);
945
946 #ifdef OLD_FFMPEG
947         /* XXX img_convert is deprecated, and does not do rescaling */
948         img_convert(p_out, out->pix_fmt,
949                 p_in, in->pix_fmt, in->w, in->h);
950 #else /* XXX replacement */
951     {
952         struct SwsContext *convert_ctx;
953
954         convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
955                 out->w, out->h, out->pix_fmt,
956                 SWS_BICUBIC, NULL, NULL, NULL);
957         if (convert_ctx == NULL) {
958                 ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
959                 return;
960         }
961         if (0)
962                 ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
963                         in->pix_fmt, in->w, in->h, out->pix_fmt, out->w, out->h);
964         sws_scale(convert_ctx,
965                 p_in->data, p_in->linesize,
966                 in->w, in->h, /* src slice */
967                 p_out->data, p_out->linesize);
968
969         sws_freeContext(convert_ctx);
970     }
971 #endif /* XXX replacement */
972 }
973
974 struct video_desc *get_video_desc(struct ast_channel *c);
975
976 /*
977  * This function is called (by asterisk) for each video packet
978  * coming from the network (the 'in' path) that needs to be processed.
979  * We need to reconstruct the entire video frame before we can decode it.
980  * After a video packet is received we have to:
981  * - extract the bitstream with pre_process_data()
982  * - append the bitstream to a buffer
983  * - if the fragment is the last (RTP Marker) we decode it with decode_video()
984  * - after the decoding is completed we display the decoded frame with show_frame()
985  */
986 int console_write_video(struct ast_channel *chan, struct ast_frame *f);
987 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
988 {
989         struct video_desc *env = get_video_desc(chan);
990         struct video_in_desc *v = &env->in;
991
992         if (v->dec == NULL) {   /* try to get the codec */
993                 v->dec = map_video_codec(f->subclass & ~1);
994                 if (v->dec == NULL) {
995                         ast_log(LOG_WARNING, "cannot find video codec, drop input 0x%x\n", f->subclass);
996                         return 0;
997                 }
998                 if (video_in_init(v, v->dec->format)) {
999                         /* This is not fatal, but we won't have incoming video */
1000                         ast_log(LOG_WARNING, "Cannot initialize input decoder\n");
1001                         v->dec = NULL;
1002                         return 0;
1003                 }
1004         }
1005         if (v->dec_ctx == NULL) {
1006                 ast_log(LOG_WARNING, "cannot decode, dropping frame\n");
1007                 return 0;       /* error */
1008         }
1009
1010         if (v->dec_in_cur == NULL)      /* no buffer for incoming frames, drop */
1011                 return 0;
1012 #if defined(DROP_PACKETS) && DROP_PACKETS > 0
1013         /* Simulate lost packets */
1014         if ((random() % 10000) <= 100*DROP_PACKETS) {
1015                 ast_log(LOG_NOTICE, "Packet lost [%d]\n", f->seqno);
1016                 return 0;
1017         }
1018 #endif
1019         if (v->discard) {
1020                 /*
1021                  * In discard mode, drop packets until we find one with
1022                  * the RTP marker set (which is the end of frame).
1023                  * Note that the RTP marker flag is sent as the LSB of the
1024                  * subclass, which is a  bitmask of formats. The low bit is
1025                  * normally used for audio so there is no interference.
1026                  */
1027                 if (f->subclass & 0x01) {
1028                         v->dec_in_cur->used = 0;
1029                         v->dec_in_cur->ebit = 0;
1030                         v->next_seq = f->seqno + 1;     /* wrap at 16 bit */
1031                         v->discard = 0;
1032                         ast_log(LOG_WARNING, "out of discard mode, frame %d\n", f->seqno);
1033                 }
1034                 return 0;
1035         }
1036
1037         /*
1038          * Only in-order fragments will be accepted. Remember seqno
1039          * has 16 bit so there is wraparound. Also, ideally we could
1040          * accept a bit of reordering, but at the moment we don't.
1041          */
1042         if (v->next_seq != f->seqno) {
1043                 ast_log(LOG_WARNING, "discarding frame out of order, %d %d\n",
1044                         v->next_seq, f->seqno);
1045                 v->discard = 1;
1046                 return 0;
1047         }
1048         v->next_seq++;
1049
1050         if (f->data == NULL || f->datalen < 2) {
1051                 ast_log(LOG_WARNING, "empty video frame, discard\n");
1052                 return 0;
1053         }
1054         if (v->dec->dec_decap(v->dec_in_cur, f->data, f->datalen)) {
1055                 ast_log(LOG_WARNING, "error in dec_decap, enter discard\n");
1056                 v->discard = 1;
1057         }
1058         if (f->subclass & 0x01) {       // RTP Marker
1059                 /* prepare to decode: advance the buffer so the video thread knows. */
1060                 struct fbuf_t *tmp = v->dec_in_cur;     /* store current pointer */
1061                 ast_mutex_lock(&v->dec_in_lock);
1062                 if (++v->dec_in_cur == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
1063                         v->dec_in_cur = &v->dec_in[0];
1064                 if (v->dec_in_dpy == NULL) {    /* were not displaying anything, so set it */
1065                         v->dec_in_dpy = tmp;
1066                 } else if (v->dec_in_dpy == v->dec_in_cur) { /* current slot is busy */
1067                         v->dec_in_cur = NULL;
1068                 }
1069                 ast_mutex_unlock(&v->dec_in_lock);
1070         }
1071         return 0;
1072 }
1073
1074
1075 /*! \brief read a frame from webcam or X11 through video_read(),
1076  * display it,  then encode and split it.
1077  * Return a list of ast_frame representing the video fragments.
1078  * The head pointer is returned by the function, the tail pointer
1079  * is returned as an argument.
1080  */
1081 static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_frame **tail)
1082 {
1083         struct video_out_desc *v = &env->out;
1084         struct ast_frame *dummy;
1085
1086         if (!v->loc_src.data) {
1087                 static volatile int a = 0;
1088                 if (a++ < 2)
1089                         ast_log(LOG_WARNING, "fail, no loc_src buffer\n");
1090                 return NULL;
1091         }
1092         if (!video_read(v))
1093                 return NULL;    /* can happen, e.g. we are reading too early */
1094
1095         if (tail == NULL)
1096                 tail = &dummy;
1097         *tail = NULL;
1098         /* Scale the video for the encoder, then use it for local rendering
1099          * so we will see the same as the remote party.
1100          */
1101         my_scale(&v->loc_src, NULL, &v->enc_in, NULL);
1102         show_frame(env, WIN_LOCAL);
1103         if (!v->sendvideo)
1104                 return NULL;
1105         if (v->enc_out.data == NULL) {
1106                 static volatile int a = 0;
1107                 if (a++ < 2)
1108                         ast_log(LOG_WARNING, "fail, no encbuf\n");
1109                 return NULL;
1110         }
1111         v->enc->enc_run(v);
1112         return v->enc->enc_encap(v, tail);
1113 }
1114
1115 /*
1116  * Helper thread to periodically poll the video source and enqueue the
1117  * generated frames to the channel's queue.
1118  * Using a separate thread also helps because the encoding can be
1119  * computationally expensive so we don't want to starve the main thread.
1120  */
1121 static void *video_thread(void *arg)
1122 {
1123         struct video_desc *env = arg;
1124         int count = 0;
1125         char save_display[128] = "";
1126
1127         env->screen = NULL;
1128         bzero(env->win, sizeof(env->win));
1129
1130         /* if sdl_videodriver is set, override the environment. Also,
1131          * if it contains 'console' override DISPLAY around the call to SDL_Init
1132          * so we use the console as opposed to the x11 version of aalib
1133          */
1134         if (!ast_strlen_zero(env->sdl_videodriver)) { /* override */
1135                 const char *s = getenv("DISPLAY");
1136                 setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1);
1137                 if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) {
1138                         ast_copy_string(save_display, s, sizeof(save_display));
1139                         unsetenv("DISPLAY");
1140                 }
1141         }
1142         if (SDL_Init(SDL_INIT_VIDEO)) {
1143                 ast_log(LOG_WARNING, "Could not initialize SDL - %s\n",
1144                         SDL_GetError());
1145                 /* again not fatal, just we won't display anything */
1146         } else {
1147                 sdl_setup(env);
1148                 if (env->sdl_ok)
1149                         ast_mutex_init(&env->in.dec_in_lock);
1150                 /* TODO, segfault if not X display present */
1151                 env->gui_ok = !gui_init(env);
1152                 if (!env->gui_ok)
1153                         ast_log(LOG_WARNING, "cannot init console gui\n");
1154         }
1155         if (!ast_strlen_zero(save_display))
1156                 setenv("DISPLAY", save_display, 1);
1157
1158         if (video_open(&env->out)) {
1159                 ast_log(LOG_WARNING, "cannot open local video source\n");
1160         } else {
1161                 /* try to register the fd. Unfortunately, if the webcam
1162                  * driver does not support select/poll we are out of luck.
1163                  */
1164                 if (env->out.fd >= 0)
1165                         ast_channel_set_fd(env->owner, 1, env->out.fd);
1166                 video_out_init(env);
1167         }
1168
1169         for (;;) {
1170                 /* XXX 20 times/sec */
1171                 struct timeval t = { 0, 50000 };
1172                 struct ast_frame *p, *f;
1173                 struct video_in_desc *v = &env->in;
1174                 struct ast_channel *chan = env->owner;
1175                 int fd = chan->alertpipe[1];
1176
1177                 /* determine if video format changed */
1178                 if (count++ % 10 == 0) {
1179                         char buf[160];
1180                         if (env->out.sendvideo)
1181                             sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
1182                                 env->out.videodevice, env->codec_name,
1183                                 env->out.enc_in.w, env->out.enc_in.h,
1184                                 env->out.fps, env->out.bitrate/1000);
1185                         else
1186                             sprintf(buf, "hold");
1187                         SDL_WM_SetCaption(buf, NULL);
1188                 }
1189
1190                 /* manage keypad events */
1191                 /* XXX here we should always check for events,
1192                 * otherwise the drag will not work */ 
1193                 if (env->gui_ok)
1194                         eventhandler(env);
1195  
1196                 /* sleep for a while */
1197                 ast_select(0, NULL, NULL, NULL, &t);
1198
1199                 SDL_UpdateRects(env->screen, 1, &env->win[WIN_KEYPAD].rect);// XXX inefficient
1200                 /*
1201                  * While there is something to display, call the decoder and free
1202                  * the buffer, possibly enabling the receiver to store new data.
1203                  */
1204                 while (v->dec_in_dpy) {
1205                         struct fbuf_t *tmp = v->dec_in_dpy;     /* store current pointer */
1206
1207                         if (v->dec->dec_run(v, tmp))
1208                                 show_frame(env, WIN_REMOTE);
1209                         tmp->used = 0;  /* mark buffer as free */
1210                         tmp->ebit = 0;
1211                         ast_mutex_lock(&v->dec_in_lock);
1212                         if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
1213                                 v->dec_in_dpy = &v->dec_in[0];
1214
1215                         if (v->dec_in_cur == NULL)      /* receiver was idle, enable it... */
1216                                 v->dec_in_cur = tmp;    /* using the slot just freed */
1217                         else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
1218                                 v->dec_in_dpy = NULL;   /* nothing more to display */
1219                         ast_mutex_unlock(&v->dec_in_lock);
1220                 }
1221
1222
1223                 f = get_video_frames(env, &p);  /* read and display */
1224                 if (!f)
1225                         continue;
1226                 if (env->shutdown)
1227                         break;
1228                 chan = env->owner;
1229                 ast_channel_lock(chan);
1230
1231                 /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */
1232                 if (chan->readq.first == NULL) {
1233                         chan->readq.first = f;
1234                 } else {
1235                         chan->readq.last->frame_list.next = f;
1236                 }
1237                 chan->readq.last = p;
1238                 /*
1239                  * more or less same as ast_queue_frame, but extra
1240                  * write on the alertpipe to signal frames.
1241                  */
1242                 if (fd > -1) {
1243                         int blah = 1, l = sizeof(blah);
1244                         for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
1245                                 if (write(fd, &blah, l) != l)
1246                                         ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
1247                                             chan->name, f->frametype, f->subclass, strerror(errno));
1248                         }
1249                 }
1250                 ast_channel_unlock(chan);
1251         }
1252         /* thread terminating, here could call the uninit */
1253         /* uninitialize the local and remote video environments */
1254         video_in_uninit(&env->in);
1255         video_out_uninit(&env->out);
1256
1257         if (env->sdl_ok)
1258                 cleanup_sdl(env);
1259
1260         env->shutdown = 0;
1261         return NULL;
1262 }
1263
1264 static void copy_geometry(struct fbuf_t *src, struct fbuf_t *dst)
1265 {
1266         if (dst->w == 0)
1267                 dst->w = src->w;
1268         if (dst->h == 0)
1269                 dst->h = src->h;
1270 }
1271
1272 /*! initialize the video environment.
1273  * Apart from the formats (constant) used by sdl and the codec,
1274  * we use enc_in as the basic geometry.
1275  */
1276 static void init_env(struct video_desc *env)
1277 {
1278         struct fbuf_t *c = &(env->out.loc_src);         /* local source */
1279         struct fbuf_t *ei = &(env->out.enc_in);         /* encoder input */
1280         struct fbuf_t *ld = &(env->out.loc_dpy);        /* local display */
1281         struct fbuf_t *rd = &(env->in.rem_dpy);         /* remote display */
1282
1283         c->pix_fmt = PIX_FMT_YUV420P;   /* default - camera format */
1284         ei->pix_fmt = PIX_FMT_YUV420P;  /* encoder input */
1285         if (ei->w == 0 || ei->h == 0) {
1286                 ei->w = 352;
1287                 ei->h = 288;
1288         }
1289         ld->pix_fmt = rd->pix_fmt = PIX_FMT_YUV420P; /* sdl format */
1290         /* inherit defaults */
1291         copy_geometry(ei, c);   /* camera inherits from encoder input */
1292         copy_geometry(ei, rd);  /* remote display inherits from encoder input */
1293         copy_geometry(rd, ld);  /* local display inherits from remote display */
1294 }
1295
1296 /*!
1297  * The first call to the video code, called by oss_new() or similar.
1298  * Here we initialize the various components we use, namely SDL for display,
1299  * ffmpeg for encoding/decoding, and a local video source.
1300  * We do our best to progress even if some of the components are not
1301  * available.
1302  */
1303 void console_video_start(struct video_desc *env, struct ast_channel *owner)
1304 {
1305         if (env == NULL)        /* video not initialized */
1306                 return;
1307         if (owner == NULL)      /* nothing to do if we don't have a channel */
1308                 return;
1309         env->owner = owner;
1310         init_env(env);
1311         env->out.enc = map_config_video_format(env->codec_name);
1312
1313         ast_log(LOG_WARNING, "start video out %s %dx%d\n",
1314                 env->codec_name, env->out.enc_in.w,  env->out.enc_in.h);
1315         /*
1316          * Register all codecs supported by the ffmpeg library.
1317          * We only need to do it once, but probably doesn't
1318          * harm to do it multiple times.
1319          */
1320         avcodec_init();
1321         avcodec_register_all();
1322         av_log_set_level(AV_LOG_ERROR); /* only report errors */
1323
1324         if (env->out.fps == 0) {
1325                 env->out.fps = 15;
1326                 ast_log(LOG_WARNING, "fps unset, forcing to %d\n", env->out.fps);
1327         }
1328         if (env->out.bitrate == 0) {
1329                 env->out.bitrate = 65000;
1330                 ast_log(LOG_WARNING, "bitrate unset, forcing to %d\n", env->out.bitrate);
1331         }
1332
1333         ast_pthread_create_background(&env->vthread, NULL, video_thread, env);
1334 }
1335
1336 /*
1337  * Parse a geometry string, accepting also common names for the formats.
1338  * Trick: if we have a leading > or < and a numeric geometry,
1339  * return the larger or smaller one.
1340  * E.g. <352x288 gives the smaller one, 320x240
1341  */
1342 static int video_geom(struct fbuf_t *b, const char *s)
1343 {
1344         int w = 0, h = 0;
1345
1346         static struct {
1347                 const char *s; int w; int h;
1348         } *fp, formats[] = {
1349                 {"vga",         640, 480 },
1350                 {"cif",         352, 288 },
1351                 {"qvga",        320, 240 },
1352                 {"qcif",        176, 144 },
1353                 {"sqcif",       128, 96 },
1354                 {NULL,          0, 0 },
1355         };
1356         if (*s == '<' || *s == '>')
1357                 sscanf(s+1,"%dx%d", &w, &h);
1358         for (fp = formats; fp->s; fp++) {
1359                 if (*s == '>') {        /* look for a larger one */
1360                         if (fp->w <= w) {
1361                                 if (fp > formats)
1362                                         fp--; /* back one step if possible */
1363                                 break;
1364                         }
1365                 } else if (*s == '<') { /* look for a smaller one */
1366                         if (fp->w < w)
1367                                 break;
1368                 } else if (!strcasecmp(s, fp->s)) { /* look for a string */
1369                         break;
1370                 }
1371         }
1372         if (*s == '<' && fp->s == NULL) /* smallest */
1373                 fp--;
1374         if (fp->s) {
1375                 b->w = fp->w;
1376                 b->h = fp->h;
1377         } else if (sscanf(s, "%dx%d", &b->w, &b->h) != 2) {
1378                 ast_log(LOG_WARNING, "Invalid video_size %s, using 352x288\n", s);
1379                 b->w = 352;
1380                 b->h = 288;
1381         }
1382         return 0;
1383 }
1384
1385 /* extend ast_cli with video commands. Called by console_video_config */
1386 int console_video_cli(struct video_desc *env, const char *var, int fd)
1387 {
1388         if (env == NULL)
1389                 return 1;       /* unrecognised */
1390
1391         if (!strcasecmp(var, "videodevice")) {
1392                 ast_cli(fd, "videodevice is [%s]\n", env->out.videodevice);
1393         } else if (!strcasecmp(var, "videocodec")) {
1394                 ast_cli(fd, "videocodec is [%s]\n", env->codec_name);
1395         } else if (!strcasecmp(var, "sendvideo")) {
1396                 ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
1397         } else if (!strcasecmp(var, "video_size")) {
1398                 ast_cli(fd, "sizes: video %dx%d camera %dx%d local %dx%d remote %dx%d in %dx%d\n",
1399                         env->out.enc_in.w, env->out.enc_in.h,
1400                         env->out.loc_src.w, env->out.loc_src.h,
1401                         env->out.loc_dpy.w, env->out.loc_src.h,
1402                         env->in.rem_dpy.w, env->in.rem_dpy.h,
1403                         env->in.dec_out.w, env->in.dec_out.h);
1404         } else if (!strcasecmp(var, "bitrate")) {
1405                 ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
1406         } else if (!strcasecmp(var, "qmin")) {
1407                 ast_cli(fd, "qmin is [%d]\n", env->out.qmin);
1408         } else if (!strcasecmp(var, "fps")) {
1409                 ast_cli(fd, "fps is [%d]\n", env->out.fps);
1410         } else {
1411                 return 1;       /* unrecognised */
1412         }
1413         return 0;       /* recognised */
1414 }
1415
1416 /*! parse config command for video support. */
1417 int console_video_config(struct video_desc **penv,
1418         const char *var, const char *val)
1419 {
1420         struct video_desc *env;
1421
1422         if (penv == NULL) {
1423                 ast_log(LOG_WARNING, "bad argument penv=NULL\n");
1424                 return 1;       /* error */
1425         }
1426         /* allocate the video descriptor first time we get here */
1427         env = *penv;
1428         if (env == NULL) {
1429                 env = *penv = ast_calloc(1, sizeof(struct video_desc));
1430                 if (env == NULL) {
1431                         ast_log(LOG_WARNING, "fail to allocate video_desc\n");
1432                         return 1;       /* error */
1433                 
1434                 }
1435                 /* set default values */
1436                 ast_copy_string(env->out.videodevice, "X11", sizeof(env->out.videodevice));
1437                 env->out.fps = 5;
1438                 env->out.bitrate = 65000;
1439                 env->out.sendvideo = 1;
1440                 env->out.qmin = 3;
1441         }
1442         CV_START(var, val);
1443         CV_STR("videodevice", env->out.videodevice);
1444         CV_BOOL("sendvideo", env->out.sendvideo);
1445         CV_F("video_size", video_geom(&env->out.enc_in, val));
1446         CV_F("camera_size", video_geom(&env->out.loc_src, val));
1447         CV_F("local_size", video_geom(&env->out.loc_dpy, val));
1448         CV_F("remote_size", video_geom(&env->in.rem_dpy, val));
1449         CV_STR("keypad", env->keypad_file);
1450         CV_F("region", keypad_cfg_read(&env->gui, val));
1451         CV_STR("keypad_font", env->keypad_font);
1452         CV_STR("sdl_videodriver", env->sdl_videodriver);
1453         CV_UINT("fps", env->out.fps);
1454         CV_UINT("bitrate", env->out.bitrate);
1455         CV_UINT("qmin", env->out.qmin);
1456         CV_STR("videocodec", env->codec_name);
1457         return 1;       /* nothing found */
1458
1459         CV_END;         /* the 'nothing found' case */
1460         return 0;               /* found something */
1461 }
1462
1463 #endif  /* video support */