remove a leftover sleep(1) used for debugging
[asterisk/asterisk.git] / channels / console_video.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright 2007-2008, Marta Carbone, Sergio Fadda, Luigi Rizzo
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*
18  * Experimental support for video sessions. We use SDL for rendering, ffmpeg
19  * as the codec library for encoding and decoding, and Video4Linux and X11
20  * to generate the local video stream.
21  *
22  * If one of these pieces is not available, either at compile time or at
23  * runtime, we do our best to run without it. Of course, no codec library
24  * means we can only deal with raw data, no SDL means we cannot do rendering,
25  * no V4L or X11 means we cannot generate data (but in principle we could
26  * stream from or record to a file).
27  *
28  * We need a recent (2007.07.12 or newer) version of ffmpeg to avoid warnings.
29  * Older versions might give 'deprecated' messages during compilation,
30  * thus not compiling in AST_DEVMODE, or don't have swscale, in which case
31  * you can try to compile #defining OLD_FFMPEG here.
32  *
33  * $Revision$
34  */
35
36 //#define DROP_PACKETS 5       /* if set, drop this % of video packets */
37 //#define OLD_FFMPEG    1       /* set for old ffmpeg with no swscale */
38
39 #include "asterisk.h"
40 #include <sys/ioctl.h>
41 #include "asterisk/cli.h"
42 #include "asterisk/file.h"
43 #include "asterisk/channel.h"
44
45 #include "console_video.h"
46
47 /*
48 The code is structured as follows.
49
50 When a new console channel is created, we call console_video_start()
51 to initialize SDL, the source, and the encoder/ decoder for the
52 formats in use (XXX the latter two should be done later, once the
53 codec negotiation is complete).  Also, a thread is created to handle
54 the video source and generate frames.
55
56 While communication is on, the local source is generated by the
57 video thread, which wakes up periodically, generates frames and
58 enqueues them in chan->readq.  Incoming rtp frames are passed to
59 console_write_video(), decoded and passed to SDL for display.
60
61 For as unfortunate and confusing as it can be, we need to deal with a
62 number of different video representations (size, codec/pixel format,
63 codec parameters), as follows:
64
65  loc_src        is the data coming from the camera/X11/etc.
66         The format is typically constrained by the video source.
67
68  enc_in         is the input required by the encoder.
69         Typically constrained in size by the encoder type.
70
71  enc_out        is the bitstream transmitted over RTP.
72         Typically negotiated while the call is established.
73
74  loc_dpy        is the format used to display the local video source.
75         Depending on user preferences this can have the same size as
76         loc_src_fmt, or enc_in_fmt, or thumbnail size (e.g. PiP output)
77
78  dec_in         is the incoming RTP bitstream. Negotiated
79         during call establishment, it is not necessarily the same as
80         enc_in_fmt
81
82  dec_out        the output of the decoder.
83         The format is whatever the other side sends, and the
84         buffer is allocated by avcodec_decode_... so we only
85         copy the data here.
86
87  rem_dpy        the format used to display the remote stream
88
89 We store the format info together with the buffer storing the data.
90 As a future optimization, a format/buffer may reference another one
91 if the formats are equivalent. This will save some unnecessary format
92 conversion.
93
94
95 In order to handle video you need to add to sip.conf (and presumably
96 iax.conf too) the following:
97
98         [general](+)
99                 videosupport=yes
100                 allow=h263      ; this or other video formats
101                 allow=h263p     ; this or other video formats
102
103  */
104
105 /*
106  * Codecs are absolutely necessary or we cannot do anything.
107  * SDL is optional (used for rendering only), so that we can still
108  * stream video withouth displaying it.
109  */
110 #if !defined(HAVE_VIDEO_CONSOLE) || !defined(HAVE_FFMPEG)
111 /* stubs if required pieces are missing */
112 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
113 {
114         return 0;       /* writing video not supported */
115 }
116
117 int console_video_cli(struct video_desc *env, const char *var, int fd)
118 {
119         return 1;       /* nothing matched */
120 }
121
122 int console_video_config(struct video_desc **penv, const char *var, const char *val)
123 {
124         return 1;       /* no configuration */
125 }
126
127 void console_video_start(struct video_desc *env, struct ast_channel *owner)
128 {
129         ast_log(LOG_NOTICE, "voice only, console video support not present\n");
130 }
131
132 void console_video_uninit(struct video_desc *env)
133 {
134 }
135
136 int console_video_formats = 0;
137
138 #else /* defined(HAVE_FFMPEG) && defined(HAVE_SDL) */
139
140 /*! The list of video formats we support. */
141 int console_video_formats = 
142         AST_FORMAT_H263_PLUS | AST_FORMAT_H263 |
143         AST_FORMAT_MP4_VIDEO | AST_FORMAT_H264 | AST_FORMAT_H261 ;
144
145
146
147 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
148         struct fbuf_t *out, AVPicture *p_out);
149
150 struct video_codec_desc;        /* forward declaration */
151 /*
152  * Descriptor of the local source, made of the following pieces:
153  *  + configuration info (geometry, device name, fps...). These are read
154  *    from the config file and copied here before calling video_out_init();
155  *  + the frame buffer (buf) and source pixel format, allocated at init time;
156  *  + the encoding and RTP info, including timestamps to generate
157  *    frames at the correct rate;
158  *  + source-specific info, i.e. fd for /dev/video, dpy-image for x11, etc,
159  *    filled in by grabber_open
160  * NOTE: loc_src.data == NULL means the rest of the struct is invalid, and
161  *      the video source is not available.
162  */
163 struct video_out_desc {
164         /* video device support.
165          * videodevice and geometry are read from the config file.
166          * At the right time we try to open it and allocate a buffer.
167          * If we are successful, webcam_bufsize > 0 and we can read.
168          */
169         /* all the following is config file info copied from the parent */
170         char            videodevice[64];
171         int             fps;
172         int             bitrate;
173         int             qmin;
174
175         int sendvideo;
176
177         struct fbuf_t   loc_src_geometry;       /* local source geometry only (from config file) */
178         struct fbuf_t   enc_out;        /* encoder output buffer, allocated in video_out_init() */
179
180         struct video_codec_desc *enc;   /* encoder */
181         void            *enc_ctx;       /* encoding context */
182         AVCodec         *codec;
183         AVFrame         *enc_in_frame;  /* enc_in mapped into avcodec format. */
184                                         /* The initial part of AVFrame is an AVPicture */
185         int             mtu;
186         struct timeval  last_frame;     /* when we read the last frame ? */
187
188         struct grab_desc *grabber;
189         void            *grabber_data;
190 };
191
192 /*
193  * The overall descriptor, with room for config info, video source and
194  * received data descriptors, SDL info, etc.
195  * This should be globally visible to all modules (grabber, vcodecs, gui)
196  * and contain all configurtion info.
197  */
198 struct video_desc {
199         char                    codec_name[64]; /* the codec we use */
200
201         pthread_t               vthread;        /* video thread */
202         ast_mutex_t             dec_lock;       /* sync decoder and video thread */
203         int                     shutdown;       /* set to shutdown vthread */
204         struct ast_channel      *owner;         /* owner channel */
205
206
207         struct fbuf_t   enc_in;         /* encoder input buffer, allocated in video_out_init() */
208
209         char                    keypad_file[256];       /* image for the keypad */
210         char                    keypad_font[256];       /* font for the keypad */
211
212         char                    sdl_videodriver[256];
213
214         struct fbuf_t           rem_dpy;        /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */
215         struct fbuf_t           loc_dpy;        /* display local source, no buffer (managed by SDL in bmp[1]) */
216
217
218         /* local information for grabbers, codecs, gui */
219         struct gui_info         *gui;
220         struct video_dec_desc   *in;            /* remote video descriptor */
221         struct video_out_desc   out;            /* local video descriptor */
222 };
223
224 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
225
226 void fbuf_free(struct fbuf_t *b)
227 {
228         struct fbuf_t x = *b;
229
230         if (b->data && b->size)
231                 ast_free(b->data);
232         bzero(b, sizeof(*b));
233         /* restore some fields */
234         b->w = x.w;
235         b->h = x.h;
236         b->pix_fmt = x.pix_fmt;
237 }
238
239 #include "vcodecs.c"
240 #include "console_gui.c"
241
242 /*! \brief Try to open a video source, return 0 on success, 1 on error */
243 static int grabber_open(struct video_out_desc *v)
244 {
245         struct grab_desc *g;
246         void *g_data;
247         int i;
248
249         for (i = 0; (g = console_grabbers[i]); i++) {
250                 g_data = g->open(v->videodevice, &v->loc_src_geometry, v->fps);
251                 if (g_data) {
252                         v->grabber = g;
253                         v->grabber_data = g_data;
254                         return 0;
255                 }
256         }
257         return 1; /* no source found */
258 }
259
260 /*! \brief complete a buffer from the local video source.
261  * Called by get_video_frames(), in turn called by the video thread.
262  */
263 static struct fbuf_t *grabber_read(struct video_out_desc *v)
264 {
265         struct timeval now = ast_tvnow();
266
267         if (v->grabber == NULL) /* not initialized */
268                 return 0;
269
270         /* check if it is time to read */
271         if (ast_tvzero(v->last_frame))
272                 v->last_frame = now;
273         if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
274                 return 0;       /* too early */
275         v->last_frame = now; /* XXX actually, should correct for drift */
276         return v->grabber->read(v->grabber_data);
277 }
278
279 /*! \brief handler run when dragging with the left button on
280  * the local source window - the effect is to move the offset
281  * of the captured area.
282  */
283 static void grabber_move(struct video_out_desc *v, int dx, int dy)
284 {
285         if (v->grabber && v->grabber->move)
286                 v->grabber->move(v->grabber_data, dx, dy);
287 }
288
289 /*
290  * Map the codec name to the library. If not recognised, use a default.
291  * This is useful in the output path where we decide by name, presumably.
292  */
293 static struct video_codec_desc *map_config_video_format(char *name)
294 {
295         int i;
296
297         for (i = 0; supported_codecs[i]; i++)
298                 if (!strcasecmp(name, supported_codecs[i]->name))
299                         break;
300         if (supported_codecs[i] == NULL) {
301                 ast_log(LOG_WARNING, "Cannot find codec for '%s'\n", name);
302                 i = 0;
303                 strcpy(name, supported_codecs[i]->name);
304         }
305         ast_log(LOG_WARNING, "Using codec '%s'\n", name);
306         return supported_codecs[i];
307 }
308
309
310 /*! \brief uninitialize the descriptor for local video stream */
311 static int video_out_uninit(struct video_desc *env)
312 {
313         struct video_out_desc *v = &env->out;
314
315         /* XXX this should be a codec callback */
316         if (v->enc_ctx) {
317                 AVCodecContext *enc_ctx = (AVCodecContext *)v->enc_ctx;
318                 avcodec_close(enc_ctx);
319                 av_free(enc_ctx);
320                 v->enc_ctx = NULL;
321         }
322         if (v->enc_in_frame) {
323                 av_free(v->enc_in_frame);
324                 v->enc_in_frame = NULL;
325         }
326         v->codec = NULL;        /* nothing to free, this is only a reference */
327         /* release the buffers */
328         fbuf_free(&env->enc_in);
329         fbuf_free(&v->enc_out);
330         /* close the grabber */
331         if (v->grabber) {
332                 v->grabber_data = v->grabber->close(v->grabber_data);
333                 v->grabber = NULL;
334         }
335         return -1;
336 }
337
338 /*
339  * Initialize the encoder for the local source:
340  * - enc_ctx, codec, enc_in_frame are used by ffmpeg for encoding;
341  * - enc_out is used to store the encoded frame (to be sent)
342  * - mtu is used to determine the max size of video fragment
343  * NOTE: we enter here with the video source already open.
344  */
345 static int video_out_init(struct video_desc *env)
346 {
347         int codec;
348         int size;
349         struct fbuf_t *enc_in;
350         struct video_out_desc *v = &env->out;
351
352         v->enc_ctx              = NULL;
353         v->codec                = NULL;
354         v->enc_in_frame         = NULL;
355         v->enc_out.data         = NULL;
356
357         codec = map_video_format(v->enc->format, CM_WR);
358         v->codec = avcodec_find_encoder(codec);
359         if (!v->codec) {
360                 ast_log(LOG_WARNING, "Cannot find the encoder for format %d\n",
361                         codec);
362                 return -1;      /* error, but nothing to undo yet */
363         }
364
365         v->mtu = 1400;  /* set it early so the encoder can use it */
366
367         /* allocate the input buffer for encoding.
368          * ffmpeg only supports PIX_FMT_YUV420P for the encoding.
369          */
370         enc_in = &env->enc_in;
371         enc_in->pix_fmt = PIX_FMT_YUV420P;
372         enc_in->size = (enc_in->w * enc_in->h * 3)/2;
373         enc_in->data = ast_calloc(1, enc_in->size);
374         if (!enc_in->data) {
375                 ast_log(LOG_WARNING, "Cannot allocate encoder input buffer\n");
376                 return video_out_uninit(env);
377         }
378         /* construct an AVFrame that points into buf_in */
379         v->enc_in_frame = avcodec_alloc_frame();
380         if (!v->enc_in_frame) {
381                 ast_log(LOG_WARNING, "Unable to allocate the encoding video frame\n");
382                 return video_out_uninit(env);
383         }
384
385         /* parameters for PIX_FMT_YUV420P */
386         size = enc_in->w * enc_in->h;
387         v->enc_in_frame->data[0] = enc_in->data;
388         v->enc_in_frame->data[1] = v->enc_in_frame->data[0] + size;
389         v->enc_in_frame->data[2] = v->enc_in_frame->data[1] + size/4;
390         v->enc_in_frame->linesize[0] = enc_in->w;
391         v->enc_in_frame->linesize[1] = enc_in->w/2;
392         v->enc_in_frame->linesize[2] = enc_in->w/2;
393
394         /* now setup the parameters for the encoder.
395          * XXX should be codec-specific
396          */
397     {
398         AVCodecContext *enc_ctx = avcodec_alloc_context();
399         v->enc_ctx = enc_ctx;
400         enc_ctx->pix_fmt = enc_in->pix_fmt;
401         enc_ctx->width = enc_in->w;
402         enc_ctx->height = enc_in->h;
403         /* XXX rtp_callback ?
404          * rtp_mode so ffmpeg inserts as many start codes as possible.
405          */
406         enc_ctx->rtp_mode = 1;
407         enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2
408         enc_ctx->bit_rate = v->bitrate;
409         enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
410         enc_ctx->qmin = v->qmin;        /* should be configured */
411         enc_ctx->time_base = (AVRational){1, v->fps};
412         enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
413
414         v->enc->enc_init(v->enc_ctx);
415  
416         if (avcodec_open(enc_ctx, v->codec) < 0) {
417                 ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n",
418                         codec);
419                 av_free(enc_ctx);
420                 v->enc_ctx = NULL;
421                 return video_out_uninit(env);
422         }
423     }
424         /*
425          * Allocate enough for the encoded bitstream. As we are compressing,
426          * we hope that the output is never larger than the input size.
427          */
428         v->enc_out.data = ast_calloc(1, enc_in->size);
429         v->enc_out.size = enc_in->size;
430         v->enc_out.used = 0;
431
432         return 0;
433 }
434
435 /*! \brief uninitialize the entire environment.
436  * In practice, signal the thread and give it a bit of time to
437  * complete, giving up if it gets stuck. Because uninit
438  * is called from hangup with the channel locked, and the thread
439  * uses the chan lock, we need to unlock here. This is unsafe,
440  * and we should really use refcounts for the channels.
441  */
442 void console_video_uninit(struct video_desc *env)
443 {
444         int i, t = 100; /* initial wait is shorter, than make it longer */
445         env->shutdown = 1;
446         for (i=0; env->shutdown && i < 10; i++) {
447                 ast_channel_unlock(env->owner);
448                 usleep(t);
449                 t = 1000000;
450                 ast_channel_lock(env->owner);
451         }
452         env->owner = NULL;
453 }
454
455 /*! fill an AVPicture from our fbuf info, as it is required by
456  * the image conversion routines in ffmpeg.
457  * XXX This depends on the format.
458  */
459 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p)
460 {
461         /* provide defaults for commonly used formats */
462         int l4 = b->w * b->h/4; /* size of U or V frame */
463         int len = b->w;         /* Y linesize, bytes */
464         int luv = b->w/2;       /* U/V linesize, bytes */
465
466         bzero(p, sizeof(*p));
467         switch (b->pix_fmt) {
468         case PIX_FMT_RGB555:
469         case PIX_FMT_RGB565:
470                 len *= 2;
471                 luv = 0;
472                 break;
473         case PIX_FMT_RGBA32:
474                 len *= 4;
475                 luv = 0;
476                 break;
477         case PIX_FMT_YUYV422:   /* Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr */
478                 len *= 2;       /* all data in first plane, probably */
479                 luv = 0;
480                 break;
481         }
482         p->data[0] = b->data;
483         p->linesize[0] = len;
484         /* these are only valid for component images */
485         p->data[1] = luv ? b->data + 4*l4 : b->data+len;
486         p->data[2] = luv ? b->data + 5*l4 : b->data+len;
487         p->linesize[1] = luv;
488         p->linesize[2] = luv;
489         return p;
490 }
491
492 /*! convert/scale between an input and an output format.
493  * Old version of ffmpeg only have img_convert, which does not rescale.
494  * New versions use sws_scale which does both.
495  */
496 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
497         struct fbuf_t *out, AVPicture *p_out)
498 {
499         AVPicture my_p_in, my_p_out;
500
501         if (p_in == NULL)
502                 p_in = fill_pict(in, &my_p_in);
503         if (p_out == NULL)
504                 p_out = fill_pict(out, &my_p_out);
505
506 #ifdef OLD_FFMPEG
507         /* XXX img_convert is deprecated, and does not do rescaling */
508         img_convert(p_out, out->pix_fmt,
509                 p_in, in->pix_fmt, in->w, in->h);
510 #else /* XXX replacement */
511     {
512         struct SwsContext *convert_ctx;
513
514         convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
515                 out->w, out->h, out->pix_fmt,
516                 SWS_BICUBIC, NULL, NULL, NULL);
517         if (convert_ctx == NULL) {
518                 ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
519                 return;
520         }
521         if (0)
522                 ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
523                         in->pix_fmt, in->w, in->h, out->pix_fmt, out->w, out->h);
524         sws_scale(convert_ctx,
525                 p_in->data, p_in->linesize,
526                 in->w, in->h, /* src slice */
527                 p_out->data, p_out->linesize);
528
529         sws_freeContext(convert_ctx);
530     }
531 #endif /* XXX replacement */
532 }
533
534 struct video_desc *get_video_desc(struct ast_channel *c);
535
536 /*
537  * This function is called (by asterisk) for each video packet
538  * coming from the network (the 'in' path) that needs to be processed.
539  * We need to reconstruct the entire video frame before we can decode it.
540  * After a video packet is received we have to:
541  * - extract the bitstream with pre_process_data()
542  * - append the bitstream to a buffer
543  * - if the fragment is the last (RTP Marker) we decode it with decode_video()
544  * - after the decoding is completed we display the decoded frame with show_frame()
545  */
546 int console_write_video(struct ast_channel *chan, struct ast_frame *f);
547 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
548 {
549         struct video_desc *env = get_video_desc(chan);
550         struct video_dec_desc *v = env->in;
551
552         if (!env->gui)  /* no gui, no rendering */
553                 return 0;
554         if (v == NULL)
555                 env->in = v = dec_init(f->subclass & ~1);
556         if (v == NULL) {
557                 /* This is not fatal, but we won't have incoming video */
558                 ast_log(LOG_WARNING, "Cannot initialize input decoder\n");
559                 return 0;
560         }
561
562         if (v->dec_in_cur == NULL)      /* no buffer for incoming frames, drop */
563                 return 0;
564 #if defined(DROP_PACKETS) && DROP_PACKETS > 0
565         /* Simulate lost packets */
566         if ((random() % 10000) <= 100*DROP_PACKETS) {
567                 ast_log(LOG_NOTICE, "Packet lost [%d]\n", f->seqno);
568                 return 0;
569         }
570 #endif
571         if (v->discard) {
572                 /*
573                  * In discard mode, drop packets until we find one with
574                  * the RTP marker set (which is the end of frame).
575                  * Note that the RTP marker flag is sent as the LSB of the
576                  * subclass, which is a  bitmask of formats. The low bit is
577                  * normally used for audio so there is no interference.
578                  */
579                 if (f->subclass & 0x01) {
580                         v->dec_in_cur->used = 0;
581                         v->dec_in_cur->ebit = 0;
582                         v->next_seq = f->seqno + 1;     /* wrap at 16 bit */
583                         v->discard = 0;
584                         ast_log(LOG_WARNING, "out of discard mode, frame %d\n", f->seqno);
585                 }
586                 return 0;
587         }
588
589         /*
590          * Only in-order fragments will be accepted. Remember seqno
591          * has 16 bit so there is wraparound. Also, ideally we could
592          * accept a bit of reordering, but at the moment we don't.
593          */
594         if (v->next_seq != f->seqno) {
595                 ast_log(LOG_WARNING, "discarding frame out of order, %d %d\n",
596                         v->next_seq, f->seqno);
597                 v->discard = 1;
598                 return 0;
599         }
600         v->next_seq++;
601
602         if (f->data == NULL || f->datalen < 2) {
603                 ast_log(LOG_WARNING, "empty video frame, discard\n");
604                 return 0;
605         }
606         if (v->d_callbacks->dec_decap(v->dec_in_cur, f->data, f->datalen)) {
607                 ast_log(LOG_WARNING, "error in dec_decap, enter discard\n");
608                 v->discard = 1;
609         }
610         if (f->subclass & 0x01) {       // RTP Marker
611                 /* prepare to decode: advance the buffer so the video thread knows. */
612                 struct fbuf_t *tmp = v->dec_in_cur;     /* store current pointer */
613                 ast_mutex_lock(&env->dec_lock);
614                 if (++v->dec_in_cur == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
615                         v->dec_in_cur = &v->dec_in[0];
616                 if (v->dec_in_dpy == NULL) {    /* were not displaying anything, so set it */
617                         v->dec_in_dpy = tmp;
618                 } else if (v->dec_in_dpy == v->dec_in_cur) { /* current slot is busy */
619                         v->dec_in_cur = NULL;
620                 }
621                 ast_mutex_unlock(&env->dec_lock);
622         }
623         return 0;
624 }
625
626
627 /*! \brief read a frame from webcam or X11 through grabber_read(),
628  * display it,  then encode and split it.
629  * Return a list of ast_frame representing the video fragments.
630  * The head pointer is returned by the function, the tail pointer
631  * is returned as an argument.
632  */
633 static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_frame **tail)
634 {
635         struct video_out_desc *v = &env->out;
636         struct ast_frame *dummy;
637         struct fbuf_t *loc_src = grabber_read(v);
638
639         if (!loc_src)
640                 return NULL;    /* can happen, e.g. we are reading too early */
641
642         if (tail == NULL)
643                 tail = &dummy;
644         *tail = NULL;
645         /* Scale the video for the encoder, then use it for local rendering
646          * so we will see the same as the remote party.
647          */
648         my_scale(loc_src, NULL, &env->enc_in, NULL);
649         show_frame(env, WIN_LOCAL);
650         if (!v->sendvideo)
651                 return NULL;
652         if (v->enc_out.data == NULL) {
653                 static volatile int a = 0;
654                 if (a++ < 2)
655                         ast_log(LOG_WARNING, "fail, no encoder output buffer\n");
656                 return NULL;
657         }
658         v->enc->enc_run(v);
659         return v->enc->enc_encap(&v->enc_out, v->mtu, tail);
660 }
661
662 /*
663  * Helper thread to periodically poll the video source and enqueue the
664  * generated frames to the channel's queue.
665  * Using a separate thread also helps because the encoding can be
666  * computationally expensive so we don't want to starve the main thread.
667  */
668 static void *video_thread(void *arg)
669 {
670         struct video_desc *env = arg;
671         int count = 0;
672         char save_display[128] = "";
673
674         /* if sdl_videodriver is set, override the environment. Also,
675          * if it contains 'console' override DISPLAY around the call to SDL_Init
676          * so we use the console as opposed to the x11 version of aalib
677          */
678         if (!ast_strlen_zero(env->sdl_videodriver)) { /* override */
679                 const char *s = getenv("DISPLAY");
680                 setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1);
681                 if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) {
682                         ast_copy_string(save_display, s, sizeof(save_display));
683                         unsetenv("DISPLAY");
684                 }
685         }
686         sdl_setup(env);
687         if (!ast_strlen_zero(save_display))
688                 setenv("DISPLAY", save_display, 1);
689
690         /* initialize grab coordinates */
691         env->out.loc_src_geometry.x = 0;
692         env->out.loc_src_geometry.y = 0;
693
694         ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */
695
696         if (grabber_open(&env->out)) {
697                 ast_log(LOG_WARNING, "cannot open local video source\n");
698         } else {
699 #if 0
700                 /* In principle, try to register the fd.
701                  * In practice, many webcam drivers do not support select/poll,
702                  * so don't bother and instead read periodically from the
703                  * video thread.
704                  */
705                 if (env->out.fd >= 0)
706                         ast_channel_set_fd(env->owner, 1, env->out.fd);
707 #endif
708                 video_out_init(env);
709         }
710
711         for (;;) {
712                 struct timeval t = { 0, 50000 };        /* XXX 20 times/sec */
713                 struct ast_frame *p, *f;
714                 struct ast_channel *chan = env->owner;
715                 int fd = chan->alertpipe[1];
716                 char *caption = NULL, buf[160];
717
718                 /* determine if video format changed */
719                 if (count++ % 10 == 0) {
720                         if (env->out.sendvideo)
721                             sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
722                                 env->out.videodevice, env->codec_name,
723                                 env->enc_in.w, env->enc_in.h,
724                                 env->out.fps, env->out.bitrate/1000);
725                         else
726                             sprintf(buf, "hold");
727                         caption = buf;
728                 }
729
730                 /* manage keypad events */
731                 /* XXX here we should always check for events,
732                 * otherwise the drag will not work */ 
733                 if (env->gui)
734                         eventhandler(env, caption);
735  
736                 /* sleep for a while */
737                 ast_select(0, NULL, NULL, NULL, &t);
738
739             if (env->in) {
740                 struct video_dec_desc *v = env->in;
741                 
742                 /*
743                  * While there is something to display, call the decoder and free
744                  * the buffer, possibly enabling the receiver to store new data.
745                  */
746                 while (v->dec_in_dpy) {
747                         struct fbuf_t *tmp = v->dec_in_dpy;     /* store current pointer */
748
749                         if (v->d_callbacks->dec_run(v, tmp))
750                                 show_frame(env, WIN_REMOTE);
751                         tmp->used = 0;  /* mark buffer as free */
752                         tmp->ebit = 0;
753                         ast_mutex_lock(&env->dec_lock);
754                         if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
755                                 v->dec_in_dpy = &v->dec_in[0];
756
757                         if (v->dec_in_cur == NULL)      /* receiver was idle, enable it... */
758                                 v->dec_in_cur = tmp;    /* using the slot just freed */
759                         else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
760                                 v->dec_in_dpy = NULL;   /* nothing more to display */
761                         ast_mutex_unlock(&env->dec_lock);
762                 }
763             }
764
765                 if (env->shutdown)
766                         break;
767                 f = get_video_frames(env, &p);  /* read and display */
768                 if (!f)
769                         continue;
770                 chan = env->owner;
771                 ast_channel_lock(chan);
772
773                 /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */
774                 if (chan->readq.first == NULL) {
775                         chan->readq.first = f;
776                 } else {
777                         chan->readq.last->frame_list.next = f;
778                 }
779                 chan->readq.last = p;
780                 /*
781                  * more or less same as ast_queue_frame, but extra
782                  * write on the alertpipe to signal frames.
783                  */
784                 if (fd > -1) {
785                         int blah = 1, l = sizeof(blah);
786                         for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
787                                 if (write(fd, &blah, l) != l)
788                                         ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
789                                             chan->name, f->frametype, f->subclass, strerror(errno));
790                         }
791                 }
792                 ast_channel_unlock(chan);
793         }
794         /* thread terminating, here could call the uninit */
795         /* uninitialize the local and remote video environments */
796         env->in = dec_uninit(env->in);
797         video_out_uninit(env);
798
799         if (env->gui)
800                 env->gui = cleanup_sdl(env->gui);
801         ast_mutex_destroy(&env->dec_lock);
802         env->shutdown = 0;
803         return NULL;
804 }
805
806 static void copy_geometry(struct fbuf_t *src, struct fbuf_t *dst)
807 {
808         if (dst->w == 0)
809                 dst->w = src->w;
810         if (dst->h == 0)
811                 dst->h = src->h;
812 }
813
814 /*! initialize the video environment.
815  * Apart from the formats (constant) used by sdl and the codec,
816  * we use enc_in as the basic geometry.
817  */
818 static void init_env(struct video_desc *env)
819 {
820         struct fbuf_t *c = &(env->out.loc_src_geometry);                /* local source */
821         struct fbuf_t *ei = &(env->enc_in);             /* encoder input */
822         struct fbuf_t *ld = &(env->loc_dpy);    /* local display */
823         struct fbuf_t *rd = &(env->rem_dpy);            /* remote display */
824
825         c->pix_fmt = PIX_FMT_YUV420P;   /* default - camera format */
826         ei->pix_fmt = PIX_FMT_YUV420P;  /* encoder input */
827         if (ei->w == 0 || ei->h == 0) {
828                 ei->w = 352;
829                 ei->h = 288;
830         }
831         ld->pix_fmt = rd->pix_fmt = PIX_FMT_YUV420P; /* sdl format */
832         /* inherit defaults */
833         copy_geometry(ei, c);   /* camera inherits from encoder input */
834         copy_geometry(ei, rd);  /* remote display inherits from encoder input */
835         copy_geometry(rd, ld);  /* local display inherits from remote display */
836 }
837
838 /*!
839  * The first call to the video code, called by oss_new() or similar.
840  * Here we initialize the various components we use, namely SDL for display,
841  * ffmpeg for encoding/decoding, and a local video source.
842  * We do our best to progress even if some of the components are not
843  * available.
844  */
845 void console_video_start(struct video_desc *env, struct ast_channel *owner)
846 {
847         if (env == NULL)        /* video not initialized */
848                 return;
849         if (owner == NULL)      /* nothing to do if we don't have a channel */
850                 return;
851         env->owner = owner;
852         init_env(env);
853         env->out.enc = map_config_video_format(env->codec_name);
854
855         ast_log(LOG_WARNING, "start video out %s %dx%d\n",
856                 env->codec_name, env->enc_in.w,  env->enc_in.h);
857         /*
858          * Register all codecs supported by the ffmpeg library.
859          * We only need to do it once, but probably doesn't
860          * harm to do it multiple times.
861          */
862         avcodec_init();
863         avcodec_register_all();
864         av_log_set_level(AV_LOG_ERROR); /* only report errors */
865
866         if (env->out.fps == 0) {
867                 env->out.fps = 15;
868                 ast_log(LOG_WARNING, "fps unset, forcing to %d\n", env->out.fps);
869         }
870         if (env->out.bitrate == 0) {
871                 env->out.bitrate = 65000;
872                 ast_log(LOG_WARNING, "bitrate unset, forcing to %d\n", env->out.bitrate);
873         }
874
875         ast_pthread_create_background(&env->vthread, NULL, video_thread, env);
876 }
877
878 /*
879  * Parse a geometry string, accepting also common names for the formats.
880  * Trick: if we have a leading > or < and a numeric geometry,
881  * return the larger or smaller one.
882  * E.g. <352x288 gives the smaller one, 320x240
883  */
884 static int video_geom(struct fbuf_t *b, const char *s)
885 {
886         int w = 0, h = 0;
887
888         static struct {
889                 const char *s; int w; int h;
890         } *fp, formats[] = {
891                 {"16cif",       1408, 1152 },
892                 {"xga",         1024, 768 },
893                 {"4cif",        704, 576 },
894                 {"vga",         640, 480 },
895                 {"cif",         352, 288 },
896                 {"qvga",        320, 240 },
897                 {"qcif",        176, 144 },
898                 {"sqcif",       128, 96 },
899                 {NULL,          0, 0 },
900         };
901         if (*s == '<' || *s == '>')
902                 sscanf(s+1,"%dx%d", &w, &h);
903         for (fp = formats; fp->s; fp++) {
904                 if (*s == '>') {        /* look for a larger one */
905                         if (fp->w <= w) {
906                                 if (fp > formats)
907                                         fp--; /* back one step if possible */
908                                 break;
909                         }
910                 } else if (*s == '<') { /* look for a smaller one */
911                         if (fp->w < w)
912                                 break;
913                 } else if (!strcasecmp(s, fp->s)) { /* look for a string */
914                         break;
915                 }
916         }
917         if (*s == '<' && fp->s == NULL) /* smallest */
918                 fp--;
919         if (fp->s) {
920                 b->w = fp->w;
921                 b->h = fp->h;
922         } else if (sscanf(s, "%dx%d", &b->w, &b->h) != 2) {
923                 ast_log(LOG_WARNING, "Invalid video_size %s, using 352x288\n", s);
924                 b->w = 352;
925                 b->h = 288;
926         }
927         return 0;
928 }
929
930 /* extend ast_cli with video commands. Called by console_video_config */
931 int console_video_cli(struct video_desc *env, const char *var, int fd)
932 {
933         if (env == NULL)
934                 return 1;       /* unrecognised */
935
936         if (!strcasecmp(var, "videodevice")) {
937                 ast_cli(fd, "videodevice is [%s]\n", env->out.videodevice);
938         } else if (!strcasecmp(var, "videocodec")) {
939                 ast_cli(fd, "videocodec is [%s]\n", env->codec_name);
940         } else if (!strcasecmp(var, "sendvideo")) {
941                 ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
942         } else if (!strcasecmp(var, "video_size")) {
943                 int in_w = 0, in_h = 0;
944                 if (env->in) {
945                         in_w = env->in->dec_out.w;
946                         in_h = env->in->dec_out.h;
947                 }
948                 ast_cli(fd, "sizes: video %dx%d camera %dx%d local %dx%d remote %dx%d in %dx%d\n",
949                         env->enc_in.w, env->enc_in.h,
950                         env->out.loc_src_geometry.w, env->out.loc_src_geometry.h,
951                         env->loc_dpy.w, env->loc_dpy.h,
952                         env->rem_dpy.w, env->rem_dpy.h,
953                         in_w, in_h);
954         } else if (!strcasecmp(var, "bitrate")) {
955                 ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
956         } else if (!strcasecmp(var, "qmin")) {
957                 ast_cli(fd, "qmin is [%d]\n", env->out.qmin);
958         } else if (!strcasecmp(var, "fps")) {
959                 ast_cli(fd, "fps is [%d]\n", env->out.fps);
960         } else {
961                 return 1;       /* unrecognised */
962         }
963         return 0;       /* recognised */
964 }
965
966 /*! parse config command for video support. */
967 int console_video_config(struct video_desc **penv,
968         const char *var, const char *val)
969 {
970         struct video_desc *env;
971
972         if (penv == NULL) {
973                 ast_log(LOG_WARNING, "bad argument penv=NULL\n");
974                 return 1;       /* error */
975         }
976         /* allocate the video descriptor first time we get here */
977         env = *penv;
978         if (env == NULL) {
979                 env = *penv = ast_calloc(1, sizeof(struct video_desc));
980                 if (env == NULL) {
981                         ast_log(LOG_WARNING, "fail to allocate video_desc\n");
982                         return 1;       /* error */
983                 
984                 }
985                 /* set default values */
986                 ast_copy_string(env->out.videodevice, "X11", sizeof(env->out.videodevice));
987                 env->out.fps = 5;
988                 env->out.bitrate = 65000;
989                 env->out.sendvideo = 1;
990                 env->out.qmin = 3;
991         }
992         CV_START(var, val);
993         CV_STR("videodevice", env->out.videodevice);
994         CV_BOOL("sendvideo", env->out.sendvideo);
995         CV_F("video_size", video_geom(&env->enc_in, val));
996         CV_F("camera_size", video_geom(&env->out.loc_src_geometry, val));
997         CV_F("local_size", video_geom(&env->loc_dpy, val));
998         CV_F("remote_size", video_geom(&env->rem_dpy, val));
999         CV_STR("keypad", env->keypad_file);
1000         CV_F("region", keypad_cfg_read(env->gui, val));
1001         CV_STR("keypad_font", env->keypad_font);
1002         CV_STR("sdl_videodriver", env->sdl_videodriver);
1003         CV_UINT("fps", env->out.fps);
1004         CV_UINT("bitrate", env->out.bitrate);
1005         CV_UINT("qmin", env->out.qmin);
1006         CV_STR("videocodec", env->codec_name);
1007         return 1;       /* nothing found */
1008
1009         CV_END;         /* the 'nothing found' case */
1010         return 0;               /* found something */
1011 }
1012
1013 #endif  /* video support */