diff options
author | Tilghman Lesher <tilghman@meg.abyt.es> | 2010-09-02 05:02:54 +0000 |
---|---|---|
committer | Tilghman Lesher <tilghman@meg.abyt.es> | 2010-09-02 05:02:54 +0000 |
commit | 5eae9f44f74f9869e46e416a2d5d092834043483 (patch) | |
tree | afc6eb9b08ef4ba9f7e0ad1bb4a59b13d5269d90 /channels | |
parent | c28c620936e31ec5a63147ae20d82d621541ae90 (diff) |
Merged revisions 284597 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
................
r284597 | tilghman | 2010-09-02 00:00:34 -0500 (Thu, 02 Sep 2010) | 29 lines
Merged revisions 284593,284595 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2
................
r284593 | tilghman | 2010-09-01 17:59:50 -0500 (Wed, 01 Sep 2010) | 18 lines
Merged revisions 284478 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r284478 | tilghman | 2010-09-01 13:49:11 -0500 (Wed, 01 Sep 2010) | 11 lines
Ensure that all areas that previously used select(2) now use poll(2), with implementations that need poll(2) implemented with select(2) safe against 1024-bit overflows.
This is a followup to the fix for the pthread timer in 1.6.2 and beyond, fixing
a potential crash bug in all supported releases.
(closes issue #17678)
Reported by: russell
Branch: https://origsvn.digium.com/svn/asterisk/team/tilghman/ast_select
Review: https://reviewboard.asterisk.org/r/824/
........
................
r284595 | tilghman | 2010-09-01 22:57:43 -0500 (Wed, 01 Sep 2010) | 2 lines
Failed to rerun bootstrap.sh after last commit
................
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@284598 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_misdn.c | 40 | ||||
-rw-r--r-- | channels/chan_phone.c | 80 | ||||
-rw-r--r-- | channels/chan_usbradio.c | 141 | ||||
-rw-r--r-- | channels/console_video.c | 239 |
4 files changed, 249 insertions, 251 deletions
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 8b31ed23a..27d727a62 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -7160,15 +7160,14 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame static struct ast_frame *misdn_read(struct ast_channel *ast) { struct chan_list *tmp; - fd_set rrfs; - struct timeval tv = { 0, 20000 }; int len, t; + struct pollfd pfd = { .fd = -1, .events = POLLIN }; if (!ast) { chan_misdn_log(1, 0, "misdn_read called without ast\n"); return NULL; } - if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) { + if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) { chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n"); return NULL; } @@ -7178,21 +7177,18 @@ static struct ast_frame *misdn_read(struct ast_channel *ast) return NULL; } - FD_ZERO(&rrfs); - FD_SET(tmp->pipe[0], &rrfs); - - t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv); - if (!t) { - chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n"); - len = 160; - } + pfd.fd = tmp->pipe[0]; + t = ast_poll(&pfd, 1, 20); if (t < 0) { - chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n", strerror(errno)); + chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno)); return NULL; } - if (FD_ISSET(tmp->pipe[0], &rrfs)) { + if (!t) { + chan_misdn_log(3, tmp->bc->port, "poll() timed out\n"); + len = 160; + } else if (pfd.revents & POLLIN) { len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf)); if (len <= 0) { @@ -10456,25 +10452,21 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ast_queue_frame(ch->ast, &frame); } } else { - fd_set wrfs; - struct timeval tv = { 0, 0 }; + struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT }; int t; - FD_ZERO(&wrfs); - FD_SET(ch->pipe[1], &wrfs); + t = ast_poll(&pfd, 1, 0); - t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv); - if (!t) { - chan_misdn_log(9, bc->port, "Select Timed out\n"); + if (t < 0) { + chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno)); break; } - - if (t < 0) { - chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno)); + if (!t) { + chan_misdn_log(9, bc->port, "poll() timed out\n"); break; } - if (FD_ISSET(ch->pipe[1], &wrfs)) { + if (pfd.revents & POLLOUT) { chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len); if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) { chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno)); diff --git a/channels/chan_phone.c b/channels/chan_phone.c index 48da10fd6..531b95cb5 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -1017,12 +1017,12 @@ static void phone_check_exception(struct phone_pvt *i) static void *do_monitor(void *data) { - fd_set rfds, efds; - int n, res; + struct pollfd *fds = NULL; + int nfds = 0, inuse_fds = 0, res; struct phone_pvt *i; int tonepos = 0; /* The tone we're playing this round */ - struct timeval wait = {0,0}; + struct timeval tv = { 0, 0 }; int dotone; /* This thread monitors all the frame relay interfaces which are not yet in use (and thus do not have a separate thread) indefinitely */ @@ -1036,33 +1036,38 @@ static void *do_monitor(void *data) } /* Build the stuff we're going to select on, that is the socket of every phone_pvt that does not have an associated owner channel */ - n = -1; - FD_ZERO(&rfds); - FD_ZERO(&efds); i = iflist; dotone = 0; - while (i) { - if (FD_ISSET(i->fd, &rfds)) - ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev); + inuse_fds = 0; + for (i = iflist; i; i = i->next) { if (!i->owner) { /* This needs to be watched, as it lacks an owner */ - FD_SET(i->fd, &rfds); - FD_SET(i->fd, &efds); - if (i->fd > n) - n = i->fd; + if (inuse_fds == nfds) { + void *tmp = ast_realloc(fds, (nfds + 1) * sizeof(*fds)); + if (!tmp) { + /* Avoid leaking */ + continue; + } + fds = tmp; + nfds++; + } + fds[inuse_fds].fd = i->fd; + fds[inuse_fds].events = POLLIN | POLLERR; + fds[inuse_fds].revents = 0; + inuse_fds++; + if (i->dialtone && i->mode != MODE_SIGMA) { /* Remember we're going to have to come back and play more dialtones */ - if (ast_tvzero(wait)) { + if (ast_tvzero(tv)) { /* If we're due for a dialtone, play one */ - if (write(i->fd, DialTone + tonepos, 240) != 240) + if (write(i->fd, DialTone + tonepos, 240) != 240) { ast_log(LOG_WARNING, "Dial tone write error\n"); + } } dotone++; } } - - i = i->next; } /* Okay, now that we know what to do, release the interface lock */ ast_mutex_unlock(&iflock); @@ -1071,26 +1076,28 @@ static void *do_monitor(void *data) if (dotone && i && i->mode != MODE_SIGMA) { /* If we're ready to recycle the time, set it to 30 ms */ tonepos += 240; - if (tonepos >= sizeof(DialTone)) - tonepos = 0; - if (ast_tvzero(wait)) { - wait = ast_tv(30000, 0); + if (tonepos >= sizeof(DialTone)) { + tonepos = 0; } - res = ast_select(n + 1, &rfds, NULL, &efds, &wait); + if (ast_tvzero(tv)) { + tv = ast_tv(0, 30000); + } + res = ast_poll2(fds, inuse_fds, &tv); } else { - res = ast_select(n + 1, &rfds, NULL, &efds, NULL); - wait = ast_tv(0,0); + res = ast_poll(fds, inuse_fds, -1); + tv = ast_tv(0, 0); tonepos = 0; } /* Okay, select has finished. Let's see what happened. */ if (res < 0) { - ast_debug(1, "select return %d: %s\n", res, strerror(errno)); + ast_debug(1, "poll returned %d: %s\n", res, strerror(errno)); continue; } /* If there are no fd's changed, just continue, it's probably time to play some more dialtones */ - if (!res) + if (!res) { continue; + } /* Alright, lock the interface list again, and let's look and see what has happened */ if (ast_mutex_lock(&iflock)) { @@ -1098,15 +1105,27 @@ static void *do_monitor(void *data) continue; } - i = iflist; - for(; i; i=i->next) { - if (FD_ISSET(i->fd, &rfds)) { + for (i = iflist; i; i = i->next) { + int j; + /* Find the record */ + for (j = 0; j < inuse_fds; j++) { + if (fds[j].fd == i->fd) { + break; + } + } + + /* Not found? */ + if (j == inuse_fds) { + continue; + } + + if (fds[j].revents & POLLIN) { if (i->owner) { continue; } phone_mini_packet(i); } - if (FD_ISSET(i->fd, &efds)) { + if (fds[j].revents & POLLERR) { if (i->owner) { continue; } @@ -1116,7 +1135,6 @@ static void *do_monitor(void *data) ast_mutex_unlock(&iflock); } return NULL; - } static int restart_monitor() diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c index b5867f5a4..82f591d08 100644 --- a/channels/chan_usbradio.c +++ b/channels/chan_usbradio.c @@ -1119,8 +1119,7 @@ static void *hidthread(void *arg) struct usb_device *usb_dev; struct usb_dev_handle *usb_handle; struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg; - struct timeval to; - fd_set rfds; + struct pollfd pfd = { .events = POLLIN }; usb_dev = hid_device_init(o->devstr); if (usb_dev == NULL) { @@ -1156,63 +1155,49 @@ static void *hidthread(void *arg) traceusb1(("hidthread: Starting normally on %s!!\n",o->name)); lastrx = 0; // popen - while(!o->stophid) - { - to.tv_sec = 0; - to.tv_usec = 50000; // maw sph + while (!o->stophid) { + pfd.fd = o->pttkick; + pfd.revents = 0; - FD_ZERO(&rfds); - FD_SET(o->pttkick[0],&rfds); - /* ast_select emulates linux behaviour in terms of timeout handling */ - res = ast_select(o->pttkick[0] + 1, &rfds, NULL, NULL, &to); + res = ast_poll2(&pfd, 1, 50); if (res < 0) { - ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); + ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno)); usleep(10000); continue; } - if (FD_ISSET(o->pttkick[0],&rfds)) - { + if (pfd.revents & POLLIN) { { char c; - if (read(o->pttkick[0],&c,1) < 0) { + if (read(o->pttkick[0], &c, 1) < 0) { ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno)); } } - if(o->wanteeprom) - { + if (o->wanteeprom) { ast_mutex_lock(&o->eepromlock); - if (o->eepromctl == 1) /* to read */ - { + if (o->eepromctl == 1) { /* to read */ /* if CS okay */ - if (!get_eeprom(usb_handle,o->eeprom)) - { - if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC) - { - ast_log(LOG_NOTICE,"UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n",o->name); - } - else - { + if (!get_eeprom(usb_handle, o->eeprom)) { + if (o->eeprom[EEPROM_MAGIC_ADDR] != EEPROM_MAGIC) { + ast_log(LOG_NOTICE, "UNSUCCESSFUL: EEPROM MAGIC NUMBER BAD on channel %s\n", o->name); + } else { o->rxmixerset = o->eeprom[EEPROM_RXMIXERSET]; - o->txmixaset = o->eeprom[EEPROM_TXMIXASET]; + o->txmixaset = o->eeprom[EEPROM_TXMIXASET]; o->txmixbset = o->eeprom[EEPROM_TXMIXBSET]; - memcpy(&o->rxvoiceadj,&o->eeprom[EEPROM_RXVOICEADJ],sizeof(float)); - memcpy(&o->rxctcssadj,&o->eeprom[EEPROM_RXCTCSSADJ],sizeof(float)); + memcpy(&o->rxvoiceadj, &o->eeprom[EEPROM_RXVOICEADJ], sizeof(float)); + memcpy(&o->rxctcssadj, &o->eeprom[EEPROM_RXCTCSSADJ], sizeof(float)); o->txctcssadj = o->eeprom[EEPROM_TXCTCSSADJ]; o->rxsquelchadj = o->eeprom[EEPROM_RXSQUELCHADJ]; ast_log(LOG_NOTICE,"EEPROM Loaded on channel %s\n",o->name); } - } - else - { - ast_log(LOG_NOTICE,"USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n",o->name); + } else { + ast_log(LOG_NOTICE, "USB Adapter has no EEPROM installed or Checksum BAD on channel %s\n", o->name); } hid_set_outputs(usb_handle,bufsave); - } - if (o->eepromctl == 2) /* to write */ - { + } + if (o->eepromctl == 2) { /* to write */ put_eeprom(usb_handle,o->eeprom); hid_set_outputs(usb_handle,bufsave); - ast_log(LOG_NOTICE,"USB Parameters written to EEPROM on %s\n",o->name); + ast_log(LOG_NOTICE, "USB Parameters written to EEPROM on %s\n", o->name); } o->eepromctl = 0; ast_mutex_unlock(&o->eepromlock); @@ -1220,38 +1205,43 @@ static void *hidthread(void *arg) buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; hid_get_inputs(usb_handle,buf); keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor); - if (keyed != o->rxhidsq) - { - if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed); + if (keyed != o->rxhidsq) { + if (o->debuglevel) { + printf("chan_usbradio() hidthread: update rxhidsq = %d\n", keyed); + } o->rxhidsq=keyed; } /* if change in tx state as controlled by xpmr */ - txtmp=o->pmrChan->txPttOut; - - if (o->lasttx != txtmp) - { - o->pmrChan->txPttHid=o->lasttx = txtmp; - if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp); - buf[o->hid_gpio_loc] = 0; - if (!o->invertptt) - { - if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt; + txtmp = o->pmrChan->txPttOut; + + if (o->lasttx != txtmp) { + o->pmrChan->txPttHid = o->lasttx = txtmp; + if (o->debuglevel) { + ast_debug(0, "hidthread: tx set to %d\n", txtmp); } - else - { - if (!txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt; + buf[o->hid_gpio_loc] = 0; + if (!o->invertptt) { + if (txtmp) { + buf[o->hid_gpio_loc] = o->hid_io_ptt; + } + } else { + if (!txtmp) { + buf[o->hid_gpio_loc] = o->hid_io_ptt; + } } buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; - memcpy(bufsave,buf,sizeof(buf)); - hid_set_outputs(usb_handle,buf); + memcpy(bufsave, buf, sizeof(buf)); + hid_set_outputs(usb_handle, buf); } time(&o->lasthidtime); } buf[o->hid_gpio_loc] = 0; - if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt; + if (o->invertptt) { + buf[o->hid_gpio_loc] = o->hid_io_ptt; + } buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl; - hid_set_outputs(usb_handle,buf); + hid_set_outputs(usb_handle, buf); pthread_exit(0); } @@ -1452,37 +1442,29 @@ static void *sound_thread(void *arg) */ read(o->sounddev, ign, sizeof(ign)); for (;;) { - fd_set rfds, wfds; - int maxfd, res; - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_SET(o->sndcmd[0], &rfds); - maxfd = o->sndcmd[0]; /* pipe from the main process */ - if (o->cursound > -1 && o->sounddev < 0) + struct pollfd pfd[2] = { { .fd = o->sndcmd[0], .events = POLLIN }, { .fd = o->sounddev } }; + int res; + + if (o->cursound > -1 && o->sounddev < 0) { setformat(o, O_RDWR); /* need the channel, try to reopen */ - else if (o->cursound == -1 && o->owner == NULL) - { + } else if (o->cursound == -1 && o->owner == NULL) { setformat(o, O_CLOSE); /* can close */ } if (o->sounddev > -1) { if (!o->owner) { /* no one owns the audio, so we must drain it */ - FD_SET(o->sounddev, &rfds); - maxfd = MAX(o->sounddev, maxfd); + pfd[1].events = POLLIN; } if (o->cursound > -1) { - FD_SET(o->sounddev, &wfds); - maxfd = MAX(o->sounddev, maxfd); + pfd[1].events |= POLLOUT; } } - /* ast_select emulates linux behaviour in terms of timeout handling */ - res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL); + res = ast_poll(pfd, o->sounddev > -1 ? 2 : 1, -1); if (res < 1) { - ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); + ast_log(LOG_WARNING, "poll failed: %s\n", strerror(errno)); sleep(1); continue; } - if (FD_ISSET(o->sndcmd[0], &rfds)) { + if (pfd[0].revents & POLLIN) { /* read which sound to play from the pipe */ int i, what = -1; @@ -1495,14 +1477,17 @@ static void *sound_thread(void *arg) break; } } - if (sounds[i].ind == -1) + if (sounds[i].ind == -1) { ast_log(LOG_WARNING, "invalid sound index: %d\n", what); + } } if (o->sounddev > -1) { - if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */ + if (pfd[1].revents & POLLIN) { /* read and ignore errors */ read(o->sounddev, ign, sizeof(ign)); - if (FD_ISSET(o->sounddev, &wfds)) + } + if (pfd[1].revents & POLLOUT) { send_sound(o); + } } } return NULL; /* Never reached */ diff --git a/channels/console_video.c b/channels/console_video.c index 88bf807d5..c26ac983f 100644 --- a/channels/console_video.c +++ b/channels/console_video.c @@ -234,34 +234,34 @@ struct video_out_desc { * and contain all configurtion info. */ struct video_desc { - char codec_name[64]; /* the codec we use */ + char codec_name[64]; /* the codec we use */ - int stayopen; /* set if gui starts manually */ - pthread_t vthread; /* video thread */ - ast_mutex_t dec_lock; /* sync decoder and video thread */ - int shutdown; /* set to shutdown vthread */ - struct ast_channel *owner; /* owner channel */ + int stayopen; /* set if gui starts manually */ + pthread_t vthread; /* video thread */ + ast_mutex_t dec_lock; /* sync decoder and video thread */ + int shutdown; /* set to shutdown vthread */ + struct ast_channel *owner; /* owner channel */ - struct fbuf_t enc_in; /* encoder input buffer, allocated in video_out_init() */ + struct fbuf_t enc_in; /* encoder input buffer, allocated in video_out_init() */ - char keypad_file[256]; /* image for the keypad */ - char keypad_font[256]; /* font for the keypad */ + char keypad_file[256]; /* image for the keypad */ + char keypad_font[256]; /* font for the keypad */ - char sdl_videodriver[256]; + char sdl_videodriver[256]; - struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */ - struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */ + struct fbuf_t rem_dpy; /* display remote video, no buffer (it is in win[WIN_REMOTE].bmp) */ + struct fbuf_t loc_dpy; /* display local source, no buffer (managed by SDL in bmp[1]) */ /* geometry of the thumbnails for all video sources. */ - struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */ + struct fbuf_t src_dpy[MAX_VIDEO_SOURCES]; /* no buffer allocated here */ - int frame_freeze; /* flag to freeze the incoming frame */ + int frame_freeze; /* flag to freeze the incoming frame */ /* local information for grabbers, codecs, gui */ - struct gui_info *gui; - struct video_dec_desc *in; /* remote video descriptor */ - struct video_out_desc out; /* local video descriptor */ + struct gui_info *gui; + struct video_dec_desc *in; /* remote video descriptor */ + struct video_out_desc out; /* local video descriptor */ }; static AVPicture *fill_pict(struct fbuf_t *b, AVPicture *p); @@ -387,8 +387,9 @@ static struct fbuf_t *grabber_read(struct video_device *dev, int fps) */ static void grabber_move(struct video_device *dev, int dx, int dy) { - if (dev->grabber && dev->grabber->move) - dev->grabber->move(dev->grabber_data, dx, dy); + if (dev->grabber && dev->grabber->move) { + dev->grabber->move(dev->grabber_data, dx, dy); + } } /* @@ -508,33 +509,32 @@ static int video_out_init(struct video_desc *env) /* now setup the parameters for the encoder. * XXX should be codec-specific */ - { - AVCodecContext *enc_ctx = avcodec_alloc_context(); - v->enc_ctx = enc_ctx; - enc_ctx->pix_fmt = enc_in->pix_fmt; - enc_ctx->width = enc_in->w; - enc_ctx->height = enc_in->h; - /* XXX rtp_callback ? - * rtp_mode so ffmpeg inserts as many start codes as possible. - */ - enc_ctx->rtp_mode = 1; - enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2 - enc_ctx->bit_rate = v->bitrate; - enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2; - enc_ctx->qmin = v->qmin; /* should be configured */ - enc_ctx->time_base = (AVRational){1, v->fps}; - enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds - - v->enc->enc_init(v->enc_ctx); - - if (avcodec_open(enc_ctx, v->codec) < 0) { - ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n", - codec); - av_free(enc_ctx); - v->enc_ctx = NULL; - return video_out_uninit(env); + { + AVCodecContext *enc_ctx = avcodec_alloc_context(); + v->enc_ctx = enc_ctx; + enc_ctx->pix_fmt = enc_in->pix_fmt; + enc_ctx->width = enc_in->w; + enc_ctx->height = enc_in->h; + /* XXX rtp_callback ? + * rtp_mode so ffmpeg inserts as many start codes as possible. + */ + enc_ctx->rtp_mode = 1; + enc_ctx->rtp_payload_size = v->mtu / 2; // mtu/2 + enc_ctx->bit_rate = v->bitrate; + enc_ctx->bit_rate_tolerance = enc_ctx->bit_rate/2; + enc_ctx->qmin = v->qmin; /* should be configured */ + enc_ctx->time_base = (AVRational){1, v->fps}; + enc_ctx->gop_size = v->fps*5; // emit I frame every 5 seconds + + v->enc->enc_init(v->enc_ctx); + + if (avcodec_open(enc_ctx, v->codec) < 0) { + ast_log(LOG_WARNING, "Unable to initialize the encoder %d\n", codec); + av_free(enc_ctx); + v->enc_ctx = NULL; + return video_out_uninit(env); + } } - } /* * Allocate enough for the encoded bitstream. As we are compressing, * we hope that the output is never larger than the input size. @@ -637,9 +637,9 @@ static void my_scale(struct fbuf_t *in, AVPicture *p_in, p_in = fill_pict(in, &my_p_in); if (p_out == NULL) p_out = fill_pict(out, &my_p_out); - - /*if win_w is different from zero then we must change - the size of the scaled buffer (the position is already + + /*if win_w is different from zero then we must change + the size of the scaled buffer (the position is already encoded into the out parameter)*/ if (out->win_w) { /* picture in picture enabled */ eff_w=out->win_w; @@ -650,26 +650,26 @@ static void my_scale(struct fbuf_t *in, AVPicture *p_in, img_convert(p_out, out->pix_fmt, p_in, in->pix_fmt, in->w, in->h); #else /* XXX replacement */ - { - struct SwsContext *convert_ctx; - - convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt, - eff_w, eff_h, out->pix_fmt, - SWS_BICUBIC, NULL, NULL, NULL); - if (convert_ctx == NULL) { - ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed"); - return; + { + struct SwsContext *convert_ctx; + + convert_ctx = sws_getContext(in->w, in->h, in->pix_fmt, + eff_w, eff_h, out->pix_fmt, + SWS_BICUBIC, NULL, NULL, NULL); + if (convert_ctx == NULL) { + ast_log(LOG_ERROR, "FFMPEG::convert_cmodel : swscale context initialization failed"); + return; + } + if (0) + ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n", + in->pix_fmt, in->w, in->h, out->pix_fmt, eff_w, eff_h); + sws_scale(convert_ctx, + p_in->data, p_in->linesize, + in->w, in->h, /* src slice */ + p_out->data, p_out->linesize); + + sws_freeContext(convert_ctx); } - if (0) - ast_log(LOG_WARNING, "in %d %dx%d out %d %dx%d\n", - in->pix_fmt, in->w, in->h, out->pix_fmt, eff_w, eff_h); - sws_scale(convert_ctx, - p_in->data, p_in->linesize, - in->w, in->h, /* src slice */ - p_out->data, p_out->linesize); - - sws_freeContext(convert_ctx); - } #endif /* XXX replacement */ } @@ -873,18 +873,20 @@ static void *video_thread(void *arg) } } sdl_setup(env); - if (!ast_strlen_zero(save_display)) + if (!ast_strlen_zero(save_display)) { setenv("DISPLAY", save_display, 1); + } ast_mutex_init(&env->dec_lock); /* used to sync decoder and renderer */ if (grabber_open(&env->out)) { ast_log(LOG_WARNING, "cannot open local video source\n"); - } + } - if (env->out.device_num) + if (env->out.device_num) { env->out.devices[env->out.device_primary].status_index |= IS_PRIMARY | IS_SECONDARY; - + } + /* even if no device is connected, we must call video_out_init, * as some of the data structures it initializes are * used in get_video_frames() @@ -893,14 +895,14 @@ static void *video_thread(void *arg) /* Writes intial status of the sources. */ if (env->gui) { - for (i = 0; i < env->out.device_num; i++) { - print_message(env->gui->thumb_bd_array[i].board, - src_msgs[env->out.devices[i].status_index]); - } + for (i = 0; i < env->out.device_num; i++) { + print_message(env->gui->thumb_bd_array[i].board, + src_msgs[env->out.devices[i].status_index]); + } } for (;;) { - struct timeval t = { 0, 50000 }; /* XXX 20 times/sec */ + struct timespec t = { 0, 50000000 }; /* XXX 20 times/sec */ struct ast_frame *p, *f; struct ast_channel *chan; int fd; @@ -908,13 +910,14 @@ static void *video_thread(void *arg) /* determine if video format changed */ if (count++ % 10 == 0) { - if (env->out.sendvideo && env->out.devices) - sprintf(buf, "%s %s %dx%d @@ %dfps %dkbps", + if (env->out.sendvideo && env->out.devices) { + snprintf(buf, sizeof(buf), "%s %s %dx%d @@ %dfps %dkbps", env->out.devices[env->out.device_primary].name, env->codec_name, env->enc_in.w, env->enc_in.h, - env->out.fps, env->out.bitrate/1000); - else - sprintf(buf, "hold"); + env->out.fps, env->out.bitrate / 1000); + } else { + sprintf(buf, "hold"); + } caption = buf; } @@ -923,36 +926,36 @@ static void *video_thread(void *arg) * otherwise the drag will not work */ if (env->gui) eventhandler(env, caption); - + /* sleep for a while */ - ast_select(0, NULL, NULL, NULL, &t); + nanosleep(&t, NULL); if (env->in) { - struct video_dec_desc *v = env->in; - - /* - * While there is something to display, call the decoder and free - * the buffer, possibly enabling the receiver to store new data. - */ - while (v->dec_in_dpy) { - struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */ - - /* decode the frame, but show it only if not frozen */ - if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze) - show_frame(env, WIN_REMOTE); - tmp->used = 0; /* mark buffer as free */ - tmp->ebit = 0; - ast_mutex_lock(&env->dec_lock); - if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */ - v->dec_in_dpy = &v->dec_in[0]; - - if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */ - v->dec_in_cur = tmp; /* using the slot just freed */ - else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */ - v->dec_in_dpy = NULL; /* nothing more to display */ - ast_mutex_unlock(&env->dec_lock); + struct video_dec_desc *v = env->in; + + /* + * While there is something to display, call the decoder and free + * the buffer, possibly enabling the receiver to store new data. + */ + while (v->dec_in_dpy) { + struct fbuf_t *tmp = v->dec_in_dpy; /* store current pointer */ + + /* decode the frame, but show it only if not frozen */ + if (v->d_callbacks->dec_run(v, tmp) && !env->frame_freeze) + show_frame(env, WIN_REMOTE); + tmp->used = 0; /* mark buffer as free */ + tmp->ebit = 0; + ast_mutex_lock(&env->dec_lock); + if (++v->dec_in_dpy == &v->dec_in[N_DEC_IN]) /* advance to next, circular */ + v->dec_in_dpy = &v->dec_in[0]; + + if (v->dec_in_cur == NULL) /* receiver was idle, enable it... */ + v->dec_in_cur = tmp; /* using the slot just freed */ + else if (v->dec_in_dpy == v->dec_in_cur) /* this was the last slot */ + v->dec_in_dpy = NULL; /* nothing more to display */ + ast_mutex_unlock(&env->dec_lock); + } } - } if (env->shutdown) break; @@ -988,7 +991,7 @@ static void *video_thread(void *arg) for (p = f; p; p = AST_LIST_NEXT(p, frame_list)) { if (write(fd, &blah, l) != l) ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d: %s!\n", - chan->name, f->frametype, f->subclass, strerror(errno)); + chan->name, f->frametype, f->subclass, strerror(errno)); } } ast_channel_unlock(chan); @@ -1194,13 +1197,13 @@ int console_video_cli(struct video_desc *env, const char *var, int fd) if (env == NULL) return 1; /* unrecognised */ - if (!strcasecmp(var, "videodevice")) { + if (!strcasecmp(var, "videodevice")) { ast_cli(fd, "videodevice is [%s]\n", env->out.devices[env->out.device_primary].name); - } else if (!strcasecmp(var, "videocodec")) { + } else if (!strcasecmp(var, "videocodec")) { ast_cli(fd, "videocodec is [%s]\n", env->codec_name); - } else if (!strcasecmp(var, "sendvideo")) { + } else if (!strcasecmp(var, "sendvideo")) { ast_cli(fd, "sendvideo is [%s]\n", env->out.sendvideo ? "on" : "off"); - } else if (!strcasecmp(var, "video_size")) { + } else if (!strcasecmp(var, "video_size")) { int in_w = 0, in_h = 0; if (env->in) { in_w = env->in->dec_out.w; @@ -1212,22 +1215,22 @@ int console_video_cli(struct video_desc *env, const char *var, int fd) env->loc_dpy.w, env->loc_dpy.h, env->rem_dpy.w, env->rem_dpy.h, in_w, in_h); - } else if (!strcasecmp(var, "bitrate")) { + } else if (!strcasecmp(var, "bitrate")) { ast_cli(fd, "bitrate is [%d]\n", env->out.bitrate); - } else if (!strcasecmp(var, "qmin")) { + } else if (!strcasecmp(var, "qmin")) { ast_cli(fd, "qmin is [%d]\n", env->out.qmin); - } else if (!strcasecmp(var, "fps")) { + } else if (!strcasecmp(var, "fps")) { ast_cli(fd, "fps is [%d]\n", env->out.fps); - } else if (!strcasecmp(var, "startgui")) { + } else if (!strcasecmp(var, "startgui")) { env->stayopen = 1; console_video_start(env, NULL); - } else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) { + } else if (!strcasecmp(var, "stopgui") && env->stayopen != 0) { env->stayopen = 0; if (env->gui && env->owner) ast_cli_command(-1, "console hangup"); else /* not in a call */ console_video_uninit(env); - } else { + } else { return 1; /* unrecognised */ } return 0; /* recognised */ |