⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cxx

📁 mcu for video conference test
💻 CXX
📖 第 1 页 / 共 4 页
字号:

BOOL IncomingAudio::Write(const void * buffer, PINDEX amount)
{
  PWaitAndSignal mutexW(audioChanMutex);
  
  if (!IsOpen())
    return FALSE;

  if (!delay.Delay(amount / 16))
    conn.OnIncomingAudio(buffer, amount);

  return TRUE;
}

BOOL IncomingAudio::Close()
{
	if (!IsOpen()) 
		return FALSE;

	PWaitAndSignal mutexA(audioChanMutex);
	os_handle = -1;
  return TRUE;
}

///////////////////////////////////////////////////////////////////////////

AudioBuffer::AudioBuffer()
  : bufferSize(PCM_BUFFER_SIZE)
{
  buffer = new BYTE[bufferSize];
  bufferStart = bufferLen = 0;
}

AudioBuffer::~AudioBuffer()
{
  delete[] buffer;
}

void AudioBuffer::Read(BYTE * data, PINDEX amount)
{
  if (amount == 0)
    return;

  PWaitAndSignal mutex(audioBufferMutex);
  
  if (bufferLen == 0) {
    memset(data, 0, amount); // nothing in the buffer. return silence
    return;
  }

  // fill output data block with silence if audiobuffer is
  // almost empty.
  if (amount > bufferLen) 
    memset(data + bufferLen, 0, amount - bufferLen);

  // only copy up to the amount of data remaining
  PINDEX copyLeft = PMIN(amount, bufferLen);

  // if buffer is wrapping, get first part
  if ((bufferStart + copyLeft) > bufferSize) {
    PINDEX toCopy = bufferSize - bufferStart;

    memcpy(data, buffer + bufferStart, toCopy);

    data        += toCopy;
    bufferLen   -= toCopy;
    copyLeft    -= toCopy;
    bufferStart = 0;
  }

  // get the remainder of the buffer
  if (copyLeft > 0) {

    memcpy(data, buffer + bufferStart, copyLeft);

    bufferLen -= copyLeft;
    bufferStart = (bufferStart + copyLeft) % bufferSize;
  }
}

void AudioBuffer::ReadAndMix(BYTE * data, PINDEX amount, PINDEX channels)
{
  if (amount == 0)
    return;

  PWaitAndSignal mutex(audioBufferMutex);
  
  if (bufferLen == 0) {
    // nothing in the buffer to mix.
    return;
  }

  // only mix up to the amount of data remaining
  PINDEX copyLeft = PMIN(amount, bufferLen);

  // if buffer is wrapping, get first part
  if ((bufferStart + copyLeft) > bufferSize) {
    PINDEX toCopy = bufferSize - bufferStart;

    Mix(data, buffer + bufferStart, toCopy, channels);

    data        += toCopy;
    bufferLen   -= toCopy;
    copyLeft    -= toCopy;
    bufferStart = 0;
  }

  // get the remainder of the buffer
  if (copyLeft > 0) {

    Mix(data, buffer + bufferStart, copyLeft, channels);

    bufferLen -= copyLeft;
    bufferStart = (bufferStart + copyLeft) % bufferSize;
  }
}

void AudioBuffer::Mix(BYTE * dst, const BYTE * src, PINDEX count, PINDEX /*channels*/)
{
#if 0
  memcpy(dst, src, count);
#else
  PINDEX i;
  for (i = 0; i < count; i += 2) {

    int srcVal = *(short *)src;
    int dstVal = *(short *)dst;

    int newVal = dstVal;

#if 1     //The loudest person gains the channel.
#define mix_abs(x) ((x) >= 0 ? (x) : -(x))
    if (mix_abs(newVal) > mix_abs(srcVal))
      dstVal = newVal;
    else
      dstVal = srcVal; 
#else   //Just add up all the channels.
    if ((newVal + srcVal) > 0x7fff)
      dstVal = 0x7fff;
    else
      dstVal += srcVal;
#endif
    *(short *)dst = (short)dstVal;

    dst += 2;
    src += 2;
  }
#endif
}

void AudioBuffer::Write(const BYTE * data, PINDEX amount)
{
  if (amount == 0)
    return;

  PWaitAndSignal mutex(audioBufferMutex);
  
  // if there is not enough room for the new data, make room
  PINDEX newLen = bufferLen + amount;
  if (newLen > bufferSize) {
    PINDEX toRemove = newLen - bufferSize;
    bufferStart = (bufferStart + toRemove) % bufferSize;
    bufferLen -= toRemove;
  }

  // copy data to the end of the new data, up to the end of the buffer
  PINDEX copyStart = (bufferStart + bufferLen) % bufferSize;
  if ((copyStart + amount) > bufferSize) {
    PINDEX toCopy = bufferSize - copyStart;
    memcpy(buffer + copyStart, data, toCopy);
    copyStart = 0;
    data      += toCopy;
    amount    -= toCopy;
    bufferLen += toCopy;
  }

  // copy the rest of the data
  if (amount > 0) {
    memcpy(buffer + copyStart, data, amount);
    bufferLen   += amount;
  }
}

