Beispiel #1
0
// 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;
}
Beispiel #2
0
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(&timestart);
#else
      gettimeofday(&timestart, &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(&timestart);
#else
        gettimeofday(&timestart, &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;
  }
}
Beispiel #3
0
void * loop_in(void * arg) 
{
  loop_handle * hd = (loop_handle *) arg;
  sv_fifo_bufferinfo infosrc;
  sv_fifo_info status_src;
  unsigned int lastdrop_src = (unsigned int) ~0;
  int bufferid;
  int res = SV_OK;

  /*
  // Start the input FIFO.
  */
  res = sv_fifo_start(hd->svsrc, hd->fifosrc);
  if(res != SV_OK)  {
    printf("sv_fifo_start(src) failed %d '%s'\n", res, sv_geterrortext(res));
    hd->running = FALSE;
  }

  while (hd->running) {
    /*
    // >>> Handle input FIFO <<<
    */
    do {
      res = sv_fifo_getbuffer(hd->svsrc, hd->fifosrc, &hd->bufsrc, NULL,
        SV_FIFO_FLAG_NODMAADDR |
        (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0) |
        (hd->bvideoonly ? SV_FIFO_FLAG_VIDEOONLY : 0) |
        (hd->baudioonly ? SV_FIFO_FLAG_AUDIOONLY : 0) |
        (hd->bplayback ? SV_FIFO_FLAG_FLUSH : 0)
      );

      switch(res) {
      case SV_ERROR_NOCARRIER:
      case SV_ERROR_INPUT_VIDEO_NOSIGNAL:
      case SV_ERROR_INPUT_VIDEO_RASTER:
      case SV_ERROR_INPUT_VIDEO_DETECTING:
      case SV_ERROR_INPUT_KEY_NOSIGNAL:
      case SV_ERROR_INPUT_KEY_RASTER:
        printf("v");	// Inform user about missing video
        fflush(stdout);
        res = SV_ACTIVE;
        break;
      case SV_ERROR_INPUT_AUDIO_NOAIV:
      case SV_ERROR_INPUT_AUDIO_NOAESEBU:
        // In these two cases, getbuffer returned a valid buffer.
        // So, we can continue without audio.
        printf("a");	// Inform user about missing audio
        fflush(stdout);
        res = SV_OK;
        break;
      case SV_ERROR_VSYNCPASSED:
        printf("NOTE: vsyncpassed possibly caused by signal disconnect\n");
        res = SV_ACTIVE;
        break;
      default:;
      }

      if(res == SV_ACTIVE) {
        // wait for next vsync and try again
        sv_fifo_vsyncwait(hd->svsrc, hd->fifosrc);
      }
    } while(res == SV_ACTIVE && hd->running);

    if (res != SV_OK)  {
      printf("sv_fifo_getbuffer(src) failed %d '%s'\n", res, sv_geterrortext(res));
      hd->running = FALSE;
      break;
    }

    dvs_mutex_enter(&hd->common.lock);
    bufferid = get_free_bufferid(hd);
    dvs_mutex_leave(&hd->common.lock);

    fill_buffer(hd, TRUE, hd->bufsrc, bufferid);

    if(hd->banc && (bufferid >= 0)) {
      //Get list pointer
      anc_element_t * current_element = &hd->anclist[bufferid];

      //If there are valid packets delete them
      if( current_element->next ) {
        //Delete all elements in list
        delete_element( bufferid, current_element->next );
        //Set first element to zero
        memset( current_element, 0, sizeof(anc_element_t) );
      }
      
      //Try to get anc packets
      while( res==SV_OK ) {
        res = sv_fifo_anc( hd->svsrc, hd->fifosrc, hd->bufsrc, &current_element->ancbuffer );
        if( res == SV_OK ) {
          current_element->valid = 1;

          //Log
          if( hd->bverbose ) {
            printf("Recorded anc_element. Buffer:%d, DID:0x%x, SDID:0x%x\n", bufferid, current_element->ancbuffer.did, current_element->ancbuffer.sdid );
          }

          //I need to allocate one more packet buffer
          current_element->next = malloc( sizeof( anc_element_t ));
          if( current_element->next != 0 )
          {
            //Set all values to zero
            memset( current_element->next, 0, sizeof( anc_element_t ));
            
            //Build the list
            current_element->next->prev = current_element;
            current_element = current_element->next;
          } else {
            printf("malloc failed %d '%s'\n", res, sv_geterrortext(res));
            hd->running = FALSE;
          }
        }
      }
      // This errorcode shows that no more packets are in the frame
      if( res == SV_ERROR_NOTAVAILABLE ) {
        res = SV_OK;
      }
    }

    res = sv_fifo_putbuffer(hd->svsrc, hd->fifosrc, hd->bufsrc, &infosrc);
    if(res != SV_OK)  {
      printf("sv_fifo_putbuffer(src) failed %d '%s'\n", res, sv_geterrortext(res));
      hd->running = FALSE;
      break;
    }

    res = sv_fifo_status(hd->svsrc, hd->fifosrc, &status_src);
    if(res != SV_OK)  {
      printf("sv_fifo_status(src) failed %d '%s'\n", res, sv_geterrortext(res));
      hd->running = FALSE;
      break;
    }

    // Save input delay
    hd->indelay_info  = status_src.recordtick - infosrc.when;
    hd->inavail_info  = status_src.availbuffers; 
    
    if(hd->bverbose || ((unsigned int)status_src.dropped > lastdrop_src)) {
      printf("ID %2d - in  %06d %d %d %d (%u)\n", bufferid, infosrc.when, status_src.nbuffers, status_src.availbuffers, status_src.dropped - lastdrop_src, infosrc.clock_low);
    }

    // Report dropped frames in input FIFO.
    if((unsigned int)status_src.dropped > lastdrop_src) {
      printf("input fifo dropped - delay might have changed\n");
    }
    lastdrop_src = status_src.dropped;

    dvs_mutex_enter(&hd->common.lock);
    if(bufferid >= 0) {
      hd->common.inputtick[bufferid] = infosrc.when;
    }
    dvs_mutex_leave(&hd->common.lock);

    /*
    // Signal that a new input buffer is ready
    */
    dvs_cond_broadcast(&hd->common.ready, &hd->common.lock, FALSE);
  }

  res = sv_fifo_stop(hd->svsrc, hd->fifosrc, 0);
  if(res != SV_OK)  {
    printf("sv_fifo_stop(src) failed %d '%s'\n", res, sv_geterrortext(res));
  }

  hd->exitcode = TRUE;
  dvs_thread_exit(&hd->exitcode, &hd->finish);

  return NULL;
}
Beispiel #4
0
void * loop_out(void * arg) 
{
  loop_handle * hd = (loop_handle *) arg;
  sv_fifo_bufferinfo infodst;
  sv_fifo_info status_dst;
  int lastdrop_dst = 0;
  int displaytick = 0;
  int res = SV_OK;
  int bufferid;
  int fifo_running = FALSE;
  int flip = 0;

  dvs_cond_wait(&hd->common.ready, &hd->common.lock, FALSE);

  while (hd->running) {
    // check for sync is detected and if genlocked when sync is on the refin
    while((res == SV_ERROR_SYNC_MISSING) || sv_fifo_sanitycheck(hd->svdst, hd->fifodst) == SV_ERROR_SYNC_MISSING &&
               hd->running)
    {
      if(fifo_running) {
        fifo_running = FALSE;
        printf("WARNING: lost genlock! Output fifo stopped.\n");
        res = sv_fifo_stop(hd->svdst, hd->fifodst, SV_FIFO_FLAG_FLUSH);
        if(res != SV_OK)  {
          printf("sv_fifo_stop(dst) failed %d '%s'\n", res, sv_geterrortext(res));
          hd->running = FALSE;
        }
        res = sv_fifo_reset(hd->svdst, hd->fifodst);
        if(res != SV_OK)  {
          printf("sv_fifo_reset(dst) failed %d '%s'\n", res, sv_geterrortext(res));
          hd->running = FALSE;
        }
      }

      sv_fifo_vsyncwait(hd->svdst, hd->fifodst);
    }

    if(!fifo_running) {
      printf("====> Restarting output fifo. <=====\n");
#if 0
      res = sv_fifo_free(hd->svdst, hd->fifodst);
      if(res != SV_OK)  {
        printf("sv_fifo_reset(dst) failed %d '%s'\n", res, sv_geterrortext(res));
        hd->running = FALSE;
      }

      // Init output FIFO.
      res = sv_fifo_init(hd->svdst, &hd->fifodst, FALSE, FALSE, TRUE, (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0), 0 );
      if(res != SV_OK)  {
        printf("sv_fifo_init(dst) failed %d '%s'\n", res, sv_geterrortext(res));
        hd->running = FALSE;
        return;
      }

      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));
      }
