AtmoExternalCaptureInput.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:10k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*
  2.  * AtmoExternalCaptureInput.cpp: Datasource which gets its data via a COM object call
  3.  * or some other external method.
  4.  *
  5.  *
  6.  * See the README.txt file for copyright information and how to reach the author(s).
  7.  *
  8.  * $Id: 1d77ee87ae0deab989cfa470451a0fc84ea3ac89 $
  9. */
  10. #include "AtmoExternalCaptureInput.h"
  11. #include "AtmoTools.h"
  12. #ifndef INT64_C
  13. #define INT64_C(c)  c ## LL
  14. #endif
  15. #if defined(_ATMO_VLC_PLUGIN_)
  16. CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
  17.                            CAtmoInput(pAtmoDynData),
  18.                            CThread(pAtmoDynData->getAtmoFilter())
  19. {
  20.     m_pCurrentFramePixels = NULL;
  21.     vlc_cond_init( &m_WakeupCond );
  22.     vlc_mutex_init( &m_WakeupLock );
  23.     msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput created.");
  24. }
  25. #else
  26. CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
  27.                            CAtmoInput(pAtmoDynData)
  28. {
  29.     m_hWakeupEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
  30.     m_pCurrentFramePixels = NULL;
  31. }
  32. #endif
  33. CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
  34. {
  35.    /* if there is still an unprocessed bufferpicture do kill it */
  36.    if(m_pCurrentFramePixels != NULL)
  37.       free(m_pCurrentFramePixels);
  38. #if defined(_ATMO_VLC_PLUGIN_)
  39.     vlc_cond_destroy( &m_WakeupCond );
  40.     vlc_mutex_destroy(&m_WakeupLock);
  41.     msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput destroyed.");
  42. #else
  43.     CloseHandle(m_hWakeupEvent);
  44. #endif
  45. }
  46. ATMO_BOOL CAtmoExternalCaptureInput::Open()
  47. {
  48.     this->Run();
  49.     return ATMO_TRUE;
  50. }
  51. // Closes the input-device.
  52. // Returns true if the input-device was closed successfully.
  53. ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
  54. {
  55.     this->Terminate();
  56.     return ATMO_TRUE;
  57. }
  58. tColorPacket CAtmoExternalCaptureInput::GetColorPacket(void)
  59. {
  60.     return this->m_ColorPacket;
  61. }
  62. /*
  63.   this method will be called from another thread or possible the COM Server to feed
  64.   new pixeldata into the calculation process it doest just the following:
  65.   1: check if last buffer was allready processed (!m_pCurrentFramePixels)
  66.   2. copy the bitmap info structure into the threads own one
  67.   3. alloc memory for frame
  68.   4. copy sourcepixeldata into own buffer...
  69.   5. let the thread wake up and return imediately to the caller
  70.   so that the real videoout wouldn't be stop for a too long time
  71. */
  72. void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
  73. {
  74.     /*
  75.        normaly we should protect this area of code by critical_section or a mutex,
  76.        but I think we can omit this here because the timing this method is called
  77.        is really slow (in terms of the speed of a modern computer?)
  78.        so it's nearly impossible that two frames are delivert in the same time
  79.        the test needs and malloc needs...
  80.     */
  81.     if( !m_pCurrentFramePixels )
  82.     {
  83.         // Last Frame was processed... take this one...
  84.         memcpy(&m_CurrentFrameHeader,bmpInfoHeader,bmpInfoHeader->biSize);
  85.         int PixelDataSize = m_CurrentFrameHeader.biHeight * m_CurrentFrameHeader.biWidth;
  86.         switch(m_CurrentFrameHeader.biBitCount) {
  87.             case 8:  /* PixelDataSize = PixelDataSize; */ break;
  88.             case 16: PixelDataSize = PixelDataSize * 2; break;
  89.             case 24: PixelDataSize = PixelDataSize * 3; break;
  90.             case 32: PixelDataSize = PixelDataSize * 4; break;
  91.         }
  92.         m_pCurrentFramePixels = malloc(PixelDataSize);
  93.         memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
  94.     }
  95. #if defined(_ATMO_VLC_PLUGIN_)
  96.    vlc_mutex_lock( &m_WakeupLock );
  97.    vlc_cond_signal( &m_WakeupCond );
  98.    vlc_mutex_unlock( &m_WakeupLock );
  99. #else
  100.     SetEvent(m_hWakeupEvent);
  101. #endif
  102. }
  103. /*
  104.  the real thread Method which is processing the pixeldata into the hardware channel
  105.  values - which are used by the thread AtmoLiveView...
  106. */
  107. #if defined (_ATMO_VLC_PLUGIN_)
  108. DWORD CAtmoExternalCaptureInput::Execute(void)
  109. {
  110.     msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput::Execute(void)");
  111.     int i = 0;
  112.     vlc_mutex_lock( &m_WakeupLock );
  113.     while ((this->m_bTerminated == ATMO_FALSE) && (!vlc_object_alive (this->m_pAtmoThread) == false)) {
  114.           int value = vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + INT64_C(75000));
  115.           if(!value) {
  116.              /* DeliverNewSourceDataPaket delivered new work for me... get it! */
  117.              CalcColors(); // read picture and calculate colors
  118.              this->m_FrameArrived = ATMO_TRUE;
  119.           }
  120.           i++;
  121.           if(i == 100) {
  122.              i = 0;
  123. #if !defined(WIN32)
  124. /* kludge for pthreads? using the same condition variable too often results in hanging the pthread
  125.    call inside vlc_cond_timedwait...
  126. */
  127. #ifdef _ATMO_KLUDGE_
  128.              vlc_cond_destroy( &m_WakeupCond );
  129.              vlc_cond_init( &m_WakeupCond );
  130. #endif
  131. #endif
  132.           }
  133.     }
  134.     vlc_mutex_unlock( &m_WakeupLock );
  135.     return 0;
  136. }
  137. #else
  138. DWORD CAtmoExternalCaptureInput::Execute(void) {
  139.     HANDLE handles[2];
  140.     handles[0] = this->m_hTerminateEvent;
  141.     handles[1] = m_hWakeupEvent;
  142.     while (this->m_bTerminated == ATMO_FALSE) {
  143.            DWORD event = WaitForMultipleObjects(2,handles,ATMO_FALSE,INFINITE);
  144.            if(event == WAIT_OBJECT_0) {
  145.               // Terminate Thread Event was set... say good bye...!
  146.               break;
  147.            }
  148.            if(event == (WAIT_OBJECT_0+1)) {
  149.               CalcColors(); // read picture and calculate colors
  150.               this->m_FrameArrived = ATMO_TRUE;
  151.            }
  152.     }
  153.     return 0;
  154. }
  155. #endif
  156. void CAtmoExternalCaptureInput::WaitForNextFrame(DWORD timeout)
  157. {
  158.     this->m_FrameArrived = ATMO_FALSE;
  159.     for(DWORD i=0;(i<timeout) && !m_FrameArrived;i++)
  160. #if defined (_ATMO_VLC_PLUGIN_)
  161.         msleep(1000);
  162. #else
  163.         Sleep(1);
  164. #endif
  165.     if(this->m_pAtmoDynData)
  166.     {
  167.         CAtmoConfig *cfg = this->m_pAtmoDynData->getAtmoConfig();
  168.         if(cfg)
  169.         {
  170.             int delay = cfg->getLiveView_FrameDelay();
  171.             if(delay > 0)
  172.             {
  173. #if defined (_ATMO_VLC_PLUGIN_)
  174.               msleep(delay * 1000);
  175. #else
  176.               Sleep(delay);
  177. #endif
  178.             }
  179.         }
  180.     }
  181. }
  182. void CAtmoExternalCaptureInput::CalcColors() {
  183.      // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
  184.     tHSVColor HSV_Img[IMAGE_SIZE];
  185.     tRGBColor pixelColor;
  186.     int srcIndex,index = 0;
  187.     memset(&HSV_Img,0,sizeof(HSV_Img));
  188.      // Convert Data to HSV values.. bla bla....
  189.     if(m_pCurrentFramePixels!=NULL)
  190.     {
  191.         if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
  192.         {
  193.           // HSVI = HSV Image allready in right format just copy the easiest task
  194.           // und weiterverarbeiten lassen
  195. #ifdef _ATMO_VLC_PLUGIN_
  196.           if(m_CurrentFrameHeader.biCompression ==  VLC_FOURCC('H','S','V','I'))
  197. #else
  198.           if(m_CurrentFrameHeader.biCompression ==  MakeDword('H','S','V','I'))
  199. #endif
  200.           {
  201.               memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
  202.           }
  203.           else if(m_CurrentFrameHeader.biCompression == BI_RGB)
  204.           {
  205.              if(m_CurrentFrameHeader.biBitCount == 16)
  206.              {
  207.                  unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
  208.                  for(int y=0;y<CAP_HEIGHT;y++)
  209.                  {
  210.                      srcIndex = y * CAP_WIDTH;
  211.                      for(int x=0;x<CAP_WIDTH;x++)
  212.                      {
  213.                          pixelColor.b = (buffer[srcIndex] & 31) << 3;
  214.                          pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
  215.                          pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
  216.                          srcIndex++;
  217.                          HSV_Img[index++] = RGB2HSV(pixelColor);
  218.                      }
  219.                  }
  220.              }
  221.              else if(m_CurrentFrameHeader.biBitCount == 24)
  222.              {
  223.                  for(int y=0;y<CAP_HEIGHT;y++)
  224.                  {
  225.                      srcIndex = y * (CAP_WIDTH*3);
  226.                      for(int x=0;x<CAP_WIDTH;x++)
  227.                      {
  228.                          pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
  229.                          pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
  230.                          pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
  231.                          HSV_Img[index++] = RGB2HSV(pixelColor);
  232.                      }
  233.                  }
  234.              }
  235.              else if(m_CurrentFrameHeader.biBitCount == 32)
  236.              {
  237.                  for(int y=0;y<CAP_HEIGHT;y++)
  238.                  {
  239.                      srcIndex = y * (CAP_WIDTH*4);
  240.                      for(int x=0;x<CAP_WIDTH;x++)
  241.                      {
  242.                          pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
  243.                          pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
  244.                          pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
  245.                          srcIndex++;
  246.                          HSV_Img[index++] = RGB2HSV(pixelColor);
  247.                      }
  248.                  }
  249.              }
  250.           }
  251.        }
  252.        /*
  253.           if the image color format wasn't recognized - the output
  254.           will be black (memset)
  255.        */
  256.        /*
  257.           now convert the pixeldata into one RGB trippel for each channel,
  258.           this is done by some very sophisticated methods and statistics ...
  259.           the only thing I know - the pixel priority is controled by some
  260.           gradients for each edge of the picture
  261.           (sorry I don't know how it exactly works because the formulars
  262.            are done by some one else...)
  263.        */
  264.        m_ColorPacket = CalcColorsAnalyzeHSV(this->m_pAtmoDynData->getAtmoConfig(), HSV_Img);
  265.        /* remove the source buffe */
  266.        free(m_pCurrentFramePixels);
  267.        /*
  268.           the buffer zereo so that deliver new data paket will wakeup the
  269.           thread on  the next frame again
  270.        */
  271.        m_pCurrentFramePixels = NULL;
  272.     }
  273. }