[glsdk/meta-ti-glsdk.git] / recipes-ti / gstreamer-ti / gstreamer-ti / 0007-Add-support-for-pad-allocated-buffers-in-TIDmaiVideo.patch
1 From 108fa0bb550f9b7355bfd5ae5340220fd1a4c9b5 Mon Sep 17 00:00:00 2001
2 From: Don Darling <don.osc2@gmail.com>
3 Date: Thu, 5 Aug 2010 15:09:54 -0500
4 Subject: [PATCH 7/8] Add support for pad-allocated buffers in TIDmaiVideoSink.
6 This feature is currently only tested and enabled for DM365.
7 ---
8 .../ticodecplugin/src/gsttidmaibuffertransport.c | 4 +-
9 .../ticodecplugin/src/gsttidmaibuffertransport.h | 6 +-
10 .../ticodecplugin/src/gsttidmaivideosink.c | 197 ++++++++++++++++++--
11 3 files changed, 191 insertions(+), 16 deletions(-)
13 diff --git a/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.c b/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.c
14 index 5fad371..9c69285 100644
15 --- a/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.c
16 +++ b/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.c
17 @@ -136,8 +136,8 @@ static void gst_tidmaibuffertransport_finalize(GstBuffer *gstbuffer)
18 */
19 if (Buffer_getBufTab(self->dmaiBuffer) != NULL) {
20 GST_LOG("clearing GStreamer useMask bit\n");
21 - Buffer_freeUseMask(self->dmaiBuffer,
22 - gst_tidmaibuffer_GST_FREE);
23 + Buffer_freeUseMask(self->dmaiBuffer, gst_tidmaibuffer_GST_FREE);
24 + Buffer_freeUseMask(self->dmaiBuffer, gst_tidmaibuffer_VIDEOSINK_FREE);
25 } else {
26 GST_LOG("calling Buffer_delete()\n");
27 Buffer_delete(self->dmaiBuffer);
28 diff --git a/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.h b/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.h
29 index 0265e70..20945f3 100644
30 --- a/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.h
31 +++ b/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaibuffertransport.h
32 @@ -52,8 +52,10 @@ G_BEGIN_DECLS
33 GstTIDmaiBufferTransportClass))
35 /* Use mask flags that keep track of where buffer is in use */
36 -#define gst_tidmaibuffer_GST_FREE 0x1
37 -#define gst_tidmaibuffer_CODEC_FREE 0x2
38 +#define gst_tidmaibuffer_GST_FREE 0x1
39 +#define gst_tidmaibuffer_CODEC_FREE 0x2
40 +#define gst_tidmaibuffer_VIDEOSINK_FREE 0x4
41 +#define gst_tidmaibuffer_DISPLAY_FREE 0x8
43 typedef struct _GstTIDmaiBufferTransport GstTIDmaiBufferTransport;
44 typedef struct _GstTIDmaiBufferTransportClass GstTIDmaiBufferTransportClass;
45 diff --git a/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaivideosink.c b/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaivideosink.c
46 index 0125ed2..7b84a8e 100644
47 --- a/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaivideosink.c
48 +++ b/gstreamer_ti/ti_build/ticodecplugin/src/gsttidmaivideosink.c
49 @@ -151,6 +151,9 @@ static GstStateChangeReturn
50 gst_tidmaivideosink_change_state(GstElement * element,
51 GstStateChange transition);
52 static GstFlowReturn
53 + gst_tidmaivideosink_buffer_alloc(GstBaseSink * bsink, guint64 offset,
54 + guint size, GstCaps * caps, GstBuffer ** buf);
55 +static GstFlowReturn
56 gst_tidmaivideosink_preroll(GstBaseSink * bsink, GstBuffer * buffer);
57 static int
58 gst_tidmaivideosink_videostd_get_attrs(VideoStd_Type videoStd,
59 @@ -353,6 +356,13 @@ static void gst_tidmaivideosink_class_init(GstTIDmaiVideoSinkClass * klass)
60 GST_DEBUG_FUNCPTR(gst_tidmaivideosink_preroll);
61 gstbase_sink_class->render =
62 GST_DEBUG_FUNCPTR(gst_tidmaivideosink_render);
63 + gstbase_sink_class->buffer_alloc =
64 + GST_DEBUG_FUNCPTR(gst_tidmaivideosink_buffer_alloc);
65 +
66 + /* Pad-buffer allocation is currently only supported for DM365 */
67 + #if !defined(Platform_dm365)
68 + gstbase_sink_class->buffer_alloc = NULL;
69 + #endif
70 }
73 @@ -663,6 +673,132 @@ static gboolean gst_tidmaivideosink_event(GstBaseSink * bsink,
76 /******************************************************************************
77 + * gst_tidmaivideosink_buffer_alloc
78 + ******************************************************************************/
79 +static GstFlowReturn gst_tidmaivideosink_buffer_alloc(GstBaseSink * bsink,
80 + guint64 offset, guint size, GstCaps * caps,
81 + GstBuffer ** buf)
82 +{
83 + GstTIDmaiVideoSink *dmaisink = GST_TIDMAIVIDEOSINK(bsink);
84 + BufferGfx_Attrs gfxAttrs = BufferGfx_Attrs_DEFAULT;
85 + gboolean alloc_unref = FALSE;
86 + Buffer_Handle hDispBuf = NULL;
87 + GstCaps *alloc_caps;
88 +
89 + *buf = NULL;
90 +
91 + GST_LOG_OBJECT(dmaisink,
92 + "a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT
93 + " and offset %" G_GUINT64_FORMAT, size, caps, offset);
94 +
95 + /* assume we're going to alloc what was requested, keep track of wheter we
96 + * need to unref or not. When we suggest a new format upstream we will
97 + * create a new caps that we need to unref. */
98 + alloc_caps = caps;
99 +
100 + /* Process the buffer caps */
101 + if (!gst_tidmaivideosink_process_caps(bsink, alloc_caps)) {
102 + return GST_FLOW_UNEXPECTED;
103 + }
104 +
105 + /* Pad buffer allocation requires that we use user-allocated display
106 + * buffers.
107 + */
108 + if (!dmaisink->useUserptrBufs && dmaisink->hDisplay) {
109 + GST_ELEMENT_ERROR(dmaisink, RESOURCE, FAILED,
110 + ("Cannot use pad buffer allocation after mmap buffers already "
111 + "in use\n"), (NULL));
112 + return GST_FLOW_UNEXPECTED;
113 + }
114 + else {
115 + dmaisink->useUserptrBufs = TRUE;
116 + }
117 +
118 + /* Allocate the display buffers */
119 + if (!dmaisink->hDispBufTab && dmaisink->useUserptrBufs) {
120 +
121 + /* Set the display attributes now so we can allocate display buffers */
122 + if (!gst_tidmaivideosink_set_display_attrs(dmaisink,
123 + dmaisink->dGfxAttrs.colorSpace)) {
124 + GST_ERROR("Error while trying to set the display attributes\n");
125 + return GST_FLOW_UNEXPECTED;
126 + }
127 +
128 + if (!gst_tidmaivideosink_alloc_display_buffers(dmaisink, size)) {
129 + GST_ERROR("Failed to allocate display buffers");
130 + return GST_FLOW_UNEXPECTED;
131 + }
132 + }
133 +
134 + /* Get a buffer from the BufTab or display driver */
135 + if (!(hDispBuf = gst_tidmaibuftab_get_buf(dmaisink->hDispBufTab))) {
136 + if (dmaisink->hDisplay &&
137 + Display_get(dmaisink->hDisplay, &hDispBuf) < 0) {
138 + GST_ELEMENT_ERROR(dmaisink, RESOURCE, FAILED,
139 + ("Failed to get display buffer\n"), (NULL));
140 + return GST_FLOW_UNEXPECTED;
141 + }
142 + }
143 +
144 + /* If the geometry doesn't match, generate a new caps for it */
145 + Buffer_getAttrs(hDispBuf, BufferGfx_getBufferAttrs(&gfxAttrs));
146 +
147 + if (gfxAttrs.dim.width != dmaisink->dGfxAttrs.dim.width ||
148 + gfxAttrs.dim.height != dmaisink->dGfxAttrs.dim.height ||
149 + gfxAttrs.colorSpace != dmaisink->dGfxAttrs.colorSpace) {
150 +
151 + GstCaps *desired_caps;
152 + GstStructure *desired_struct;
153 +
154 + /* make a copy of the incomming caps to create the new suggestion. We
155 + * can't use make_writable because we might then destroy the original
156 + * caps which we still need when the peer does not accept the
157 + * suggestion.
158 + */
159 + desired_caps = gst_caps_copy (caps);
160 + desired_struct = gst_caps_get_structure (desired_caps, 0);
161 +
162 + GST_DEBUG ("we prefer to receive a %ldx%ld video; %ldx%ld was requested",
163 + gfxAttrs.dim.width, gfxAttrs.dim.height,
164 + dmaisink->dGfxAttrs.dim.width, dmaisink->dGfxAttrs.dim.height);
165 + gst_structure_set (desired_struct, "width", G_TYPE_INT,
166 + gfxAttrs.dim.width, NULL);
167 + gst_structure_set (desired_struct, "height", G_TYPE_INT,
168 + gfxAttrs.dim.height, NULL);
169 +
170 + if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (dmaisink),
171 + desired_caps)) {
172 + alloc_caps = desired_caps;
173 + alloc_unref = TRUE;
174 +
175 + if (!gst_tidmaivideosink_process_caps(bsink, alloc_caps)) {
176 + return GST_FLOW_UNEXPECTED;
177 + }
178 + GST_DEBUG ("peer pad accepts our desired caps %" GST_PTR_FORMAT,
179 + desired_caps);
180 + }
181 + else {
182 + GST_DEBUG ("peer pad does not accept our desired caps %"
183 + GST_PTR_FORMAT, desired_caps);
184 + }
185 + }
186 +
187 + /* Return the display buffer */
188 + BufferGfx_resetDimensions(hDispBuf);
189 + Buffer_freeUseMask(hDispBuf, gst_tidmaibuffer_DISPLAY_FREE);
190 + *buf = gst_tidmaibuffertransport_new(hDispBuf, NULL);
191 + gst_buffer_set_caps(*buf, alloc_caps);
192 +
193 + /* If we allocated new caps, unref them now */
194 + if (alloc_unref) {
195 + gst_caps_unref (alloc_caps);
196 + }
197 +
198 + return GST_FLOW_OK;
199 +}
200 +
201 +
202 +/******************************************************************************
203 * gst_tidmaivideosink_preroll
204 ******************************************************************************/
205 static GstFlowReturn gst_tidmaivideosink_preroll(GstBaseSink * bsink,
206 @@ -1282,6 +1418,18 @@ static gboolean gst_tidmaivideosink_init_display(GstTIDmaiVideoSink * sink)
207 return FALSE;
208 }
210 + /* If we own the display buffers, tell DMAI to delay starting the
211 + * display until we call Display_put for the first time.
212 + */
213 + if (sink->hDispBufTab) {
214 + #if defined(Platform_dm365)
215 + sink->dAttrs.delayStreamon = TRUE;
216 + #else
217 + GST_ERROR("delayed V4L2 streamon not supported\n");
218 + return FALSE;
219 + #endif
220 + }
221 +
222 /* Allocate user-allocated display buffers, if requested */
223 if (!sink->hDispBufTab && sink->useUserptrBufs) {
224 if (!gst_tidmaivideosink_alloc_display_buffers(sink, 0)) {
225 @@ -1416,9 +1564,6 @@ static gboolean gst_tidmaivideosink_process_caps(GstBaseSink * bsink,
226 gst_structure_get_fraction(structure, "framerate", &framerateNum,
227 &framerateDen);
229 - /* Error check new values against existing ones */
230 - /* TBD */
231 -
232 /* Populate the display graphics attributes */
233 dmaisink->dGfxAttrs.bAttrs.reference = dmaisink->contiguousInputFrame;
234 dmaisink->dGfxAttrs.dim.width = width;
235 @@ -1445,9 +1590,10 @@ static gboolean gst_tidmaivideosink_process_caps(GstBaseSink * bsink,
236 static GstFlowReturn gst_tidmaivideosink_render(GstBaseSink * bsink,
237 GstBuffer * buf)
238 {
239 - Buffer_Handle hDispBuf = NULL;
240 - Buffer_Handle inBuf = NULL;
241 - GstTIDmaiVideoSink *sink = GST_TIDMAIVIDEOSINK(bsink);
242 + Buffer_Handle hDispBuf = NULL;
243 + Buffer_Handle inBuf = NULL;
244 + gboolean inBufIsOurs = FALSE;
245 + GstTIDmaiVideoSink *sink = GST_TIDMAIVIDEOSINK(bsink);
246 BufferGfx_Dimensions dim;
247 gchar dur_str[64];
248 gchar ts_str[64];
249 @@ -1470,7 +1616,10 @@ static GstFlowReturn gst_tidmaivideosink_render(GstBaseSink * bsink,
250 * generated via videotestsrc plugin.
251 */
252 if (GST_IS_TIDMAIBUFFERTRANSPORT(buf)) {
253 - inBuf = GST_TIDMAIBUFFERTRANSPORT_DMAIBUF(buf);
254 + inBuf = GST_TIDMAIBUFFERTRANSPORT_DMAIBUF(buf);
255 + inBufIsOurs = (sink->hDispBufTab &&
256 + GST_TIDMAIBUFTAB_BUFTAB(sink->hDispBufTab) ==
257 + Buffer_getBufTab(inBuf));
258 } else {
259 /* allocate DMAI buffer */
260 if (sink->tempDmaiBuf == NULL) {
261 @@ -1532,11 +1681,33 @@ static GstFlowReturn gst_tidmaivideosink_render(GstBaseSink * bsink,
262 */
263 for (i = 0; i < sink->framerepeat; i++) {
265 - /* Get a buffer from the display driver */
266 - if (Display_get(sink->hDisplay, &hDispBuf) < 0) {
267 - GST_ELEMENT_ERROR(sink, RESOURCE, FAILED,
268 - ("Failed to get display buffer\n"), (NULL));
269 - goto cleanup;
270 + /* If the input buffer originated from this element via pad allocation,
271 + * simply give it back to the display and continue.
272 + */
273 + if (inBufIsOurs) {
274 +
275 + /* Mark buffer as in-use by the display so it can't be re-used
276 + * until it comes back from Display_get */
277 + Buffer_setUseMask(inBuf, Buffer_getUseMask(inBuf) |
278 + gst_tidmaibuffer_DISPLAY_FREE);
279 +
280 + if (Display_put(sink->hDisplay, inBuf) < 0) {
281 + GST_ELEMENT_ERROR(sink, RESOURCE, FAILED,
282 + ("Failed to put display buffer\n"), (NULL));
283 + goto cleanup;
284 + }
285 + continue;
286 + }
287 +
288 + /* Otherwise, our input buffer originated from up-stream. Retrieve a
289 + * display buffer to copy the contents into.
290 + */
291 + else {
292 + if (Display_get(sink->hDisplay, &hDispBuf) < 0) {
293 + GST_ELEMENT_ERROR(sink, RESOURCE, FAILED,
294 + ("Failed to get display buffer\n"), (NULL));
295 + goto cleanup;
296 + }
297 }
299 /* Retrieve the dimensions of the display buffer */
300 @@ -1844,8 +2015,10 @@ static gboolean gst_tidmaivideosink_alloc_display_buffers(
301 gfxAttrs.dim.height, gfxAttrs.dim.lineLength, gfxAttrs.colorSpace);
302 }
304 + gfxAttrs.bAttrs.useMask = gst_tidmaibuffer_VIDEOSINK_FREE;
305 sink->hDispBufTab = gst_tidmaibuftab_new(sink->dAttrs.numBufs, bufSize,
306 BufferGfx_getBufferAttrs(&gfxAttrs));
307 + gst_tidmaibuftab_set_blocking(sink->hDispBufTab, FALSE);
309 return TRUE;
310 }
311 --
312 1.7.0.4