[ekiga] handle multiple video output streams



commit 97a504873a69ef598e69cb769136c17b1b422bd5
Author: VÃctor Manuel JÃquez Leal <vjaquez igalia com>
Date:   Tue Aug 21 20:48:58 2012 +0200

    handle multiple video output streams
    
    After enabling H.239, Ekiga will need to handle multiple remote video
    streams. Currently Ekiga only shows one remote video stream.
    
    This patch sets the basics for multiple remote video streams: each remote
    video stream is named uniquely and according to it the video output would be
    able to manage the stream.
    
    For now, the patch only shows the first remote video stream to reach the
    endpoint, the subsequent is just ignored.
    
    Closes bug #682387.

 .../videooutput-manager-common.cpp                 |   22 ++++++++----
 .../videooutput-manager-common.h                   |    2 +-
 lib/engine/components/opal/opal-call-manager.cpp   |   31 +++++++++++++++++
 lib/engine/components/opal/opal-call-manager.h     |    6 +++
 lib/engine/components/opal/opal-videooutput.cpp    |   36 +++++++++++---------
 lib/engine/components/opal/opal-videooutput.h      |    5 ++-
 lib/engine/videoinput/videoinput-core.cpp          |    2 +-
 lib/engine/videooutput/videooutput-core.cpp        |   12 +++---
 lib/engine/videooutput/videooutput-core.h          |    4 +-
 lib/engine/videooutput/videooutput-manager.h       |    4 +-
 10 files changed, 87 insertions(+), 37 deletions(-)
---
diff --git a/lib/engine/components/common-videooutput/videooutput-manager-common.cpp b/lib/engine/components/common-videooutput/videooutput-manager-common.cpp
index 9597217..9342047 100644
--- a/lib/engine/components/common-videooutput/videooutput-manager-common.cpp
+++ b/lib/engine/components/common-videooutput/videooutput-manager-common.cpp
@@ -123,13 +123,15 @@ GMVideoOutputManager::Main ()
 void GMVideoOutputManager::set_frame_data (const char* data,
 					   unsigned width,
 					   unsigned height,
-					   bool local,
+					   unsigned type,
 					   int devices_nbr)
