604a580280b368b9ad0a8c397d0bc4655f96e656
[asterisk/asterisk.git] / channels / console_video.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright 2007, 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         sleep(1);
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 uninitialize the entire environment.
437  * In practice, signal the thread and give it a bit of time to
438  * complete, giving up if it gets stuck. Because uninit
439  * is called from hangup with the channel locked, and the thread
440  * uses the chan lock, we need to unlock here. This is unsafe,
441  * and we should really use refcounts for the channels.
442  */
443 void console_video_uninit(struct video_desc *env)
444 {
445         int i, t = 100; /* initial wait is shorter, than make it longer */
446         env->shutdown = 1;
447         for (i=0; env->shutdown && i < 10; i++) {
448                 ast_channel_unlock(env->owner);
449                 usleep(t);
450                 t = 1000000;
451                 ast_channel_lock(env->owner);
452         }
453         env->owner = NULL;
454 }
455
456 /*! fill an AVPicture from our fbuf info, as it is required by
457  * the image conversion routines in ffmpeg.
458  * XXX This depends on the format.
459  */
460 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p)
461 {
462         /* provide defaults for commonly used formats */
463         int l4 = b->w * b->h/4; /* size of U or V frame */
464         int len = b->w;         /* Y linesize, bytes */
465         int luv = b->w/2;       /* U/V linesize, bytes */
466
467         bzero(p, sizeof(*p));
468         switch (b->pix_fmt) {
469         case PIX_FMT_RGB555:
470         case PIX_FMT_RGB565:
471                 len *= 2;
472                 luv = 0;
473                 break;
474         case PIX_FMT_RGBA32:
475                 len *= 4;
476                 luv = 0;
477                 break;
478         case PIX_FMT_YUYV422:   /* Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr */
479                 len *= 2;       /* all data in first plane, probably */
480                 luv = 0;
481                 break;
482         }
483         p->data[0] = b->data;
484         p->linesize[0] = len;
485         /* these are only valid for component images */
486         p->data[1] = luv ? b->data + 4*l4 : b->data+len;
487         p->data[2] = luv ? b->data + 5*l4 : b->data+len;
488         p->linesize[1] = luv;
489         p->linesize[2] = luv;
490         return p;
491 }
492
493 /*! convert/scale between an input and an output format.
494  * Old version of ffmpeg only have img_convert, which does not rescale.
495  * New versions use sws_scale which does both.
496  */
497 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
498         struct fbuf_t *out, AVPicture *p_out)
499 {
500         AVPicture my_p_in, my_p_out;
501
502         if (p_in == NULL)
503                 p_in = fill_pict(in, &my_p_in);
504         if (p_out == NULL)
505                 p_out = fill_pict(out, &my_p_out);
506
507 #ifdef OLD_FFMPEG
508         /* XXX img_convert is deprecated, and does not do rescaling */
509         img_convert(p_out, out->pix_fmt,
510                 p_in, in->pix_fmt, in->w, in->h);
511 #else /* XXX replacement */
512     {
513         struct SwsContext *convert_ctx;
514
515         convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
516                 out->w, out->h, out->pix_fmt,
517                 SWS_BICUBIC, NULL, NULL, NULL);
518         if (convert_ctx == NULL) {
519                 ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
520                 return;
521         }
522         if (0)
523                 ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
524                         in->pix_fmt, in->w, in->h, out->pix_fmt, out->w, out->h);
525         sws_scale(convert_ctx,
526                 p_in->data, p_in->linesize,
527                 in->w, in->h, /* src slice */
528                 p_out->data, p_out->linesize);
529
530         sws_freeContext(convert_ctx);
531     }
532 #endif /* XXX replacement */
533 }
534
535 struct video_desc *get_video_desc(struct ast_channel *c);
536
537 /*
538  * This function is called (by asterisk) for each video packet
539  * coming from the network (the 'in' path) that needs to be processed.
540  * We need to reconstruct the entire video frame before we can decode it.
541  * After a video packet is received we have to:
542  * - extract the bitstream with pre_process_data()
543  * - append the bitstream to a buffer
544  * - if the fragment is the last (RTP Marker) we decode it with decode_video()
545  * - after the decoding is completed we display the decoded frame with show_frame()
546  */
547 int console_write_video(struct ast_channel *chan, struct ast_frame *f);
548 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
549 {
550         struct video_desc *env = get_video_desc(chan);
551         struct video_dec_desc *v = env->in;
552
553         if (!env->gui)  /* no gui, no rendering */
554                 return 0;
555         if (v == NULL)
556                 env->in = v = dec_init(f->subclass & ~1);
557         if (v == NULL) {
558                 /* This is not fatal, but we won't have incoming video */
559                 ast_log(LOG_WARNING, "Cannot initialize input decoder\n");
560                 return 0;
561         }
562
563         if (v->dec_in_cur == NULL)      /* no buffer for incoming frames, drop */
564                 return 0;
565 #if defined(DROP_PACKETS) && DROP_PACKETS > 0
566         /* Simulate lost packets */
567         if ((random() % 10000) <= 100*DROP_PACKETS) {
568                 ast_log(LOG_NOTICE, "Packet lost [%d]\n", f->seqno);
569                 return 0;
570         }
571 #endif
572         if (v->discard) {
573                 /*
574                  * In discard mode, drop packets until we find one with
575                  * the RTP marker set (which is the end of frame).
576                  * Note that the RTP marker flag is sent as the LSB of the
577                  * subclass, which is a  bitmask of formats. The low bit is
578                  * normally used for audio so there is no interference.
579                  */
580                 if (f->subclass & 0x01) {
581                         v->dec_in_cur->used = 0;
582                         v->dec_in_cur->ebit = 0;
583                         v->next_seq = f->seqno + 1;     /* wrap at 16 bit */
584                         v->discard = 0;
585                         ast_log(LOG_WARNING, "out of discard mode, frame %d\n", f->seqno);
586                 }
587                 return 0;
588         }
589
590         /*
591          * Only in-order fragments will be accepted. Remember seqno
592          * has 16 bit so there is wraparound. Also, ideally we could
593          * accept a bit of reordering, but at the moment we don't.
594          */
595         if (v->next_seq != f->seqno) {
596                 ast_log(LOG_WARNING, "discarding frame out of order, %d %d\n",
597                         v->next_seq, f->seqno);
598                 v->discard = 1;
599                 return 0;
600         }
601         v->next_seq++;
602
603         if (f->data == NULL || f->datalen < 2) {
604                 ast_log(LOG_WARNING, "empty video frame, discard\n");
605                 return 0;
606         }
607         if (v->d_callbacks->dec_decap(v->dec_in_cur, f->data, f->datalen)) {
608                 ast_log(LOG_WARNING, "error in dec_decap, enter discard\n");
609                 v->discard = 1;
610         }
611         if (f->subclass & 0x01) {       // RTP Marker
612                 /* prepare to decode: advance the buffer so the video thread knows. */
613                 struct fbuf_t *tmp = v->dec_in_cur;     /* store current pointer */
614                 ast_mutex_lock(&env->dec_lock);
615                 if (++v->dec_in_cur == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
616                         v->dec_in_cur = &v->dec_in[0];
617                 if (v->dec_in_dpy == NULL) {    /* were not displaying anything, so set it */
618                         v->dec_in_dpy = tmp;
619                 } else if (v->dec_in_dpy == v->dec_in_cur) { /* current slot is busy */
620                         v->dec_in_cur = NULL;
621                 }
622                 ast_mutex_unlock(&env->dec_lock);
623         }
624         return 0;
625 }
626
627
628 /*! \brief read a frame from webcam or X11 through grabber_read(),
629  * display it,  then encode and split it.
630  * Return a list of ast_frame representing the video fragments.
631  * The head pointer is returned by the function, the tail pointer
632  * is returned as an argument.
633  */
634 static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_frame **tail)
635 {
636         struct video_out_desc *v = &env->out;
637         struct ast_frame *dummy;
638         struct fbuf_t *loc_src = grabber_read(v);
639
640         if (!loc_src)
641                 return NULL;    /* can happen, e.g. we are reading too early */
642
643         if (tail == NULL)
644                 tail = &dummy;
645         *tail = NULL;
646         /* Scale the video for the encoder, then use it for local rendering
647          * so we will see the same as the remote party.
648          */
649         my_scale(loc_src, NULL, &env->enc_in, NULL);
650         show_frame(env, WIN_LOCAL);
651         if (!v->sendvideo)
652                 return NULL;
653         if (v->enc_out.data == NULL) {
654                 static volatile int a = 0;
655                 if (a++ < 2)
656                         ast_log(LOG_WARNING, "fail, no encoder output buffer\n");
657                 return NULL;
658         }
659         v->enc->enc_run(v);
660         return v->enc->enc_encap(&v->enc_out, v->mtu, tail);
661 }
662
663 /*
664  * Helper thread to periodically poll the video source and enqueue the
665  * generated frames to the channel's queue.
666  * Using a separate thread also helps because the encoding can be
667  * computationally expensive so we don't want to starve the main thread.
668  */
669 static void *video_thread(void *arg)
670 {
671         struct video_desc *env = arg;
672         int count = 0;
673         char save_display[128] = "";
674
675         /* if sdl_videodriver is set, override the environment. Also,
676          * if it contains 'console' override DISPLAY around the call to SDL_Init
677          * so we use the console as opposed to the x11 version of aalib
678          */
679         if (!ast_strlen_zero(env->sdl_videodriver)) { /* override */
680                 const char *s = getenv("DISPLAY");
681                 setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1);
682                 if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) {
683                         ast_copy_string(save_display, s, sizeof(save_display));
684                         unsetenv("DISPLAY");
685                 }
686         }
687         sdl_setup(env);
688         if (!ast_strlen_zero(save_display))
689                 setenv("DISPLAY", save_display, 1);
690
691         /* initialize grab coordinates */
692         env->out.loc_src_geometry.x = 0;
693         env->out.loc_src_geometry.y = 0;
694
695         ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */
696
697         if (grabber_open(&env->out)) {
698                 ast_log(LOG_WARNING, "cannot open local video source\n");
699         } else {
700 #if 0
701                 /* In principle, try to register the fd.
702                  * In practice, many webcam drivers do not support select/poll,
703                  * so don't bother and instead read periodically from the
704                  * video thread.
705                  */
706                 if (env->out.fd >= 0)
707                         ast_channel_set_fd(env->owner, 1, env->out.fd);
708 #endif
709                 video_out_init(env);
710         }
711
712         for (;;) {
713                 struct timeval t = { 0, 50000 };        /* XXX 20 times/sec */
714                 struct ast_frame *p, *f;
715                 struct ast_channel *chan = env->owner;
716                 int fd = chan->alertpipe[1];
717                 char *caption = NULL, buf[160];
718
719                 /* determine if video format changed */
720                 if (count++ % 10 == 0) {
721                         if (env->out.sendvideo)
722                             sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
723                                 env->out.videodevice, env->codec_name,
724                                 env->enc_in.w, env->enc_in.h,
725                                 env->out.fps, env->out.bitrate/1000);
726                         else
727                             sprintf(buf, "hold");
728                         caption = buf;
729                 }
730
731                 /* manage keypad events */
732                 /* XXX here we should always check for events,
733                 * otherwise the drag will not work */ 
734                 if (env->gui)
735                         eventhandler(env, caption);
736  
737                 /* sleep for a while */
738                 ast_select(0, NULL, NULL, NULL, &t);
739
740             if (env->in) {
741                 struct video_dec_desc *v = env->in;
742                 
743                 /*
744                  * While there is something to display, call the decoder and free
745                  * the buffer, possibly enabling the receiver to store new data.
746                  */
747                 while (v->dec_in_dpy) {
748                         struct fbuf_t *tmp = v->dec_in_dpy;     /* store current pointer */
749
750                         if (v->d_callbacks->dec_run(v, tmp))
751                                 show_frame(env, WIN_REMOTE);
752                         tmp->used = 0;  /* mark buffer as free */
753                         tmp->ebit = 0;
754                         ast_mutex_lock(&env->dec_lock);
755                         if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN])    /* advance to next, circular */
756                                 v->dec_in_dpy = &v->dec_in[0];
757
758                         if (v->dec_in_cur == NULL)      /* receiver was idle, enable it... */
759                                 v->dec_in_cur = tmp;    /* using the slot just freed */
760                         else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */
761                                 v->dec_in_dpy = NULL;   /* nothing more to display */
762                         ast_mutex_unlock(&env->dec_lock);
763                 }
764             }
765
766                 if (env->shutdown)
767                         break;
768                 f = get_video_frames(env, &p);  /* read and display */
769                 if (!f)
770                         continue;
771                 chan = env->owner;
772                 ast_channel_lock(chan);
773
774                 /* AST_LIST_INSERT_TAIL is only good for one frame, cannot use here */
775                 if (chan->readq.first == NULL) {
776                         chan->readq.first = f;
777                 } else {
778                         chan->readq.last->frame_list.next = f;
779                 }
780                 chan->readq.last = p;
781                 /*
782                  * more or less same as ast_queue_frame, but extra
783                  * write on the alertpipe to signal frames.
784                  */
785                 if (fd > -1) {
786                         int blah = 1, l = sizeof(blah);
787                         for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
788                                 if (write(fd, &blah, l) != l)
789                                         ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
790                                             chan->name, f->frametype, f->subclass, strerror(errno));
791                         }
792                 }
793                 ast_channel_unlock(chan);
794         }
795         /* thread terminating, here could call the uninit */
796         /* uninitialize the local and remote video environments */
797         env->in = dec_uninit(env->in);
798         video_out_uninit(env);
799
800         if (env->gui)
801                 env->gui = cleanup_sdl(env->gui);
802         ast_mutex_destroy(&env->dec_lock);
803         env->shutdown = 0;
804         return NULL;
805 }
806
807 static void copy_geometry(struct fbuf_t *src, struct fbuf_t *dst)
808 {
809         if (dst->w == 0)
810                 dst->w = src->w;
811         if (dst->h == 0)
812                 dst->h = src->h;
813 }
814
815 /*! initialize the video environment.
816  * Apart from the formats (constant) used by sdl and the codec,
817  * we use enc_in as the basic geometry.
818  */
819 static void init_env(struct video_desc *env)
820 {
821         struct fbuf_t *c = &(env->out.loc_src_geometry);                /* local source */
822         struct fbuf_t *ei = &(env->enc_in);             /* encoder input */
823         struct fbuf_t *ld = &(env->loc_dpy);    /* local display */
824         struct fbuf_t *rd = &(env->rem_dpy);            /* remote display */
825
826         c->pix_fmt = PIX_FMT_YUV420P;   /* default - camera format */
827         ei->pix_fmt = PIX_FMT_YUV420P;  /* encoder input */
828         if (ei->w == 0 || ei->h == 0) {
829                 ei->w = 352;
830                 ei->h = 288;
831         }
832         ld->pix_fmt = rd->pix_fmt = PIX_FMT_YUV420P; /* sdl format */
833         /* inherit defaults */
834         copy_geometry(ei, c);   /* camera inherits from encoder input */
835         copy_geometry(ei, rd);  /* remote display inherits from encoder input */
836         copy_geometry(rd, ld);  /* local display inherits from remote display */
837 }
838
839 /*!
840  * The first call to the video code, called by oss_new() or similar.
841  * Here we initialize the various components we use, namely SDL for display,
842  * ffmpeg for encoding/decoding, and a local video source.
843  * We do our best to progress even if some of the components are not
844  * available.
845  */
846 void console_video_start(struct video_desc *env, struct ast_channel *owner)
847 {
848         if (env == NULL)        /* video not initialized */
849                 return;
850         if (owner == NULL)      /* nothing to do if we don't have a channel */
851                 return;
852         env->owner = owner;
853         init_env(env);
854         env->out.enc = map_config_video_format(env->codec_name);
855
856         ast_log(LOG_WARNING, "start video out %s %dx%d\n",
857                 env->codec_name, env->enc_in.w,  env->enc_in.h);
858         /*
859          * Register all codecs supported by the ffmpeg library.
860          * We only need to do it once, but probably doesn't
861          * harm to do it multiple times.
862          */
863         avcodec_init();
864         avcodec_register_all();
865         av_log_set_level(AV_LOG_ERROR); /* only report errors */
866
867         if (env->out.fps == 0) {
868                 env->out.fps = 15;
869                 ast_log(LOG_WARNING, "fps unset, forcing to %d\n", env->out.fps);
870         }
871         if (env->out.bitrate == 0) {
872                 env->out.bitrate = 65000;
873                 ast_log(LOG_WARNING, "bitrate unset, forcing to %d\n", env->out.bitrate);
874         }
875
876         ast_pthread_create_background(&env->vthread, NULL, video_thread, env);
877 }
878
879 /*
880  * Parse a geometry string, accepting also common names for the formats.
881  * Trick: if we have a leading > or < and a numeric geometry,
882  * return the larger or smaller one.
883  * E.g. <352x288 gives the smaller one, 320x240
884  */
885 static int video_geom(struct fbuf_t *b, const char *s)
886 {
887         int w = 0, h = 0;
888
889         static struct {
890                 const char *s; int w; int h;
891         } *fp, formats[] = {
892                 {"16cif",       1408, 1152 },
893                 {"xga",         1024, 768 },
894                 {"4cif",        704, 576 },
895                 {"vga",         640, 480 },
896                 {"cif",         352, 288 },
897                 {"qvga",        320, 240 },
898                 {"qcif",        176, 144 },
899                 {"sqcif",       128, 96 },
900                 {NULL,          0, 0 },
901         };
902         if (*s == '<' || *s == '>')
903                 sscanf(s+1,"%dx%d", &w, &h);
904         for (fp = formats; fp->s; fp++) {
905                 if (*s == '>') {        /* look for a larger one */
906                         if (fp->w <= w) {
907                                 if (fp > formats)
908                                         fp--; /* back one step if possible */
909                                 break;
910                         }
911                 } else if (*s == '<') { /* look for a smaller one */
912                         if (fp->w < w)
913                                 break;
914                 } else if (!strcasecmp(s, fp->s)) { /* look for a string */
915                         break;
916                 }
917         }
918         if (*s == '<' && fp->s == NULL) /* smallest */
919                 fp--;
920         if (fp->s) {
921                 b->w = fp->w;
922                 b->h = fp->h;
923         } else if (sscanf(s, "%dx%d", &b->w, &b->h) != 2) {
924                 ast_log(LOG_WARNING, "Invalid video_size %s, using 352x288\n", s);
925                 b->w = 352;
926                 b->h = 288;
927         }
928         return 0;
929 }
930
931 /* extend ast_cli with video commands. Called by console_video_config */
932 int console_video_cli(struct video_desc *env, const char *var, int fd)
933 {
934         if (env == NULL)
935                 return 1;       /* unrecognised */
936
937         if (!strcasecmp(var, "videodevice")) {
938                 ast_cli(fd, "videodevice is [%s]\n", env->out.videodevice);
939         } else if (!strcasecmp(var, "videocodec")) {
940                 ast_cli(fd, "videocodec is [%s]\n", env->codec_name);
941         } else if (!strcasecmp(var, "sendvideo")) {
942                 ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
943         } else if (!strcasecmp(var, "video_size")) {
944                 int in_w = 0, in_h = 0;
945                 if (env->in) {
946                         in_w = env->in->dec_out.w;
947                         in_h = env->in->dec_out.h;
948                 }
949                 ast_cli(fd, "sizes: video %dx%d camera %dx%d local %dx%d remote %dx%d in %dx%d\n",
950                         env->enc_in.w, env->enc_in.h,
951                         env->out.loc_src_geometry.w, env->out.loc_src_geometry.h,
952                         env->loc_dpy.w, env->loc_dpy.h,
953                         env->rem_dpy.w, env->rem_dpy.h,
954                         in_w, in_h);
955         } else if (!strcasecmp(var, "bitrate")) {
956                 ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
957         } else if (!strcasecmp(var, "qmin")) {
958                 ast_cli(fd, "qmin is [%d]\n", env->out.qmin);
959         } else if (!strcasecmp(var, "fps")) {
960                 ast_cli(fd, "fps is [%d]\n", env->out.fps);
961         } else {
962                 return 1;       /* unrecognised */
963         }
964         return 0;       /* recognised */
965 }
966
967 /*! parse config command for video support. */
968 int console_video_config(struct video_desc **penv,
969         const char *var, const char *val)
970 {
971         struct video_desc *env;
972
973         if (penv == NULL) {
974                 ast_log(LOG_WARNING, "bad argument penv=NULL\n");
975                 return 1;       /* error */
976         }
977         /* allocate the video descriptor first time we get here */
978         env = *penv;
979         if (env == NULL) {
980                 env = *penv = ast_calloc(1, sizeof(struct video_desc));
981                 if (env == NULL) {
982                         ast_log(LOG_WARNING, "fail to allocate video_desc\n");
983                         return 1;       /* error */
984                 
985                 }
986                 /* set default values */
987                 ast_copy_string(env->out.videodevice, "X11", sizeof(env->out.videodevice));
988                 env->out.fps = 5;
989                 env->out.bitrate = 65000;
990                 env->out.sendvideo = 1;
991                 env->out.qmin = 3;
992         }
993         CV_START(var, val);
994         CV_STR("videodevice", env->out.videodevice);
995         CV_BOOL("sendvideo", env->out.sendvideo);
996         CV_F("video_size", video_geom(&env->enc_in, val));
997         CV_F("camera_size", video_geom(&env->out.loc_src_geometry, val));
998         CV_F("local_size", video_geom(&env->loc_dpy, val));
999         CV_F("remote_size", video_geom(&env->rem_dpy, val));
1000         CV_STR("keypad", env->keypad_file);
1001         CV_F("region", keypad_cfg_read(env->gui, val));
1002         CV_STR("keypad_font", env->keypad_font);
1003         CV_STR("sdl_videodriver", env->sdl_videodriver);
1004         CV_UINT("fps", env->out.fps);
1005         CV_UINT("bitrate", env->out.bitrate);
1006         CV_UINT("qmin", env->out.qmin);
1007         CV_STR("videocodec", env->codec_name);
1008         return 1;       /* nothing found */
1009
1010         CV_END;         /* the 'nothing found' case */
1011         return 0;               /* found something */
1012 }
1013
1014 #endif  /* video support */