Hopefully, fixes the display of the remote video received in SIP calls in the call dialog.

cusax-fix
Lyubomir Marinov 16 years ago
parent 5024f083d1
commit 6de2a751aa

@ -527,13 +527,7 @@ public void run()
}
// REMOTE
Component[] videos =
videoTelephony
.getVisualComponents(callPeer);
Component video =
((videos == null) || (videos.length < 1)) ? null
: videos[0];
Component video = videoTelephony.getVisualComponent(callPeer);
if (video != null)
videoContainer

@ -263,11 +263,7 @@ public void videoAdded(VideoEvent e)
*/
public void videoRemoved(VideoEvent e)
{
if (fireVideoEvent(
e.getType(),
e.getVisualComponent(),
e.getOrigin()))
e.consume();
videoAdded(e);
}
};

@ -6,6 +6,7 @@
*/
package net.java.sip.communicator.impl.protocol.sip;
import java.awt.Component;
import java.net.*;
import java.util.*;
@ -17,6 +18,7 @@
import net.java.sip.communicator.service.neomedia.format.*;
import net.java.sip.communicator.service.netaddr.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
@ -33,7 +35,8 @@ public class CallPeerMediaHandler
/**
* Our class logger.
*/
private Logger logger = Logger.getLogger(CallPeerMediaHandler.class);
private static final Logger logger
= Logger.getLogger(CallPeerMediaHandler.class);
/**
* A reference to the CallPeerSipImpl instance that this handler is
@ -108,6 +111,57 @@ public class CallPeerMediaHandler
*/
private VideoMediaStream videoStream = null;
/**
* The <tt>List</tt> of <tt>VideoListener</tt>s interested in
* <tt>VideoEvent</tt>s fired by this instance or rather its
* <tt>VideoMediaStream</tt>.
*/
private final List<VideoListener> videoListeners
= new LinkedList<VideoListener>();
/**
* The neomedia <tt>VideoListener</tt> which listens to {@link #videoStream}
* for changes in the availability of visual <tt>Component</tt>s displaying
* remote video and re-fires them as
* <tt>net.java.sip.communicator.service.protocol.event.VideoEvent</tt>s
* originating from this instance.
*/
private final net.java.sip.communicator.service.neomedia.event.VideoListener videoStreamVideoListener
= new net.java.sip.communicator.service.neomedia.event.VideoListener()
{
/**
* Notifies this neomedia <tt>VideoListener</tt> that a new visual
* <tt>Component</tt> displaying remote video has been added in
* {@link CallPeerMediaHandler#videoStream}.
*
* @param event the neomedia <tt>VideoEvent</tt> which specifies the
* newly-added visual <tt>Component</tt> displaying remote video
*/
public void videoAdded(
net.java.sip.communicator.service.neomedia.event.VideoEvent event)
{
if (fireVideoEvent(
event.getType(),
event.getVisualComponent(),
event.getOrigin()))
event.consume();
}
/**
* Notifies this neomedia <tt>VideoListener</tt> that a visual
* <tt>Component</tt> displaying remote video has been removed from
* {@link CallPeerMediaHandler#videoStream}.
*
* @param event the neomedia <tt>VideoEvent</tt> which specifies the
* removed visual <tt>Component</tt> displaying remote video
*/
public void videoRemoved(
net.java.sip.communicator.service.neomedia.event.VideoEvent event)
{
videoAdded(event);
}
};
/**
* A <tt>URL</tt> pointing to a location with call information or a call
* control web interface related to the <tt>CallPeer</tt> that we are
@ -307,11 +361,7 @@ private void closeStream(MediaType type)
}
else
{
if (this.videoStream != null)
{
videoStream.close();
videoStream = null;
}
setVideoStream(null);
if (this.videoStreamConnector != null)
{
@ -613,7 +663,7 @@ private MediaStream configureAndStartStream(
if( stream instanceof AudioMediaStream)
this.audioStream = (AudioMediaStream)stream;
else
this.videoStream = (VideoMediaStream)stream;
setVideoStream((VideoMediaStream)stream);
if ( ! stream.isStarted())
stream.start();
@ -1178,4 +1228,172 @@ private void setCallInfoURL(URL callInfolURL)
{
this.callInfoURL = callInfolURL;
}
/**
* Sets the RTP media stream that this instance uses to stream video to a
* specific <tt>VideoMediaStream</tt>.
*
* @param videoStream the <tt>VideoMediaStream</tt> to be set as the RTP
* media stream that this instance uses to stream video
*/
private void setVideoStream(VideoMediaStream videoStream)
{
if (this.videoStream != videoStream)
{
/*
* Make sure we will no longer notify the registered VideoListeners
* about changes in the availability of video in the old
* videoStream.
*/
Component oldVisualComponent = null;
if (this.videoStream != null)
{
this.videoStream.removeVideoListener(videoStreamVideoListener);
oldVisualComponent = this.videoStream.getVisualComponent();
this.videoStream.close();
}
this.videoStream = videoStream;
/*
* Make sure we will notify the registered VideoListeners about
* changes in the availability of video in the new videoStream.
*/
Component newVisualComponent = null;
if (this.videoStream != null)
{
this.videoStream.addVideoListener(videoStreamVideoListener);
newVisualComponent = this.videoStream.getVisualComponent();
}
/*
* Notify the VideoListeners in case there was a change in the
* availability of the visual <tt>Component</tt>s displaying remote
* video.
*/
if (oldVisualComponent != null)
fireVideoEvent(
VideoEvent.VIDEO_REMOVED,
oldVisualComponent,
VideoEvent.REMOTE);
if (newVisualComponent != null)
fireVideoEvent(
VideoEvent.VIDEO_REMOVED,
newVisualComponent,
VideoEvent.REMOTE);
}
}
/**
* Registers a specific <tt>VideoListener</tt> with this instance so that it
* starts receiving notifications from it about changes in the availability
* of visual <tt>Component</tt>s displaying video.
*
* @param listener the <tt>VideoListener</tt> to be registered with this
* instance and to start receiving notifications from it about changes in
* the availability of visual <tt>Component</tt>s displaying video
*/
public void addVideoListener(VideoListener listener)
{
if (listener == null)
throw new NullPointerException("listener");
synchronized (videoListeners)
{
if (!videoListeners.contains(listener))
videoListeners.add(listener);
}
}
/**
* Notifies the <tt>VideoListener</tt>s registered with this
* <tt>CallPeerMediaHandler</tt> about a specific type of change in the
* availability of a specific visual <tt>Component</tt> depicting video.
*
* @param type the type of change as defined by <tt>VideoEvent</tt> in the
* availability of the specified visual <tt>Component</tt> depicting video
* @param visualComponent the visual <tt>Component</tt> depicting video
* which has been added or removed in this <tt>CallPeerMediaHandler</tt>
* @param origin {@link VideoEvent#LOCAL} if the origin of the video is
* local (e.g. it is being locally captured); {@link VideoEvent#REMOTE} if
* the origin of the video is remote (e.g. a remote peer is streaming it)
* @return <tt>true</tt> if this event and, more specifically, the visual
* <tt>Component</tt> it describes have been consumed and should be
* considered owned, referenced (which is important because
* <tt>Component</tt>s belong to a single <tt>Container</tt> at a time);
* otherwise, <tt>false</tt>
*/
protected boolean fireVideoEvent(
int type,
Component visualComponent,
int origin)
{
VideoListener[] listeners;
synchronized (videoListeners)
{
listeners
= videoListeners
.toArray(new VideoListener[videoListeners.size()]);
}
boolean consumed;
if (listeners.length > 0)
{
VideoEvent event
= new VideoEvent(this, type, visualComponent, origin);
for (VideoListener listener : listeners)
switch (type)
{
case VideoEvent.VIDEO_ADDED:
listener.videoAdded(event);
break;
case VideoEvent.VIDEO_REMOVED:
listener.videoRemoved(event);
break;
}
consumed = event.isConsumed();
}
else
consumed = false;
return consumed;
}
/**
* Gets the visual <tt>Component</tt> in which video from the remote peer is
* currently being rendered or <tt>null</tt> if there is currently no video
* streaming from the remote peer.
*
* @return the visual <tt>Component</tt> in which video from the remote peer
* is currently being rendered or <tt>null</tt> if there is currently no
* video streaming from the remote peer
*/
public Component getVisualComponent()
{
return (videoStream == null) ? null : videoStream.getVisualComponent();
}
/**
* Unregisters a specific <tt>VideoListener</tt> from this instance so that
* it stops receiving notifications from it about changes in the
* availability of visual <tt>Component</tt>s displaying video.
*
* @param listener the <tt>VideoListener</tt> to be unregistered from this
* instance and to stop receiving notifications from it about changes in the
* availability of visual <tt>Component</tt>s displaying video
*/
public void removeVideoListener(VideoListener listener)
{
if (listener != null)
synchronized (videoListeners)
{
videoListeners.remove(listener);
}
}
}

