Hi everyone,
I am working on HDMI driver for latest Samsung SoC. I encountered problem with format and crop setup. I noticed that this issue was mentioned other threads before. First I would like to describe environment of a cropping problem. There are two pieces of multimedia hardware on board I am working with. The avi decoder called MFC, and hdmi hardware called HDMI. Please refer to posts for further details:

http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/24022
http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/28885

The MFC transforms movie stream to image in NV12T format. This format is very similar to NV12 but pixels are organized into macroblocks of size 64 x 32. More information about NV12T format can be found in post:
http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/28942
Due to hardware limitations sizes of output image have to multiples of 128 x 32 pixels. The problem comes when movie size is not a multiple of 128 x 32. The MFC is a M2M device, so it supports G_CROP ioctl on both CAPTURE and OUTPUT buffer. The active area in output image is obtained by calling G_CROP on CAPTURE buffer.

Let's consider following scenario:

MFC configuration is done in the first few steps.
1. We have H264 movie in resolution 320 x 240.
2. ioctl(fd = MFC, S_FMT, v4l2_format { .type = OUTPUT,
   .pixelformat=FMT_H264})
3. Allocates buffers using REQBUF
4. QBUF few frames to get stream resolution
5. Calls ioctl(fd = MFC, G_FMT, v4l2_format { .type = CAPTURE}) to get width and height of buffer that suit to the movie. Lets call it full_width, and full_height. These are 384 x 256 because it is the smallest multiple of 128 x 64 that contains full image. 6. Call ioctl(fd = MFC, G_CROP, v4l2_crop { .type = CAPTURE}) to get movie resolution. Call it width and height.

Now HDMI is configured. Assume 720p resolution on display. One wants to see movie on full screen, this is resolution 1280 x 720.

7. ioctl(fd = HDMI, S_FMT, v4l2_format { .type = OUTPUT,
  .pixelformat=FMT_NV12T, .height = full_height, .width = full_width })
8. Allocate buffers using REQBUF
9. Queue buffers and start streaming and so on.

In such a case, MFC creates buffer of size 384 x 256. Only subimage of size 320 x 240 contains movie frame. All padding pixels are filled with zeros. The output image 384 x 256 is passed to HDMI which is an V4L2 output device. Zeroed pixels in YCrCr color space it an ugly green color. Such an ugly color is seen on output display.

And here comes the problem.

---------------------------------------------------------------

How to eliminate those ugly padding pixels from display output?

---------------------------------------------------------------

I think that possible solution to such a problem would be introducing new functionality called buffer crop. Please look at figures below. Figure 1 is similar to image 1.1 from V4L2 documentation:
http://www.linuxtv.org/downloads/v4l-dvb-apis/crop.html#crop-scale.
The value bounds.* refer to v4l2_cropcap.bounds. These values describe limits for cropping at output. The values c.* refer to v4l2_crop.c and describe active area on output device. Figure 2 depicts new feature called buffer crop. The image sizes pix.width and pix.height are configured using VIDIOC_S_FMT ioctl. The values bc.* define cropping rectangle in buffer. Only pixels inside IMAGE DATA rectangle are written/read during streaming. Only these pixels should be passed
to HDMI output. All other pixels are left untouched.

      bounds.width
  +--------------------+
  |                    |
 b| (c.left, c.top)    |
 o|       /            |
 u|      /             |
 n|     / c.width      |
 d|    +---------+     |
 s|  c |         |     |
 .|  . |         |     |
 h|  h |         |     |
 e|  e |  IMAGE  |     |
 i|  i |   DATA  |     |
 g|  g |         |     |
 h|  h |         |     |
 t|  t +---------+     |
  |                    |
  |                    |
  +--------------------+

Fig 1. Data on display.


      pix.width
 +-----------------------+
 |                       |
 |(bc.left, bc.top)      |
