]> git.vomp.tv Git - vompserver.git/blob - transceiver.c
Patch from Dave Pickles for VDR 1.3 tv/radio channel detection
[vompserver.git] / transceiver.c
1 /*
2      Edited for VOMP by Chris Tallon
3      Edits Copyright 2004-2005 Chris Tallon
4 */
5
6 /*
7  *   MediaMVP Server
8  *
9  *   (C) 2003 Dominic Morris
10  *
11  *   $Id$
12  *   $Date$
13  *
14  *   Transceiver stuff - blatantly stolen from streamdev then changed
15  *   a bit..
16  */
17
18
19
20
21
22 #include "transceiver.h"
23 #include "ts2ps.h"
24 #include "ts2es.h"
25 //#include "setup.h"
26
27 #include <vdr/ringbuffer.h>
28
29 #include <sys/types.h>
30 #include <unistd.h>
31
32
33 #define VIDEOBUFSIZE MEGABYTE(1)
34
35 /* Disable logging if BUFCOUNT buffer overflows occur within BUFOVERTIME
36    milliseconds. Enable logging again if there is no error within BUFOVERTIME
37    milliseconds. */
38 #define BUFOVERTIME  5000
39 #define BUFOVERCOUNT 100
40
41 #if VDRVERSNUM < 10300
42 cMediamvpTransceiver::cMediamvpTransceiver(const cChannel *Channel, int Priority, int Socket, cDevice *Device) :
43                 cReceiver(Channel->Ca(), Priority, 7, Channel->Vpid(), Channel->Ppid(),
44                                 Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2(),
45                                 Channel->Tpid()) {
46 #else
47 cMediamvpTransceiver::cMediamvpTransceiver(const cChannel *Channel, int Priority, int Socket, cDevice *Device) :
48                 cReceiver(Channel->Ca(), Priority, Channel->Vpid(),
49                                 Channel->Apids(), Channel->Dpids(), Channel->Spids()) {
50 #endif        
51         m_Active = false;
52         m_Socket = Socket;
53         m_Remux = NULL;
54         m_Device = Device;
55
56         m_RingBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
57 //        m_RingBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 20, true);
58
59     /* Select the correct Muxing depending on whether it's video or not */
60 #if VDRVERSNUM < 10300
61     if ( Channel->Vpid() == 0 || Channel->Vpid() == 1 || Channel->Vpid() == 0x1FFF ) {
62         m_Remux = new cTS2ESRemux(Channel->Apid1());
63     } else {
64                 m_Remux = new cTS2PSRemux(Channel->Vpid(), Channel->Apid1(), 0, 0, 0, 0);
65     }
66 #else
67     if ( Channel->Vpid() == 0 || Channel->Vpid() == 1 || Channel->Vpid() == 0x1FFF ) {
68         m_Remux = new cTS2ESRemux(Channel->Apid(0));
69     } else {
70                 m_Remux = new cTS2PSRemux(Channel->Vpid(), Channel->Apid(0), 0, 0, 0, 0);
71     }
72 #endif
73     printf("Created transceiver at %p, remux @%p ringbuffer %p\n",this,m_Remux,m_RingBuffer);
74
75     /* Suggested by Peter Wagner to assist single DVB card systems */
76 #ifdef SINGLE_DEVICE
77         m_Device->SwitchChannel(Channel, true);
78 #else
79         m_Device->SwitchChannel(Channel, false);
80 #endif
81         Attach();
82
83
84         // CJT
85         rb.init(1000000);
86         pthread_mutex_init(&ringLock, NULL);
87
88 }
89
90 cMediamvpTransceiver::~cMediamvpTransceiver(void)
91 {
92     printf("Deleting transceiver at %p, remux @%p ringbuffer %p\n",this,m_Remux,m_RingBuffer);
93
94         Detach();
95         if (m_Remux)
96         delete m_Remux;
97     m_Remux = NULL;
98     if ( m_RingBuffer)
99         delete m_RingBuffer;
100     m_RingBuffer = NULL;
101 }
102
103 void cMediamvpTransceiver::Activate(bool On)
104 {
105         if (On)
106                 Start();
107         else if (m_Active)
108                 Stop();
109 }
110
111 void cMediamvpTransceiver::Stop(void)
112 {
113         if (m_Active) {
114                 m_Active = false;
115                 usleep(50000);
116                 Cancel(0);
117         }
118 }
119
120 void cMediamvpTransceiver::Receive(uchar *Data, int Length)
121 {
122         static time_t firsterr = 0;
123         static int errcnt = 0;
124         static bool showerr = true;
125
126         if (m_Active) {
127                 int p = m_RingBuffer->Put(Data, Length);
128                 if (p != Length) {
129                         ++errcnt;
130 #if VDRVERSNUM < 10300
131                         if (showerr) {
132                                 if (firsterr == 0)
133                                         firsterr = time_ms();
134                                 else if (firsterr + BUFOVERTIME > time_ms() && errcnt > BUFOVERCOUNT) {
135                                         esyslog("ERROR: too many buffer overflows, logging stopped");
136                                         showerr = false;
137                                         firsterr = time_ms();
138                                 }
139                         } else if (firsterr + BUFOVERTIME < time_ms()) {
140                                 showerr = true;
141                                 firsterr = 0;
142                                 errcnt = 0;
143                         }
144
145                         if (showerr)
146                                 esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length - p);
147                         else
148                                 firsterr = time_ms();
149 #else
150                         if (showerr) {
151                                 if (firsterr == 0) {
152                                         firsterr = 1;
153                                         lastTime.Set();
154                                 }
155                                 else if (lastTime.Elapsed() > BUFOVERTIME && errcnt > BUFOVERCOUNT) {
156                                         esyslog("ERROR: too many buffer overflows, logging stopped");
157                                         showerr = false;
158                                 }
159                         } else if (lastTime.Elapsed() < BUFOVERTIME) {
160                                 showerr = true;
161                                 firsterr = 0;
162                                 errcnt = 0;
163                         }
164
165                         if (showerr)
166                                 esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length - p);
167                         else
168                                 firsterr = 1;
169 #endif
170                 }
171         }
172 }
173
174 void cMediamvpTransceiver::Action(void)
175 {
176         int max = 0;
177
178
179         printf("Mediamvp: Transceiver thread started (pid=%d)", getpid());
180
181
182         m_Active = true;
183
184         while (m_Active) {
185                 int recvd;
186                 const uchar *block = m_RingBuffer->Get(recvd);
187
188                 if (block && recvd > 0) {
189                         const uchar *sendBlock;
190                         int bytes = 0;
191                         int taken = recvd;
192
193             sendBlock = m_Remux->Process(block, taken, bytes);
194
195                         m_RingBuffer->Del(taken);
196
197                         if (bytes > max)
198                                 max = bytes;
199       // CJT
200
201        //     write(m_Socket,sendBlock,bytes);
202       //      printf("Written %i bytes\n", bytes);
203
204
205       pthread_mutex_lock(&ringLock);
206       rb.put((unsigned char*)sendBlock, bytes);
207       pthread_mutex_unlock(&ringLock);
208 //printf("Put %i into buffer\n", bytes);
209
210
211                 } else
212                         usleep(1);
213         }
214
215
216         printf("Mediamvp: Transceiver thread ended");
217 }
218
219 unsigned long cMediamvpTransceiver::getBlock(unsigned char* buffer, unsigned long amount)
220 {
221   pthread_mutex_lock(&ringLock);
222
223   while ((unsigned long)rb.getContent() < amount)
224   {
225     pthread_mutex_unlock(&ringLock);
226     usleep(500000);
227     pthread_mutex_lock(&ringLock);
228   }
229
230   unsigned long amountReceived = rb.get(buffer, amount);
231   pthread_mutex_unlock(&ringLock);
232   return amountReceived;
233 }