static int end_block( void *d ) { struct framedropper *drop = (struct framedropper *)d; if( ! drop->input ) { spook_log( SL_ERR, "framedrop: missing input stream name" ); return -1; } if( ! drop->output ) { spook_log( SL_ERR, "framedrop: missing output stream name" ); return -1; } if( drop->scale < 1 ) { spook_log( SL_ERR, "framedrop: missing scale factor" ); return -1; } return 0; }
static int end_block(void *d) { struct adpcm_encoder *en = (struct adpcm_encoder *)d; int32_t i32Ret; if (! en->output) { spook_log(SL_ERR, "adpcm: missing output stream name"); return -1; } i32Ret = ImportAdpcmEncConfig(&en->sAdpcmEncConfig); if (i32Ret < 0) return i32Ret; if (en->sAdpcmEncConfig.m_eFormat == eADPCM_IMA) { spook_log(SL_ERR, "adpcm: missing DVI format"); return -1; } //create import alaw thread en->ex = new_exchanger(4, deliver_frame_to_stream, en->output); pthread_create(&en->thread, NULL, adpcm_loop, en); return 0; }
static int set_format( int num_tokens, struct token *tokens, void *d ) { struct rtp_spook_input *conf = (struct rtp_spook_input *)d; if( conf->output ) { spook_log( SL_ERR, "rtpi: output format must be specified " "before output stream name" ); return -1; } if( ! strcasecmp( tokens[1].v.str, "pcm" ) ) conf->format = FORMAT_PCM; else if( ! strcasecmp( tokens[1].v.str, "mpeg4" ) ) conf->format = FORMAT_MPEG4; else if( ! strcasecmp( tokens[1].v.str, "mjpeg" ) ) conf->format = FORMAT_JPEG; else { spook_log( SL_ERR, "rtpi: format \"%s\" is unsupported; try " "PCM, MJPEG, or MPEG4", tokens[1].v.str ); return -1; } return 0; }
static void do_accept( struct event_info *ei, void *d ) { struct listener *listener = (struct listener *)d; int fd, addrlen; struct sockaddr_un addr; struct ctl_sock *cs; addrlen = sizeof( addr ); if( ( fd = accept( listener->fd, (struct sockaddr *)&addr, &addrlen ) ) < 0 ) { spook_log( SL_WARN, "error accepting control connection: %s", strerror( errno ) ); return; } spook_log( SL_DEBUG, "accepted control connection" ); cs = (struct ctl_sock *)malloc( sizeof( struct ctl_sock ) ); if( ! cs ) { spook_log( SL_ERR, "out of memory on malloc ctl_sock" ); close( fd ); return; } cs->fd = fd; cs->read_event = add_fd_event( fd, 0, 0, do_read, cs ); }
static bool SimpleAnalyserHasImproved( S_QOS_ANALYSER *psObjBase ) { SimpleQosAnalyser *psObj = (SimpleQosAnalyser *) psObjBase; S_RTP_STATS *psCur = &psObj->sStats[psObj->i32CurIndex % STATS_HISTORY]; S_RTP_STATS *psPrev = &psObj->sStats[(STATS_HISTORY + psObj->i32CurIndex - 1) % STATS_HISTORY]; if (psPrev->fLostPercentage >= fUnacceptableLossRate) { if (psCur->fLostPercentage < psPrev->fLostPercentage) { spook_log(SL_INFO, "MSQosAnalyser: lost percentage has improved"); return true; } else goto end; } if (psObj->bRoundTripPropDoubled && psCur->fRoundTripProp < psPrev->fRoundTripProp) { spook_log(SL_INFO, "MSQosAnalyser: rt prop decrased"); psObj->bRoundTripPropDoubled = false; return true; } end: spook_log(SL_INFO, "MSQosAnalyser: no improvements."); return false; }
static int end_block( void *d ) { struct mpeg4_encoder *en = (struct mpeg4_encoder *)d; if( ! en->output ) { spook_log( SL_ERR, "mpeg4: missing output stream name" ); return -1; } if( ! en->input ) { spook_log( SL_ERR, "mpeg4: missing input stream name" ); return -1; } if( en->bitrate < 0 ) { spook_log( SL_ERR, "mpeg4: bitrate must be specified" ); return -1; } en->ex = new_exchanger( 8, deliver_frame_to_stream, en->output ); pthread_create( &en->encoding_thread, NULL, mpeg4_loop, en ); return 0; }
static int end_block( void *d ) { struct rtp_spook_input *conf = (struct rtp_spook_input *)d; int i; if( ! conf->output ) { spook_log( SL_ERR, "rtpi: missing output stream name" ); return -1; } if( conf->fps < 0 ) { spook_log( SL_ERR, "v4l: framerate not specified for webcam" ); return -1; } else if( conf->fps > 0 ) { conf->fincr = 1; conf->fbase = conf->fps; } else { spook_log( SL_INFO, "v4l: must figure out framerate" ); return -1; } if( rtp_setup( conf ) < 0 ) return -1; conf->ex = new_exchanger( conf->fps, get_back_frame1, conf ); for( i = 0; i < conf->fps; ++i ) exchange_frame( conf->ex, new_frame() ); pthread_create( &conf->thread, NULL, capture_loop, conf ); return 0; }
static int dc1394_setup( struct dc1394_input *conf ) { raw1394handle_t raw_handle; nodeid_t *camera_nodes = NULL; int numPorts; int actual_count = 0, c, i; struct raw1394_portinfo ports[16]; raw_handle = raw1394_new_handle(); if( ! raw_handle ) { spook_log( SL_ERR, "dc1394: unable to acquire a raw1394 handle" ); return -1; } numPorts = raw1394_get_port_info( raw_handle, ports, 16 ); raw1394_destroy_handle( raw_handle ); for( i = 0; i < numPorts; ++i ) { int camCount = 0; raw_handle = raw1394_new_handle(); raw1394_set_port( raw_handle, i ); camera_nodes = dc1394_get_camera_nodes( raw_handle, &camCount, 1 ); raw1394_destroy_handle( raw_handle ); spook_log( SL_INFO, "dc1394: found %d cams on port %d", camCount, i ); for( c = 0; c < camCount; ++c ) { if( cam_setup( conf, actual_count, i, camera_nodes[c], c ) < 0 ) return -1; if( ++actual_count == conf->cam_count ) return 0; } // this doesn't work, fix later (just a li'l memory leak...) //dc1394_free_camera_nodes( camera_nodes ); } if( actual_count == 0 ) { spook_log( SL_ERR, "dc1394: did not find any IIDC cameras" ); return -1; } if( actual_count < conf->cam_count ) spook_log( SL_WARN, "dc1394: only found %d cameras, some outputs will be inactive", actual_count ); return 0; }
static void drop_sock( struct ctl_sock *cs ) { spook_log( SL_DEBUG, "closed control connection" ); remove_event( cs->read_event ); close( cs->fd ); free( cs ); }
static int end_block(void *d) { struct h264_encoder *en = (struct h264_encoder *)d; int32_t i32Ret; if (! en->output) { spook_log(SL_ERR, "h264: missing output stream name"); return -1; } i32Ret = ImportH264EncConfig(&en->sH264EncConfig); if (i32Ret < 0) return i32Ret; if (en->eH264EncRes >= en->sH264EncConfig.m_ui32WorkablePipes) { printf("plugin-rtsp: No H264 workable pipes \n"); return -2; } en->ex = new_exchanger(get_max_frame_slot() * 2, deliver_frame_to_stream, en->output); // en->ex = new_exchanger( 8, deliver_frame_to_stream, en->output ); //use push callback instead of import // pthread_create( &en->thread, NULL, h264_loop, en ); return 0; }
static bool SimpleAnalyserProcRTCP( S_QOS_ANALYSER *psObjBase, S_RTCP_MBLK *psRTCPBlk, int32_t i32ClockRate ) { SimpleQosAnalyser *psObj = (SimpleQosAnalyser *) psObjBase; S_RTP_STATS *psCur; const S_RTCP_REPORT_BLOCK *psRB = NULL; psRB = RTCP_RR_GetReportBlock(psRTCPBlk, 0); if (psRB && (REPORT_BLOCK_GET_SSRC(psRB) == psObj->u32SSRC)) { psObj->i32CurIndex ++; psCur = &psObj->sStats[psObj->i32CurIndex % STATS_HISTORY]; psCur->u64HighSeqRecv = REPORT_BLOCK_GET_HIGH_EXT_SEQ(psRB); psCur->fLostPercentage = 100.0 * (float)REPORT_BLOCK_GET_FRACTION_LOST(psRB) / 256.0; psCur->fIntJitter = 1000.0 * (float)REPORT_BLOCK_GET_INTERARRIVAL_JITTER(psRB) / (float)i32ClockRate; psCur->fRoundTripProp = psObj->psRTPep->dRTT; spook_log(SL_INFO, "MSQosAnalyser: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec", psCur->fLostPercentage, psCur->fIntJitter, psCur->fRoundTripProp); } return psRB != NULL; }
static void *capture_loop( void *d ) { struct oss_input *conf = (struct oss_input *)d; unsigned char *buf; int len = 0, ret, blocksize; blocksize = conf->rate * conf->channels * 2 / 50; spook_log( SL_VERBOSE, "input-oss: blocksize is %d", blocksize ); buf = malloc( blocksize ); for(;;) { ret = read( conf->fd, buf + len, blocksize - len ); if( ret < 0 ) { perror( "read" ); break; } len += ret; if( len == blocksize ) { audio_ring_input( conf->ring, buf, len ); len = 0; } } return NULL; }
static void mpeg4_stop( struct mpeg4_decoder *en ) { spook_log( SL_DEBUG, "mpeg4: destroying mpeg4 decoder" ); xvid_decore( en->xvid_handle, XVID_DEC_DESTROY, NULL, NULL ); en->xvid_handle = NULL; }
static void mpeg4_start( struct mpeg4_encoder *en, struct frame *f ) { xvid_enc_create_t xvid_enc_create; xvid_enc_plugin_t plugins[1]; xvid_plugin_single_t single; en->reset_pending = 0; en->width = f->width; en->height = f->height; memset( &xvid_enc_create, 0, sizeof( xvid_enc_create ) ); xvid_enc_create.version = XVID_VERSION; xvid_enc_create.width = en->width; xvid_enc_create.height = en->height; xvid_enc_create.profile = XVID_PROFILE_ARTS_L4; en->input->stream->get_framerate( en->input->stream, &xvid_enc_create.fincr, &xvid_enc_create.fbase ); spook_log( SL_DEBUG, "creating mpeg4 encoder with fincr=%d fbase=%d", xvid_enc_create.fincr, xvid_enc_create.fbase ); xvid_enc_create.zones = NULL; xvid_enc_create.num_zones = 0; xvid_enc_create.plugins = plugins; xvid_enc_create.num_plugins = 1; xvid_enc_create.num_threads = 0; xvid_enc_create.max_key_interval = 300; xvid_enc_create.max_bframes = 0; xvid_enc_create.bquant_ratio = 150; xvid_enc_create.bquant_offset = 100; xvid_enc_create.frame_drop_ratio = 0; xvid_enc_create.global = 0; memset( &single, 0, sizeof( single ) ); single.version = XVID_VERSION; single.bitrate = en->bitrate * 1000; plugins[0].func = xvid_plugin_single; plugins[0].param = &single; if( xvid_encore( NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL ) ) { spook_log( SL_ERR, "mpeg4: unable to start XviD!" ); return; } en->xvid_handle = xvid_enc_create.handle; }
static void *mpeg4_loop( void *d ) { struct mpeg4_decoder *en = (struct mpeg4_decoder *)d; xvid_dec_frame_t xvid_dec_frame; xvid_dec_stats_t xvid_dec_stats; struct frame *out, *input; int used, pos; for(;;) { input = get_next_frame( en->ex, 1 ); if( en->reset_pending && en->xvid_handle ) mpeg4_stop( en ); if( ! en->xvid_handle ) mpeg4_start( en, input ); out = new_frame(); out->width = en->width; out->height = en->height; pos = 0; while( input->length - pos > 0 ) { memset( &xvid_dec_frame, 0, sizeof( xvid_dec_frame ) ); xvid_dec_frame.version = XVID_VERSION; xvid_dec_frame.general = 0; xvid_dec_frame.bitstream = input->d + pos; xvid_dec_frame.length = input->length - pos; xvid_dec_frame.output.plane[0] = out->d; xvid_dec_frame.output.stride[0] = 2 * out->width; xvid_dec_frame.output.csp = XVID_CSP_UYVY; xvid_dec_stats.version = XVID_VERSION; used = xvid_decore( en->xvid_handle, XVID_DEC_DECODE, &xvid_dec_frame, &xvid_dec_stats ); if( used < 0 ) { out->length = 0; spook_log( SL_WARN, "mpeg4: XviD decoding failed!" ); } if( xvid_dec_stats.type == XVID_TYPE_VOL ) { out->width = en->width = xvid_dec_stats.data.vol.width; out->height = en->height = xvid_dec_stats.data.vol.height; } pos += used; } out->format = FORMAT_RAW_UYVY; out->length = 2 * out->width * out->height; out->key = 1; deliver_frame( en->ex, out ); unref_frame( input ); } return NULL; }
static int cam_setup( struct dc1394_input *conf, int cam, int port, nodeid_t node, int dma_chan ) { unsigned int channel; unsigned int speed; conf->cam[cam].running = 0; conf->camera[cam].node = node; conf->cam[cam].handle = dc1394_create_handle( port ); if( ! conf->cam[cam].handle ) { spook_log( SL_ERR, "dc1394: unable to create a camera handle" ); return -1; } if( dc1394_get_iso_channel_and_speed( conf->cam[cam].handle, node, &channel, &speed ) != DC1394_SUCCESS ) { spook_log( SL_ERR, "dc1394: unable to create an ISO channel" ); return -1; } if( dc1394_dma_setup_capture( conf->cam[cam].handle, node, dma_chan, FORMAT_VGA_NONCOMPRESSED, MODE_320x240_YUV422, SPEED_400, FRAMERATE_30, 8 /* num buffers */, #ifdef DC1394_EXTRA_BUFFERING_FLAG 0 /* do_extra_buffering */, #endif 1 /* drop frames */, NULL /* device name */, &conf->camera[cam] ) != DC1394_SUCCESS ) { spook_log( SL_ERR, "dc1394: unable to set up DMA for camera" ); return -1; } if( dc1394_start_iso_transmission( conf->cam[cam].handle, conf->camera[cam].node ) != DC1394_SUCCESS ) { spook_log( SL_ERR, "dc1394: unable to start ISO transfer from camera" ); return -1; } conf->cam[cam].outq = new_soft_queue( 16 ); add_softqueue_event( conf->cam[cam].outq, 0, get_back_frame, &conf->cam[cam] ); return 0; }
static int end_block( void *d ) { struct dc1394_input *conf = (struct dc1394_input *)d; if( conf->cam_count == 0 ) { spook_log( SL_ERR, "dc1394: missing output stream name" ); return -1; } if( dc1394_setup( conf ) < 0 ) { spook_log( SL_ERR, "dc1394: unable to initialize video input" ); return -1; } pthread_create( &conf->thread, NULL, capture_loop, conf ); return 0; }
static void set_running( struct stream *s, int running ) { struct mpeg4_decoder *en = (struct mpeg4_decoder *)s->private; spook_log( SL_DEBUG, "mpeg4 decoder is told to set running to %d", running ); if( ! en->running && running ) en->reset_pending = 1; set_waiting( en->input, running ); en->running = running; }
int control_listen(void) { struct sockaddr_un addr; struct listener *listener; int fd; addr.sun_family = AF_UNIX; strcpy( addr.sun_path, "spook.sock" ); unlink( addr.sun_path ); if( ( fd = socket( PF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) { spook_log( SL_ERR, "error creating control socket: %s", strerror( errno ) ); return -1; } if( bind( fd, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) { spook_log( SL_ERR, "unable to bind control socket: %s", strerror( errno ) ); close( fd ); return -1; } if( listen( fd, 5 ) < 0 ) { spook_log( SL_ERR, "error attempting to listen on control socket: %s", strerror( errno ) ); close( fd ); return -1; } listener = (struct listener *)malloc( sizeof( struct listener ) ); listener->fd = fd; add_fd_event( fd, 0, 0, do_accept, listener ); spook_log( SL_INFO, "listening on control socket %s", addr.sun_path ); return 0; }
bool QOSAnalyser_HasImproved( S_QOS_ANALYSER *psObj ) { if (psObj->psDesc->pfn_has_improved) { return psObj->psDesc->pfn_has_improved(psObj); } spook_log(SL_VERBOSE, "Unimplemented has_improved() call."); return true; }
static int set_framerate_num( int num_tokens, struct token *tokens, void *d ) { struct rtp_spook_input *conf = (struct rtp_spook_input *)d; if( conf->fps >= 0 ) { spook_log( SL_ERR, "v4l: frame rate has already been set!" ); return -1; } conf->fps = tokens[1].v.num; return 0; }
static int set_scale( int num_tokens, struct token *tokens, void *d ) { struct framedropper *drop = (struct framedropper *)d; if( tokens[1].v.num < 1 ) { spook_log( SL_ERR, "framedrop: scale factor cannot be less than 1!" ); return -1; } drop->scale = tokens[1].v.num; return 0; }
static int set_bitrate( int num_tokens, struct token *tokens, void *d ) { struct mpeg4_encoder *en = (struct mpeg4_encoder *)d; if( tokens[1].v.num < 10 || tokens[1].v.num > 4000 ) { spook_log( SL_ERR, "mpeg4: bitrate must be between 10 and 4000" ); return -1; } en->bitrate = tokens[1].v.num; return 0; }
static int set_samplerate( int num_tokens, struct token *tokens, void *d ) { struct oss_input *conf = (struct oss_input *)d; if( conf->rate > 0 ) { spook_log( SL_ERR, "oss: sample rate has already been set!" ); return -1; } conf->rate = tokens[1].v.num; return 0; }
static int mpv_process_frame(struct frame *f, void *d) { struct rtp_mpv *out = (struct rtp_mpv *)d; int flen, start, in_picture = 0, have_vsh = 0; unsigned int start_code; out->blk_count = 0; for (start = 0; start < f->length; start += flen) { if (out->blk_count == 48) { spook_log(SL_WARN, "rtp-mpv: too many elements to send"); break; } flen = find_next_code(f->d + start, f->length - start); if (flen == 0) flen = f->length - start; start_code = GET_32(f->d + start); if (start_code <= 0x000001AF || start_code == 0x000001B8) in_picture = 1; if (in_picture) { if (start_code == 0x00000100) parse_picture_header(out, f->d + start, flen); out->blk[out->blk_count].d = f->d + start; out->blk[out->blk_count].len = flen; ++out->blk_count; } else { /* we have not seen a GOP or picture start code yet */ if (start_code == 0x000001B3) { out->vsh_len = 0; have_vsh = 1; parse_video_sequence_header(out, f->d + start, flen); } if (have_vsh) { memcpy(out->vsh + out->vsh_len, f->d + start, flen); out->vsh_len += flen; } } } return out->init_done; }
static int set_output( int num_tokens, struct token *tokens, void *d ) { struct framedropper *drop = (struct framedropper *)d; if( ! drop->input ) { spook_log( SL_ERR, "framedrop: input must be specified before output" ); return -1; } drop->output = new_stream( tokens[1].v.str, drop->input->stream->format, drop ); if( ! drop->output ) { spook_log( SL_ERR, "framedrop: unable to create stream \"%s\"", tokens[1].v.str ); return -1; } drop->output->get_framerate = get_framerate; drop->output->set_running = set_running; return 0; }
static int set_input( int num_tokens, struct token *tokens, void *d ) { struct mpeg4_decoder *en = (struct mpeg4_decoder *)d; int formats[1] = { FORMAT_MPEG4 }; if( ! ( en->input = connect_to_stream( tokens[1].v.str, mpeg4_decode, en, formats, 1 ) ) ) { spook_log( SL_ERR, "mpeg4: unable to connect to stream \"%s\"", tokens[1].v.str ); return -1; } return 0; }
bool QOSAnalyser_ProcRTCP( S_QOS_ANALYSER *psObj, S_RTCP_MBLK *psRTCPBlk, int32_t i32ClockRate ) { if (psObj->psDesc->pfn_proc_rtcp) { return psObj->psDesc->pfn_proc_rtcp(psObj, psRTCPBlk, i32ClockRate); } spook_log(SL_VERBOSE, "Unimplemented process_rtcp() call."); return false; }
static int set_input( int num_tokens, struct token *tokens, void *d ) { struct framedropper *drop = (struct framedropper *)d; if( ! ( drop->input = connect_to_stream( tokens[1].v.str, do_framedrop, drop, NULL, 0 ) ) ) { spook_log( SL_ERR, "framedrop: unable to connect to stream \"%s\"\n", tokens[1].v.str ); return -1; } return 0; }
static void SimpleAnalyserSuggestAction( S_QOS_ANALYSER *psObjBase, S_RATE_CTRL_ACT *psAction ) { SimpleQosAnalyser *psObj = (SimpleQosAnalyser *) psObjBase; S_RTP_STATS *psCur = &psObj->sStats[psObj->i32CurIndex % STATS_HISTORY]; /*big losses and big jitter */ if (psCur->fLostPercentage >= fUnacceptableLossRate && psCur->fIntJitter >= i32BigJitter) { psAction->eActType = eRATE_CTRL_ACT_DEC_BITRATE; if (psCur->fLostPercentage > 50) psAction->i32Value = 50; else psAction->i32Value = (int32_t) psCur->fLostPercentage; spook_log(SL_INFO, "MSQosAnalyser: loss rate unacceptable and big jitter. Decreasing video bitrate %d percent.", psAction->i32Value); } else if (RoundTripPropIncreased(psObj)) { psAction->eActType = eRATE_CTRL_ACT_DEC_BITRATE; psAction->i32Value = 20; spook_log(SL_INFO, "MSQosAnalyser: rt_prop doubled. Decreasing video bitrate %d percent.", psAction->i32Value); } else if (psCur->fLostPercentage >= fUnacceptableLossRate) { /*big loss rate but no jitter, and no big rtp_prop: pure lossy network*/ psAction->eActType = eRATE_CTRL_ACT_DEC_PACKETRATE; spook_log(SL_INFO, "MSQosAnalyser: loss rate unacceptable."); } else { psAction->eActType = eRATE_CTRL_ACT_DO_NOTHING; spook_log(SL_INFO, "MSQosAnalyser: everything is fine."); } }