p|        \              |
i|         \  bc.width   |
x|          +---------+  |
.|         b|         |  |
h|         c|         |  |
e|         .|         |  |
i|         h|  IMAGE  |  |
g|         e|   DATA  |  |
h|         i|         |  |
t|         g|         |  |
 |         h|         |  |
 |         t+---------+  |
 |                       |
 |                       |
 +-----------------------+

Fig 2. Data in buffer.

Going back to above-mentioned scenario described. In order to avoid showing ugly pixels on output display one would configure buffer crop with value { left = 0, top = 0, width = 320, height = 240}. The driver would automatically adjust all values to accepted limits, align and scaling factors. For hw I possess no such changes need to be applied.

The only problem is passing such a buffer crop to driver by V4L2 api.
I considered a few solutions.

1. Use existing API.
Use bytesperline field in struct v4l2_pix_format to configure real width of image data. Additionally one would have to compute proper pointer in
v4l2_buffer.m.userptr to simulate left/top offsets. Unfortunately, value
bytesperline has little meaning for macroblock formats, because there is no such a thing like 'Distance in bytes between the leftmost pixels in two adjacent lines'. Pixels are not ordered linearly. Better definition of bytesperline has to be stated. Computing proper pointer to pixel for image in macroblock format would be possible only for very small set of coordinates. It may involve complex and error-prone computations.

What about more complex formats like JPEG? It is not possible to compute a pointer without decompressing image, and parsing it, and applying modification to data before passing buffer by VIDIOC_QBUF. It is not possible to perform such cropping even though it is support in hardware.

2. Use existing API. Version II.
The v4l2_crop structure lacks any free place for extensions. It is quite often that a device supports only one buffer type. Then other buffer types could be passed in v4l2_crop.type. For example passing V4L2_BUF_TYPE_VIDEO_OVERLAY for devices that support only V4L2_BUF_TYPE_VIDEO_OUTPUT would indicate configuration of buffer crop. I heard some rumour that Nokia once used this solution. For M2M devices buffer cropping in OUTPUT buffer is configured by setting crop on CAPTURE buffer and vice-versa.

3. Introduce new ioctl.
New ioctl called VIDIOC_S_BUFCROP would be used to configure buffer cropping. It would use exactly the same parameters as VIDIOC_S_CROP. Additionally VIDIOC_S_BUFCROPCAP would be added. It would be used to inform application about possible cropping in buffer data. Ioctl VIDIOC_G_BUFCROP would return current configuration of cropping. If driver does not support buffer cropping then ioctl would return {left = 0, top = 0, width = image_width, height = image_height}.

4. Introduce new ioctl. Version II
There was much discussion on scaling configuration by V4L2 api. Please look to post:
http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/27581/focus=28243
It was stated there that atomic crop/format configuration is needed. I thought that it would be a good idea to kill two birds using one stone. I mean setting both normal crop and buffer crop at the same time. Usage of buffer cropping may help to avoid changing image format. So following structure is proposed. It is passed to driver with new VIDIOC_S_CROP2 ioctl.

struct v4l2_crop2 {
        u32 type; /* buffer type */
        struct v4l2_crop c; /* crop in hw configured by S_CROP ioctl */
        struct v4l2_crop b; /* crop in buffer */
        u32 hint; /* hints for driver for crop adjustments */
        u32 reserved[?]; /* place for possible extensions */
};

Hint would be bit flags that Exemplary hint might be V4L2_CROP_HINT_B_WIDTH_UP, which would prevent driver from lowering width of buffer cropping. Keeping height on c crop fixed could be achieved by (V4L2_CROP_HINT_C_HEIGHT_UP | V4L2_CROP_HINT_C_HEIGHT_DOWN). Other hint might be V4L2_CROP_HINT_FMT_FIXED that would imply keeping width and height of image fixed. The driver would use hints to adjust cropping according both to application and hardware restriction
simultaneously.

What it your opinion about proposed solutions?

Looking for a reply,

Best regards,
Tomasz Stanislawski




--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to