mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-06 02:32:23 +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);
|
| GST_API_VIDEO_TOOLBOX, &error);
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
goto api_error;
|
goto api_error;
|
||||||
|
|
||||||
|
self->cur_outbufs = g_ptr_array_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
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_width = self->caps_height = 0;
|
||||||
self->caps_fps_n = self->caps_fps_d = 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);
|
g_object_unref (self->ctx);
|
||||||
self->ctx = NULL;
|
self->ctx = NULL;
|
||||||
}
|
}
|
||||||
|
@ -380,10 +385,10 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf)
|
||||||
GstVTApi *vt = self->ctx->vt;
|
GstVTApi *vt = self->ctx->vt;
|
||||||
CMSampleBufferRef sbuf;
|
CMSampleBufferRef sbuf;
|
||||||
VTStatus status;
|
VTStatus status;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
guint i;
|
||||||
|
|
||||||
self->cur_inbuf = buf;
|
self->cur_inbuf = buf;
|
||||||
self->cur_flowret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
sbuf = gst_vtdec_sample_buffer_from (self, buf);
|
sbuf = gst_vtdec_sample_buffer_from (self, buf);
|
||||||
|
|
||||||
status = vt->VTDecompressionSessionDecodeFrame (self->session, sbuf, 0, 0, 0);
|
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);
|
self->ctx->cm->FigSampleBufferRelease (sbuf);
|
||||||
|
|
||||||
gst_buffer_unref (buf);
|
|
||||||
self->cur_inbuf = NULL;
|
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
|
static void
|
||||||
|
@ -413,7 +427,7 @@ gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, gsize unk2,
|
||||||
GstVTDec *self = GST_VTDEC_CAST (data);
|
GstVTDec *self = GST_VTDEC_CAST (data);
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
if (result != kVTSuccess || self->cur_flowret != GST_FLOW_OK)
|
if (result != kVTSuccess)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
if (!gst_vtdec_negotiate_downstream (self))
|
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_metadata (buf, self->cur_inbuf,
|
||||||
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
|
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:
|
beach:
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -70,7 +70,7 @@ struct _GstVTDec
|
||||||
VTDecompressionSessionRef session;
|
VTDecompressionSessionRef session;
|
||||||
|
|
||||||
GstBuffer * cur_inbuf;
|
GstBuffer * cur_inbuf;
|
||||||
GstFlowReturn cur_flowret;
|
GPtrArray * cur_outbufs;
|
||||||
};
|
};
|
||||||
|
|
||||||
void gst_vtdec_register_elements (GstPlugin * plugin);
|
void gst_vtdec_register_elements (GstPlugin * plugin);
|
||||||
|
|
|
@ -286,6 +286,8 @@ gst_vtenc_change_state (GstElement * element, GstStateChange transition)
|
||||||
| GST_API_VIDEO_TOOLBOX, &error);
|
| GST_API_VIDEO_TOOLBOX, &error);
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
goto api_error;
|
goto api_error;
|
||||||
|
|
||||||
|
self->cur_outbufs = g_ptr_array_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
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);
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
|
||||||
|
g_ptr_array_free (self->cur_outbufs, TRUE);
|
||||||
|
self->cur_outbufs = NULL;
|
||||||
|
|
||||||
g_object_unref (self->ctx);
|
g_object_unref (self->ctx);
|
||||||
self->ctx = NULL;
|
self->ctx = NULL;
|
||||||
}
|
}
|
||||||
|
@ -713,9 +718,10 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf)
|
||||||
CMTime ts, duration;
|
CMTime ts, duration;
|
||||||
CVPixelBufferRef pbuf = NULL;
|
CVPixelBufferRef pbuf = NULL;
|
||||||
VTStatus vt_status;
|
VTStatus vt_status;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
guint i;
|
||||||
|
|
||||||
self->cur_inbuf = buf;
|
self->cur_inbuf = buf;
|
||||||
self->cur_flowret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
ts = self->ctx->cm->CMTimeMake
|
ts = self->ctx->cm->CMTimeMake
|
||||||
(GST_TIME_AS_MSECONDS (GST_BUFFER_TIMESTAMP (buf)), 1000);
|
(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);
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
|
||||||
cv->CVPixelBufferRelease (pbuf);
|
cv->CVPixelBufferRelease (pbuf);
|
||||||
|
|
||||||
gst_buffer_unref (buf);
|
|
||||||
self->cur_inbuf = NULL;
|
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:
|
cv_error:
|
||||||
{
|
{
|
||||||
gst_buffer_unref (buf);
|
|
||||||
self->cur_inbuf = NULL;
|
self->cur_inbuf = NULL;
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
return GST_FLOW_ERROR;
|
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_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (self);
|
g_ptr_array_add (self->cur_outbufs, buf);
|
||||||
self->cur_flowret = gst_pad_push (self->srcpad, buf);
|
|
||||||
GST_OBJECT_LOCK (self);
|
|
||||||
|
|
||||||
beach:
|
beach:
|
||||||
return kVTSuccess;
|
return kVTSuccess;
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct _GstVTEnc
|
||||||
CFMutableDictionaryRef options;
|
CFMutableDictionaryRef options;
|
||||||
|
|
||||||
GstBuffer * cur_inbuf;
|
GstBuffer * cur_inbuf;
|
||||||
GstFlowReturn cur_flowret;
|
GPtrArray * cur_outbufs;
|
||||||
gboolean expect_keyframe;
|
gboolean expect_keyframe;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue