mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
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:
parent
6b63954f63
commit
ebd2a6d6e9
4 changed files with 44 additions and 17 deletions
|
@ -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;
|
||||
|
|
|
@ -70,7 +70,7 @@ struct _GstVTDec
|
|||
VTDecompressionSessionRef session;
|
||||
|
||||
GstBuffer * cur_inbuf;
|
||||
GstFlowReturn cur_flowret;
|
||||
GPtrArray * cur_outbufs;
|
||||
};
|
||||
|
||||
void gst_vtdec_register_elements (GstPlugin * plugin);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -76,7 +76,7 @@ struct _GstVTEnc
|
|||
CFMutableDictionaryRef options;
|
||||
|
||||
GstBuffer * cur_inbuf;
|
||||
GstFlowReturn cur_flowret;
|
||||
GPtrArray * cur_outbufs;
|
||||
gboolean expect_keyframe;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue