diff --git a/libempathy/empathy-call-handler.c b/libempathy/empathy-call-handler.c
index 3172499..537bdde 100644
--- a/libempathy/empathy-call-handler.c
+++ b/libempathy/empathy-call-handler.c
@@ -43,6 +43,7 @@ enum {
   SINK_PAD_ADDED,
   REQUEST_RESOURCE,
   CLOSED,
+  VIDEO_STREAM_CHANGED,
   LAST_SIGNAL
 };
 
@@ -71,6 +72,13 @@ typedef struct {
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCallHandler)
 
 static void
+empathy_call_handler_call_video_stream_cb (EmpathyTpCall *call,
+    GParamSpec *property, EmpathyCallHandler *self)
+{
+  g_signal_emit (G_OBJECT (self), signals[VIDEO_STREAM_CHANGED], 0);
+}
+
+static void
 empathy_call_handler_dispose (GObject *object)
 {
   EmpathyCallHandlerPriv *priv = GET_PRIV (object);
@@ -93,6 +101,8 @@ empathy_call_handler_dispose (GObject *object)
   if (priv->call != NULL)
     {
       empathy_tp_call_close (priv->call);
+      g_signal_handlers_disconnect_by_func (priv->call,
+          empathy_call_handler_call_video_stream_cb, object);
       g_object_unref (priv->call);
     }
 
@@ -262,6 +272,13 @@ empathy_call_handler_class_init (EmpathyCallHandlerClass *klass)
       g_cclosure_marshal_VOID__VOID,
       G_TYPE_NONE,
       0);
