Build console_video support by linking in, as opposed to including,
authorLuigi Rizzo <rizzo@icir.org>
Sat, 22 Dec 2007 18:28:40 +0000 (18:28 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Sat, 22 Dec 2007 18:28:40 +0000 (18:28 +0000)
console_video.c

This will ease the task of splitting console_video.c into its components
(V4L and X11 grabbers, various video codecs and packetizers, SDL),
as well as ease future extensions (e.g. additional video sources,
codecs and rendering engines).

For the time being nothing changes for users: video support is off by
default, and requires -DHAVE_VIDEO_CONSOLE on the command line to be included
(if SDL and FFMPEG are available).

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@94615 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/Makefile
channels/chan_oss.c
channels/console_video.c
channels/console_video.h [new file with mode: 0644]

index c02bbeb..50df82c 100644 (file)
@@ -51,6 +51,8 @@ endif
 
 all: _all
 
+chan_oss.so: console_video.o
+
 include $(ASTTOPDIR)/Makefile.moddir_rules
 
 ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)
index 14e6cdc..460d095 100644 (file)
@@ -63,6 +63,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/musiconhold.h"
 #include "asterisk/app.h"
 
+#include "console_video.h"
+
 /* ringtones we use */
 #include "busy.h"
 #include "ringtone.h"
@@ -268,8 +270,6 @@ static struct sound sounds[] = {
        { -1, NULL, 0, 0, 0, 0 },       /* end marker */
 };
 
-struct video_desc;             /* opaque type for video support */
-
 /*!
  * \brief descriptor for one of our channels.
  *
@@ -350,7 +350,7 @@ struct chan_oss_pvt {
 static struct chan_oss_pvt *find_desc(char *dev);
 
 /*! \brief return the pointer to the video descriptor */
