Пример #1
0
/**
 * gst_switch_server_new_record:
 *  @return: TRUE if succeeded.
 *
 *  Start a new recording.
 *  
 */
gboolean
gst_switch_server_new_record (GstSwitchServer * srv)
{
  GstWorkerClass *worker_class;
  gboolean result = FALSE;

  g_return_val_if_fail (GST_IS_RECORDER (srv->recorder), FALSE);

  if (srv->recorder) {
    GST_SWITCH_SERVER_LOCK_RECORDER (srv);
    if (srv->recorder) {
      gst_worker_stop (GST_WORKER (srv->recorder));
      g_object_set (G_OBJECT (srv->recorder),
          "mode", srv->composite->mode,
          "port", srv->composite->encode_sink_port,
          "width", srv->composite->width,
          "height", srv->composite->height, NULL);
      worker_class = GST_WORKER_CLASS (G_OBJECT_GET_CLASS (srv->recorder));
      if (worker_class->reset (GST_WORKER (srv->recorder))) {
        result = gst_worker_start (GST_WORKER (srv->recorder));
      } else {
        ERROR ("failed to reset composite recorder");
      }
    }
    GST_SWITCH_SERVER_UNLOCK_RECORDER (srv);
  }
  return result;
}
Пример #2
0
int
main (int argc, char **argv)
{
  gst_init (&argc, &argv);

  g_mutex_init (&trans_lock);

  mainloop = g_main_loop_new (NULL, TRUE);

  worker0 = GST_WORKER (g_object_new (GST_TYPE_WORKER,
          "name", "test-worker-0", NULL));

  worker0->pipeline_func = test_worker_pipeline;

  g_signal_connect (worker0, "prepare-worker",
      G_CALLBACK (test_worker_prepare), NULL);
  g_signal_connect (worker0, "start-worker",
      G_CALLBACK (test_worker_start), NULL);
  g_signal_connect (worker0, "end-worker", G_CALLBACK (test_worker_end), NULL);

  g_thread_new ("test-pulse", (GThreadFunc) test_worker_pulse, worker0);

  gst_worker_start (worker0);

  g_main_loop_run (mainloop);

  g_mutex_clear (&trans_lock);

  INFO ("end");
  return 0;
}
Пример #3
0
/**
 * gst_composite_apply_parameters:
 *
 * Applying new composite parameters such as PIP position. This is actually
 * resetting the composite pipeline with the new parameters.
 */
static void
gst_composite_apply_parameters (GstComposite * composite)
{
  GstWorkerClass *worker_class;

  g_return_if_fail (GST_IS_COMPOSITE (composite));

  worker_class = GST_WORKER_CLASS (G_OBJECT_GET_CLASS (composite));

  if (!worker_class->reset (GST_WORKER (composite))) {
    ERROR ("failed to reset composite");
  }
  /*
     if (!worker_class->reset (GST_WORKER (composite->output))) {
     ERROR ("failed to reset composite output");
     }
   */

  /*
     g_object_set (composite->recorder,
     "port", composite->encode_sink_port,
     "mode", composite->mode, "width", composite->width,
     "height", composite->height, NULL);

     if (!worker_class->reset (GST_WORKER (composite->recorder))) {
     ERROR ("failed to reset composite recorder");
     }
   */
}
Пример #4
0
static void
gst_switch_server_end_case (GstCase *cas, GstSwitchServer *srv)
{
  gint caseport = 0;
  GList *item;

  GST_SWITCH_SERVER_LOCK_CASES (srv);

  switch (cas->type) {
  default:
    srv->cases = g_list_remove (srv->cases, cas);
    INFO ("Removed %s (%p, %d) (%d cases left)", GST_WORKER (cas)->name,
	cas, G_OBJECT (cas)->ref_count,	g_list_length (srv->cases));
    caseport = cas->sink_port;
    g_object_unref (cas);
    break;
  case GST_CASE_INPUT_a:
  case GST_CASE_INPUT_v:
    srv->cases = g_list_remove (srv->cases, cas);
    INFO ("Removed %s %p (%d cases left)", GST_WORKER (cas)->name, cas,
	g_list_length (srv->cases));
    caseport = cas->sink_port;
    g_object_unref (cas);
    for (item = srv->cases; item;) {
      GstCase *c = GST_CASE (item->data);
      if (c->sink_port == caseport) {
	gst_worker_stop (GST_WORKER (c));
	item = g_list_next (item);
	/*
	srv->cases = g_list_remove (srv->cases, c);
	g_object_unref (G_OBJECT (c));
	*/
      } else {
	item = g_list_next (item);
      }
    }
    break;
  }

  GST_SWITCH_SERVER_UNLOCK_CASES (srv);

  if (caseport)
    gst_switch_server_revoke_port (srv, caseport);
}
Пример #5
0
/**
 * @brief
 * @param ui The GstSwitchUI instance.
 * @param port The compose port number.
 * @memberof GstSwitchUI
 */
static void
gst_switch_ui_set_compose_port (GstSwitchUI * ui, gint port)
{
  GstElement *overlay = NULL;

  GST_SWITCH_UI_LOCK_COMPOSE (ui);
  if (ui->compose) {
    gst_worker_stop (GST_WORKER (ui->compose));
    g_object_unref (ui->compose);
  }

  ui->compose = gst_switch_ui_new_video_disp (ui, ui->compose_view, port);
  overlay = gst_worker_get_element (GST_WORKER (ui->compose), "overlay");
  if (overlay) {
    g_signal_connect (overlay, "draw",
        G_CALLBACK (gst_switch_ui_compose_draw), ui);
  }
  GST_SWITCH_UI_UNLOCK_COMPOSE (ui);
}
Пример #6
0
/**
 * gst_composite_prepare:
 * @return TRUE if the composite pipeline is well prepared.
 *
 * Prepare the composite pipeline.
 */
static gboolean
gst_composite_prepare (GstComposite * composite)
{
  g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE);

  if (composite->scaler == NULL) {
    composite->scaler = GST_WORKER (g_object_new (GST_TYPE_WORKER,
            "name", "scale", NULL));
    composite->scaler->pipeline_func_data = composite;
    composite->scaler->pipeline_func = (GstWorkerGetPipelineString)
        gst_composite_get_scaler_string;
  } else {
    GstWorkerClass *worker_class;
    worker_class = GST_WORKER_CLASS (G_OBJECT_GET_CLASS (composite->scaler));
    if (!worker_class->reset (GST_WORKER (composite->scaler))) {
      ERROR ("failed to reset scaler");
    }
  }
  return TRUE;
}
Пример #7
0
static gboolean
gst_switch_ptz_prepare (GstSwitchPTZ * ptz)
{
  GstWorker *worker = GST_WORKER (ptz);
  GstElement *sink = gst_worker_get_element_unlocked (worker, "sink");
  gulong handle = GDK_WINDOW_XID (gtk_widget_get_window (ptz->video_view));
  g_return_val_if_fail (GST_IS_ELEMENT (sink), FALSE);
  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), handle);
  gst_object_unref (sink);
  return TRUE;
}
Пример #8
0
/**
 * @brief
 * @param ui The GstSwitchUI instance.
 * @param worker
 * @memberof GstSwitchUI
 */
static void
gst_switch_ui_end_audio_visual (GstWorker * worker, GstSwitchUI * ui)
{
  GstAudioVisual *visual = GST_AUDIO_VISUAL (worker);
  INFO ("audio ended: %s, %d", worker->name, visual->port);
  if (visual->renewing) {
    g_object_unref (GST_WORKER (visual));
  } else {
    gst_switch_ui_remove_preview (ui, worker, "audio-visual");
  }
}
Пример #9
0
/**
 * gst_switch_server_prepare_composite:
 * @return TRUE if the composite worker is prepared.
 *
 * Preparing the composite worker.
 */