@ -8,6 +8,7 @@
import java.net.*;
import java.text.*;
import java.util.*;
import javax.sip.*;
import javax.sip.address.*;
@ -94,6 +95,20 @@ public class CallPeerSipImpl
*/
private final CallPeerMediaHandler mediaHandler;
/**
* The <tt>PropertyChangeListener</tt> which listens to
* {@link #mediaHandler} for changes in the values of its properties.
*/
private PropertyChangeListener mediaHandlerPropertyChangeListener;
/**
* The <tt>List</tt> of <tt>PropertyChangeListener</tt>s listening to this
* <tt>CallPeer</tt> for changes in the values of its properties related to
* video.
*/
private final List<PropertyChangeListener> videoPropertyChangeListeners
= new LinkedList<PropertyChangeListener>();
/**
* Creates a new call peer with address <tt>peerAddress</tt>.
*
@ -391,10 +406,7 @@ public Contact getContact()
@Override
public URL getCallInfoURL()
{
if (mediaHandler == null)
return null;
return mediaHandler.getCallInfoURL();
return getMediaHandler().getCallInfoURL();
}
/**
@ -1334,10 +1346,51 @@ public boolean isLocalVideoStreaming()
*/
public void addVideoPropertyChangeListener(PropertyChangeListener listener)
{
/**
* @todo update to neomedia.
getMediaCallSession().addPropertyChangeListener(listener);
*/
if (listener == null)
throw new NullPointerException("listener");
synchronized (videoPropertyChangeListeners)
{
/*
* The video is part of the media-related functionality and thus it
* is the responsibility of mediaHandler. So listen to mediaHandler
* for video-related property changes and re-fire them as
* originating from this instance.
*/
if (!videoPropertyChangeListeners.contains(listener)
&& videoPropertyChangeListeners.add(listener)
&& (mediaHandlerPropertyChangeListener == null))
{
mediaHandlerPropertyChangeListener
= new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent event)
{
Iterable<PropertyChangeListener> listeners;
synchronized (videoPropertyChangeListeners)
{
listeners
= new LinkedList<PropertyChangeListener>(
videoPropertyChangeListeners);
}
PropertyChangeEvent thisEvent
= new PropertyChangeEvent(
this,
event.getPropertyName(),
event.getOldValue(),
event.getNewValue());
for (PropertyChangeListener listener : listeners)
listener.propertyChange(thisEvent);
}
};
// getMediaHandler()
// .addPropertyChangeListener(
// mediaHandlerPropertyChangeListener);
}
}
}
/**
@ -1353,10 +1406,28 @@ public void addVideoPropertyChangeListener(PropertyChangeListener listener)
public void removeVideoPropertyChangeListener(
PropertyChangeListener listener)
{
/**
* @todo update to neomedia.
getMediaCallSession().removePropertyChangeListener(listener);
*/
if (listener != null)
synchronized (videoPropertyChangeListeners)
{
/*
* The video is part of the media-related functionality and thus
* it is the responsibility of mediaHandler. So we're listening
* to mediaHandler for video-related property changes and w're
* re-firing them as originating from this instance. Make sure
* that we're not listening to mediaHandler if noone is
* interested in video-related property changes originating from
* this instance.
*/
if (videoPropertyChangeListeners.remove(listener)
&& videoPropertyChangeListeners.isEmpty()
&& (mediaHandlerPropertyChangeListener != null))
{
// getMediaHandler()
// .removePropertyChangeListener(
// mediaHandlerPropertyChangeListener);
mediaHandlerPropertyChangeListener = null;
}
}
}
/**
@ -1389,7 +1460,7 @@ public void handleAuthenticationChallenge(ClientTransaction retryTran)
* @return a reference to the <tt>CallPeerMediaHandler</tt> instance that
* this peer uses for media related tips and tricks.
*/
private CallPeerMediaHandler getMediaHandler()
CallPeerMediaHandler getMediaHandler()
{
return mediaHandler;
}