-static attribute_unused struct video_desc *get_video_desc(struct ast_channel *c)
+struct video_desc *get_video_desc(struct ast_channel *c)
 {
        struct chan_oss_pvt *o = c->tech_pvt;
        return o ? o->env : NULL;
@@ -388,24 +388,11 @@ static int oss_indicate(struct ast_channel *chan, int cond, const void *data, si
 static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static char tdesc[] = "OSS Console Channel Driver";
 
-#ifdef HAVE_VIDEO_CONSOLE
-#include "console_video.c"
-#else
-#define CONSOLE_VIDEO_CMDS                                     \
-               "console {device}"
-/* provide replacements for some symbols used */
-#define        console_write_video             NULL
-#define        console_video_start(x, y)       {}
-#define        console_video_uninit(x)         {}
-#define        console_video_config(x, y, z)   1       /* pretend nothing recognised */
-#define        console_video_cli(x, y, z)      0       /* pretend nothing recognised */
-#define        CONSOLE_FORMAT_VIDEO            0
-#endif
-
-static const struct ast_channel_tech oss_tech = {
+/* cannot do const because need to update some fields at runtime */
+static struct ast_channel_tech oss_tech = {
        .type = "Console",
        .description = tdesc,
-       .capabilities = AST_FORMAT_SLINEAR | CONSOLE_FORMAT_VIDEO,
+       .capabilities = AST_FORMAT_SLINEAR, /* overwritten later */
        .requester = oss_request,
        .send_digit_begin = oss_digit_begin,
        .send_digit_end = oss_digit_end,
@@ -1017,7 +1004,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
        c->nativeformats = AST_FORMAT_SLINEAR;
        /* if the console makes the call, add video to the offer */
        if (state == AST_STATE_RINGING)
-               c->nativeformats |= CONSOLE_FORMAT_VIDEO;
+               c->nativeformats |= console_video_formats;
 
        c->readformat = AST_FORMAT_SLINEAR;
        c->writeformat = AST_FORMAT_SLINEAR;
@@ -1114,7 +1101,7 @@ static char *console_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
        value = a->argc > e->args ? a->argv[e->args] : NULL;
        if (value)      /* handle setting */
                store_config_core(o, var, value);
-       if (console_video_cli(o->env, var, a->fd))      /* print video-related values */
+       if (!console_video_cli(o->env, var, a->fd))     /* print video-related values */
                return CLI_SUCCESS;
        /* handle other values */
        if (!strcasecmp(var, "device")) {
@@ -1161,14 +1148,29 @@ static char *console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli
        return CLI_SUCCESS;
 }
 
+/*! \brief helper function for the answer key/cli command */
+char *console_do_answer(int fd);
+char *console_do_answer(int fd)
+{
+       struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
+       struct chan_oss_pvt *o = find_desc(oss_active);
+       if (!o->owner) {
+               if (fd > -1)
+                       ast_cli(fd, "No one is calling us\n");
+               return CLI_FAILURE;
+       }
+       o->hookstate = 1;
+       o->cursound = -1;
+       o->nosound = 0;
+       ast_queue_frame(o->owner, &f);
+       return CLI_SUCCESS;
+}
+
 /*!
  * \brief answer command from the console
  */
 static char *console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
-       struct chan_oss_pvt *o = find_desc(oss_active);
-
        switch (cmd) {
        case CLI_INIT:
                e->command = "console answer";
@@ -1182,15 +1184,7 @@ static char *console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
        }
        if (a->argc != e->args)
                return CLI_SHOWUSAGE;
-       if (!o->owner) {
-               ast_cli(a->fd, "No one is calling us\n");
-               return CLI_FAILURE;
-       }
-       o->hookstate = 1;
-       o->cursound = -1;
-       o->nosound = 0;
-       ast_queue_frame(o->owner, &f);
-       return CLI_SUCCESS;
+       return console_do_answer(a->fd);
 }
 
 /*!
@@ -1538,7 +1532,7 @@ static void store_config_core(struct chan_oss_pvt *o, const char *var, const cha
                return;
 
        if (!console_video_config(&o->env, var, value))
-               return;
+               return; /* matched there */
        CV_BOOL("autoanswer", o->autoanswer);
        CV_BOOL("autohangup", o->autohangup);
        CV_BOOL("overridecontext", o->overridecontext);
@@ -1657,6 +1651,8 @@ static int load_module(void)
                return AST_MODULE_LOAD_FAILURE;
        }
 
+       oss_tech.capabilities |= console_video_formats;
+
        if (ast_channel_register(&oss_tech)) {
                ast_log(LOG_ERROR, "Unable to register channel type 'OSS'\n");
                return AST_MODULE_LOAD_FAILURE;
index d59d3bb..f35813e 100644 (file)
 //#define DROP_PACKETS 5       /* if set, drop this % of video packets */
 //#define OLD_FFMPEG   1       /* set for old ffmpeg with no swscale */
 
+#include "asterisk.h"
+#include <sys/ioctl.h>
+#include <math.h>      /* sqrt */
+#include "asterisk/cli.h"
+#include "asterisk/file.h"
+#include "asterisk/channel.h"
+
+#include "console_video.h"
 
 /*
 The code is structured as follows.
@@ -84,7 +92,40 @@ iax.conf too) the following:
  * In principle SDL is optional too (used for rendering only, but we
  * could still source data withouth it), however at the moment it is required.
  */
-#if defined(HAVE_FFMPEG) && defined(HAVE_SDL)
+#if !defined(HAVE_VIDEO_CONSOLE) || !defined(HAVE_FFMPEG) || !defined(HAVE_SDL)
+/* stubs if required pieces are missing */
+int console_write_video(struct ast_channel *chan, struct ast_frame *f)
+{
+       return 0;       /* writing video not supported */
+}
+
+int console_video_cli(struct video_desc *env, const char *var, int fd)
+{
+       return 1;       /* nothing matched */
+}
+
+int console_video_config(struct video_desc **penv, const char *var, const char *val)
+{
+       return 1;       /* no configuration */
+}
+
+void console_video_start(struct video_desc *env, struct ast_channel *owner)
+{
+       ast_log(LOG_WARNING, "console video support not present\n");
+}
+
+void console_video_uninit(struct video_desc *env)
+{
+}
+
+int console_video_formats = 0;
+
+#else /* defined(HAVE_FFMPEG) && defined(HAVE_SDL) */
+
+/*! The list of video formats we support. */
+int console_video_formats = 
+       AST_FORMAT_H263_PLUS | AST_FORMAT_H263 |
+       AST_FORMAT_MP4_VIDEO | AST_FORMAT_H264 | AST_FORMAT_H261 ;
 
 #ifdef HAVE_X11
 #include <X11/Xlib.h>          /* this should be conditional */
@@ -304,12 +345,6 @@ struct video_desc {
        struct display_window   win[WIN_MAX];
 };
 
-/*! The list of video formats we support. */
-#define CONSOLE_FORMAT_VIDEO   (                       \
-       AST_FORMAT_H263_PLUS | AST_FORMAT_H263 |        \
-       AST_FORMAT_MP4_VIDEO |                          \
-       AST_FORMAT_H264 | AST_FORMAT_H261)
-
 static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p);
 
 static void fbuf_free(struct fbuf_t *b)
@@ -1867,7 +1902,7 @@ static void cleanup_sdl(struct video_desc *env)
  * uses the chan lock, we need to unlock here. This is unsafe,
  * and we should really use refcounts for the channels.
  */
-static void console_video_uninit(struct video_desc *env)
+void console_video_uninit(struct video_desc *env)
 {
        int i, t = 100; /* initial wait is shorter, than make it longer */
        env->shutdown = 1;
@@ -2011,7 +2046,7 @@ static void show_frame(struct video_desc *env, int out)
        SDL_UnlockYUVOverlay(bmp);
 }
 
-static struct video_desc *get_video_desc(struct ast_channel *c);
+struct video_desc *get_video_desc(struct ast_channel *c);
 
 /*
  * This function is called (by asterisk) for each video packet
@@ -2023,7 +2058,8 @@ static struct video_desc *get_video_desc(struct ast_channel *c);
  * - if the fragment is the last (RTP Marker) we decode it with decode_video()
  * - after the decoding is completed we display the decoded frame with show_frame()
  */
-static int console_write_video(struct ast_channel *chan, struct ast_frame *f)
+int console_write_video(struct ast_channel *chan, struct ast_frame *f);
+int console_write_video(struct ast_channel *chan, struct ast_frame *f)
 {
        struct video_desc *env = get_video_desc(chan);
        struct video_in_desc *v = &env->in;
@@ -2236,13 +2272,11 @@ static void append_char(char *str, int *str_pos, const char c)
 /* accumulate digits, possibly call dial if in connected mode */
 static void keypad_digit(struct video_desc *env, int digit)
 {      
-       struct chan_oss_pvt *o = find_desc(oss_active);
-
-       if (o->owner) {         /* we have a call, send the digit */
+       if (env->owner) {               /* we have a call, send the digit */
                struct ast_frame f = { AST_FRAME_DTMF, 0 };
 
                f.subclass = digit;
-               ast_queue_frame(o->owner, &f);
+               ast_queue_frame(env->owner, &f);
        } else {                /* no call, accumulate digits */
                append_char(env->gui.inbuf, &env->gui.inbuf_pos, digit);
        }
@@ -2258,25 +2292,31 @@ static void keypad_send_command(struct video_desc *env, char *command)
 }
 
 /* function used to toggle on/off the status of some variables */
-static char *keypad_toggle(int index)
+static char *keypad_toggle(struct video_desc *env, int index)
 {
-       struct chan_oss_pvt *o = find_desc(oss_active);
        ast_log(LOG_WARNING, "keypad_toggle(%i) called\n", index);
 
        switch (index) {
-       case KEY_MUTE:
-               o->mute = !o->mute;
-               break;
        case KEY_SENDVIDEO:
-               o->env->out.sendvideo = !o->env->out.sendvideo;
+               env->out.sendvideo = !env->out.sendvideo;
                break;
-       case KEY_AUTOANSWER:
+#ifdef notyet
+       case KEY_MUTE: {
+               struct chan_oss_pvt *o = find_desc(oss_active);
+               o->mute = !o->mute;
+               }
+               break;
+       case KEY_AUTOANSWER: {
+               struct chan_oss_pvt *o = find_desc(oss_active);
                o->autoanswer = !o->autoanswer;
+               }
                break;
+#endif
        }
        return NULL;
 }
 
+char *console_do_answer(int fd);
 /*
  * Function called when the pick up button is pressed
  * perform actions according the channel status:
@@ -2289,15 +2329,10 @@ static char *keypad_toggle(int index)
  */
 static void keypad_pick_up(struct video_desc *env)
 {
-       struct chan_oss_pvt *o = find_desc(oss_active);
        ast_log(LOG_WARNING, "keypad_pick_up called\n");
 
-       if (o->owner) { /* someone is calling us, just answer */
-               struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
-               o->hookstate = 1;
-               o->cursound = -1;
-               o->nosound = 0;
-               ast_queue_frame(o->owner, &f);
+       if (env->owner) { /* someone is calling us, just answer */
+               console_do_answer(-1);
        } else if (env->gui.inbuf_pos) { /* we have someone to call */
                ast_cli_command(env->gui.outfd, env->gui.inbuf);
        }
@@ -2404,7 +2439,7 @@ static void handle_button_event(struct video_desc *env, SDL_MouseButtonEvent but
        case KEY_MUTE:
        case KEY_AUTOANSWER:
        case KEY_SENDVIDEO:
-               keypad_toggle(index);
+               keypad_toggle(env, index);
                break;
 
        case KEY_LOCALVIDEO:
@@ -2822,8 +2857,7 @@ static int set_win(SDL_Surface *screen, struct display_window *win, int fmt,
  * We do our best to progress even if some of the components are not
  * available.
  */
-static void console_video_start(struct video_desc *env,
-       struct ast_channel *owner)
+void console_video_start(struct video_desc *env, struct ast_channel *owner)
 {
        if (env == NULL)        /* video not initialized */
                return;
@@ -3187,21 +3221,11 @@ static int keypad_cfg_read(struct gui_info *gui, const char *val)
        return 1;
 }
 
-/* list of commands supported by the cli.
- * For write operation we use the commands in console_video_config(),
- * for reads we use console_video_cli(). XXX Names should be fixed.
- */
-#define CONSOLE_VIDEO_CMDS                             \
-       "console {videodevice|videocodec|sendvideo"     \
-       "|video_size|bitrate|fps|qmin"                  \
-       "|keypad|keypad_mask|keypad_entry"              \
-       "}"
-
 /* extend ast_cli with video commands. Called by console_video_config */
-static int console_video_cli(struct video_desc *env, const char *var, int fd)
+int console_video_cli(struct video_desc *env, const char *var, int fd)
 {
        if (env == NULL)
-               return 0;       /* unrecognised */
+               return 1;       /* unrecognised */
 
         if (!strcasecmp(var, "videodevice")) {
                ast_cli(fd, "videodevice is [%s]\n", env->out.videodevice);
@@ -3223,13 +3247,13 @@ static int console_video_cli(struct video_desc *env, const char *var, int fd)
         } else if (!strcasecmp(var, "fps")) {
                ast_cli(fd, "fps is [%d]\n", env->out.fps);
         } else {
-               return 0;       /* unrecognised */
+               return 1;       /* unrecognised */
        }
-       return 1;       /* recognised */
+       return 0;       /* recognised */
 }
 
 /*! parse config command for video support. */
-static int console_video_config(struct video_desc **penv,
+int console_video_config(struct video_desc **penv,
        const char *var, const char *val)
 {
        struct video_desc *env;
diff --git a/channels/console_video.h b/channels/console_video.h
new file mode 100644 (file)
index 0000000..cb627a1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2007 Luigi Rizzo
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*
+ * Common header for console video support
+ *
+ * $Revision$
+ */
+
+struct video_desc;             /* opaque type for video support */
+
+struct video_desc *get_video_desc(struct ast_channel *c);
+
+/* linked by console_video.o */
+int console_write_video(struct ast_channel *chan, struct ast_frame *f);
+extern int console_video_formats;
+int console_video_cli(struct video_desc *env, const char *var, int fd);
+int console_video_config(struct video_desc **penv, const char *var, const char *val);
+void console_video_uninit(struct video_desc *env);
+void console_video_start(struct video_desc *env, struct ast_channel *owner);
+
+#ifdef HAVE_VIDEO_CONSOLE
+#define CONSOLE_VIDEO_CMDS                              \
+        "console {videodevice|videocodec|sendvideo"     \
+        "|video_size|bitrate|fps|qmin"                  \
+        "|keypad|keypad_mask|keypad_entry"              \
+        "|device"                                      \
+       "}"
+
+#else
+#define CONSOLE_VIDEO_CMDS                                     \
+               "console {device}"
+#endif
+
+/* end of file */