[asterisk-commits] rizzo: branch rizzo/video_v2 r82365 - in /team/rizzo/video_v2: ./ channels/ i...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Sep 13 19:16:34 CDT 2007
Author: rizzo
Date: Thu Sep 13 19:16:33 2007
New Revision: 82365
URL: http://svn.digium.com/view/asterisk?view=rev&rev=82365
Log:
compilable version of chan_oss with video support.
Functionality still not tested, nor autoconf issues to detect
the correct version of ffmpeg and the presence of the various
libs involved.
Added:
team/rizzo/video_v2/channels/console_video.c (with props)
Modified:
team/rizzo/video_v2/Makefile
team/rizzo/video_v2/channels/Makefile
team/rizzo/video_v2/channels/chan_oss.c
team/rizzo/video_v2/configure
team/rizzo/video_v2/configure.ac
team/rizzo/video_v2/include/asterisk/autoconfig.h.in
team/rizzo/video_v2/utils/Makefile
Modified: team/rizzo/video_v2/Makefile
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/Makefile?view=diff&rev=82365&r1=82364&r2=82365
==============================================================================
--- team/rizzo/video_v2/Makefile (original)
+++ team/rizzo/video_v2/Makefile Thu Sep 13 19:16:33 2007
@@ -283,6 +283,10 @@
HAVEDOT=no
endif
+# Add library for ffmpeg and SDL lib.
+ASTCFLAGS+=`sdl-config --cflags`
+SOLINK+=-lavcodec -lz -lm -g `sdl-config --libs`
+
all: _all
@echo " +--------- Asterisk Build Complete ---------+"
@echo " + Asterisk has successfully been built, and +"
Modified: team/rizzo/video_v2/channels/Makefile
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/channels/Makefile?view=diff&rev=82365&r1=82364&r2=82365
==============================================================================
--- team/rizzo/video_v2/channels/Makefile (original)
+++ team/rizzo/video_v2/channels/Makefile Thu Sep 13 19:16:33 2007
@@ -103,6 +103,8 @@
$(CMD_PREFIX) $(CXX) $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) -o $@ $< h323/libchanh323.a $(CHANH323LIB) -L$(PWLIBDIR)/lib $(PTLIB) -L$(OPENH323DIR)/lib $(H323LIB) -L/usr/lib -lcrypto -lssl -lexpat
endif
+chan_oss.o: console_video.c
+
chan_misdn.o: ASTCFLAGS+=-Imisdn
misdn_config.o: ASTCFLAGS+=-Imisdn
Modified: team/rizzo/video_v2/channels/chan_oss.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/channels/chan_oss.c?view=diff&rev=82365&r1=82364&r2=82365
==============================================================================
--- team/rizzo/video_v2/channels/chan_oss.c (original)
+++ team/rizzo/video_v2/channels/chan_oss.c Thu Sep 13 19:16:33 2007
@@ -286,6 +286,8 @@
static int oss_debug;
+#include "console_video.c"
+
/*!
* Each sound is made of 'datalen' samples of sound, repeated as needed to
* generate 'samplen' samples of data, then followed by 'silencelen' samples
@@ -382,7 +384,15 @@
char oss_read_buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
int readpos; /*!< read position above */
struct ast_frame read_f; /*!< returned by oss_read */
+
+ struct video_desc env; /* video support stuff */
};
+
+static struct video_desc *get_video_desc(struct ast_channel *c)
+{
+ struct chan_oss_pvt *o = c->tech_pvt;
+ return o ? &(o->env) : NULL;
+}
static struct chan_oss_pvt oss_default = {
.cursound = -1,
@@ -420,7 +430,7 @@
static const struct ast_channel_tech oss_tech = {
.type = "Console",
.description = tdesc,
- .capabilities = AST_FORMAT_SLINEAR,
+ .capabilities = AST_FORMAT_SLINEAR | CONSOLE_FORMAT_VIDEO,
.requester = oss_request,
.send_digit_begin = oss_digit_begin,
.send_digit_end = oss_digit_end,
@@ -430,6 +440,7 @@
.read = oss_read,
.call = oss_call,
.write = oss_write,
+ .write_video = console_write_video,
.indicate = oss_indicate,
.fixup = oss_fixup,
};
@@ -864,6 +875,7 @@
c->tech_pvt = NULL;
o->owner = NULL;
ast_verbose(" << Hangup on console >> \n");
+ console_video_uninit(&o->env);
ast_module_unref(ast_module_info->self);
if (o->hookstate) {
if (o->autoanswer || o->autohangup) {
@@ -920,10 +932,12 @@
int res;
struct chan_oss_pvt *o = c->tech_pvt;
struct ast_frame *f = &o->read_f;
+ struct ast_frame *fv = get_video_frames(get_video_desc(c));
/* XXX can be simplified returning &ast_null_frame */
/* prepare a NULL frame in case we don't have enough data to return */
bzero(f, sizeof(struct ast_frame));
+ AST_LIST_NEXT(f, frame_list) = fv; /* append video frames */
f->frametype = AST_FRAME_NULL;
f->src = oss_tech.type;
@@ -1028,6 +1042,10 @@
setformat(o, O_RDWR);
ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
c->nativeformats = AST_FORMAT_SLINEAR;
+ /* if the console makes the call, add video */
+ if (state == 5)
+ c->nativeformats |= CONSOLE_FORMAT_VIDEO;
+
c->readformat = AST_FORMAT_SLINEAR;
c->writeformat = AST_FORMAT_SLINEAR;
c->tech_pvt = o;
@@ -1051,6 +1069,7 @@
/* XXX what about the channel itself ? */
}
}
+ console_video_start(get_video_desc(c), o->owner); /* XXX cleanup */
return c;
}
@@ -1529,6 +1548,10 @@
M_F("mixer", store_mixer(o, v->value))
M_F("callerid", store_callerid(o, v->value))
M_F("boost", store_boost(o, v->value))
+ M_STR("videodevice", o->env.videodevice)
+ M_UINT("videowidth", o->env.w)
+ M_UINT("videoheight", o->env.h)
+ M_UINT("fps", o->env.fps)
M_END(/* */);
}
Added: team/rizzo/video_v2/channels/console_video.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/channels/console_video.c?view=auto&rev=82365
==============================================================================
--- team/rizzo/video_v2/channels/console_video.c (added)
+++ team/rizzo/video_v2/channels/console_video.c Thu Sep 13 19:16:33 2007
@@ -1,0 +1,959 @@
+/* header for console video */
+/*
+ * experimental support for video sessions. We use:
+ * - SDL for rendering both incoming and outgoing data,
+ * - ffmpeg for encoding and decoding;
+ * - video4linux for accessing the source.
+ */
+//#define DROP_PACKETS 5 // if set, simulate this percentage of lost video packets
+#define HAVE_V4L 1
+#define HAVE_SDL 1
+#define HAVE_FFMPEG 1
+
+#if !defined(HAVE_FFMPEG) || HAVE_FFMPEG == 0 || !defined(HAVE_SDL) || HAVE_SDL == 0
+/* stubs for everything */
+struct video_desc { /* empty */
+ int w;
+ int h;
+ int fps;
+ char videodevice[64];
+};
+#define CONSOLE_FORMAT_VIDEO 0
+#define console_write_video NULL
+static void console_video_start(struct video_desc *env,
+ struct ast_channel *owner)
+{
+}
+
+static void console_video_uninit(struct video_desc *env)
+{
+}
+
+static struct ast_frame *get_video_frames(struct video_desc *env)
+{
+ return NULL;
+}
+
+#else /* the body of the file */
+/*
+ * In order to decode video you need the following patch to the
+ * main Makefile:
+
+@@ -269,6 +273,11 @@
+ SOLINK=-shared -fpic -L/usr/local/ssl/lib
+ endif
+
++# GCC configuration flags for SDL library
++ASTCFLAGS+=`sdl-config --cflags`
++# Add library for ffmpeg and SDL lib.
++SOLINK+=-lavcodec -lz -lm -g `sdl-config --libs`
++
+ # This is used when generating the doxygen documentation
+ ifneq ($(DOT),:)
+ HAVEDOT=yes
+
+Then you need to add to sip.conf:
+ [general](+)
+ allow=h263p
+ videosupport=yes
+
+ */
+/*
+ * Examples for video encoding are at http://www.irisa.fr/texmex/people/dufouil/ffmpegdoxy/apiexample_8c-source.html
+ */
+
+#include <ffmpeg/avcodec.h>
+// #include <ffmpeg/swscale.h> /* requires a recent ffmpeg */
+#include <SDL/SDL.h>
+
+/* Structures for ffmpeg processing */
+/*
+ * Information for decoding incoming video stream.
+ * We need:
+ * - one descriptor per output stream (camera or file, plus encoding context)
+ * - one descriptor per incoming stream (network data, plus decoding context)
+ * - one descriptor per window (SDL).
+ */
+
+struct dbuf_t { /* buffers, dynamically allocated */
+ uint8_t *data;
+ int size;
+ int used;
+};
+
+struct video_out_desc {
+ /* webcam support.
+ * videodevice and geometry are read from the config file.
+ * At the right time we try to open it and allocate a buffer.
+ * If we are successful, webcam_bufsize > 0 and we can read.
+ */
+ int w; /* geometry */
+ int h;
+ int fd; /* file descriptor */
+ struct dbuf_t buf;
+ AVCodecContext *context;
+ AVCodec *codec;
+ AVFrame *frame;
+ int lasttxframe;
+ int fps;
+ struct dbuf_t decbuf;
+ struct timeval ts;
+ struct timeval msts;
+ int mtu;
+};
+
+struct video_in_desc {
+ AVCodecContext *context; /* information about the codec in the stream */
+ AVCodec *codec; /* reference to the codec */
+ AVFrame *frame; /* place to store the frame */
+ AVCodecParserContext *parser;
+ int completed; /* probably unnecessary */
+ struct dbuf_t buf;
+ int lastrxframe;
+ int discard;
+ struct timeval ts;
+ int received;
+};
+
+struct video_desc {
+ int w;
+ int h;
+ int fps;
+ char videodevice[64];
+
+ struct video_in_desc in;
+ struct video_out_desc out;
+
+ SDL_Surface *screen;
+ int initialized;
+ SDL_Overlay *bmp[2];
+
+ struct ast_frame *echo;
+
+};
+
+struct _cm { /* map ffmpeg codec types to asterisk formats */
+ uint32_t ast_format; /* 0 is a terminator */
+ enum CodecID codec;
+};
+
+/*! the list of video formats we support */
+#define CONSOLE_FORMAT_VIDEO AST_FORMAT_H263_PLUS
+
+static struct _cm video_formats[] = {
+ { AST_FORMAT_H263_PLUS, CODEC_ID_H263 },
+ { 0, 0 },
+};
+
+/*! \brief support to open a webcam using video4linux1 and read()
+ *
+ */
+#if !defined(HAVE_V4L) || HAVE_V4L != 1
+/* stubs */
+static int webcam_open(struct video_desc *env)
+{
+ return -1;
+}
+static int webcam_read(struct video_out_desc *v)
+{
+ return 0;
+}
+
+#else
+
+/* the real thing */
+#include <linux/videodev.h>
+
+static int webcam_open(struct video_desc *env)
+{
+ int i;
+ const char *device = env->videodevice;
+ struct video_window vw = { 0 }; /* camera attributes */
+ struct video_picture vp;
+ struct video_out_desc *v = &env->out;
+
+ /* copy config from parent */
+ v->w = env->w;
+ v->h = env->h;
+ v->fps = env->fps;
+
+ if (v->buf.data) /* buffer allocated means device already open */
+ return v->fd;
+
+ v->fd = open(device, O_RDONLY | O_NONBLOCK);
+ if (v->fd < 0) {
+ ast_log(LOG_WARNING, "error opening camera %s\n", device);
+ return v->fd;
+ }
+
+ i = fcntl(v->fd, F_GETFL);
+ if (-1 == fcntl(v->fd, F_SETFL, i | O_NONBLOCK)) {
+ ast_log(LOG_WARNING, "error F_SETFL for %s [%s]\n", device, strerror(errno));
+ }
+ /* set format */
+ vw.width = v->w;
+ vw.height = v->h;
+ vw.flags = v->fps << 16;
+ v->buf.size = (vw.width * vw.height * 3)/2; /* yuv411 */
+ if (ioctl(v->fd, VIDIOCSWIN, &vw) == -1) {
+ ast_log(LOG_WARNING, "error setting format for %s [%s]\n", device, strerror(errno));
+ goto error;
+ }
+ if (ioctl(v->fd, VIDIOCGPICT, &vp) == -1) {
+ ast_log(LOG_WARNING, "error reading picture info\n");
+ goto error;
+ }
+ ast_log(LOG_WARNING, "contrast %d bright %d colour %d hue %d whiteness %d palette %d\n",
+ vp.contrast, vp.brightness,
+ vp.colour, vp.hue,
+ vp.whiteness, vp.palette);
+ vp.palette = VIDEO_PALETTE_YUV420P;
+ if (ioctl(v->fd, VIDIOCSPICT, &vp) == -1) {
+ ast_log(LOG_WARNING, "error setting picture info\n");
+ goto error;
+ }
+ ast_log(LOG_WARNING, "videodev %s opened, size %dx%d %d\n", device, v->w, v->h, v->buf.size);
+ v->buf.data = ast_calloc(1, v->buf.size);
+ if (!v->buf.data) {
+ ast_log(LOG_WARNING, "error allocating buffer %d bytes\n", v->buf.size);
+ goto error;
+ }
+
+ v->buf.used = 0;
+ return v->fd;
+
+error:
+ if (v->fd >= 0)
+ close(v->fd);
+ v->fd = -1;
+ if (v->buf.data)
+ ast_free(v->buf.data);
+ v->buf.data = NULL;
+ return -1;
+}
+
+/*! \brief complete a buffer from the webcam */
+static int webcam_read(struct video_out_desc *v)
+{
+ if (v->buf.data == NULL) /* not initialized */
+ return 0;
+
+ for (;;) {
+ int r, l = v->buf.size - v->buf.used;
+ r = read(v->fd, v->buf.data + v->buf.used, l);
+ // ast_log(LOG_WARNING, "read %d of %d bytes from webcam\n", r, l);
+ if (r < 0) { /* read error */
+ return 0;
+ }
+ if (r == 0) /* no data */
+ return 0;
+ v->buf.used += r;
+ if (r == l) {
+ v->buf.used = 0; /* prepare for next frame */
+ return v->buf.size;
+ }
+ }
+}
+#endif /* HAVE_V4L */
+
+static void show_frame(struct video_desc *env, int out);
+
+static int webcam_encode(struct video_desc *env)
+{
+ int n_enc;
+
+ // struct timeval now = ast_tvnow();
+ // ast_log(LOG_WARNING, "video frame ready at %d.%06d\n", (int)now.tv_sec % 1000, (int)now.tv_usec);
+ show_frame(env, 1);
+ // XXX Codichiamo il frame
+ // XXX Vedi la alsa_read per il continuo
+ n_enc = avcodec_encode_video(env->out.context, env->out.decbuf.data, env->out.decbuf.size, env->out.frame);
+
+ return n_enc;
+}
+
+/* Helper function to process incoming video.
+ * For each incoming video call invoke ffmpeg_init() to intialize
+ * the decoding structure then incoming video frames are processed
+ * by write_video() which in turn calls pre_process_data(), to extract
+ * the bitstream; accumulates data into a buffer within video_desc. When
+ * a frame is complete (determined by the marker bit in the RTP header)
+ * call decode_video() to decoding and if it successful call show_frame()
+ * to display the frame.
+ */
+
+static struct video_desc *get_video_desc(struct ast_channel *c);
+
+/*! \brief map an asterisk format into an ffmpeg one */
+static enum CodecID map_video_format(uint32_t ast_format)
+{
+ struct _cm *i;
+
+ for (i = video_formats; i->ast_format != 0; i++)
+ if (ast_format & i->ast_format)
+ return i->codec;
+ return CODEC_ID_NONE;
+}
+
+static int video_in_uninit(struct video_in_desc *v)
+{
+ if (v->context) {
+ avcodec_close(v->context);
+ av_free(v->context);
+ }
+ if (v->frame)
+ av_free(v->frame);
+ if (v->buf.data)
+ free(v->buf.data);
+ bzero(v, sizeof(*v));
+ return -1; /* error, in case someone cares */
+}
+
+static int video_in_init(struct video_in_desc *v, uint32_t format)
+{
+ enum CodecID codec;
+
+ v->codec = NULL;
+ v->context = NULL;
+ v->frame = NULL;
+ v->parser = NULL;
+ v->buf.data = NULL;
+ v->completed = 0;
+ v->lastrxframe = -1;
+
+ v->ts = ast_tvnow();
+ codec = map_video_format(format);
+ ast_log(LOG_WARNING, "init for format 0x%x gives %d\n", format, codec);
+
+ v->codec = avcodec_find_decoder(codec);
+ if (!v->codec) {
+ ast_log(LOG_WARNING, "Unable to find the decoder for format %d\n", codec);
+ return video_in_uninit(v);
+ }
+ /*
+ * Initialize the codec context.
+ */
+ v->context = avcodec_alloc_context();
+ if (avcodec_open(v->context, v->codec) < 0) {
+ ast_log(LOG_WARNING, "Unable to open the codec context\n");
+ return video_in_uninit(v);
+ }
+
+ v->parser = av_parser_init(codec);
+ if (!v->parser) {
+ ast_log(LOG_WARNING, "Unable to initialize the decoder parser\n");
+ return video_in_uninit(v);
+ }
+
+ v->frame = avcodec_alloc_frame();
+ if (!v->frame) {
+ ast_log(LOG_WARNING, "Unable to allocate the decoding video frame\n");
+ return video_in_uninit(v);
+ }
+ return 0; /* ok */
+}
+
+static int video_out_uninit(struct video_out_desc *v)
+{
+ if (v->context) {
+ avcodec_close(v->context);
+ av_free(v->context);
+ }
+
+ if (v->frame)
+ av_free(v->frame);
+
+ if (v->buf.data)
+ free(v->buf.data);
+
+ if(v->fd >= 0)
+ close(v->fd);
+
+ if(v->decbuf.data)
+ free(v->decbuf.data);
+
+ v->fd = -1;
+
+ return -1;
+}
+
+static int video_out_init(struct video_out_desc *v, uint32_t format)
+{
+ int codec;
+ int size;
+
+ v->context = NULL;
+ v->codec = NULL;
+ v->frame = NULL;
+ v->lasttxframe = -1;
+ v->decbuf.data = NULL;
+
+ ast_log(LOG_WARNING, "video_out_init start 0x%x", format);
+ codec = map_video_format(format);
+ v->codec = avcodec_find_encoder(codec);
+ if (!v->codec) {
+ ast_log(LOG_WARNING, "Unable to find the encoder for format %d\n", codec);
+ return video_out_uninit(v);
+ }
+
+ v->context = avcodec_alloc_context();
+ v->context->pix_fmt = PIX_FMT_YUV420P;
+ v->context->width = v->w;
+ v->context->height = v->h;
+ v->context->rtp_mode = 1;
+ v->context->rtp_payload_size = v->mtu / 2; // mtu/2
+ v->context->flags|=CODEC_FLAG_H263P_UMV;
+ v->context->flags|=CODEC_FLAG_AC_PRED;
+ v->context->flags|=CODEC_FLAG_H263P_SLICE_STRUCT;
+ //v->context->bit_rate = 20000;
+ //v->context->gop_size = (int) v->fps*5; // emit I frame every 5 seconds
+
+ fprintf(stderr, "w: %d...h: %d...fps: %d...", v->w, v->h, v->fps);
+ v->context->time_base = (AVRational){1, v->fps};
+ if (avcodec_open(v->context, v->codec) < 0) {
+ ast_log(LOG_WARNING, "Unable to initialize the encoder parser\n");
+ av_free(v->context);
+ v->context = NULL;
+ return video_out_uninit(v);
+ }
+ fprintf(stderr, "2...");
+
+ v->frame = avcodec_alloc_frame();
+ if (!v->frame) {
+ ast_log(LOG_WARNING, "Unable to allocate the encoding video frame\n");
+ return video_out_uninit(v);
+ }
+ fprintf(stderr, "3...\n");
+
+ if(!v->buf.data) {
+ ast_log(LOG_WARNING, "Unable to set frame buffer\n");
+ return video_out_uninit(v);
+ }
+
+ size = v->w*v->h;
+ v->frame->data[0] = v->buf.data;
+ v->frame->data[1] = v->frame->data[0] + size;
+ v->frame->data[2] = v->frame->data[1] + size/4;
+ v->frame->linesize[0] = v->context->width;
+ v->frame->linesize[1] = v->context->width/2;
+ v->frame->linesize[2] = v->context->width/2;
+
+ v->decbuf.data = ast_calloc(1, v->buf.size);
+ v->decbuf.size = v->buf.size;
+ v->decbuf.used = 0;
+
+ v->msts = ast_tvnow();
+
+ v->mtu = 1400;
+ ast_log(LOG_VERBOSE, "video_out_init done");
+
+ return 0;
+}
+
+/*
+ * It initializes the video_desc struct which contains all the structures
+ * needed by ffmpeg and SDL libraries.
+ * - Registering of all codecs supported by the ffmpeg.
+ * - Searching for H.263+ decoder (H.263 decoder can decode H.263+ stream).
+ * - Allocation and initialization of codec context.
+ * - Initialization of codec parser (it should be used
+ * to reconstruct the entire bitstream from a fragmented stream)
+ * - Allocation of a new frame
+ * - Initializzation of the SDL environment to support the video
+ */
+static void ffmpeg_init(struct video_desc *env, uint32_t format)
+{
+ env->screen = NULL;
+ env->initialized = 0;
+ env->bmp[0] = env->bmp[1] = NULL;
+
+ // SDL specific
+ if(SDL_Init(SDL_INIT_VIDEO)) {
+ fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
+ return;
+ }
+
+ if (video_in_init(&env->in, format))
+ return;
+
+ env->initialized = 1;
+}
+
+/*
+ * Freeing all memory used and uninitialize
+ * the ffmpeg and SDL environments.
+ */
+static void console_video_uninit(struct video_desc *env)
+{
+ struct ast_frame *f;
+ int i = 0;
+
+ while ( (f = env->echo) != NULL) {
+ env->echo = AST_LIST_NEXT(f, frame_list);
+ ast_frfree(f);
+ i++;
+ }
+ ast_log(LOG_WARNING, "ffmpeg_uninit drop %d frames\n", i);
+ video_in_uninit(&env->in);
+ video_out_uninit(&env->out);
+ if (env->bmp[0])
+ SDL_FreeYUVOverlay(env->bmp[0]);
+ if (env->bmp[1])
+ SDL_FreeYUVOverlay(env->bmp[1]);
+ SDL_Quit();
+
+ /*if (env->out.buf.data) {
+ free(env->out.buf.data);
+ env->out.buf.data = NULL;
+ if (env->out.fd >= 0)
+ close(env->out.fd);
+ }*/
+ { /* clear the struct but restore some fields */
+ struct video_desc x = *env; /* make a copy */
+ fprintf(stderr, "vd: %s\n", x.videodevice);
+ bzero(env, sizeof(struct video_desc));
+ /* restore fields... */
+ bcopy(x.videodevice, env->videodevice, sizeof(env->videodevice));
+ env->w = x.w;
+ env->h = x.h;
+ env->fps = x.fps;
+ }
+}
+
+#define MAKE_MASK(bits) ( (1<<(bits)) -1 )
+
+/*
+ * Get the P flag from the H.263+ header from the RTP payload (see RFC 2429).
+ */
+static inline unsigned int rfc2429_get_P(const uint8_t *header){
+ return (header[0]>>2) & 0x1;
+}
+
+/*
+ * Get the PLEN variable from the H.263+ header from the RTP payload (see RFC 2429).
+ */
+static inline unsigned int rfc2429_get_PLEN(const uint8_t *header){
+ unsigned short *p=(unsigned short*)header;
+ return (ntohs(p[0])>>3) & MAKE_MASK(6);
+}
+
+/*! \brief extract the bitstreem from the RTP payload.
+ * This is format dependent.
+ * For h261, the format is defined in RFC 4587
+ * and basically has a fixed 4-byte header as follows:
+ * 3 bits SBIT start bit, how many msbits to ignore in first byte
+ * 3 bits EBIT end bit, how many lsbits to ignore in last byte
+ * 1 bit I 1 if frame only contain INTRA blocks
+ * 1 bit V 0 if motion vector not used, 1 if may be used
+ * 4 bits GOBN gob number at start of packet (0 for gob header)
+ * 5 bits MBAP macroblock address predictor
+ * 5 bits QUANT quantizer value
+ * 5 bits HMVD horiz motion vector
+ * 5 bits VMVD vert. motion vector
+ *
+ * For h263, the format is defined in RFC 2429
+ * and basically has a fixed 2-byte header as follows:
+ * 5 bits RR reserved, shall be 0
+ * 1 bit P indicate a start/end condition,
+ * in which case the payload should be prepended
+ * by two zero-valued bytes.
+ * 1 bit V there is an additional VRC header after this header
+ * 6 bits PLEN length in bytes of extra picture header
+ * 3 bits PEBIT how many bits to be ignored in the last byte
+ *
+ * XXX the code below is not complete.
+ */
+static uint8_t *pre_process_data(uint8_t *data, int *len)
+{
+ int PLEN;
+ int P;
+
+ if(data == NULL)
+ return NULL;
+ if(*len < 2)
+ return NULL;
+
+ PLEN = rfc2429_get_PLEN(data);
+ P = rfc2429_get_P(data);
+
+ if(PLEN > 0) {
+ data += PLEN;
+ (*len) -= PLEN;
+ }
+ if(P)
+ data[0] = data[1] = 0;
+ else {
+ data += 2;
+ (*len) -= 2;
+ }
+
+ return data;
+}
+
+/*
+ * It decodes a valid H.263 frame.
+ * The av_parser_parse should merge a randomly choped up stream into proper frames.
+ * After that, if we have a valid frame, we decode it until the entire frame is processed.
+ */
+static int decode_video(struct video_in_desc *v)
+{
+ uint8_t *src = v->buf.data;
+ int srclen = v->buf.used;
+
+ if (!srclen)
+ return 0;
+ while (srclen) {
+ uint8_t *data;
+ int datalen;
+ int ret = av_parser_parse(v->parser, v->context, &data, &datalen, src, srclen, 0, 0);
+ if (datalen) {
+ ret = avcodec_decode_video(v->context, v->frame, &(v->completed), data, datalen);
+ if(ret < 0) {
+ ast_log(LOG_NOTICE, "Errore nella decodifica\n");
+ return 0;
+ }
+ src += ret;
+ srclen -= ret;
+ }
+ // ast_log(LOG_WARNING, "in %d ret %d/%d outlen %d complete %d\n", v->buf.used, srclen, ret, datalen, v->completed);
+ }
+ return 1;
+}
+
+/*
+ * It displays the decoded video frame using the SDL library.
+ * - Set the video mode to use the resolution specified by the codec context
+ * - Create a YUV Overlay to copy into it the decoded frame
+ * - After the decoded frame is copied into the overlay, we display it
+ * TODO: change the call img_convert(): it is deprecated.
+ * 'out' is set to display the outgoing stream
+ */
+static void show_frame(struct video_desc *env, int out)
+{
+ AVPicture pict;
+ SDL_Rect rect;
+ AVCodecContext *c = env->in.context; /* shorthand */
+ int w = env->out.w ? env->out.w : c->width; /* pick geometry between webcam and default */
+ int h = env->out.h ? env->out.h : c->height; /* pick geometry between webcam and default */
+ SDL_Overlay *bmp;
+
+ if (!env->initialized)
+ return;
+ if(env->screen == NULL) {
+ env->screen = SDL_SetVideoMode(2*w, h, 0, 0);
+ if(!env->screen) {
+ ast_log(LOG_ERROR, "SDL: could not set video mode - exiting\n");
+ return;
+ }
+ SDL_WM_SetCaption("Asterisk console Video Output", NULL);
+ }
+
+ if(!env->bmp[0])
+ env->bmp[0] = SDL_CreateYUVOverlay(w, h, SDL_YV12_OVERLAY, env->screen);
+ if(!env->bmp[1])
+ env->bmp[1] = SDL_CreateYUVOverlay(w, h, SDL_YV12_OVERLAY, env->screen);
+
+ bmp = env->bmp[out];
+ SDL_LockYUVOverlay(bmp);
+ pict.data[0] = bmp->pixels[0];
+ pict.data[1] = bmp->pixels[2];
+ pict.data[2] = bmp->pixels[1];
+ pict.linesize[0] = bmp->pitches[0];
+ pict.linesize[1] = bmp->pitches[2];
+ pict.linesize[2] = bmp->pitches[1];
+
+ if (out) { /* raw stream from camera */
+ int l4 = w*h/4; /* U or v frame */
+ bcopy(env->out.buf.data, bmp->pixels[0], 4*l4);
+ bcopy(env->out.buf.data + 4*l4, bmp->pixels[2], l4);
+ bcopy(env->out.buf.data + 5*l4, bmp->pixels[1], l4);
+ } else { /* decode */
+#if 1 /* XXX img_convert is deprecated */
+ img_convert(&pict, PIX_FMT_YUV420P, (AVPicture *)env->in.frame, c->pix_fmt, c->width, c->height);
+#else /* XXX replacement */
+ struct SwsContext *convert_ctx;
+ AVPicture *pict_in = (AVPicture *)env->in.frame;
+
+ convert_ctx = sws_getContext(c->width, c->height, c->pix_fmt /* input format */,
+ w, h, PIX_FMT_YUV420P /* output format ? */,
+ SWS_BICUBIC, NULL, NULL, NULL);
+ if (convert_ctx == NULL) {
+ ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed");
+ return;
+ }
+
+ sws_scale(convert_ctx,
+ pict_in->data, pict_in->linesize,
+ w, h, /* src slice */
+ pict.data, pict.linesize);
+
+ sws_freeContext(convert_ctx);
+
+#endif /* XXX replacement */
+ }
+ SDL_UnlockYUVOverlay(bmp);
+ rect.x = w*out;
+ rect.y = 0;
+ rect.w = w;
+ rect.h = h;
+ SDL_DisplayYUVOverlay(bmp, &rect);
+}
+
+/*
+ * This function is called (by asterisk) for each video packet that needs to be processed.
+ * We need to reconstruct the entire video frame before we can decode it.
+ * After a video packet is received we have to:
+ * - extract the bitstream with pre_process_data()
+ * - append the bitstream to a buffer
+ * - 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)
+{
+ uint8_t *data;
+ int len;
+ struct video_desc *env = get_video_desc(chan);
+ struct timeval now = ast_tvnow();
+ int i;
+
+ if(!env->initialized)
+ ffmpeg_init(env, f->subclass);
+ if(!env->initialized)
+ return -1; /* error */
+
+ if (0) { /* echo frames back to the sender */
+ struct ast_frame *f1, **fp;
+ f1 = ast_frdup(f);
+ for (fp = &env->echo; (*fp) != NULL ; fp = &AST_LIST_NEXT((*fp), frame_list) )
+ ;
+ *fp = f1;
+ }
+
+ i = ast_tvdiff_ms(now, env->in.ts);
+ if (i > 1000) {
+ //ast_log(LOG_WARNING, "received %d video frames in %d ms\n", env->in.received, i);
+ env->in.received = 0;
+ env->in.ts = now;
+ }
+ env->in.received++;
+#if defined(DROP_PACKETS) && DROP_PACKETS > 0
+ /*
+ * Fragment of code to simulate lost/delayed packets
+ */
+ if((random() % 10000) <= 100*DROP_PACKETS) {
+ ast_log(LOG_NOTICE, "Packet lost [%d]\n", f->seqno);
+ return 0;
+ }
+#endif
+ /*
+ * If there is the discard flag, every packet must be discarded.
+ * When a marked packet arrive we can restart the decoding.
+ * XXX note that the RTP marker flag is sent as the LSB of the
+ * subclass. This is slightly annoying as it goes to overwrite
+ * the payload type entry.
+ */
+ if(env->in.discard) {
+ if(f->subclass & 0x01) {
+ free(env->in.buf.data);
+ env->in.buf.data = NULL;
+ env->in.buf.used = 0;
+ env->in.lastrxframe = f->seqno;
+ env->in.discard = 0;
+ }
+ return 0;
+ }
+
+ /*
+ * Only ordered fragment will be accepted.
+ * We can handle the circular seqno with the following operation
+ * (seqno is a 16 bits number)
+ */
+ if((env->in.lastrxframe+1)%0x10000 != f->seqno && env->in.lastrxframe != -1) {
+ env->in.discard = 1;
+ return 0;
+ }
+
+ len = f->datalen;
+ data = pre_process_data(f->data, &len);
+
+ /* allocate buffer as we see fit. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE
+ * and a 0 as a buffer terminator to prevent trouble.
+ */
+ if(env->in.buf.data == NULL) {
+ env->in.buf.size = len + FF_INPUT_BUFFER_PADDING_SIZE;
+ env->in.buf.used = 0;
+ env->in.buf.data = malloc(len);
+ } else if (env->in.buf.used + len + FF_INPUT_BUFFER_PADDING_SIZE> env->in.buf.size) {
+ env->in.buf.size = env->in.buf.used + len + FF_INPUT_BUFFER_PADDING_SIZE;
+ env->in.buf.data = realloc(env->in.buf.data, env->in.buf.size);
+ }
+ memcpy(env->in.buf.data+env->in.buf.used, data, len);
+ env->in.buf.used += len;
+ env->in.buf.data[env->in.buf.used] = '\0';
+ if(f->subclass & 0x01) // RTP Marker
+ if(decode_video(&env->in)) {
+ show_frame(env, 0);
+ env->in.completed = 0;
+ env->in.buf.used = 0;
+ }
+ env->in.lastrxframe = f->seqno;
+
+ return 0;
+}
+
+
+/*
+ * Find the next PSC (Picture Start Code) of the frame
+ */
+static uint8_t *get_psc(uint8_t *begin, uint8_t *end, int packet_size)
+{
+ int i;
+ uint8_t *ret=NULL;
+ uint8_t *p;
+ if (begin==end) return NULL;
+ for(i=1,p=begin+1;p<end && i<packet_size;++i,++p){
+ if (p[-1]==0 && p[0]==0){
+ ret=p-1;
+ }
+ p++;/* to skip possible 0 after the PSC that would make a double detection */
+ }
+ return ret;
+}
+
+#ifndef MIN
+#define MIN(a, b) (a) < (b) ? (a) : (b)
+#endif
+
+/*
+ * Create RTP/H.263 fragmets to avoid IP fragmentation
+ */
+static struct ast_frame *create_video_segment(struct video_out_desc *out, uint8_t *start, uint8_t *end, int last_packet)
+{
+ int len = end-start;
+ int size = MIN(len, out->mtu);
+ uint8_t *data;
+ struct ast_frame *f, *fp = NULL, *ftop = NULL;
+ int header = 0; // the first frag contains the PSC
+
+ do {
+ f = ast_malloc(sizeof(*f));
+ if(fp)
+ fp->frame_list.next = f;
+ else
+ ftop = f;
+ fp = f;
+
+ data = ast_malloc(size+header);
+ memcpy(data+header, start, size);
+
+ if(header == 2)
+ data[0] = data[1] = 0; // P == 0
+ else {
+ data[0] |= 0x04; // P == 1
+ header = 2;
+ }
+
+ f->has_timing_info = 1;
+ f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts);
+ f->frametype = AST_FRAME_VIDEO;
+ f->subclass = CONSOLE_FORMAT_VIDEO;
+ f->samples = 0;
+ f->offset = 0;
+ f->src = "Console";
+ // This flags teels asterisk that the data and
+ // the header are dinamically allocated
+ f->mallocd = AST_MALLOCD_DATA | AST_MALLOCD_HDR;
+ f->delivery.tv_sec = 0;
+ f->delivery.tv_usec = 0;
+ f->seqno = ++(out->lasttxframe);
+ f->datalen = size+header;
+ f->data = data;
+ f->frame_list.next = NULL;
+
+ start += size;
+ len = end-start;
+ size = MIN(len, out->mtu);
+ } while(len > 0);
+
+ f->subclass |= last_packet; // RTP Marker
+
+ return ftop;
+}
+
+/*
+ * Search for PSCs and create ast_frame list of RTP packets
+ */
+static struct ast_frame *split_frame(struct video_out_desc *out, int len)
+{
+ uint8_t *lastpsc = out->decbuf.data;
+ uint8_t *end = out->decbuf.data+len;
+ uint8_t *psc, *pos;
+ struct ast_frame *f, *fp = NULL, *ftop = NULL;
+
+ while(1) {
+ psc = get_psc(lastpsc+2, end, out->mtu);
+
+ pos = (psc == NULL) ? end : psc;
+
+ f = create_video_segment(out, lastpsc, pos, 0);
+ lastpsc = psc;
+
+ if(fp)
+ fp->frame_list.next = f;
+ else
+ ftop = f;
+
+ if(psc == NULL)
+ break;
+
+ fp = f;
+ }
+
+ return ftop;
+}
+
+static struct ast_frame *get_video_frames(struct video_desc *env)
+{
+ int webcam_buflen;
+ struct timeval tvnow;
+ int period, fdiff;
+
+ if (!webcam_read(&env->out))
+ return NULL;
+
+ // XXX - questa porzione di codice limita la generazione dei
+ // frame al framerate specificato nel file di configurazione
+ // I frame della webcam che non rientrano nel framerate
+ // vengono scartati.
+ tvnow = ast_tvnow();
+ period = 1000/env->out.fps;
+ fdiff = ast_tvdiff_ms(tvnow, env->out.msts);
+ if (fdiff < period)
+ return NULL;
+
+ env->out.msts.tv_sec = tvnow.tv_sec;
+ env->out.msts.tv_usec = tvnow.tv_usec;
+ /* get frame and put them in the queue */
+ webcam_buflen = webcam_encode(env);
+ return split_frame(&(env->out), webcam_buflen);
+}
+
+static void console_video_start(struct video_desc *env,
+ struct ast_channel *owner)
+{
+ avcodec_init();
+ /*
+ * Register all codecs supported by the ffmpeg library.
+ * Doing it once is enough.
+ */
+ avcodec_register_all();
+
+ webcam_open(env);
+ if (env->out.buf.data && owner) { /* drive webcam */
+ owner->fds[1] = env->out.fd;
+ video_out_init(&env->out, CONSOLE_FORMAT_VIDEO);
+ }
+ ast_log(LOG_VERBOSE, "console_video_start owner %p", owner);
+ env->out.ts = ast_tvnow();
+}
+#endif /* video support */
Propchange: team/rizzo/video_v2/channels/console_video.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/rizzo/video_v2/channels/console_video.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/rizzo/video_v2/channels/console_video.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/rizzo/video_v2/configure
URL: http://svn.digium.com/view/asterisk/team/rizzo/video_v2/configure?view=diff&rev=82365&r1=82364&r2=82365
==============================================================================
--- team/rizzo/video_v2/configure (original)
+++ team/rizzo/video_v2/configure Thu Sep 13 19:16:33 2007
@@ -1,10 +1,9 @@
#! /bin/sh
-# From configure.ac Revision: 79972 .
+# From configure.ac Revision: 81873 .
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61.
+# Generated by GNU Autoconf 2.59.
#
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
#
@@ -13,26 +12,73 @@
## M4sh Initialization. ##
## --------------------- ##
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
+# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
- setopt NO_GLOB_SUBST
-else
- case `(set -o) 2>/dev/null` in
- *posix*) set -o posix ;;
-esac
-
-fi
-
-
-
-
-# PATH needs CR
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
@@ -53,466 +99,124 @@
rm -f conf$$.sh
fi
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
- as_unset=unset
-else
- as_unset=false
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-as_nl='
-'
-IFS=" "" $as_nl"
-
-# Find who we are. Look in the path if we contain no directory separator.
-case $0 in
- *[\\/]* ) as_myself=$0 ;;
- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
done
-IFS=$as_save_IFS
-
- ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
- as_myself=$0
-fi
-if test ! -f "$as_myself"; then
- echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
- { (exit 1); exit 1; }
-fi
-
-# Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
- LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
- LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
- LC_TELEPHONE LC_TIME
-do
- if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
- eval $as_var=C; export $as_var
- else
- ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1 &&
- test "X`expr 00001 : '.*\(...\)'`" = X001; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
- as_basename=basename
-else
- as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
- X"$0" : 'X\(//\)$' \| \
- X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-echo X/"$0" |
- sed '/^.*\/\([^/][^/]*\)\/*$/{
- s//\1/
- q
- }
- /^X\/\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\/\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
-
-# CDPATH.
-$as_unset CDPATH
-
-
-if test "x$CONFIG_SHELL" = x; then
- if (eval ":") 2>/dev/null; then
- as_have_required=yes
-else
- as_have_required=no
-fi
-
- if test $as_have_required = yes && (eval ":
-(as_func_return () {
- (exit \$1)
-}
-as_func_success () {
- as_func_return 0
-}
-as_func_failure () {
- as_func_return 1
-}
-as_func_ret_success () {
- return 0
-}
-as_func_ret_failure () {
- return 1
-}
-
-exitcode=0
-if as_func_success; then
- :
-else
- exitcode=1
- echo as_func_success failed.
-fi
-
-if as_func_failure; then
- exitcode=1
- echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
- :
-else
- exitcode=1
- echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
- exitcode=1
- echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
- :
-else
- exitcode=1
- echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0) || { (exit 1); exit 1; }
-
-(
- as_lineno_1=\$LINENO
- as_lineno_2=\$LINENO
- test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
- test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
-") 2> /dev/null; then
- :
-else
- as_candidate_shells=
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- case $as_dir in
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
/*)
- for as_base in sh bash ksh sh5; do
- as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
- done;;
[... 47155 lines stripped ...]
More information about the asterisk-commits
mailing list