00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "asterisk.h"
00040 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 147809 $")
00041 #include <sys/ioctl.h>
00042 #include "asterisk/cli.h"
00043 #include "asterisk/file.h"
00044 #include "asterisk/channel.h"
00045
00046 #include "console_video.h"
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #if !defined(HAVE_VIDEO_CONSOLE) || !defined(HAVE_FFMPEG)
00112
00113 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
00114 {
00115 return 0;
00116 }
00117
00118 int console_video_cli(struct video_desc *env, const char *var, int fd)
00119 {
00120 return 1;
00121 }
00122
00123 int console_video_config(struct video_desc **penv, const char *var, const char *val)
00124 {
00125 return 1;
00126 }
00127
00128 void console_video_start(struct video_desc *env, struct ast_channel *owner)
00129 {
00130 ast_log(LOG_NOTICE, "voice only, console video support not present\n");
00131 }
00132
00133 void console_video_uninit(struct video_desc *env)
00134 {
00135 }
00136
00137 int console_video_formats = 0;
00138
00139 #else
00140
00141
00142 int console_video_formats =
00143 AST_FORMAT_H263_PLUS | AST_FORMAT_H263 |
00144 AST_FORMAT_MP4_VIDEO | AST_FORMAT_H264 | AST_FORMAT_H261 ;
00145
00146
00147
00148 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
00149 struct fbuf_t *out, AVPicture *p_out);
00150
00151 struct video_codec_desc;
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 struct video_out_desc {
00165
00166
00167
00168
00169
00170
00171 char videodevice[64];
00172 int fps;
00173 int bitrate;
00174 int qmin;
00175
00176 int sendvideo;
00177
00178 struct fbuf_t loc_src_geometry;
00179 struct fbuf_t enc_out;
00180
00181 struct video_codec_desc *enc;
00182 void *enc_ctx;
00183 AVCodec *codec;
00184 AVFrame *enc_in_frame;
00185
00186 int mtu;
00187 struct timeval last_frame;
00188
00189 struct grab_desc *grabber;
00190 void *grabber_data;
00191 };
00192
00193
00194
00195
00196
00197
00198
00199 struct video_desc {
00200 char codec_name[64];
00201
00202 int stayopen;
00203 pthread_t vthread;
00204 ast_mutex_t dec_lock;
00205 int shutdown;
00206 struct ast_channel *owner;
00207
00208
00209 struct fbuf_t enc_in;
00210
00211 char keypad_file[256];
00212 char keypad_font[256];
00213
00214 char sdl_videodriver[256];
00215
00216 struct fbuf_t rem_dpy;
00217 struct fbuf_t loc_dpy;
00218
00219
00220
00221 struct gui_info *gui;
00222 struct video_dec_desc *in;
00223 struct video_out_desc out;
00224 };
00225
00226 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
00227
00228 void fbuf_free(struct fbuf_t *b)
00229 {
00230 struct fbuf_t x = *b;
00231
00232 if (b->data && b->size)
00233 ast_free(b->data);
00234 memset(b, '\0', sizeof(*b));
00235
00236 b->w = x.w;
00237 b->h = x.h;
00238 b->pix_fmt = x.pix_fmt;
00239 }
00240
00241 #include "vcodecs.c"
00242 #include "console_gui.c"
00243
00244
00245 static int grabber_open(struct video_out_desc *v)
00246 {
00247 struct grab_desc *g;
00248 void *g_data;
00249 int i;
00250
00251 for (i = 0; (g = console_grabbers[i]); i++) {
00252 g_data = g->open(v->videodevice, &v->loc_src_geometry, v->fps);
00253 if (g_data) {
00254 v->grabber = g;
00255 v->grabber_data = g_data;
00256 return 0;
00257 }
00258 }
00259 return 1;
00260 }
00261
00262
00263
00264
00265 static struct fbuf_t *grabber_read(struct video_out_desc *v)
00266 {
00267 struct timeval now = ast_tvnow();
00268
00269 if (v->grabber == NULL)
00270 return 0;
00271
00272
00273 if (ast_tvzero(v->last_frame))
00274 v->last_frame = now;
00275 if (ast_tvdiff_ms(now, v->last_frame) < 1000/v->fps)
00276 return 0;
00277 v->last_frame = now;
00278 return v->grabber->read(v->grabber_data);
00279 }
00280
00281
00282
00283
00284
00285 static void grabber_move(struct video_out_desc *v, int dx, int dy)
00286 {
00287 if (v->grabber && v->grabber->move)
00288 v->grabber->move(v->grabber_data, dx, dy);
00289 }
00290
00291
00292
00293
00294
00295 static struct video_codec_desc *map_config_video_format(char *name)
00296 {
00297 int i;
00298
00299 for (i = 0; supported_codecs[i]; i++)
00300 if (!strcasecmp(name, supported_codecs[i]->name))
00301 break;
00302 if (supported_codecs[i] == NULL) {
00303 ast_log(LOG_WARNING, "Cannot find codec for '%s'\n", name);
00304 i = 0;
00305 strcpy(name, supported_codecs[i]->name);
00306 }
00307 ast_log(LOG_WARNING, "Using codec '%s'\n", name);
00308 return supported_codecs[i];
00309 }
00310
00311
00312
00313 static int video_out_uninit(struct video_desc *env)
00314 {
00315 struct video_out_desc *v = &env->out;
00316
00317
00318 if (v->enc_ctx) {
00319 AVCodecContext *enc_ctx = (AVCodecContext *)v->enc_ctx;
00320 avcodec_close(enc_ctx);
00321 av_free(enc_ctx);
00322 v->enc_ctx = NULL;
00323 }
00324 if (v->enc_in_frame) {
00325 av_free(v->enc_in_frame);
00326 v->enc_in_frame = NULL;
00327 }
00328 v->codec = NULL;
00329
00330 fbuf_free(&env->enc_in);
00331 fbuf_free(&v->enc_out);
00332
00333 if (v->grabber) {
00334 v->grabber_data = v->grabber->close(v->grabber_data);
00335 v->grabber = NULL;
00336 }
00337 return -1;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347 static int video_out_init(struct video_desc *env)
00348 {
00349 int codec;
00350 int size;
00351 struct fbuf_t *enc_in;
00352 struct video_out_desc *v = &env->out;
00353
00354 v->enc_ctx = NULL;
00355 v->codec = NULL;
00356 v->enc_in_frame = NULL;
00357 v->enc_out.data = NULL;
00358
00359 codec = map_video_format(v->enc->format, CM_WR);
00360 v->codec = avcodec_find_encoder(codec);
00361 if (!v->codec) {
00362 ast_log(LOG_WARNING, "Cannot find the encoder for format %d\n",
00363 codec);
00364 return -1;
00365 }
00366
00367 v->mtu = 1400;
00368
00369
00370
00371
00372 enc_in = &env->enc_in;
00373 enc_in->pix_fmt = PIX_FMT_YUV420P;
00374 enc_in->size = (enc_in->w * enc_in->h * 3)/2;
00375 enc_in->data = ast_calloc(1, enc_in->size);
00376 if (!enc_in->data) {
00377 ast_log(LOG_WARNING, "Cannot allocate encoder input buffer\n");
00378 return video_out_uninit(env);
00379 }
00380
00381 v->enc_in_frame = avcodec_alloc_frame();
00382 if (!v->enc_in_frame) {
00383 ast_log(LOG_WARNING, "Unable to allocate the encoding video frame\n");
00384 return video_out_uninit(env);
00385 }
00386
00387
00388 size = enc_in->w * enc_in->h;
00389 v->enc_in_frame->data[0] = enc_in->data;
00390 v->enc_in_frame->data[1] = v->enc_in_frame->data[0] + size;
00391 v->enc_in_frame->data[2] = v->enc_in_frame->data[1] + size/4;
00392 v->enc_in_frame->linesize[0] = enc_in->w;
00393 v->enc_in_frame->linesize[1] = enc_in->w/2;
00394 v->enc_in_frame->linesize[2] = enc_in->w/2;
00395
00396
00397
00398
00399 {
00400 AVCodecContext *enc_ctx = avcodec_alloc_context();
00401 v->enc_ctx = enc_ctx;
00402 enc_ctx->pix_fmt = enc_in->pix_fmt;
00403 enc_ctx->width = enc_in->w;
00404 enc_ctx->height = enc_in->h;
00405
00406
00407
00408 enc_ctx->rtp_mode = 1;
00409 enc_ctx->rtp_payload_size = v->mtu / 2;
00410 enc_ctx->bit_rate = v->bitrate;
00411 enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2;
00412 enc_ctx->qmin = v->qmin;
00413 enc_ctx->time_base = (AVRational){1, v->fps};
00414 enc_ctx->gop_size = v->fps*5;
00415
00416 v->enc->enc_init(v->enc_ctx);
00417
00418 if (avcodec_open(enc_ctx, v->codec) < 0) {
00419 ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n",
00420 codec);
00421 av_free(enc_ctx);
00422 v->enc_ctx = NULL;
00423 return video_out_uninit(env);
00424 }
00425 }
00426
00427
00428
00429
00430 v->enc_out.data = ast_calloc(1, enc_in->size);
00431 v->enc_out.size = enc_in->size;
00432 v->enc_out.used = 0;
00433
00434 return 0;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 void console_video_uninit(struct video_desc *env)
00448 {
00449 int i, t = 100;
00450 if (env->stayopen == 0) {
00451 env->shutdown = 1;
00452 for (i=0; env->shutdown && i < 10; i++) {
00453 if (env->owner)
00454 ast_channel_unlock(env->owner);
00455 usleep(t);
00456 t = 1000000;
00457 if (env->owner)
00458 ast_channel_lock(env->owner);
00459 }
00460 }
00461 env->owner = NULL;
00462 }
00463
00464
00465
00466
00467
00468 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p)
00469 {
00470
00471 int l4 = b->w * b->h/4;
00472 int len = b->w;
00473 int luv = b->w/2;
00474
00475 memset(p, '\0', sizeof(*p));
00476 switch (b->pix_fmt) {
00477 case PIX_FMT_RGB555:
00478 case PIX_FMT_RGB565:
00479 len *= 2;
00480 luv = 0;
00481 break;
00482 case PIX_FMT_RGBA32:
00483 len *= 4;
00484 luv = 0;
00485 break;
00486 case PIX_FMT_YUYV422:
00487 len *= 2;
00488 luv = 0;
00489 break;
00490 }
00491 p->data[0] = b->data;
00492 p->linesize[0] = len;
00493
00494 p->data[1] = luv ? b->data + 4*l4 : b->data+len;
00495 p->data[2] = luv ? b->data + 5*l4 : b->data+len;
00496 p->linesize[1] = luv;
00497 p->linesize[2] = luv;
00498 return p;
00499 }
00500
00501
00502
00503
00504
00505 static void my_scale(struct fbuf_t *in, AVPicture *p_in,
00506 struct fbuf_t *out, AVPicture *p_out)
00507 {
00508 AVPicture my_p_in, my_p_out;
00509
00510 if (p_in == NULL)
00511 p_in = fill_pict(in, &my_p_in);
00512 if (p_out == NULL)
00513 p_out = fill_pict(out, &my_p_out);
00514
00515 #ifdef OLD_FFMPEG
00516
00517 img_convert(p_out, out->pix_fmt,
00518 p_in, in->pix_fmt, in->w, in->h);
00519 #else
00520 {
00521 struct SwsContext *convert_ctx;
00522
00523 convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt,
00524 out->w, out->h, out->pix_fmt,
00525 SWS_BICUBIC, NULL, NULL, NULL);
00526 if (convert_ctx == NULL) {
00527 ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
00528 return;
00529 }
00530 if (0)
00531 ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n",
00532 in->pix_fmt, in->w, in->h, out->pix_fmt, out->w, out->h);
00533 sws_scale(convert_ctx,
00534 p_in->data, p_in->linesize,
00535 in->w, in->h,
00536 p_out->data, p_out->linesize);
00537
00538 sws_freeContext(convert_ctx);
00539 }
00540 #endif
00541 }
00542
00543 struct video_desc *get_video_desc(struct ast_channel *c);
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 int console_write_video(struct ast_channel *chan, struct ast_frame *f);
00556 int console_write_video(struct ast_channel *chan, struct ast_frame *f)
00557 {
00558 struct video_desc *env = get_video_desc(chan);
00559 struct video_dec_desc *v = env->in;
00560
00561 if (!env->gui)
00562 return 0;
00563 if (v == NULL)
00564 env->in = v = dec_init(f->subclass & ~1);
00565 if (v == NULL) {
00566
00567 ast_log(LOG_WARNING, "Cannot initialize input decoder\n");
00568 return 0;
00569 }
00570
00571 if (v->dec_in_cur == NULL)
00572 return 0;
00573 #if defined(DROP_PACKETS) && DROP_PACKETS > 0
00574
00575 if ((random() % 10000) <= 100*DROP_PACKETS) {
00576 ast_log(LOG_NOTICE, "Packet lost [%d]\n", f->seqno);
00577 return 0;
00578 }
00579 #endif
00580 if (v->discard) {
00581
00582
00583
00584
00585
00586
00587
00588 if (f->subclass & 0x01) {
00589 v->dec_in_cur->used = 0;
00590 v->dec_in_cur->ebit = 0;
00591 v->next_seq = f->seqno + 1;
00592 v->discard = 0;
00593 ast_log(LOG_WARNING, "out of discard mode, frame %d\n", f->seqno);
00594 }
00595 return 0;
00596 }
00597
00598
00599
00600
00601
00602
00603 if (v->next_seq != f->seqno) {
00604 ast_log(LOG_WARNING, "discarding frame out of order, %d %d\n",
00605 v->next_seq, f->seqno);
00606 v->discard = 1;
00607 return 0;
00608 }
00609 v->next_seq++;
00610
00611 if (f->data == NULL || f->datalen < 2) {
00612 ast_log(LOG_WARNING, "empty video frame, discard\n");
00613 return 0;
00614 }
00615 if (v->d_callbacks->dec_decap(v->dec_in_cur, f->data, f->datalen)) {
00616 ast_log(LOG_WARNING, "error in dec_decap, enter discard\n");
00617 v->discard = 1;
00618 }
00619 if (f->subclass & 0x01) {
00620
00621 struct fbuf_t *tmp = v->dec_in_cur;
00622 ast_mutex_lock(&env->dec_lock);
00623 if (++v->dec_in_cur == &v->dec_in[N_DEC_IN])
00624 v->dec_in_cur = &v->dec_in[0];
00625 if (v->dec_in_dpy == NULL) {
00626 v->dec_in_dpy = tmp;
00627 } else if (v->dec_in_dpy == v->dec_in_cur) {
00628 v->dec_in_cur = NULL;
00629 }
00630 ast_mutex_unlock(&env->dec_lock);
00631 }
00632 return 0;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642 static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_frame **tail)
00643 {
00644 struct video_out_desc *v = &env->out;
00645 struct ast_frame *dummy;
00646 struct fbuf_t *loc_src = grabber_read(v);
00647
00648 if (!loc_src)
00649 return NULL;
00650
00651 if (tail == NULL)
00652 tail = &dummy;
00653 *tail = NULL;
00654
00655
00656
00657 my_scale(loc_src, NULL, &env->enc_in, NULL);
00658 show_frame(env, WIN_LOCAL);
00659 if (!v->sendvideo)
00660 return NULL;
00661 if (v->enc_out.data == NULL) {
00662 static volatile int a = 0;
00663 if (a++ < 2)
00664 ast_log(LOG_WARNING, "fail, no encoder output buffer\n");
00665 return NULL;
00666 }
00667 v->enc->enc_run(v);
00668 return v->enc->enc_encap(&v->enc_out, v->mtu, tail);
00669 }
00670
00671
00672
00673
00674
00675
00676
00677 static void *video_thread(void *arg)
00678 {
00679 struct video_desc *env = arg;
00680 int count = 0;
00681 char save_display[128] = "";
00682
00683
00684
00685
00686
00687 if (!ast_strlen_zero(env->sdl_videodriver)) {
00688 const char *s = getenv("DISPLAY");
00689 setenv("SDL_VIDEODRIVER", env->sdl_videodriver, 1);
00690 if (s && !strcasecmp(env->sdl_videodriver, "aalib-console")) {
00691 ast_copy_string(save_display, s, sizeof(save_display));
00692 unsetenv("DISPLAY");
00693 }
00694 }
00695 sdl_setup(env);
00696 if (!ast_strlen_zero(save_display))
00697 setenv("DISPLAY", save_display, 1);
00698
00699
00700 env->out.loc_src_geometry.x = 0;
00701 env->out.loc_src_geometry.y = 0;
00702
00703 ast_mutex_init(&env->dec_lock);
00704
00705 if (grabber_open(&env->out)) {
00706 ast_log(LOG_WARNING, "cannot open local video source\n");
00707 } else {
00708 #if 0
00709
00710
00711
00712
00713
00714 if (env->out.fd >= 0)
00715 ast_channel_set_fd(env->owner, 1, env->out.fd);
00716 #endif
00717 video_out_init(env);
00718 }
00719
00720 for (;;) {
00721 struct timeval t = { 0, 50000 };
00722 struct ast_frame *p, *f;
00723 struct ast_channel *chan;
00724 int fd;
00725 char *caption = NULL, buf[160];
00726
00727
00728 if (count++ % 10 == 0) {
00729 if (env->out.sendvideo)
00730 sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps",
00731 env->out.videodevice, env->codec_name,
00732 env->enc_in.w, env->enc_in.h,
00733 env->out.fps, env->out.bitrate/1000);
00734 else
00735 sprintf(buf, "hold");
00736 caption = buf;
00737 }
00738
00739
00740
00741
00742 if (env->gui)
00743 eventhandler(env, caption);
00744
00745
00746 ast_select(0, NULL, NULL, NULL, &t);
00747
00748 if (env->in) {
00749 struct video_dec_desc *v = env->in;
00750
00751
00752
00753
00754
00755 while (v->dec_in_dpy) {
00756 struct fbuf_t *tmp = v->dec_in_dpy;
00757
00758 if (v->d_callbacks->dec_run(v, tmp))
00759 show_frame(env, WIN_REMOTE);
00760 tmp->used = 0;
00761 tmp->ebit = 0;
00762 ast_mutex_lock(&env->dec_lock);
00763 if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN])
00764 v->dec_in_dpy = &v->dec_in[0];
00765
00766 if (v->dec_in_cur == NULL)
00767 v->dec_in_cur = tmp;
00768 else if (v->dec_in_dpy == v->dec_in_cur)
00769 v->dec_in_dpy = NULL;
00770 ast_mutex_unlock(&env->dec_lock);
00771 }
00772 }
00773
00774 if (env->shutdown)
00775 break;
00776 f = get_video_frames(env, &p);
00777 if (!f)
00778 continue;
00779 chan = env->owner;
00780 if (chan == NULL)
00781 continue;
00782 fd = chan->alertpipe[1];
00783 ast_channel_lock(chan);
00784
00785
00786 if (chan->readq.first == NULL) {
00787 chan->readq.first = f;
00788 } else {
00789 chan->readq.last->frame_list.next = f;
00790 }
00791 chan->readq.last = p;
00792
00793
00794
00795
00796 if (fd > -1) {
00797 int blah = 1, l = sizeof(blah);
00798 for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) {
00799 if (write(fd, &blah, l) != l)
00800 ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n",
00801 chan->name, f->frametype, f->subclass, strerror(errno));
00802 }
00803 }
00804 ast_channel_unlock(chan);
00805 }
00806
00807
00808 env->in = dec_uninit(env->in);
00809 video_out_uninit(env);
00810
00811 if (env->gui)
00812 env->gui = cleanup_sdl(env->gui);
00813 ast_mutex_destroy(&env->dec_lock);
00814 env->shutdown = 0;
00815 return NULL;
00816 }
00817
00818 static void copy_geometry(struct fbuf_t *src, struct fbuf_t *dst)
00819 {
00820 if (dst->w == 0)
00821 dst->w = src->w;
00822 if (dst->h == 0)
00823 dst->h = src->h;
00824 }
00825
00826
00827
00828
00829
00830 static void init_env(struct video_desc *env)
00831 {
00832 struct fbuf_t *c = &(env->out.loc_src_geometry);
00833 struct fbuf_t *ei = &(env->enc_in);
00834 struct fbuf_t *ld = &(env->loc_dpy);
00835 struct fbuf_t *rd = &(env->rem_dpy);
00836
00837 c->pix_fmt = PIX_FMT_YUV420P;
00838 ei->pix_fmt = PIX_FMT_YUV420P;
00839 if (ei->w == 0 || ei->h == 0) {
00840 ei->w = 352;
00841 ei->h = 288;
00842 }
00843 ld->pix_fmt = rd->pix_fmt = PIX_FMT_YUV420P;
00844
00845 copy_geometry(ei, c);
00846 copy_geometry(ei, rd);
00847 copy_geometry(rd, ld);
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857 void console_video_start(struct video_desc *env, struct ast_channel *owner)
00858 {
00859 ast_log(LOG_WARNING, "env %p chan %p\n", env, owner);
00860 if (env == NULL)
00861 return;
00862 env->owner = owner;
00863 if (env->stayopen)
00864 return;
00865 init_env(env);
00866 env->out.enc = map_config_video_format(env->codec_name);
00867
00868 ast_log(LOG_WARNING, "start video out %s %dx%d\n",
00869 env->codec_name, env->enc_in.w, env->enc_in.h);
00870
00871
00872
00873
00874
00875 avcodec_init();
00876 avcodec_register_all();
00877 av_log_set_level(AV_LOG_ERROR);
00878
00879 if (env->out.fps == 0) {
00880 env->out.fps = 15;
00881 ast_log(LOG_WARNING, "fps unset, forcing to %d\n", env->out.fps);
00882 }
00883 if (env->out.bitrate == 0) {
00884 env->out.bitrate = 65000;
00885 ast_log(LOG_WARNING, "bitrate unset, forcing to %d\n", env->out.bitrate);
00886 }
00887 ast_pthread_create_background(&env->vthread, NULL, video_thread, env);
00888 if (env->owner == NULL)
00889 env->stayopen = 1;
00890 }
00891
00892
00893
00894
00895
00896
00897
00898 static int video_geom(struct fbuf_t *b, const char *s)
00899 {
00900 int w = 0, h = 0;
00901
00902 static struct {
00903 const char *s; int w; int h;
00904 } *fp, formats[] = {
00905 {"16cif", 1408, 1152 },
00906 {"xga", 1024, 768 },
00907 {"4cif", 704, 576 },
00908 {"vga", 640, 480 },
00909 {"cif", 352, 288 },
00910 {"qvga", 320, 240 },
00911 {"qcif", 176, 144 },
00912 {"sqcif", 128, 96 },
00913 {NULL, 0, 0 },
00914 };
00915 if (*s == '<' || *s == '>')
00916 sscanf(s+1,"%dx%d", &w, &h);
00917 for (fp = formats; fp->s; fp++) {
00918 if (*s == '>') {
00919 if (fp->w <= w) {
00920 if (fp > formats)
00921 fp--;
00922 break;
00923 }
00924 } else if (*s == '<') {
00925 if (fp->w < w)
00926 break;
00927 } else if (!strcasecmp(s, fp->s)) {
00928 break;
00929 }
00930 }
00931 if (*s == '<' && fp->s == NULL)
00932 fp--;
00933 if (fp->s) {
00934 b->w = fp->w;
00935 b->h = fp->h;
00936 } else if (sscanf(s, "%dx%d", &b->w, &b->h) != 2) {
00937 ast_log(LOG_WARNING, "Invalid video_size %s, using 352x288\n", s);
00938 b->w = 352;
00939 b->h = 288;
00940 }
00941 return 0;
00942 }
00943
00944
00945 int console_video_cli(struct video_desc *env, const char *var, int fd)
00946 {
00947 if (env == NULL)
00948 return 1;
00949
00950 if (!strcasecmp(var, "videodevice")) {
00951 ast_cli(fd, "videodevice is [%s]\n", env->out.videodevice);
00952 } else if (!strcasecmp(var, "videocodec")) {
00953 ast_cli(fd, "videocodec is [%s]\n", env->codec_name);
00954 } else if (!strcasecmp(var, "sendvideo")) {
00955 ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off");
00956 } else if (!strcasecmp(var, "video_size")) {
00957 int in_w = 0, in_h = 0;
00958 if (env->in) {
00959 in_w = env->in->dec_out.w;
00960 in_h = env->in->dec_out.h;
00961 }
00962 ast_cli(fd, "sizes: video %dx%d camera %dx%d local %dx%d remote %dx%d in %dx%d\n",
00963 env->enc_in.w, env->enc_in.h,
00964 env->out.loc_src_geometry.w, env->out.loc_src_geometry.h,
00965 env->loc_dpy.w, env->loc_dpy.h,
00966 env->rem_dpy.w, env->rem_dpy.h,
00967 in_w, in_h);
00968 } else if (!strcasecmp(var, "bitrate")) {
00969 ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate);
00970 } else if (!strcasecmp(var, "qmin")) {
00971 ast_cli(fd, "qmin is [%d]\n", env->out.qmin);
00972 } else if (!strcasecmp(var, "fps")) {
00973 ast_cli(fd, "fps is [%d]\n", env->out.fps);
00974 } else if (!strcasecmp(var, "startgui")) {
00975 console_video_start(env, NULL);
00976 } else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) {
00977 env->stayopen = 0;
00978 if (env->gui && env->owner)
00979 ast_cli_command(-1, "console hangup");
00980 else
00981 console_video_uninit(env);
00982 } else {
00983 return 1;
00984 }
00985 return 0;
00986 }
00987
00988
00989 int console_video_config(struct video_desc **penv,
00990 const char *var, const char *val)
00991 {
00992 struct video_desc *env;
00993
00994 if (penv == NULL) {
00995 ast_log(LOG_WARNING, "bad argument penv=NULL\n");
00996 return 1;
00997 }
00998
00999 env = *penv;
01000 if (env == NULL) {
01001 env = *penv = ast_calloc(1, sizeof(struct video_desc));
01002 if (env == NULL) {
01003 ast_log(LOG_WARNING, "fail to allocate video_desc\n");
01004 return 1;
01005
01006 }
01007
01008 ast_copy_string(env->out.videodevice, "X11", sizeof(env->out.videodevice));
01009 env->out.fps = 5;
01010 env->out.bitrate = 65000;
01011 env->out.sendvideo = 1;
01012 env->out.qmin = 3;
01013 }
01014 CV_START(var, val);
01015 CV_STR("videodevice", env->out.videodevice);
01016 CV_BOOL("sendvideo", env->out.sendvideo);
01017 CV_F("video_size", video_geom(&env->enc_in, val));
01018 CV_F("camera_size", video_geom(&env->out.loc_src_geometry, val));
01019 CV_F("local_size", video_geom(&env->loc_dpy, val));
01020 CV_F("remote_size", video_geom(&env->rem_dpy, val));
01021 CV_STR("keypad", env->keypad_file);
01022 CV_F("region", keypad_cfg_read(env->gui, val));
01023 CV_STR("keypad_font", env->keypad_font);
01024 CV_STR("sdl_videodriver", env->sdl_videodriver);
01025 CV_UINT("fps", env->out.fps);
01026 CV_UINT("bitrate", env->out.bitrate);
01027 CV_UINT("qmin", env->out.qmin);
01028 CV_STR("videocodec", env->codec_name);
01029 return 1;
01030
01031 CV_END;
01032 return 0;
01033 }
01034
01035 #endif