/* 服务端 - 客户端回调 */ void client_cb(channel_ref_t* channel, channel_cb_event_e e) { if (e & channel_cb_event_close) { connector_count--; if (connector_count == 0) { printf("all client closed\n"); loop_exit(channel_ref_get_loop(channel)); } } }
int main(int argc, char* argv[]) { loop_handle * hd = &global_handle; dvs_thread thread_in; dvs_thread thread_out; int res = TRUE; int c; memset(hd, 0, sizeof(loop_handle)); hd->running = TRUE; hd->ndelay = 4; while(--argc) { argv++; // skip progamname if(**argv == '-') { c = tolower(*++*argv); // get option character ++*argv; if(**argv == '=') ++*argv; // skip equalsign if(**argv == ' ') ++*argv; // skip space switch(c) { case '2': hd->buse2cards = TRUE; break; case 'a': hd->baudioonly = TRUE; break; case 'b': hd->bottom2top = TRUE; // flipping by using bottom2top break; case 'd': hd->ndelay = atoi(*argv); break; case 'f': hd->bfieldbased = TRUE; break; case 'v': hd->bvideoonly = TRUE; break; case 'x': hd->bverbose = TRUE; break; case 'p': hd->banc = TRUE; break; case 'q': hd->bancstreamer = TRUE; break; default: res = usage(); } } else { res = usage(); } } if(hd->banc && hd->bancstreamer) { printf("Parameter for anc overrides anc streamer.\n"); hd->bancstreamer = FALSE; } signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); if(res) { res = loop_init(hd); } if(res) { if(!dvs_thread_create(&thread_in, loop_in, hd, &hd->finish)) { printf("Creating input thread failed.\n"); res = FALSE; } } if(res) { if(!dvs_thread_create(&thread_out, loop_out, hd, &hd->finish)) { printf("Creating output thread failed.\n"); res = FALSE; } } if(res) { do { if(hd->bplayback) { printf("playback mode\n"); } else { printf("loop-through mode\n"); } c = getc(stdin); hd->bplayback = !hd->bplayback; } while (hd->running); } dvs_cond_broadcast(&hd->common.ready, &hd->common.lock, FALSE); dvs_thread_exitcode(&thread_in, &hd->finish); dvs_thread_exitcode(&thread_out, &hd->finish); loop_exit(hd); signal(SIGTERM, NULL); signal(SIGINT, NULL); return (res == TRUE) ? 0 : 1; }
int loop_init(loop_handle * hd) { sv_fifo_configinfo config; int modesrc = 0; int modedst = 0; int syncmode = 0; int res; int i; char anclayout[1024]; // Open first card. hd->svsrc = sv_open(""); if (hd->svsrc == NULL) { printf("loop_init: sv_open(\"\") failed\n"); loop_exit(hd); return FALSE; } if(hd->buse2cards) { // Open second card. hd->svdst = sv_open("PCI,card:1"); if(hd->svdst == NULL) { printf("loop_init: sv_open(\"PCI.card:1\") failed\n"); loop_exit(hd); return FALSE; } } else { // Use first card for output as well. hd->svdst = hd->svsrc; } // Get current videomode from first card. res = sv_option_get(hd->svsrc, SV_OPTION_VIDEOMODE, &modesrc); if(res != SV_OK) { printf("loop_init: sv_option_get() failed\n"); loop_exit(hd); return FALSE; } // Get current videomode from second card. res = sv_option_get(hd->svdst, SV_OPTION_VIDEOMODE, &modedst); if(res != SV_OK) { printf("loop_init: sv_option_get() failed\n"); loop_exit(hd); return FALSE; } // Compare if both videomodes do match. if((modesrc & SV_MODE_MASK) != (modedst & SV_MODE_MASK)) { printf("loop_init: Raster of source and destination board do not match.\n"); loop_exit(hd); return FALSE; } // Check sync mode res = sv_query(hd->svsrc, SV_QUERY_SYNCMODE, 0, &syncmode); if(res != SV_OK) { printf("loop_init: sv_query(SV_QUERY_SYNCMODE) failed\n"); loop_exit(hd); return FALSE; } if(syncmode == SV_SYNC_INTERNAL) { printf("Error:\tPlease configure another sync mode,\n\tit is not possible to have a stable in to out delay with SV_SYNC_INTERNAL.\n"); loop_exit(hd); return FALSE; } switch(modesrc & SV_MODE_MASK) { case SV_MODE_SMPTE274_47P: case SV_MODE_SMPTE274_48P: case SV_MODE_SMPTE274_50P: case SV_MODE_SMPTE274_59P: case SV_MODE_SMPTE274_60P: case SV_MODE_SMPTE274_71P: case SV_MODE_SMPTE274_72P: hd->bdualsdi = TRUE; break; } // Get information about current raster. res = sv_storage_status(hd->svsrc, 0, NULL, &hd->storage, sizeof(sv_storageinfo), 0); if(res != SV_OK) { printf("loop_init: sv_storage_status() failed = %d '%s'\n", res, sv_geterrortext(res)); } // How many ticks does a frame last? hd->vinterlace = hd->storage.vinterlace; //frame to field correction hd->ndelay = hd->ndelay * hd->storage.vinterlace; //fieldbased correction if(hd->bfieldbased) { hd->vinterlace = 1; } if(hd->banc) { // Disable the fifo ancgenerator because else you will get double packets in loopback res = sv_option_set(hd->svdst, SV_OPTION_ANCGENERATOR, SV_ANCDATA_DISABLE ); if(res != SV_OK) { printf("loop_init: sv_option_set() failed\n"); loop_exit(hd); return FALSE; } } // Init input FIFO. res = sv_fifo_init(hd->svsrc, &hd->fifosrc, TRUE, // input FIFO FALSE, TRUE, // enable DMA mode (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0) | (hd->bfieldbased ? SV_FIFO_FLAG_FIELD : 0), // enable field-based mode 0 // use maximum available buffers ); if(res != SV_OK) { printf("sv_fifo_init(src) failed %d '%s'\n", res, sv_geterrortext(res)); loop_exit(hd); return FALSE; } res = sv_fifo_sanitylevel(hd->svsrc, hd->fifosrc, SV_FIFO_SANITY_LEVEL_FATAL, SV_FIFO_SANITY_VERSION_1); if(res != SV_OK) { printf("sv_fifo_sanitylevel(dst) failed %d '%s'\n", res, sv_geterrortext(res)); } // Init output FIFO. res = sv_fifo_init(hd->svdst, &hd->fifodst, FALSE, // output FIFO FALSE, TRUE, // enable DMA mode (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0), 0 // use maximum available buffers ); if(res != SV_OK) { printf("sv_fifo_init(dst) failed %d '%s'\n", res, sv_geterrortext(res)); loop_exit(hd); return FALSE; } res = sv_fifo_sanitylevel(hd->svdst, hd->fifodst, SV_FIFO_SANITY_LEVEL_FATAL, SV_FIFO_SANITY_VERSION_1); if(res != SV_OK) { printf("sv_fifo_sanitylevel(dst) failed %d '%s'\n", res, sv_geterrortext(res)); } if(hd->bverbose && hd->bancstreamer) { int required = 0; res = sv_fifo_anclayout(hd->svsrc, hd->fifosrc, anclayout, sizeof(anclayout), &required); if(res == SV_ERROR_BUFFERSIZE) { printf("sv_fifo_anclayout(src) buffer too small (required %d)\n", required); } else if(res != SV_OK) { printf("sv_fifo_anclayout(src) failed %d '%s'\n", res, sv_geterrortext(res)); } else { printf("ANC layout (input):\n%s\n", anclayout); } res = sv_fifo_anclayout(hd->svdst, hd->fifodst, anclayout, sizeof(anclayout), &required); if(res == SV_ERROR_BUFFERSIZE) { printf("sv_fifo_anclayout(dst) buffer too small (required %d)\n", required); } else if(res != SV_OK) { printf("sv_fifo_anclayout(dst) failed %d '%s'\n", res, sv_geterrortext(res)); } else { printf("ANC layout (output):\n%s\n", anclayout); } } // Fetch some information about FIFO buffer sizes. res = sv_fifo_configstatus(hd->svsrc, hd->fifosrc, &config); if(res != SV_OK) { printf("sv_fifo_configstatus(src) failed %d '%s'\n", res, sv_geterrortext(res)); loop_exit(hd); return FALSE; } // Allocate sufficient memory for video and audio data. for(i = 0; i < MAX_ID; i++) { memset( &hd->anclist[i], 0, sizeof(hd->anclist[i]) ); hd->livebuffer_org[i] = malloc(config.vbuffersize + config.abuffersize + (config.dmaalignment-1)); hd->livebuffer[i] = (char *)((uintptr)(hd->livebuffer_org[i] + (config.dmaalignment-1)) & ~(uintptr)(config.dmaalignment-1)); if(!hd->livebuffer_org[i]) { printf("malloc(%d) livebuffer %d failed\n", config.vbuffersize + config.abuffersize + (config.dmaalignment-1), i); loop_exit(hd); return FALSE; } if(config.ancbuffersize && hd->bancstreamer) { hd->ancbuffer_org[i] = malloc(config.ancbuffersize + (config.dmaalignment-1)); hd->ancbuffer[i] = (char *)((uintptr)(hd->ancbuffer_org[i] + (config.dmaalignment-1)) & ~(uintptr)(config.dmaalignment-1)); if(!hd->ancbuffer_org[i]) { printf("malloc(%d) ancbuffer %d failed\n", config.ancbuffersize + (config.dmaalignment-1), i); loop_exit(hd); return FALSE; } } } // Allocate sufficient memory for video and audio data. hd->blackbuffer_org = malloc(config.vbuffersize + config.abuffersize + (config.dmaalignment-1)); hd->blackbuffer = (char *)((uintptr)(hd->blackbuffer_org + (config.dmaalignment-1)) & ~(uintptr)(config.dmaalignment-1)); if(!hd->blackbuffer_org) { printf("malloc(%d) blackbuffer failed\n", config.vbuffersize + config.abuffersize + (config.dmaalignment-1)); loop_exit(hd); return FALSE; } memset(hd->blackbuffer_org, 0, config.vbuffersize + config.abuffersize + (config.dmaalignment-1)); // Allocate sufficient memory for video and audio data. hd->nobuffer_org = malloc(config.vbuffersize + config.abuffersize + (config.dmaalignment-1)); hd->nobuffer = (char *)((uintptr)(hd->nobuffer_org + (config.dmaalignment-1)) & ~(uintptr)(config.dmaalignment-1)); if(!hd->nobuffer_org) { printf("malloc(%d) nobuffer failed\n", config.vbuffersize + config.abuffersize + (config.dmaalignment-1)); loop_exit(hd); return FALSE; } memset(hd->nobuffer_org, 0xff, config.vbuffersize + config.abuffersize + (config.dmaalignment-1)); dvs_mutex_init(&hd->common.lock); dvs_cond_init(&hd->common.ready); return TRUE; }