static void gst_vtdec_enqueue_frame (void *data1, void *data2, VTStatus result, VTDecodeInfoFlags info, CVBufferRef cvbuf, CMTime pts, CMTime duration) { GstVTDec *self = GST_VTDEC_CAST (data1); GstBuffer *src_buf = GST_BUFFER (data2); GstBuffer *buf; if (result != kVTSuccess) { GST_ERROR_OBJECT (self, "Error decoding frame %d", result); goto beach; } if (kVTDecodeInfo_FrameDropped & info) { GST_WARNING_OBJECT (self, "Frame dropped"); goto beach; } buf = gst_core_video_buffer_new (cvbuf, &self->vinfo); gst_buffer_copy_into (buf, src_buf, GST_BUFFER_COPY_METADATA, 0, -1); GST_BUFFER_PTS (buf) = pts.value; GST_BUFFER_DURATION (buf) = duration.value; g_queue_push_head (self->cur_outbufs, buf); if (GST_BUFFER_PTS (src_buf) <= GST_BUFFER_DTS (src_buf)) { GST_LOG_OBJECT (self, "Flushing interal queue of buffers"); self->flush = TRUE; } else { GST_LOG_OBJECT (self, "Queuing buffer"); } beach: return; }
static void gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2, CVBufferRef cvbuf) { GstVTDec *self = GST_VTDEC_CAST (data); GstBuffer *buf; if (result != kVTSuccess) goto beach; buf = gst_core_video_buffer_new (self->ctx, cvbuf, &self->vinfo); gst_buffer_copy_into (buf, self->cur_inbuf, GST_BUFFER_COPY_METADATA, 0, -1); g_ptr_array_add (self->cur_outbufs, buf); beach: return; }
static GstStateChangeReturn gst_vtdec_change_state (GstElement * element, GstStateChange transition) { GstVTDec *self = GST_VTDEC_CAST (element); GError *error = NULL; GstStateChangeReturn ret; if (transition == GST_STATE_CHANGE_NULL_TO_READY) { self->ctx = gst_core_media_ctx_new (GST_API_CORE_VIDEO | GST_API_CORE_MEDIA | GST_API_VIDEO_TOOLBOX, &error); if (error != NULL) goto api_error; self->cur_outbufs = g_ptr_array_new (); } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (transition == GST_STATE_CHANGE_READY_TO_NULL) { gst_vtdec_destroy_session (self, &self->session); self->ctx->cm->FigFormatDescriptionRelease (self->fmt_desc); self->fmt_desc = NULL; gst_video_info_init (&self->vinfo); g_ptr_array_free (self->cur_outbufs, TRUE); self->cur_outbufs = NULL; g_object_unref (self->ctx); self->ctx = NULL; } return ret; api_error: { GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("API error"), ("%s", error->message)); g_clear_error (&error); return GST_STATE_CHANGE_FAILURE; } }
static GstFlowReturn gst_vtdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstVTDec *self = GST_VTDEC_CAST (parent); if (!gst_vtdec_is_negotiated (self)) goto not_negotiated; if (self->session == NULL) goto pending_caps; return gst_vtdec_decode_buffer (self, buf); not_negotiated: GST_DEBUG_OBJECT (self, "chain called while not negotiated"); gst_buffer_unref (buf); return GST_FLOW_NOT_NEGOTIATED; pending_caps: gst_buffer_unref (buf); GST_DEBUG_OBJECT (self, "dropped buffer %p (waiting for complete caps)", buf); return GST_FLOW_OK; }
static gboolean gst_vtdec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstVTDec *self = GST_VTDEC_CAST (parent); gboolean forward = TRUE; gboolean res = TRUE; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); res = gst_vtdec_sink_setcaps (self, caps); } default: break; } if (forward) res = gst_pad_event_default (pad, parent, event); return res; }