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.
This commit is contained in:
Ole André Vadla Ravnås 2010-12-10 00:58:58 +01:00
parent f7e5878c9e
commit f3d8e3920d
2 changed files with 26 additions and 20 deletions

View file

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

View file

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