Example #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;
}
Example #2
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;
}