示例#1
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;
}
示例#2
0
//
// read_picture()
//
// Read from disk, write to dvs card
static int read_picture(int card, sv_handle *sv, sv_fifo *poutput)
{
    sv_fifo_buffer      *pbuffer;
    int                 res;
    char                frame[element_size];

    // Get sv memmory buffer
    if ((res = sv_fifo_getbuffer(sv, poutput, &pbuffer, NULL, 0)) != SV_OK)
    {
        return res;
    }

    // Increasing the size of dma.size does not get audio samples only 0x80's
    //
    // dma buffer is structured as follows
    //
    // video frame      offset= 0
    // audio ch. 0, 1   offset= pbuffer->audio[0].addr[0]
    // audio ch. 2, 3   offset= pbuffer->audio[0].addr[1]
    //
    pbuffer->dma.addr = (char *)frame;
    pbuffer->dma.size = element_size;       // video + audio

    int audio_size = 1920*2*4;
    char *video_buf = frame;
    char *audio_buf = frame + video_size;

    // if requested display black frames at start
    if (black_frames > 0 && black_frames_displayed < black_frames) {
        int i;
        for (i = 0; i < video_size; i+= 4) {
            video_buf[i+0] = 0x80;
            video_buf[i+1] = 0x80;
            video_buf[i+2] = 0x80;
            video_buf[i+3] = 0x80;
        }
        memcpy(video_buf, black_frame_buf, video_size);
        memset(audio_buf, 0, audio_size);
        memset(audio_buf + 0x4000, 0, audio_size);
        black_frames_displayed++;
    }
    else
    {
        int input_exhausted;
      READ_FROM_FILE:
        input_exhausted = 0;

        if ( fread(video_buf, video_size, 1, fp_video) != 1 )
        {
            if (feof(fp_video))
                input_exhausted = 1;
            else
                perror("fread from video file");
        }
        current_video_frame++;

        if (no_audio) {
            memset(audio_buf, 0, audio_size);
            memset(audio_buf + 0x4000, 0, audio_size);
        }
        else
        {
            if ( fread(audio_buf, audio_size, 1, fp_audio12) != 1 )
            {
                if (feof(fp_audio12))
                    input_exhausted = 1;
                else
                    perror("fread from audio 12 file");
            }
            if ( fread(audio_buf + 0x4000, audio_size, 1, fp_audio34) != 1 )
            {
                if (feof(fp_audio34))
                    input_exhausted = 1;
                else
                    perror("fread from audio 34 file");
            }
        }
        if (input_exhausted) {
            if (loop) {
                printf("Reached end of input, looping\n");
                fseeko(fp_video, frame_inpoint * video_size, SEEK_SET);
                current_video_frame = frame_inpoint;
                if (! no_audio) {
                    fseeko(fp_audio12, frame_inpoint * audio_size, SEEK_SET);
                    fseeko(fp_audio34, frame_inpoint * audio_size, SEEK_SET);
                }
                goto READ_FROM_FILE;
            }

            printf("Reached end of input\n");
            exit(0);
        }
        if (frame_outpoint > 0 && current_video_frame >= frame_outpoint) {
            fseeko(fp_video, frame_inpoint * video_size, SEEK_SET);
            current_video_frame = frame_inpoint;
            if (! no_audio) {
                fseeko(fp_audio12, frame_inpoint * audio_size, SEEK_SET);
                fseeko(fp_audio34, frame_inpoint * audio_size, SEEK_SET);
            }
        }
    }

    // set timecode
    // doesn't appear to work i.e. get output over SDI
    int dvs_timecode = int_to_dvs_tc(timecode);
    pbuffer->timecode.vitc_tc = dvs_timecode;
    pbuffer->timecode.vitc_tc2 = dvs_timecode | 0x80000000;     // set high bit for second field timecode

    // send the filled in buffer to the hardware
    SV_CHECK(sv_fifo_putbuffer(sv, poutput, pbuffer, NULL));

    if (verbose > 1)
    {
        // timecode:
        //   vitc_tc=268441105 vitc_tc2=-1879042543   for "10:00:16:11"

        printf("card %d:  element_size=%d vitc_tc=%08x vitc_tc2=%8x tc_int=%d\n",
                    card, element_size,
                    pbuffer->timecode.vitc_tc,
                    pbuffer->timecode.vitc_tc2,
                    timecode);
        fflush(stdout);
    }

    timecode++;

    return SV_OK;
}
示例#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;
}