-{ 
+{
   Ekiga::DisplayInfo local_display_info;
 
   get_display_info(local_display_info);
 
+  bool local = (type == 0);
+
   var_mutex.Wait();
 
   if (local) {
@@ -141,7 +143,7 @@ void GMVideoOutputManager::set_frame_data (const char* data,
     memcpy (lframeStore.GetPointer(), data, (width * height * 3) >> 1);
     local_frame_received = true;
   }
-  else {
+  else if (type == 1) { // REMOTE 1
 
     /* memcpy the frame */
     rframeStore.SetSize (width * height * 3);
@@ -149,9 +151,13 @@ void GMVideoOutputManager::set_frame_data (const char* data,
     current_frame.remote_height= height;
     memcpy (rframeStore.GetPointer(), data, (width * height * 3) >> 1);
     remote_frame_received = true;
+  } else {
+    var_mutex.Signal();
+    run_thread.Signal();
+    return; // nothing happened
   }
 
-  /* If there is only one device open, ignore the setting, and 
+  /* If there is only one device open, ignore the setting, and
    * display what we can actually display.
    */
   if (devices_nbr <= 1) {
@@ -164,19 +170,19 @@ void GMVideoOutputManager::set_frame_data (const char* data,
       local_frame_received = false;
     }
 
-    current_frame.both_streams_active = false;;
+    current_frame.both_streams_active = false;
   } else {
-  
+
     if (local_frame_received && !remote_frame_received)
         local_display_info.mode = Ekiga::VO_MODE_LOCAL;
-  
+
     if (!local_frame_received && remote_frame_received)
         local_display_info.mode = Ekiga::VO_MODE_REMOTE;
 
     current_frame.both_streams_active = local_frame_received & remote_frame_received;
   }
   current_frame.mode = local_display_info.mode;
-  current_frame.zoom = local_display_info.zoom; 
+  current_frame.zoom = local_display_info.zoom;
 
   if (local) {
 
diff --git a/lib/engine/components/common-videooutput/videooutput-manager-common.h b/lib/engine/components/common-videooutput/videooutput-manager-common.h
index dfeb59d..3bdbf42 100644
--- a/lib/engine/components/common-videooutput/videooutput-manager-common.h
+++ b/lib/engine/components/common-videooutput/videooutput-manager-common.h
@@ -114,7 +114,7 @@
     virtual void set_frame_data (const char* data,
                                   unsigned width,
                                   unsigned height,
-                                  bool local,
+                                  unsigned type,
                                   int devices_nbr);
 
     virtual void set_display_info (const Ekiga::DisplayInfo & _display_info)
diff --git a/lib/engine/components/opal/opal-call-manager.cpp b/lib/engine/components/opal/opal-call-manager.cpp
index b80dca4..17bc02e 100644
--- a/lib/engine/components/opal/opal-call-manager.cpp
+++ b/lib/engine/components/opal/opal-call-manager.cpp
@@ -852,3 +852,34 @@ CallManager::ReportSTUNError (const std::string error)
 				 10);
   }
 }
+
+PBoolean
+CallManager::CreateVideoOutputDevice(const OpalConnection & connection,
+                                     const OpalMediaFormat & media_fmt,
+                                     PBoolean preview,
+                                     PVideoOutputDevice * & device,
+                                     PBoolean & auto_delete)
+{
+  PVideoDevice::OpenArgs videoArgs;
+  PString title;
+
+  videoArgs = preview ?
+    GetVideoPreviewDevice() : GetVideoOutputDevice();
+
+  if (!preview) {
+    unsigned openChannelCount = 0;
+    OpalMediaStreamPtr mediaStream;
+
+    while ((mediaStream = connection.GetMediaStream(OpalMediaType::Video(),
+                                                    preview, mediaStream)) != NULL)
+      ++openChannelCount;
+
+    videoArgs.deviceName += psprintf(" ID=%u", openChannelCount);
+  }
+
+  media_fmt.AdjustVideoArgs(videoArgs);
+
+  auto_delete = true;
+  device = PVideoOutputDevice::CreateOpenedDevice(videoArgs, false);
+  return device != NULL;
+}
diff --git a/lib/engine/components/opal/opal-call-manager.h b/lib/engine/components/opal/opal-call-manager.h
index 1d64b8b..0c2f177 100644
--- a/lib/engine/components/opal/opal-call-manager.h
+++ b/lib/engine/components/opal/opal-call-manager.h
@@ -170,6 +170,12 @@ private:
 
     void ReportSTUNError (const std::string error);
 
+    virtual PBoolean CreateVideoOutputDevice(const OpalConnection & connection,
+                                             const OpalMediaFormat & media_fmt,
+                                             PBoolean preview,
+                                             PVideoOutputDevice * & device,
+                                             PBoolean & auto_delete);
+
     /* The various related endpoints */
     GMPCSSEndpoint *pcssEP;
 
diff --git a/lib/engine/components/opal/opal-videooutput.cpp b/lib/engine/components/opal/opal-videooutput.cpp
index a3254d8..14ea264 100644
--- a/lib/engine/components/opal/opal-videooutput.cpp
+++ b/lib/engine/components/opal/opal-videooutput.cpp
@@ -48,7 +48,7 @@ PMutex PVideoOutputDevice_EKIGA::videoDisplay_mutex;
 /* The Methods */
 PVideoOutputDevice_EKIGA::PVideoOutputDevice_EKIGA (Ekiga::ServiceCore & _core)
 : core (_core)
-{ 
+{
   PWaitAndSignal m(videoDisplay_mutex); /* FIXME: if it's really needed
 					 * then we may crash : it's wrong to
 					 * use 'core' from a thread -- mutex
@@ -58,9 +58,9 @@ PVideoOutputDevice_EKIGA::PVideoOutputDevice_EKIGA (Ekiga::ServiceCore & _core)
   videooutput_core = core.get<Ekiga::VideoOutputCore> ("videooutput-core");
 
   is_active = FALSE;
-  
+
   /* Used to distinguish between input and output device. */
-  device_id = 0; 
+  device_id = LOCAL;
 }
 
 
@@ -73,22 +73,26 @@ PVideoOutputDevice_EKIGA::~PVideoOutputDevice_EKIGA()
 
   if (is_active) {
     devices_nbr--;
-    if (devices_nbr==0)
+    if (devices_nbr == 0)
       videooutput_core->stop();
     is_active = false;
   }
 }
 
 
-bool 
+bool
 PVideoOutputDevice_EKIGA::Open (const PString &name,
 				G_GNUC_UNUSED bool unused)
-{ 
-  if (name == "EKIGAIN") 
-    device_id = 1; 
-
-  return TRUE; 
+{
+  if (name == "EKIGAIN") {
+    device_id = LOCAL;
+  } else { // EKIGAOUT
+    PString devname = name;
+    PINDEX id = devname.Find("ID=");
+    device_id = REMOTE + atoi(&devname[id + 3]);
+  }
 
+  return TRUE;
 }
 
 PStringArray PVideoOutputDevice_EKIGA::GetDeviceNames() const
@@ -113,15 +117,15 @@ bool PVideoOutputDevice_EKIGA::SetFrameData (unsigned x,
 					   const BYTE * data,
 					   bool endFrame)
 {
- PWaitAndSignal m(videoDisplay_mutex);
+  PWaitAndSignal m(videoDisplay_mutex);
 
   if (x > 0 || y > 0)
     return FALSE;
 
-  if (width < 160 || width > 2048) 
+  if (width < 160 || width > 2048)
     return FALSE;
-  
-  if (height <120 || height > 2048) 
+
+  if (height <120 || height > 2048)
     return FALSE;
 
   if (!endFrame)
@@ -135,7 +139,7 @@ bool PVideoOutputDevice_EKIGA::SetFrameData (unsigned x,
     devices_nbr++;
   }
 
-  videooutput_core->set_frame_data((const char*) data, width, height, (device_id == LOCAL), devices_nbr);
+  videooutput_core->set_frame_data((const char*) data, width, height, device_id, devices_nbr);
 
   return TRUE;
 }
@@ -146,5 +150,5 @@ bool PVideoOutputDevice_EKIGA::SetColourFormat (const PString & colour_format)
     return PVideoOutputDevice::SetColourFormat (colour_format);
   }
 
-  return FALSE;  
+  return FALSE;
 }
diff --git a/lib/engine/components/opal/opal-videooutput.h b/lib/engine/components/opal/opal-videooutput.h
index fdd7eeb..049eeba 100644
--- a/lib/engine/components/opal/opal-videooutput.h
+++ b/lib/engine/components/opal/opal-videooutput.h
@@ -137,7 +137,10 @@ class PVideoOutputDevice_EKIGA : public PVideoOutputDevice
 
   bool is_active;
 
-  enum {REMOTE, LOCAL};
+  enum {
+    LOCAL,
+    REMOTE,
+  };
 
   Ekiga::ServiceCore & core;
   boost::shared_ptr<Ekiga::VideoOutputCore> videooutput_core;
diff --git a/lib/engine/videoinput/videoinput-core.cpp b/lib/engine/videoinput/videoinput-core.cpp
index b499b32..d801839 100644
--- a/lib/engine/videoinput/videoinput-core.cpp
+++ b/lib/engine/videoinput/videoinput-core.cpp
@@ -112,7 +112,7 @@ void VideoInputCore::VideoPreviewManager::Main ()
     while (!pause_thread) {
       if (frame) {
         videoinput_core.get_frame_data(frame);
-        videooutput_core->set_frame_data(frame, width, height, true, 1);
+        videooutput_core->set_frame_data(frame, width, height, 0, 1);
       }
       // We have to sleep some time outside the mutex lock
       // to give other threads time to get the mutex
diff --git a/lib/engine/videooutput/videooutput-core.cpp b/lib/engine/videooutput/videooutput-core.cpp
index 44ddf7d..55392f9 100644
--- a/lib/engine/videooutput/videooutput-core.cpp
+++ b/lib/engine/videooutput/videooutput-core.cpp
@@ -151,17 +151,17 @@ void VideoOutputCore::stop ()
 void VideoOutputCore::set_frame_data (const char *data,
                                   unsigned width,
                                   unsigned height,
-                                  bool local,
+                                  unsigned type,
                                   int devices_nbr)
 {
   core_mutex.Wait ();
 
-  if (local) {
+  if (type == 0) { // LOCAL
     videooutput_stats.tx_frames++;
     videooutput_stats.tx_width = width;
     videooutput_stats.tx_height = height;
   }
-  else {
+  else if (type == 1) { // REMOTE 1
     videooutput_stats.rx_frames++;
     videooutput_stats.rx_width = width;
     videooutput_stats.rx_height = height;
@@ -170,7 +170,7 @@ void VideoOutputCore::set_frame_data (const char *data,
   GTimeVal current_time;
   g_get_current_time (&current_time);
 
-  long unsigned milliseconds = ((current_time.tv_sec - last_stats.tv_sec) * 1000) 
+  long unsigned milliseconds = ((current_time.tv_sec - last_stats.tv_sec) * 1000)
                              + ((current_time.tv_usec - last_stats.tv_usec) / 1000);
 
   if (milliseconds > 2000) {
@@ -182,11 +182,11 @@ void VideoOutputCore::set_frame_data (const char *data,
   }
 
   core_mutex.Signal ();
-  
+
   for (std::set<VideoOutputManager *>::iterator iter = managers.begin ();
        iter != managers.end ();
        iter++) {
-    (*iter)->set_frame_data (data,width, height, local, devices_nbr);
+    (*iter)->set_frame_data (data, width, height, type, devices_nbr);
   }
 }
 
diff --git a/lib/engine/videooutput/videooutput-core.h b/lib/engine/videooutput/videooutput-core.h
index a5037e1..79ba042 100644
--- a/lib/engine/videooutput/videooutput-core.h
+++ b/lib/engine/videooutput/videooutput-core.h
@@ -137,14 +137,14 @@ namespace Ekiga
        * @param data a pointer to the buffer with the data to be written. It will not be freed.
        * @param width the width in pixels of the frame to be written.
        * @param height the height in pixels of the frame to be written.
-       * @param local true if the frame is a frame of the local video source, false if it is from the remote end.
+       * @param type the type of the frame: 0 - local video source or >0 from the remote end.
        * @param devices_nbr 1 if only local or remote device has been opened, 2 if both have been opened.
        */
 
       void set_frame_data (const char *data,
                            unsigned width,
                            unsigned height,
-                           bool local,
+                           unsigned type,
                            int devices_nbr);
 
       void set_display_info (const DisplayInfo & _display_info);
diff --git a/lib/engine/videooutput/videooutput-manager.h b/lib/engine/videooutput/videooutput-manager.h
index 9938199..a96d8c0 100644
--- a/lib/engine/videooutput/videooutput-manager.h
+++ b/lib/engine/videooutput/videooutput-manager.h
@@ -86,13 +86,13 @@ namespace Ekiga
        * @param data a pointer to the buffer with the data to be written. It will not be freed.
        * @param width the width in pixels of the frame to be written.
        * @param height the height in pixels of the frame to be written.
-       * @param local true if the frame is a frame of the local video source, false if it is from the remote end.
+       * @param type the type of the frame: 0 - local video source or >0 from the remote end.
        * @param devices_nbr 1 if only local or remote device has been opened, 2 if both have been opened.
        */
       virtual void set_frame_data (const char *data,
                                    unsigned width,
                                    unsigned height,
-                                   bool local,
+                                   unsigned type,
                                    int devices_nbr) = 0;
 
       virtual void set_display_info (const DisplayInfo &) { };



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]