/*
 * cal-mpeg.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#include "malloc.h"

#include "cal-mpeg.h"


// --- cCalPES ---------------------------------------------------------------

cCalPES::cCalPES(void) {
  data = NULL;
  length = 0;
  };
  
cCalPES::cCalPES(const uchar *Data, int Length) {
  data = NULL;
  length = 0;
  if((Length < 3) || !(Data[0] == 0 && Data[1] == 0 && Data[2] == 1))
    return;
  if(Length < 6)
    return;
  length = (Data[4]<<8) + Data[5] + 6;
  if(Length < length)
    return;
  if(((Data[6]>>6) & 3) != 2)
    return;
  data = (uchar *)malloc(length);
  memcpy(data, Data, length);
  };

cCalPES::~cCalPES() {
  if(data) {
    free(data);
    data = NULL;
  }
  };
 
//uchar *cCalPES::GetPacket(void) { return data; } {
//  };

pts_t cCalPES::GetPTS(void) {
  if(!HasPTS())
    return NO_PTS;
  if(((data[9]>>5) & 1) != 1)
    return INVALID_PTS;
  
  if((data[9] & 1) != 1)
    return INVALID_PTS;
  if((data[11] & 1) != 1)
    return INVALID_PTS;
  if((data[13] & 1) != 1)
    return INVALID_PTS;

  pts_t pts = (pts_t)(((data[9]>>1LL) & 7LL)<<30LL) + (data[10]<<22LL) + (((data[11]>>1LL) & 127LL)<<15LL) +
              (data[12]<<7LL) + ((data[13]>>1LL) & 127LL);
  return pts;
  };

pts_t cCalPES::GetDTS(void) {
  if(!HasDTS())
    return NO_DTS;
  if(((data[14]>>4) & 1) != 1)
    return INVALID_DTS;
  
  if((data[14] & 1) != 1)
    return INVALID_DTS;
  if((data[16] & 1) != 1)
    return INVALID_DTS;
  if((data[18] & 1) != 1)
    return INVALID_DTS;

  pts_t dts = (pts_t)(((data[14]>>1LL) & 7LL)<<30LL) + (data[15]<<22LL) + (((data[16]>>1LL) & 127LL)<<15) +
              (data[17]<<7LL) + ((data[18]>>1LL) & 127LL);
  return dts;
  };
  
void cCalPES::GetPayload(uchar *Data, int& Length) {
  int pos = data[8] + 9;
  Length = GetLength() - pos;
  memcpy(Data, &data[pos], Length);
  };

void cCalPES::SetPTS(pts_t Pts) {
  data[9] = (data[9]&0xF1) + ((Pts>>30LL & 7LL)<<1LL);  // F1 means 11110001 in binary representation
  data[10] = Pts>>22LL & 255LL;
  data[11] = 1 + ((Pts>>15LL & 127LL)<<1LL);
  data[12] = Pts>>7LL & 255LL;
  data[13] = 1 + ((Pts & 127LL)<<1LL);
  };


// ---------------------------------------------------------------------------

cString PTSToHMST(pts_t pts, bool withT) {
  char buffer[16];
  if(pts == NO_PTS || pts == INVALID_PTS) {
    snprintf(buffer, sizeof(buffer), "%s", (pts==NO_PTS) ? "Not available" : "Invalid" );
    return buffer;
  }
  int t = ((pts_t)(pts/90)) % 1000;
  int s = ((pts_t)pts/90000);
  int m = s / 60 % 60;
  int h = s / 3600;
  s %= 60;
  if(withT) {
    snprintf(buffer, sizeof(buffer), "%d:%02d:%02d.%03d", h, m, s, t);
  } else {
    snprintf(buffer, sizeof(buffer), "%d:%02d:%02d", h, m, s);
  }
  return buffer;
  };

cString PTSToHMSF(pts_t pts, bool withF) {
  char buffer[16];
  if(pts == NO_PTS || pts == INVALID_PTS) {
    snprintf(buffer, sizeof(buffer), "%s", (pts==NO_PTS) ? "Not available" : "Invalid" );
    return buffer;
  }
  int f = (((pts_t)(pts/90/40)) % 25) + 1;
  int s = ((pts_t)pts/90000);
  int m = s / 60 % 60;
  int h = s / 3600;
  s %= 60;
  if(withF) {
    snprintf(buffer, sizeof(buffer), "%d:%02d:%02d.%02d", h, m, s, f);
  } else {
    snprintf(buffer, sizeof(buffer), "%d:%02d:%02d", h, m, s);
  }
  return buffer;
  };
