2 * Plugin Name : fbvideosink
3 * Description : A fbdev Video Sink Plugin for TI Davinci DM644x
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
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
12 * :: following YUV formats are supported by fbvideosink
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.
36 #include "gstfbvideosink.h"
41 #define ENDIANNESS G_LITTLE_ENDIAN
44 #define GREENMASK 2016
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
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
= {
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",
76 GST_STATIC_CAPS("video/x-raw-yuv, "
77 "framerate = (fraction) [ 0, MAX ], "
78 "width = (int) [ 1, MAX ], "
79 "height = (int) [ 1, MAX ];"
81 "framerate = (fraction) [ 0, MAX ], "
82 "width = (int) [ 1, MAX ], "
83 "height = (int) [ 1, MAX ]")
90 static gint
gst_fbvideosink_get_format_from_caps(GstFbVideoSink
*
93 static GstVideoSinkClass
*parent_class
= NULL
;
96 GType
gst_fbimage_buffer_get_type(void);
97 static GstFbImageBuffer
*gst_fbvideosink_fbimage_new(GstFbVideoSink
*
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
)
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
);
117 printf("fbvideosink: gst_fbvideosink_fbimage_put BEGIN...\n");
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
))
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
);
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
));
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
));
144 fbcontext
->vScreenInfo
.xoffset
= 0;
145 fbcontext
->vScreenInfo
.yoffset
= D1_MAX_HEIGHT
* offset
;
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
);
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));
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
);
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
);
179 (fbvideosink
->framesDisplayed
)++;
182 printf(" Frames Displayed is # %d\n",fbvideosink
->framesDisplayed
);
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;
193 printf("fbvideosink: gst_fbvideosink_fbimage_put END..\n");
197 static GstFlowReturn
gst_fbvideosink_show_frame(GstBaseSink
* bsink
,
200 GstFbVideoSink
*fbvideosink
;
202 GstFbImageBuffer
*temp
,**start_fbimage
;
203 GstBuffer
**start_buf
;
207 printf("fbvideosink: gst_fbvideosink_show_frame BEGIN..\n");
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");
218 printf ("fbvideosink: gst_fbvideosink_show_frame: fast put of bufferpool buffer %p\n", buf
);
220 gst_fbvideosink_fbimage_put(fbvideosink
, GST_FBIMAGE_BUFFER(buf
));
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
)
238 GST_DEBUG("Coping data from received buffer to fbvideosinks internal buffer");
240 temp
= fbvideosink
->fbimage
;
241 start_fbimage
= &(fbvideosink
->fbimage
);
245 printf("fbvideosink: show_frame Width is %d... Height is %d\n",temp
->width
,temp
->height
);
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));
256 printf("Copying from %x location to %x location ...%d bytes\n",GST_BUFFER_DATA(buf
),GST_BUFFER_DATA(temp
),temp
->height
*2);
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);
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
));
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");
281 printf("ContigFree done. Count : %d\n", count
);
285 #endif /* SLOW_MEMCOPY */
287 gst_fbvideosink_fbimage_put(fbvideosink
, fbvideosink
->fbimage
);
291 printf("fbvideosink: gst_fbvideosink_show_frame END..\n");
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.")
305 printf("fbvideosink: gst_fbvideosink_show_frame NO IMAGE ERROR END..\n");
308 return GST_FLOW_ERROR
;
310 #endif /* SLOW_MEMCOPY */
315 /* This function handles GstFbImage creation*/
316 static GstFbImageBuffer
*gst_fbvideosink_fbimage_new(GstFbVideoSink
*
320 GstFbImageBuffer
*fbimage
= NULL
;
321 GstStructure
*structure
= NULL
;
322 GstFbContext
*fbcontext
;
324 gboolean succeeded
= FALSE
;
327 printf("fbvideosink: gst_fbvideosink_fbimage_new BEGIN..\n");
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
,
346 printf("creating %dx%d\n", fbimage
->width
, fbimage
->height
);
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
357 (fbcontext
->fbdevFd
, FBIOGET_VSCREENINFO
,
358 &(fbcontext
->vScreenInfo
)) == -1) {
360 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
361 ("Could not get variable screen info"));
363 printf("fbvideosink: ERROR in fbimage_new - could not get variable screen info\n");
369 // Get fixed screen information
371 (fbcontext
->fbdevFd
, FBIOGET_FSCREENINFO
,
372 &(fbcontext
->fScreenInfo
)) == -1) {
374 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
375 ("Could not get fixed screen info"));
377 printf("fbvideosink: ERROR in fbimage_new - could not get fixed screen info\n");
382 if (fbimage
->height
> D1_MAX_HEIGHT
)
383 fbcontext
->vScreenInfo
.yres
= D1_MAX_HEIGHT
;
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
);
404 printf("Buffer Pointer %d....%x\n",i
,fbcontext
->buffers
[i
]);
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
);
414 // Put variable screen information
416 (fbcontext
->fbdevFd
, FBIOPUT_VSCREENINFO
,
417 &(fbcontext
->vScreenInfo
)) == -1) {
419 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
420 ("Could not put variable screen info"));
422 printf("fbvideosink: ERROR in fbimage_new - could not put variable screen info\n");
429 int ypos = (D1_MAX_HEIGHT - fbcontext->vScreenInfo.yres) >> 2;
430 if (ioctl(fbcontext->fbdevFd, FBIO_SETPOSY, ypos) == -1) {
432 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
433 ("Could not set SET POSY"));
439 int xpos = (D1_WIDTH - fbcontext->vScreenInfo.xres) >> 1;
440 if (ioctl(fbcontext->fbdevFd, FBIO_SETPOSX, xpos) == -1) {
442 GST_ELEMENT_ERROR(fbvideosink, RESOURCE, WRITE, (NULL),
443 ("Could not set SET POSX"));
448 // Get variable screen information
450 (fbcontext
->fbdevFd
, FBIOGET_VSCREENINFO
,
451 &(fbcontext
->vScreenInfo
)) == -1) {
453 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
454 ("Could not get variable screen info"));
456 printf("fbvideosink: ERROR in fbimage_new - could not get variable screen info -- 222\n");
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
);
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
);
484 /*Added by Pratheesh */
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");
496 fbimage
->fbvideosink
= gst_object_ref(fbvideosink
);
497 fbimage
->size
= fbcontext
->screensize
;
500 printf("fbImage Size is %d\n",fbcontext
->screensize
);
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;
512 //new code buffer management
514 if (counter == fbcontext->noofbuffers){
515 printf(" no more buffers to allocate, counter = %d = num of buffers",counter);
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
;
529 ("FBVIDEOSINK: Returning Buffer with Data Pointer : %p , and Offset: %d\n",
530 GST_BUFFER_DATA(fbimage
), i
);
532 printf("fbvideosink: fbimage new,ptr:%p offset:%d\n",GST_BUFFER_DATA(fbimage
),i
);
543 GST_BUFFER_DATA(fbimage) = fbcontext->buffers[counter];
544 GST_BUFFER_SIZE(fbimage) = fbimage->size;
545 GST_BUFFER_OFFSET(fbimage) = counter;
548 printf("fbimage new,ptr:%p offset:%d\n",GST_BUFFER_DATA(fbimage),counter);
557 printf("fbvideosink: ERROR in fbimage_new -- Beach Unlocked\n");
559 gst_fbimage_buffer_free(fbimage
);
564 printf("fbvideosink: gst_fbvideosink_fbimage_new END..\n");
572 static void gst_fbvideosink_finalize(GObject
* object
)
574 GstFbVideoSink
*fbvideosink
;
577 printf("fbvideosink: gst_fbvideosink_finalize BEGIN..\n");
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
);
589 printf("fbvideosink: gst_fbvideosink_finalize END..\n");
594 static GstFlowReturn
gst_fbvideosink_buffer_alloc(GstBaseSink
* bsink
,
600 GstFbVideoSink
*fbvideosink
= GST_FBVIDEOSINK(bsink
);
604 printf("fbvideosink: gst_fbvideosink_buffer_alloc BEGIN..\n");
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
;
616 printf("fbvideosink: gst_fbvideosink_buffer_alloc Allocated buffer of size %d bytes at %p location..\n",size
,GST_BUFFER_DATA(*buf
));
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
);
625 fbvideosink
->cmem_buffers_list
= g_slist_append(fbvideosink
->cmem_buffers_list
, node
);
626 g_mutex_unlock(fbvideosink
->pool_lock
);
631 GST_BUFFER_SIZE(*buf
) = size
;
632 gst_buffer_set_caps(GST_BUFFER(*buf
), caps
);
635 printf("fbvideosink: gst_fbvideosink_buffer_alloc END..\n");
641 /* This function destroys a GstFbImage*/
642 static void gst_fbimage_buffer_destroy(GstFbImageBuffer
* fbimage
)
644 GstFbVideoSink
*fbvideosink
;
647 printf("fbvideosink: gst_fbvideosink_buffer_destroy BEGIN..\n");
650 fbvideosink
= fbimage
->fbvideosink
;
651 if (fbvideosink
== NULL
)
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
);
673 printf("fbvideosink: gst_fbvideosink_buffer_destroy END..\n");
680 GST_WARNING("no sink found");
685 static void gst_fbimage_buffer_finalize(GstFbImageBuffer
* fbimage
)
687 GstFbVideoSink
*fbvideosink
;
690 printf("fbvideosink: gst_fbvideosink_buffer_finalize BEGIN..\n");
693 fbvideosink
= fbimage
->fbvideosink
;
694 //GstFbContext *fbcontext = fbvideosink->fbcontext;
695 if (fbvideosink
== NULL
)
698 /* If our geometry changed we can't reuse that image. */
699 if ((fbimage
->width
!= fbvideosink
->video_width
) ||
700 (fbimage
->height
!= fbvideosink
->video_height
)) {
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
);
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
);
711 /* In that case we can reuse the image and add it to our image pool. */
712 GST_DEBUG("recycling image in pool");
714 printf("recycling image in pool:%x pts:%llu\n",
715 GST_BUFFER_DATA(fbimage
),GST_BUFFER_TIMESTAMP(fbimage
));
717 /* need to increment the refcount again to recycle */
718 gst_buffer_ref(GST_BUFFER(fbimage
));
719 //fbcontext->avail[GST_BUFFER_OFFSET(fbimage)] = TRUE;
723 printf("fbvideosink: gst_fbvideosink_buffer_finalize END..\n");
730 GST_WARNING("no sink found");
735 static void gst_fbimage_buffer_init(GstFbImageBuffer
* fbimage
,
740 printf("fbvideosink: gst_fbvideosink_buffer_init BEGIN..\n");
744 printf("fbvideosink: gst_fbvideosink_buffer_init END..\n");
750 static void gst_fbimage_buffer_class_init(gpointer g_class
,
753 GstMiniObjectClass
*mini_object_class
= GST_MINI_OBJECT_CLASS(g_class
);
756 printf("fbvideosink: gst_fbvideosink_class_init BEGIN..\n");
759 mini_object_class
->finalize
=
760 (GstMiniObjectFinalizeFunction
) gst_fbimage_buffer_finalize
;
763 printf("fbvideosink: gst_fbvideosink_class_init END..\n");
768 GType
gst_fbimage_buffer_get_type(void)
770 static GType _gst_fbimage_buffer_type
;
773 printf("fbvideosink: gst_fbimage_buffer_get_type BEGIN..\n");
776 if (G_UNLIKELY(_gst_fbimage_buffer_type
== 0)) {
777 static const GTypeInfo fbimage_buffer_info
= {
778 sizeof(GstBufferClass
),
781 gst_fbimage_buffer_class_init
,
784 sizeof(GstFbImageBuffer
),
786 (GInstanceInitFunc
) gst_fbimage_buffer_init
,
789 _gst_fbimage_buffer_type
=
790 g_type_register_static(GST_TYPE_BUFFER
, "GstFbImageBuffer",
791 &fbimage_buffer_info
, 0);
795 printf("fbvideosink: gst_fbimage_buffer_get_type END..\n");
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
*
810 printf("fbvideosink: gst_fbvideosink_get_format_from_caps BEGIN..\n");
813 g_return_val_if_fail(GST_IS_FBVIDEOSINK(fbvideosink
), 0);
815 list
= fbvideosink
->fbcontext
->formats_list
;
818 GstFbImageFormat
*format
= list
->data
;
821 GstCaps
*icaps
= NULL
;
823 icaps
= gst_caps_intersect(caps
, format
->caps
);
824 if (!gst_caps_is_empty(icaps
)) {
825 gst_caps_unref(icaps
);
827 printf("fbvideosink: gst_fbvideosink_get_format_from_caps END..\n");
829 return format
->format
;
832 list
= g_list_next(list
);
836 printf("fbvideosink: gst_fbvideosink_get_format_from_caps - Return 0 END..\n");
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
)
849 printf("fbvideosink: gst_fbvideosink_fbcontext_clear BEGIN..\n");
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
);
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
;
882 printf("fbvideosink: gst_fbvideosink_fbcontext_clear END..\n");
887 static void gst_fbvideosink_cmembuffers_clear(GstFbVideoSink
* fbvideosink
)
891 printf("fbvideosink: gst_fbvideosink_cmembuffers_clear BEGIN..\n");
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");
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
);
919 g_mutex_unlock(fbvideosink
->pool_lock
);
924 printf("fbvideosink: gst_fbvideosink_cmembuffers_clear END..\n");
929 static void gst_fbimage_buffer_free(GstFbImageBuffer
* fbimage
)
933 printf("fbvideosink: gst_fbimage_buffer_free BEGIN..\n");
936 /* make sure it is not recycled */
937 printf ("Inside buffer free\n");
939 fbimage
->height
= -1;
940 gst_buffer_unref(GST_BUFFER(fbimage
));
943 printf("fbvideosink: gst_fbimage_buffer_free END..\n");
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
*
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 */
965 printf("fbvideosink: gst_fbvideosink_calculate_pixel_aspect_ratio BEGIN..\n");
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 */
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 */
981 for (i
= 1; i
< sizeof(par
) / (sizeof(gint
) * 2); ++i
) {
982 gdouble this_delta
= DELTA(i
);
984 if (this_delta
< delta
) {
990 GST_DEBUG("Decided on index %d (%d/%d)", index
, par
[index
][0],
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
)
1003 printf("fbvideosink: gst_fbvideosink_calculate_pixel_aspect_ratio END..\n");
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
1012 static GstFbContext
*gst_fbvideosink_fbcontext_get(GstFbVideoSink
*
1015 GstFbContext
*fbcontext
= NULL
;
1017 //printf ("Inside fbvideosink_fbcontext_get\n");
1020 printf("fbvideosink: gst_fbvideosink_fbcontext_get BEGIN..\n");
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) {
1036 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
1037 ("Could not open device: %s",
1038 fbvideosink
->device
));
1043 GST_DEBUG_OBJECT(fbvideosink
, "Display Device Opened Successfully");
1045 // Get fixed screen information
1047 (fbcontext
->fbdevFd
, FBIOGET_FSCREENINFO
,
1048 &(fbcontext
->fScreenInfo
)) == -1) {
1050 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
1051 ("Could not get fixed screen info"));
1055 // Get variable screen information
1057 (fbcontext
->fbdevFd
, FBIOGET_VSCREENINFO
,
1058 &(fbcontext
->vScreenInfo
)) == -1) {
1060 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
1061 ("Could not get variable screen info"));
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) {
1074 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
1075 ("Could not SET variable screen info"));
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
);
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);
1105 (guint8
*) mmap(0, fbcontext
->fScreenInfo
.line_length
* fbcontext
->vScreenInfo
.yres_virtual
,
1106 PROT_READ
| PROT_WRITE
, MAP_SHARED
,
1107 fbcontext
->fbdevFd
, 0);
1110 printf("I am in get function :....... \n");
1111 printf("Screen Size here is : ....%d\n",fbcontext
->screensize
);
1114 // fbcontext->bufferIndex = 1;
1116 // printf("ssize: %d\n",fbcontext->screensize);
1118 if ((int) fbcontext
->data
== -1) {
1120 GST_ELEMENT_ERROR(fbvideosink
, RESOURCE
, WRITE
, (NULL
),
1121 ("failed to map framebuffer device to memory"));
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
);
1137 gst_fbvideosink_calculate_pixel_aspect_ratio(fbcontext
);
1138 fbcontext
->endianness
= ENDIANNESS
;
1140 fbcontext
->caps
= gst_caps_new_full(gst_structure_new
1142 "width", GST_TYPE_INT_RANGE
,
1144 "height", GST_TYPE_INT_RANGE
,
1147 GST_TYPE_FRACTION_RANGE
, 0, 1,
1148 G_MAXINT
, 1, "format",
1150 GST_MAKE_FOURCC('U', 'Y', 'V',
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",
1160 GST_MAKE_FOURCC('Y', 'U', 'Y',
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",
1170 GST_MAKE_FOURCC('Y', 'V', 'Y',
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
,
1185 GST_TYPE_FRACTION_RANGE
, 0, 1,
1186 G_MAXINT
, 1, NULL
), NULL
);
1188 GstFbImageFormat
*format
= NULL
;
1189 format
= g_new0(GstFbImageFormat
, 1);
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
,
1196 "height", GST_TYPE_INT_RANGE
,
1199 GST_TYPE_FRACTION_RANGE
, 0, 1,
1202 fbcontext
->formats_list
=
1203 g_list_append(fbcontext
->formats_list
, format
);
1206 format
= g_new0(GstFbImageFormat
, 1);
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
,
1215 GST_TYPE_FRACTION_RANGE
, 0, 1,
1217 fbcontext
->formats_list
=
1218 g_list_append(fbcontext
->formats_list
, format
);
1221 format
= g_new0(GstFbImageFormat
, 1);
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
,
1230 GST_TYPE_FRACTION_RANGE
, 0, 1,
1232 fbcontext
->formats_list
=
1233 g_list_append(fbcontext
->formats_list
, format
);
1236 format
= g_new0(GstFbImageFormat
, 1);
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
,
1249 GST_TYPE_FRACTION_RANGE
, 0, 1,
1251 fbcontext
->formats_list
=
1252 g_list_append(fbcontext
->formats_list
, format
);
1257 printf("fbvideosink: gst_fbvideosink_fbcontext_get END..\n");
1263 static GstStateChangeReturn
gst_fbvideosink_change_state(GstElement
*
1268 GstStateChangeReturn ret
= GST_STATE_CHANGE_SUCCESS
;
1269 GstFbVideoSink
*fbvideosink
;
1272 printf("fbvideosink: gst_fbvideosink_change_state BEGIN..\n");
1275 fbvideosink
= GST_FBVIDEOSINK(element
);
1277 switch (transition
) {
1278 case GST_STATE_CHANGE_NULL_TO_READY
:
1280 printf("fbvideosink: change_state from NULL to READY..\n");
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");
1300 case GST_STATE_CHANGE_READY_TO_PAUSED
:
1302 printf("fbvideosink: change_of_state from READY_TO_PAUSED..\n");
1305 case GST_STATE_CHANGE_PAUSED_TO_PLAYING
:
1307 printf("fbvideosink: change_of_state from PAUSED_TO_PLAYING..\n");
1312 printf("fbvideosink: Invalid Change of state requested..\n");
1318 GST_ELEMENT_CLASS(parent_class
)->change_state(element
, transition
);
1319 if (ret
== GST_STATE_CHANGE_FAILURE
){
1321 printf("fbvideosink: gst_fbvideosink_change_state - Return with failure END..\n");
1325 switch (transition
) {
1326 case GST_STATE_CHANGE_PLAYING_TO_PAUSED
:
1328 printf("fbvideosink: change_of_state from PLAYING_TO_PAUSED..\n");
1331 case GST_STATE_CHANGE_PAUSED_TO_READY
:
1333 printf("fbvideosink: change_of_state from PAUSED_TO_READY..\n");
1335 fbvideosink
->fps_n
= 0;
1336 fbvideosink
->fps_d
= 1;
1337 GST_VIDEO_SINK_WIDTH(fbvideosink
) = 0;
1338 GST_VIDEO_SINK_HEIGHT(fbvideosink
) = 0;
1340 case GST_STATE_CHANGE_READY_TO_NULL
:
1342 printf("fbvideosink: change_of_state from READY_TO_NULL..\n");
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
;
1362 printf("fbvideosink: change_of_state INVALID ..\n");
1368 printf("fbvideosink: gst_fbvideosink_change_state END..\n");
1374 static GstCaps
*gst_fbvideosink_getcaps(GstBaseSink
* bsink
)
1376 GstFbVideoSink
*fbvideosink
;
1379 printf("fbvideosink: gst_fbvideosink_getcaps BEGIN and gst_pad_get_pad_template_caps..\n");
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
,
1392 GstFbVideoSink
*fbvideosink
;
1393 GstStructure
*structure
;
1394 GstCaps
*intersection
;
1395 guint32 im_format
= 0;
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
;
1406 printf("fbvideosink: gst_fbvideosink_setcaps BEGIN..\n");
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
,
1420 if (gst_caps_is_empty(intersection
)) {
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
);
1436 fbvideosink
->fps_n
= gst_value_get_fraction_numerator(fps
);
1437 fbvideosink
->fps_d
= gst_value_get_fraction_denominator(fps
);
1440 printf(" Video Width %d\n",video_width
);
1441 printf("Video Height %d\n",video_height
);
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");
1456 printf("Pixel Aspect Ratio %d\n",caps_par
);
1460 video_par_n
= gst_value_get_fraction_numerator(caps_par
);
1461 video_par_d
= gst_value_get_fraction_denominator(caps_par
);
1467 /* get display's PAR */
1468 if (fbvideosink
->par
) {
1469 display_par_n
= gst_value_get_fraction_numerator(fbvideosink
->par
);
1471 gst_value_get_fraction_denominator(fbvideosink
->par
);
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
);
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
);
1492 printf("video width/height: %dx%d, calculated display ratio: %d/%d",
1493 video_width
, video_height
, num
, den
);
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
;
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");
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 %"
1535 GST_FOURCC_ARGS(fbvideosink
->fbcontext
->
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
;
1546 printf("fbvideosink: gst_fbvideosink_setcaps END..\n");
1552 static void gst_fbvideosink_get_times(GstBaseSink
* bsink
, GstBuffer
* buf
,
1553 GstClockTime
* start
,
1556 GstFbVideoSink
*fbvideosink
;
1559 static XDAS_Int8
*prevbuf
= NULL
;
1560 static UInt prevbufSize
= 0;
1561 #endif /* SLOW_MEMCOPY */
1564 printf("fbvideosink: gst_fbvideosink_get_times BEGIN..\n");
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
);
1574 if (fbvideosink
->fps_n
> 0) {
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);
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");
1593 // printf("ContigFree done. Count : %d\n", count);
1598 prevbuf
= GST_BUFFER_DATA(buf
);
1599 prevbufSize
= GST_BUFFER_SIZE(buf
);
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");
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));
1626 printf("GST BUFFER SIZE (buf) : %d\n",GST_BUFFER_SIZE(buf
));
1627 printf("fbimage->size : %d \n",fbvideosink
->fbimage
->size
);
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));
1640 printf("Copying from %x location to %x location ...%d bytes\n",GST_BUFFER_DATA(buf
),GST_BUFFER_DATA(temp
),temp
->height
*2);
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");
1659 g_mutex_lock(fbvideosink
->pool_lock
);
1661 struct cmem_buffers_node
*node
;
1663 GSList
*list
= fbvideosink
->cmem_buffers_list
;
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));
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 */
1693 printf("fbvideosink: gst_fbvideosink_get_times END..\n");
1703 static void gst_fbvideosink_set_property(GObject
* object
, guint prop_id
,
1704 const GValue
* value
,
1707 GstFbVideoSink
*fbvideosink
;
1710 printf("fbvideosink: gst_fbvideosink_set_property BEGIN..\n");
1713 fbvideosink
= GST_FBVIDEOSINK(object
);
1718 printf("fbvideosink: Set_property PROP_DEVICE..\n");
1720 g_free(fbvideosink
->device
);
1721 fbvideosink
->device
= g_value_dup_string(value
);
1725 printf("fbvideosink: Invalid property ID..\n");
1727 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
1732 printf("fbvideosink: gst_fbvideosink_set_property END..\n");
1738 static void gst_fbvideosink_get_property(GObject
* object
, guint prop_id
,
1742 GstFbVideoSink
*fbvideosink
;
1745 printf("fbvideosink: gst_fbvideosink_get_property BEGIN..\n");
1749 fbvideosink
= GST_FBVIDEOSINK(object
);
1753 g_value_set_string(value
, fbvideosink
->device
);
1756 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
1761 printf("fbvideosink: gst_fbvideosink_get_property END..\n");
1767 gboolean
gst_fbvideosink_query(GstElement
* element
, GstQuery
* query
)
1770 GValue framesDisplayed
= { 0, };
1771 GstFbVideoSink
*fbvideosink
= GST_FBVIDEOSINK(element
);
1775 printf("fbvideosink: gst_fbvideosink_query BEGIN..\n");
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
);
1787 printf("fbvideosink: gst_fbvideosink_query END..\n");
1794 static void gst_fbvideosink_init(GstFbVideoSink
* fbvideosink
)
1796 GstElementClass
*element_class
=
1797 GST_ELEMENT_CLASS(GST_FBVIDEOSINK_GET_CLASS(fbvideosink
));
1801 printf("fbvideosink: gst_fbvideosink_init BEGIN..\n");
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
;
1821 printf("fbvideosink: gst_fbvideosink_init END..\n");
1826 static void gst_fbvideosink_base_init(gpointer g_class
)
1828 GstElementClass
*element_class
= GST_ELEMENT_CLASS(g_class
);
1831 printf("fbvideosink: gst_fbvideosink_base_init BEGIN..\n");
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
)
1841 printf("fbvideosink: gst_fbvideosink_base_init END..\n");
1846 static void gst_fbvideosink_class_init(GstFbVideoSinkClass
* klass
)
1848 GObjectClass
*gobject_class
;
1849 GstElementClass
*gstelement_class
;
1850 GstBaseSinkClass
*gstbasesink_class
;
1853 printf("fbvideosink: gst_fbvideosink_class_init BEGIN..\n");
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)",
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
);
1891 printf("fbvideosink: gst_fbvideosink_class_init END..\n");
1898 Object Typing and Creation
1900 GType
gst_fbvideosink_get_type(void)
1902 static GType fbvideosink_type
= 0;
1905 printf("fbvideosink: gst_fbvideosink_get_type BEGIN..\n");
1908 if (!fbvideosink_type
) {
1909 static const GTypeInfo fbvideosink_info
= {
1910 sizeof(GstFbVideoSinkClass
),
1911 gst_fbvideosink_base_init
,
1913 (GClassInitFunc
) gst_fbvideosink_class_init
,
1916 sizeof(GstFbVideoSink
),
1918 (GInstanceInitFunc
) gst_fbvideosink_init
,
1922 g_type_register_static(GST_TYPE_VIDEO_SINK
, "GstFbVideoSink",
1923 &fbvideosink_info
, 0);
1927 printf("fbvideosink: gst_fbvideosink_get_type END..\n");
1930 return fbvideosink_type
;