static void type_instance_init (GTypeInstance *instance, gpointer g_class) { GstOmxBaseFilter21 *self; GstElementClass *element_class; GstOmxBaseFilter21Class *bclass; int i; char srcname[10]; element_class = GST_ELEMENT_CLASS (g_class); bclass = GST_OMX_BASE_FILTER21_CLASS (g_class); self = GST_OMX_BASE_FILTER21 (instance); GST_LOG_OBJECT (self, "begin"); self->gomx = g_omx_core_new (self, g_class); for (i = 0; i < NUM_INPUTS; i++) { sprintf(srcname, "in_%02x", i); self->input_port_index[i] = OMX_VSWMOSAIC_INPUT_PORT_START_INDEX + i; self->in_port[i] = g_omx_core_get_port (self->gomx, srcname, self->input_port_index[i]); self->in_port[i]->omx_allocate = TRUE; self->in_port[i]->share_buffer = FALSE; self->in_port[i]->port_index = self->input_port_index[i]; } self->output_port_index = OMX_VSWMOSAIC_OUTPUT_PORT_START_INDEX; self->out_port = g_omx_core_get_port (self->gomx, "out", self->output_port_index); self->out_port->buffer_alloc = buffer_alloc; self->out_port->omx_allocate = TRUE; self->out_port->share_buffer = FALSE; self->out_port->port_index = self->output_port_index; self->number_eos = 2; self->ready_lock = g_mutex_new (); self->collectpads = gst_collect_pads_new(); gst_collect_pads_set_function(self->collectpads, &collected_pads, self); for (i = 0; i < NUM_INPUTS; i++) { sprintf(srcname, "sink_%02x", i); self->sinkpad[i] = gst_pad_new_from_template (gst_element_class_get_pad_template (element_class, srcname), srcname); gst_pad_set_chain_function (self->sinkpad[i], bclass->pad_chain); gst_pad_set_event_function (self->sinkpad[i], bclass->pad_event); gst_pad_set_setcaps_function (self->sinkpad[i], GST_DEBUG_FUNCPTR (sink_setcaps)); gst_element_add_pad (GST_ELEMENT (self), self->sinkpad[i]); gst_collect_pads_add_pad(self->collectpads, self->sinkpad[i], sizeof(GstCollectData)); } self->srcpad= gst_pad_new_from_template (gst_element_class_get_pad_template (element_class, "src"), "src"); gst_pad_set_activatepush_function (self->srcpad, activate_push); gst_pad_set_setcaps_function (self->srcpad, GST_DEBUG_FUNCPTR (src_setcaps)); gst_element_add_pad (GST_ELEMENT (self), self->srcpad); self->duration = GST_CLOCK_TIME_NONE; self->sink_camera_timestamp = GST_CLOCK_TIME_NONE; self->out_framerate = NULL; GST_LOG_OBJECT (self, "end"); }
static void get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec) { GstOmxBaseFilter21 *self; self = GST_OMX_BASE_FILTER21 (obj); switch (prop_id) { case ARG_COMPONENT_ROLE: g_value_set_string (value, self->omx_role); break; case ARG_COMPONENT_NAME: g_value_set_string (value, self->omx_component); break; case ARG_LIBRARY_NAME: g_value_set_string (value, self->omx_library); break; case ARG_USE_TIMESTAMPS: g_value_set_boolean (value, self->gomx->use_timestamps); break; case ARG_GEN_TIMESTAMPS: g_value_set_boolean (value, self->gomx->gen_timestamps); break; case ARG_X_SINK_0: g_value_set_uint(value,self->x[0]); break; case ARG_Y_SINK_0: g_value_set_uint(value,self->y[0]); break; case ARG_X_SINK_1: g_value_set_uint(value,self->x[1]); break; case ARG_Y_SINK_1: g_value_set_uint(value,self->y[1]); break; case ARG_NUM_INPUT_BUFFERS: case ARG_NUM_OUTPUT_BUFFERS: { OMX_PARAM_PORTDEFINITIONTYPE param; GOmxPort *port = (prop_id == ARG_NUM_INPUT_BUFFERS) ? self->in_port[0] : self->out_port; G_OMX_PORT_GET_DEFINITION (port, ¶m); g_value_set_uint (value, param.nBufferCountActual); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; } }
static void type_instance_init (GTypeInstance *instance, gpointer g_class) { GstOmxBaseFilter21 *omx_base; omx_base = GST_OMX_BASE_FILTER21 (instance); omx_base->omx_setup = omx_setup; GST_DEBUG_OBJECT (omx_base, "start"); }
static gboolean sink_setcaps (GstPad *pad, GstCaps *caps) { GstStructure *structure; GstOmxBaseFilter21 *self; GOmxCore *gomx; GstVideoFormat format; int sink_number; self = GST_OMX_BASE_FILTER21 (GST_PAD_PARENT (pad)); if(strcmp(GST_PAD_NAME(pad), "sink_00") == 0){ sink_number=0; } else if(strcmp(GST_PAD_NAME(pad), "sink_01") == 0){ sink_number=1; } gomx = (GOmxCore *) self->gomx; GST_INFO_OBJECT (self, "setcaps (sink): %d", sink_number); GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, caps); g_return_val_if_fail (caps, FALSE); g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); structure = gst_caps_get_structure (caps, 0); g_return_val_if_fail (structure, FALSE); if (!gst_video_format_parse_caps_strided (caps, &format, &self->in_width[sink_number], &self->in_height[sink_number], &self->in_stride[sink_number])) { GST_WARNING_OBJECT (self, "width and/or height is not set in caps"); return FALSE; } if (!self->in_stride[sink_number]) { self->in_stride[sink_number] = gstomx_calculate_stride (self->in_width[sink_number], format); } { /* Output framerate correspond to the minimum input framerate */ const GValue *sink_framerate = NULL; sink_framerate = gst_structure_get_value (structure, "framerate"); if( GST_VALUE_HOLDS_FRACTION(sink_framerate) ) { if( self->out_framerate == NULL || gst_value_compare(sink_framerate, self->out_framerate) == GST_VALUE_LESS_THAN ) { self->out_framerate = sink_framerate; self->duration = gst_util_uint64_scale_int(GST_SECOND, gst_value_get_fraction_denominator(sink_framerate), gst_value_get_fraction_numerator(sink_framerate)); } } } return gst_pad_set_caps (pad, caps); }
static gboolean activate_push (GstPad *pad, gboolean active) { gboolean result = TRUE; GstOmxBaseFilter21 *self; int i; self = GST_OMX_BASE_FILTER21 (gst_pad_get_parent (pad)); if (active) { GST_DEBUG_OBJECT (self, "activate"); self->last_pad_push_return = GST_FLOW_OK; /* we do not start the task yet if the pad is not connected */ if (gst_pad_is_linked (pad)) { if (self->ready) { /** @todo link callback function also needed */ for (i = 0; i < NUM_INPUTS; i++) g_omx_port_resume (self->in_port[i]); g_omx_port_resume (self->out_port); //result = gst_pad_start_task (pad, output_loop, pad); } } } else { GST_DEBUG_OBJECT (self, "deactivate"); if (self->ready) { /* unlock loops */ for (i = 0; i < NUM_INPUTS; i++) g_omx_port_pause (self->in_port[i]); g_omx_port_pause (self->out_port); } /* make sure streaming finishes */ result = gst_pad_stop_task (pad); } gst_object_unref (self); return result; }
static gboolean src_setcaps (GstPad *pad, GstCaps *caps) { GstOmxBaseFilter21 *self; GstVideoFormat format; GstStructure *structure; self = GST_OMX_BASE_FILTER21 (GST_PAD_PARENT (pad)); structure = gst_caps_get_structure (caps, 0); GST_INFO_OBJECT (self, "setcaps (src): %" GST_PTR_FORMAT, caps); g_return_val_if_fail (caps, FALSE); g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); if (!gst_video_format_parse_caps_strided (caps, &format, &self->out_width, &self->out_height, &self->out_stride)) { GST_WARNING_OBJECT (self, "width and/or height is not set in caps"); return FALSE; } if (!self->out_stride) { self->out_stride = gstomx_calculate_stride (self->out_width, format); } /* Set output framerate already calculated in sink_setcaps */ if( self->out_framerate == NULL ) { GST_WARNING_OBJECT (self, "unable to calculate output framerate"); return FALSE; } gint out_framerate_num = gst_value_get_fraction_numerator(self->out_framerate); gint out_framerate_denom = gst_value_get_fraction_denominator(self->out_framerate); gst_structure_set(structure, "framerate", GST_TYPE_FRACTION, out_framerate_num, out_framerate_denom, NULL); GST_INFO_OBJECT(self, "output framerate is: %d/%d", out_framerate_num, out_framerate_denom); /* save the src caps later needed by omx transport buffer */ if (self->out_port->caps) gst_caps_unref (self->out_port->caps); self->out_port->caps = gst_caps_copy (caps); return TRUE; }
static GstCaps * create_src_caps (GstOmxBaseFilter21 *omx_base) { GstCaps *caps; GstOmxBaseFilter21 *self; int width, height; GstStructure *struc; self = GST_OMX_BASE_FILTER21 (omx_base); caps = gst_pad_peer_get_caps (omx_base->srcpad); if (gst_caps_is_empty (caps)) { width = 1920; height = 1088; } else { GstStructure *s; s = gst_caps_get_structure (caps, 0); if (!(gst_structure_get_int (s, "width", &width) && gst_structure_get_int (s, "height", &height))) { width = 1920; height = 1088; } } caps = gst_caps_new_empty (); struc = gst_structure_new (("video/x-raw-yuv"), "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), NULL); gst_caps_append_structure (caps, struc); return caps; }
static void finalize (GObject *obj) { GstOmxBaseFilter21 *self; self = GST_OMX_BASE_FILTER21 (obj); if (self->codec_data) { gst_buffer_unref (self->codec_data); self->codec_data = NULL; } g_omx_core_free (self->gomx); g_free (self->omx_role); g_free (self->omx_component); g_free (self->omx_library); g_mutex_free (self->ready_lock); G_OBJECT_CLASS (parent_class)->finalize (obj); }
static void omx_setup (GstOmxBaseFilter21 *omx_base) { int i; GOmxCore *gomx; OMX_ERRORTYPE eError = OMX_ErrorNone; OMX_PARAM_BUFFER_MEMORYTYPE memTypeCfg; OMX_PARAM_PORTDEFINITIONTYPE paramPort; OMX_CONFIG_VSWMOSAIC_CREATEMOSAICLAYOUT sMosaic; OMX_CONFIG_VSWMOSAIC_SETBACKGROUNDCOLOR sMosaicBg; OMX_PARAM_VSWMOSAIC_MOSAIC_PERIODICITY sMosaicFPS; GstOmxBaseFilter21 *self; gomx = (GOmxCore *) omx_base->gomx; self = GST_OMX_BASE_FILTER21(omx_base); GST_LOG_OBJECT (self, "begin"); /* set the output cap */ gst_pad_set_caps (self->srcpad, create_src_caps (omx_base)); /* Setting Memory type at input port to Raw Memory */ GST_LOG_OBJECT (self, "Setting input port to Raw memory"); _G_OMX_INIT_PARAM (&memTypeCfg); memTypeCfg.eBufMemoryType = OMX_BUFFER_MEMORY_DEFAULT; for ( i = 0; i < NUM_INPUTS; i++) { memTypeCfg.nPortIndex = omx_base->in_port[i]->port_index; eError = OMX_SetParameter (gomx->omx_handle, OMX_TI_IndexParamBuffMemType, &memTypeCfg); if (eError != OMX_ErrorNone) { return; } } /* Setting Memory type at output port to Raw Memory */ GST_LOG_OBJECT (self, "Setting output port to Raw memory"); memTypeCfg.nPortIndex = omx_base->out_port->port_index; memTypeCfg.eBufMemoryType = OMX_BUFFER_MEMORY_DEFAULT; eError = OMX_SetParameter (gomx->omx_handle, OMX_TI_IndexParamBuffMemType, &memTypeCfg); if (eError != OMX_ErrorNone) { return; } GST_LOG_OBJECT (self, "Setting port definition (input)"); for ( i = 0; i < NUM_INPUTS; i++) { /* set input height/width and color format */ G_OMX_PORT_GET_DEFINITION (omx_base->in_port[i], ¶mPort); paramPort.format.video.nFrameWidth = self->in_width[i]; paramPort.format.video.nFrameHeight = self->in_height[i]; /* swmosaic is connceted to scalar, whose stride is different than width*/ paramPort.format.video.nStride = self->in_stride[i]; paramPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; paramPort.format.video.eColorFormat = OMX_COLOR_FormatYCbYCr; paramPort.nBufferSize = (paramPort.format.video.nStride * paramPort.format.video.nFrameHeight); paramPort.nBufferAlignment = 0; paramPort.bBuffersContiguous = 0; G_OMX_PORT_SET_DEFINITION (omx_base->in_port[i], ¶mPort); g_omx_port_setup (omx_base->in_port[i], ¶mPort); } G_OMX_PORT_GET_DEFINITION (omx_base->out_port, ¶mPort); paramPort.format.video.nFrameWidth = self->out_width; paramPort.format.video.nFrameHeight = self->out_height; paramPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; paramPort.format.video.eColorFormat = OMX_COLOR_FormatYCbYCr; paramPort.nBufferAlignment = 0; paramPort.bBuffersContiguous = 0; paramPort.nBufferCountActual = 4; paramPort.format.video.nStride = self->out_stride; paramPort.nBufferSize = paramPort.format.video.nStride * paramPort.format.video.nFrameHeight; G_OMX_PORT_SET_DEFINITION (omx_base->out_port, ¶mPort); g_omx_port_setup (omx_base->out_port, ¶mPort); _G_OMX_INIT_PARAM (&sMosaic); sMosaic.nPortIndex = OMX_VSWMOSAIC_OUTPUT_PORT_START_INDEX; sMosaic.nOpWidth = self->out_width; /* Width in pixels */ sMosaic.nOpHeight = self->out_height; /* Height in pixels */ sMosaic.nOpPitch = self->out_stride; /* Pitch in bytes */ sMosaic.nNumWindows = 2; sMosaic.sMosaicWinFmt[0].dataFormat = OMX_COLOR_FormatYCbYCr; sMosaic.sMosaicWinFmt[0].nPortIndex = 0; sMosaic.sMosaicWinFmt[0].pitch[0] = self->in_stride[0]; sMosaic.sMosaicWinFmt[0].winStartX = self->x[0]; sMosaic.sMosaicWinFmt[0].winStartY = self->y[0]; sMosaic.sMosaicWinFmt[0].winWidth = self->in_width[0]; sMosaic.sMosaicWinFmt[0].winHeight = self->in_height[0]; sMosaic.sMosaicWinFmt[1].dataFormat = OMX_COLOR_FormatYCbYCr; sMosaic.sMosaicWinFmt[1].nPortIndex = 1; sMosaic.sMosaicWinFmt[1].pitch[0] = self->in_stride[1]; sMosaic.sMosaicWinFmt[1].winStartX = self->x[1]; sMosaic.sMosaicWinFmt[1].winStartY = self->y[1]; sMosaic.sMosaicWinFmt[1].winWidth = self->in_width[1]; sMosaic.sMosaicWinFmt[1].winHeight = self->in_height[1]; eError = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVSWMOSAICCreateMosaicLayout, &sMosaic); if (eError != OMX_ErrorNone) { printf("Error during Layout settings\n"); } _G_OMX_INIT_PARAM(&sMosaicBg); sMosaicBg.nPortIndex = OMX_VSWMOSAIC_OUTPUT_PORT_START_INDEX; sMosaicBg.uColor = BG_COLOR; eError = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVSWMOSAICSetBackgroundColor, &sMosaicBg); if (eError != OMX_ErrorNone) { printf("Error during background\n"); } // FPS settings didn't work actually #if 1 _G_OMX_INIT_PARAM(&sMosaicFPS); sMosaicFPS.nPortIndex = OMX_VSWMOSAIC_OUTPUT_PORT_START_INDEX; sMosaicFPS.nFps = 60; eError = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexParamVSWMOSAICMosaicPeriodicity, &sMosaicFPS); if (eError != OMX_ErrorNone) { printf("Error during FPS settings : %s\n",g_omx_error_to_str (eError)); } #endif }
static gboolean pad_event (GstPad *pad, GstEvent *event) { GstOmxBaseFilter21 *self; GOmxCore *gomx; gboolean ret = TRUE; int i; self = GST_OMX_BASE_FILTER21 (GST_OBJECT_PARENT (pad)); gomx = self->gomx; GST_INFO_OBJECT (self, "begin: event=%s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: /* printf ("Recieved EOS event, press <CTRL+C> to terminate pipeline.\n"); */ g_mutex_lock (self->ready_lock); self->number_eos--; printf("EOS : %d\n",self->number_eos); g_mutex_unlock (self->ready_lock); if(self->number_eos == 0){ ret = gst_pad_push_event (self->srcpad, event); } else{ gst_event_unref (event); } break; case GST_EVENT_FLUSH_START: gst_event_ref(event); ret &= gst_pad_push_event (self->srcpad, event); self->last_pad_push_return = GST_FLOW_WRONG_STATE; g_omx_core_flush_start (gomx); gst_pad_pause_task (self->srcpad); ret = TRUE; break; case GST_EVENT_FLUSH_STOP: gst_event_ref(event); ret &= gst_pad_push_event (self->srcpad, event); self->last_pad_push_return = GST_FLOW_OK; g_omx_core_flush_stop (gomx); /*if (self->ready) gst_pad_start_task (self->srcpad, output_loop, self->srcpad);*/ ret = TRUE; break; case GST_EVENT_NEWSEGMENT: self->last_buf_timestamp = GST_CLOCK_TIME_NONE; gst_event_ref(event); ret &= gst_pad_push_event (self->srcpad, event); break; default: gst_event_ref(event); ret &= gst_pad_push_event (self->srcpad, event); break; } GST_LOG_OBJECT (self, "end"); return ret; }
static GstFlowReturn pad_chain (GstPad *pad, GstBuffer *buf) { GOmxCore *gomx; GOmxPort *in_port; GstOmxBaseFilter21 *self; GstFlowReturn ret = GST_FLOW_OK; int i; static sink_init = 0; int sink_number; static gboolean init_done = FALSE; self = GST_OMX_BASE_FILTER21 (GST_OBJECT_PARENT (pad)); if(strcmp(GST_PAD_NAME(pad), "sink_00") == 0){ sink_number=0; self->sink_camera_timestamp = GST_BUFFER_TIMESTAMP(buf); } else if(strcmp(GST_PAD_NAME(pad), "sink_01") == 0){ sink_number=1; } PRINT_BUFFER (self, buf); gomx = self->gomx; GST_LOG_OBJECT (self, "begin: size=%u, state=%d, sink_number=%d", GST_BUFFER_SIZE (buf), gomx->omx_state, sink_number); /*if (G_LIKELY (gomx->omx_state != OMX_StateExecuting)) { GST_INFO_OBJECT (self, "Begin - Port %d", sink_number); //setup_input_buffer (self, buf, sink_number); //sink_init++; //g_mutex_lock (self->ready_lock); if(init_done == TRUE){ GST_INFO_OBJECT (self, "Init_done"); //g_mutex_unlock(self->ready_lock); } if(init_done == TRUE){ sink_init = 0; init_done = FALSE; } else{ while(sink_init != 2){ usleep(1000); } } }*/ if (G_UNLIKELY (gomx->omx_state == OMX_StateLoaded)) { GST_INFO_OBJECT (self, "omx: prepare"); /** @todo this should probably go after doing preparations. */ if (self->omx_setup) { self->omx_setup (self); } /* enable input port */ for(i=0;i<NUM_INPUTS;i++){ GST_INFO_OBJECT (self,"Enable Port %d",self->in_port[i]->port_index); OMX_SendCommand (gomx->omx_handle, OMX_CommandPortEnable, self->in_port[i]->port_index, NULL); g_sem_down (self->in_port[i]->core->port_sem); } GST_INFO_OBJECT (self,"Enable Port %d",self->out_port->port_index); /* enable output port */ OMX_SendCommand (gomx->omx_handle,OMX_CommandPortEnable, self->out_port->port_index, NULL); g_sem_down (self->out_port->core->port_sem); /* indicate that port is now configured */ setup_ports (self); g_omx_core_prepare (self->gomx); if (gomx->omx_state == OMX_StateIdle) { self->ready = TRUE; //gst_pad_start_task (self->srcpad, output_loop, self->srcpad); } if (gomx->omx_state != OMX_StateIdle) goto out_flushing; GST_INFO_OBJECT (self, "omx: end state Loaded"); } if (G_UNLIKELY (gomx->omx_state == OMX_StateIdle)) { g_omx_core_start (gomx); GST_INFO_OBJECT (self, "Release Port - %d", sink_number); init_done = TRUE; //g_mutex_unlock (self->ready_lock); if (gomx->omx_state != OMX_StateExecuting){ GST_INFO_OBJECT (self, "omx: executing FAILED !"); goto out_flushing; } } if (G_LIKELY (self->in_port[sink_number]->enabled)) { if (G_UNLIKELY (gomx->omx_state != OMX_StateExecuting)) { GST_ERROR_OBJECT (self, "Whoa! very wrong"); } while (TRUE) { gint sent; if (self->last_pad_push_return != GST_FLOW_OK || !(gomx->omx_state == OMX_StateExecuting || gomx->omx_state == OMX_StatePause)) { GST_INFO_OBJECT (self, "last_pad_push_return=%d", self->last_pad_push_return); goto out_flushing; } sent = g_omx_port_send (self->in_port[sink_number], buf); if (G_UNLIKELY (sent < 0)) { ret = GST_FLOW_WRONG_STATE; goto out_flushing; } else if (sent < GST_BUFFER_SIZE (buf)) { GstBuffer *subbuf = gst_buffer_create_sub (buf, sent, GST_BUFFER_SIZE (buf) - sent); gst_buffer_unref (buf); buf = subbuf; } else { gst_buffer_unref (buf); break; } } } else { GST_WARNING_OBJECT (self, "done"); ret = GST_FLOW_UNEXPECTED; } return ret; leave: GST_LOG_OBJECT (self, "end"); return ret; /* special conditions */ out_flushing: { const gchar *error_msg = NULL; if (gomx->omx_error) { error_msg = "Error from OpenMAX component"; } else if (gomx->omx_state != OMX_StateExecuting && gomx->omx_state != OMX_StatePause) { error_msg = "OpenMAX component in wrong state"; } if (error_msg) { GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), (error_msg)); ret = GST_FLOW_ERROR; } gst_buffer_unref (buf); goto leave; } }
static void output_loop (gpointer data) { GstPad *pad; GOmxCore *gomx; GOmxPort *out_port; GstOmxBaseFilter21 *self; GstFlowReturn ret = GST_FLOW_OK; GstOmxBaseFilter21Class *bclass; pad = data; self = GST_OMX_BASE_FILTER21 (gst_pad_get_parent (pad)); gomx = self->gomx; bclass = GST_OMX_BASE_FILTER21_GET_CLASS (self); if (!self->ready) { g_error ("not ready"); return; } out_port = (GOmxPort *)gst_pad_get_element_private(pad); if (G_LIKELY (out_port->enabled)) { gpointer obj = g_omx_port_recv (out_port); if (G_UNLIKELY (!obj)) { GST_WARNING_OBJECT (self, "null buffer: leaving"); ret = GST_FLOW_WRONG_STATE; goto leave; } if (G_LIKELY (GST_IS_BUFFER (obj))) { if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) { GstCaps *caps = NULL; GstStructure *structure; GValue value = { 0 }; caps = gst_pad_get_negotiated_caps (pad); caps = gst_caps_make_writable (caps); structure = gst_caps_get_structure (caps, 0); g_value_init (&value, GST_TYPE_BUFFER); gst_value_set_buffer (&value, obj); gst_buffer_unref (obj); gst_structure_set_value (structure, "codec_data", &value); g_value_unset (&value); gst_pad_set_caps (pad, caps); } else { GstBuffer *buf = GST_BUFFER (obj); ret = bclass->push_buffer (self, buf); GST_DEBUG_OBJECT (self, "ret=%s", gst_flow_get_name (ret)); // HACK!! Dont care if one of the output pads are not connected ret = GST_FLOW_OK; } } else if (GST_IS_EVENT (obj)) { GST_INFO_OBJECT (self, "got eos"); gst_pad_push_event (pad, obj); ret = GST_FLOW_UNEXPECTED; goto leave; } } leave: self->last_pad_push_return = ret; if (gomx->omx_error != OMX_ErrorNone) { GST_INFO_OBJECT (self, "omx_error=%s", g_omx_error_to_str (gomx->omx_error)); ret = GST_FLOW_ERROR; } if (ret != GST_FLOW_OK) { GST_INFO_OBJECT (self, "pause task, reason: %s", gst_flow_get_name (ret)); gst_pad_pause_task (pad); } gst_object_unref (self); }
static void set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec) { GstOmxBaseFilter21 *self; self = GST_OMX_BASE_FILTER21(obj); switch (prop_id) { case ARG_COMPONENT_ROLE: g_free (self->omx_role); self->omx_role = g_value_dup_string (value); break; case ARG_COMPONENT_NAME: g_free (self->omx_component); self->omx_component = g_value_dup_string (value); break; case ARG_LIBRARY_NAME: g_free (self->omx_library); self->omx_library = g_value_dup_string (value); break; case ARG_USE_TIMESTAMPS: self->gomx->use_timestamps = g_value_get_boolean (value); break; case ARG_GEN_TIMESTAMPS: self->gomx->gen_timestamps = g_value_get_boolean (value); break; case ARG_X_SINK_0: self->x[0] = g_value_get_uint(value); break; case ARG_Y_SINK_0: self->y[0] = g_value_get_uint(value); break; case ARG_X_SINK_1: self->x[1] = g_value_get_uint(value); break; case ARG_Y_SINK_1: self->y[1] = g_value_get_uint(value); break; case ARG_NUM_INPUT_BUFFERS: { OMX_PARAM_PORTDEFINITIONTYPE param; OMX_U32 nBufferCountActual = g_value_get_uint (value); int i; for (i = 0; i < NUM_INPUTS; i++) { G_OMX_PORT_GET_DEFINITION (self->in_port[i], ¶m); g_return_if_fail (nBufferCountActual >= param.nBufferCountMin); param.nBufferCountActual = nBufferCountActual; G_OMX_PORT_SET_DEFINITION (self->in_port[i], ¶m); } } break; case ARG_NUM_OUTPUT_BUFFERS: { OMX_PARAM_PORTDEFINITIONTYPE param; OMX_U32 nBufferCountActual = g_value_get_uint (value); G_OMX_PORT_GET_DEFINITION (self->out_port, ¶m); g_return_if_fail (nBufferCountActual >= param.nBufferCountMin); param.nBufferCountActual = nBufferCountActual; G_OMX_PORT_SET_DEFINITION (self->out_port, ¶m); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; } }
static GstStateChangeReturn change_state (GstElement *element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstOmxBaseFilter21 *self; GOmxCore *core; int i; self = GST_OMX_BASE_FILTER21(element); core = self->gomx; printf("begin: changing state %s -> %s\n", gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); GST_INFO_OBJECT (self, "begin: changing state %s -> %s", gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: g_omx_core_init (core); if (core->omx_state != OMX_StateLoaded) { ret = GST_STATE_CHANGE_FAILURE; goto leave; } break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_collect_pads_start(self->collectpads); break; case GST_STATE_CHANGE_PAUSED_TO_READY: gst_collect_pads_stop(self->collectpads); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) goto leave; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: printf("Paused to ready\n"); g_mutex_lock (self->ready_lock); if (self->ready) { /* unlock */ for (i = 0; i < NUM_INPUTS; i++){ g_omx_port_finish (self->in_port[i]); } g_omx_port_finish (self->out_port); g_omx_core_stop (core); g_omx_core_unload (core); self->ready = FALSE; } g_mutex_unlock (self->ready_lock); if (core->omx_state != OMX_StateLoaded && core->omx_state != OMX_StateInvalid) { ret = GST_STATE_CHANGE_FAILURE; goto leave; } break; case GST_STATE_CHANGE_READY_TO_NULL: g_omx_core_deinit (core); break; default: break; } leave: GST_LOG_OBJECT (self, "end"); return ret; }