Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | From 3781d40940d46d7e6a502092d24aac7997f6da5b Mon Sep 17 00:00:00 2001 |
| 2 | From: Mingke Wang <mingke.wang@freescale.com> |
| 3 | Date: Thu, 5 Mar 2015 12:06:23 +0800 |
| 4 | Subject: [PATCH 1/4] basetextoverlay: make memory copy when video buffer's |
| 5 | memory is ready only |
| 6 | |
| 7 | 1. since gst_buffer_make_writable just lookup the refcount to determine if |
| 8 | a buffer is writable, and it will use _gst_buffer_copy() which don't |
| 9 | perform a deep memory copy even if the flag of a memory is set to |
| 10 | GST_MEMORY_FLAG_READONLY. So, we detect the memory flag and use |
| 11 | gst_buffer_copy_region with GST_BUFFER_COPY_DEEP parameter to perform |
| 12 | deep memory copy. if the allocator of a memory don't support mem_copy |
| 13 | interface, the it will return NULL, if this case, we can use |
| 14 | gst_buffer_make_writable() to get a shared memory buffer or the orignal |
| 15 | buffer if the buffer's refcount is 1. |
| 16 | 2. new feature is no added if caps has no feature during caps negotiation |
| 17 | |
| 18 | Upstream-Status: Submitted [https://bugzilla.gnome.org/show_bug.cgi?id=747495] |
| 19 | |
| 20 | Signed-off-by: Mingke Wang <mingke.wang@freescale.com> |
| 21 | |
| 22 | diff --git a/ext/pango/gstbasetextoverlay.c b/ext/pango/gstbasetextoverlay.c |
| 23 | index c919861..3c0a1d7 100755 |
| 24 | --- a/ext/pango/gstbasetextoverlay.c |
| 25 | +++ b/ext/pango/gstbasetextoverlay.c |
| 26 | @@ -747,6 +747,7 @@ gst_base_text_overlay_negotiate (GstBaseTextOverlay * overlay, GstCaps * caps) |
| 27 | if (f == NULL) { |
| 28 | f = gst_caps_features_new |
| 29 | (GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL); |
| 30 | + gst_caps_set_features(overlay_caps, 0, f); |
| 31 | } else { |
| 32 | gst_caps_features_add (f, |
| 33 | GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); |
| 34 | @@ -1890,16 +1891,71 @@ gst_base_text_overlay_push_frame (GstBaseTextOverlay * overlay, |
| 35 | if (gst_pad_check_reconfigure (overlay->srcpad)) |
| 36 | gst_base_text_overlay_negotiate (overlay, NULL); |
| 37 | |
| 38 | - video_frame = gst_buffer_make_writable (video_frame); |
| 39 | - |
| 40 | if (overlay->attach_compo_to_buffer) { |
| 41 | GST_DEBUG_OBJECT (overlay, "Attaching text overlay image to video buffer"); |
| 42 | + video_frame = gst_buffer_make_writable (video_frame); |
| 43 | gst_buffer_add_video_overlay_composition_meta (video_frame, |
| 44 | overlay->composition); |
| 45 | /* FIXME: emulate shaded background box if want_shading=true */ |
| 46 | goto done; |
| 47 | } |
| 48 | |
| 49 | + gint m = gst_buffer_n_memory(video_frame); |
| 50 | + gboolean mem_rdonly = FALSE; |
| 51 | + GstMemory *mem; |
| 52 | + GstBuffer *orig = video_frame; |
| 53 | + |
| 54 | + while (--m>=0) { |
| 55 | + mem = gst_buffer_get_memory(video_frame, m); |
| 56 | + if (GST_MEMORY_IS_READONLY(mem)) { |
| 57 | + mem_rdonly = TRUE; |
| 58 | + gst_memory_unref (mem); |
| 59 | + break; |
| 60 | + } |
| 61 | + gst_memory_unref (mem); |
| 62 | + } |
| 63 | + |
| 64 | + if (mem_rdonly) { |
| 65 | + // since gst_buffer_make_writable just lookup the refcount to determine if |
| 66 | + // a buffer is writable, and it will use _gst_buffer_copy() which don't |
| 67 | + // perform a deep memory copy even if the flag of a memory is set to |
| 68 | + // GST_MEMORY_FLAG_READONLY. So, we detect the memory flag and use |
| 69 | + // gst_buffer_copy_region with GST_BUFFER_COPY_DEEP parameter to perform |
| 70 | + // deep memory copy. if the allocator of a memory don't support mem_copy |
| 71 | + // interface, the it will return NULL, if this case, we can use |
| 72 | + // gst_buffer_make_writable() to get a shared memory buffer or the orignal |
| 73 | + // buffer if the buffer's refcount is 1. |
| 74 | + GstBuffer *new_buf = gst_buffer_copy_region (video_frame, |
| 75 | + GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1); |
| 76 | + |
| 77 | + GST_DEBUG_OBJECT (overlay, "copy %s video frame buffer %p -> %p", |
| 78 | + g_type_name (GST_MINI_OBJECT_TYPE (video_frame)), video_frame, new_buf); |
| 79 | + |
| 80 | + if (!new_buf) { |
| 81 | + //maybe the allocator don't support mem_copy interface, the we just use |
| 82 | + //gst_buffer_make_writable() to get a writable buffer. |
| 83 | + video_frame = gst_buffer_make_writable (video_frame); |
| 84 | + } else { |
| 85 | + gst_mini_object_unref (video_frame); |
| 86 | + GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_TAG_MEMORY); |
| 87 | + video_frame = new_buf; |
| 88 | + } |
| 89 | + |
| 90 | + if (!video_frame) { |
| 91 | + GST_WARNING_OBJECT (overlay, "make writable buffer failed"); |
| 92 | + return GST_FLOW_OK; |
| 93 | + } |
| 94 | + |
| 95 | + m = gst_buffer_n_memory(video_frame); |
| 96 | + while (--m>=0) { |
| 97 | + mem = gst_buffer_get_memory(video_frame, m); |
| 98 | + GST_MEMORY_FLAG_UNSET (mem, GST_MEMORY_FLAG_READONLY); |
| 99 | + gst_memory_unref (mem); |
| 100 | + } |
| 101 | + } else { |
| 102 | + video_frame = gst_buffer_make_writable (video_frame); |
| 103 | + } |
| 104 | + |
| 105 | if (!gst_video_frame_map (&frame, &overlay->info, video_frame, |
| 106 | GST_MAP_READWRITE)) |
| 107 | goto invalid_frame; |
| 108 | @@ -1918,6 +1974,18 @@ gst_base_text_overlay_push_frame (GstBaseTextOverlay * overlay, |
| 109 | |
| 110 | gst_video_frame_unmap (&frame); |
| 111 | |
| 112 | + if (mem_rdonly && orig == video_frame) { |
| 113 | + //if we used the original buffer and it's mem is set to read only, |
| 114 | + //recover the memory ready only flag since we unset it before |
| 115 | + // gst_video_frame_map () |
| 116 | + m = gst_buffer_n_memory(video_frame); |
| 117 | + while (--m>=0) { |
| 118 | + mem = gst_buffer_get_memory(video_frame, m); |
| 119 | + GST_MEMORY_FLAGS(mem) |= (GST_MEMORY_FLAG_READONLY); |
| 120 | + gst_memory_unref (mem); |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | done: |
| 125 | |
| 126 | return gst_pad_push (overlay->srcpad, video_frame); |
| 127 | -- |
| 128 | 1.7.9.5 |
| 129 | |