From ebd2a6d6e9b18bf8e3f29c53735603444be0e7c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Wed, 10 Nov 2010 23:16:51 +0100 Subject: [PATCH] applemedia: don't push synchronously from callback The codec that called us might be holding locks to shared resources, so we should never push downstream from within its buffer callback. Note that a GstBufferList is not used here because we need to preserve the buffer metadata held by our GstBuffer subclasses. --- sys/applemedia/vtdec.c | 28 +++++++++++++++++++++------- sys/applemedia/vtdec.h | 2 +- sys/applemedia/vtenc.c | 29 +++++++++++++++++++++-------- sys/applemedia/vtenc.h | 2 +- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/sys/applemedia/vtdec.c b/sys/applemedia/vtdec.c index bd8c050576..eb5d2f1ac3 100644 --- a/sys/applemedia/vtdec.c +++ b/sys/applemedia/vtdec.c @@ -146,6 +146,8 @@ gst_vtdec_change_state (GstElement * element, GstStateChange transition) | 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); @@ -161,6 +163,9 @@ gst_vtdec_change_state (GstElement * element, GstStateChange transition) self->caps_width = self->caps_height = 0; self->caps_fps_n = self->caps_fps_d = 0; + g_ptr_array_free (self->cur_outbufs, TRUE); + self->cur_outbufs = NULL; + g_object_unref (self->ctx); self->ctx = NULL; } @@ -380,10 +385,10 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) GstVTApi *vt = self->ctx->vt; CMSampleBufferRef sbuf; VTStatus status; + GstFlowReturn ret = GST_FLOW_OK; + guint i; self->cur_inbuf = buf; - self->cur_flowret = GST_FLOW_OK; - sbuf = gst_vtdec_sample_buffer_from (self, buf); status = vt->VTDecompressionSessionDecodeFrame (self->session, sbuf, 0, 0, 0); @@ -399,11 +404,20 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) } self->ctx->cm->FigSampleBufferRelease (sbuf); - - gst_buffer_unref (buf); self->cur_inbuf = NULL; + gst_buffer_unref (buf); - return self->cur_flowret; + for (i = 0; i != self->cur_outbufs->len; i++) { + GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i); + + if (ret == GST_FLOW_OK) + ret = gst_pad_push (self->srcpad, buf); + else + gst_buffer_unref (buf); + } + g_ptr_array_set_size (self->cur_outbufs, 0); + + return ret; } static void @@ -413,7 +427,7 @@ gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, gsize unk2, GstVTDec *self = GST_VTDEC_CAST (data); GstBuffer *buf; - if (result != kVTSuccess || self->cur_flowret != GST_FLOW_OK) + if (result != kVTSuccess) goto beach; if (!gst_vtdec_negotiate_downstream (self)) @@ -424,7 +438,7 @@ gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, gsize unk2, gst_buffer_copy_metadata (buf, self->cur_inbuf, GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); - self->cur_flowret = gst_pad_push (self->srcpad, buf); + g_ptr_array_add (self->cur_outbufs, buf); beach: return; diff --git a/sys/applemedia/vtdec.h b/sys/applemedia/vtdec.h index 4176a09843..3ebb26f9a6 100644 --- a/sys/applemedia/vtdec.h +++ b/sys/applemedia/vtdec.h @@ -70,7 +70,7 @@ struct _GstVTDec VTDecompressionSessionRef session; GstBuffer * cur_inbuf; - GstFlowReturn cur_flowret; + GPtrArray * cur_outbufs; }; void gst_vtdec_register_elements (GstPlugin * plugin); diff --git a/sys/applemedia/vtenc.c b/sys/applemedia/vtenc.c index e286e90fe1..43a16229e1 100644 --- a/sys/applemedia/vtenc.c +++ b/sys/applemedia/vtenc.c @@ -286,6 +286,8 @@ gst_vtenc_change_state (GstElement * element, GstStateChange transition) | 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); @@ -307,6 +309,9 @@ gst_vtenc_change_state (GstElement * element, GstStateChange transition) GST_OBJECT_UNLOCK (self); + g_ptr_array_free (self->cur_outbufs, TRUE); + self->cur_outbufs = NULL; + g_object_unref (self->ctx); self->ctx = NULL; } @@ -713,9 +718,10 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf) CMTime ts, duration; CVPixelBufferRef pbuf = NULL; VTStatus vt_status; + GstFlowReturn ret = GST_FLOW_OK; + guint i; self->cur_inbuf = buf; - self->cur_flowret = GST_FLOW_OK; ts = self->ctx->cm->CMTimeMake (GST_TIME_AS_MSECONDS (GST_BUFFER_TIMESTAMP (buf)), 1000); @@ -761,16 +767,25 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf) GST_OBJECT_UNLOCK (self); cv->CVPixelBufferRelease (pbuf); - - gst_buffer_unref (buf); self->cur_inbuf = NULL; + gst_buffer_unref (buf); - return self->cur_flowret; + for (i = 0; i != self->cur_outbufs->len; i++) { + GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i); + + if (ret == GST_FLOW_OK) + ret = gst_pad_push (self->srcpad, buf); + else + gst_buffer_unref (buf); + } + g_ptr_array_set_size (self->cur_outbufs, 0); + + return ret; cv_error: { - gst_buffer_unref (buf); self->cur_inbuf = NULL; + gst_buffer_unref (buf); return GST_FLOW_ERROR; } @@ -810,9 +825,7 @@ gst_vtenc_output_buffer (void *data, int a2, int a3, int a4, GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); } - GST_OBJECT_UNLOCK (self); - self->cur_flowret = gst_pad_push (self->srcpad, buf); - GST_OBJECT_LOCK (self); + g_ptr_array_add (self->cur_outbufs, buf); beach: return kVTSuccess; diff --git a/sys/applemedia/vtenc.h b/sys/applemedia/vtenc.h index 19d1c7cee3..875b2fbfab 100644 --- a/sys/applemedia/vtenc.h +++ b/sys/applemedia/vtenc.h @@ -76,7 +76,7 @@ struct _GstVTEnc CFMutableDictionaryRef options; GstBuffer * cur_inbuf; - GstFlowReturn cur_flowret; + GPtrArray * cur_outbufs; gboolean expect_keyframe; };