コード例 #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
ファイル: test_fd_leaks.c プロジェクト: bossjones/gst-switch
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
ファイル: gstcomposite.c プロジェクト: bossjones/gst-switch
/**
 * gst_composite_start:
 *
 * This is invokved when the composite pipeline started.
 */
static void
gst_composite_start (GstComposite * composite)
{
  g_return_if_fail (GST_IS_COMPOSITE (composite));

  gst_worker_start (composite->scaler);
}
コード例 #4
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;
  }
}
コード例 #5
0
ファイル: gstswitchui.c プロジェクト: jhenstridge/gst-switch
/**
 * @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;
}
コード例 #6
0
ファイル: gstcomposite.c プロジェクト: bossjones/gst-switch
/**
 * 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;
}
コード例 #7
0
ファイル: gstswitchui.c プロジェクト: jhenstridge/gst-switch
/**
 * @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;
}
コード例 #8
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;
}
コード例 #9
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;
}
コード例 #10
0
ファイル: gstcomposite.c プロジェクト: bossjones/gst-switch
/**
 * 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
ファイル: gstswitchptz.c プロジェクト: jhenstridge/gst-switch
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 ();
  }
}
コード例 #12
0
ファイル: gstswitchserver.c プロジェクト: thaytan/gst-switch
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;
  }
}
コード例 #13
0
ファイル: gstswitchserver.c プロジェクト: thaytan/gst-switch
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;
  }
}