static gboolean
gst_switch_server_prepare_composite (GstSwitchServer * srv,
    GstCompositeMode mode)
{
  gint port, encode;

  if (srv->composite) {
    return TRUE;
  }

  port = gst_switch_server_alloc_port (srv);
  encode = gst_switch_server_alloc_port (srv);

  INFO ("Compose sink to %d, %d", port, encode);

  g_assert (srv->composite == NULL);
  srv->composite = GST_COMPOSITE (g_object_new (GST_TYPE_COMPOSITE,
          "name", "composite", "port",
          port, "encode", encode, "mode", mode, NULL));

  g_signal_connect (srv->composite, "start-worker",
      G_CALLBACK (gst_switch_server_worker_start), srv);
  g_signal_connect (srv->composite, "worker-null",
      G_CALLBACK (gst_switch_server_worker_null), srv);

  /*
     g_signal_connect (srv->composite, "start-output",
     G_CALLBACK (gst_switch_server_start_output), srv);
     g_signal_connect (srv->composite, "start-recorder",
     G_CALLBACK (gst_switch_server_start_recorder), srv);
   */
  g_signal_connect (srv->composite, "end-transition",
      G_CALLBACK (gst_switch_server_end_transition), srv);

  GST_SWITCH_SERVER_LOCK_PIP (srv);
  srv->pip_x = srv->composite->b_x;
  srv->pip_y = srv->composite->b_y;
  srv->pip_w = srv->composite->b_width;
  srv->pip_h = srv->composite->b_height;
  GST_SWITCH_SERVER_UNLOCK_PIP (srv);

  if (!gst_worker_start (GST_WORKER (srv->composite)))
    goto error_start_composite;

  return TRUE;

error_start_composite:
  {
    g_object_unref (srv->composite);
    srv->composite = NULL;
    return FALSE;
  }
}
Пример #10
0
/**
 * gst_composite_retry_adjustment:
 * @return Always FALSE to allow glib to cleanup the timeout source
 *
 * This is invoked when the pipeline is reporting errors and requiring PIP
 * adjustment.
 */
static gboolean
gst_composite_retry_adjustment (GstComposite * composite)
{
  g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE);

  if (composite->adjusting) {
    GST_COMPOSITE_LOCK_ADJUSTMENT (composite);
    if (composite->adjusting) {
      GstWorkerClass *worker_class;
      WARN ("adjusting PIP error, retry..");
      worker_class = GST_WORKER_CLASS (G_OBJECT_GET_CLASS (composite));
      if (!worker_class->reset (GST_WORKER (composite))) {
        ERROR ("failed to reset composite");
      }
      gst_worker_start (GST_WORKER (composite));
    }
    GST_COMPOSITE_UNLOCK_ADJUSTMENT (composite);
  }

  return FALSE;
}
Пример #11
0
/**
 * @brief Initialize the GstRecorder instance.
 * @param rec The GstRecorder instance.
 * @memberof GstRecorder
 */
static void
gst_recorder_init (GstRecorder * rec)
{
  rec->sink_port = 0;
  rec->mode = 0;
  rec->width = 0;
  rec->height = 0;

  // Recording pipeline needs clean shut-down
  // via EOS to close out each recording
  GST_WORKER (rec)->send_eos_on_stop = TRUE;
  //INFO ("init %p", rec);
}
Пример #12
0
/**
 * @brief
 * @param ui The GstSwitchUI instance.
 * @param frame
 * @param visual
 * @memberof GstSwitchUI
 */
static GstAudioVisual *
gst_switch_ui_renew_audio_visual (GstSwitchUI * ui, GtkWidget * frame,
    GstAudioVisual * visual)
{
  gulong handle = visual->handle;
  gint port = visual->port;

  visual->renewing = TRUE;
  gst_worker_stop (GST_WORKER (visual));

  visual = gst_switch_ui_new_audio_visual_unsafe (ui, NULL, handle, port);

  g_object_set_data (G_OBJECT (frame), "audio-visual", visual);
  return visual;
}
Пример #13
0
/**
 * @brief
 * @param disp The GstVideoDisp instance.
 * @memberof GstVideoDisp
 */
static gboolean
gst_video_disp_prepare (GstVideoDisp * disp)
{
  GstWorker *worker = GST_WORKER (disp);
  GstElement *sink = gst_worker_get_element_unlocked (worker, "sink");

  g_return_val_if_fail (GST_IS_ELEMENT (sink), FALSE);

  gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), disp->handle);

  gst_object_unref (sink);

  //INFO ("prepared display video on %ld", disp->handle);
  return TRUE;
}
Пример #14
0
/**
 * gst_composite_start_transition:
 *
 * Start the new transtition request, this will set the %transition flag into
 * TRUE.
 */
static void
gst_composite_start_transition (GstComposite * composite)
{
  g_return_if_fail (GST_IS_COMPOSITE (composite));

  GST_COMPOSITE_LOCK_TRANSITION (composite);

  if (gst_composite_ready_for_transition (composite)) {
    composite->transition = gst_worker_stop (GST_WORKER (composite));
    /*
       INFO ("transtion ok=%d, %d, %dx%d", composite->transition,
       composite->mode, composite->width, composite->height);
     */
  }

  GST_COMPOSITE_UNLOCK_TRANSITION (composite);
}
Пример #15
0
/**
 * @brief
 * @param ui The GstSwitchUI instance.
 * @param view
 * @param port
 * @memberof GstSwitchUI
 */
static GstVideoDisp *
gst_switch_ui_new_video_disp (GstSwitchUI * ui, GtkWidget * view, gint port)
{
  gchar *name = g_strdup_printf ("video-%d", port);
  GdkWindow *xview = gtk_widget_get_window (view);
  GstVideoDisp *disp = GST_VIDEO_DISP (g_object_new (GST_TYPE_VIDEO_DISP,
          "name", name, "port",
          port,
          "handle",
          (gulong)
          GDK_WINDOW_XID (xview),
          NULL));
  g_free (name);
  g_object_set_data (G_OBJECT (view), "video-display", disp);
  if (!gst_worker_start (GST_WORKER (disp)))
    ERROR ("failed to start video display");
  return disp;
}
Пример #16
0
/**
 * gst_composite_retry_transition:
 * @return Always FALSE to allow glib to cleanup the timeout source
 *
 * This is invoked when the pipeline's getting errors to retry the transition
 * request.
 */
static gboolean
gst_composite_retry_transition (GstComposite * composite)
{
  g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE);

  if (composite->transition) {
    GST_COMPOSITE_LOCK_TRANSITION (composite);
    if (composite->transition) {
      WARN ("new mode %d, %dx%d (error transition)",
          composite->mode, composite->width, composite->height);
      gst_composite_apply_parameters (composite);
      gst_worker_start (GST_WORKER (composite));
    }
    GST_COMPOSITE_UNLOCK_TRANSITION (composite);
  }

  return FALSE;
}
Пример #17
0
/**
 * @param rec The GstRecorder instance.
 * @memberof GstRecorder
 * @return TRUE indicating the recorder is prepared, FALSE otherwise.
 *
 * Invoked when the GstWorker is preparing the pipeline.
 */
static gboolean
gst_recorder_prepare (GstRecorder * rec)
{
  GstElement *tcp_sink = NULL;

  g_return_val_if_fail (GST_IS_RECORDER (rec), FALSE);

  tcp_sink = gst_worker_get_element_unlocked (GST_WORKER (rec), "tcp_sink");

  g_return_val_if_fail (GST_IS_ELEMENT (tcp_sink), FALSE);

  g_signal_connect (tcp_sink, "client-added",
      G_CALLBACK (gst_recorder_client_socket_added), rec);

  g_signal_connect (tcp_sink, "client-socket-removed",
      G_CALLBACK (gst_recorder_client_socket_removed), rec);

  gst_object_unref (tcp_sink);
  return TRUE;
}
Пример #18
0
/**
 * gst_switch_server_create_output:
 * @return TRUE if the composite output worker is created.
 *
 * Create the composite output worker.
 */
static gboolean
gst_switch_server_create_output (GstSwitchServer * srv)
{
  if (srv->output) {
    return TRUE;
  }

  srv->output = GST_WORKER (g_object_new (GST_TYPE_WORKER,
          "name", "output", NULL));
  srv->output->pipeline_func_data = srv;
  srv->output->pipeline_func = (GstWorkerGetPipelineString)
      gst_switch_server_get_output_string;

  g_signal_connect (srv->output, "prepare-worker",
      G_CALLBACK (gst_switch_server_prepare_output), srv);
  g_signal_connect (srv->output, "start-worker",
      G_CALLBACK (gst_switch_server_start_output), srv);

  gst_worker_start (srv->output);
  return TRUE;
}
Пример #19
0
/**
 * @brief
 * @param ui The GstSwitchUI instance.
 * @param view
 * @param handle
 * @param port
 * @memberof GstSwitchUI
 */
