static gboolean gst_goo_encpcm_event (GstPad* pad, GstEvent* event) { GstGooEncPcm* self = GST_GOO_ENCPCM (gst_pad_get_parent (pad)); gboolean ret = FALSE; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: GST_INFO_OBJECT (self, "New segement event"); ret = gst_pad_push_event (self->srcpad, event); break; case GST_EVENT_EOS: GST_INFO_OBJECT (self, "EOS event"); omx_wait_for_done (self); ret = gst_pad_push_event (self->srcpad, event); break; default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (self); return ret; }
static void omx_output_buffer_cb (GooPort* port, OMX_BUFFERHEADERTYPE* buffer, gpointer data) { g_return_if_fail (buffer->nFlags != OMX_BUFFERFLAG_DATACORRUPT); g_assert (GOO_IS_PORT (port)); g_assert (buffer != NULL); g_assert (GOO_IS_COMPONENT (data)); GooComponent* component = GOO_COMPONENT (data); GstGooEncPcm* self = GST_GOO_ENCPCM ( g_object_get_data (G_OBJECT (data), "gst") ); g_assert (self != NULL); { process_output_buffer (self, buffer); if (buffer->nFlags == OMX_BUFFERFLAG_EOS || goo_port_is_eos (port)) { GST_INFO_OBJECT (self, "EOS found in output buffer (%d)", buffer->nFilledLen); goo_component_set_done (self->component); } } GST_INFO_OBJECT (self, ""); return; }
static GstStateChangeReturn gst_goo_encpcm_state_change (GstElement* element, GstStateChange transition) { g_assert (GST_IS_GOO_ENCPCM (element)); GstGooEncPcm* self = GST_GOO_ENCPCM (element); GstStateChangeReturn ret; switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: GST_DEBUG_OBJECT (self, "GST_STATE_CHANGE_READY_TO_PAUSED"); self->rate = 0; self->channels = 0; self->ts = 0; self->outcount = 0; gst_goo_adapter_clear (self->adapter); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: GST_OBJECT_LOCK (self); goo_component_set_state_pause (self->component); GST_OBJECT_UNLOCK (self); break; case GST_STATE_CHANGE_PAUSED_TO_READY: break; case GST_STATE_CHANGE_READY_TO_NULL: omx_stop (self); break; default: break; } return ret; }
static void gst_goo_encpcm_dispose (GObject* object) { G_OBJECT_CLASS (parent_class)->dispose (object); GstGooEncPcm* self = GST_GOO_ENCPCM (object); if (G_LIKELY (self->inport)) { GST_DEBUG ("unrefing outport"); g_object_unref (self->inport); } if (G_LIKELY (self->outport)) { GST_DEBUG ("unrefing outport"); g_object_unref (self->outport); } if (G_LIKELY (self->component)) { GST_DEBUG ("unrefing component"); G_OBJECT(self->component)->ref_count = 1; g_object_unref (self->component); } if (G_LIKELY (self->factory)) { GST_DEBUG ("unrefing factory"); g_object_unref (self->factory); } if (G_LIKELY (self->adapter)) { GST_DEBUG ("unrefing adapter"); g_object_unref (self->adapter); } return; }
static gboolean gst_goo_encpcm_setcaps (GstPad* pad, GstCaps* caps) { GstGooEncPcm *self = GST_GOO_ENCPCM (gst_pad_get_parent (pad)); GstStructure *structure; GstCaps *copy; structure = gst_caps_get_structure (caps, 0); /* get channel count */ gst_structure_get_int (structure, "channels", &self->channels); gst_structure_get_int (structure, "rate", &self->rate); /* this is not wrong but will sound bad */ if (self->channels != 1) { g_warning ("audio capture is optimized for mono channels"); } /* create reverse caps */ copy = gst_caps_new_simple ("audio/x-raw-int", "channels", G_TYPE_INT, self->channels, "rate", G_TYPE_INT, self->rate, NULL); /* precalc duration as it's constant now */ self->duration = gst_util_uint64_scale_int (160, GST_SECOND, self->rate * self->channels); gst_pad_set_caps (self->srcpad, copy); gst_caps_unref (copy); omx_start (self); gst_object_unref (self); GST_DEBUG_OBJECT (self, ""); return TRUE; }
static void gst_goo_encpcm_get_property (GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { g_assert (GST_IS_GOO_ENCPCM (object)); GstGooEncPcm* self = GST_GOO_ENCPCM (object); switch (prop_id) { case PROP_NUM_OUTPUT_BUFFERS: g_object_get_property (G_OBJECT (self->outport), "buffercount", value); break; case PROP_NUM_INPUT_BUFFERS: g_object_get_property (G_OBJECT (self->inport), "buffercount", value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } return; }
static GstFlowReturn gst_goo_encpcm_chain (GstPad* pad, GstBuffer* buffer) { GstGooEncPcm* self = GST_GOO_ENCPCM (gst_pad_get_parent (pad)); guint omxbufsiz = GOO_PORT_GET_DEFINITION (self->inport)->nBufferSize; GstFlowReturn ret; if (self->rate == 0 || self->channels == 0 || self->component->cur_state != OMX_StateExecuting) { goto not_negotiated; } if (goo_port_is_tunneled (self->inport)) { GST_DEBUG_OBJECT (self, "DASF Source"); OMX_BUFFERHEADERTYPE* omxbuf = NULL; omxbuf = goo_port_grab_buffer (self->outport); ret = process_output_buffer (self, omxbuf); return ret; } /* discontinuity clears adapter, FIXME, maybe we can set some * encoder flag to mask the discont. */ if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { gst_goo_adapter_clear (self->adapter); self->ts = 0; } /* take latest timestamp, FIXME timestamp is the one of the * first buffer in the adapter. */ if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) { self->ts = GST_BUFFER_TIMESTAMP (buffer); } ret = GST_FLOW_OK; GST_DEBUG_OBJECT (self, "Pushing a GST buffer to adapter (%d)", GST_BUFFER_SIZE (buffer)); gst_goo_adapter_push (self->adapter, buffer); /* Collect samples until we have enough for an output frame */ while (gst_goo_adapter_available (self->adapter) >= omxbufsiz) { GST_DEBUG_OBJECT (self, "Popping an OMX buffer"); OMX_BUFFERHEADERTYPE* omxbuf; omxbuf = goo_port_grab_buffer (self->inport); gst_goo_adapter_peek (self->adapter, omxbufsiz, omxbuf); omxbuf->nFilledLen = omxbufsiz; gst_goo_adapter_flush (self->adapter, omxbufsiz); goo_component_release_buffer (self->component, omxbuf); } GST_DEBUG_OBJECT (self, ""); return ret; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (self, STREAM, TYPE_NOT_FOUND, (NULL), ("unknown type")); return GST_FLOW_NOT_NEGOTIATED; } }