From 7a8845243c5b97f3402a6a258879db0bd13c4d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 31 Dec 2012 09:47:01 +0100 Subject: [PATCH] mfc: Do zerocopy if we get EGLImage buffers --- sys/mfc/gstmfcdec.c | 175 +++++++++++++++++++++++++++++--------------- sys/mfc/gstmfcdec.h | 2 + 2 files changed, 120 insertions(+), 57 deletions(-) diff --git a/sys/mfc/gstmfcdec.c b/sys/mfc/gstmfcdec.c index b7581ca34b..929667980f 100644 --- a/sys/mfc/gstmfcdec.c +++ b/sys/mfc/gstmfcdec.c @@ -143,6 +143,7 @@ gst_mfc_dec_start (GstVideoDecoder * decoder) self->dst_stride[0] = 0; self->dst_stride[1] = 0; self->dst_stride[2] = 0; + self->mmap = TRUE; /* Initialize with H264 here, we chose the correct codec in set_format */ 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[2] = 0; - if (fimc_set_dst_format (fimc, 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->fimc_format = fimc_format; state = 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)); return FALSE; } - -fimc_dst_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to set FIMC destination parameters"), (NULL)); - return FALSE; - } } static GstFlowReturn @@ -598,62 +588,124 @@ gst_mfc_dec_dequeue_output (GstMFCDec * self) const guint8 *mfc_outbuf_comps[3] = { NULL, }; gint i, j, h, w, src_stride, dst_stride; guint8 *dst_, *src_; + GstMemory *mem; 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], (void **) &mfc_outbuf_comps[1]); - if (fimc_convert (fimc, (void **) mfc_outbuf_comps, - (void **) self->dst) < 0) - goto fimc_convert_error; + if (gst_buffer_n_memory (outbuf) == 1 + && (mem = gst_buffer_peek_memory (outbuf, 0)) + && strcmp (mem->allocator->mem_type, "GstEGLImage") == 0) { + void *dst[3]; - if (!gst_video_frame_map (&vframe, &state->info, outbuf, GST_MAP_WRITE)) - goto frame_map_error; + if (self->mmap) { + fimc_release_dst_buffers (fimc); - 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; - } + + if (self->format == GST_VIDEO_FORMAT_NV12) { + self->dst_stride[0] = GST_ROUND_UP_4 (self->width); + self->dst_stride[1] = GST_ROUND_UP_4 (self->width); + self->dst_stride[2] = 0; + } else { + self->dst_stride[0] = GST_ROUND_UP_4 (self->width); + self->dst_stride[1] = GST_ROUND_UP_4 ((self->width + 1) / 2); + self->dst_stride[2] = GST_ROUND_UP_4 ((self->width + 1) / 2); } - break; - case GST_VIDEO_FORMAT_NV12: - for (j = 0; j < 2; j++) { - dst_ = (guint8 *) GST_VIDEO_FRAME_PLANE_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) * (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; + 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 = FALSE; + + if (fimc_request_dst_buffers (fimc) < 0) + goto fimc_dst_requestbuffers_error; + + self->dst[0] = NULL; + self->dst[1] = NULL; + self->dst[2] = NULL; + } + + 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; - default: - g_assert_not_reached (); - break; + break; + case GST_VIDEO_FORMAT_NV12: + for (j = 0; j < 2; j++) { + dst_ = (guint8 *) GST_VIDEO_FRAME_PLANE_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) * (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) { @@ -729,6 +781,15 @@ frame_map_error: 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: { GST_ELEMENT_ERROR (self, LIBRARY, FAILED, diff --git a/sys/mfc/gstmfcdec.h b/sys/mfc/gstmfcdec.h index 770cdb8360..3aeb4f5b33 100644 --- a/sys/mfc/gstmfcdec.h +++ b/sys/mfc/gstmfcdec.h @@ -58,6 +58,7 @@ struct _GstMFCDec GstBuffer *codec_data; GstVideoFormat format; + FimcColorFormat fimc_format; Fimc *fimc; gint width, height; gint crop_left, crop_top; @@ -66,6 +67,7 @@ struct _GstMFCDec void *dst[3]; int dst_stride[3]; + gboolean mmap; }; struct _GstMFCDecClass