///////////////////////////////////////////////////////////////////////////
#ifndef NO_VIDEO
IncomingVideo::IncomingVideo(MyH323EndPoint & _ep, MyH323Connection & _conn)
  : ep(_ep), conn(_conn), width(0), height(0), frameSize(0)
{
  closed = FALSE;
}

IncomingVideo::~IncomingVideo()
{
   IncomingVideo::Close();
   PVideoChannel::Close();
}
   
BOOL IncomingVideo::Write(const void * buffer, PINDEX amount)
{
  amount = (frameSize*3) >> 1;    // frameSize==width*height
  
  PWaitAndSignal mutex( videoChanMutex );

  if (closed){
    return FALSE;
  }

  conn.OnIncomingVideo(buffer, amount);

  return TRUE;
}

void IncomingVideo::SetRenderFrameSize(int _width, int _height) 
{ 
   PTRACE(3,"IncomingVideo Set size"); 
   width  = _width;
   height = _height;
   frameSize = width * height;
}
      
BOOL IncomingVideo::Close()
{
   PWaitAndSignal mutex(videoChanMutex);
   closed = TRUE;

   return TRUE;
  
}
 
///////////////////////////////////////////////////////////////////////////

OutgoingVideo::OutgoingVideo(MyH323EndPoint & _ep, MyH323Connection & _conn, int framesPerSec, BOOL _videoLarge)
  : ep(_ep), conn(_conn), videoLarge(_videoLarge)
{
  closed = FALSE;

  if ( ( framesPerSec>0 ) && ( framesPerSec < 31 ) ) {
    msBetweenFrames= 1000/framesPerSec;
  } else {
    cerr << "Invalid video transmit frame rate. Frame rate should be between 1 and 30 frames per second"<<endl;
    msBetweenFrames = 100;
  }
}

OutgoingVideo::~OutgoingVideo()
{
   OutgoingVideo::Close();
}

BOOL OutgoingVideo::Read(void *buffer, PINDEX  amount)
{
   PWaitAndSignal mutex1(videoChanMutex);

   amount = (( videoLarge ? 352*288*3 : 176*144*3 ) >> 1);
 
   if (!delay.Delay(msBetweenFrames)) 
      conn.OnOutgoingVideo(buffer, amount);
  
   return TRUE;
}


BOOL OutgoingVideo::Close()
{
//  PWaitAndSignal mutex(videoChanMutex);
  closed = TRUE;
  return TRUE;  
}


///////////////////////////////////////////////////////////////////////////

VideoBuffer::VideoBuffer()
  : xSize(176), ySize(144)
{
  buffer = NULL;
  SetSize( xSize, ySize );
}

VideoBuffer::~VideoBuffer()
{
  delete[] buffer;
}


//Writes data into the specified posn of the buffer.
//0 == top left, 1 == top right
//2 == bot left, 3 == bot right
void VideoBuffer::Write(BYTE * data, PINDEX amount,  PINDEX posn)
{
   // It appears that a full frame is always written.
   // We can determine the size of the frame by how much
   // is written.

   if (amount == 0)
     return;

   PWaitAndSignal mutex(videoBufferMutex);
  
   BYTE *yFirst, *ySecond, *u, *v, *srcYFirst, *srcYSecond, *srcU, *srcV;
   int  srcFrameSize = (amount<<1)/3;
   int  srcXSize     = (srcFrameSize == (176 * 144) ? 176 : 352 );
   int  srcYSize     = (srcFrameSize == (176 * 144) ? 144 : 288 );

   yFirst  = buffer;
   u= buffer + bufferFrameSize;
   v= buffer + bufferFrameSize + (bufferFrameSize >> 2);

   srcYFirst  = data;
   srcYSecond = srcYFirst + (xSize == srcXSize ?
   			     srcXSize << 1 :
			     srcXSize);
   srcU  = data + srcFrameSize;
   srcV  = data + srcFrameSize + (srcFrameSize >> 2);

   switch (posn) {
      case 0:
         break;
      case 1:
         yFirst +=(xSize >> 1);
         u +=(xSize >> 2);
         v +=(xSize >> 2);
         break;
      case 2:
         yFirst += (bufferFrameSize >> 1);
         u += (bufferFrameSize >> 3);
         v += (bufferFrameSize >> 3);
         break;
      case 3:
         yFirst += (bufferFrameSize >> 1) + (xSize >> 1);
         u += (bufferFrameSize >> 3) + (xSize >> 2);
         v += (bufferFrameSize >> 3) + (xSize >> 2);
         break;
      default: 
         return;
   }
    
   ySecond = yFirst + xSize;    // added down here so that any changes to
   				// yFirst are taken into account - pez
   // Special case, can fit 'in' images perfectly inside 'out' images
   if ( xSize == 352 && srcXSize == 176 ) {
      for(int i=0; i < 144; i+=2) {
         memcpy(yFirst, srcYFirst, 176);
	 memcpy(ySecond, srcYSecond, 176);
	 memcpy(u, srcU, 88 );
	 memcpy(v, srcV, 88 );

	 srcYFirst += 352;
	 srcYSecond += 352;
	 yFirst += 704;
	 ySecond += 704;
	 srcU += 88;
	 srcV += 88;
	 u    += 176;
	 v    += 176;
      }
   } else {
      // This code handles the other 2 cases in a generic fashion
      int src_step   = 3 * srcXSize;
      int step       = xSize + (xSize >> 1);
      int srcuv_step = (srcXSize >> 1);
      int uv_step    = (xSize >> 2);

      for(int i=0; i<srcYSize; i+=4) {
         for(int j=0; j<srcXSize; j+=4) {
            *yFirst++  = *srcYFirst;
            srcYFirst += 2;
            *yFirst++  = *srcYFirst;
            srcYFirst += 2;
            *ySecond++ = *srcYSecond;
            srcYSecond += 2;
            *ySecond++ = *srcYSecond;
            srcYSecond += 2;
            *u++ = *srcU;
            *v++ = *srcV;
            srcU+= 2;
            srcV+= 2;
         }
         srcYFirst  += src_step;
         srcYSecond += src_step;
         yFirst     += step;
         ySecond    += step;
         srcU += srcuv_step;
         srcV += srcuv_step;
         u    += uv_step;
         v    += uv_step;
      }
   }

   return;
}