static GstAudioVisual *
gst_switch_ui_new_audio_visual_unsafe (GstSwitchUI * ui, GtkWidget * view,
    gulong handle, gint port)
{
  gchar *name = g_strdup_printf ("visual-%d", port);
  GstAudioVisual *visual;

  if (view && handle == 0) {
    GdkWindow *xview = gtk_widget_get_window (view);
    handle = GDK_WINDOW_XID (xview);
  }

  visual =
      GST_AUDIO_VISUAL (g_object_new
      (GST_TYPE_AUDIO_VISUAL, "name", name, "port", port,
          "handle", handle, "active", (ui->audio_port == port), NULL));
  g_free (name);
  if (!gst_worker_start (GST_WORKER (visual)))
    ERROR ("failed to start audio visual");
  return visual;
}
Пример #20
0
/**
 * gst_switch_server_create_recorder:
 * @return TRUE if the recorder is created successfully.
 *
 * Creating the recorder.
 */
static gboolean
gst_switch_server_create_recorder (GstSwitchServer * srv)
{
  if (srv->recorder) {
    return TRUE;
  }

  GST_SWITCH_SERVER_LOCK_RECORDER (srv);
  srv->recorder = GST_RECORDER (g_object_new (GST_TYPE_RECORDER,
          "name", "recorder", "port",
          srv->composite->encode_sink_port, "mode",
          srv->composite->mode, "width",
          srv->composite->width, "height", srv->composite->height, NULL));

  g_signal_connect (srv->recorder, "start-worker",
      G_CALLBACK (gst_switch_server_start_recorder), srv);

  gst_worker_start (GST_WORKER (srv->recorder));
  GST_SWITCH_SERVER_UNLOCK_RECORDER (srv);
  return TRUE;
}
Пример #21
0
/**
 * @brief
 * @param ui The GstSwitchUI instance.
 * @param worker
 * @param name
 * @memberof GstSwitchUI
 */
static void
gst_switch_ui_remove_preview (GstSwitchUI * ui, GstWorker * worker,
    const gchar * name)
{
  GList *v = NULL;
  GST_SWITCH_UI_LOCK_SELECT (ui);
  v = gtk_container_get_children (GTK_CONTAINER (ui->preview_box));
  for (; v; v = g_list_next (v)) {
    GtkWidget *frame = GTK_WIDGET (v->data);
    gpointer data = g_object_get_data (G_OBJECT (frame), name);
    if (data && GST_IS_WORKER (data) && GST_WORKER (data) == worker) {
      if (ui->selected == frame) {
        GList *nxt = g_list_next (v);
        if (nxt == NULL)
          nxt = g_list_previous (v);
        ui->selected = nxt ? GTK_WIDGET (nxt->data) : NULL;
      }
      gtk_widget_destroy (frame);
      g_object_unref (worker);
    }
  }
  GST_SWITCH_UI_UNLOCK_SELECT (ui);
}
Пример #22
0
static void
gst_switch_ptz_run (GstSwitchPTZ * ptz)
{
  if (ptz->controller == NULL) {
#if 0
    GtkWidget *d = gtk_message_dialog_new (NULL,
        GTK_DIALOG_DESTROY_WITH_PARENT,
        GTK_MESSAGE_ERROR,
        GTK_BUTTONS_CLOSE,
        "You don't specify the correct protocol (check the -p option)!");
    gtk_dialog_run (GTK_DIALOG (d));
    gtk_widget_destroy (d);
#endif
    g_print ("You don't specify the correct protocol (check the -p option)!\n");
    return;
  }

  if (ptz->window) {
    gtk_widget_show_all (ptz->window);
    gst_worker_start (GST_WORKER (ptz));
    gtk_main ();
  }
}
Пример #23
0
/**
 * gst_composite_adjust_pip:
 *  @param composite The GstComposite instance
 *  @param x the X position of the PIP
 *  @param y the Y position of the PIP
 *  @param w the width of the PIP
 *  @param h the height of the PIP
 *  @return PIP has been changed succefully 
 *
 *  Change the PIP position and size.
 */
