guint gst_switch_server_adjust_pip (GstSwitchServer * srv, gint dx, gint dy, gint dw, gint dh) { guint result = 0; g_return_val_if_fail (GST_IS_COMPOSITE (srv->composite), 0); GST_SWITCH_SERVER_LOCK_PIP (srv); srv->pip_x += dx, srv->pip_y += dy; srv->pip_w += dw, srv->pip_h += dh; if (srv->pip_x < 0) srv->pip_x = 0; if (srv->pip_y < 0) srv->pip_y = 0; if (srv->pip_w < GST_SWITCH_COMPOSITE_MIN_PIP_W) srv->pip_w = GST_SWITCH_COMPOSITE_MIN_PIP_W; if (srv->pip_h < GST_SWITCH_COMPOSITE_MIN_PIP_H) srv->pip_h = GST_SWITCH_COMPOSITE_MIN_PIP_H; result = gst_composite_adjust_pip (srv->composite, srv->pip_x, srv->pip_y, srv->pip_w, srv->pip_h); if (dx != 0) result |= (1 << 0); if (dy != 0) result |= (1 << 1); if (dw != 0) result |= (1 << 2); if (dh != 0) result |= (1 << 3); GST_SWITCH_SERVER_UNLOCK_PIP (srv); return result; }
/** * gst_composite_end: * * This is invoked when the composite pipeline is ended. */ static void gst_composite_end (GstComposite * composite) { g_return_if_fail (GST_IS_COMPOSITE (composite)); gst_worker_stop (composite->scaler); }
gboolean gst_switch_server_new_record (GstSwitchServer * srv) { g_return_val_if_fail (GST_IS_COMPOSITE (srv->composite), FALSE); return gst_composite_new_record (srv->composite); }
/** * 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"); } */ }
/** * gst_composite_error: * * Handling the composite pipeline errors. */ static void gst_composite_error (GstComposite * composite) { g_return_if_fail (GST_IS_COMPOSITE (composite)); if (composite->transition) { g_timeout_add (10, (GSourceFunc) gst_composite_retry_transition, composite); } else if (composite->adjusting) { g_timeout_add (10, (GSourceFunc) gst_composite_retry_adjustment, composite); } }
/** * gst_composite_close_adjustment: * @return Always return false to let glib to cleanup timeout source * * Invoked when composite pipeline is coming alive and it's currently * adjusting the PIP. */ static gboolean gst_composite_close_adjustment (GstComposite * composite) { g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE); if (composite->adjusting) { GST_COMPOSITE_LOCK_ADJUSTMENT (composite); composite->adjusting = FALSE; GST_COMPOSITE_UNLOCK_ADJUSTMENT (composite); } return FALSE; }
/** * gst_composite_alive: * * Invoked when the compisite pipeline is online. */ static void gst_composite_alive (GstComposite * composite) { g_return_if_fail (GST_IS_COMPOSITE (composite)); if (composite->transition) { #if 0 g_timeout_add (10, (GSourceFunc) gst_composite_close_transition, composite); #else gst_composite_close_transition (composite); #endif } else if (composite->adjusting) { g_timeout_add (10, (GSourceFunc) gst_composite_close_adjustment, composite); } }
/** * gst_composite_close_transition: * * Invoked when the composite pipeline is coming alive. This will emit * %gst_composite_end_transition. * * @see %gst_composite_end_transition */ static gboolean gst_composite_close_transition (GstComposite * composite) { g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE); if (composite->transition) { GST_COMPOSITE_LOCK_TRANSITION (composite); if (composite->transition) { //gst_worker_start (GST_WORKER (composite->output)); /* It's ok to discard the source ID here, the timeout is one-shot. */ g_timeout_add (200, (GSourceFunc) gst_composite_end_transition, composite); } GST_COMPOSITE_UNLOCK_TRANSITION (composite); } return FALSE; }
/** * 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); }
/** * 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; }
/** * gst_composite_commit_adjustment: * @return Always FALSE to tell glib to cleanup the timeout source. * * Commit a PIP adjustment request. */ static gboolean gst_composite_commit_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; worker_class = GST_WORKER_CLASS (G_OBJECT_GET_CLASS (composite)); if (!worker_class->reset (GST_WORKER (composite))) { ERROR ("failed to reset composite"); } } GST_COMPOSITE_UNLOCK_ADJUSTMENT (composite); } return FALSE; }
/** * gst_composite_commit_transition: * @return Always return FALSE to tell glib to cleanup the event source. * * Commit a transition request. * * @see %gst_composite_end_transition */ static gboolean gst_composite_commit_transition (GstComposite * composite) { g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE); if (composite->transition) { GST_COMPOSITE_LOCK_TRANSITION (composite); if (composite->transition) { /* INFO ("new mode %d, %dx%d applying...", composite->mode, composite->width, composite->height); */ gst_composite_apply_parameters (composite); } GST_COMPOSITE_UNLOCK_TRANSITION (composite); } return FALSE; }
/** * gst_composite_null: * * Invoked when the composite pipeline is going NULL. */ static GstWorkerNullReturn gst_composite_null (GstComposite * composite) { g_return_val_if_fail (GST_IS_COMPOSITE (composite), GST_WORKER_NR_END); if (composite->transition) { #if 0 g_timeout_add (10, (GSourceFunc) gst_composite_commit_transition, composite); #else gst_composite_commit_transition (composite); #endif } else if (composite->adjusting) { g_timeout_add (10, (GSourceFunc) gst_composite_commit_adjustment, composite); } return composite->deprecated ? GST_WORKER_NR_END : GST_WORKER_NR_REPLAY; }
/** * 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; }
/** * gst_composite_end_transition: * @return Always return FALSE to allow glib to free the event source. * * Invoked when the transition is finished. * * @see %gst_composite_commit_transition */ static gboolean gst_composite_end_transition (GstComposite * composite) { g_return_val_if_fail (GST_IS_COMPOSITE (composite), FALSE); if (composite->transition) { GST_COMPOSITE_LOCK_TRANSITION (composite); if (composite->transition) { /* INFO ("new mode %d, %dx%d transited", composite->mode, composite->width, composite->height); */ composite->transition = FALSE; g_signal_emit (composite, gst_composite_signals[SIGNAL_END_TRANSITION], 0 /*, composite->mode */ ); } GST_COMPOSITE_UNLOCK_TRANSITION (composite); } return FALSE; }
/** * 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; }