+
+  signals[VIDEO_STREAM_CHANGED] =
+    g_signal_new ("video-stream-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+      g_cclosure_marshal_VOID__VOID,
+      G_TYPE_NONE,
+      0);
 }
 
 /**
@@ -514,6 +531,9 @@ empathy_call_handler_request_cb (EmpathyDispatchOperation *operation,
 
   g_object_ref (priv->call);
 
+  g_signal_connect (priv->call, "notify::video-stream",
+      G_CALLBACK (empathy_call_handler_call_video_stream_cb), self);
+
   empathy_call_handler_start_tpfs (self);
 
   empathy_tp_call_to (priv->call, priv->contact,
@@ -536,6 +556,8 @@ empathy_call_handler_start_call (EmpathyCallHandler *handler)
   if (priv->call != NULL)
     {
       empathy_call_handler_start_tpfs (handler);
+      g_signal_connect (priv->call, "notify::video-stream",
+          G_CALLBACK (empathy_call_handler_call_video_stream_cb), handler);
       empathy_tp_call_accept_incoming_call (priv->call);
       return;
     }
diff --git a/libempathy/empathy-tp-call.c b/libempathy/empathy-tp-call.c
index 2971e0f..bf3fe77 100644
--- a/libempathy/empathy-tp-call.c
+++ b/libempathy/empathy-tp-call.c
@@ -672,3 +672,40 @@ empathy_tp_call_has_dtmf (EmpathyTpCall *call)
       TP_IFACE_QUARK_CHANNEL_INTERFACE_DTMF);
 }
 
+/**
+ * empathy_tp_call_is_receiving_video:
+ * @call: the call
+ *
+ * Indicates if the call is receiving video or not.
+ *
+ * Returns: %TRUE if the call is currently receiving video, %FALSE otherwise.
+ */
+gboolean
+empathy_tp_call_is_receiving_video (EmpathyTpCall *call)
+{
+  EmpathyTpCallPriv *priv = GET_PRIV (call);
+
+  g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), FALSE);
+
+  return priv->video->direction == TP_MEDIA_STREAM_DIRECTION_RECEIVE ||
+            priv->video->direction == TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
+}
+
+/**
+ * empathy_tp_call_is_sending_video:
+ * @call: the call
+ *
+ * Indicates if the call is sending video or not.
+ *
+ * Returns: %TRUE if the call is currently sending video, %FALSE otherwise.
+ */
+gboolean
+empathy_tp_call_is_sending_video (EmpathyTpCall *call)
+{
+  EmpathyTpCallPriv *priv = GET_PRIV (call);
+
+  g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), FALSE);
+
+  return priv->video->direction == TP_MEDIA_STREAM_DIRECTION_SEND ||
+            priv->video->direction == TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
+}
diff --git a/libempathy/empathy-tp-call.h b/libempathy/empathy-tp-call.h
index 406ed1c..a00fe3e 100644
--- a/libempathy/empathy-tp-call.h
+++ b/libempathy/empathy-tp-call.h
@@ -85,6 +85,8 @@ void empathy_tp_call_request_video_stream_direction (EmpathyTpCall *call,
 void empathy_tp_call_start_tone (EmpathyTpCall *call, TpDTMFEvent event);
 void empathy_tp_call_stop_tone (EmpathyTpCall *call);
 gboolean empathy_tp_call_has_dtmf (EmpathyTpCall *call);
+gboolean empathy_tp_call_is_receiving_video (EmpathyTpCall *call);
+gboolean empathy_tp_call_is_sending_video (EmpathyTpCall *call);
 
 G_END_DECLS
 
diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c
index dd993fc..0bd546a 100644
--- a/src/empathy-call-window.c
+++ b/src/empathy-call-window.c
@@ -87,6 +87,7 @@ struct _EmpathyCallWindowPriv
   gboolean connected;
 
   GtkUIManager *ui_manager;
+  GtkWidget *self_user_output_frame;
   GtkWidget *video_output;
   GtkWidget *video_preview;
   GtkWidget *remote_user_avatar_widget;
@@ -99,6 +100,7 @@ struct _EmpathyCallWindowPriv
   GtkWidget *camera_button;
   GtkWidget *toolbar;
   GtkWidget *pane;
+  GtkAction *show_preview;
   GtkAction *send_video;
   GtkAction *menu_fullscreen;
 
@@ -206,6 +208,9 @@ static void empathy_call_window_video_menu_popup (EmpathyCallWindow *window,
 static void empathy_call_window_status_message (EmpathyCallWindow *window,
   gchar *message);
 
+static void empathy_call_window_update_avatars_visibility (EmpathyTpCall *call,
+  EmpathyCallWindow *window);
+
 static gboolean empathy_call_window_bus_message (GstBus *bus,
   GstMessage *message, gpointer user_data);
 
@@ -524,7 +529,7 @@ empathy_call_window_init (EmpathyCallWindow *self)
   GtkWidget *h;
   GtkWidget *arrow;
   GtkWidget *page;
-  GtkWidget *remote_user_output_frame, *self_user_output_frame;
+  GtkWidget *remote_user_output_frame;
   GtkWidget *remote_user_output_hbox, *self_user_output_hbox;
   GstBus *bus;
   gchar *filename;
@@ -538,6 +543,7 @@ empathy_call_window_init (EmpathyCallWindow *self)
     "camera", &priv->camera_button,
     "toolbar", &priv->toolbar,
     "send_video", &priv->send_video,
+    "show_preview", &priv->show_preview,
     "ui_manager", &priv->ui_manager,
     "menufullscreen", &priv->menu_fullscreen,
     NULL);
@@ -600,9 +606,9 @@ empathy_call_window_init (EmpathyCallWindow *self)
   gtk_box_pack_start (GTK_BOX (priv->content_hbox), priv->vbox,
                       FALSE, FALSE, CONTENT_HBOX_CHILDREN_PACKING_PADDING);
 
-  self_user_output_frame = gtk_frame_new (NULL);
-  gtk_widget_set_size_request (self_user_output_frame, SELF_VIDEO_SECTION_WIDTH,
-      SELF_VIDEO_SECTION_HEIGTH);
+  priv->self_user_output_frame = gtk_frame_new (NULL);
+  gtk_widget_set_size_request (priv->self_user_output_frame,
+      SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGTH);
   self_user_output_hbox = gtk_hbox_new (FALSE, 0);
 
   priv->self_user_avatar_widget = gtk_image_new ();
@@ -615,10 +621,10 @@ empathy_call_window_init (EmpathyCallWindow *self)
   gtk_box_pack_start (GTK_BOX (self_user_output_hbox), priv->video_preview,
       TRUE, TRUE, 0);
 
-  gtk_container_add (GTK_CONTAINER (self_user_output_frame),
+  gtk_container_add (GTK_CONTAINER (priv->self_user_output_frame),
       self_user_output_hbox);
 
-  gtk_box_pack_start (GTK_BOX (priv->vbox), self_user_output_frame, FALSE,
+  gtk_box_pack_start (GTK_BOX (priv->vbox), priv->self_user_output_frame, FALSE,
       FALSE, 0);
 
   priv->video_input = empathy_video_src_new ();
@@ -1013,6 +1019,10 @@ empathy_call_window_disconnected (EmpathyCallWindow *self)
 
   empathy_call_window_status_message (self, _("Disconnected"));
 
+  gtk_widget_hide (priv->video_output);
+  gtk_widget_hide (priv->video_preview);
+  gtk_widget_show (priv->self_user_avatar_widget);
+  gtk_widget_show (priv->remote_user_avatar_widget);
   gtk_widget_set_sensitive (priv->camera_button, FALSE);
   gtk_action_set_sensitive (priv->send_video, FALSE);
   priv->sending_video = FALSE;
@@ -1113,12 +1123,26 @@ empathy_call_window_connected (gpointer user_data)
   if (empathy_tp_call_has_dtmf (call))
     gtk_widget_set_sensitive (priv->dtmf_panel, TRUE);
 
+
+  priv->sending_video = empathy_tp_call_is_sending_video (call);
+
+  if (priv->sending_video)
+      {
+        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview),
+            TRUE);
+        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video),
+            TRUE);
+        gtk_toggle_tool_button_set_active (
+            GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), TRUE);
+      }
+
   if (priv->video_input != NULL)
     {
       gtk_widget_set_sensitive (priv->camera_button, TRUE);
       gtk_action_set_sensitive (priv->send_video, TRUE);
     }
 