gboolean
gst_composite_adjust_pip (GstComposite * composite, gint x, gint y,
    gint w, gint h)
{
  gboolean result = FALSE;
  GstIterator *iter = NULL;
  GValue value = { 0 };
  GstElement *element = NULL;
  gboolean done = FALSE;

  g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE);

  GST_COMPOSITE_LOCK (composite);
  if (composite->adjusting) {
    WARN ("last PIP adjustment request is progressing");
    goto end;
  }

  composite->b_x = x;
  composite->b_y = y;

  if (composite->b_width != w || composite->b_height != h) {
    composite->b_width = w;
    composite->b_height = h;
    composite->adjusting = TRUE;
    gst_worker_stop (GST_WORKER (composite));
    result = TRUE;
    goto end;
  }

  element = gst_worker_get_element (GST_WORKER (composite), "mix");
  iter = gst_element_iterate_sink_pads (element);
  while (iter && !done) {
    switch (gst_iterator_next (iter, &value)) {
      case GST_ITERATOR_OK:
      {
        GstPad *pad = g_value_get_object (&value);
        if (g_strcmp0 (gst_pad_get_name (pad), "sink_1") == 0) {
          g_object_set (pad, "xpos", composite->b_x,
              "ypos", composite->b_y, NULL);
          done = TRUE;
          result = TRUE;
        }
        g_value_reset (&value);
      }
        break;
      case GST_ITERATOR_RESYNC:
        gst_iterator_resync (iter);
        break;
      case GST_ITERATOR_DONE:
        done = TRUE;
        break;
      default:
        /* iterator returned _ERROR or premature end with _OK,
         * mark an error and exit */
        done = TRUE;
        result = FALSE;
        break;
    }
  }

  if (G_IS_VALUE (&value))
    g_value_unset (&value);
  if (iter)
    gst_iterator_free (iter);

  composite->adjusting = FALSE;

  /*
     if (!result) {
     WARN ("failed to adjust PIP: %d, %d, %d, %d", x, y, w, h);
     }
   */