void VideoBuffer::Clear(PINDEX posn)
{
   PWaitAndSignal mutex(videoBufferMutex);
  
   BYTE *yFirst, *ySecond, *u, *v;

   yFirst  = buffer;
   u= buffer + bufferFrameSize;
   v= buffer + bufferFrameSize + (bufferFrameSize/4);

   switch (posn) {
      case 0:
         break;
      case 1:
         yFirst += (xSize >> 1);
         u += (xSize >> 2);
         v += (xSize >> 2);
	 break;
      case 2:
         yFirst += (bufferFrameSize >> 1);
         u += (bufferFrameSize >> 3);
         v += (bufferFrameSize >> 3);
         break;
      case 3:
         yFirst += (bufferFrameSize >>1) + (xSize >> 1);
         u += (bufferFrameSize >> 3) + (xSize >> 2);
	 v += (bufferFrameSize >> 3) + (xSize >> 2);
	 break;
      default:
         return;
   }
   ySecond = yFirst + xSize;

   for(int y=0; y < (ySize>>1); y+=2) {
      memset(yFirst, 0x80, xSize >> 1); // Mid Grey
      memset(ySecond, 0x80, xSize >> 1); // Mid Grey
      memset(u, 0x80, xSize >> 2);
      memset(v, 0x80, xSize >> 2);
      yFirst     += xSize * 2;
      ySecond    += xSize * 2;
      u    += (xSize >> 1);
      v    += (xSize >> 1);
   }

   return;
}

void VideoBuffer::SetSize(int x, int y)
{
  PWaitAndSignal mutex(videoBufferMutex);
  if ( buffer != NULL )
    delete[] buffer;
  xSize = x;
  ySize = y;
  bufferFrameSize = xSize * ySize;
  videoBufferSize = bufferFrameSize
                    + (bufferFrameSize >> 2 )
                    + (bufferFrameSize >> 2); // Y + U + V;
  buffer = new BYTE[ videoBufferSize ];
  memset( buffer, 0x80, videoBufferSize); // Set Y, U and V to 0x80 - Mid Grey.
}


void VideoBuffer::Read(BYTE * data, PINDEX amount)
{
  if (amount == 0)
    return;
  PWaitAndSignal mutex(videoBufferMutex);
  memcpy(data,buffer,amount);
}
#endif //NO_VIDEO
///////////////////////////////////////////////////////////////////////////



#define	MIN_HEADROOM	30
#define	MAX_HEADROOM	60

AudioDelay::AudioDelay()
{
  firstTime = TRUE;
  error = 0;
}

void AudioDelay::Restart()
{
  firstTime = TRUE;
}

BOOL AudioDelay::Delay(int frameTime)
{
  if (firstTime) {
    firstTime = FALSE;
    previousTime = PTime();
    return TRUE;
  }

  error += frameTime;

  PTime now;
  PTimeInterval delay = now - previousTime;
  error -= (int)delay.GetMilliSeconds();
  previousTime = now;

  if (error > 0) 
#ifdef P_LINUX
    usleep(error * 1000);
#else
    PThread::Current()->Sleep(error);
#endif

  return error <= -frameTime;

  //if (headRoom > MAX_HEADROOM)
  //  PThread::Current()->Sleep(headRoom - MIN_HEADROOM);
}

// End of File ///////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -