/*
   vector.c
*/

#include "videoport.h"

int main(int argc, char **argv)
{
  videoport p;
  int direction = (tolower(*argv[1]) == 'v') ?
    VIDEOPORT_DIRECTION_VM : VIDEOPORT_DIRECTION_MV;
  char *filename = argv[2];
  int issue_count;
  diskperformance diskperf = diskperformance_open();
  int fd;
  int nbytes, totalbytes;
  struct dioattr dioinfo;
  int vector_chunksize;
  int vector_memalign;
  int nvectors = 10; /* number of fields per readv/writev  */
  videofield **fields;
  struct iovec *vectors;

  NC(p = videoport_open(direction, 30, VIDEOPORT_ADVISE_NOACCESS));

  NC(fields = malloc(nvectors * sizeof(videofield *)));
  NC(vectors = malloc(nvectors * sizeof(struct iovec)));
  
  if (direction == VIDEOPORT_DIRECTION_VM)
    {
      printf("writing input video to file %s\n", filename);
      OC(fd = open(filename, O_RDWR|O_TRUNC|O_CREAT|O_DIRECT, 0644));
    }
  else /* direction == VIDEOPORT_DIRECTION_MV */
    {
      printf("reading video from file %s for output\n", filename);
      OC(fd = open(filename, O_RDONLY|O_DIRECT, 0644));
    }

  nbytes = p->max_valid_bytes_per_field;
  totalbytes = nbytes * nvectors;

  /* get direct I/O constraints for this fd */
  OC(fcntl(fd, F_DIOINFO, &dioinfo));
  vector_chunksize = max(dioinfo.d_miniosz, getpagesize());
  vector_memalign = max(dioinfo.d_mem, getpagesize());
  assert(totalbytes >= vector_chunksize);
  assert(totalbytes <= dioinfo.d_maxiosz);
  assert((nbytes % vector_chunksize) == 0);

  issue_count = 0;
  diskperformance_datapoint(diskperf, 0, p);

  for(;;)
    {
      int i, rc;
      
      for(i=0; i < nvectors; i++)
        {
          videoport_wait_for_space_or_data(p);
          fields[i] = videoport_get_one_field(p);
          assert((((uintptr_t)fields[i]->pixels) % vector_memalign) == 0);
          vectors[i].iov_base = fields[i]->pixels;
          vectors[i].iov_len = nbytes;
        }
      
      if (direction == VIDEOPORT_DIRECTION_VM)
        {
          OC(rc = writev(fd, vectors, nvectors));
        }
      else
        {
          OC(rc = readv(fd, vectors, nvectors));
        }
      if (rc != totalbytes) error_exit("EOF or out of disk space");
      
      ++issue_count;
      diskperformance_datapoint(diskperf, 
                                ((off64_t)issue_count) * totalbytes, p);

      for(i=0; i < nvectors; i++)
        {
          videoport_put_one_field(p, fields[i]);
        }
    }
}

  