end:
  GST_COMPOSITE_UNLOCK (composite);
  return result;
}
Пример #24
0
gboolean
gst_switch_server_switch (GstSwitchServer * srv, gint channel, gint port)
{
  GList *item;
  gboolean result = FALSE;
  GstCase *compose_case, *candidate_case;
  GstCase *work1, *work2;
  GCallback callback = G_CALLBACK (gst_switch_server_end_case);
  gchar *name;

  compose_case = NULL;
  candidate_case = NULL;

  GST_SWITCH_SERVER_LOCK_CASES (srv);

  for (item = srv->cases; item; item = g_list_next (item)) {
    GstCase *cas = GST_CASE (item->data);
    switch (channel) {
    case 'A':
      if (cas->type == GST_CASE_COMPOSITE_A) goto get_target_stream;
      break;      
    case 'B':
      if (cas->type == GST_CASE_COMPOSITE_B) goto get_target_stream;
      break;
    case 'a':
      if (cas->type == GST_CASE_COMPOSITE_a) goto get_target_stream;
      break;
    default:
      WARN ("unknown channel %c", (gchar) channel);
      break;
    get_target_stream:
      if (compose_case == NULL) {
	compose_case = cas;
      }
    }
    switch (cas->type) {
    case GST_CASE_COMPOSITE_A:
    case GST_CASE_COMPOSITE_B:
    case GST_CASE_COMPOSITE_a:
    case GST_CASE_PREVIEW:
      if (cas->sink_port == port) {
	candidate_case = cas;
      }
    default:
      break;
    }
  }

  if (!candidate_case) {
    ERROR ("no stream for port %d (candidate)", port);
    goto end;
  }

  if (!compose_case) {
    ERROR ("no stream for port %d (compose)", port);
    goto end;
  }

  if (candidate_case == compose_case) {
    ERROR ("stream on %d already at %c", port, (gchar) channel);
    goto end;
  }

  INFO ("switching: %s (%d), %s (%d)",
      GST_WORKER (compose_case)->name, compose_case->type,
      GST_WORKER (candidate_case)->name, candidate_case->type);

  if (candidate_case->serve_type != compose_case->serve_type) {
    ERROR ("stream type not matched");
    goto end;
  }

  name = g_strdup (GST_WORKER (compose_case)->name);
  work1 = GST_CASE (g_object_new (GST_TYPE_CASE, "name", name,
	  "type",    compose_case->type,
	  "serve",   compose_case->serve_type,
	  "port",    candidate_case->sink_port,
	  "input",   candidate_case->input,
	  "branch",  candidate_case->branch,
	  NULL));
  g_free (name);

  name = g_strdup (GST_WORKER (candidate_case)->name);
  work2 = GST_CASE (g_object_new (GST_TYPE_CASE, "name", name,
	  "type",    candidate_case->type,
	  "serve",   candidate_case->serve_type,
	  "port",    compose_case->sink_port,
	  "input",   compose_case->input,
	  "branch",  compose_case->branch,
	  NULL));
  g_free (name);

  if (compose_case->serve_type == GST_SERVE_VIDEO_STREAM) {
    g_object_set (work1,
	"awidth",  compose_case->a_width,
	"aheight", compose_case->a_height,
	"bwidth",  compose_case->b_width,
	"bheight", compose_case->b_height,
	NULL);
    g_object_set (work2,
	"awidth",  candidate_case->a_width,
	"aheight", candidate_case->a_height,
	"bwidth",  candidate_case->b_width,
	"bheight", candidate_case->b_height,
	NULL);
  } else {
    g_signal_connect (G_OBJECT (work1), "start-worker",
	G_CALLBACK (gst_switch_server_start_audio), srv);
  }

  compose_case->switching = TRUE;
  candidate_case->switching = TRUE;
  gst_worker_stop (GST_WORKER (compose_case));
  gst_worker_stop (GST_WORKER (candidate_case));

  g_signal_connect (work1, "end-worker", callback, srv);
  g_signal_connect (work2, "end-worker", callback, srv);

  if (!gst_worker_start (GST_WORKER (work1)))
    goto error_start_work;
  if (!gst_worker_start (GST_WORKER (work2)))
    goto error_start_work;

  srv->cases = g_list_append (srv->cases, work1);
  srv->cases = g_list_append (srv->cases, work2);

  result = TRUE;

  INFO ("switched: %s <-> %s",
      GST_WORKER (work1)->name, GST_WORKER (work2)->name);

 end:
  GST_SWITCH_SERVER_UNLOCK_CASES (srv);
  return result;

 error_start_work:
  {
    ERROR ("failed to start works");
    g_object_unref (work1);
    g_object_unref (work2);
    GST_SWITCH_SERVER_UNLOCK_CASES (srv);
    return result;
  }
}
Пример #25
0
static void
gst_switch_server_serve (GstSwitchServer *srv, GSocket *client,
    GstSwitchServeStreamType serve_type)
{
  GSocketInputStreamX *stream = G_SOCKET_INPUT_STREAM (g_object_new (
	  G_TYPE_SOCKET_INPUT_STREAM, "socket", client, NULL));
  GstCaseType type = GST_CASE_UNKNOWN;
  GstCaseType inputtype = GST_CASE_UNKNOWN;
  GstCaseType branchtype = GST_CASE_UNKNOWN;
  gint num_cases = g_list_length (srv->cases);
  GstCase *input = NULL, *branch = NULL, *workcase = NULL;
  gchar *name;
  gint port = 0;
  GCallback start_callback = G_CALLBACK (gst_switch_server_start_case);
  GCallback end_callback = G_CALLBACK (gst_switch_server_end_case);

  GST_SWITCH_SERVER_LOCK_SERVE (srv);
  GST_SWITCH_SERVER_LOCK_CASES (srv);
  switch (serve_type) {
  case GST_SERVE_AUDIO_STREAM: inputtype = GST_CASE_INPUT_a; break;
  case GST_SERVE_VIDEO_STREAM: inputtype = GST_CASE_INPUT_v; break;
  default: goto error_unknown_serve_type;
  }

  type = gst_switch_server_suggest_case_type (srv, serve_type);
  switch (type) {
  case GST_CASE_COMPOSITE_A: branchtype = GST_CASE_BRANCH_A; break;
  case GST_CASE_COMPOSITE_B: branchtype = GST_CASE_BRANCH_B; break;
  case GST_CASE_COMPOSITE_a: branchtype = GST_CASE_BRANCH_a; break;
  case GST_CASE_PREVIEW:     branchtype = GST_CASE_BRANCH_p; break;
  default: goto error_unknown_case_type;
  }

  port = gst_switch_server_alloc_port (srv);

  //INFO ("case-type: %d, %d, %d", type, branchtype, port);

  name = g_strdup_printf ("input_%d", port);
  input = GST_CASE (g_object_new (GST_TYPE_CASE, "name", name,
	  "type", inputtype, "port", port, "serve", serve_type,
	  "stream", stream, NULL));
  g_object_unref (stream);
  g_object_unref (client);
  g_free (name);

  name = g_strdup_printf ("branch_%d", port);
  branch = GST_CASE (g_object_new (GST_TYPE_CASE, "name", name,
	  "type", branchtype, "port", port, "serve", serve_type, NULL));
  g_free (name);

  name = g_strdup_printf ("case-%d", num_cases);
  workcase = GST_CASE (g_object_new (GST_TYPE_CASE, "name", name,
	  "type", type, "port", port, "serve", serve_type,
	  "input", input, "branch", branch, NULL));
  g_free (name);

  srv->cases = g_list_append (srv->cases, input);
  srv->cases = g_list_append (srv->cases, branch);
  srv->cases = g_list_append (srv->cases, workcase);
  GST_SWITCH_SERVER_UNLOCK_CASES (srv);

  if (serve_type == GST_SERVE_VIDEO_STREAM) {
    g_object_set (input,
	"awidth",  srv->composite->a_width,
	"aheight", srv->composite->a_height,
	"bwidth",  srv->composite->b_width,
	"bheight", srv->composite->b_height,
	NULL);
    g_object_set (branch,
	"awidth",  srv->composite->a_width,
	"aheight", srv->composite->a_height,
	"bwidth",  srv->composite->b_width,
	"bheight", srv->composite->b_height,
	NULL);
    g_object_set (workcase,
	"awidth",  srv->composite->a_width,
	"aheight", srv->composite->a_height,
	"bwidth",  srv->composite->b_width,
	"bheight", srv->composite->b_height,
	NULL);
  }

  g_signal_connect (branch, "start-worker", start_callback, srv);
  g_signal_connect (input, "end-worker", end_callback, srv);
  g_signal_connect (branch, "end-worker", end_callback, srv);
  g_signal_connect (workcase, "end-worker", end_callback, srv);

  if (!gst_worker_start (GST_WORKER (input)))
    goto error_start_branch;
  if (!gst_worker_start (GST_WORKER (branch)))
    goto error_start_branch;
  if (!gst_worker_start (GST_WORKER (workcase)))
    goto error_start_workcase;

  GST_SWITCH_SERVER_UNLOCK_SERVE (srv);
  return;

  /* Errors Handling */
 error_unknown_serve_type:
  {
    ERROR ("unknown serve type %d", serve_type);
    g_object_unref (stream);
    g_object_unref (client);
    GST_SWITCH_SERVER_UNLOCK_CASES (srv);
    GST_SWITCH_SERVER_UNLOCK_SERVE (srv);
    return;
  }

 error_unknown_case_type:
  {
    ERROR ("unknown case type (serve type %d)", serve_type);
    g_object_unref (stream);
    g_object_unref (client);
    GST_SWITCH_SERVER_UNLOCK_CASES (srv);
    GST_SWITCH_SERVER_UNLOCK_SERVE (srv);
    return;
  }

 error_start_branch:
 error_start_workcase:
  {
    ERROR ("failed serving new client");
    GST_SWITCH_SERVER_LOCK_CASES (srv);
    srv->cases = g_list_remove (srv->cases, branch);
    srv->cases = g_list_remove (srv->cases, workcase);
    GST_SWITCH_SERVER_UNLOCK_CASES (srv);
    g_object_unref (stream);
    g_object_unref (branch);
    g_object_unref (workcase);
    gst_switch_server_revoke_port (srv, port);
    GST_SWITCH_SERVER_UNLOCK_SERVE (srv);
    return;
  }
}