After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 760270 - videoparse: add support of padded video
videoparse: add support of padded video
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-bad
git master
Other All
: Normal enhancement
: 1.7.2
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2016-01-07 14:36 UTC by Aurélien Zanelli
Modified: 2016-01-28 19:53 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
rawparse: add a vfunc to enable subclass to add buffer metadata (1.44 KB, patch)
2016-01-07 14:38 UTC, Aurélien Zanelli
none Details | Review
videoparse: cache video info in instance (3.57 KB, patch)
2016-01-07 14:40 UTC, Aurélien Zanelli
none Details | Review
videoparse: add properties to set image padding (6.64 KB, patch)
2016-01-07 14:45 UTC, Aurélien Zanelli
none Details | Review
[1/6] videoparse: cache video info in instance (3.57 KB, patch)
2016-01-12 14:25 UTC, Aurélien Zanelli
committed Details | Review
[2/6] rawparse: rename 'set_buffer_flags' vfunc to 'pre_push_buffer' (2.78 KB, patch)
2016-01-12 14:28 UTC, Aurélien Zanelli
committed Details | Review
[3/6] videoparse: add properties to set framesize, strides and planes offsets (11.65 KB, patch)
2016-01-12 14:33 UTC, Aurélien Zanelli
none Details | Review
[4/6] rawparse: use size of buffer we got from adapter (1.29 KB, patch)
2016-01-12 14:37 UTC, Aurélien Zanelli
committed Details | Review
[5/6] rawparse: add 'decide_allocation' vfunc to let subclass parse an allocation query (1.83 KB, patch)
2016-01-12 14:39 UTC, Aurélien Zanelli
committed Details | Review
[6/6] videoparse: use decide_allocation to check if downstream supports videometa (3.47 KB, patch)
2016-01-12 14:40 UTC, Aurélien Zanelli
committed Details | Review
[3/6] videoparse: add properties to set framesize, strides and planes offsets (13.08 KB, patch)
2016-01-26 15:32 UTC, Aurélien Zanelli
none Details | Review
[3/6] videoparse: add properties to set framesize, strides and planes offsets (13.24 KB, patch)
2016-01-28 09:42 UTC, Aurélien Zanelli
needs-work Details | Review
[3/6] videoparse: add properties to set framesize, strides and planes offsets (13.21 KB, patch)
2016-01-28 12:47 UTC, Aurélien Zanelli
committed Details | Review
videoparse: Fix framesize calculation (1.42 KB, patch)
2016-01-28 17:02 UTC, Nicolas Dufresne (ndufresne)
committed Details | Review
videoparse: initialize update_size to FALSE when updating info (924 bytes, patch)
2016-01-28 17:33 UTC, Aurélien Zanelli
committed Details | Review

Description Aurélien Zanelli 2016-01-07 14:36:17 UTC
Currently raw video parser (videoparse) doesn't support video with padding, e.g custom stride.
So I propose to solve this by adding 4 properties: top,bottom,left and right; and use them in GstVideoAlignment to adjust video info and so framesize.

Also, in case we have padding, I propose to add video meta to output buffer using a new vfunc in rawparse 'add_buffer_meta'.

So that we should be able to successfully play a raw video with padding.
Comment 1 Aurélien Zanelli 2016-01-07 14:38:20 UTC
Created attachment 318417 [details] [review]
rawparse: add a vfunc to enable subclass to add buffer metadata

First patch to add a vfunc to add buffer metadata in rawparse base class.
Comment 2 Aurélien Zanelli 2016-01-07 14:40:00 UTC
Created attachment 318419 [details] [review]
videoparse: cache video info in instance

This patch stored video info in video parser instance to avoid initializing one and filling one each time we use GstVideoInfo to make our life easier, ie calculate the framesize and the caps.
Comment 3 Sebastian Dröge (slomo) 2016-01-07 14:44:17 UTC
Good idea but top/bottom/left/right padding is different from stride and they should be provided separately. You might also have different stride per plane, and padding between planes (i.e. plane offsets).

Adding videometa is probably required in all these cases, you however have to check if downstream actually supports it and otherwise fail (or convert).
Comment 4 Aurélien Zanelli 2016-01-07 14:45:16 UTC
Created attachment 318420 [details] [review]
videoparse: add properties to set image padding

