From f3d8e3920dfc4126a8c98e4e376b8f2fb21d560c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Fri, 10 Dec 2010 00:58:58 +0100 Subject: [PATCH] applemedia: only enqueue buffers in the VideoToolbox callbacks These callbacks may fire from any thread, hence we should only enqueue buffers and let the streaming thread take care of the rest as soon as the blocking encode or decode operation has finished. --- sys/applemedia/vtdec.c | 21 ++++++++++++--------- sys/applemedia/vtenc.c | 25 ++++++++++++++----------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/sys/applemedia/vtdec.c b/sys/applemedia/vtdec.c index eb5d2f1ac3..22db2e8696 100644 --- a/sys/applemedia/vtdec.c +++ b/sys/applemedia/vtdec.c @@ -45,7 +45,7 @@ static VTDecompressionSessionRef gst_vtdec_create_session (GstVTDec * self, static void gst_vtdec_destroy_session (GstVTDec * self, VTDecompressionSessionRef * session); static GstFlowReturn gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf); -static void gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, +static void gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2, CVBufferRef cvbuf); static CMSampleBufferRef gst_vtdec_sample_buffer_from (GstVTDec * self, @@ -358,7 +358,7 @@ gst_vtdec_create_session (GstVTDec * self, CMFormatDescriptionRef fmt_desc) gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferBytesPerRowAlignmentKey), 2 * self->negotiated_width); - callback.func = gst_vtdec_output_frame; + callback.func = gst_vtdec_enqueue_frame; callback.data = self; status = self->ctx->vt->VTDecompressionSessionCreate (NULL, fmt_desc, @@ -407,13 +407,20 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) self->cur_inbuf = NULL; gst_buffer_unref (buf); + if (self->cur_outbufs->len > 0) { + if (!gst_vtdec_negotiate_downstream (self)) + ret = GST_FLOW_NOT_NEGOTIATED; + } + for (i = 0; i != self->cur_outbufs->len; i++) { GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i); - if (ret == GST_FLOW_OK) + if (ret == GST_FLOW_OK) { + gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); ret = gst_pad_push (self->srcpad, buf); - else + } else { gst_buffer_unref (buf); + } } g_ptr_array_set_size (self->cur_outbufs, 0); @@ -421,7 +428,7 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) } static void -gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, gsize unk2, +gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2, CVBufferRef cvbuf) { GstVTDec *self = GST_VTDEC_CAST (data); @@ -430,11 +437,7 @@ gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, gsize unk2, if (result != kVTSuccess) goto beach; - if (!gst_vtdec_negotiate_downstream (self)) - goto beach; - buf = gst_core_video_buffer_new (self->ctx, cvbuf); - gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); gst_buffer_copy_metadata (buf, self->cur_inbuf, GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); diff --git a/sys/applemedia/vtenc.c b/sys/applemedia/vtenc.c index 43a16229e1..c7878482c3 100644 --- a/sys/applemedia/vtenc.c +++ b/sys/applemedia/vtenc.c @@ -77,7 +77,7 @@ static VTStatus gst_vtenc_session_configure_property_double (GstVTEnc * self, VTCompressionSessionRef session, CFStringRef name, gdouble value); static GstFlowReturn gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf); -static VTStatus gst_vtenc_output_buffer (void *data, int a2, int a3, int a4, +static VTStatus gst_vtenc_enqueue_buffer (void *data, int a2, int a3, int a4, CMSampleBufferRef sbuf, int a6, int a7); static gboolean gst_vtenc_buffer_is_keyframe (GstVTEnc * self, CMSampleBufferRef sbuf); @@ -411,9 +411,7 @@ gst_vtenc_negotiate_downstream (GstVTEnc * self, CMSampleBufferRef sbuf) gst_buffer_unref (codec_data); } - GST_OBJECT_UNLOCK (self); result = gst_pad_set_caps (self->srcpad, caps); - GST_OBJECT_LOCK (self); gst_caps_unref (caps); @@ -502,7 +500,7 @@ gst_vtenc_create_session (GstVTEnc * self) gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey), self->negotiated_height); - callback.func = gst_vtenc_output_buffer; + callback.func = gst_vtenc_enqueue_buffer; callback.data = self; status = vt->VTCompressionSessionCreate (NULL, @@ -770,13 +768,22 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf) self->cur_inbuf = NULL; gst_buffer_unref (buf); + if (self->cur_outbufs->len > 0) { + GstCoreMediaBuffer *cmbuf = + GST_CORE_MEDIA_BUFFER_CAST (g_ptr_array_index (self->cur_outbufs, 0)); + if (!gst_vtenc_negotiate_downstream (self, cmbuf->sample_buf)) + ret = GST_FLOW_NOT_NEGOTIATED; + } + for (i = 0; i != self->cur_outbufs->len; i++) { GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i); - if (ret == GST_FLOW_OK) + if (ret == GST_FLOW_OK) { + gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); ret = gst_pad_push (self->srcpad, buf); - else + } else { gst_buffer_unref (buf); + } } g_ptr_array_set_size (self->cur_outbufs, 0); @@ -792,7 +799,7 @@ cv_error: } static VTStatus -gst_vtenc_output_buffer (void *data, int a2, int a3, int a4, +gst_vtenc_enqueue_buffer (void *data, int a2, int a3, int a4, CMSampleBufferRef sbuf, int a6, int a7) { GstVTEnc *self = data; @@ -812,11 +819,7 @@ gst_vtenc_output_buffer (void *data, int a2, int a3, int a4, } self->expect_keyframe = FALSE; - if (!gst_vtenc_negotiate_downstream (self, sbuf)) - goto beach; - buf = gst_core_media_buffer_new (self->ctx, sbuf); - gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); gst_buffer_copy_metadata (buf, self->cur_inbuf, GST_BUFFER_COPY_TIMESTAMPS); if (is_keyframe) { GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);