

#include "Encoder2250.hh"
#include "s2250mid.h"
#include <string.h>


#define BITRATE 800000
#define MY_ENCODER_BOARD 0
#define NTSC 		 0
#define VIDEO_BUFF_SIZE 128000

Encoder2250*
Encoder2250::createNew(UsageEnvironment& env,
			EncoderParameters params) {
  return new Encoder2250(env, params);
}

Encoder2250::Encoder2250(UsageEnvironment& env,
			   EncoderParameters params)
  : FramedSource(env), fParams(params) {
  // Any initialization of the device would be done here
  
  printf("Opening connection to Video Encoder\n");
    int ret = SN_OpenBoard(MY_ENCODER_BOARD);
    if( ret != 0)
    {
        printf("Error opening connnection to Encoder board\n");
        SN_CloseBoard(MY_ENCODER_BOARD);
        
    }
    

	
   printf("Setting video standard to NTSC\n");
   if(SN_SetVideoSystem(MY_ENCODER_BOARD,NTSC) < 0 )
	{
	  printf("Error Setting Video Standard to NTSC\n");
      	  SN_CloseBoard(MY_ENCODER_BOARD);
	 
        }


    printf("Setting video input\n");

    if(SN_SetVideoSource(MY_ENCODER_BOARD,1) != 0)
     {
	printf("Error Setting Video Input Type\n");
        SN_CloseBoard(MY_ENCODER_BOARD);
       
     }	 


    printf("Setting Chip Settings \n");
    // set motion jpeg, full size, NTSC, 4MBit/s (Iframe setting N/A for MOTIONJPEG)
    if( SN_SetBasicChipSettings(0, MPEG2, 1, MID2250_VIDSYS_NTSC, BITRATE, 1) !=0)
	{
	  printf("Error Setting up Chip\r");
	  
	}
  
    SN_StartStream(MY_ENCODER_BOARD); 
  
   
}

Encoder2250::~Encoder2250(){}
    
	
	TFrameInfo FrameInfo;
    struct timeval PresTime;

 void Encoder2250::doGetNextFrame() {

  // Arrange here for our "deliverFrame" member function to be called
  // when the next frame of data becomes available from the device.
  // This must be done in a non-blocking fashion - i.e., so that we
  // return immediately from this function even if no data is
  // currently available.
  //
  // If the device can be implemented as a readable socket, then one easy
  // way to do this is using a call to
  //     envir().taskScheduler().turnOnBackgroundReadHandling( ... )
  // (See examples of this call in the "liveMedia" directory.)

  // If, for some reason, the source device stops being readable
  // (e.g., it gets closed), then you do the following:
 // if (0 /* the source stops being readable */) {
  //  handleClosure(this);
  //  return;
  //}

	//unsigned char buffer[VIDEO_BUFF_SIZE];
	
	fMaxSize = VIDEO_BUFF_SIZE; //deliverFrame()in param
    printf("Getting Frame...\n");

		int i = 0, Vid = 0; 
   	 while( i < 10000)
   	 {
        		Vid = SN_GetOneFrame( 0, buffer, VIDEO_BUFF_SIZE, &FrameInfo);
       		 if( Vid == 0)
           		 break;
        i++;
        usleep(1);
   	 }
     if( Vid != 0)
       {
   	     printf("failed to get one frame\n");
   	     SN_StopStream(MY_ENCODER_BOARD);
   	     SN_CloseBoard(MY_ENCODER_BOARD);
   	     
   	   }
	
	CallBack(buffer,FrameInfo.VideoLength);
	
}

void Encoder2250::deliverFrame(unsigned char bufferIn[], size_t len) {
// This would be called when new frame data is available from the device.
  // This function should deliver the next frame of data from the device,
  // using the following parameters (class members):
  // 'in' parameters (these should *not* be modified by this function):
  //     fTo: The frame data is copied to this address.
  //         (Note that the variable "fTo" is *not* modified.  Instead,
  //          the frame data is copied to the address pointed to by "fTo".)
  //     fMaxSize: This is the maximum number of bytes that can be copied
  //         (If the actual frame is larger than this, then it should
  //          be truncated, and "fNumTruncatedBytes" set accordingly.)
  // 'out' parameters (these are modified by this function):
  //     fFrameSize: Should be set to the delivered frame size (<= fMaxSize).
  //     fNumTruncatedBytes: Should be set iff the delivered frame would have been
  //         bigger than "fMaxSize", in which case it's set to the number of bytes
  //         that have been omitted.
  //     fPresentationTime: Should be set to the frame's presentation time
  //         (seconds, microseconds).
  //     fDurationInMicroseconds: Should be set to the frame's duration, if known.
  
  
  //if (!isCurrentlyAwaitingData()) return; // we're not ready for the data yet

  // Deliver the data here:
	//SN_GetOneFrame( 0, buffer, VIDEO_BUFF_SIZE, &FrameInfo);
	
	
	printf("Delivering Bytes...\n");
	memmove(fTo, bufferIn, len); //deliverFrame()in param 
	
	
	fFrameSize = len;
	
	nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
				(TaskFunc*)FramedSource::afterGetting, this);
				
	
  // After delivering the data, inform the reader that it is now available:
  //FramedSource::afterGetting(this);

}

void Encoder2250::CallBack(unsigned char bufferIn[], size_t len) {

deliverFrame(bufferIn, len);

}