This is the patch which add the 4 properties to set padding. It also add in each output buffer video info metadata.

Note that I currently assume that downstream supports GstVideoMeta. We may check if it's the case or not. And if downstream doesn't support them, we should have to copy frame to remove padding.
Comment 5 Nicolas Dufresne (ndufresne) 2016-01-07 14:47:21 UTC
I would prefer if we add two properties, strides and offset, a coma seperated list form to make it easy to use from gst-launch.

The problem with top/left/right/bottom is that you cannot specify arbitrary padding between planes, which I have seen from time to time. (and of course we need not to assume what downstream support, and copy if the GstVideoMeta is not supported).
Comment 6 Aurélien Zanelli 2016-01-08 11:05:48 UTC
(In reply to Nicolas Dufresne (stormer) from comment #5)
> I would prefer if we add two properties, strides and offset, a coma
> seperated list form to make it easy to use from gst-launch.

Not a bad idea, I will go for it with both expressed in bytes as it solve arbitrary padding between planes. I think we should also support padding between images, so we may have to provide a 'framesize' property.

If I'm right, with this set of property, we could handle all cases:
- padding before image
- padding after image
- padding between planes
- padding before and after image line per plane (with stride)
Comment 7 Nicolas Dufresne (ndufresne) 2016-01-08 18:06:19 UTC
Oh good point about framesize, I agree. And offsets (with an s), correcting my typo. Btw, if downstream does not support GstVideoMeta, you can simply use gst_video_frame_copy(), it works for "normalizing" video frames.
Comment 8 Aurélien Zanelli 2016-01-12 14:25:58 UTC
Created attachment 318874 [details] [review]
[1/6] videoparse: cache video info in instance
Comment 9 Aurélien Zanelli 2016-01-12 14:28:00 UTC
Created attachment 318875 [details] [review]
[2/6] rawparse: rename 'set_buffer_flags' vfunc to 'pre_push_buffer'

Minor naming change to allow subclass to make other change in the buffer, not just the flags.
Comment 10 Aurélien Zanelli 2016-01-12 14:33:55 UTC
Created attachment 318876 [details] [review]
[3/6] videoparse: add properties to set framesize, strides and planes offsets

This patch only add the properties 'framesize', 'strides' and 'offsets' and copy frame when we have some as support of videometa is not present yet.
Comment 11 Aurélien Zanelli 2016-01-12 14:37:11 UTC
Created attachment 318878 [details] [review]
[4/6] rawparse: use size of buffer we got from adapter

When rawparse push a buffer, it increments its current offset using buffer size. But buffer size could have changed in pre_push_frame call causing wrong position update and so wrong data to be handled.
Comment 12 Aurélien Zanelli 2016-01-12 14:39:45 UTC
Created attachment 318879 [details] [review]
[5/6] rawparse: add 'decide_allocation' vfunc to let subclass parse an allocation query

This patch send an allocation query to downstream element and add a simple vfunc to let 'subclass' check result of it. It will be used to check if downstream supports various meta so base class doesn't handle any buffer pool or allocation parameters.
Comment 13 Aurélien Zanelli 2016-01-12 14:40:24 UTC
Created attachment 318881 [details] [review]
[6/6] videoparse: use decide_allocation to check if downstream supports videometa
Comment 14 Aurélien Zanelli 2016-01-12 14:48:26 UTC
Here is a new patch set to add discussed properties and needed vfunc in rawparse base class. I tried to split commits to make them easier to review and comment, especially the vfunc part and their usage.
Comment 15 Nicolas Dufresne (ndufresne) 2016-01-25 22:46:54 UTC
Review of attachment 318874 [details] [review]:

Good.
Comment 16 Nicolas Dufresne (ndufresne) 2016-01-25 22:47:44 UTC
Review of attachment 318875 [details] [review]:

Good.
Comment 17 Nicolas Dufresne (ndufresne) 2016-01-25 23:00:03 UTC
Review of attachment 318876 [details] [review]:

::: gst/rawparse/gstvideoparse.c
@@ +31,3 @@
 
+#include <stdlib.h>
+#include <stdio.h>

Why ?

@@ +302,3 @@
+{
+  return info->stride[plane] *
+      GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, plane, info->height);

You need a special case for nv12-64z32 . In tiled format, the stride is an encoding of the number of tiles in x and y axis. So you extract those two values using the macros, and then you calculate the number of tiles, multiplied by the size of each tiles.

@@ +347,3 @@
+
+  /* 1. check that provided offsets are greaters than the default ones and is
+   * consistent with plane size */

For I420, GStreamer defaults add an empty line, which imho is acceptable no to have. It's a minor issue though.
Comment 18 Nicolas Dufresne (ndufresne) 2016-01-25 23:00:59 UTC
Review of attachment 318878 [details] [review]:

Looks good.
Comment 19 Nicolas Dufresne (ndufresne) 2016-01-25 23:01:41 UTC
Review of attachment 318879 [details] [review]:

Good.
Comment 20 Nicolas Dufresne (ndufresne) 2016-01-25 23:03:03 UTC
Review of attachment 318881 [details] [review]:

Good.
Comment 21 Aurélien Zanelli 2016-01-26 15:32:06 UTC
Created attachment 319760 [details] [review]
[3/6] videoparse: add properties to set framesize, strides and planes offsets

(In reply to Nicolas Dufresne (stormer) from comment #17)
> Review of attachment 318876 [details] [review] [review]:
> 
> ::: gst/rawparse/gstvideoparse.c
> @@ +31,3 @@
>  
> +#include <stdlib.h>
> +#include <stdio.h>
> 
> Why ?
stdlib is needed for atoi function used to parse stride/offset string but stdio was not needed so I remove it.

> 
> @@ +302,3 @@
> +{
> +  return info->stride[plane] *
> +      GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, plane, info->height);
> 
> You need a special case for nv12-64z32 . In tiled format, the stride is an
> encoding of the number of tiles in x and y axis. So you extract those two
> values using the macros, and then you calculate the number of tiles,
> multiplied by the size of each tiles.

I've done the modification, I've also change the stride update check for tiled format. In case format is tiled I check number of tile in x and y is set by user is greater than the defaults one.

> 
> @@ +347,3 @@
> +
> +  /* 1. check that provided offsets are greaters than the default ones and
> is
> +   * consistent with plane size */
> 
> For I420, GStreamer defaults add an empty line, which imho is acceptable no
> to have. It's a minor issue though.
I'm not sure I understand what you mean here.
Do you mean the 'empty line' added by the round up of height when it's no a multiple of 2 ?
In this case, it seems right to do that, no ?
Comment 22 Nicolas Dufresne (ndufresne) 2016-01-26 19:48:19 UTC
(In reply to Aurélien Zanelli from comment #21)
> Created attachment 319760 [details] [review] [review]
> [3/6] videoparse: add properties to set framesize, strides and planes offsets
> 
> (In reply to Nicolas Dufresne (stormer) from comment #17)
> > Review of attachment 318876 [details] [review] [review] [review]:
> > 
> > ::: gst/rawparse/gstvideoparse.c
> > @@ +31,3 @@
> >  
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > 
> > Why ?
> stdlib is needed for atoi function used to parse stride/offset string but
> stdio was not needed so I remove it.

Make sense. Would it possible to port to g_ascii_strtoll() or g_ascii_strtoull(), just to make sure we stay portable (maybe I'm over worried here ?)

> > 
> > @@ +347,3 @@
> > +
> > +  /* 1. check that provided offsets are greaters than the default ones and
> > is
> > +   * consistent with plane size */
> > 
> > For I420, GStreamer defaults add an empty line, which imho is acceptable no
> > to have. It's a minor issue though.
> I'm not sure I understand what you mean here.
> Do you mean the 'empty line' added by the round up of height when it's no a
> multiple of 2 ?
> In this case, it seems right to do that, no ?

So, what we do in GStreamer as a default for I420 and YV12 is:

  info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);

This effectively skip a line. Skipping this line has no effect on memory alignment. Odd and even lines have the same memory alignment. I don't really know the origin of this. An offset 0 to 0 and offset 1 to (even if height is odd):

  info->offset[1] = info->stride[0] * height;

Would be completely valid. In fact this is what you get from GLMemory. So basically, this is one case where the GStreamer default offset is not the minimum acceptable offset. The minimum acceptable offset is (for i < (num_planes -1)):

  offset[i + 1] = offset[i] + height * stride[i]
Comment 23 Aurélien Zanelli 2016-01-27 12:50:28 UTC
(In reply to Nicolas Dufresne (stormer) from comment #22)
> (In reply to Aurélien Zanelli from comment #21)
> > stdlib is needed for atoi function used to parse stride/offset string but
> > stdio was not needed so I remove it.
> 
> Make sense. Would it possible to port to g_ascii_strtoll() or
> g_ascii_strtoull(), just to make sure we stay portable (maybe I'm over
> worried here ?)

No problem to port it, in fact I found we often use these functions to parse int. After some research, it seems they have more error checking that atoi.

> > > For I420, GStreamer defaults add an empty line, which imho is acceptable no
> > > to have. It's a minor issue though.
> > I'm not sure I understand what you mean here.
> > Do you mean the 'empty line' added by the round up of height when it's no a
> > multiple of 2 ?
> > In this case, it seems right to do that, no ?
> 
> So, what we do in GStreamer as a default for I420 and YV12 is:
> 
>   info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
> 
> This effectively skip a line. Skipping this line has no effect on memory
> alignment. Odd and even lines have the same memory alignment. I don't really
> know the origin of this.

In my current understanding, it's due to the subsampling of 4:2:0 formats:
If we have a NxN luma plane, U and V planes have a size of (N/2)x(N/2) since
1 chroma sample is mapped to a 2x2 squared luma sample.
So, for me, it implies that luma plane width and height should be at least multiple of two.

So I think we round up U/V plane offset to be more portable as some elements may not like an odd number of lines.

We may CC Wim here to have more details on that. And by the way, it is the same for NV12/NV21 formats.

> An offset 0 to 0 and offset 1 to (even if height is odd):
> 
>   info->offset[1] = info->stride[0] * height;
> 
> Would be completely valid. In fact this is what you get from GLMemory. So
> basically, this is one case where the GStreamer default offset is not the
> minimum acceptable offset. The minimum acceptable offset is (for i <
> (num_planes -1)):
> 
>   offset[i + 1] = offset[i] + height * stride[i]

I think, there is no issue to handle this special case in videoparse so I will do it.
Comment 24 Aurélien Zanelli 2016-01-28 09:42:25 UTC
Created attachment 319905 [details] [review]
[3/6] videoparse: add properties to set framesize, strides and planes offsets

Strides and offsets parsing has been ported to g_ascii_strtoll.
Comment 25 Aurélien Zanelli 2016-01-28 11:01:46 UTC
Review of attachment 319905 [details] [review]:

::: gst/rawparse/gstvideoparse.c
@@ -212,0 +276,135 @@
+static gboolean
+gst_video_parse_deserialize_int_array (const gchar * str, gint * dest,
+    guint n_values)
... 132 more ...

should be vp->offset[i] < min_offset
Comment 26 Aurélien Zanelli 2016-01-28 12:47:52 UTC
Created attachment 319923 [details] [review]
[3/6] videoparse: add properties to set framesize, strides and planes offsets

I fix update_offset function which was incorrect.
It now check user offset against the max of info->offset[i] and user_offset[i-1] + plane_size[i-1]

I also propose to make the 4:2:0 formats odd height handling after reviewing/merging this patch to keep it simple.
Comment 27 Nicolas Dufresne (ndufresne) 2016-01-28 13:36:06 UTC
Review of attachment 319923 [details] [review]:

Looks good to me know. I'm fine with dealing with remaining details in separate patches.
Comment 28 Nicolas Dufresne (ndufresne) 2016-01-28 13:37:28 UTC
(In reply to Aurélien Zanelli from comment #26)
> I also propose to make the 4:2:0 formats odd height handling after
> reviewing/merging this patch to keep it simple.

Yes, good idea.
Comment 29 Nicolas Dufresne (ndufresne) 2016-01-28 16:22:04 UTC
I'm marking it fixed, we can carry the rest in seperate bugs of course.
Comment 30 Nicolas Dufresne (ndufresne) 2016-01-28 16:41:53 UTC
I actually found a little bug here, this should work, but display artefact:

GST_DEBUG=2 gst-launch-1.0 videotestsrc ! videoparse format=i420 width=320 height=240 strides=320,160,160,0 ! xvimagesink
Comment 31 Nicolas Dufresne (ndufresne) 2016-01-28 16:46:08 UTC
For some reason it recalculates the frame size wrong.

videoparse gstvideoparse.c:495:gst_video_parse_update_info:<videoparse0> video info: 320x240, format I420, size 192000, stride {320,160,160,0}, offset {0,76800,96000,0}
Comment 32 Nicolas Dufresne (ndufresne) 2016-01-28 16:52:44 UTC
Ok, the problem is about adding the offset, you endup adding twice the same part of the memory. You also need to understand that with videometa, conversion from let's say I420 to YV12 can be done by flipping the two last offsets. So the minimum frame size is a bit more complex to calculate.
Comment 33 Nicolas Dufresne (ndufresne) 2016-01-28 17:02:39 UTC
Created attachment 319957 [details] [review]
videoparse: Fix framesize calculation

When the framesize is not specified, we try and calculate a size from
the strides and offset information. This was done with the sum of
offsets + the size of the last frame. That is just wrong method. We also
need to account for video meta that may be flipping two planes. An
example is if you convert I420 to YV12 by flipping the two last offsets.
Comment 34 Nicolas Dufresne (ndufresne) 2016-01-28 17:04:38 UTC
That fixes it for me, need more testing (I'm a bit in a hurry now). Another issue is that we have no equivalent for framesize_set, so if we set a stride or an offset, we can no longer also add a framesize (it get overwritten). This can be solved by overriding the property, and then proxying to the base class with the appropriate method.
Comment 35 Aurélien Zanelli 2016-01-28 17:33:35 UTC
Created attachment 319958 [details] [review]
videoparse: initialize update_size to FALSE when updating info

I also let update_size uninitialized which can cause bad behavior.
Here is a patch to initialize it.
Comment 36 Aurélien Zanelli 2016-01-28 18:06:17 UTC
(In reply to Nicolas Dufresne (stormer) from comment #33)
> Created attachment 319957 [details] [review] [review]
> videoparse: Fix framesize calculation
> 
> When the framesize is not specified, we try and calculate a size from
> the strides and offset information. This was done with the sum of
> offsets + the size of the last frame. That is just wrong method. We also
> need to account for video meta that may be flipping two planes. An
> example is if you convert I420 to YV12 by flipping the two last offsets.

I don't set the patch as accepted as I don't know if I'm allowed to do this but patch looks good. 
There is just 'planesize' which may be a confusion name though.

I tested it with I420 and Y42B with default and custom stride and it's ok.
However flipping offsets doesn't work at all since user provided offsets are checked against provided format defaults offsets which are sorted from small to large. Hence offsets will likely be ignored in this case.
Comment 37 Aurélien Zanelli 2016-01-28 18:19:01 UTC
(In reply to Nicolas Dufresne (stormer) from comment #34)
> That fixes it for me, need more testing (I'm a bit in a hurry now). Another
> issue is that we have no equivalent for framesize_set, so if we set a stride
> or an offset, we can no longer also add a framesize (it get overwritten).
> This can be solved by overriding the property, and then proxying to the base
> class with the appropriate method.

User provided framesize is set after size update from strides/offset to video info struct (only if bigger). Then when we set the base class framesize, we read back the value from info so it takes the user value if one has been set and is valid.
Confusing thing is that I updated directly vp->info.size instead of info->size (info point to &vp->info). I could make a patch to replace vp->info by info to make it clearer.
Comment 38 Nicolas Dufresne (ndufresne) 2016-01-28 19:39:34 UTC
Ah ok, make sense, I didn't tested that framesize presumed issue, I fully trust you on that. Let's push those two then, we can improve the validation later (it's not a regression).
Comment 39 Nicolas Dufresne (ndufresne) 2016-01-28 19:52:55 UTC
Attachment 319957 [details] pushed as acb7205 - videoparse: Fix framesize calculation
Attachment 319958 [details] pushed as 5fd3511 - videoparse: initialize update_size to FALSE when updating info