int main(int argc, char ** argv) { sv_handle * sv = NULL; int res = SV_OK; int bsavemode; int bhosttransfer; int bsetbuffersize = 0; int nframes; sv_storageinfo storage; char * buffer; char * buffer_org; int buffersize; int us; int i, j; #ifdef WIN32 LARGE_INTEGER frequency; LARGE_INTEGER timestart; LARGE_INTEGER timeend; QueryPerformanceFrequency(&frequency); #else struct timeval timestart; struct timeval timeend; struct timezone tz; #endif if(argc < 2) { usage(); return -1; } if(!strcmp(argv[1], "load")) { bsavemode = 0; bhosttransfer = 1; } else if(!strcmp(argv[1], "save")) { bsavemode = 1; bhosttransfer = 1; } else if(!strcmp(argv[1], "read")) { bsavemode = 0; bhosttransfer = 0; } else if(!strcmp(argv[1], "write")) { bsavemode = 1; bhosttransfer = 0; } else { usage(); return -1; } #ifndef WIN32 signal(SIGINT, signal_handler); signal(SIGKILL, signal_handler); #endif res = sv_openex(&sv, "", SV_OPENPROGRAM_DEMOPROGRAM, SV_OPENTYPE_DEFAULT, 0, 0); if(res != SV_OK) { printf("dmaspeed: Error '%s' opening video device", sv_geterrortext(res)); return -1; } res = sv_storage_status(sv, 0, NULL, &storage, sizeof(storage), 0); if(bhosttransfer) { buffersize = storage.fieldsize[0] + storage.fieldsize[1]; if(argc >= 3) { nframes = atoi(argv[2]); } else { nframes = 10; } } else { if(argc >= 3) { buffersize = atoi(argv[2]); if(buffersize == 0) { buffersize = strtol(argv[2], NULL, 16); } buffersize = buffersize & ~(ALIGNMENT - 1); bsetbuffersize = 1; } else { buffersize = 0x200000; } nframes = 1; } buffer_org = malloc(buffersize + ALIGNMENT + alignment[0]); buffer = (void*)(((uintptr)buffer_org + ALIGNMENT - 1) & ~(ALIGNMENT-1)); if(buffer == NULL) { fprintf(stderr, "dmaspeed: Failure to allocate video buffer\n"); res = SV_ERROR_MALLOC; } if(res == SV_OK) { if(bhosttransfer) { if(bsavemode) { printf("dmaspeed: frames %d frames, Device -> CPUMemory\n", nframes); } else { printf("dmaspeed: frames %d frames, CPUMemory -> Device\n", nframes); } printf("dmaspeed: framesize %d\n", buffersize); printf("dmaspeed: totalsize %d bytes total\n", nframes * buffersize); #ifdef WIN32 QueryPerformanceCounter(×tart); #else gettimeofday(×tart, &tz); #endif res = sv_transfertest(sv, bsavemode, buffer, buffersize, 0, nframes, storage.storagexsize, storage.storageysize, storage.nbits); #ifdef WIN32 QueryPerformanceCounter(&timeend); #else gettimeofday(&timeend, &tz); #endif if(res == SV_ERROR_PARAMETER) { printf("dmaspeed: returned SV_ERROR_PARAMTER, did you specify more frames than in memory ?\n"); } else if(res == SV_OK) { #ifdef WIN32 #ifdef VERBOSE printf("dmaspeed: frequency %d\n", (int)frequency.QuadPart); printf("dmaspeed: time %d\n", (int)(timeend.QuadPart - timestart.QuadPart)); #endif if(frequency.QuadPart) { us = (int)(((timeend.QuadPart - timestart.QuadPart) * 1000000) / frequency.QuadPart); } else { us = 0; } #else us = (int)((timeend.tv_sec * 1000000 + timeend.tv_usec) - (timestart.tv_sec * 1000000 + timestart.tv_usec)); #ifdef VERBOSE printf("dmaspeed: frequency %d\n", 1000000); printf("dmaspeed: time %d\n", us); #endif #endif if(us) { printf("dmaspeed: %d us %d B/s %d MB/s\n", us, (int)(((int64)nframes * buffersize * 1000000) / us), (int)(((int64)nframes * buffersize) / us)); } else { printf("dmaspeed: Error 0 us execution time ?\n"); } } } else { sv_memory_dma(sv, bsavemode, (void*)((uintptr)buffer), 0x100000, buffersize, NULL); for(i = 0; (res == SV_OK) && (i < arraysize(alignment)); i++) { #ifdef WIN32 QueryPerformanceCounter(×tart); #else gettimeofday(×tart, &tz); #endif if(bsetbuffersize) { res = sv_memory_dma(sv, bsavemode, (void*)((uintptr)buffer+alignment[i]), 0x100000, buffersize, NULL); } else { res = sv_memory_dma(sv, bsavemode, (void*)((uintptr)buffer), 0x100000, buffersize, NULL); } if((res != SV_OK) && (res != SV_ERROR_BUFFER_NOTALIGNED)) { fprintf(stderr, "sv_memory_dma failed: "); sv_errorprint(sv, res); } #ifdef WIN32 QueryPerformanceCounter(&timeend); if(frequency.QuadPart) { us = (int)(((timeend.QuadPart - timestart.QuadPart) * 1000000) / frequency.QuadPart); } else { us = 0; } #else gettimeofday(&timeend, &tz); us = (int)((timeend.tv_sec * 1000000 + timeend.tv_usec) - (timestart.tv_sec * 1000000 + timestart.tv_usec)); #endif resultus[i] = us; } j = i - 1; if(res == SV_ERROR_BUFFER_NOTALIGNED) { res = SV_OK; } if(bsetbuffersize) { for(i = 0; (i < arraysize(alignment)) && (i < j); i++) { if(resultus[i]) { printf("dmaspeed %3d e6/s alignment:%08x/%6d time %d us\n", buffersize / resultus[i], alignment[i], alignment[i], resultus[i]); } else { printf("dmaspeed %3d e6/s alignment:%08x/%6d time %d us ****\n", 0, alignment[i], alignment[i], 0); } } } else { for(us = 0, i = 0; (i < arraysize(alignment)) && (i < j); i++) { us += resultus[i]; } printf("Transferspeed: %3d e6/s %s\n", (int)(buffersize / (us / arraysize(alignment))), bsavemode?"CPUMemory->Device":"Device->CPUMemory"); } } } else { printf("dmaspeed: returned %s\n", sv_geterrortext(res)); } sv_close(sv); free(buffer_org); if(res != SV_OK) { sv_errorprint(sv, res); } if(res == SV_OK) { return 0; } else { return -1; } }
// card number passed as void * (using cast) static void * sdi_monitor(void *arg) { long card = (long)arg; sv_handle *sv = a_sv[card]; sv_fifo *poutput; sv_info status_info; sv_storageinfo storage_info; printf("card = %ld\n", card); SV_CHECK( sv_status( sv, &status_info) ); SV_CHECK( sv_storage_status(sv, 0, NULL, &storage_info, sizeof(storage_info), 0) ); SV_CHECK( sv_fifo_init( sv, &poutput, // FIFO handle FALSE, // bInput (FALSE for playback) TRUE, // bShared (TRUE for input/output share memory) TRUE, // bDMA FALSE, // reserved 0) ); // nFrames (0 means use maximum) SV_CHECK( sv_fifo_start(sv, poutput) ); // Loop forever reading frames and displaying. // This will not use 99% CPU since sv_fifo_getbuffer() will block // until a hardware buffer frame is available. int last_res = -1; while (1) { int res; if ((res = read_picture(card, sv, poutput)) != SV_OK) { // Display error only when things change if (res != last_res) { fprintf(stderr, "card %ld: failed to capture video: (%d) %s\n", card, res, res == SV_ERROR_INPUT_VIDEO_NOSIGNAL ? "INPUT_VIDEO_NOSIGNAL" : sv_geterrortext(res)); // reset FIFO if error indicates FIFO problem if (res == SV_ERROR_FIFO_PUTBUFFER) { fprintf(stderr, "SV_ERROR_FIFO_PUTBUFFER: restarting fifo\n"); SV_CHECK( sv_fifo_reset(sv, poutput) ); SV_CHECK( sv_fifo_start(sv, poutput) ); } } last_res = res; usleep( 2 * 1000 * 1000); // 2 second poll continue; } // Only display OK message once if (res != last_res && res == SV_OK) { fprintf(stderr, "card %ld: Video signal OK\n", card); } last_res = res; } return NULL; }
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; }