aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-multimedia/gstreamer/gst-plugins-good/0018-videocrop-kick-off-NV12-zero-copy-cropping.patch
blob: 4e391dbaec416c9302c5e495dbfa513f7d3f24c9 (plain)
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
From 795110fd2b53f1197e94c61078153b3433a1d296 Mon Sep 17 00:00:00 2001
From: Kazunori Kobayashi <kkobayas@igel.co.jp>
Date: Thu, 4 Oct 2012 13:45:06 +0900
Subject: [PATCH 18/31] videocrop: kick off NV12 zero-copy cropping

This patch allows videocrop plugin to do zero-copy cropping by
adjusting the buffer offsets that are rowstride and chroma_byte_offset.
First of all, the function of cropping with memcpy is passed through
when the semi planar is set. Then, chroma_byte_offset is adjusted
to compensate for the extra offset due to creating the subbuffer,
which is caused by offsetting the buffer address based on Y plane.
---
 gst/videocrop/gstvideocrop.c |   37 ++++++++++++++++++++++++++++++++-----
 1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/gst/videocrop/gstvideocrop.c b/gst/videocrop/gstvideocrop.c
index df02302..6b1da8a 100644
--- a/gst/videocrop/gstvideocrop.c
+++ b/gst/videocrop/gstvideocrop.c
@@ -522,7 +522,8 @@ gst_video_crop_transform (GstBaseTransform * trans, GstBuffer * inbuf,
 
   if (vcrop->stride_supported &&
       ((vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE) ||
-          (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX))) {
+          (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) ||
+          (vcrop->in.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR))) {
     GST_LOG_OBJECT (vcrop, "passthrough because of zero-copy cropping");
     return GST_FLOW_OK;
   }
@@ -634,6 +635,7 @@ gst_video_crop_transform_caps (GstBaseTransform * trans,
     0,};
     GstVideoCropImageDetails img_details = { 0, };
     guint rowstride;
+    gint chroma_byte_offset, delta_chroma_offs;
 
     structure = gst_caps_get_structure (caps, i);
 
@@ -656,7 +658,7 @@ gst_video_crop_transform_caps (GstBaseTransform * trans,
     gst_structure_set_value (new_structure, "width", &w_val);
     gst_structure_set_value (new_structure, "height", &h_val);
 
-    /* set rowstride when creating output caps */
+    /* set rowstride and adjust chroma_byte_offset when creating output caps */
     if (!GST_VALUE_HOLDS_INT_RANGE (&w_val) &&
         !GST_VALUE_HOLDS_INT_RANGE (&h_val)) {
       if (!gst_video_crop_get_image_details_from_structure (vcrop, &img_details,
@@ -665,20 +667,42 @@ gst_video_crop_transform_caps (GstBaseTransform * trans,
         goto add_structure;
       }
     } else {
-      GST_LOG_OBJECT (vcrop, "go through setting rowstride");
+      GST_LOG_OBJECT (vcrop,
+          "go through setting rowstride and adjusting chroma_byte_offset");
       goto add_structure;
     }
 
     if (img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE ||
-        img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX)
+        img_details.packing == VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX) {
       rowstride = img_details.stride;
-    else
+      delta_chroma_offs = 0;
+    } else if (img_details.packing == VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR) {
+      guint ratio_y_c;
+
+      rowstride = img_details.stride;
+      /* Y plane / UV plane */
+      ratio_y_c = img_details.uv_off / (img_details.size - img_details.uv_off);
+      delta_chroma_offs = rowstride * vcrop->crop_top / ratio_y_c;
+    } else {
       rowstride = 0;
+      delta_chroma_offs = 0;
+    }
 
     if (vcrop->stride_supported && (direction == GST_PAD_SINK) && rowstride)
       gst_structure_set (new_structure, "rowstride", G_TYPE_INT,
           (gint) rowstride, NULL);
 
+    if (vcrop->stride_supported &&
+        gst_structure_get_int (structure, "chroma_byte_offset",
+            &chroma_byte_offset) && delta_chroma_offs) {
+      /* Adjust chroma_byte_offset because it would exceed the proper value
+         by delta_chroma_offs. It is due to offsetting the buffer address that
+         indicates Y plane with subbuffer for zero-copy cropping. */
+      chroma_byte_offset -= delta_chroma_offs;
+      gst_structure_set (new_structure, "chroma_byte_offset", G_TYPE_INT,
+          chroma_byte_offset, NULL);
+    }
+
   add_structure:
     g_value_unset (&w_val);
     g_value_unset (&h_val);
@@ -797,6 +821,9 @@ gst_video_crop_prepare_output_buffer (GstBaseTransform * trans,
   } 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) {
+    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");
-- 
1.7.9.5