implement the "console startgui" and "console stopgui"
[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         int                     stayopen;       /* set if gui starts manually */
202         pthread_t               vthread;        /* video thread */
203         ast_mutex_t             dec_lock;       /* sync decoder and video thread */
204         int                     shutdown;       /* set to shutdown vthread */
205         struct ast_channel      *owner;         /* owner channel */
206
207
208         struct fbuf_t   enc_in;         /* encoder input buffer, allocated in video_out_init() */
209
210         char                    keypad_file[256];       /* image for the keypad */
211         char                    keypad_font[256];       /* font for the keypad */
212
213         char                    sdl_videodriver[256];
214
215         struct fbuf_t           rem_dpy;        /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */
216         struct fbuf_t           loc_dpy;        /* display local source, no buffer (managed by SDL in bmp[1]) */
217
218
219         /* local information for grabbers, codecs, gui */
220         struct gui_info         *gui;
221         struct video_dec_desc   *in;            /* remote video descriptor */
222         struct video_out_desc   out;            /* local video descriptor */
223 };
224
225 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
226
227 void fbuf_free(struct fbuf_t *b)
228 {
229         struct fbuf_t x = *b;
230
231         if (b->data && b->size)
232                 ast_free(b->data);
233         bzero(b, sizeof(*b));
234         /* restore some fields */
235         b->w = x.w;
236         b->h = x.h;
237         b->pix_fmt = x.pix_fmt;
238 }
239
240 #include "vcodecs.c"
241 #include "console_gui.c"
242
243 /*! \brief Try to open a video source, return 0 on success, 1 on error */
244 static int grabber_open(struct video_out_desc *v)
245 {
246         struct grab_desc *g;
247         void *g_data;
248         int i;
249
250         for (i = 0; (g = console_grabbers[i]); i++) {
251                 g_data = g->open(v->videodevice, &v->loc_src_geometry, v->fps);
252                 if (g_data) {
253                         v->grabber = g;
254                         v->grabber_data = g_data;
255                         return 0;
256                 }
257         }
258         return 1; /* no source found */
259 }
260
261 /*! \brief complete a buffer from the local video source.
262  * Called by get_video_frames(), in turn called by the video thread.
263  */
264 static struct fbuf_t *grabber_read(struct video_out_desc *v)
265 {
266         struct timeval now = ast_tvnow();
267
268         if (v->grabber == NULL) /* not initialized */
269                 return 0;
270
271         /* check if it is time to read */
272         if (ast_tvzero(v->last_frame))
273                 v->last_frame = now;
274         if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
275                 return 0;       /* too early */
276         v->last_frame = now; /* XXX actually, should correct for drift */
277         return v->grabber->read(v->grabber_data);
278 }
279
280 /*! \brief handler run when dragging with the left button on
281  * the local source window - the effect is to move the offset
282  * of the captured area.
283  */
284 static void grabber_move(struct video_out_desc *v, int dx, int dy)
285 {
286         if (v->grabber && v->grabber->move)
287                 v->grabber->move(v->grabber_data, dx, dy);
288 }
289
290 /*
291  * Map the codec name to the library. If not recognised, use a default.
292  * This is useful in the output path where we decide by name, presumably.
293  */
294 static struct video_codec_desc *map_config_video_format(char *name)
295 {
296         int i;
297
298         for (i = 0; supported_codecs[i]; i++)
299                 if (!strcasecmp(name, supported_codecs[i]->name))
300                         break;
301         if (supported_codecs[i] == NULL) {
302                 ast_log(LOG_WARNING, "Cannot find codec for '%s'\n", name);
303                 i = 0;
304                 strcpy(name, supported_codecs[i]->name);
305         }
306         ast_log(LOG_WARNING, "Using codec '%s'\n", name);
307         return supported_codecs[i];
308 }
309
310
311 /*! \brief uninitialize the descriptor for local video stream */
312 static int video_out_uninit(struct video_desc *env)
313 {
314         struct video_out_desc *v = &env->out;
315
316         /* XXX this should be a codec callback */
317         if (v->enc_ctx) {
318                 AVCodecContext *enc_ctx = (AVCodecContext *)v->enc_ctx;
319                 avcodec_close(enc_ctx);
320                 av_free(enc_ctx);
321                 v->enc_ctx = NULL;
322         }
323         if (v->enc_in_frame) {
324                 av_free(v->enc_in_frame);
325                 v->enc_in_frame = NULL;
326         }
327         v->codec = NULL;        /* nothing to free, this is only a reference */
328         /* release the buffers */
329         fbuf_free(&env->enc_in);
330         fbuf_free(&v->enc_out);
331         /* close the grabber */
332         if (v->grabber) {
333                 v->grabber_data = v->grabber->close(v->grabber_data);
334                 v->grabber = NULL;
335         }
336         return -1;
337 }
338
339 /*
340  * Initialize the encoder for the local source:
341  * - enc_ctx, codec, enc_in_frame are used by ffmpeg for encoding;
342  * - enc_out is used to store the encoded frame (to be sent)
343  * - mtu is used to determine the max size of video fragment
344  * NOTE: we enter here with the video source already open.
345  */
346 static int video_out_init(struct video_desc *env)
347 {
348         int codec;
349         int size;
350         struct fbuf_t *enc_in;
351         struct video_out_desc *v = &env->out;
352
353         v->enc_ctx              = NULL;
354         v->codec                = NULL;
355         v->enc_in_frame         = NULL;
356         v->enc_out.data         = NULL;
357
358         codec = map_video_format(v->enc->format, CM_WR);
359         v->codec = avcodec_find_encoder(codec);
360         if (!v->codec) {
361                 ast_log(LOG_WARNING, "Cannot find the encoder for format %d\n",
362                         codec);
363                 return -1;      /* error, but nothing to undo yet */
364         }
365
366         v->mtu = 1400;  /* set it early so the encoder can use it */
367
368         /* allocate the input buffer for encoding.
369          * ffmpeg only supports PIX_FMT_YUV420P for the encoding.
370          */
371         enc_in = &env->enc_in;
372         enc_in->pix_fmt = PIX_FMT_YUV420P;
373         enc_in->size = (enc_in->w * enc_in->h * 3)/2;
374         enc_in->data = ast_calloc(1, enc_in->size);
375         if (!enc_in->data) {
376                 ast_log(LOG_WARNING, "Cannot allocate encoder input buffer\n");
377                 return video_out_uninit(env);
378         }
379         /* construct an AVFrame that points into buf_in */
380         v->enc_in_frame = avcodec_alloc_frame();
381         if (!v->enc_in_frame) {
382                 ast_log(LOG_WARNING, "Unable to allocate the encoding video frame\n");
383                 return video_out_uninit(env);
384         }
385
386         /* parameters for PIX_FMT_YUV420P */
387         size = enc_in->w * enc_in->h;
388         v->enc_in_frame->data[0] = enc_in->data;
389         v->enc_in_frame->data[1] = v->enc_in_frame->data[0] + size;
390         v->enc_in_frame->data[2] = v->enc_in_frame->data[1] + size/4;
391         v->enc_in_frame->linesize[0] = enc_in->w;
392         v->enc_in_frame->linesize[1] = enc_in->w/2;
393         v->enc_in_frame->linesize[2] = enc_in->w/2;
394
395         /* now setup the parameters for the encoder.
396          * XXX should be codec-specific
397          */
398     {
399         AVCodecContext *enc_ctx = avcodec_alloc_context();
400         v->enc_ctx = enc_ctx;
401         enc_ctx->pix_fmt = enc_in->pix_fmt;
402         enc_ctx->width = enc_in->w;
403         enc_ctx->height = enc_in->h;
404         /* XXX rtp_callback ?
405          * rtp_mode so ffmpeg inserts as many start codes as possible.
406          */
407         enc_ctx->rtp_mode = 1;
408         enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2
409         enc_ctx->bit_rate = v->bitrate;
410         enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
411         enc_ctx->qmin = v->qmin;        /* should be configured */
412         enc_ctx->time_base = (AVRational){1, v->fps};
413         enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds
414
415         v->enc->enc_init(v->enc_ctx);
416  
417         if (avcodec_open(enc_ctx, v->codec) < 0) {
418                 ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n",
419                         codec);
420                 av_free(enc_ctx);
421                 v->enc_ctx = NULL;
422                 return video_out_uninit(env);
423         }
424     }
425         /*
426          * Allocate enough for the encoded bitstream. As we are compressing,
427          * we hope that the output is never larger than the input size.
428          */
429         v->enc_out.data = ast_calloc(1, enc_in->size);
430         v->enc_out.size = enc_in->size;
431         v->enc_out.used = 0;
432
433         return 0;
434 }
435
436 /*! \brief possibly uninitialize the video console.
437  * Called at the end of a call, should reset the 'owner' field,
438  * then possibly terminate the video thread if the gui has
439  * not been started manually.
440  * In practice, signal the thread and give it a bit of time to
441  * complete, giving up if it gets stuck. Because uninit
442  * is called from hangup with the channel locked, and the thread
443  * uses the chan lock, we need to unlock here. This is unsafe,
444  * and we should really use refcounts for the channels.
445  */
446 void console_video_uninit(struct video_desc *env)
447 {
448         int i, t = 100; /* initial wait is shorter, than make it longer */
449         if (env->stayopen == 0) {       /* in a call */
450                 env->shutdown = 1;
451                 for (i=0; env->shutdown && i < 10; i++) {
452                         if (env->owner)
453                                 ast_channel_unlock(env->owner);
454                         usleep(t);
455                         t = 1000000;
456                         if (env->owner)
457                                 ast_channel_lock(env->owner);
458                 }
459         }
460         env->owner = NULL;      /* this is unconditional */
461 }
462
463 /*! fill an AVPicture from our fbuf info, as it is required by
464  * the image conversion routines in ffmpeg.
465  * XXX This depends on the format.
466  */
467 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p)
468 {
469         /* provide defaults for commonly used formats */
470         int l4 = b->w * b->h/4; /* size of U or V frame */
471         int len = b->w;         /* Y linesize, bytes */
472         int luv = b->w/2;       /* U/V linesize, bytes */
473
474         bzero(p, sizeof(*p));
475         switch (b->pix_fmt) {
476         case PIX_FMT_RGB555:
477         case PIX_FMT_RGB565:
478                 len *= 2;
479                 luv = 0;
480                 break;
481         case PIX_FMT_RGBA32:
482                 len *= 4;
483                 luv = 0;
484                 break;
485         case PIX_FMT_YUYV422:   /* Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr */
486                 len *= 2;       /* all data in first plane, probably */
487                 luv = 0;
488                 break;
489         }
490         p->data[0] = b->data;
491         p->linesize[0] = len;
492         /* these are only valid for component images */
493         p->data[1] = luv ? b->data + 4*l4 : b->data+len;
494         p->data[2] = luv ? b->data + 5*l4 : b->data+len;
495         p->linesize[1] = luv;
496         p->linesize[2] = luv;
497         return p;
498 }
499
500 /*! convert/scale between an input and an output format.
501  * Old version of ffmpeg only have img_convert, which does not rescale.
502  * New versions use sws_scale which does both.
503  */
504 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
505         struct fbuf_t *out, AVPicture *p_out)
506 {
507         AVPicture my_p_in, my_p_out;
508
509         if (p_in == NULL)
510                 p_in = fill_pict(in, &my_p_in);
511         if (p_out == NULL)
512                 p_out = fill_pict(out, &my_p_out);
513
514 #ifdef OLD_FFMPEG
515         /* XXX img_convert is deprecated, and does not do rescaling */
516         img_convert(p_out, out->pix_fmt,
517                 p_in, in->pix_fmt, in->w, in->h);
518 #else /* XXX replacement */
519     {
520         struct SwsContext *convert_ctx;
521
522         convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
523                 out->w, out->h, out->pix_fmt,
524                 SWS_BICUBIC, NULL, NULL, NULL);
525         if (convert_ctx == NULL) {
526                 ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
527                 return;
528         }
529         if (0)
530                 ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
531                         in->pix_fmt, in->w, in->h, out->pix_fmt, out->w, out->h);
532         sws_scale(convert_ctx,
533                 p_in->data, p_in->linesize,
534                 in->w, in->h, /* src slice */
535                 p_out->data, p_out->linesize);
536
537         sws_freeContext(convert_ctx);
538     }
539 #endif /* XXX replacement */
540 }
541
542 struct video_desc *get_video_desc(struct ast_channel *c);
543
544 /*
545  * This function is called (by asterisk) for each video packet
546  * coming from the network (the 'in' path) that needs to be processed.
547  * We need to reconstruct the entire video frame before we can decode it.
548  * After a video packet is received we have to:
549  * - extract the bitstream with pre_process_data()
550  * - append the bitstream to a buffer
551  * - if the fragment is the last (RTP Marker) we decode it with decode_video()
552  * - after the decoding is completed we display the decoded frame with show_frame()
553  */
554 int console_write_video(struct ast_channel *chan, struct ast_frame *f);
555 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
556 {
557         struct video_desc *env = get_video_desc(chan);
558         struct video_dec_desc *v = env->in;
559
560         if (!env->gui)  /* no gui, no rendering */
561                 return 0;
562         if (v == NULL)
563                 env->in = v = dec_init(f->subclass & ~1);
564         if (v == NULL) {
565                 /* This is not fatal, but we won't have incoming video */
566                 ast_log(LOG_WARNING, "Cannot initialize input decoder\n");
567                 return 0;
568         }
569
570         if (v->dec_in_cur == NULL)      /* no buffer for incoming frames, drop */
571                 return 0;
572 #if defined(DROP_PACKETS) && DROP_PACKETS > 0
573         /* Simulate lost packets */
574         if ((random() % 10000) <= 100*DROP_PACKETS) {
575                 ast_log(LOG_NOTICE, "Packet lost [%d]\n", f->seqno);
576                 return 0;
577         }
578 #endif
579         if (v->discard) {
580                 /*
581                  * In discard mode, drop packets until we find one with
582                  * the RTP marker set (which is the end of frame).
583                  * Note that the RTP marker flag is sent as the LSB of the
584                  * subclass, which is a  bitmask of formats. The low bit is
585                  * normally used for audio so there is no interference.
586                  */
587                 if (f->subclass & 0x01) {
588                         v->dec_in_cur->used = 0;
589                         v->dec_in_cur->ebit = 0;
590                         v->next_seq = f->seqno + 1;     /* wrap at 16 bit */
591                         v->discard = 0;
592                         ast_log(LOG_WARNING, "out of discard mode, frame %d\n", f->seqno);
593                 }
594                 return 0;
595         }
596
597         /*
598          * Only in-order fragments will be accepted. Remember seqno
599          * has 16 bit so there is wraparound. Also, ideally we could
600          * accept a bit of reordering, but at the moment we don't.
601          */
602         if (v->next_seq != f->seqno) {
603                 ast_log(LOG_WARNING, "discarding frame out of order, %d %d\n",
604                         v->next_seq, f->seqno);
605                 v->discard = 1;
606                 return 0;
607         }
608         v->next_seq++;
609
610         if (f->data == NULL || f->datalen < 2) {
611                 ast_log(LOG_WARNING, "empty video frame, discard\n");
612                 return 0;
613         }
614         if (v->d_callbacks->dec_decap(v->dec_in_cur, f->data, f->datalen)) {
615                 ast_log(LOG_WARNING, "error in dec_decap, enter discard\n");
616                 v->discard = 1;
617         }
618         if (f->subclass & 0x01) {       // RTP Marker
619                 /* prepare to decode: advance the buffer so the video thread knows. */
620                 struct fbuf_t *tmp = v->dec_in_cur;     /* store current pointer */
621                 ast_mutex_lock(&env->dec_lock);
622                 if (++v->dec_in_cur == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
623                         v->dec_in_cur = &v->dec_in[0];
624                 if (v->dec_in_dpy == NULL) {    /* were not displaying anything, so set it */
625                         v->dec_in_dpy = tmp;
626                 } else if (v->dec_in_dpy == v->dec_in_cur) { /* current slot is busy */
627                         v->dec_in_cur = NULL;
628                 }
629                 ast_mutex_unlock(&env->dec_lock);
630         }
631         return 0;
632 }
633
634
635 /*! \brief read a frame from webcam or X11 through grabber_read(),
636  * display it,  then encode and split it.
637  * Return a list of ast_frame representing the video fragments.
638  * The head pointer is returned by the function, the tail pointer
639  * is returned as an argument.
640  */
641 static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_frame **tail)
642 {
643         struct video_out_desc *v = &env->out;
644         struct ast_frame *dummy;
645         struct fbuf_t *loc_src = grabber_read(v);
646
647         if (!loc_src)
648                 return NULL;    /* can happen, e.g. we are reading too early */
649
650         if (tail == NULL)
651                 tail = &dummy;
652         *tail = NULL;
653         /* Scale the video for the encoder, then use it for local rendering
654          * so we will see the same as the remote party.
655          */
656         my_scale(loc_src, NULL, &env->enc_in, NULL);
657         show_frame(env, WIN_LOCAL);
658         if (!v->sendvideo)
659                 return NULL;
660         if (v->enc_out.data == NULL) {
661                 static volatile int a = 0;
662                 if (a++ < 2)
663                         ast_log(LOG_WARNING, "fail, no encoder output buffer\n");
664                 return NULL;
665         }
666         v->enc->enc_run(v);
667         return v->enc->enc_encap(&v->enc_out, v->mtu, tail);
668 }
669
670 int print_message(struct board *b, const char *s);
671
672 /*
673  * Helper thread to periodically poll the video source and enqueue the
674  * generated frames to the channel's queue.
675  * Using a separate thread also helps because the encoding can be
676  * computationally expensive so we don't want to starve the main thread.
677  */
678 static void *video_thread(void *arg)
679 {
680         struct video_desc *env = arg;
681         int count = 0;
682         char save_display[128] = "";
683
684         /* if sdl_videodriver is set, override the environment. Also,
685          * if it contains 'console' override DISPLAY around the call to SDL_Init
686          * so we use the console as opposed to the x11 version of aalib
687          */
688         if (!ast_strlen_zero(env->sdl_videodriver)) { /* override */
689                 const char *s = getenv("DISPLAY");
690                 setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1);
691                 if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) {
692                         ast_copy_string(save_display, s, sizeof(save_display));
693                         unsetenv("DISPLAY");
694                 }
695         }
696         sdl_setup(env);
697         if (!ast_strlen_zero(save_display))
698                 setenv("DISPLAY", save_display, 1);
699
700         /* initialize grab coordinates */
701         env->out.loc_src_geometry.x = 0;
702         env->out.loc_src_geometry.y = 0;
703
704         ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */
705
706         if (grabber_open(&env->out)) {
707                 ast_log(LOG_WARNING, "cannot open local video source\n");
708         } else {
709 #if 0
710                 /* In principle, try to register the fd.
711                  * In practice, many webcam drivers do not support select/poll,
712                  * so don't bother and instead read periodically from the
713                  * video thread.
714                  */
715                 if (env->out.fd >= 0)
716                         ast_channel_set_fd(env->owner, 1, env->out.fd);
717 #endif
718                 video_out_init(env);
719         }
720
721         for (;;) {
722                 struct timeval t = { 0, 50000 };        /* XXX 20 times/sec */
723                 struct ast_frame *p, *f;
724                 struct ast_channel *chan;
725                 int fd;
726                 char *caption = NULL, buf[160];
727
728                 sprintf(buf, "%d   \r", count);
729                 if (env->gui)
730                         print_message(env->gui->bd_msg, buf);
731
732                 /* determine if video format changed */
733                 if (count++ % 10 == 0) {
734                         if (env->out.sendvideo)
735                             sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
736                                 env->out.videodevice, env->codec_name,
737                                 env->enc_in.w, env->enc_in.h,
738                                 env->out.fps, env->out.bitrate/1000);
739                         else
740                             sprintf(buf, "hold");
741                         caption = buf;
742                 }
743
744                 /* manage keypad events */
745                 /* XXX here we should always check for events,
746                 * otherwise the drag will not work */ 
747                 if (env->gui)
748                         eventhandler(env, caption);
749  
750                 /* sleep for a while */
751                 ast_select(0, NULL, NULL, NULL, &t);
752
753             if (env->in) {
754                 struct video_dec_desc *v = env->in;
755                 
756                 /*
757                  * While there is something to display, call the decoder and free
758                  * the buffer, possibly enabling the receiver to store new data.
759                  */
760                 while (v->dec_in_dpy) {
761                         struct fbuf_t *tmp = v->dec_in_dpy;     /* store current pointer */
762
763                         if (v->d_callbacks->dec_run(v, tmp))
764                                 show_frame(env, WIN_REMOTE);
765                         tmp->used = 0;  /* mark buffer as free */
766                         tmp->ebit = 0;
767                         ast_mutex_lock(&env->dec_lock);
768                         if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
769                                 v->dec_in_dpy = &v->dec_in[0];
770
771                         if (v->dec_in_cur == NULL)      /* receiver was idle, enable it... */
772                                 v->dec_in_cur = tmp;    /* using the slot just freed */
773                         else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
774                                 v->dec_in_dpy = NULL;   /* nothing more to display */
775                         ast_mutex_unlock(&env->dec_lock);
776                 }
777             }
778
779                 if (env->shutdown)
780                         break;
781                 f = get_video_frames(env, &p);  /* read and display */
782                 if (!f)
783                         continue;
784                 chan = env->owner;
785                 if (chan == NULL)
786                         continue;
787                 fd = chan->alertpipe[1];
788                 ast_channel_lock(chan);
789
790                 /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */
791                 if (chan->readq.first == NULL) {
792                         chan->readq.first = f;
793                 } else {
794                         chan->readq.last->frame_list.next = f;
795                 }
796                 chan->readq.last = p;
797                 /*
798                  * more or less same as ast_queue_frame, but extra
799                  * write on the alertpipe to signal frames.
800                  */
801                 if (fd > -1) {
802                         int blah = 1, l = sizeof(blah);
803                         for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
804                                 if (write(fd, &blah, l) != l)
805                                         ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
806                                             chan->name, f->frametype, f->subclass, strerror(errno));
807                         }
808                 }
809                 ast_channel_unlock(chan);
810         }
811         /* thread terminating, here could call the uninit */
812         /* uninitialize the local and remote video environments */
813         env->in = dec_uninit(env->in);
814         video_out_uninit(env);
815
816         if (env->gui)
817                 env->gui = cleanup_sdl(env->gui);
818         ast_mutex_destroy(&env->dec_lock);
819         env->shutdown = 0;
820         return NULL;
821 }
822
823 static void copy_geometry(struct fbuf_t *src, struct fbuf_t *dst)
824 {
825         if (dst->w == 0)
826                 dst->w = src->w;
827         if (dst->h == 0)
828                 dst->h = src->h;
829 }
830
831 /*! initialize the video environment.
832  * Apart from the formats (constant) used by sdl and the codec,
833  * we use enc_in as the basic geometry.
834  */
835 static void init_env(struct video_desc *env)
836 {
837         struct fbuf_t *c = &(env->out.loc_src_geometry);                /* local source */
838         struct fbuf_t *ei = &(env->enc_in);             /* encoder input */
839         struct fbuf_t *ld = &(env->loc_dpy);    /* local display */
840         struct fbuf_t *rd = &(env->rem_dpy);            /* remote display */
841
842         c->pix_fmt = PIX_FMT_YUV420P;   /* default - camera format */
843         ei->pix_fmt = PIX_FMT_YUV420P;  /* encoder input */
844         if (ei->w == 0 || ei->h == 0) {
845                 ei->w = 352;
846                 ei->h = 288;
847         }
848         ld->pix_fmt = rd->pix_fmt = PIX_FMT_YUV420P; /* sdl format */
849         /* inherit defaults */
850         copy_geometry(ei, c);   /* camera inherits from encoder input */
851         copy_geometry(ei, rd);  /* remote display inherits from encoder input */
852         copy_geometry(rd, ld);  /* local display inherits from remote display */
853 }
854
855 /*!
856  * The first call to the video code, called by oss_new() or similar.
857  * Here we initialize the various components we use, namely SDL for display,
858  * ffmpeg for encoding/decoding, and a local video source.
859  * We do our best to progress even if some of the components are not
860  * available.
861  */
862 void console_video_start(struct video_desc *env, struct ast_channel *owner)
863 {
864         ast_log(LOG_WARNING, "env %p chan %p\n", env, owner);
865         if (env == NULL)        /* video not initialized */
866                 return;
867         env->owner = owner;     /* work even if no owner is specified */
868         if (env->stayopen)
869                 return;         /* already initialized, nothing to do */
870         init_env(env);
871         env->out.enc = map_config_video_format(env->codec_name);
872
873         ast_log(LOG_WARNING, "start video out %s %dx%d\n",
874                 env->codec_name, env->enc_in.w,  env->enc_in.h);
875         /*
876          * Register all codecs supported by the ffmpeg library.
877          * We only need to do it once, but probably doesn't
878          * harm to do it multiple times.
879          */
880         avcodec_init();
881         avcodec_register_all();
882         av_log_set_level(AV_LOG_ERROR); /* only report errors */
883
884         if (env->out.fps == 0) {
885                 env->out.fps = 15;
886                 ast_log(LOG_WARNING, "fps unset, forcing to %d\n", env->out.fps);
887         }
888         if (env->out.bitrate == 0) {
889                 env->out.bitrate = 65000;
890                 ast_log(LOG_WARNING, "bitrate unset, forcing to %d\n", env->out.bitrate);
891         }
892         ast_pthread_create_background(&env->vthread, NULL, video_thread, env);
893         if (env->owner == NULL)
894                 env->stayopen = 1;      /* manually opened so don't close on hangup */
895 }
896
897 /*
898  * Parse a geometry string, accepting also common names for the formats.
899  * Trick: if we have a leading > or < and a numeric geometry,
900  * return the larger or smaller one.
901  * E.g. <352x288 gives the smaller one, 320x240
902  */
903 static int video_geom(struct fbuf_t *b, const char *s)
904 {
905         int w = 0, h = 0;
906
907         static struct {
908                 const char *s; int w; int h;
909         } *fp, formats[] = {
910                 {"16cif",       1408, 1152 },
911                 {"xga",         1024, 768 },
912                 {"4cif",        704, 576 },
913                 {"vga",         640, 480 },
914                 {"cif",         352, 288 },
915                 {"qvga",        320, 240 },
916                 {"qcif",        176, 144 },
917                 {"sqcif",       128, 96 },
918                 {NULL,          0, 0 },
919         };
920         if (*s == '<' || *s == '>')
921                 sscanf(s+1,"%dx%d", &w, &h);
922         for (fp = formats; fp->s; fp++) {
923                 if (*s == '>') {        /* look for a larger one */
924                         if (fp->w <= w) {
925                                 if (fp > formats)
926                                         fp--; /* back one step if possible */
927                                 break;
928                         }
929                 } else if (*s == '<') { /* look for a smaller one */
930                         if (fp->w < w)
931                                 break;
932                 } else if (!strcasecmp(s, fp->s)) { /* look for a string */
933                         break;
934                 }
935         }
936         if (*s == '<' && fp->s == NULL) /* smallest */
937                 fp--;
938         if (fp->s) {
939                 b->w = fp->w;
940                 b->h = fp->h;
941         } else if (sscanf(s, "%dx%d", &b->w, &b->h) != 2) {
942                 ast_log(LOG_WARNING, "Invalid video_size %s, using 352x288\n", s);
943                 b->w = 352;
944                 b->h = 288;
945         }
946         return 0;
947 }
948
949 /* extend ast_cli with video commands. Called by console_video_config */
950 int console_video_cli(struct video_desc *env, const char *var, int fd)
951 {
952         if (env == NULL)
953                 return 1;       /* unrecognised */
954
955         if (!strcasecmp(var, "videodevice")) {
956                 ast_cli(fd, "videodevice is [%s]\n", env->out.videodevice);
957         } else if (!strcasecmp(var, "videocodec")) {
958                 ast_cli(fd, "videocodec is [%s]\n", env->codec_name);
959         } else if (!strcasecmp(var, "sendvideo")) {
960                 ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
961         } else if (!strcasecmp(var, "video_size")) {
962                 int in_w = 0, in_h = 0;
963                 if (env->in) {
964                         in_w = env->in->dec_out.w;
965                         in_h = env->in->dec_out.h;
966                 }
967                 ast_cli(fd, "sizes: video %dx%d camera %dx%d local %dx%d remote %dx%d in %dx%d\n",
968                         env->enc_in.w, env->enc_in.h,
969                         env->out.loc_src_geometry.w, env->out.loc_src_geometry.h,
970                         env->loc_dpy.w, env->loc_dpy.h,
971                         env->rem_dpy.w, env->rem_dpy.h,
972                         in_w, in_h);
973         } else if (!strcasecmp(var, "bitrate")) {
974                 ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
975         } else if (!strcasecmp(var, "qmin")) {
976                 ast_cli(fd, "qmin is [%d]\n", env->out.qmin);
977         } else if (!strcasecmp(var, "fps")) {
978                 ast_cli(fd, "fps is [%d]\n", env->out.fps);
979         } else if (!strcasecmp(var, "startgui")) {
980                 console_video_start(env, NULL);
981         } else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) {
982                 env->stayopen = 0;
983                 if (env->gui && env->owner)
984                         ast_cli_command(-1, "console hangup");
985                 else /* not in a call */
986                         console_video_uninit(env);
987         } else {
988                 return 1;       /* unrecognised */
989         }
990         return 0;       /* recognised */
991 }
992
993 /*! parse config command for video support. */
994 int console_video_config(struct video_desc **penv,
995         const char *var, const char *val)
996 {
997         struct video_desc *env;
998
999         if (penv == NULL) {
1000                 ast_log(LOG_WARNING, "bad argument penv=NULL\n");
1001                 return 1;       /* error */
1002         }
1003         /* allocate the video descriptor first time we get here */
1004         env = *penv;
1005         if (env == NULL) {
1006                 env = *penv = ast_calloc(1, sizeof(struct video_desc));
1007                 if (env == NULL) {
1008                         ast_log(LOG_WARNING, "fail to allocate video_desc\n");
1009                         return 1;       /* error */
1010                 
1011                 }
1012                 /* set default values */
1013                 ast_copy_string(env->out.videodevice, "X11", sizeof(env->out.videodevice));
1014                 env->out.fps = 5;
1015                 env->out.bitrate = 65000;
1016                 env->out.sendvideo = 1;
1017                 env->out.qmin = 3;
1018         }
1019         CV_START(var, val);
1020         CV_STR("videodevice", env->out.videodevice);
1021         CV_BOOL("sendvideo", env->out.sendvideo);
1022         CV_F("video_size", video_geom(&env->enc_in, val));
1023         CV_F("camera_size", video_geom(&env->out.loc_src_geometry, val));
1024         CV_F("local_size", video_geom(&env->loc_dpy, val));
1025         CV_F("remote_size", video_geom(&env->rem_dpy, val));
1026         CV_STR("keypad", env->keypad_file);
1027         CV_F("region", keypad_cfg_read(env->gui, val));
1028         CV_STR("keypad_font", env->keypad_font);
1029         CV_STR("sdl_videodriver", env->sdl_videodriver);
1030         CV_UINT("fps", env->out.fps);
1031         CV_UINT("bitrate", env->out.bitrate);
1032         CV_UINT("qmin", env->out.qmin);
1033         CV_STR("videocodec", env->codec_name);
1034         return 1;       /* nothing found */
1035
1036         CV_END;         /* the 'nothing found' case */
1037         return 0;               /* found something */
1038 }
1039
1040 #endif  /* video support */