void process_debt(int fd) { /* After a short write, we finally can deliver the "debt" */ ssize_t ret; dpf("Selecting %d for writing because of debt %d\n", fd, fdinfo[fd].debt); send_was_interrupted2: ret = send(fd, fdinfo[fd].buff, fdinfo[fd].debt, 0); dpf(" sent %d bytes\n", ret); if (ret == 0) { fprintf(stderr, "send returned 0? Submit to codinghorror?\n"); close_fd(fd); return; } else if (ret < 0) { if(errno==EINTR) goto send_was_interrupted2; if(errno==EAGAIN) { fdinfo[fd].writeready=0; fdinfo[fd].we_should_epoll_for_writes=1; epoll_update(fd); } else { fprintf(stderr, "Why epoll hasn't told us that there would be error at sending?\n"); perror("send"); close_fd(fd); return; } } else { if (ret < fdinfo[fd].debt) { dpf(" short write at %d\n", fd); /* _Again_ short write. Need to remember the rest of the buffer somewhere. */ int l = fdinfo[fd].debt - ret; char* b = (char*)malloc(l); if (b == NULL) { perror("malloc"); close_fd(fd); return; } memcpy(b, fdinfo[fd].buff + ret, l); free(fdinfo[fd].buff); fdinfo[fd].buff = b; fdinfo[fd].debt = l; fdinfo[fd].we_should_epoll_for_writes=1; epoll_update(fd); dpf(" re-stored debt %d for %d\n", l, fd); } else { /* Now the debt is fulfilled */ free(fdinfo[fd].buff); fdinfo[fd].buff = NULL; fdinfo[fd].debt = 0; dpf(" debt is fulfilled for %d\n", fd); /* and we can start a new cycle */ fdinfo[fdinfo[fd].peerfd].we_should_epoll_for_reads = 1; epoll_update(fdinfo[fd].peerfd); } } }
/* * Define the trace printout procedures. We always include these, in case * other modules were compiled with DEBUG set. Note that they must use * out/errprintf, not fprintf nor fput[cs], because of the way that * stdout/stderr are implemented on DLL/shared library builds. */ void dflush(void) { errflush_nomem(); } static const char * dprintf_file_tail(const char *file) { const char *tail = file + strlen(file); while (tail > file && (isalnum((unsigned char)tail[-1]) || tail[-1] == '.' || tail[-1] == '_') ) --tail; return tail; } #if __LINE__ /* compiler provides it */ void dprintf_file_and_line(const char *file, int line) { if (gs_debug['/']) dpf(dprintf_file_and_line_format, dprintf_file_tail(file), line); }
static void y422p_handler(Instance *pi, void *data) { NScale_private *priv = (NScale_private *)pi; YUV422P_buffer *y422p_in = data; if (pi->outputs[OUTPUT_YUV422P].destination) { if (priv->Nx == 1 && priv->Ny == 1) { /* Pass-through */ PostData(y422p_in, pi->outputs[OUTPUT_YUV422P].destination); return; } /* else... */ YUV422P_buffer *y422p_out = YUV422P_buffer_new(y422p_in->width/priv->Nx, y422p_in->height/priv->Ny, &y422p_in->c); N_scale(priv, y422p_in->y, y422p_in->width, y422p_in->height, y422p_out->y, y422p_out->width, y422p_out->height); N_scale(priv, y422p_in->cr, y422p_in->cr_width, y422p_in->cr_height, y422p_out->cr, y422p_out->cr_width, y422p_out->cr_height); N_scale(priv, y422p_in->cb, y422p_in->cb_width, y422p_in->cb_height, y422p_out->cb, y422p_out->cb_width, y422p_out->cb_height); dpf("posting %dx%d image to output\n", y422p_out->width, y422p_out->height); y422p_out->c.timestamp = y422p_in->c.timestamp; PostData(y422p_out, pi->outputs[OUTPUT_YUV422P].destination); } YUV422P_buffer_release(y422p_in); }
static void * server_entry(void *argp) { void (*server_proc) (void *) = (void (*)(void *))argp; server_proc(NULL); dpf(("rx_pthread.c: server_entry: Server proc returned unexpectedly\n")); return (void *) -1; /* reused as return value, see pthread(3) */ }
void Input::OnInput(LPARAM lParam) { // Keyboard/mouse input const uint buffersize = 64; static BYTE lpb[buffersize]; UINT dwSize; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); assert(dwSize <= buffersize); if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) dpf("GetRawInputData does not return correct size !\n"); RAWINPUT* raw = (RAWINPUT*)lpb; if (raw->header.dwType == RIM_TYPEKEYBOARD) { uint key_code = raw->data.keyboard.VKey; bool key_up = raw->data.keyboard.Flags & RI_KEY_BREAK; key_down[key_code] = !key_up; } else if (raw->header.dwType == RIM_TYPEMOUSE) { if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) mousebutton_left_down = true; if (raw->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) mousebutton_left_down = false; if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) mousebutton_middle_down = true; if (raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) mousebutton_middle_down = false; if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) mousebutton_right_down = true; if (raw->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) mousebutton_right_down = false; mouse_dx = (float)raw->data.mouse.lLastX; mouse_dy = (float)raw->data.mouse.lLastY; } }
static int do_run(Instance *pi, const char *value) { /* Clones and posts the jpeg buffer N times. N=atoi(value). */ JpegSource_private *priv = (JpegSource_private *)pi; int count = atoi(value); int i; if (!priv->jpeg) { fprintf(stderr, "JpegSource has no jpeg data!\n"); return 1; } if (!pi->outputs[OUTPUT_JPEG].destination) { fprintf(stderr, "JpegSource has no destination!\n"); return 1; } Image_common c = { .label = priv->label }; for (i=0; i < count; i++) { Jpeg_buffer *tmp = Jpeg_buffer_from(priv->jpeg->data, priv->jpeg->encoded_length, &c); dpf("%d/%d (%d)\n", i, count, pi->outputs[OUTPUT_JPEG].destination->parent->pending_messages); while (pi->outputs[OUTPUT_JPEG].destination->parent->pending_messages > 5) { /* Throttle output. 25ms sleep. */ nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 25 * 1000 * 1000}, NULL); } PostData(tmp, pi->outputs[OUTPUT_JPEG].destination); } if (pi->outputs[OUTPUT_CONFIG].destination) { PostData(Config_buffer_new("quit", "0"), pi->outputs[OUTPUT_CONFIG].destination); } return 0; }
void epoll_update(int fd) { struct epoll_event ev; memset(&ev, 0, sizeof ev); ev.events = EPOLLONESHOT; if (fdinfo[fd].status=='.' || fdinfo[fd].status==0) { fprintf(stderr, "Bad epoll_update on fd %d with status '%c'\n", fd, fdinfo[fd].status); return; } dpf(epoll_update_msgs[fdinfo[fd].we_should_epoll_for_reads + 2*fdinfo[fd].we_should_epoll_for_writes], fd); if (fdinfo[fd].we_should_epoll_for_reads) { ev.events |= EPOLLIN; } if (fdinfo[fd].we_should_epoll_for_writes) { ev.events |= EPOLLOUT; } ev.data.fd = fd; int ret = epoll_ctl(kdpfd, EPOLL_CTL_MOD, fd, &ev); if(ret<0) { fprintf(stderr, "epoll_ctl MOD error errno=%d\n", errno); } }
/* this function returns the total number of interface addresses * the buffer has to be passed in by the caller. It also returns * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it * gets the mask which is then passed into the kernel and is used * by afsi_SetServerIPRank(). */ int rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[], afs_uint32 mtuBuffer[], int maxSize) { int i, count = 0; #if defined(AFS_USERSPACE_IP_ADDR) int s, len; struct ifconf ifc; struct ifreq ifs[NIFS], *ifr; struct sockaddr_in *a; #endif #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV) char *cp, *cplim; /* used only for AIX 41 */ #endif #if !defined(AFS_USERSPACE_IP_ADDR) count = rx_getAllAddr_internal(addrBuffer, 1024, 0); for (i = 0; i < count; i++) { maskBuffer[i] = htonl(0xffffffff); mtuBuffer[i] = htonl(1500); } return count; #else /* AFS_USERSPACE_IP_ADDR */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) return 0; ifc.ifc_len = sizeof(ifs); ifc.ifc_buf = (caddr_t) ifs; i = ioctl(s, SIOCGIFCONF, &ifc); if (i < 0) { close(s); return 0; } len = ifc.ifc_len / sizeof(struct ifreq); if (len > NIFS) len = NIFS; #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV) if (ifc.ifc_len > sizeof(ifs)) /* safety check */ ifc.ifc_len = sizeof(ifs); for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len; cp < cplim; cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) { ifr = (struct ifreq *)cp; #else for (i = 0; i < len; ++i) { ifr = &ifs[i]; #endif a = (struct sockaddr_in *)&ifr->ifr_addr; if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) { if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) { perror("SIOCGIFFLAGS"); continue; /* ignore this address */ } if (a->sin_addr.s_addr == htonl(0x7f000001) ) continue; /* skip loopback address as well. */ if (count >= maxSize) { /* no more space */ dpf(("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr)); continue; } addrBuffer[count] = a->sin_addr.s_addr; if (ioctl(s, SIOCGIFNETMASK, (caddr_t) ifr) < 0) { perror("SIOCGIFNETMASK"); maskBuffer[count] = htonl(0xffffffff); } else { maskBuffer[count] = (((struct sockaddr_in *) (&ifr->ifr_addr))->sin_addr).s_addr; } mtuBuffer[count] = htonl(1500); #ifdef SIOCGIFMTU if (ioctl(s, SIOCGIFMTU, (caddr_t) ifr) < 0) { perror("SIOCGIFMTU"); } else { mtuBuffer[count] = htonl(ifr->ifr_metric); } #endif /* SIOCGIFMTU */ #ifdef SIOCRIPMTU if (ioctl(s, SIOCRIPMTU, (caddr_t) ifr) < 0) { perror("SIOCRIPMTU"); } else { mtuBuffer[count] = htonl(ifr->ifr_metric); } #endif /* SIOCRIPMTU */ count++; } } close(s); return count; #endif /* AFS_USERSPACE_IP_ADDR */ }
/* this function returns the total number of interface addresses ** the buffer has to be passed in by the caller */ #else /* UKERNEL indirectly, on DARWIN or XBSD */ static int rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks) { int s; int i, len, count = 0; struct ifconf ifc; struct ifreq ifs[NIFS], *ifr; struct sockaddr_in *a; /* can't ever be AFS_DARWIN_ENV or AFS_XBSD_ENV, no? */ #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) char *cp, *cplim, *cpnext; /* used only for AIX 41 */ #endif s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) return 0; ifc.ifc_len = sizeof(ifs); ifc.ifc_buf = (caddr_t) ifs; i = ioctl(s, SIOCGIFCONF, &ifc); if (i < 0) return 0; len = ifc.ifc_len / sizeof(struct ifreq); if (len > NIFS) len = NIFS; #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) if (ifc.ifc_len > sizeof(ifs)) /* safety check */ ifc.ifc_len = sizeof(ifs); for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len; cp < cplim; #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) cp += _SIZEOF_ADDR_IFREQ(*ifr) #else #ifdef AFS_AIX51_ENV cp = cpnext #else cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a)) #endif #endif ) #else for (i = 0; i < len; ++i) #endif { #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) ifr = (struct ifreq *)cp; #else ifr = &ifs[i]; #endif a = (struct sockaddr_in *)&ifr->ifr_addr; #ifdef AFS_AIX51_ENV cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a)); #endif if (a->sin_family != AF_INET) continue; if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) { perror("SIOCGIFFLAGS"); continue; /* ignore this address */ } if (a->sin_addr.s_addr != 0) { if (!loopbacks) { if (a->sin_addr.s_addr == htonl(0x7f000001)) continue; /* skip loopback address as well. */ } else { if (ifr->ifr_flags & IFF_LOOPBACK) continue; /* skip aliased loopbacks as well. */ } if (count >= maxSize) /* no more space */ dpf(("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr)); else buffer[count++] = a->sin_addr.s_addr; } } close(s); return count; }
int rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[], afs_uint32 mtuBuffer[], int maxSize) { int s; size_t needed; int mib[6]; struct if_msghdr *ifm, *nextifm; struct ifa_msghdr *ifam; struct sockaddr_dl *sdl; struct rt_addrinfo info; char *buf, *lim, *next; int count = 0, addrcount = 0; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; /* address family */ mib[4] = NET_RT_IFLIST; mib[5] = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) return 0; if ((buf = malloc(needed)) == NULL) return 0; if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { free(buf); return 0; } #if defined(AFS_OBSD42_ENV) ifm_fixversion(buf, &needed); #endif s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) return 0; lim = buf + needed; next = buf; while (next < lim) { ifm = (struct if_msghdr *)next; if (ifm->ifm_type != RTM_IFINFO) { dpf(("out of sync parsing NET_RT_IFLIST\n")); free(buf); return 0; } sdl = (struct sockaddr_dl *)(ifm + 1); next += ifm->ifm_msglen; ifam = NULL; addrcount = 0; while (next < lim) { nextifm = (struct if_msghdr *)next; if (nextifm->ifm_type != RTM_NEWADDR) break; if (ifam == NULL) ifam = (struct ifa_msghdr *)nextifm; addrcount++; next += nextifm->ifm_msglen; } if ((ifm->ifm_flags & IFF_UP) == 0) continue; /* not up */ while (addrcount > 0) { struct sockaddr_in *a; info.rti_addrs = ifam->ifam_addrs; /* Expand the compacted addresses */ rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) { addrcount--; continue; } a = (struct sockaddr_in *) info.rti_info[RTAX_IFA]; if (a->sin_addr.s_addr != htonl(0x7f000001) ) { if (count >= maxSize) { /* no more space */ dpf(("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr)); } else { struct ifreq ifr; addrBuffer[count] = a->sin_addr.s_addr; a = (struct sockaddr_in *) info.rti_info[RTAX_NETMASK]; if (a) maskBuffer[count] = a->sin_addr.s_addr; else maskBuffer[count] = htonl(0xffffffff); memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen); if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0) mtuBuffer[count] = htonl(1500); else mtuBuffer[count] = htonl(ifr.ifr_mtu); count++; } } addrcount--; ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); } } free(buf); return count; }
int rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks) { size_t needed; int mib[6]; struct if_msghdr *ifm, *nextifm; struct ifa_msghdr *ifam; struct sockaddr_dl *sdl; struct rt_addrinfo info; char *buf, *lim, *next; int count = 0, addrcount = 0; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; /* address family */ mib[4] = NET_RT_IFLIST; mib[5] = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) return 0; if ((buf = malloc(needed)) == NULL) return 0; if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { free(buf); return 0; } #if defined(AFS_OBSD42_ENV) ifm_fixversion(buf, &needed); #endif lim = buf + needed; next = buf; while (next < lim) { ifm = (struct if_msghdr *)next; if (ifm->ifm_type != RTM_IFINFO) { dpf(("out of sync parsing NET_RT_IFLIST\n")); free(buf); return 0; } sdl = (struct sockaddr_dl *)(ifm + 1); next += ifm->ifm_msglen; ifam = NULL; addrcount = 0; while (next < lim) { nextifm = (struct if_msghdr *)next; if (nextifm->ifm_type != RTM_NEWADDR) break; if (ifam == NULL) ifam = (struct ifa_msghdr *)nextifm; addrcount++; next += nextifm->ifm_msglen; } if ((ifm->ifm_flags & IFF_UP) == 0) continue; /* not up */ while (addrcount > 0) { struct sockaddr_in *a; info.rti_addrs = ifam->ifam_addrs; /* Expand the compacted addresses */ rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) { addrcount--; continue; } a = (struct sockaddr_in *) info.rti_info[RTAX_IFA]; if (count >= maxSize) /* no more space */ dpf(("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr)); else if (!loopbacks && a->sin_addr.s_addr == htonl(0x7f000001)) { addrcount--; continue; /* skip loopback address as well. */ } else if (loopbacks && ifm->ifm_flags & IFF_LOOPBACK) { addrcount--; continue; /* skip aliased loopbacks as well. */ } else buffer[count++] = a->sin_addr.s_addr; addrcount--; ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); } } free(buf); return count; }
void rx_upcall(socket_t so, void *arg, __unused int waitflag) { mbuf_t m; int error = 0; int i, flags = 0; struct msghdr msg; struct sockaddr_storage ss; struct sockaddr *sa = NULL; struct sockaddr_in from; struct rx_packet *p; afs_int32 rlen; afs_int32 tlen; afs_int32 savelen; /* was using rlen but had aliasing problems */ size_t nbytes, resid, noffset; p = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE); rx_computelen(p, tlen); rx_SetDataSize(p, tlen); /* this is the size of the user data area */ tlen += RX_HEADER_SIZE; /* now this is the size of the entire packet */ rlen = rx_maxJumboRecvSize; /* this is what I am advertising. Only check * it once in order to avoid races. */ tlen = rlen - tlen; if (tlen > 0) { tlen = rxi_AllocDataBuf(p, tlen, RX_PACKET_CLASS_RECV_CBUF); if (tlen > 0) { tlen = rlen - tlen; } else tlen = rlen; } else tlen = rlen; /* add some padding to the last iovec, it's just to make sure that the * read doesn't return more data than we expect, and is done to get around * our problems caused by the lack of a length field in the rx header. */ savelen = p->wirevec[p->niovecs - 1].iov_len; p->wirevec[p->niovecs - 1].iov_len = savelen + RX_EXTRABUFFERSIZE; resid = nbytes = tlen + sizeof(afs_int32); memset(&msg, 0, sizeof(struct msghdr)); msg.msg_name = &ss; msg.msg_namelen = sizeof(struct sockaddr_storage); sa =(struct sockaddr *) &ss; do { m = NULL; error = sock_receivembuf(so, &msg, &m, MSG_DONTWAIT, &nbytes); if (!error) { size_t sz, offset = 0; noffset = 0; resid = nbytes; for (i=0;i<p->niovecs && resid;i++) { sz=MIN(resid, p->wirevec[i].iov_len); error = mbuf_copydata(m, offset, sz, p->wirevec[i].iov_base); if (error) break; resid-=sz; offset+=sz; noffset += sz; } } } while (0); mbuf_freem(m); /* restore the vec to its correct state */ p->wirevec[p->niovecs - 1].iov_len = savelen; if (error == EWOULDBLOCK && noffset > 0) error = 0; if (!error) { int host, port; nbytes -= resid; if (sa->sa_family == AF_INET) from = *(struct sockaddr_in *)sa; p->length = nbytes - RX_HEADER_SIZE;; if ((nbytes > tlen) || (p->length & 0x8000)) { /* Bogus packet */ if (nbytes <= 0) { if (rx_stats_active) { MUTEX_ENTER(&rx_stats_mutex); rx_atomic_inc(&rx_stats.bogusPacketOnRead); rx_stats.bogusHost = from.sin_addr.s_addr; MUTEX_EXIT(&rx_stats_mutex); } dpf(("B: bogus packet from [%x,%d] nb=%d", from.sin_addr.s_addr, from.sin_port, nbytes)); } return; } else { /* Extract packet header. */ rxi_DecodePacketHeader(p); host = from.sin_addr.s_addr; port = from.sin_port; if (p->header.type > 0 && p->header.type < RX_N_PACKET_TYPES) { if (rx_stats_active) { rx_atomic_inc(&rx_stats.packetsRead[p->header.type - 1]); } } #ifdef RX_TRIMDATABUFS /* Free any empty packet buffers at the end of this packet */ rxi_TrimDataBufs(p, 1); #endif /* receive pcket */ p = rxi_ReceivePacket(p, so, host, port, 0, 0); } } /* free packet? */ if (p) rxi_FreePacket(p); return; }
void dprintf_file_only(const char *file) { if (gs_debug['/']) dpf(dprintf_file_only_format, dprintf_file_tail(file)); }
static void gray_handler(Instance *pi, void *msg) { MotionDetect_private *priv = (MotionDetect_private *)pi; Gray_buffer *gray = msg; int y, x, sum; int mask_check; dpf("%s:%s()\n", __FILE__, __func__); if (priv->accum && (priv->accum->width != gray->width || priv->accum->height != gray->height)) { /* Size has changed. Discard accumulator buffer. */ Gray_buffer_release(priv->accum); priv->accum = 0L; } if (!priv->accum) { priv->accum = Gray_buffer_new(gray->width, gray->height, 0L); memcpy(priv->accum->data, gray->data, gray->data_length); } if (priv->mask && priv->mask->height == gray->height && priv->mask->width == gray->width) { mask_check = 1; } else { mask_check = 0; } sum = 0; for (y=0; y < gray->height; y+=10) { for (x=0; x < gray->width; x+=10) { int offset = y * gray->width + x; if (mask_check) { if (priv->mask->data[offset] == 0) { continue; } } /* The abs() is redundant with the squaring (d*d) below, but I'm keeping it anyway in case I remove or change the squaring. */ int d = abs(priv->accum->data[offset] - gray->data[offset]); sum += (d*d); /* Store with minimal IIR filtering. */ priv->accum->data[offset] = (priv->accum->data[offset] * 2 + gray->data[offset])/3; } } /* Running sum with more substantial IIR filtering. */ priv->running_sum = (priv->running_sum * 15 + sum)/(15+1); if (pi->outputs[OUTPUT_CONFIG].destination) { char temp[64]; snprintf(temp, 64, "%d %d", sum, priv->running_sum); PostData(Config_buffer_new("text", temp), pi->outputs[OUTPUT_CONFIG].destination); } if (pi->outputs[ OUTPUT_MOTIONDETECT].destination) { MotionDetect_result *md = MotionDetect_result_new(); md->sum = sum; PostData(md, pi->outputs[ OUTPUT_MOTIONDETECT].destination); } Gray_buffer_release(gray); // printf("MotionDetect sum=%d\n", sum); }
static void compress_and_post(Instance *pi, int width, int height, uint8_t *c1, uint8_t *c2, uint8_t *c3, Image_common *c, int compress_mode) { /* Compress input buffer. See "libjpeg.txt" in IJPEG source, and "cjpeg.c". */ CJpeg_private *priv = (CJpeg_private *)pi; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; Jpeg_buffer *jpeg_out = 0L; double t1, t2; int report_time = 0; if (0) printf("%s:%s(width=%d height=%d c1=%p c2=%p c3=%p)\n", __FILE__, __func__, width, height, c1, c2, c3); cti_getdoubletime(&t1); cinfo.err = jpeg_std_error(&jerr); /* NOTE: See ERREXIT, error_exit, this may cause the program to call exit()! */ jpeg_create_compress(&cinfo); jpeg_out = Jpeg_buffer_new(0, 0L); /* Pass 0 to let libjpeg allocate output buffer */ jpeg_out->width = width; jpeg_out->height = height; if (c->timestamp == 0.0) { jpeg_out->c.timestamp = t1; /* Save timestamp. */ } if (compress_mode == COMPRESS_Y422 || compress_mode == COMPRESS_Y420) { int w2 = (width/8)*8; int h2 = (height/8)*8; if (w2 != width) { fprintf(stderr, "warning: truncating width from %d to %d\n", width, w2); jpeg_out->width = w2; } if (h2 != height) { fprintf(stderr, "warning: truncating height from %d to %d\n", height, h2); jpeg_out->height = h2; } // jpeg_out->tv = y422p_in->tv; } jpeg_mem_dest(&cinfo, &jpeg_out->data, &jpeg_out->encoded_length); /* NOTE: It turns out there is actually no need for jinit_read_mem() [rdmem.c], just set the pointers in the encode loop! */ cinfo.image_width = jpeg_out->width; cinfo.image_height = jpeg_out->height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; /* reset below if y422p or y420p*/ jpeg_set_defaults(&cinfo); /* See "Raw (downsampled) image data" section in libjpeg.txt. */ if (compress_mode == COMPRESS_Y422) { cinfo.raw_data_in = TRUE; jpeg_set_colorspace(&cinfo, JCS_YCbCr); cinfo.do_fancy_downsampling = FALSE; // http://www.lavrsen.dk/svn/motion/trunk/picture.c cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; } else if (compress_mode == COMPRESS_Y420) { cinfo.raw_data_in = TRUE; jpeg_set_colorspace(&cinfo, JCS_YCbCr); cinfo.do_fancy_downsampling = FALSE; // http://www.lavrsen.dk/svn/motion/trunk/picture.c cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; } /* Various options can be set here... */ //cinfo.dct_method = JDCT_FLOAT; cinfo.dct_method = priv->dct_method; /* Ah, we have to set this up here! */ jpeg_set_quality (&cinfo, priv->adjusted_quality, TRUE); jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { if (compress_mode == COMPRESS_Y422) { int n; /* Setup necessary for raw downsampled data. */ JSAMPROW y[16]; JSAMPROW cb[16]; JSAMPROW cr[16]; for (n=0; n < 16; n++) { y[n] = c1 + ((cinfo.next_scanline+n)* width); cb[n] = c2 + ((cinfo.next_scanline+n) * width / 2); cr[n] = c3 + ((cinfo.next_scanline+n) * width / 2); } JSAMPARRAY array[3] = { y, cb, cr}; JSAMPIMAGE image = array; /* Need to pass enough lines at a time, see "(num_lines < lines_per_iMCU_row)" test in jcapistd.c */ jpeg_write_raw_data(&cinfo, image, 16); } else if (compress_mode == COMPRESS_Y420) { int n; /* Setup necessary for raw downsampled data. */ // fprintf(stderr, "420 cinfo.next_scanline=%d\n", cinfo.next_scanline); JSAMPROW y[16]; JSAMPROW cb[16]; JSAMPROW cr[16]; for (n=0; n < 16; n++) { y[n] = c1 + ((cinfo.next_scanline+n)* width); cb[n] = c2 + (((cinfo.next_scanline/2)+n) * width / 2); cr[n] = c3 + (((cinfo.next_scanline/2)+n) * width / 2); } JSAMPARRAY array[3] = { y, cb, cr}; JSAMPIMAGE image = array; /* Need to pass enough lines at a time, see "(num_lines < lines_per_iMCU_row)" test in jcapistd.c */ jpeg_write_raw_data(&cinfo, image, 16); } else { JSAMPROW row_pointer[1]; /* pointer to a single row */ row_pointer[0] = c1 + (cinfo.next_scanline * width * 3); jpeg_write_scanlines(&cinfo, row_pointer, 1); } } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); // fprintf(stderr, "jpeg_out->encoded_length=%lu\n", jpeg_out->encoded_length); if (pi->outputs[OUTPUT_JPEG].destination) { PostData(jpeg_out, pi->outputs[OUTPUT_JPEG].destination); } else { /* Discard output buffer! */ Jpeg_buffer_release(jpeg_out); } jpeg_out = 0L; /* Clear output buffer copy. */ /* Calculate compress time. */ cti_getdoubletime(&t2); double tdiff = (t2 - t1); if (pi->counter % (30) == 0) { dpf("tdiff=%.5f\n", tdiff); } if ((priv->time_limit > 0.0) && (tdiff > priv->time_limit)) { /* Compress time went over time limit, call sched_yield(), which should prevent starving other threads, most importantly video and audio capture. Frames will back up on this thread, but on systems like 1.6GHz P4 which can just barely handle 640x480@30fps, it tends to even out. */ sched_yield(); /* Turn down quality. */ if (priv->adjusted_quality > 50) { priv->adjusted_quality -= 5; } report_time = 1; } else if (priv->adjusted_quality < priv->quality) { /* Ratchet quality back up, but only by 2, we don't "ping-pong" +/- 5. */ int temp = priv->adjusted_quality + 2; priv->adjusted_quality = cti_min(temp, priv->quality); report_time = 1; } if (report_time) { dpf("* %.5f (q=%d)\n", tdiff, priv->adjusted_quality); } }
static void ALSACapture_tick(Instance *pi) { ALSAio_private *priv = (ALSAio_private *)pi; int wait_flag; if (!priv->c.enable || !priv->c.handle) { wait_flag = 1; } else { wait_flag = 0; } Handler_message *hm; hm = GetData(pi, wait_flag); if (hm) { hm->handler(pi, hm->data); ReleaseMessage(&hm,pi); } if (!priv->c.enable || !priv->c.handle) { /* Not enabled or no handle, don't try to capture anything. */ return; } /* Read a block of data. */ int rc; snd_pcm_sframes_t n; int state; snd_pcm_uframes_t frames = priv->c.frames_per_io; int dir = 0; state = snd_pcm_state(priv->c.handle); dpf("%s: state(1)=%s\n", __func__, ALSAio_state_to_string(state)); if (state == SND_PCM_STATE_OPEN || state == SND_PCM_STATE_SETUP) { /* One time capture setup. */ fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); rc = snd_pcm_hw_params_set_period_size_near(priv->c.handle, priv->c.hwparams, &frames, &dir); fprintf(stderr, "%s: set_period_size_near returns %d (frames %d:%d)\n", __func__, rc, (int)priv->c.frames_per_io, (int)frames); rc = snd_pcm_hw_params(priv->c.handle, priv->c.hwparams); if (rc < 0) { fprintf(stderr, "*** snd_pcm_hw_params %s: %s\n", s(priv->c.device), snd_strerror(rc)); } state = snd_pcm_state(priv->c.handle); fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); rc = snd_pcm_prepare(priv->c.handle); state = snd_pcm_state(priv->c.handle); fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); /* Initialize running_timestamp. */ cti_getdoubletime(&priv->c.running_timestamp); } snd_pcm_hw_params_get_period_size(priv->c.hwparams, &frames, &dir); int size = frames * priv->c.format_bytes * priv->c.channels; if (!size) { // This can happen if channels or format_bytes was not set... fprintf(stderr, "%s: size error - %ld * %d * %d\n", __func__, frames , priv->c.format_bytes , priv->c.channels); while (1) { sleep(1); } } if (!priv->c.rate) { fprintf(stderr, "%s: error - rate is 0!\n", __func__); while (1) { sleep(1); } } /* Allocate buffer for PCM samples. */ uint8_t *buffer = Mem_malloc(size+1); buffer[size] = 0x55; //int val = hwparams->rate; //snd_pcm_hw_params_get_period_time(params, &val, &dir); /* Read the data. */ n = snd_pcm_readi(priv->c.handle, buffer, frames); if (buffer[size] != 0x55) { fprintf(stderr, "*** overwrote audio buffer!\n"); } if (n != frames) { fprintf(stderr, "*** snd_pcm_readi %s: %s\n", s(priv->c.device), snd_strerror((int)n)); fprintf(stderr, "*** attempting snd_pcm_prepare() to correct...\n"); snd_pcm_prepare(priv->c.handle); goto out; } // fprintf(stderr, "*** read %d frames\n", (int) n); double calculated_period = frames*1.0/(priv->c.rate); priv->c.running_timestamp += calculated_period; double tnow; cti_getdoubletime(&tnow); /* Do coarse adjustment if necessary, this can happen after a system date change via ntp or htpdate. */ if (fabs(priv->c.running_timestamp - tnow) > 5.0) { fprintf(stderr, "coarse timestamp adjustment, %.3f -> %.3f\n", priv->c.running_timestamp, tnow); priv->c.running_timestamp = tnow; } /* Adjust running timestamp if it slips too far either way. Smoothing, I guess. */ if (priv->c.running_timestamp - tnow > calculated_period) { dpf("priv->c.rate=%d, %.3f - %.3f (%.5f) > %.5f : - running timestamp\n", priv->c.rate, priv->c.running_timestamp, tnow, (tnow - priv->c.running_timestamp), calculated_period); priv->c.running_timestamp -= (calculated_period/2.0); } else if (tnow - priv->c.running_timestamp > calculated_period) { dpf("priv->c.rate=%d, %.3f - %.3f (%.5f) > %.5f : + running timestamp\n", priv->c.rate, tnow, priv->c.running_timestamp, (tnow - priv->c.running_timestamp), calculated_period); priv->c.running_timestamp += (calculated_period/2.0); } int buffer_bytes = n * priv->c.format_bytes * priv->c.channels; if (pi->outputs[OUTPUT_AUDIO].destination) { Audio_buffer * audio = Audio_buffer_new(priv->c.rate, priv->c.channels, priv->c.atype); Audio_buffer_add_samples(audio, buffer, buffer_bytes); audio->timestamp = priv->c.running_timestamp; //fprintf(stderr, "posting audio buffer %d bytes\n", buffer_bytes); PostData(audio, pi->outputs[OUTPUT_AUDIO].destination); /* TESTING: disable after posting once */ //pi->outputs[OUTPUT_AUDIO].destination = NULL; } if (pi->outputs[OUTPUT_WAV].destination) { Wav_buffer *wav = Wav_buffer_new(priv->c.rate, priv->c.channels, priv->c.format_bytes); wav->timestamp = priv->c.running_timestamp; dpf("%s allocated wav @ %p\n", __func__, wav); wav->data = buffer; buffer = 0L; /* Assign, do not free below. */ wav->data_length = buffer_bytes; Wav_buffer_finalize(wav); if (priv->c.analyze) { analyze_rate(priv, wav); } PostData(wav, pi->outputs[OUTPUT_WAV].destination); static int x = 0; wav->seq = x++; wav = 0L; } out: if (buffer) { Mem_free(buffer); } }
static void Wav_handler(Instance *pi, void *data) { ALSAio_private *priv = (ALSAio_private *)pi; Wav_buffer *wav_in = data; int state; int dir = 0; int rc; //int i; snd_pcm_sframes_t n; if (!priv->c.enable) { return; } if (!priv->c.rate) { /* Set rate. */ char channels[32]; char rate[32]; sprintf(rate, "%d", wav_in->params.rate); set_rate(pi, rate); /* Set channels. */ sprintf(channels, "%d", wav_in->params.channels); set_channels(pi, channels); /* Set format */ snd_pcm_format_t format = ALSAio_bps_to_snd_fmt(wav_in->params.bits_per_sample); if (format != SND_PCM_FORMAT_UNKNOWN) { priv->c.format = format; rc = snd_pcm_hw_params_set_format(priv->c.handle, priv->c.hwparams, priv->c.format); if (rc < 0) { fprintf(stderr, "*** %s: snd_pcm_hw_params_set_format %s: %s\n", __func__, s(priv->c.device), snd_strerror(rc)); } } } state = snd_pcm_state(priv->c.handle); dpf("%s: state(1)=%s\n", __func__, ALSAio_state_to_string(state)); if (state == SND_PCM_STATE_OPEN || state == SND_PCM_STATE_SETUP) { /* One time playback setup. */ /* FIXME: Why does 64 work on NVidia CK804 with "snd_intel8x0" driver, but not 32, 128, 2048? How to find out what will work? */ snd_pcm_uframes_t frames = priv->c.frames_per_io; fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); rc = snd_pcm_hw_params_set_period_size_near(priv->c.handle, priv->c.hwparams, &frames, &dir); fprintf(stderr, "set_period_size_near returns %d (frames=%d)\n", rc, (int)frames); int periods = 4; rc = snd_pcm_hw_params_set_periods(priv->c.handle, priv->c.hwparams, periods, 0); if (rc < 0) { fprintf(stderr, "*** snd_pcm_hw_params_set_periods %s: %s\n", s(priv->c.device), snd_strerror(rc)); } rc = snd_pcm_hw_params(priv->c.handle, priv->c.hwparams); if (rc < 0) { fprintf(stderr, "*** snd_pcm_hw_params %s: %s\n", s(priv->c.device), snd_strerror(rc)); } state = snd_pcm_state(priv->c.handle); fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); rc = snd_pcm_prepare(priv->c.handle); state = snd_pcm_state(priv->c.handle); fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); } dpf("%s: state(2)=%s\n", __func__, ALSAio_state_to_string(state)); int out_frames = wav_in->data_length / (priv->c.channels * priv->c.format_bytes); int frames_written = 0; while (1) { n = snd_pcm_writei(priv->c.handle, (uint8_t*)wav_in->data + (frames_written * (priv->c.channels * priv->c.format_bytes)), out_frames); if (n > 0) { out_frames -= n; frames_written += n; } else { break; } } if (n < 0) { fprintf(stderr, "*** snd_pcm_writei %s: %s\n", s(priv->c.device), snd_strerror((int)n)); fprintf(stderr, "*** attempting snd_pcm_prepare() to correct...\n"); snd_pcm_prepare(priv->c.handle); } if (wav_in->no_feedback == 0 /* The default is 0, set to 1 if "filler" code below is called. */ && pi->outputs[OUTPUT_FEEDBACK].destination) { Feedback_buffer *fb = Feedback_buffer_new(); fb->seq = wav_in->seq; PostData(fb, pi->outputs[OUTPUT_FEEDBACK].destination); } Wav_buffer_release(&wav_in); }