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.
This commit is contained in:
Ole André Vadla Ravnås 2010-11-10 23:16:51 +01:00
parent 6b63954f63
commit ebd2a6d6e9
4 changed files with 44 additions and 17 deletions

View file

@ -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;

View file

@ -70,7 +70,7 @@ struct _GstVTDec
VTDecompressionSessionRef session;
GstBuffer * cur_inbuf;
GstFlowReturn cur_flowret;
GPtrArray * cur_outbufs;
};
void gst_vtdec_register_elements (GstPlugin * plugin);

View file

@ -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;

View file

@ -76,7 +76,7 @@ struct _GstVTEnc
CFMutableDictionaryRef options;
GstBuffer * cur_inbuf;
GstFlowReturn cur_flowret;
GPtrArray * cur_outbufs;
gboolean expect_keyframe;
};