mfc: Do zerocopy if we get EGLImage buffers

This commit is contained in:
Sebastian Dröge 2012-12-31 09:47:01 +01:00
parent 37603c7dbd
commit 7a8845243c
2 changed files with 120 additions and 57 deletions

View file

@ -143,6 +143,7 @@ gst_mfc_dec_start (GstVideoDecoder * decoder)
self->dst_stride[0] = 0; self->dst_stride[0] = 0;
self->dst_stride[1] = 0; self->dst_stride[1] = 0;
self->dst_stride[2] = 0; self->dst_stride[2] = 0;
self->mmap = TRUE;
/* Initialize with H264 here, we chose the correct codec in set_format */ /* Initialize with H264 here, we chose the correct codec in set_format */
self->context = mfc_dec_create (CODEC_TYPE_H264, 1); self->context = mfc_dec_create (CODEC_TYPE_H264, 1);
@ -433,11 +434,7 @@ gst_mfc_dec_negotiate (GstVideoDecoder * decoder)
self->dst_stride[1] = 0; self->dst_stride[1] = 0;
self->dst_stride[2] = 0; self->dst_stride[2] = 0;
if (fimc_set_dst_format (fimc, fimc_format, self->width, self->fimc_format = fimc_format;
self->height, self->dst_stride,
self->crop_left, self->crop_top,
self->crop_width, self->crop_height) < 0)
goto fimc_dst_error;
state = state =
gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self),
@ -466,13 +463,6 @@ fimc_src_requestbuffers_error:
("Failed to request FIMC source buffers"), (NULL)); ("Failed to request FIMC source buffers"), (NULL));
return FALSE; return FALSE;
} }
fimc_dst_error:
{
GST_ELEMENT_ERROR (self, LIBRARY, FAILED,
("Failed to set FIMC destination parameters"), (NULL));
return FALSE;
}
} }
static GstFlowReturn static GstFlowReturn
@ -598,62 +588,124 @@ gst_mfc_dec_dequeue_output (GstMFCDec * self)
const guint8 *mfc_outbuf_comps[3] = { NULL, }; const guint8 *mfc_outbuf_comps[3] = { NULL, };
gint i, j, h, w, src_stride, dst_stride; gint i, j, h, w, src_stride, dst_stride;
guint8 *dst_, *src_; guint8 *dst_, *src_;
GstMemory *mem;
fimc = self->fimc; fimc = self->fimc;
if (!self->dst[0]
&& fimc_request_dst_buffers_mmap (fimc, self->dst,
self->dst_stride) < 0)
goto fimc_dst_requestbuffers_error;
mfc_buffer_get_output_data (mfc_outbuf, (void **) &mfc_outbuf_comps[0], mfc_buffer_get_output_data (mfc_outbuf, (void **) &mfc_outbuf_comps[0],
(void **) &mfc_outbuf_comps[1]); (void **) &mfc_outbuf_comps[1]);
if (fimc_convert (fimc, (void **) mfc_outbuf_comps, if (gst_buffer_n_memory (outbuf) == 1
(void **) self->dst) < 0) && (mem = gst_buffer_peek_memory (outbuf, 0))
goto fimc_convert_error; && strcmp (mem->allocator->mem_type, "GstEGLImage") == 0) {
void *dst[3];
if (!gst_video_frame_map (&vframe, &state->info, outbuf, GST_MAP_WRITE)) if (self->mmap) {
goto frame_map_error; fimc_release_dst_buffers (fimc);
switch (state->info.finfo->format) {
case GST_VIDEO_FORMAT_I420: if (self->format == GST_VIDEO_FORMAT_NV12) {
case GST_VIDEO_FORMAT_YV12: self->dst_stride[0] = GST_ROUND_UP_4 (self->width);
for (j = 0; j < 3; j++) { self->dst_stride[1] = GST_ROUND_UP_4 (self->width);
dst_ = (guint8 *) GST_VIDEO_FRAME_COMP_DATA (&vframe, j); self->dst_stride[2] = 0;
src_ = self->dst[j]; } else {
src_stride = self->dst_stride[j]; self->dst_stride[0] = GST_ROUND_UP_4 (self->width);
h = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, j); self->dst_stride[1] = GST_ROUND_UP_4 ((self->width + 1) / 2);
w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, j); self->dst_stride[2] = GST_ROUND_UP_4 ((self->width + 1) / 2);
dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, j);
for (i = 0; i < h; i++) {
memcpy (dst_, src_, w);
dst_ += dst_stride;
src_ += src_stride;
}
} }
break; if (fimc_set_dst_format (fimc, self->fimc_format, self->width,
case GST_VIDEO_FORMAT_NV12: self->height, self->dst_stride, self->crop_left,
for (j = 0; j < 2; j++) { self->crop_top, self->crop_width, self->crop_height) < 0)
dst_ = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&vframe, j); goto fimc_dst_error;
src_ = self->dst[j]; self->mmap = FALSE;
src_stride = self->dst_stride[j];
h = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, j); if (fimc_request_dst_buffers (fimc) < 0)
w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, j) * (j == 0 ? 1 : 2); goto fimc_dst_requestbuffers_error;
dst_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, j);
for (i = 0; i < h; i++) { self->dst[0] = NULL;
memcpy (dst_, src_, w); self->dst[1] = NULL;
dst_ += dst_stride; self->dst[2] = NULL;
src_ += src_stride; }
if (!gst_video_frame_map (&vframe, &state->info, outbuf, GST_MAP_WRITE))
goto frame_map_error;
dst[0] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0);
dst[1] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1);
if (self->format == GST_VIDEO_FORMAT_NV12)
dst[2] = NULL;
else
dst[2] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 2);
if (fimc_convert (fimc, (void **) mfc_outbuf_comps, (void **) dst) < 0)
goto fimc_convert_error;
gst_video_frame_unmap (&vframe);
} else {
if (!self->mmap) {
fimc_release_dst_buffers (fimc);
self->dst_stride[0] = 0;
self->dst_stride[1] = 0;
self->dst_stride[2] = 0;
if (fimc_set_dst_format (fimc, self->fimc_format, self->width,
self->height, self->dst_stride, self->crop_left,
self->crop_top, self->crop_width, self->crop_height) < 0)
goto fimc_dst_error;
self->mmap = TRUE;
}
if (!self->dst[0]
&& fimc_request_dst_buffers_mmap (fimc, self->dst,
self->dst_stride) < 0)
goto fimc_dst_requestbuffers_error;
if (fimc_convert (fimc, (void **) mfc_outbuf_comps,
(void **) self->dst) < 0)
goto fimc_convert_error;
if (!gst_video_frame_map (&vframe, &state->info, outbuf, GST_MAP_WRITE))
goto frame_map_error;
switch (state->info.finfo->format) {
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
for (j = 0; j < 3; j++) {
dst_ = (guint8 *) GST_VIDEO_FRAME_COMP_DATA (&vframe, j);
src_ = self->dst[j];
src_stride = self->dst_stride[j];
h = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, j);
w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, j);
dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, j);
for (i = 0; i < h; i++) {
memcpy (dst_, src_, w);
dst_ += dst_stride;
src_ += src_stride;
}
} }
} break;
break; case GST_VIDEO_FORMAT_NV12:
default: for (j = 0; j < 2; j++) {
g_assert_not_reached (); dst_ = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&vframe, j);
break; src_ = self->dst[j];
src_stride = self->dst_stride[j];
h = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, j);
w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, j) * (j == 0 ? 1 : 2);
dst_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, j);
for (i = 0; i < h; i++) {
memcpy (dst_, src_, w);
dst_ += dst_stride;
src_ += src_stride;
}
}
break;
default:
g_assert_not_reached ();
break;
}
gst_video_frame_unmap (&vframe);
} }
gst_video_frame_unmap (&vframe);
} }
if (frame) { if (frame) {
@ -729,6 +781,15 @@ frame_map_error:
goto done; goto done;
} }
fimc_dst_error:
{
GST_ELEMENT_ERROR (self, LIBRARY, FAILED,
("Failed to set FIMC destination parameters"), (NULL));
ret = GST_FLOW_ERROR;
goto done;
}
fimc_dst_requestbuffers_error: fimc_dst_requestbuffers_error:
{ {
GST_ELEMENT_ERROR (self, LIBRARY, FAILED, GST_ELEMENT_ERROR (self, LIBRARY, FAILED,

View file

@ -58,6 +58,7 @@ struct _GstMFCDec
GstBuffer *codec_data; GstBuffer *codec_data;
GstVideoFormat format; GstVideoFormat format;
FimcColorFormat fimc_format;
Fimc *fimc; Fimc *fimc;
gint width, height; gint width, height;
gint crop_left, crop_top; gint crop_left, crop_top;
@ -66,6 +67,7 @@ struct _GstMFCDec
void *dst[3]; void *dst[3];
int dst_stride[3]; int dst_stride[3];
gboolean mmap;
}; };
struct _GstMFCDecClass struct _GstMFCDecClass