From cfe1ff1c08fbaa7492fac6f524d4b3003037d3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 26 Dec 2012 13:18:09 +0100 Subject: [PATCH] mfc: Refactor fimc code a bit --- sys/mfc/fimc/fimc.c | 261 ++++++++++++++++++++++++++------------------ sys/mfc/fimc/fimc.h | 7 +- sys/mfc/gstmfcdec.c | 51 +++++++-- 3 files changed, 199 insertions(+), 120 deletions(-) diff --git a/sys/mfc/fimc/fimc.c b/sys/mfc/fimc/fimc.c index 964c192001..b5bef8fbb2 100644 --- a/sys/mfc/fimc/fimc.c +++ b/sys/mfc/fimc/fimc.c @@ -63,12 +63,14 @@ struct _Fimc struct v4l2_capability caps; int set_src; + int has_src_buffers; FimcColorFormat src_format; struct v4l2_format src_fmt; struct v4l2_crop src_crop; struct v4l2_requestbuffers src_requestbuffers; int set_dst; + int has_dst_buffers; FimcColorFormat dst_format; struct v4l2_format dst_fmt; struct v4l2_crop dst_crop; @@ -212,7 +214,6 @@ fimc_set_src_format (Fimc * fimc, FimcColorFormat format, int width, int height, { struct v4l2_format fmt; struct v4l2_crop crop; - struct v4l2_requestbuffers requestbuffers; struct v4l2_control control; int i; @@ -224,10 +225,9 @@ fimc_set_src_format (Fimc * fimc, FimcColorFormat format, int width, int height, && fimc->src_crop.c.left == crop_left && fimc->src_crop.c.top == crop_top && fimc->src_crop.c.width == crop_width && fimc->src_crop.c.height == crop_height) { - if (fimc->src_requestbuffers.memory == V4L2_MEMORY_USERPTR - && fimc->src_fmt.fmt.pix_mp.plane_fmt[0].bytesperline == stride[0] - && fimc->src_fmt.fmt.pix_mp.plane_fmt[1].bytesperline == stride[1] - && fimc->src_fmt.fmt.pix_mp.plane_fmt[2].bytesperline == stride[2]) { + if (fimc->src_fmt.fmt.pix_mp.plane_fmt[0].bytesperline == stride[0] && + fimc->src_fmt.fmt.pix_mp.plane_fmt[1].bytesperline == stride[1] && + fimc->src_fmt.fmt.pix_mp.plane_fmt[2].bytesperline == stride[2]) { GST_DEBUG ("Nothing has changed"); return 0; } @@ -238,7 +238,6 @@ fimc_set_src_format (Fimc * fimc, FimcColorFormat format, int width, int height, memset (&fmt, 0, sizeof (fmt)); memset (&crop, 0, sizeof (crop)); - memset (&requestbuffers, 0, sizeof (requestbuffers)); memset (&control, 0, sizeof (control)); fimc->src_format = format; @@ -253,8 +252,7 @@ fimc_set_src_format (Fimc * fimc, FimcColorFormat format, int width, int height, for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) { fmt.fmt.pix_mp.plane_fmt[i].bytesperline = stride[i]; fmt.fmt.pix_mp.plane_fmt[i].sizeimage = - fimc_color_format_get_component_height (format, i, - height) * stride[i]; + fimc_color_format_get_component_height (format, i, height) * stride[i]; } if (ioctl (fimc->fd, VIDIOC_S_FMT, &fmt) < 0) { @@ -277,6 +275,33 @@ fimc_set_src_format (Fimc * fimc, FimcColorFormat format, int width, int height, fimc->src_crop = crop; + control.id = V4L2_CID_ROTATE; + control.value = 0; + + if (ioctl (fimc->fd, VIDIOC_S_CTRL, &control) < 0) { + GST_ERROR ("Failed to set rotation to 0: %d", errno); + return -1; + } + + fimc->set_src = 1; + + return 0; +} + +int +fimc_request_src_buffers (Fimc * fimc) +{ + struct v4l2_requestbuffers requestbuffers; + + if (fimc->has_dst_buffers) { + GST_ERROR ("Already have dst buffers"); + return -1; + } + + fimc->has_src_buffers = 0; + + memset (&requestbuffers, 0, sizeof (requestbuffers)); + requestbuffers.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; requestbuffers.memory = V4L2_MEMORY_USERPTR; requestbuffers.count = 1; @@ -293,26 +318,26 @@ fimc_set_src_format (Fimc * fimc, FimcColorFormat format, int width, int height, return -1; } - control.id = V4L2_CID_ROTATE; - control.value = 0; - - if (ioctl (fimc->fd, VIDIOC_S_CTRL, &control) < 0) { - GST_ERROR ("Failed to set rotation to 0: %d", errno); - return -1; - } - - fimc->set_src = 1; + fimc->has_src_buffers = 1; return 0; } -static int -fimc_set_dst_format_internal (Fimc * fimc, FimcColorFormat format, int width, int height, - int stride[3], int crop_left, int crop_top, int crop_width, int crop_height, int direct) +int +fimc_release_src_buffers (Fimc * fimc) +{ + /* Nothing to do here now */ + fimc->has_src_buffers = 0; + + return 0; +} + +int +fimc_set_dst_format (Fimc * fimc, FimcColorFormat format, int width, int height, + int stride[3], int crop_left, int crop_top, int crop_width, int crop_height) { struct v4l2_format fmt; struct v4l2_crop crop; - struct v4l2_requestbuffers requestbuffers; struct v4l2_control control; int i; @@ -324,34 +349,19 @@ fimc_set_dst_format_internal (Fimc * fimc, FimcColorFormat format, int width, in && fimc->dst_crop.c.left == crop_left && fimc->dst_crop.c.top == crop_top && fimc->dst_crop.c.width == crop_width && fimc->dst_crop.c.height == crop_height) { - if (!direct) { - if (fimc->dst_requestbuffers.memory == V4L2_MEMORY_USERPTR && - fimc->dst_fmt.fmt.pix_mp.plane_fmt[0].bytesperline == stride[0] && - fimc->dst_fmt.fmt.pix_mp.plane_fmt[1].bytesperline == stride[1] && - fimc->dst_fmt.fmt.pix_mp.plane_fmt[2].bytesperline == stride[2]) { - GST_DEBUG ("Nothing has changed"); - return 0; - } - } else { - if (fimc->dst_requestbuffers.memory == V4L2_MEMORY_MMAP) { - GST_DEBUG ("Nothing has changed"); - return 0; - } + if (fimc->dst_fmt.fmt.pix_mp.plane_fmt[0].bytesperline == stride[0] && + fimc->dst_fmt.fmt.pix_mp.plane_fmt[1].bytesperline == stride[1] && + fimc->dst_fmt.fmt.pix_mp.plane_fmt[2].bytesperline == stride[2]) { + GST_DEBUG ("Nothing has changed"); + return 0; } } /* Something has changed */ fimc->set_dst = 0; - for (i = 0; i < 3; i++) { - if (fimc->dst_buffer_data[i]) - munmap (fimc->dst_buffer_data[i], fimc->dst_buffer_size[i]); - fimc->dst_buffer_data[i] = NULL; - fimc->dst_buffer_size[i] = 0; - } memset (&fmt, 0, sizeof (fmt)); memset (&crop, 0, sizeof (crop)); - memset (&requestbuffers, 0, sizeof (requestbuffers)); memset (&control, 0, sizeof (control)); fimc->dst_format = format; @@ -363,12 +373,10 @@ fimc_set_dst_format_internal (Fimc * fimc, FimcColorFormat format, int width, in fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; fmt.fmt.pix_mp.num_planes = fimc_color_format_get_nplanes (format); - if (!direct) { - for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) { - fmt.fmt.pix_mp.plane_fmt[i].bytesperline = stride[i]; - fmt.fmt.pix_mp.plane_fmt[i].sizeimage = - fimc_color_format_get_component_height (format, i, height) * stride[i]; - } + for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) { + fmt.fmt.pix_mp.plane_fmt[i].bytesperline = stride[i]; + fmt.fmt.pix_mp.plane_fmt[i].sizeimage = + fimc_color_format_get_component_height (format, i, height) * stride[i]; } if (ioctl (fimc->fd, VIDIOC_S_FMT, &fmt) < 0) { @@ -391,22 +399,6 @@ fimc_set_dst_format_internal (Fimc * fimc, FimcColorFormat format, int width, in fimc->dst_crop = crop; - requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - requestbuffers.memory = direct ? V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR; - requestbuffers.count = 1; - - if (ioctl (fimc->fd, VIDIOC_REQBUFS, &requestbuffers) < 0) { - GST_ERROR ("Failed to request dst buffers: %d", errno); - return -1; - } - - fimc->dst_requestbuffers = requestbuffers; - - if (requestbuffers.count < 1) { - GST_ERROR ("Got %d buffers instead of %d", requestbuffers.count, 1); - return -1; - } - control.id = V4L2_CID_ROTATE; control.value = 0; @@ -421,32 +413,79 @@ fimc_set_dst_format_internal (Fimc * fimc, FimcColorFormat format, int width, in } int -fimc_set_dst_format (Fimc * fimc, FimcColorFormat format, int width, int height, - int stride[3], int crop_left, int crop_top, int crop_width, int crop_height) +fimc_request_dst_buffers (Fimc * fimc) { - return fimc_set_dst_format_internal (fimc, format, width, height, stride, crop_left, crop_top, crop_width, crop_height, 0); + struct v4l2_requestbuffers requestbuffers; + + if (fimc->has_dst_buffers) { + GST_ERROR ("Already have dst buffers"); + return -1; + } + + fimc->has_dst_buffers = 0; + + memset (&requestbuffers, 0, sizeof (requestbuffers)); + + requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + requestbuffers.memory = V4L2_MEMORY_USERPTR; + requestbuffers.count = 1; + + if (ioctl (fimc->fd, VIDIOC_REQBUFS, &requestbuffers) < 0) { + GST_ERROR ("Failed to request dst buffers: %d", errno); + return -1; + } + + fimc->dst_requestbuffers = requestbuffers; + + if (requestbuffers.count < 1) { + GST_ERROR ("Got %d buffers instead of %d", requestbuffers.count, 1); + return -1; + } + + fimc->has_dst_buffers = 1; + + return 0; } int -fimc_set_dst_format_direct (Fimc * fimc, FimcColorFormat format, int width, - int height, int crop_left, int crop_top, int crop_width, int crop_height, - void *dst[3], int stride[3]) +fimc_request_dst_buffers_mmap (Fimc * fimc, void *dst[3], int stride[3]) { + struct v4l2_requestbuffers requestbuffers; struct v4l2_plane planes[3]; struct v4l2_buffer buffer; int i; + if (fimc->has_dst_buffers) { + GST_ERROR ("Already have dst buffers"); + return -1; + } + + fimc->has_dst_buffers = 0; + + memset (&requestbuffers, 0, sizeof (requestbuffers)); memset (planes, 0, sizeof (planes)); memset (&buffer, 0, sizeof (buffer)); - if (fimc_set_dst_format_internal (fimc, format, width, height, NULL, crop_left, - crop_top, crop_width, crop_height, 1) < 0) - return -1; + requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + requestbuffers.memory = V4L2_MEMORY_MMAP; + requestbuffers.count = 1; - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buffer.memory = V4L2_MEMORY_MMAP; + if (ioctl (fimc->fd, VIDIOC_REQBUFS, &requestbuffers) < 0) { + GST_ERROR ("Failed to request dst buffers: %d", errno); + return -1; + } + + fimc->dst_requestbuffers = requestbuffers; + + if (requestbuffers.count < 1) { + GST_ERROR ("Got %d buffers instead of %d", requestbuffers.count, 1); + return -1; + } + + buffer.type = fimc->dst_requestbuffers.type; + buffer.memory = fimc->dst_requestbuffers.memory; buffer.index = 0; - buffer.length = fimc_color_format_get_nplanes (format); + buffer.length = fimc_color_format_get_nplanes (fimc->dst_format); buffer.m.planes = planes; if (ioctl (fimc->fd, VIDIOC_QUERYBUF, &buffer) < 0) { @@ -481,22 +520,45 @@ fimc_set_dst_format_direct (Fimc * fimc, FimcColorFormat format, int width, stride[2] /= 2; } + fimc->has_dst_buffers = 1; + return 0; } -static int -fimc_convert_internal (Fimc * fimc, void *src[3], void *dst[3], int direct) +int +fimc_release_dst_buffers (Fimc * fimc) +{ + int i; + + fimc->has_dst_buffers = 0; + + for (i = 0; i < 3; i++) { + if (fimc->dst_buffer_data[i]) + munmap (fimc->dst_buffer_data[i], fimc->dst_buffer_size[i]); + } + + return 0; +} + +int +fimc_convert (Fimc * fimc, void *src[3], void *dst[3]) { struct v4l2_plane planes[3]; struct v4l2_buffer buffer; enum v4l2_buf_type type; int i; + if (!fimc->set_src || !fimc->set_dst || + !fimc->has_src_buffers || !fimc->has_dst_buffers) { + GST_ERROR ("Not configured yet"); + return -1; + } + memset (planes, 0, sizeof (planes)); memset (&buffer, 0, sizeof (buffer)); - buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - buffer.memory = V4L2_MEMORY_USERPTR; + buffer.type = fimc->src_requestbuffers.type; + buffer.memory = fimc->src_requestbuffers.memory; buffer.length = fimc->src_fmt.fmt.pix_mp.num_planes; buffer.index = 0; buffer.m.planes = planes; @@ -514,15 +576,15 @@ fimc_convert_internal (Fimc * fimc, void *src[3], void *dst[3], int direct) memset (planes, 0, sizeof (planes)); memset (&buffer, 0, sizeof (buffer)); - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buffer.memory = direct ? V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR; + buffer.type = fimc->dst_requestbuffers.type; + buffer.memory = fimc->dst_requestbuffers.memory; buffer.length = fimc->dst_fmt.fmt.pix_mp.num_planes; buffer.index = 0; buffer.m.planes = planes; for (i = 0; i < buffer.length; i++) { buffer.m.planes[i].length = fimc->dst_fmt.fmt.pix_mp.plane_fmt[i].sizeimage; - if (direct) + if (fimc->dst_requestbuffers.memory == V4L2_MEMORY_MMAP) buffer.m.planes[i].m.mem_offset = fimc->dst_planes[i].m.mem_offset; else buffer.m.planes[i].m.userptr = (unsigned long) dst[i]; @@ -533,13 +595,13 @@ fimc_convert_internal (Fimc * fimc, void *src[3], void *dst[3], int direct) return -1; } - type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + type = fimc->src_requestbuffers.type; if (ioctl (fimc->fd, VIDIOC_STREAMON, &type) < 0) { GST_ERROR ("Activating input stream failed: %d", errno); return -1; } - type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + type = fimc->dst_requestbuffers.type; if (ioctl (fimc->fd, VIDIOC_STREAMON, &type) < 0) { GST_ERROR ("Activating output stream failed: %d", errno); return -1; @@ -548,8 +610,8 @@ fimc_convert_internal (Fimc * fimc, void *src[3], void *dst[3], int direct) memset (planes, 0, sizeof (planes)); memset (&buffer, 0, sizeof (buffer)); - buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - buffer.memory = V4L2_MEMORY_USERPTR; + buffer.type = fimc->src_requestbuffers.type; + buffer.memory = fimc->src_requestbuffers.memory; buffer.length = fimc->src_fmt.fmt.pix_mp.num_planes; buffer.m.planes = planes; @@ -561,8 +623,8 @@ fimc_convert_internal (Fimc * fimc, void *src[3], void *dst[3], int direct) memset (planes, 0, sizeof (planes)); memset (&buffer, 0, sizeof (buffer)); - buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - buffer.memory = direct ? V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR; + buffer.type = fimc->dst_requestbuffers.type; + buffer.memory = fimc->dst_requestbuffers.memory; buffer.length = fimc->dst_fmt.fmt.pix_mp.num_planes; buffer.m.planes = planes; @@ -571,13 +633,13 @@ fimc_convert_internal (Fimc * fimc, void *src[3], void *dst[3], int direct) return -1; } - type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + type = fimc->src_requestbuffers.type; if (ioctl (fimc->fd, VIDIOC_STREAMOFF, &type) < 0) { GST_ERROR ("Deactivating input stream failed: %d", errno); return -1; } - type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + type = fimc->dst_requestbuffers.type; if (ioctl (fimc->fd, VIDIOC_STREAMOFF, &type) < 0) { GST_ERROR ("Deactivating output stream failed: %d", errno); return -1; @@ -586,22 +648,3 @@ fimc_convert_internal (Fimc * fimc, void *src[3], void *dst[3], int direct) return 0; } -int -fimc_convert (Fimc * fimc, void *src[3], void *dst[3]) -{ - if (!fimc->set_src || !fimc->set_dst || - fimc->dst_requestbuffers.memory == V4L2_MEMORY_MMAP) - return -1; - - return fimc_convert_internal (fimc, src, dst, 0); -} - -int -fimc_convert_direct (Fimc * fimc, void *src[3]) -{ - if (!fimc->set_src || !fimc->set_dst || - fimc->dst_requestbuffers.memory == V4L2_MEMORY_USERPTR) - return -1; - - return fimc_convert_internal (fimc, src, NULL, 1); -} diff --git a/sys/mfc/fimc/fimc.h b/sys/mfc/fimc/fimc.h index e35c78b12a..480a0ab4b1 100644 --- a/sys/mfc/fimc/fimc.h +++ b/sys/mfc/fimc/fimc.h @@ -60,12 +60,15 @@ Fimc * fimc_new (void); void fimc_free (Fimc * fimc); int fimc_set_src_format (Fimc *fimc, FimcColorFormat format, int width, int height, int stride[3], int crop_left, int crop_top, int crop_width, int crop_height); +int fimc_request_src_buffers (Fimc *fimc); +int fimc_release_src_buffers (Fimc *fimc); int fimc_set_dst_format (Fimc *fimc, FimcColorFormat format, int width, int height, int stride[3], int crop_left, int crop_top, int crop_width, int crop_height); -int fimc_set_dst_format_direct (Fimc *fimc, FimcColorFormat format, int width, int height, int crop_left, int crop_top, int crop_width, int crop_height, void *dst[3], int stride[3]); +int fimc_request_dst_buffers (Fimc *fimc); +int fimc_request_dst_buffers_mmap (Fimc *fimc, void *dst[3], int stride[3]); +int fimc_release_dst_buffers (Fimc *fimc); int fimc_convert (Fimc *fimc, void *src[3], void *dst[3]); -int fimc_convert_direct (Fimc *fimc, void *src[3]); #ifdef __cplusplus } diff --git a/sys/mfc/gstmfcdec.c b/sys/mfc/gstmfcdec.c index 4ea2020e03..f8fd0e5f41 100644 --- a/sys/mfc/gstmfcdec.c +++ b/sys/mfc/gstmfcdec.c @@ -371,20 +371,29 @@ gst_mfc_dec_negotiate (GstVideoDecoder * decoder) break; } + fimc_release_src_buffers (fimc); + if (fimc_set_src_format (fimc, FIMC_COLOR_FORMAT_YUV420SPT, self->width, self->height, self->src_stride, self->crop_left, self->crop_top, self->crop_width, self->crop_height) < 0) goto fimc_src_error; - if (fimc_set_dst_format_direct (fimc, fimc_format, self->width, - self->height, self->crop_left, self->crop_top, self->crop_width, - self->crop_height, self->dst, self->dst_stride) < 0) - goto fimc_dst_error; + if (fimc_request_src_buffers (fimc) < 0) + goto fimc_src_requestbuffers_error; - GST_DEBUG_OBJECT (self, - "Got direct output buffer: %p [%d], %p [%d], %p [%d]", self->dst[0], - self->dst_stride[0], self->dst[1], self->dst_stride[1], self->dst[2], - self->dst_stride[2]); + fimc_release_dst_buffers (fimc); + self->dst[0] = NULL; + self->dst[1] = NULL; + self->dst[2] = NULL; + self->dst_stride[0] = 0; + 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; state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), @@ -394,6 +403,12 @@ gst_mfc_dec_negotiate (GstVideoDecoder * decoder) return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder); + + GST_DEBUG_OBJECT (self, + "Got direct output buffer: %p [%d], %p [%d], %p [%d]", self->dst[0], + self->dst_stride[0], self->dst[1], self->dst_stride[1], self->dst[2], + self->dst_stride[2]); + fimc_src_error: { GST_ELEMENT_ERROR (self, LIBRARY, FAILED, @@ -401,6 +416,13 @@ fimc_src_error: return FALSE; } +fimc_src_requestbuffers_error: + { + GST_ELEMENT_ERROR (self, LIBRARY, FAILED, + ("Failed to request FIMC source buffers"), (NULL)); + return FALSE; + } + fimc_dst_error: { GST_ELEMENT_ERROR (self, LIBRARY, FAILED, @@ -534,10 +556,13 @@ gst_mfc_dec_dequeue_output (GstMFCDec * self) 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_direct (fimc, (void **) mfc_outbuf_comps) < 0) + 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)) @@ -656,6 +681,14 @@ frame_map_error: goto done; } +fimc_dst_requestbuffers_error: + { + GST_ELEMENT_ERROR (self, LIBRARY, FAILED, + ("Failed to request FIMC destination buffers"), (NULL)); + ret = GST_FLOW_ERROR; + goto done; + } + fimc_convert_error: { GST_ELEMENT_ERROR (self, LIBRARY, FAILED,