@ -270,6 +270,7 @@ public CallPeerSipImpl findCallPeer(Dialog dialog)
* @return a reference to the <tt>ProtocolProviderServiceSipImpl</tt>
* instance that created this call.
*/
@Override
public ProtocolProviderServiceSipImpl getProtocolProvider()
{
return (ProtocolProviderServiceSipImpl)super.getProtocolProvider();

@ -51,12 +51,12 @@ public OperationSetVideoTelephonySipImpl(
}
/**
* Delegates to the CallSession of the Call of the specified CallPeer
* because the video is provided by the CallSession in the SIP protocol
* implementation. Because other OperationSetVideoTelephony implementations
* may not provide their video through the CallSession, this implementation
* promotes itself as the provider of the video by replacing the CallSession
* in the VideoEvents it fires.
* Delegates to the <tt>CallPeerMediaHandler</tt> of the specified
* <tt>CallPeer</tt> because the video is provided by it. Because other
* <tt>OperationSetVideoTelephony</tt> implementations may not provide their
* video through the <tt>CallPeerMediaHandler</tt>, this implementation
* promotes itself as the provider of the video by replacing the
* <tt>CallPeerMediaHandler</tt> in the <tt>VideoEvents</tt> it fires.
*
* @param peer the <tt>CallPeer</tt> that we will be registering
* <tt>listener</tt> with.
@ -67,11 +67,10 @@ public void addVideoListener(CallPeer peer, VideoListener listener)
if (listener == null)
throw new NullPointerException("listener");
/**
* @todo update to neomedia.
((CallPeerSipImpl) peer).getMediaCallSession()
.addVideoListener(new InternalVideoListener(this, peer, listener));
*/
((CallPeerSipImpl) peer)
.getMediaHandler()
.addVideoListener(
new InternalVideoListener(this, peer, listener));
}
/**
@ -136,34 +135,21 @@ public void disposeLocalVisualComponent(CallPeer peer, Component component)
}
/**
* Delegates to the CallSession of the Call of the specified CallPeer
* because the video is provided by the CallSession in the SIP protocol
* implementation.
* Gets the visual/video <tt>Component</tt> available in this telephony for
* a specific <tt>CallPeer</tt>.
*
* @param peer the peer whose visual <tt>Component</tt>s we'd like to
* retrieve.
*
* @return all visual <tt>Component</tt>s for the specified <tt>peer</tt>.
* @param peer the <tt>CallPeer</tt> whose video is to be retrieved
* @return the visual/video <tt>Component</tt> available in this telephony
* for the specified <tt>peer</tt> if any; otherwise, <tt>null</tt>
*/
public Component[] getVisualComponents(CallPeer peer)
public Component getVisualComponent(CallPeer peer)
{
/**
* @todo update to neomedia.
CallSession callSession =((CallPeerSipImpl)peer).getMediaCallSession();
return (callSession != null) ? callSession.getVisualComponents()
: new Component[0];
*/
return null;
return ((CallPeerSipImpl) peer).getMediaHandler().getVisualComponent();
}
/**
* Delegates to the CallSession of the Call of the specified CallPeer
* because the video is provided by the CallSession in the SIP protocol
* implementation. Because other OperationSetVideoTelephony implementations
* may not provide their video through the CallSession, this implementation
* promotes itself as the provider of the video by replacing the CallSession
* in the VideoEvents it fires.
* Delegates to the <tt>CallPeerMediaHandler</tt> of the specified
* <tt>CallPeer</tt> because the video is provided by it.
*
* @param peer the <tt>CallPeer</tt> that we'd like to unregister our
* <tt>VideoListener</tt> from.
@ -171,15 +157,11 @@ public Component[] getVisualComponents(CallPeer peer)
*/
public void removeVideoListener(CallPeer peer, VideoListener listener)
{
/**
* @todo update to neomedia.
if (listener != null)
{
((CallPeerSipImpl) peer).getMediaCallSession()
.removeVideoListener(
new InternalVideoListener(this, peer, listener));
}
*/
((CallPeerSipImpl) peer)
.getMediaHandler()
.removeVideoListener(
new InternalVideoListener(this, peer, listener));
}
/**
@ -246,8 +228,9 @@ public boolean isLocalVideoStreaming(Call call)
* when the properties associated with the specified <tt>Call</tt> change
* their values
*/
public void addPropertyChangeListener(Call call,
PropertyChangeListener listener)
public void addPropertyChangeListener(
Call call,
PropertyChangeListener listener)
{
((CallSipImpl) call).addVideoPropertyChangeListener(listener);
}
@ -264,8 +247,9 @@ public void addPropertyChangeListener(Call call,
* notified when the properties associated with the specified <tt>Call</tt>
* change their values
*/
public void removePropertyChangeListener(Call call,
PropertyChangeListener listener)
public void removePropertyChangeListener(
Call call,
PropertyChangeListener listener)
{
((CallSipImpl) call).removeVideoPropertyChangeListener(listener);
}
@ -317,8 +301,10 @@ private static class InternalVideoListener
* that the videos in the SIP protocol implementation is managed by the
* <tt>CallSession</tt> and not by the specified <tt>telephony</tt>
*/
public InternalVideoListener(OperationSetVideoTelephony telephony,
CallPeer peer, VideoListener delegate)
public InternalVideoListener(
OperationSetVideoTelephony telephony,
CallPeer peer,
VideoListener delegate)
{
if (peer == null)
throw new NullPointerException("peer cannot be null");
@ -339,6 +325,7 @@ public InternalVideoListener(OperationSetVideoTelephony telephony,
* @return true if the underlying peer, telephony operation set and
* delegate are equal to those of the <tt>other</tt> instance.
*/
@Override
public boolean equals(Object other)
{
if (other == this)
@ -360,6 +347,7 @@ public boolean equals(Object other)
* @return a hashcode based on the hash codes of the wrapped telephony
* operation set and <tt>VideoListener</tt> delegate.
*/
@Override
public int hashCode()
{
return (telephony.hashCode() << 16) + (delegate.hashCode() >> 16);
@ -376,8 +364,16 @@ public int hashCode()
*/
public void videoAdded(VideoEvent event)
{
delegate.videoAdded(new VideoEvent(this, event.getType(), event
.getVisualComponent(), event.getOrigin()));
VideoEvent delegateEvent
= new VideoEvent(
this,
event.getType(),
event.getVisualComponent(),
event.getOrigin());
delegate.videoAdded(delegateEvent);
if (delegateEvent.isConsumed())
event.consume();
}
/**
@ -392,8 +388,16 @@ public void videoAdded(VideoEvent event)
*/
public void videoRemoved(VideoEvent event)
{
delegate.videoAdded(new VideoEvent(this, event.getType(), event
.getVisualComponent(), event.getOrigin()));
VideoEvent delegateEvent
= new VideoEvent(
this,
event.getType(),
event.getVisualComponent(),
event.getOrigin());
delegate.videoRemoved(delegateEvent);
if (delegateEvent.isConsumed())
event.consume();
}
}
}

@ -13,6 +13,7 @@ Import-Package: org.apache.log4j,
net.java.sip.communicator.service.gui,
net.java.sip.communicator.service.neomedia,
net.java.sip.communicator.service.neomedia.device,
net.java.sip.communicator.service.neomedia.event,
net.java.sip.communicator.service.neomedia.format,
net.java.sip.communicator.service.netaddr,
net.java.sip.communicator.service.protocol,

@ -79,15 +79,14 @@ public Component createLocalVisualComponent(CallPeer peer,
public void disposeLocalVisualComponent(CallPeer peer, Component component);
/**
* Gets the visual/video <tt>Component</tt>s available in this telephony
* for a specific <tt>CallPeer</tt>.
* Gets the visual/video <tt>Component</tt> available in this telephony for
* a specific <tt>CallPeer</tt>.
*
* @param peer the <tt>CallPeer</tt> whose videos are to be retrieved
*
* @return an array of the visual <tt>Component</tt>s available in this
* telephony for the specified <tt>peer</tt>
* @param peer the <tt>CallPeer</tt> whose video is to be retrieved
* @return the visual/video <tt>Component</tt> available in this telephony
* for the specified <tt>peer</tt> if any; otherwise, <tt>null</tt>
*/
public Component[] getVisualComponents(CallPeer peer);
public Component getVisualComponent(CallPeer peer);
/**
* Removes a specific <tt>VideoListener</tt> from this telephony in

Loading…
Cancel
Save