+  empathy_call_window_update_avatars_visibility (call, self);
   g_object_unref (call);
 
   g_mutex_lock (priv->lock);
@@ -1334,6 +1358,48 @@ empathy_call_window_bus_message (GstBus *bus, GstMessage *message,
 }
 
 static void
+empathy_call_window_update_avatars_visibility (EmpathyTpCall *call,
+    EmpathyCallWindow *window)
+{
+  EmpathyCallWindowPriv *priv = GET_PRIV (window);
+
+  if (empathy_tp_call_is_receiving_video (call))
+    {
+      gtk_widget_hide (priv->remote_user_avatar_widget);
+      gtk_widget_show (priv->video_output);
+    }
+  else
+    {
+      gtk_widget_hide (priv->video_output);
+      gtk_widget_show (priv->remote_user_avatar_widget);
+    }
+
+  if (empathy_tp_call_is_sending_video (call))
+    {
+      gtk_widget_hide (priv->self_user_avatar_widget);
+      gtk_widget_show (priv->video_preview);
+    }
+  else
+    {
+      gtk_widget_hide (priv->video_preview);
+      gtk_widget_show (priv->self_user_avatar_widget);
+    }
+}
+
+static void
+empathy_call_window_video_stream_changed_cb (EmpathyCallHandler *handler,
+    EmpathyCallWindow *window)
+{
+  EmpathyTpCall *call;
+  EmpathyCallWindowPriv *priv = GET_PRIV (window);
+
+  g_object_get (priv->handler, "tp-call", &call, NULL);
+
+  empathy_call_window_update_avatars_visibility (call, window);
+  g_object_unref (call);
+}
+
+static void
 empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (window);
@@ -1349,6 +1415,8 @@ empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window)
     G_CALLBACK (empathy_call_window_src_added_cb), window);
   g_signal_connect (priv->handler, "sink-pad-added",
     G_CALLBACK (empathy_call_window_sink_added_cb), window);
+  g_signal_connect (priv->handler, "video-stream-changed",
+    G_CALLBACK (empathy_call_window_video_stream_changed_cb), window);
 
 
   preview = empathy_video_widget_get_element (
@@ -1532,6 +1600,11 @@ empathy_call_window_camera_toggled_cb (GtkToggleToolButton *toggle,
     return;
   priv->sending_video = active;
 
+  /* When we start sending video, we want to show the video preview by
+     default. */
+  if (priv->sending_video)
+    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview), TRUE);
+
   empathy_call_window_set_send_video (window, active);
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), active);
 }
@@ -1549,6 +1622,11 @@ empathy_call_window_send_video_toggled_cb (GtkToggleAction *toggle,
     return;
   priv->sending_video = active;
 
+  /* When we start sending video, we want to show the video preview by
+     default. */
+  if (priv->sending_video)
+    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview), TRUE);
+
   empathy_call_window_set_send_video (window, active);
   gtk_toggle_tool_button_set_active (
       GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), active);
@@ -1558,7 +1636,15 @@ static void
 empathy_call_window_show_preview_toggled_cb (GtkToggleAction *toggle,
   EmpathyCallWindow *window)
 {
-  /* FIXME: Not implemented */
+  gboolean show_preview_toggled;
+  EmpathyCallWindowPriv *priv = GET_PRIV (window);
+
+  show_preview_toggled = gtk_toggle_action_get_active (toggle);
+
+  if (show_preview_toggled)
+    gtk_widget_show (priv->self_user_output_frame);
+  else
+    gtk_widget_hide (priv->self_user_output_frame);
 }
 
 static void
diff --git a/src/empathy-call-window.ui b/src/empathy-call-window.ui
index a0e1e13..2214fcd 100644
--- a/src/empathy-call-window.ui
+++ b/src/empathy-call-window.ui
@@ -34,6 +34,7 @@
           <object class="GtkToggleAction" id="show_preview">
             <property name="name">show_preview</property>
             <property name="label" translatable="yes">Video preview</property>
+            <property name="active">True</property>
           </object>
         </child>
         <child>
