1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
From e22281e0458c48f1d38b7a2abf20121378a811f8 Mon Sep 17 00:00:00 2001
From: Kazunori Kobayashi <kkobayas@igel.co.jp>
Date: Thu, 18 Oct 2012 18:27:03 +0900
Subject: [PATCH 22/31] videocrop: move output buffer size calculation to
transform_size()
transform_size() is the optional method that can be overridden to
calculate buffer sizes. The default implementation uses get_unit_size(),
but when performing zero-copy cropping, transform_size() should be used
because the buffer size calculation is different from the default.
The buffer size calculation should be performed using the tranform_size()
override, rather than being inlined in prepare_output_buffer().
---
gst/videocrop/gstvideocrop.c | 120 +++++++++++++++++++++++++++++++++---------
1 file changed, 95 insertions(+), 25 deletions(-)
diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c
index 4d2a027..4887137 100644
--- a/gst/videocrop/gstvideocrop.c
+++ b/gst/videocrop/gstvideocrop.c
@@ -140,6 +140,9 @@ static gboolean gst_video_crop_src_event (GstBaseTransform * trans,
static GstFlowReturn gst_video_crop_prepare_output_buffer (GstBaseTransform *
trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
static gboolean gst_video_crop_query_stride_supported (GstVideoCrop * vcrop);
+static gboolean gst_videocrop_transform_size (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
+ guint * othersize);
static void
gst_video_crop_base_init (gpointer g_class)
@@ -234,6 +237,8 @@ gst_video_crop_class_init (GstVideoCropClass * klass)
GST_DEBUG_FUNCPTR (gst_video_crop_get_unit_size);
basetransform_class->prepare_output_buffer =
GST_DEBUG_FUNCPTR (gst_video_crop_prepare_output_buffer);
+ basetransform_class->transform_size =
+ GST_DEBUG_FUNCPTR (gst_videocrop_transform_size);
basetransform_class->passthrough_on_same_caps = FALSE;
basetransform_class->src_event = GST_DEBUG_FUNCPTR (gst_video_crop_src_event);
@@ -838,7 +843,6 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans,
GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf)
{
GstVideoCrop *vcrop = GST_VIDEO_CROP (trans);
- guint sub_offset, sub_size;
if (!gst_video_crop_query_stride_supported (vcrop)) {
GST_LOG_OBJECT
@@ -847,30 +851,7 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans,
return GST_FLOW_OK;
}
- if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) {
- sub_offset = (vcrop->crop_top * vcrop->in.stride) +
- (vcrop->crop_left * vcrop->in.bytes_per_pixel);
- } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) {
- sub_offset = (vcrop->crop_top * vcrop->in.stride) +
- (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel);
- } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) {
- GstStructure *structure;
-
- structure = gst_caps_get_structure (caps, 0);
- if (vcrop->interlaced)
- sub_offset = (vcrop->crop_top / 2 * vcrop->in.stride) +
- ROUND_DOWN_2 (vcrop->crop_left);
- else
- sub_offset = (vcrop->crop_top * vcrop->in.stride) +
- ROUND_DOWN_2 (vcrop->crop_left);
- } else {
- GST_LOG_OBJECT (vcrop,
- "can't do zero-copy cropping except for packed format");
- return GST_FLOW_OK;
- }
-
- sub_size = vcrop->in.size - sub_offset;
- *buf = gst_buffer_create_sub (input, sub_offset, sub_size);
+ *buf = gst_buffer_create_sub (input, vcrop->in.size - size, size);
if (*buf == NULL) {
GST_ERROR_OBJECT (vcrop, "failed to create subbuffer");
return GST_FLOW_ERROR;
@@ -880,6 +861,95 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans,
return GST_FLOW_OK;
}
+static gboolean
+gst_videocrop_transform_size (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
+ guint * othersize)
+{
+ GstVideoCrop *vcrop = GST_VIDEO_CROP (trans);
+ guint inunitsize;
+
+ if (!gst_video_crop_query_stride_supported (vcrop) ||
+ direction == GST_PAD_SRC) {
+ guint outunitsize, units;
+
+ if (!gst_video_crop_get_unit_size (trans, caps, &inunitsize))
+ goto no_in_size;
+
+ GST_DEBUG_OBJECT (vcrop, "input size %d, input unit size %d", size,
+ inunitsize);
+
+ /* input size must be a multiple of the unit_size of the input caps */
+ if (inunitsize == 0 || (size % inunitsize != 0))
+ goto no_multiple;
+
+ /* get the amount of units */
+ units = size / inunitsize;
+
+ /* now get the unit size of the output */
+ if (!gst_video_crop_get_unit_size (trans, othercaps, &outunitsize))
+ goto no_out_size;
+
+ /* the output size is the unit_size times the amount of units on the
+ * input */
+ *othersize = units * outunitsize;
+ } else {
+ guint sub_offset;
+
+ /* Calculate a subbufer size for zero-copy cropping. The subbuffer is
+ created in prepare_output_buffer (). */
+ if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) {
+ sub_offset = (vcrop->crop_top * vcrop->in.stride) +
+ (vcrop->crop_left * vcrop->in.bytes_per_pixel);
+ } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) {
+ sub_offset = (vcrop->crop_top * vcrop->in.stride) +
+ (ROUND_DOWN_2 (vcrop->crop_left) * vcrop->in.bytes_per_pixel);
+ } else if (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) {
+ GstStructure *structure;
+
+ structure = gst_caps_get_structure (caps, 0);
+ if (vcrop->interlaced)
+ sub_offset = (vcrop->crop_top / 2 * vcrop->in.stride) +
+ ROUND_DOWN_2 (vcrop->crop_left);
+ else
+ sub_offset = (vcrop->crop_top * vcrop->in.stride) +
+ ROUND_DOWN_2 (vcrop->crop_left);
+ } else {
+ GST_LOG_OBJECT (vcrop,
+ "can't do zero-copy cropping except for packed format");
+ return FALSE;
+ }
+
+ *othersize = vcrop->in.size - sub_offset;
+ }
+
+ GST_DEBUG_OBJECT (vcrop, "transformed size to %d", *othersize);
+
+ return TRUE;
+
+ /* ERRORS */
+no_in_size:
+ {
+ GST_DEBUG_OBJECT (vcrop, "could not get in_size");
+ g_warning ("%s: could not get in_size", GST_ELEMENT_NAME (trans));
+ return FALSE;
+ }
+no_multiple:
+ {
+ GST_DEBUG_OBJECT (vcrop, "Size %u is not a multiple of unit size %u", size,
+ inunitsize);
+ g_warning ("%s: size %u is not a multiple of unit size %u",
+ GST_ELEMENT_NAME (trans), size, inunitsize);
+ return FALSE;
+ }
+no_out_size:
+ {
+ GST_DEBUG_OBJECT (vcrop, "could not get out_size");
+ g_warning ("%s: could not get out_size", GST_ELEMENT_NAME (trans));
+ return FALSE;
+ }
+}
+
static void
gst_video_crop_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
--
1.7.9.5
|