#endif

      res = sv_fifo_startex(hd->svdst, hd->fifodst, &displaytick, NULL, NULL, NULL);
      if(res != SV_OK)  {
        printf("sv_fifo_start(dst) failed %d '%s'\n", res, sv_geterrortext(res));
        hd->running = FALSE;
      }
      fifo_running = TRUE;
    }

    res = sv_fifo_getbuffer(hd->svdst, hd->fifodst, &hd->bufdst, NULL,
      SV_FIFO_FLAG_NODMAADDR |
      (hd->bancstreamer ? SV_FIFO_FLAG_ANC : 0) |
      (hd->bvideoonly ? SV_FIFO_FLAG_VIDEOONLY : 0) |
      (hd->baudioonly ? SV_FIFO_FLAG_AUDIOONLY : 0) |
      (hd->bfieldbased ? SV_FIFO_FLAG_FIELD : 0) |  // enable field-based mode
      (hd->bvideoonly ? 0 : SV_FIFO_FLAG_SETAUDIOSIZE) |
      (hd->bottom2top ? SV_FIFO_FLAG_STORAGEMODE : 0)
    );
    switch(res) {
      case SV_ERROR_SYNC_MISSING:
        continue;
        break;
      default:
        if(res != SV_OK)  {
          printf("sv_fifo_getbuffer(dst) failed %d '%s'\n", res, sv_geterrortext(res));
          hd->running = FALSE;
        }
        break;
    }

    if(hd->bottom2top) {
      hd->bufdst->storage.storagemode = hd->storage.videomode & (SV_MODE_COLOR_MASK|SV_MODE_NBIT_MASK|SV_MODE_STORAGE_FRAME|SV_MODE_STORAGE_BOTTOM2TOP);
      hd->bufdst->storage.xsize       = hd->storage.storagexsize;
      hd->bufdst->storage.ysize       = hd->storage.storageysize;

      if(flip) {
        hd->bufdst->storage.storagemode |= SV_MODE_STORAGE_BOTTOM2TOP;
      } else {
        hd->bufdst->storage.storagemode &= ~SV_MODE_STORAGE_BOTTOM2TOP;
      }

      flip = (displaytick / 100) & 1;
    }

    dvs_mutex_enter(&hd->common.lock);
    bufferid = get_bufferid(hd, displaytick, hd->ndelay );
    dvs_mutex_leave(&hd->common.lock);

    fill_buffer(hd, FALSE, hd->bufdst, bufferid);

    if(hd->banc && (bufferid >= 0)) {
      //Get list
      anc_element_t * current_element = &hd->anclist[bufferid];
       
      //Try to get anc packets
      while( current_element->valid ) {
        current_element->valid = 0;
        res = sv_fifo_anc( hd->svsrc, hd->fifodst, hd->bufdst, &current_element->ancbuffer );
        if( res == SV_OK ) {
          //Log
          if( hd->bverbose ) {
            printf("Displayed anc_element. Buffer:%d, DID:0x%x, SDID:0x%x\n", bufferid, current_element->ancbuffer.did, current_element->ancbuffer.sdid );
          }
          if( current_element->next ) {
            current_element = current_element->next;
          }
        }
      }
    }

    res = sv_fifo_putbuffer(hd->svdst, hd->fifodst, hd->bufdst, &infodst);
    if(res != SV_OK)  {
      printf("sv_fifo_putbuffer(dst) failed %d '%s'\n", res, sv_geterrortext(res));
      hd->running = FALSE;
      break;
    }

    // Calculate next output tick.
    displaytick = infodst.when + hd->vinterlace;

    res = sv_fifo_status(hd->svdst, hd->fifodst, &status_dst);
    if(res != SV_OK)  {
      printf("sv_fifo_status(dst) failed %d '%s'\n", res, sv_geterrortext(res));
      hd->running = FALSE;
      break;
    }

    // Save output delay
    hd->outdelay_info = infodst.when - status_dst.displaytick;
    
    if(!hd->bverbose) {
      printf("\rDmaloop: %s  in-delay:%2d/%d ticks  out-delay:%2d ticks              ", (bufferid!=-1) ? "running" : "no buffer", hd->indelay_info, hd->inavail_info, hd->outdelay_info);
    }

    if(hd->bverbose || (status_dst.dropped > lastdrop_dst)) {
      printf("ID %2d - out %06d %d %d %d (%u)\n", bufferid, infodst.when, status_dst.nbuffers, status_dst.availbuffers, status_dst.dropped - lastdrop_dst, infodst.clock_low);
    }

    // Report dropped frames in output FIFO.
    if(status_dst.dropped > lastdrop_dst) {
      printf("output fifo dropped - delay might have changed\n");
    }
    lastdrop_dst = status_dst.dropped;

    /*
     * Wait until I need a new buffer
     */
    if(hd->bfieldbased || hd->bdualsdi) {
      while(hd->running && ((status_dst.nbuffers - status_dst.availbuffers) > 3/*Fields*/)) {
        // Wait for next vsync
        res = sv_fifo_vsyncwait(hd->svdst, hd->fifodst);
        if(res != SV_OK)  {
          printf("sv_fifo_vsyncwait(dst) failed %d '%s'\n", res, sv_geterrortext(res));
	        hd->running = FALSE;  
        }
      
        // Check buffer count
        res = sv_fifo_status(hd->svdst, hd->fifodst, &status_dst);
        if(res != SV_OK)  {
          printf("sv_fifo_status(dst) failed %d '%s'\n", res, sv_geterrortext(res));
          hd->running = FALSE;  
        }
      }
    } else {
      while(hd->running && ((status_dst.nbuffers - status_dst.availbuffers) > 2 /*Frames*/)) {
        // Wait for next vsync
        res = sv_fifo_vsyncwait(hd->svdst, hd->fifodst);
        if(res != SV_OK) {
          printf("sv_fifo_vsyncwait(dst) failed %d '%s'\n", res, sv_geterrortext(res));
          hd->running = FALSE;
        }
            
        // Check buffer count
        res = sv_fifo_status(hd->svdst, hd->fifodst, &status_dst);
        if(res != SV_OK)  {
          printf("sv_fifo_status(dst) failed %d '%s'\n", res, sv_geterrortext(res));
          hd->running = FALSE;  
        }
      }
    }
  }

  res = sv_fifo_stop(hd->svdst, hd->fifodst, SV_FIFO_FLAG_FLUSH);
  if(res != SV_OK)  {
    printf("sv_fifo_stop(dst) failed %d '%s'\n", res, sv_geterrortext(res));
  }

  hd->exitcode = TRUE;
  dvs_thread_exit(&hd->exitcode, &hd->finish);

  return NULL;
}
Beispiel #5
0
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;
}