#include <iostream>
#include <unistd.h>
#include "ccreceiver.h"

//cCcReceiver::cCcReceiver(int Ca, int Vpid)
//:cReceiver(Ca, -1, 1, Vpid), cThread("cc receiver")
cCcReceiver::cCcReceiver(int Ca, int Vpid, int Apid[], int Dpid[])
:cReceiver(Ca, -1, Vpid, Apid, Dpid, NULL), cThread("cc receiver")
{
  dprint(2, "cCcReceiver::cCcReceiver()");
  cMutexLock lock(&m_Mutex);
  m_Active = false;
  m_VideoPid = Vpid;  
  m_parser = NULL;
  m_lastPacketSize = -1;
  m_queue_size = 0;
}
 
cCcReceiver::~cCcReceiver(void)
{
  dprint(2, "cCcReceiver::~cCcReceiver()");
  Detach();
  cMutexLock lock(&m_Mutex);
  if (m_Active) {
     m_Active = false;
     if(m_parser!=NULL)
        	delete m_parser;
     Cancel(0);
     }
}

void cCcReceiver::Action(void)
{
  int t0;
  byte data[READ_BUFFER];
  int len = 0;
  dprint(1, "cCcReceiver::Action()");
  m_Active = true;
  while (m_Active) {
	//cMutexLock lock(&m_Mutex);
        t0 = time_ms();
        len = GetUserData((byte *)&data);
        dprint(3, "cCcReceiver::Action() loop (%d bytes)", len);
        if(len>0){		
        	while(m_parser->ParseBuffer(data, len));	
		m_parser->InitParser();
	}
	
						
        cCondWait::SleepMs(RECEIVER_FREQ - (time_ms() - t0));
    }
}

void cCcReceiver::Activate(bool On)
{
  dprint(2, "cCcReceiver::Activate()");
  if (On) {
     if (!m_Active){
	cMutexLock lock(&m_Mutex);
        Start();
        if(m_parser!=NULL)
        	delete m_parser;
        m_parser = new cCCExtractor();
        m_parser->Init(sizeof(READ_BUFFER));
      }
  }
  else if (m_Active) {
     cMutexLock lock(&m_Mutex);
     m_Active = false;
     delete m_parser;
     m_parser = NULL;
     Cancel(0);
  }
   
}

CC_Data *cCcReceiver::GetCC(){
	dprint(3,"cCCReceiver::getCC\n");
	if(m_parser==NULL){
		dprint(2, "Queue is empty.\n");
		return NULL;
	}
	return m_parser->PopCC();
}

void cCcReceiver::Receive(uchar *Data, int Length)
{
	if(m_lastPacketSize!=Length){
		dprint(1, "CC: Packet size: %d bytes\n", Length);
		m_lastPacketSize=Length;
	}
	if (Length == TS_SIZE) {
     //int pid = ((Data[1] & 0x1f) << 8) | (Data[2]);
     /* the following originates from libdvbmpeg: */
     if (!(Data[3] & PAYLOAD)) {
        return;
        }
     uint8_t off = 0;
     if (Data[3] & ADAPT_FIELD) {
        off = Data[4] + 1;
        }
     if (Data[1] & PAY_START) {
        uint8_t *sb = Data + 4 + off;
        if (sb[7] & PTS_DTS_FLAGS) {
           uint8_t *pay = sb + sb[8] + 9; 
           int l = TS_SIZE - 13 - off - sb[8];
           if((m_parser != NULL) && (l>0)){
		dprint(5, "Data stored (%d/%d).\n", m_queue_size, Length);
		StoreStream(pay, l);					 }
	   }
     /* end */
     }
  }	
}

bool cCcReceiver::StoreStream(byte *data, int len){
	dprint(4, "StoreStream\n");
	cMutexLock lock(&m_Mutex_Data);
	int size = len;
	
	if((len + m_queue_size)>=READ_BUFFER)
		size = READ_BUFFER - m_queue_size;		
	
	for(int i=0; i<size; i++)
		m_queue[m_queue_size++] = data[i];
		
	return (size == len);
}

int cCcReceiver::GetUserData(byte *store){
	dprint(4, "cCcReceiver::GetUserData()");
	cMutexLock lock(&m_Mutex_Data);
	dprint(4, "cCcReceiver::GetUserData() - locked");
	int r = m_queue_size;
	for(int i=0; i< m_queue_size; i++)
		store[i] = m_queue[i];
	m_queue_size = 0;
	dprint(4, "cCcReceiver::GetUserData() - finnished");
	return r;	
}
