Fixed compile errors caused by combining plugins
[gst-davinci.git] / ti_plugins / davinci / src / gstfbvideosink.c
blob3f9b9fcfabf1907a19b4927997701bf92e62638a
1 /*
2 * Plugin Name : fbvideosink
3 * Description : A fbdev Video Sink Plugin for TI Davinci DM644x
5 * test pipelines:
6 * gst-launch-0.10 videotestsrc ! video/x-raw-rgb ! fbvideosink device=/dev/fb0
7 * gst-launch-0.10 videotestsrc ! ffmpegcolorspace ! video/x-raw-rgb ! fbvideosink
8 * device=/dev/fb0
9 * gst-launch-0.10 videotestsrc ! video/x-raw-yuv ! fbvideosink device=/dev/fb3
10 * gst-launch-0.10 videotestsrc ! video/x-raw-yuv,format=\(fourcc\)UYVY ! fbvideosink
11 * device=/dev/fb3
12 * :: following YUV formats are supported by fbvideosink
13 * : UYVY
14 * : YUY2
15 * : YVYU
16 * :: ffmpegcolorspace supports only YUY2
17 * videotestsrc supports all of the above
19 * Copyright (C) 2007 Texas Instruments, Inc.
21 * This program is free software; you can redistribute it and/or modify it
22 * under the terms of the GNU Lesser General Public License as published
23 * by the Free Software Foundation version 2.1 of the License.
25 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
26 * whether express or implied; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include "gstfbvideosink.h"
37 #include <stdlib.h>
40 //temporary define's
41 #define ENDIANNESS G_LITTLE_ENDIAN
42 #define DEPTH 16
43 #define REDMASK 63488
44 #define GREENMASK 2016
45 #define BLUEMASK 31
48 /* test variables */
49 int count = 0;
51 #ifdef SLOW_MEMCOPY
52 int to_be_displayed = 0;
53 #endif /* SLOW_MEMCOPY */
55 #include <gst/gstinfo.h>
57 GST_DEBUG_CATEGORY_STATIC(gst_debug_fbvideosink);
58 #define GST_CAT_DEFAULT gst_debug_fbvideosink
60 /* fbimage buffers */
61 #define GST_TYPE_FBIMAGE_BUFFER (gst_fbimage_buffer_get_type())
62 #define GST_IS_FBIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_FBIMAGE_BUFFER))
63 #define GST_FBIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_FBIMAGE_BUFFER, GstFbImageBuffer))
65 static GstElementDetails gst_fbvideosink_details = {
66 "FBDEV Video Sink",
67 "Sink/Video",
68 "A fbdev based Video Sink",
69 "Rishi Bhattacharya <rishi@gstreamer.net>"
72 static GstStaticPadTemplate gst_fbvideosink_sink_template_factory =
73 GST_STATIC_PAD_TEMPLATE("sink",
74 GST_PAD_SINK,
75 GST_PAD_ALWAYS,
76 GST_STATIC_CAPS("video/x-raw-yuv, "
77 "framerate = (fraction) [ 0, MAX ], "
78 "width = (int) [ 1, MAX ], "
79 "height = (int) [ 1, MAX ];"
80 "video/x-raw-rgb, "
81 "framerate = (fraction) [ 0, MAX ], "
82 "width = (int) [ 1, MAX ], "
83 "height = (int) [ 1, MAX ]")
85 enum {
86 PROP_0,
87 PROP_DEVICE
90 static gint gst_fbvideosink_get_format_from_caps(GstFbVideoSink *
91 fbvideosink,
92 GstCaps * caps);
93 static GstVideoSinkClass *parent_class = NULL;
94 static guint counter;
96 GType gst_fbimage_buffer_get_type(void);
97 static GstFbImageBuffer *gst_fbvideosink_fbimage_new(GstFbVideoSink *
98 fbvideosink,
99 GstCaps * caps);
100 static void gst_fbimage_buffer_free(GstFbImageBuffer * fbimage);
101 static void gst_fbimage_buffer_finalize(GstFbImageBuffer * fbimage);
103 /* This function puts a GstFbImage on a FrameBuffer Display */
104 static void gst_fbvideosink_fbimage_put(GstFbVideoSink * fbvideosink,
105 GstFbImageBuffer * fbimage)
107 guint offset;
108 GstFbContext *fbcontext;
109 g_return_if_fail(GST_IS_FBVIDEOSINK(fbvideosink));
110 g_return_if_fail(fbvideosink->fbcontext != NULL);
112 fbcontext = fbvideosink->fbcontext;
113 g_mutex_lock(fbvideosink->fb_lock);
114 guint dummy;
116 #ifdef DEBUG_OUT
117 printf("fbvideosink: gst_fbvideosink_fbimage_put BEGIN...\n");
118 #endif
120 // fbcontext->vScreenInfo.yoffset = fbcontext->vScreenInfo.yres * fbcontext->bufferIndex;
121 for (offset = 0; offset < fbcontext->noofbuffers; offset++) {
122 if (fbcontext->buffers[offset] == GST_BUFFER_DATA(fbimage))
123 break;
126 if (offset >= fbcontext->noofbuffers) {
127 GST_DEBUG("PAN FAILED...offset not recognized...");
128 printf("fbvideosink_put: PAN FAILED...offset not recognized...%d..\n",offset);
129 g_mutex_unlock(fbvideosink->fb_lock);
130 return;
133 // offset = GST_BUFFER_OFFSET(fbimage);// + 1;
134 GST_DEBUG("Frame Buffer Offset: %d\n", offset);
135 GST_DEBUG("The Data Pointer of the current Frame: 0x%x\n",
136 GST_BUFFER_DATA(fbimage));
138 #ifdef DEBUG_OUT
139 printf("Frame Buffer Offset: %d\n", offset);
140 printf("The Data Pointer of the current Frame: 0x%x\n",
141 GST_BUFFER_DATA(fbimage));
142 #endif
144 fbcontext->vScreenInfo.xoffset = 0;
145 fbcontext->vScreenInfo.yoffset = D1_MAX_HEIGHT * offset;
147 #ifdef DEBUG_OUT
148 printf(" The offset value is %d\n",offset);
149 printf(" The Line length value is %d\n",fbcontext->fScreenInfo.line_length);
150 printf(" The yres value is %d\n",fbcontext->vScreenInfo.yres);
151 #endif
153 //fbcontext->vScreenInfo.yoffset = fbcontext->vScreenInfo.yres * offset; // Changed by PB
154 //data = fbcontext->data + ( fbcontext->vScreenInfo.yoffset * (fbcontext->fScreenInfo.line_length));
156 //do the memcpy into the buffer at the location pointed by data
157 GST_DEBUG_OBJECT(fbvideosink, "PANNING THE DISPLAY...");
159 //memcpy(data , GST_BUFFER_DATA(fbimage), GST_BUFFER_SIZE(fbimage));
160 //PAN the display
161 if (ioctl
162 (fbcontext->fbdevFd, FBIOPAN_DISPLAY,
163 &(fbcontext->vScreenInfo)) == -1) {
164 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
165 ("PAN DISPLAY Failed"));
167 g_mutex_unlock(fbvideosink->fb_lock);
168 return;
171 //Wait for VSYNC signal from fb device before continuing
172 if (ioctl(fbcontext->fbdevFd, FBIO_WAITFORVSYNC, 0) == -1) {
173 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
174 ("Wait for VSYNC Failed"));
175 g_mutex_unlock(fbvideosink->fb_lock);
176 return;
179 (fbvideosink->framesDisplayed)++;
181 #ifdef DEBUG_OUT
182 printf(" Frames Displayed is # %d\n",fbvideosink->framesDisplayed);
183 #endif
185 //gst_buffer_unref(fbimage);
186 //gst_fbimage_buffer_finalize (fbimage);
187 fbcontext->avail[offset] = TRUE;
188 g_mutex_unlock(fbvideosink->fb_lock);
189 //fbcontext->bufferIndex = (++(fbcontext->bufferIndex)) % fbcontext->noofbuffers;
192 #ifdef DEBUG_OUT
193 printf("fbvideosink: gst_fbvideosink_fbimage_put END..\n");
194 #endif
197 static GstFlowReturn gst_fbvideosink_show_frame(GstBaseSink * bsink,
198 GstBuffer * buf)
200 GstFbVideoSink *fbvideosink;
201 guint i;
202 GstFbImageBuffer *temp,**start_fbimage;
203 GstBuffer **start_buf;
206 #ifdef DEBUG_OUT
207 printf("fbvideosink: gst_fbvideosink_show_frame BEGIN..\n");
208 #endif
210 fbvideosink = GST_FBVIDEOSINK(bsink);
211 /* If this buffer has been allocated using our buffer management we simply
212 put the fbimage which is in the PRIVATE pointer */
214 if (GST_IS_FBIMAGE_BUFFER(buf))
216 GST_DEBUG("fast put of bufferpool buffer");
217 #ifdef DEBUG_OUT
218 printf ("fbvideosink: gst_fbvideosink_show_frame: fast put of bufferpool buffer %p\n", buf);
219 #endif
220 gst_fbvideosink_fbimage_put(fbvideosink, GST_FBIMAGE_BUFFER(buf));
222 else
225 #ifdef SLOW_MEMCOPY
227 GST_DEBUG("slow copy into bufferpool buffer");
228 /* Else we have to copy the data into our private image, */
229 /* if we have one... */
230 if (!fbvideosink->fbimage) {
231 GST_DEBUG_OBJECT(fbvideosink, "creating our fbimage");
233 fbvideosink->fbimage = gst_fbvideosink_fbimage_new(fbvideosink,
234 GST_BUFFER_CAPS(buf));
235 if (!fbvideosink->fbimage)
236 goto no_image;
238 GST_DEBUG("Coping data from received buffer to fbvideosinks internal buffer");
240 temp = fbvideosink->fbimage;
241 start_fbimage = &(fbvideosink->fbimage);
242 start_buf = &buf;
244 #ifdef DEBUG_OUT
245 printf("fbvideosink: show_frame Width is %d... Height is %d\n",temp->width,temp->height);
246 #endif
248 GST_BUFFER_TIMESTAMP(temp) = GST_BUFFER_TIMESTAMP(buf);
250 GST_BUFFER_OFFSET(temp) = 0;
251 GST_BUFFER_OFFSET(buf) = 0;
252 for (i=0; i < temp->height; i++){
253 // printf("SHOW FRAME:GST_BUFFER_TIMESTAMP:%llu\n",GST_BUFFER_TIMESTAMP(buf));
254 // memcpy(GST_BUFFER_DATA(temp), GST_BUFFER_DATA(buf),MIN(GST_BUFFER_SIZE(buf), fbvideosink->fbimage->size));
255 #ifdef DEBUG_OUT
256 printf("Copying from %x location to %x location ...%d bytes\n",GST_BUFFER_DATA(buf),GST_BUFFER_DATA(temp),temp->height*2);
257 #endif
258 memcpy(GST_BUFFER_DATA(temp), GST_BUFFER_DATA(buf),temp->width*2);
259 GST_BUFFER_DATA(temp) += fbvideosink->fbcontext->fScreenInfo.line_length;
260 GST_BUFFER_DATA(buf) += temp->width*2;
264 // GST_BUFFER_TIMESTAMP(temp) = GST_BUFFER_TIMESTAMP(buf);
265 // GST_BUFFER_TIMESTAMP(*start_fbimage) = GST_BUFFER_TIMESTAMP(*start_buf);
267 GST_BUFFER_DATA(temp) = GST_BUFFER_DATA(temp) - (fbvideosink->fbcontext->fScreenInfo.line_length * temp->height );
268 GST_BUFFER_DATA(buf) = GST_BUFFER_DATA(buf) - (temp->height * temp->width *2);
270 #ifdef DEBUG_OUT
271 printf("Origin start %x location - Destination start %x location bytes - Size to free %x bytes \n",GST_BUFFER_DATA(*start_buf),GST_BUFFER_DATA(*start_fbimage), GST_BUFFER_SIZE(*start_buf));
272 #endif
274 // if (Memory_contigFree((XDAS_Int8 *)GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)) == FALSE)
275 if (Memory_contigFree((XDAS_Int8 *)GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)) == FALSE)
276 printf("ContigFree failed\n");
277 else{
278 count--;
279 to_be_displayed--;
280 #ifdef DEBUG_OUT
281 printf("ContigFree done. Count : %d\n", count);
282 #endif
285 #endif /* SLOW_MEMCOPY */
287 gst_fbvideosink_fbimage_put(fbvideosink, fbvideosink->fbimage);
290 #ifdef DEBUG_OUT
291 printf("fbvideosink: gst_fbvideosink_show_frame END..\n");
292 #endif
293 return GST_FLOW_OK;
295 #ifdef SLOW_MEMCOPY
296 /* ERRORS */
297 no_image:
299 /* No image available. That's very bad ! */
300 GST_DEBUG("could not create image");
301 GST_ELEMENT_ERROR(fbvideosink, CORE, NEGOTIATION, (NULL),
302 ("Failed creating an FbImage in fbvideosink chain function.")
304 #ifdef DEBUG_OUT
305 printf("fbvideosink: gst_fbvideosink_show_frame NO IMAGE ERROR END..\n");
306 #endif
308 return GST_FLOW_ERROR;
310 #endif /* SLOW_MEMCOPY */
315 /* This function handles GstFbImage creation*/
316 static GstFbImageBuffer *gst_fbvideosink_fbimage_new(GstFbVideoSink *
317 fbvideosink,
318 GstCaps * caps)
320 GstFbImageBuffer *fbimage = NULL;
321 GstStructure *structure = NULL;
322 GstFbContext *fbcontext;
323 guint i;
324 gboolean succeeded = FALSE;
326 #ifdef DEBUG_OUT
327 printf("fbvideosink: gst_fbvideosink_fbimage_new BEGIN..\n");
328 #endif
330 g_return_val_if_fail(GST_IS_FBVIDEOSINK(fbvideosink), NULL);
332 fbcontext = fbvideosink->fbcontext;
333 fbimage=(GstFbImageBuffer *) gst_mini_object_new(GST_TYPE_FBIMAGE_BUFFER);
335 structure = gst_caps_get_structure(caps, 0);
337 if (!gst_structure_get_int(structure, "width", &fbimage->width) ||
338 !gst_structure_get_int(structure, "height", &fbimage->height)) {
339 GST_WARNING("failed getting geometry from caps %"
340 GST_PTR_FORMAT, caps);
343 GST_LOG_OBJECT(fbvideosink, "creating %dx%d", fbimage->width,
344 fbimage->height);
345 #ifdef DEBUG_OUT
346 printf("creating %dx%d\n", fbimage->width, fbimage->height);
347 #endif
349 /*Added by Pratheesh */
350 if (!fbcontext->doneonce) {
351 fbcontext->doneonce = TRUE;
352 // if (fbimage->height > MAX_FRAME_HEIGHT)
353 // fbcontext->vScreenInfo.yres = MAX_FRAME_HEIGHT;
355 // Get variable screen information
356 if (ioctl
357 (fbcontext->fbdevFd, FBIOGET_VSCREENINFO,
358 &(fbcontext->vScreenInfo)) == -1) {
359 g_free(fbcontext);
360 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
361 ("Could not get variable screen info"));
362 #ifdef DEBUG_OUT
363 printf("fbvideosink: ERROR in fbimage_new - could not get variable screen info\n");
364 #endif
366 return FALSE;
369 // Get fixed screen information
370 if (ioctl
371 (fbcontext->fbdevFd, FBIOGET_FSCREENINFO,
372 &(fbcontext->fScreenInfo)) == -1) {
373 g_free(fbcontext);
374 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
375 ("Could not get fixed screen info"));
376 #ifdef DEBUG_OUT
377 printf("fbvideosink: ERROR in fbimage_new - could not get fixed screen info\n");
378 #endif
379 return FALSE;
382 if (fbimage->height > D1_MAX_HEIGHT)
383 fbcontext->vScreenInfo.yres = D1_MAX_HEIGHT;
384 else
385 fbcontext->vScreenInfo.yres = fbimage->height;
387 fbcontext->vScreenInfo.xres = fbimage->width;
388 // fbcontext->vScreenInfo.yres_virtual =
389 // D1_HEIGHT_PAL * fbcontext->noofbuffers;
390 fbcontext->vScreenInfo.yres_virtual = D1_MAX_HEIGHT * fbcontext->noofbuffers;
391 fbcontext->vScreenInfo.xres_virtual = fbimage->width;
392 //new code for buffer management
394 fbcontext->screensize = fbcontext->fScreenInfo.line_length * fbcontext->vScreenInfo.yres;//Added by PB
396 for (i = 0; i < fbcontext->noofbuffers; i++) {
397 fbcontext->avail[i] = TRUE;
398 fbcontext->buffers[i] =
399 // fbcontext->data + (i * D1_MAX_HEIGHT * fbimage->width * 2);
400 fbcontext->data + (i * fbcontext->screensize);
401 GST_DEBUG("Mapped Frame Buffer Data Pointer: %p, Offset: %d\n",
402 fbcontext->buffers[i], i);
403 #ifdef DEBUG_OUT
404 printf("Buffer Pointer %d....%x\n",i,fbcontext->buffers[i]);
405 #endif
408 #ifdef DEBUG_OUT
409 printf("Variable Screen Info is %d\n",fbcontext->vScreenInfo.yres);
410 printf("Fixed Screen Info Line Length is %d\n",fbcontext->fScreenInfo.line_length);
411 #endif
413 //end
414 // Put variable screen information
415 if (ioctl
416 (fbcontext->fbdevFd, FBIOPUT_VSCREENINFO,
417 &(fbcontext->vScreenInfo)) == -1) {
418 g_free(fbcontext);
419 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
420 ("Could not put variable screen info"));
421 #ifdef DEBUG_OUT
422 printf("fbvideosink: ERROR in fbimage_new - could not put variable screen info\n");
423 #endif
424 return FALSE;
427 // Set Y coordinate
429 int ypos = (D1_MAX_HEIGHT - fbcontext->vScreenInfo.yres) >> 2;
430 if (ioctl(fbcontext->fbdevFd, FBIO_SETPOSY, ypos) == -1) {
431 g_free(fbcontext);
432 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
433 ("Could not set SET POSY"));
434 return FALSE;
437 // Set X coordinate
439 int xpos = (D1_WIDTH - fbcontext->vScreenInfo.xres) >> 1;
440 if (ioctl(fbcontext->fbdevFd, FBIO_SETPOSX, xpos) == -1) {
441 g_free(fbcontext);
442 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
443 ("Could not set SET POSX"));
444 return FALSE;
448 // Get variable screen information
449 if (ioctl
450 (fbcontext->fbdevFd, FBIOGET_VSCREENINFO,
451 &(fbcontext->vScreenInfo)) == -1) {
452 g_free(fbcontext);
453 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
454 ("Could not get variable screen info"));
455 #ifdef DEBUG_OUT
456 printf("fbvideosink: ERROR in fbimage_new - could not get variable screen info -- 222\n");
457 #endif
458 return FALSE;
461 fbcontext->depth = fbcontext->vScreenInfo.red.length +
462 fbcontext->vScreenInfo.green.length +
463 fbcontext->vScreenInfo.blue.length;
465 // fbcontext->width = (fbcontext->fScreenInfo.line_length * 8) / fbcontext->bpp;
466 fbcontext->width = fbcontext->vScreenInfo.xres;
467 fbcontext->height = fbcontext->vScreenInfo.yres;
468 fbcontext->widthmm = fbcontext->vScreenInfo.width;
469 fbcontext->heightmm = fbcontext->vScreenInfo.height;
471 GST_DEBUG_OBJECT(fbvideosink,
472 "Frame Buffer reports %dx%d pixels and %d mm x %d mm",
473 fbcontext->width, fbcontext->height,
474 fbcontext->widthmm, fbcontext->heightmm);
475 #ifdef DEBUG_OUT
476 printf("Frame Buffer reports %dx%d pixels and %d mm x %d mm\n",
477 fbcontext->width, fbcontext->height,
478 fbcontext->widthmm, fbcontext->heightmm);
479 #endif
484 /*Added by Pratheesh */
485 fbimage->im_format =
486 gst_fbvideosink_get_format_from_caps(fbvideosink, caps);
488 if (!fbimage->im_format) {
489 GST_WARNING_OBJECT(fbvideosink,
490 "failed to get format from caps %"
491 GST_PTR_FORMAT, caps);
492 printf ( "failed to get format from caps\n");
493 goto beach_unlocked;
496 fbimage->fbvideosink = gst_object_ref(fbvideosink);
497 fbimage->size = fbcontext->screensize;
499 #ifdef DEBUG_OUT
500 printf("fbImage Size is %d\n",fbcontext->screensize);
501 #endif
503 /* old code
504 GST_BUFFER_MALLOCDATA (fbimage) = g_malloc (fbimage->size);
505 GST_BUFFER_DATA (fbimage) = GST_BUFFER_MALLOCDATA (fbimage);
506 GST_BUFFER_SIZE (fbimage) = fbimage->size;
508 succeeded = TRUE;
511 //replaced with
512 //new code buffer management
514 if (counter == fbcontext->noofbuffers){
515 printf(" no more buffers to allocate, counter = %d = num of buffers",counter);
516 return NULL;
520 for (i = 0; i < fbcontext->noofbuffers; i++) {
521 if (fbcontext->avail[i] == TRUE) {
522 GST_BUFFER_DATA(fbimage) = fbcontext->buffers[i];
523 GST_BUFFER_SIZE(fbimage) = fbimage->size;
524 GST_BUFFER_OFFSET(fbimage) = i;
525 fbcontext->avail[i] = FALSE;
527 succeeded = TRUE;
528 GST_DEBUG
529 ("FBVIDEOSINK: Returning Buffer with Data Pointer : %p , and Offset: %d\n",
530 GST_BUFFER_DATA(fbimage), i);
531 #ifdef DEBUG_OUT
532 printf("fbvideosink: fbimage new,ptr:%p offset:%d\n",GST_BUFFER_DATA(fbimage),i);
533 #endif
534 break;
539 //end of new code
541 else
543 GST_BUFFER_DATA(fbimage) = fbcontext->buffers[counter];
544 GST_BUFFER_SIZE(fbimage) = fbimage->size;
545 GST_BUFFER_OFFSET(fbimage) = counter;
546 succeeded = TRUE;
547 #ifdef DEBUG_OUT
548 printf("fbimage new,ptr:%p offset:%d\n",GST_BUFFER_DATA(fbimage),counter);
549 #endif
550 counter++;
554 beach_unlocked:
555 if (!succeeded) {
556 #ifdef DEBUG_OUT
557 printf("fbvideosink: ERROR in fbimage_new -- Beach Unlocked\n");
558 #endif
559 gst_fbimage_buffer_free(fbimage);
560 fbimage = NULL;
563 #ifdef DEBUG_OUT
564 printf("fbvideosink: gst_fbvideosink_fbimage_new END..\n");
565 #endif
566 return fbimage;
572 static void gst_fbvideosink_finalize(GObject * object)
574 GstFbVideoSink *fbvideosink;
576 #ifdef DEBUG_OUT
577 printf("fbvideosink: gst_fbvideosink_finalize BEGIN..\n");
578 #endif
580 fbvideosink = GST_FBVIDEOSINK(object);
582 if (fbvideosink->par) {
583 g_free(fbvideosink->par);
584 fbvideosink->par = NULL;
586 G_OBJECT_CLASS(parent_class)->finalize(object);
588 #ifdef DEBUG_OUT
589 printf("fbvideosink: gst_fbvideosink_finalize END..\n");
590 #endif
594 static GstFlowReturn gst_fbvideosink_buffer_alloc(GstBaseSink * bsink,
595 guint64 offset,
596 guint size,
597 GstCaps * caps,
598 GstBuffer ** buf)
600 GstFbVideoSink *fbvideosink = GST_FBVIDEOSINK(bsink);
603 #ifdef DEBUG_OUT
604 printf("fbvideosink: gst_fbvideosink_buffer_alloc BEGIN..\n");
605 #endif
606 *buf = gst_buffer_new();
607 GST_BUFFER_DATA(*buf) = (XDAS_Int8 *) Memory_contigAlloc(size,Memory_DEFAULTALIGNMENT);
609 if(GST_BUFFER_DATA(*buf) == NULL)
611 printf("FBVIDEOSINK:CMEM couldn't allocate buffers\n");
612 return GST_FLOW_ERROR;
615 #ifdef DEBUG_OUT
616 printf("fbvideosink: gst_fbvideosink_buffer_alloc Allocated buffer of size %d bytes at %p location..\n",size,GST_BUFFER_DATA(*buf));
617 #endif
619 #ifdef DEALLOC
621 g_mutex_lock(fbvideosink->pool_lock);
622 struct cmem_buffers_node *node = (struct cmem_buffers_node *)malloc(sizeof(struct cmem_buffers_node));
623 node->ptr = GST_BUFFER_DATA(*buf);
624 node->size = size;
625 fbvideosink->cmem_buffers_list = g_slist_append(fbvideosink->cmem_buffers_list, node);
626 g_mutex_unlock(fbvideosink->pool_lock);
628 #endif /* DEALLOC */
630 count++;
631 GST_BUFFER_SIZE(*buf) = size;
632 gst_buffer_set_caps(GST_BUFFER(*buf), caps);
634 #ifdef DEBUG_OUT
635 printf("fbvideosink: gst_fbvideosink_buffer_alloc END..\n");
636 #endif
638 return GST_FLOW_OK;
641 /* This function destroys a GstFbImage*/
642 static void gst_fbimage_buffer_destroy(GstFbImageBuffer * fbimage)
644 GstFbVideoSink *fbvideosink;
646 #ifdef DEBUG_OUT
647 printf("fbvideosink: gst_fbvideosink_buffer_destroy BEGIN..\n");
648 #endif
650 fbvideosink = fbimage->fbvideosink;
651 if (fbvideosink == NULL)
652 goto no_sink;
654 g_return_if_fail(GST_IS_FBVIDEOSINK(fbvideosink));
656 /* If the destroyed image is the current one we destroy our reference too */
657 if (fbvideosink->cur_image == fbimage)
658 fbvideosink->cur_image = NULL;
660 if (GST_BUFFER_DATA(fbimage)) {
661 guint offset = GST_BUFFER_OFFSET(fbimage);
663 fbvideosink->fbcontext->avail[offset] = TRUE;
664 // g_free ((guint8 *)GST_BUFFER_DATA(fbimage));
665 (GST_BUFFER_DATA(fbimage)) = NULL;
666 (GST_BUFFER_SIZE(fbimage)) = 0;
669 fbimage->fbvideosink = NULL;
670 gst_object_unref(fbvideosink);
672 #ifdef DEBUG_OUT
673 printf("fbvideosink: gst_fbvideosink_buffer_destroy END..\n");
674 #endif
676 return;
678 no_sink:
680 GST_WARNING("no sink found");
681 return;
685 static void gst_fbimage_buffer_finalize(GstFbImageBuffer * fbimage)
687 GstFbVideoSink *fbvideosink;
689 #ifdef DEBUG_OUT
690 printf("fbvideosink: gst_fbvideosink_buffer_finalize BEGIN..\n");
691 #endif
693 fbvideosink = fbimage->fbvideosink;
694 //GstFbContext *fbcontext = fbvideosink->fbcontext;
695 if (fbvideosink == NULL)
696 goto no_sink;
698 /* If our geometry changed we can't reuse that image. */
699 if ((fbimage->width != fbvideosink->video_width) ||
700 (fbimage->height != fbvideosink->video_height)) {
701 GST_DEBUG
702 ("destroy image as its size changed %dx%d vs current %dx%d",
703 fbimage->width, fbimage->height, fbvideosink->video_width,
704 fbvideosink->video_height);
705 /*printf
706 ("destroy image as its size changed %dx%d vs current %dx%d\n",
707 fbimage->width, fbimage->height, fbvideosink->video_width,
708 fbvideosink->video_height); */
709 gst_fbimage_buffer_destroy(fbimage);
710 } else {
711 /* In that case we can reuse the image and add it to our image pool. */
712 GST_DEBUG("recycling image in pool");
713 #ifdef DEBUG_OUT
714 printf("recycling image in pool:%x pts:%llu\n",
715 GST_BUFFER_DATA(fbimage),GST_BUFFER_TIMESTAMP(fbimage));
716 #endif
717 /* need to increment the refcount again to recycle */
718 gst_buffer_ref(GST_BUFFER(fbimage));
719 //fbcontext->avail[GST_BUFFER_OFFSET(fbimage)] = TRUE;
722 #ifdef DEBUG_OUT
723 printf("fbvideosink: gst_fbvideosink_buffer_finalize END..\n");
724 #endif
726 return;
728 no_sink:
730 GST_WARNING("no sink found");
731 return;
735 static void gst_fbimage_buffer_init(GstFbImageBuffer * fbimage,
736 gpointer g_class)
739 #ifdef DEBUG_OUT
740 printf("fbvideosink: gst_fbvideosink_buffer_init BEGIN..\n");
741 #endif
743 #ifdef DEBUG_OUT
744 printf("fbvideosink: gst_fbvideosink_buffer_init END..\n");
745 #endif
747 return;
750 static void gst_fbimage_buffer_class_init(gpointer g_class,
751 gpointer class_data)
753 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
755 #ifdef DEBUG_OUT
756 printf("fbvideosink: gst_fbvideosink_class_init BEGIN..\n");
757 #endif
759 mini_object_class->finalize =
760 (GstMiniObjectFinalizeFunction) gst_fbimage_buffer_finalize;
762 #ifdef DEBUG_OUT
763 printf("fbvideosink: gst_fbvideosink_class_init END..\n");
764 #endif
768 GType gst_fbimage_buffer_get_type(void)
770 static GType _gst_fbimage_buffer_type;
772 #ifdef DEBUG_OUT
773 printf("fbvideosink: gst_fbimage_buffer_get_type BEGIN..\n");
774 #endif
776 if (G_UNLIKELY(_gst_fbimage_buffer_type == 0)) {
777 static const GTypeInfo fbimage_buffer_info = {
778 sizeof(GstBufferClass),
779 NULL,
780 NULL,
781 gst_fbimage_buffer_class_init,
782 NULL,
783 NULL,
784 sizeof(GstFbImageBuffer),
786 (GInstanceInitFunc) gst_fbimage_buffer_init,
787 NULL
789 _gst_fbimage_buffer_type =
790 g_type_register_static(GST_TYPE_BUFFER, "GstFbImageBuffer",
791 &fbimage_buffer_info, 0);
794 #ifdef DEBUG_OUT
795 printf("fbvideosink: gst_fbimage_buffer_get_type END..\n");
796 #endif
798 return _gst_fbimage_buffer_type;
801 /* This function tries to get a format matching with a given caps in the
802 supported list of formats we generated in gst_fbvideosink_get_fb_support */
803 static gint gst_fbvideosink_get_format_from_caps(GstFbVideoSink *
804 fbvideosink,
805 GstCaps * caps)
807 GList *list = NULL;
809 #ifdef DEBUG_OUT
810 printf("fbvideosink: gst_fbvideosink_get_format_from_caps BEGIN..\n");
811 #endif
813 g_return_val_if_fail(GST_IS_FBVIDEOSINK(fbvideosink), 0);
815 list = fbvideosink->fbcontext->formats_list;
817 while (list) {
818 GstFbImageFormat *format = list->data;
820 if (format) {
821 GstCaps *icaps = NULL;
823 icaps = gst_caps_intersect(caps, format->caps);
824 if (!gst_caps_is_empty(icaps)) {
825 gst_caps_unref(icaps);
826 #ifdef DEBUG_OUT
827 printf("fbvideosink: gst_fbvideosink_get_format_from_caps END..\n");
828 #endif
829 return format->format;
832 list = g_list_next(list);
835 #ifdef DEBUG_OUT
836 printf("fbvideosink: gst_fbvideosink_get_format_from_caps - Return 0 END..\n");
837 #endif
839 return 0;
842 /* This function cleans the Fb context. Closing the Frame Buffer,
843 and unrefing the caps for supported formats. */
844 static void gst_fbvideosink_fbcontext_clear(GstFbVideoSink * fbvideosink)
846 GList *formats_list;
848 #ifdef DEBUG_OUT
849 printf("fbvideosink: gst_fbvideosink_fbcontext_clear BEGIN..\n");
850 #endif
852 g_return_if_fail(GST_IS_FBVIDEOSINK(fbvideosink));
853 g_return_if_fail(fbvideosink->fbcontext != NULL);
855 formats_list = fbvideosink->fbcontext->formats_list;
857 while (formats_list) {
858 GstFbImageFormat *format = formats_list->data;
860 gst_caps_unref(format->caps);
861 g_free(format);
862 formats_list = g_list_next(formats_list);
865 if (fbvideosink->fbcontext->formats_list)
866 g_list_free(fbvideosink->fbcontext->formats_list);
868 gst_caps_unref(fbvideosink->fbcontext->caps);
869 g_free(fbvideosink->fbcontext->par);
871 //fbcontext->data will be pointing to the first byte of the frame buffer
872 munmap(fbvideosink->fbcontext->data,
873 (fbvideosink->fbcontext->screensize) *
874 fbvideosink->fbcontext->noofbuffers);
875 fbvideosink->fbcontext->data = NULL;
876 close(fbvideosink->fbcontext->fbdevFd);
877 g_free(fbvideosink->fbcontext);
878 fbvideosink->fbcontext = NULL;
881 #ifdef DEBUG_OUT
882 printf("fbvideosink: gst_fbvideosink_fbcontext_clear END..\n");
883 #endif
887 static void gst_fbvideosink_cmembuffers_clear(GstFbVideoSink * fbvideosink)
890 #ifdef DEBUG_OUT
891 printf("fbvideosink: gst_fbvideosink_cmembuffers_clear BEGIN..\n");
892 #endif
894 #ifdef DEALLOC
895 g_mutex_lock(fbvideosink->pool_lock);
897 struct cmem_buffers_node *node;
899 //printf("Clearing cmem buffers\n");
901 while (fbvideosink->cmem_buffers_list)
903 node = fbvideosink->cmem_buffers_list->data;
905 if (Memory_contigFree(node->ptr,node->size) == FALSE)
907 printf("ContigFree failed\n");
909 else
911 //printf("Freed buffer:%p of size:%d\n",node->ptr,node->size);
913 /* fbvideosink->cmem_buffers_list = g_slist_delete_link(fbvideosink->cmem_buffers_list,fbvideosink->cmem_buffers_list); */
914 fbvideosink->cmem_buffers_list = g_slist_remove(fbvideosink->cmem_buffers_list, node);
916 free(node);
919 g_mutex_unlock(fbvideosink->pool_lock);
920 #endif /* DEALLOC */
923 #ifdef DEBUG_OUT
924 printf("fbvideosink: gst_fbvideosink_cmembuffers_clear END..\n");
925 #endif
929 static void gst_fbimage_buffer_free(GstFbImageBuffer * fbimage)
932 #ifdef DEBUG_OUT
933 printf("fbvideosink: gst_fbimage_buffer_free BEGIN..\n");
934 #endif
936 /* make sure it is not recycled */
937 printf ("Inside buffer free\n");
938 fbimage->width = -1;
939 fbimage->height = -1;
940 gst_buffer_unref(GST_BUFFER(fbimage));
942 #ifdef DEBUG_OUT
943 printf("fbvideosink: gst_fbimage_buffer_free END..\n");
944 #endif
948 /* This function calculates the pixel aspect ratio based on the properties
949 * in the fbcontext structure and stores it there. */
950 static void gst_fbvideosink_calculate_pixel_aspect_ratio(GstFbContext *
951 fbcontext)
953 gint par[][2] = {
954 {1, 1}, /* regular screen */
955 {16, 15}, /* PAL TV */
956 {11, 10}, /* 525 line Rec.601 video */
957 {54, 59} /* 625 line Rec.601 video */
959 gint i;
960 gint index;
961 gdouble ratio;
962 gdouble delta;
964 #ifdef DEBUG_OUT
965 printf("fbvideosink: gst_fbvideosink_calculate_pixel_aspect_ratio BEGIN..\n");
966 #endif
968 #define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
970 /* first calculate the "real" ratio based on the FbContext values;
971 * which is the "physical" w/h divided by the w/h in pixels of the display */
972 ratio =
973 (gdouble) (fbcontext->widthmm * fbcontext->height) /
974 (fbcontext->heightmm * fbcontext->width);
976 GST_DEBUG("calculated pixel aspect ratio: %f", ratio);
977 /* now find the one from par[][2] with the lowest delta to the real one */
978 delta = DELTA(0);
979 index = 0;
981 for (i = 1; i < sizeof(par) / (sizeof(gint) * 2); ++i) {
982 gdouble this_delta = DELTA(i);
984 if (this_delta < delta) {
985 index = i;
986 delta = this_delta;
990 GST_DEBUG("Decided on index %d (%d/%d)", index, par[index][0],
991 par[index][1]);
993 g_free(fbcontext->par);
994 fbcontext->par = g_new0(GValue, 1);
995 g_value_init(fbcontext->par, GST_TYPE_FRACTION);
996 gst_value_set_fraction(fbcontext->par, par[index][0], par[index][1]);
997 GST_DEBUG("set fbcontext PAR to %d/%d",
998 gst_value_get_fraction_numerator(fbcontext->par),
999 gst_value_get_fraction_denominator(fbcontext->par)
1002 #ifdef DEBUG_OUT
1003 printf("fbvideosink: gst_fbvideosink_calculate_pixel_aspect_ratio END..\n");
1004 #endif
1008 /* This function gets the fbdev and global info about it. Everything is
1009 stored in our object and will be cleaned when the object is disposed. Note
1010 here that caps for supported format are generated without any window or
1011 image creation */
1012 static GstFbContext *gst_fbvideosink_fbcontext_get(GstFbVideoSink *
1013 fbvideosink)
1015 GstFbContext *fbcontext = NULL;
1016 guint i;
1017 //printf ("Inside fbvideosink_fbcontext_get\n");
1019 #ifdef DEBUG_OUT
1020 printf("fbvideosink: gst_fbvideosink_fbcontext_get BEGIN..\n");
1021 #endif
1023 g_return_val_if_fail(GST_IS_FBVIDEOSINK(fbvideosink), NULL);
1025 /* Allocate 1 element of type GstFbContext and initialize to 0's*/
1026 fbcontext = g_new0(GstFbContext, 1);
1028 fbcontext->im_format = 0;
1029 fbcontext->doneonce = FALSE;
1031 /* Device Driver Open Call for /dev/fb/3 Video Frame Window */
1032 fbcontext->fbdevFd = open(fbvideosink->device, O_RDWR);
1034 if (fbcontext->fbdevFd < 0) {
1035 g_free(fbcontext);
1036 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
1037 ("Could not open device: %s",
1038 fbvideosink->device));
1040 return NULL;
1043 GST_DEBUG_OBJECT(fbvideosink, "Display Device Opened Successfully");
1045 // Get fixed screen information
1046 if (ioctl
1047 (fbcontext->fbdevFd, FBIOGET_FSCREENINFO,
1048 &(fbcontext->fScreenInfo)) == -1) {
1049 g_free(fbcontext);
1050 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
1051 ("Could not get fixed screen info"));
1052 return NULL;
1055 // Get variable screen information
1056 if (ioctl
1057 (fbcontext->fbdevFd, FBIOGET_VSCREENINFO,
1058 &(fbcontext->vScreenInfo)) == -1) {
1059 g_free(fbcontext);
1060 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
1061 ("Could not get variable screen info"));
1062 return NULL;
1066 /* Added by PB*/
1067 fbcontext->vScreenInfo.xres = D1_WIDTH;
1068 fbcontext->vScreenInfo.yres = D1_HEIGHT;
1069 fbcontext->vScreenInfo.bits_per_pixel = SCREEN_BPP;
1071 /* Set video display format */
1072 if (ioctl(fbcontext->fbdevFd, FBIOPUT_VSCREENINFO, &(fbcontext->vScreenInfo)) == -1) {
1073 g_free(fbcontext);
1074 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
1075 ("Could not SET variable screen info"));
1076 return NULL;
1079 if ( fbcontext->vScreenInfo.xres != D1_WIDTH ||
1080 fbcontext->vScreenInfo.yres != D1_HEIGHT ||
1081 fbcontext->vScreenInfo.bits_per_pixel != SCREEN_BPP){
1082 printf("Failed to get the requested screen size: %dx%d at %d bpp\n",D1_WIDTH,D1_HEIGHT,SCREEN_BPP);
1086 /* ---------- */
1089 //find out the buffering that is used (double, triple, quadriple, ...)
1090 fbcontext->noofbuffers = TRIPLE_BUF;
1091 //printf("Number of buffers = %d\n", fbcontext->noofbuffers);
1092 fbcontext->bpp = fbcontext->vScreenInfo.bits_per_pixel;
1093 // Figure out the size of the screen in bytes
1094 // fbcontext->screensize = D1_WIDTH * D1_MAX_HEIGHT * (fbcontext->bpp / 8);
1095 fbcontext->screensize = fbcontext->fScreenInfo.line_length * fbcontext->vScreenInfo.yres;//Added by PB
1097 //printf("Screen size = %d\n", fbcontext->screensize);
1098 // Map the device to memory
1099 // fbcontext->data =
1100 // (guint8 *) mmap(0, fbcontext->screensize * fbcontext->noofbuffers,
1101 // PROT_READ | PROT_WRITE, MAP_SHARED,
1102 // fbcontext->fbdevFd, 0);
1104 fbcontext->data =
1105 (guint8 *) mmap(0, fbcontext->fScreenInfo.line_length * fbcontext->vScreenInfo.yres_virtual,
1106 PROT_READ | PROT_WRITE, MAP_SHARED,
1107 fbcontext->fbdevFd, 0);
1109 #ifdef DEBUG_OUT
1110 printf("I am in get function :....... \n");
1111 printf("Screen Size here is : ....%d\n",fbcontext->screensize);
1112 #endif
1114 // fbcontext->bufferIndex = 1;
1116 // printf("ssize: %d\n",fbcontext->screensize);
1118 if ((int) fbcontext->data == -1) {
1119 g_free(fbcontext);
1120 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
1121 ("failed to map framebuffer device to memory"));
1122 return NULL;
1125 #if 0
1126 //new code for buffer management
1127 for (i = 0; i < fbcontext->noofbuffers; i++) {
1128 fbcontext->avail[i] = TRUE;
1129 fbcontext->buffers[i] =
1130 fbcontext->data + (i * fbcontext->screensize);
1131 GST_DEBUG("Mapped Frame Buffer Data Pointer: %p, Offset: %d\n",
1132 fbcontext->buffers[i], i);
1134 //end
1135 #endif
1137 gst_fbvideosink_calculate_pixel_aspect_ratio(fbcontext);
1138 fbcontext->endianness = ENDIANNESS;
1140 fbcontext->caps = gst_caps_new_full(gst_structure_new
1141 ("video/x-raw-yuv",
1142 "width", GST_TYPE_INT_RANGE,
1143 176, 720,
1144 "height", GST_TYPE_INT_RANGE,
1145 144, 576,
1146 "framerate",
1147 GST_TYPE_FRACTION_RANGE, 0, 1,
1148 G_MAXINT, 1, "format",
1149 GST_TYPE_FOURCC,
1150 GST_MAKE_FOURCC('U', 'Y', 'V',
1151 'Y'), NULL),
1152 gst_structure_new
1153 ("video/x-raw-yuv", "width",
1154 G_TYPE_INT, fbcontext->width,
1155 "height", G_TYPE_INT,
1156 fbcontext->height, "framerate",
1157 GST_TYPE_FRACTION_RANGE, 0, 1,
1158 G_MAXINT, 1, "format",
1159 GST_TYPE_FOURCC,
1160 GST_MAKE_FOURCC('Y', 'U', 'Y',
1161 '2'), NULL),
1162 gst_structure_new
1163 ("video/x-raw-yuv", "width",
1164 G_TYPE_INT, fbcontext->width,
1165 "height", G_TYPE_INT,
1166 fbcontext->height, "framerate",
1167 GST_TYPE_FRACTION_RANGE, 0, 1,
1168 G_MAXINT, 1, "format",
1169 GST_TYPE_FOURCC,
1170 GST_MAKE_FOURCC('Y', 'V', 'Y',
1171 'U'), NULL),
1172 gst_structure_new
1173 ("video/x-raw-rgb", "endianness",
1174 G_TYPE_INT, fbcontext->endianness,
1175 "depth", G_TYPE_INT,
1176 fbcontext->depth, "bpp",
1177 G_TYPE_INT, fbcontext->bpp,
1178 "blue_mask", G_TYPE_INT, BLUEMASK,
1179 "green_mask", G_TYPE_INT,
1180 GREENMASK, "red_mask", G_TYPE_INT,
1181 REDMASK, "width", G_TYPE_INT,
1182 fbcontext->width, "height",
1183 G_TYPE_INT, fbcontext->height,
1184 "framerate",
1185 GST_TYPE_FRACTION_RANGE, 0, 1,
1186 G_MAXINT, 1, NULL), NULL);
1188 GstFbImageFormat *format = NULL;
1189 format = g_new0(GstFbImageFormat, 1);
1190 if (format) {
1191 // printf(" I am in UYVY \n\n");
1192 format->format = GST_MAKE_FOURCC('U', 'Y', 'V', 'Y');
1193 format->caps = gst_caps_new_simple("video/x-raw-yuv",
1194 "width", GST_TYPE_INT_RANGE,
1195 176, 720,
1196 "height", GST_TYPE_INT_RANGE,
1197 144, 576,
1198 "framerate",
1199 GST_TYPE_FRACTION_RANGE, 0, 1,
1200 G_MAXINT, 1, NULL);
1202 fbcontext->formats_list =
1203 g_list_append(fbcontext->formats_list, format);
1206 format = g_new0(GstFbImageFormat, 1);
1207 if (format) {
1208 // printf(" I am in YUY2 format \n\n");
1209 format->format = GST_MAKE_FOURCC('Y', 'U', 'Y', '2');
1210 format->caps = gst_caps_new_simple("video/x-raw-yuv",
1211 "width", G_TYPE_INT,
1212 fbcontext->width, "height",
1213 G_TYPE_INT, fbcontext->height,
1214 "framerate",
1215 GST_TYPE_FRACTION_RANGE, 0, 1,
1216 G_MAXINT, 1, NULL);
1217 fbcontext->formats_list =
1218 g_list_append(fbcontext->formats_list, format);
1221 format = g_new0(GstFbImageFormat, 1);
1222 if (format) {
1223 // printf(" I am in YVYU format \n\n");
1224 format->format = GST_MAKE_FOURCC('Y', 'V', 'Y', 'U');
1225 format->caps = gst_caps_new_simple("video/x-raw-yuv",
1226 "width", G_TYPE_INT,
1227 fbcontext->width, "height",
1228 G_TYPE_INT, fbcontext->height,
1229 "framerate",
1230 GST_TYPE_FRACTION_RANGE, 0, 1,
1231 G_MAXINT, 1, NULL);
1232 fbcontext->formats_list =
1233 g_list_append(fbcontext->formats_list, format);
1236 format = g_new0(GstFbImageFormat, 1);
1237 if (format) {
1238 // printf(" I am in RGB format \n\n");
1239 format->format = GST_MAKE_FOURCC('R', 'G', 'B', ' ');
1240 format->caps = gst_caps_new_simple("video/x-raw-rgb",
1241 "endianness", G_TYPE_INT,
1242 BYTE_ORDER, "depth", G_TYPE_INT,
1243 fbcontext->depth, "bpp",
1244 G_TYPE_INT, fbcontext->bpp,
1245 "width", G_TYPE_INT,
1246 fbcontext->width, "height",
1247 G_TYPE_INT, fbcontext->height,
1248 "framerate",
1249 GST_TYPE_FRACTION_RANGE, 0, 1,
1250 G_MAXINT, 1, NULL);
1251 fbcontext->formats_list =
1252 g_list_append(fbcontext->formats_list, format);
1256 #ifdef DEBUG_OUT
1257 printf("fbvideosink: gst_fbvideosink_fbcontext_get END..\n");
1258 #endif
1260 return fbcontext;
1263 static GstStateChangeReturn gst_fbvideosink_change_state(GstElement *
1264 element,
1265 GstStateChange
1266 transition)
1268 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1269 GstFbVideoSink *fbvideosink;
1271 #ifdef DEBUG_OUT
1272 printf("fbvideosink: gst_fbvideosink_change_state BEGIN..\n");
1273 #endif
1275 fbvideosink = GST_FBVIDEOSINK(element);
1277 switch (transition) {
1278 case GST_STATE_CHANGE_NULL_TO_READY:
1279 #ifdef DEBUG_OUT
1280 printf("fbvideosink: change_state from NULL to READY..\n");
1281 #endif
1282 fbvideosink->pool_lock = g_mutex_new();
1283 fbvideosink->fb_lock = g_mutex_new();
1284 /* Initializing the FbContext */
1285 if (!fbvideosink->fbcontext
1286 && !(fbvideosink->fbcontext =
1287 gst_fbvideosink_fbcontext_get(fbvideosink)))
1288 return GST_STATE_CHANGE_FAILURE;
1289 /* update object's par with calculated one if not set yet */
1290 if (!fbvideosink->par) {
1291 fbvideosink->par = g_new0(GValue, 1);
1292 gst_value_init_and_copy(fbvideosink->par,
1293 fbvideosink->fbcontext->par);
1294 GST_DEBUG_OBJECT(fbvideosink,
1295 "set calculated PAR on object's PAR");
1297 counter = 0;
1299 break;
1300 case GST_STATE_CHANGE_READY_TO_PAUSED:
1301 #ifdef DEBUG_OUT
1302 printf("fbvideosink: change_of_state from READY_TO_PAUSED..\n");
1303 #endif
1304 break;
1305 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1306 #ifdef DEBUG_OUT
1307 printf("fbvideosink: change_of_state from PAUSED_TO_PLAYING..\n");
1308 #endif
1309 break;
1310 default:
1311 #ifdef DEBUG_OUT
1312 printf("fbvideosink: Invalid Change of state requested..\n");
1313 #endif
1314 break;
1317 ret =
1318 GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
1319 if (ret == GST_STATE_CHANGE_FAILURE){
1320 #ifdef DEBUG_OUT
1321 printf("fbvideosink: gst_fbvideosink_change_state - Return with failure END..\n");
1322 #endif
1323 return ret;
1325 switch (transition) {
1326 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1327 #ifdef DEBUG_OUT
1328 printf("fbvideosink: change_of_state from PLAYING_TO_PAUSED..\n");
1329 #endif
1330 break;
1331 case GST_STATE_CHANGE_PAUSED_TO_READY:
1332 #ifdef DEBUG_OUT
1333 printf("fbvideosink: change_of_state from PAUSED_TO_READY..\n");
1334 #endif
1335 fbvideosink->fps_n = 0;
1336 fbvideosink->fps_d = 1;
1337 GST_VIDEO_SINK_WIDTH(fbvideosink) = 0;
1338 GST_VIDEO_SINK_HEIGHT(fbvideosink) = 0;
1339 break;
1340 case GST_STATE_CHANGE_READY_TO_NULL:
1341 #ifdef DEBUG_OUT
1342 printf("fbvideosink: change_of_state from READY_TO_NULL..\n");
1343 #endif
1344 if (fbvideosink->fbimage) {
1345 gst_fbimage_buffer_free(fbvideosink->fbimage);
1346 fbvideosink->fbimage = NULL;
1349 if (fbvideosink->cmem_buffers_list)
1350 gst_fbvideosink_cmembuffers_clear(fbvideosink);
1351 if (fbvideosink->pool_lock)
1352 g_mutex_free(fbvideosink->pool_lock);
1353 if (fbvideosink->fb_lock)
1354 g_mutex_free(fbvideosink->fb_lock);
1355 if (fbvideosink->fbcontext) {
1356 gst_fbvideosink_fbcontext_clear(fbvideosink);
1357 fbvideosink->fbcontext = NULL;
1359 break;
1360 default:
1361 #ifdef DEBUG_OUT
1362 printf("fbvideosink: change_of_state INVALID ..\n");
1363 #endif
1364 break;
1367 #ifdef DEBUG_OUT
1368 printf("fbvideosink: gst_fbvideosink_change_state END..\n");
1369 #endif
1371 return ret;
1374 static GstCaps *gst_fbvideosink_getcaps(GstBaseSink * bsink)
1376 GstFbVideoSink *fbvideosink;
1378 #ifdef DEBUG_OUT
1379 printf("fbvideosink: gst_fbvideosink_getcaps BEGIN and gst_pad_get_pad_template_caps..\n");
1380 #endif
1381 fbvideosink = GST_FBVIDEOSINK(bsink);
1382 // if (fbvideosink->fbcontext)
1383 // return gst_caps_ref(fbvideosink->fbcontext->caps);
1385 return gst_caps_copy(gst_pad_get_pad_template_caps
1386 (GST_VIDEO_SINK_PAD(fbvideosink)));
1389 static gboolean gst_fbvideosink_setcaps(GstBaseSink * bsink,
1390 GstCaps * caps)
1392 GstFbVideoSink *fbvideosink;
1393 GstStructure *structure;
1394 GstCaps *intersection;
1395 guint32 im_format = 0;
1396 gboolean ret;
1397 gint video_width, video_height;
1398 gint video_par_n, video_par_d; /* video's PAR */
1399 gint display_par_n, display_par_d; /* display's PAR */
1400 GValue display_ratio = { 0, }; /* display w/h ratio */
1401 const GValue *caps_par;
1402 const GValue *fps;
1403 gint num, den;
1405 #ifdef DEBUG_OUT
1406 printf("fbvideosink: gst_fbvideosink_setcaps BEGIN..\n");
1407 #endif
1410 fbvideosink = GST_FBVIDEOSINK(bsink);
1411 GST_DEBUG_OBJECT(fbvideosink,
1412 "In setcaps. Possible caps %" GST_PTR_FORMAT
1413 ", setting caps %" GST_PTR_FORMAT,
1414 fbvideosink->fbcontext->caps, caps);
1416 intersection = gst_caps_intersect(fbvideosink->fbcontext->caps, caps);
1417 GST_DEBUG_OBJECT(fbvideosink, "intersection returned %" GST_PTR_FORMAT,
1418 intersection);
1420 if (gst_caps_is_empty(intersection)) {
1421 printf ("Empty\n");
1422 return FALSE;
1425 gst_caps_unref(intersection);
1427 structure = gst_caps_get_structure(caps, 0);
1428 ret = gst_structure_get_int(structure, "width", &video_width);
1429 ret &= gst_structure_get_int(structure, "height", &video_height);
1430 fps = gst_structure_get_value(structure, "framerate");
1431 ret &= (fps != NULL);
1433 if (!ret)
1434 return FALSE;
1436 fbvideosink->fps_n = gst_value_get_fraction_numerator(fps);
1437 fbvideosink->fps_d = gst_value_get_fraction_denominator(fps);
1439 #ifdef DEBUG_OUT
1440 printf(" Video Width %d\n",video_width);
1441 printf("Video Height %d\n",video_height);
1442 #endif
1444 fbvideosink->video_width = video_width;
1445 fbvideosink->video_height = video_height;
1446 /* get aspect ratio from caps if it's present, and
1447 * convert video width and height to a display width and height
1448 * using wd / hd = wv / hv * PARv / PARd
1449 * the ratio wd / hd will be stored in display_ratio */
1450 g_value_init(&display_ratio, GST_TYPE_FRACTION);
1452 /* get video's PAR */
1453 caps_par = gst_structure_get_value(structure, "pixel-aspect-ratio");
1455 #ifdef DEBUG_OUT
1456 printf("Pixel Aspect Ratio %d\n",caps_par);
1457 #endif
1459 if (caps_par) {
1460 video_par_n = gst_value_get_fraction_numerator(caps_par);
1461 video_par_d = gst_value_get_fraction_denominator(caps_par);
1462 } else {
1463 video_par_n = 1;
1464 video_par_d = 1;
1467 /* get display's PAR */
1468 if (fbvideosink->par) {
1469 display_par_n = gst_value_get_fraction_numerator(fbvideosink->par);
1470 display_par_d =
1471 gst_value_get_fraction_denominator(fbvideosink->par);
1472 } else {
1473 display_par_n = 1;
1474 display_par_d = 1;
1477 #ifdef DEBUG_OUT
1478 printf("video par n: %d, display par n: %d, video par d: %d, display par d: %d\n",
1479 video_par_n,display_par_n, video_par_d,display_par_d);
1480 #endif
1482 gst_value_set_fraction(&display_ratio,
1483 video_width * video_par_n * display_par_d,
1484 video_height * video_par_d * display_par_n);
1486 num = gst_value_get_fraction_numerator(&display_ratio);
1487 den = gst_value_get_fraction_denominator(&display_ratio);
1488 GST_DEBUG_OBJECT(fbvideosink,
1489 "video width/height: %dx%d, calculated display ratio: %d/%d",
1490 video_width, video_height, num, den);
1491 #ifdef DEBUG_OUT
1492 printf("video width/height: %dx%d, calculated display ratio: %d/%d",
1493 video_width, video_height, num, den);
1494 #endif
1496 /* now find a width x height that respects this display ratio.
1497 * prefer those that have one of w/h the same as the incoming video
1498 * using wd / hd = num / den
1501 /* start with same height, because of interlaced video */
1502 /* check hd / den is an integer scale factor, and scale wd with the PAR */
1503 if (video_height % den == 0) {
1504 GST_DEBUG_OBJECT(fbvideosink, "keeping video height");
1505 GST_VIDEO_SINK_WIDTH(fbvideosink) = video_height * num / den;
1506 GST_VIDEO_SINK_HEIGHT(fbvideosink) = video_height;
1507 } else if (video_width % num == 0) {
1508 GST_DEBUG_OBJECT(fbvideosink, "keeping video width");
1509 GST_VIDEO_SINK_WIDTH(fbvideosink) = video_width;
1510 GST_VIDEO_SINK_HEIGHT(fbvideosink) = video_width * den / num;
1511 } else {
1512 GST_DEBUG_OBJECT(fbvideosink,
1513 "approximating while keeping video height");
1514 GST_VIDEO_SINK_WIDTH(fbvideosink) = video_height * num / den;
1515 GST_VIDEO_SINK_HEIGHT(fbvideosink) = video_height;
1518 im_format = gst_fbvideosink_get_format_from_caps(fbvideosink, caps);
1519 if (im_format == 0) {
1520 //printf ("Format\n");
1521 return FALSE;
1525 /* We renew our fbimage only if size or format changed;
1526 * the fbimage is the same size as the video pixel size */
1527 if ((fbvideosink->fbimage)
1528 && ((im_format != fbvideosink->fbimage->im_format)
1529 || (video_width != fbvideosink->fbimage->width)
1530 || (video_height != fbvideosink->fbimage->height))
1532 GST_DEBUG_OBJECT(fbvideosink,
1533 "old format %" GST_FOURCC_FORMAT ", new format %"
1534 GST_FOURCC_FORMAT,
1535 GST_FOURCC_ARGS(fbvideosink->fbcontext->
1536 im_format),
1537 GST_FOURCC_ARGS(im_format));
1538 GST_DEBUG_OBJECT(fbvideosink, "renewing fbimage");
1539 gst_buffer_unref(GST_BUFFER(fbvideosink->fbimage));
1540 fbvideosink->fbimage = NULL;
1543 fbvideosink->fbcontext->im_format = im_format;
1545 #ifdef DEBUG_OUT
1546 printf("fbvideosink: gst_fbvideosink_setcaps END..\n");
1547 #endif
1549 return TRUE;
1552 static void gst_fbvideosink_get_times(GstBaseSink * bsink, GstBuffer * buf,
1553 GstClockTime * start,
1554 GstClockTime * end)
1556 GstFbVideoSink *fbvideosink;
1557 guint i;
1558 #ifdef SLOW_MEMCOPY
1559 static XDAS_Int8 *prevbuf = NULL;
1560 static UInt prevbufSize = 0;
1561 #endif /* SLOW_MEMCOPY */
1563 #ifdef DEBUG_OUT
1564 printf("fbvideosink: gst_fbvideosink_get_times BEGIN..\n");
1565 #endif
1567 fbvideosink = GST_FBVIDEOSINK(bsink);
1569 if (GST_BUFFER_TIMESTAMP_IS_VALID(buf)) {
1570 *start = GST_BUFFER_TIMESTAMP(buf);
1571 if (GST_BUFFER_DURATION_IS_VALID(buf)) {
1572 *end = *start + GST_BUFFER_DURATION(buf);
1573 } else {
1574 if (fbvideosink->fps_n > 0) {
1575 *end =
1576 *start +
1577 (GST_SECOND * fbvideosink->fps_d) / fbvideosink->fps_n;
1581 // printf ("Get times for buffer:%p %llu %llu\n",GST_BUFFER_DATA(buf), *start, *end);
1583 #ifdef SLOW_MEMCOPY
1584 if ((to_be_displayed != 0) && (prevbuf != NULL))
1586 // printf("GET TIMES:GST_BUFFER_DATA:%x\n",prevbuf);
1587 if (Memory_contigFree((XDAS_Int8 *)prevbuf,prevbufSize) == FALSE)
1588 printf("ContigFree failed\n");
1589 else
1591 count--;
1592 to_be_displayed--;
1593 // printf("ContigFree done. Count : %d\n", count);
1597 to_be_displayed++;
1598 prevbuf = GST_BUFFER_DATA(buf);
1599 prevbufSize = GST_BUFFER_SIZE(buf);
1600 #else
1602 GST_DEBUG("slow copy into bufferpool buffer");
1603 /* Else we have to copy the data into our private image, */
1604 /* if we have one... */
1605 if (!fbvideosink->fbimage) {
1606 GST_DEBUG_OBJECT(fbvideosink, "creating our fbimage");
1608 fbvideosink->fbimage = gst_fbvideosink_fbimage_new(fbvideosink,
1609 GST_BUFFER_CAPS(buf));
1611 if (!fbvideosink->fbimage)
1612 printf("FBIMAGE not initialized\n");
1615 GST_DEBUG
1616 ("Coping data from received buffer to fbvideosinks internal buffer");
1617 GstFbImageBuffer *temp;
1619 temp = fbvideosink->fbimage;
1621 // printf("GET TIMES:GST_BUFFER_TIMESTAMP:%llu\n",GST_BUFFER_TIMESTAMP(buf));
1622 // printf("GET TIMES:GST_BUFFER_DATA:%x\n",GST_BUFFER_DATA(buf));
1623 // printf("GET TIMES:GST_BUFFER_DATA TEMP:%x\n",GST_BUFFER_DATA(temp));
1625 #ifdef DEBUG_OUT
1626 printf("GST BUFFER SIZE (buf) : %d\n",GST_BUFFER_SIZE(buf));
1627 printf("fbimage->size : %d \n",fbvideosink->fbimage->size);
1628 #endif
1631 // memcpy(GST_BUFFER_DATA(temp), GST_BUFFER_DATA(buf),MIN(GST_BUFFER_SIZE(buf), fbvideosink->fbimage->size));
1632 // memcpy(GST_BUFFER_DATA(temp), GST_BUFFER_DATA(buf),fbvideosink->fbimage->size);
1633 GST_BUFFER_TIMESTAMP(temp) = GST_BUFFER_TIMESTAMP(buf);
1636 for (i=0; i < temp->height; i++){
1637 // printf("SHOW FRAME:GST_BUFFER_TIMESTAMP:%llu\n",GST_BUFFER_TIMESTAMP(buf));
1638 // memcpy(GST_BUFFER_DATA(temp), GST_BUFFER_DATA(buf),MIN(GST_BUFFER_SIZE(buf), fbvideosink->fbimage->size));
1639 #ifdef DEBUG_OUT
1640 printf("Copying from %x location to %x location ...%d bytes\n",GST_BUFFER_DATA(buf),GST_BUFFER_DATA(temp),temp->height*2);
1641 #endif
1642 memcpy(GST_BUFFER_DATA(temp), GST_BUFFER_DATA(buf),temp->width*2);
1643 GST_BUFFER_DATA(temp) += fbvideosink->fbcontext->fScreenInfo.line_length;
1644 GST_BUFFER_DATA(buf) += temp->width*2;
1649 GST_BUFFER_DATA(temp) = GST_BUFFER_DATA(temp) - (fbvideosink->fbcontext->fScreenInfo.line_length * temp->height );
1650 GST_BUFFER_DATA(buf) = GST_BUFFER_DATA(buf) - (temp->height * temp->width *2);
1653 if (Memory_contigFree((XDAS_Int8 *)GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf)) == FALSE)
1654 printf("ContigFree failed\n");
1655 else
1657 count--;
1658 #ifdef DEALLOC
1659 g_mutex_lock(fbvideosink->pool_lock);
1661 struct cmem_buffers_node *node;
1663 GSList *list = fbvideosink->cmem_buffers_list;
1665 while (list)
1667 node = list->data;
1669 if(node != NULL && node->ptr == (XDAS_Int8 *)GST_BUFFER_DATA(buf))
1671 /*fbvideosink->cmem_buffers_list = g_slist_delete_link(fbvideosink->cmem_buffers_list,list);*/
1672 fbvideosink->cmem_buffers_list = g_slist_remove(fbvideosink->cmem_buffers_list, node);
1674 //printf("Node with cmem ptr:%p freed\n",(XDAS_Int8 *)GST_BUFFER_DATA(buf));
1676 free(node);
1678 break;
1681 list = g_slist_next(list);
1684 g_mutex_unlock(fbvideosink->pool_lock);
1685 #endif /* DEALLOC */
1686 // printf("ContigFree done. Count : %d\n", count);
1690 #endif /* SLOW_MEMCOPY */
1692 #ifdef DEBUG_OUT
1693 printf("fbvideosink: gst_fbvideosink_get_times END..\n");
1694 #endif
1699 /*...
1700 Init and Class Init
1701 ...*/
1703 static void gst_fbvideosink_set_property(GObject * object, guint prop_id,
1704 const GValue * value,
1705 GParamSpec * pspec)
1707 GstFbVideoSink *fbvideosink;
1709 #ifdef DEBUG_OUT
1710 printf("fbvideosink: gst_fbvideosink_set_property BEGIN..\n");
1711 #endif
1713 fbvideosink = GST_FBVIDEOSINK(object);
1715 switch (prop_id) {
1716 case PROP_DEVICE:
1717 #ifdef DEBUG_OUT
1718 printf("fbvideosink: Set_property PROP_DEVICE..\n");
1719 #endif
1720 g_free(fbvideosink->device);
1721 fbvideosink->device = g_value_dup_string(value);
1722 break;
1723 default:
1724 #ifdef DEBUG_OUT
1725 printf("fbvideosink: Invalid property ID..\n");
1726 #endif
1727 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1728 break;
1731 #ifdef DEBUG_OUT
1732 printf("fbvideosink: gst_fbvideosink_set_property END..\n");
1733 #endif
1738 static void gst_fbvideosink_get_property(GObject * object, guint prop_id,
1739 GValue * value,
1740 GParamSpec * pspec)
1742 GstFbVideoSink *fbvideosink;
1744 #ifdef DEBUG_OUT
1745 printf("fbvideosink: gst_fbvideosink_get_property BEGIN..\n");
1746 #endif
1749 fbvideosink = GST_FBVIDEOSINK(object);
1751 switch (prop_id) {
1752 case PROP_DEVICE:
1753 g_value_set_string(value, fbvideosink->device);
1754 break;
1755 default:
1756 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1757 break;
1760 #ifdef DEBUG_OUT
1761 printf("fbvideosink: gst_fbvideosink_get_property END..\n");
1762 #endif
1767 gboolean gst_fbvideosink_query(GstElement * element, GstQuery * query)
1769 GstStructure *vidp;
1770 GValue framesDisplayed = { 0, };
1771 GstFbVideoSink *fbvideosink = GST_FBVIDEOSINK(element);
1774 #ifdef DEBUG_OUT
1775 printf("fbvideosink: gst_fbvideosink_query BEGIN..\n");
1776 #endif
1778 g_value_init(&framesDisplayed, G_TYPE_UINT);
1779 g_value_set_uint(&framesDisplayed, fbvideosink->framesDisplayed);
1781 vidp = gst_query_get_structure(query);
1782 gst_structure_set_value(vidp, "framesDisplayed", &framesDisplayed);
1783 g_value_unset(&framesDisplayed);
1786 #ifdef DEBUG_OUT
1787 printf("fbvideosink: gst_fbvideosink_query END..\n");
1788 #endif
1791 return TRUE;
1794 static void gst_fbvideosink_init(GstFbVideoSink * fbvideosink)
1796 GstElementClass *element_class =
1797 GST_ELEMENT_CLASS(GST_FBVIDEOSINK_GET_CLASS(fbvideosink));
1800 #ifdef DEBUG_OUT
1801 printf("fbvideosink: gst_fbvideosink_init BEGIN..\n");
1802 #endif
1804 fbvideosink->fbcontext = NULL;
1805 fbvideosink->fbimage = NULL;
1806 fbvideosink->cur_image = NULL;
1807 fbvideosink->framesDisplayed = 0;
1809 fbvideosink->fps_n = 0;
1810 fbvideosink->fps_d = 0;
1811 fbvideosink->video_width = 0;
1812 fbvideosink->video_height = 0;
1814 fbvideosink->cmem_buffers_list = NULL;
1816 fbvideosink->par = NULL;
1817 fbvideosink->device = g_strdup(DEFAULT_DEVICE);
1818 element_class->query = gst_fbvideosink_query;
1820 #ifdef DEBUG_OUT
1821 printf("fbvideosink: gst_fbvideosink_init END..\n");
1822 #endif
1826 static void gst_fbvideosink_base_init(gpointer g_class)
1828 GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
1830 #ifdef DEBUG_OUT
1831 printf("fbvideosink: gst_fbvideosink_base_init BEGIN..\n");
1832 #endif
1834 gst_element_class_set_details(element_class, &gst_fbvideosink_details);
1835 gst_element_class_add_pad_template(element_class,
1836 gst_static_pad_template_get
1837 (&gst_fbvideosink_sink_template_factory)
1840 #ifdef DEBUG_OUT
1841 printf("fbvideosink: gst_fbvideosink_base_init END..\n");
1842 #endif
1846 static void gst_fbvideosink_class_init(GstFbVideoSinkClass * klass)
1848 GObjectClass *gobject_class;
1849 GstElementClass *gstelement_class;
1850 GstBaseSinkClass *gstbasesink_class;
1852 #ifdef DEBUG_OUT
1853 printf("fbvideosink: gst_fbvideosink_class_init BEGIN..\n");
1854 #endif
1856 gobject_class = (GObjectClass *) klass;
1857 gstelement_class = (GstElementClass *) klass;
1858 gstbasesink_class = (GstBaseSinkClass *) klass;
1860 parent_class = g_type_class_ref(GST_TYPE_VIDEO_SINK);
1862 gobject_class->set_property = gst_fbvideosink_set_property;
1863 gobject_class->get_property = gst_fbvideosink_get_property;
1864 g_object_class_install_property(gobject_class, PROP_DEVICE,
1865 g_param_spec_string("device", "Device",
1866 "Frame Buffer Device (usually /dev/fb0)",
1867 DEFAULT_DEVICE,
1868 G_PARAM_READWRITE)
1871 gobject_class->finalize = gst_fbvideosink_finalize;
1872 gstelement_class->change_state =
1873 GST_DEBUG_FUNCPTR(gst_fbvideosink_change_state);
1875 gstbasesink_class->get_caps =
1876 GST_DEBUG_FUNCPTR(gst_fbvideosink_getcaps);
1877 gstbasesink_class->set_caps =
1878 GST_DEBUG_FUNCPTR(gst_fbvideosink_setcaps);
1880 gstbasesink_class->buffer_alloc =
1881 GST_DEBUG_FUNCPTR(gst_fbvideosink_buffer_alloc);
1882 gstbasesink_class->get_times =
1883 GST_DEBUG_FUNCPTR(gst_fbvideosink_get_times);
1884 //gstbasesink_class->preroll =
1885 //GST_DEBUG_FUNCPTR(gst_fbvideosink_show_frame);
1886 gstbasesink_class->render =
1887 GST_DEBUG_FUNCPTR(gst_fbvideosink_show_frame);
1890 #ifdef DEBUG_OUT
1891 printf("fbvideosink: gst_fbvideosink_class_init END..\n");
1892 #endif
1896 /*....
1897 Public Methods
1898 Object Typing and Creation
1899 ...*/
1900 GType gst_fbvideosink_get_type(void)
1902 static GType fbvideosink_type = 0;
1904 #ifdef DEBUG_OUT
1905 printf("fbvideosink: gst_fbvideosink_get_type BEGIN..\n");
1906 #endif
1908 if (!fbvideosink_type) {
1909 static const GTypeInfo fbvideosink_info = {
1910 sizeof(GstFbVideoSinkClass),
1911 gst_fbvideosink_base_init,
1912 NULL,
1913 (GClassInitFunc) gst_fbvideosink_class_init,
1914 NULL,
1915 NULL,
1916 sizeof(GstFbVideoSink),
1918 (GInstanceInitFunc) gst_fbvideosink_init,
1921 fbvideosink_type =
1922 g_type_register_static(GST_TYPE_VIDEO_SINK, "GstFbVideoSink",
1923 &fbvideosink_info, 0);
1926 #ifdef DEBUG_OUT
1927 printf("fbvideosink: gst_fbvideosink_get_type END..\n");
1928 #endif
1930 return fbvideosink_type;