use calibrated timestamps (as suggested by slomo)
[gst-plugin-dreamsource.git] / src / gstdreamsource.c
1 /*
2  * GStreamer dreamsource
3  * Copyright 2014-2015 Andreas Frisch <fraxinas@opendreambox.org>
4  *
5  * This program is licensed under the Creative Commons
6  * Attribution-NonCommercial-ShareAlike 3.0 Unported
7  * License. To view a copy of this license, visit
8  * http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
9  * Creative Commons,559 Nathan Abbott Way,Stanford,California 94305,USA.
10  *
11  * Alternatively, this program may be distributed and executed on
12  * hardware which is licensed by Dream Property GmbH.
13  *
14  * This program is NOT free software. It is open source, you are allowed
15  * to modify it (if you keep the license), but it may not be commercially
16  * distributed other than under the conditions noted above.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 #include <gst/gst.h>
23
24 #include "gstdreamsource.h"
25 #include "gstdreamaudiosource.h"
26 #include "gstdreamvideosource.h"
27 #include "gstdreamtssource.h"
28
29 static gboolean
30 plugin_init (GstPlugin * plugin)
31 {
32   gboolean res = TRUE;
33   res &= gst_dreamaudiosource_plugin_init (plugin);
34   res &= gst_dreamvideosource_plugin_init (plugin);
35   res &= gst_dreamtssource_plugin_init (plugin);
36
37   return res;
38 }
39
40 GST_PLUGIN_DEFINE (
41         GST_VERSION_MAJOR,
42         GST_VERSION_MINOR,
43         dreamsource,
44         "Dreambox Audio/Video Source",
45         plugin_init,
46         VERSION,
47         "Proprietary",
48         "dreamsource",
49         "https://schwerkraft.elitedvb.net/scm/browser.php?group_id=10"
50 )
51
52 GST_DEBUG_CATEGORY_STATIC (dreamsourceclock_debug);
53 #define GST_CAT_DEFAULT dreamsourceclock_debug
54
55 G_DEFINE_TYPE (GstDreamSourceClock, gst_dreamsource_clock, GST_TYPE_SYSTEM_CLOCK);
56
57 static GstClockTime gst_dreamsource_clock_get_internal_time (GstClock * clock);
58
59 static void
60 gst_dreamsource_clock_class_init (GstDreamSourceClockClass * klass)
61 {
62         GstClockClass *clock_class = (GstClockClass *) klass;
63         GST_DEBUG_CATEGORY_INIT (dreamsourceclock_debug, "dreamsourceclock", 0, "dreamsourceclock");
64         clock_class->get_internal_time = gst_dreamsource_clock_get_internal_time;
65 }
66
67 static void
68 gst_dreamsource_clock_init (GstDreamSourceClock * self)
69 {
70         self->fd = 0;
71         self->stc_offset = 0;
72         self->first_stc = 0;
73         self->prev_stc = 0;
74         GST_OBJECT_FLAG_SET (self, GST_CLOCK_FLAG_CAN_SET_MASTER);
75 }
76
77 GstClock *
78 gst_dreamsource_clock_new (const gchar * name, int fd)
79 {
80         GstDreamSourceClock *self = GST_DREAMSOURCE_CLOCK (g_object_new (GST_TYPE_DREAMSOURCE_CLOCK, "name", name, "clock-type", GST_CLOCK_TYPE_OTHER, NULL));
81         self->fd = fd;
82         GST_INFO_OBJECT (self, "gst_dreamsource_clock_new fd=%i", self->fd);
83         return GST_CLOCK_CAST (self);
84 }
85
86 static GstClockTime gst_dreamsource_clock_get_internal_time (GstClock * clock)
87 {
88         GstDreamSourceClock *self = GST_DREAMSOURCE_CLOCK (clock);
89
90         uint32_t stc;
91         GstClockTime encoder_time = 0;
92
93         GST_OBJECT_LOCK(self);
94         if (self->fd > 0) {
95                 int ret = ioctl(self->fd, ENC_GET_STC, &stc);
96                 if (ret == 0)
97                 {
98                         GST_LOG_OBJECT (self, "current stc=%" GST_TIME_FORMAT "", GST_TIME_ARGS(ENCTIME_TO_GSTTIME(stc)));
99                         if (G_UNLIKELY(self->first_stc == 0))
100                                 self->first_stc = stc;
101
102                         stc -= self->first_stc;
103
104                         if (stc < self->prev_stc)
105                         {
106                                 self->stc_offset += UINT32_MAX;
107                                 GST_DEBUG_OBJECT (self, "clock_wrap! new offset=%" PRIu64 " ", self->stc_offset);
108                         }
109
110                         self->prev_stc = stc;
111
112                         uint64_t total_stc = stc + self->stc_offset;
113 //                      GST_WARNING_OBJECT (self, "after subtract stc_offset=%" PRIu64 "   new total_stc=%" PRIu64 "", self->stc_offset, total_stc);
114                         encoder_time = ENCTIME_TO_GSTTIME(total_stc);
115                         GST_LOG_OBJECT (self, "result %" GST_TIME_FORMAT "", GST_TIME_ARGS(encoder_time));
116                 }
117                 else
118                         GST_WARNING_OBJECT (self, "can't ENC_GET_STC error: %s, fd=%i, ret=%i", strerror(errno), self->fd, ret);
119         }
120         else
121                 GST_ERROR_OBJECT (self, "timebase not available because encoder device is not opened");
122
123         GST_OBJECT_UNLOCK(self);
124         return encoder_time;
125 }