]> git.vomp.tv Git - vompserver.git/blob - transceiver.c
Initial import
[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 cMediamvpTransceiver::cMediamvpTransceiver(const cChannel *Channel, int Priority, int Socket, cDevice *Device) :
42                 cReceiver(Channel->Ca(), Priority, 7, Channel->Vpid(), Channel->Ppid(),
43                                 Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2(),
44                                 Channel->Tpid()) {
45         m_Active = false;
46         m_Socket = Socket;
47         m_Remux = NULL;
48         m_Device = Device;
49
50         m_RingBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
51 //        m_RingBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 20, true);
52
53     /* Select the correct Muxing depending on whether it's video or not */
54     if ( Channel->Vpid() == 0 || Channel->Vpid() == 1 || Channel->Vpid() == 0x1FFF ) {
55         m_Remux = new cTS2ESRemux(Channel->Apid1());
56     } else {
57                 m_Remux = new cTS2PSRemux(Channel->Vpid(), Channel->Apid1(), 0, 0, 0, 0);
58     }
59     printf("Created transceiver at %p, remux @%p ringbuffer %p\n",this,m_Remux,m_RingBuffer);
60
61     /* Suggested by Peter Wagner to assist single DVB card systems */
62 #ifdef SINGLE_DEVICE
63         m_Device->SwitchChannel(Channel, true);
64 #else
65         m_Device->SwitchChannel(Channel, false);
66 #endif
67         Attach();
68
69
70         // CJT
71         rb.init(1000000);
72         pthread_mutex_init(&ringLock, NULL);
73
74 }
75
76 cMediamvpTransceiver::~cMediamvpTransceiver(void)
77 {
78     printf("Deleting transceiver at %p, remux @%p ringbuffer %p\n",this,m_Remux,m_RingBuffer);
79
80         Detach();
81         if (m_Remux)
82         delete m_Remux;
83     m_Remux = NULL;
84     if ( m_RingBuffer)
85         delete m_RingBuffer;
86     m_RingBuffer = NULL;
87 }
88
89 void cMediamvpTransceiver::Activate(bool On)
90 {
91         if (On)
92                 Start();
93         else if (m_Active)
94                 Stop();
95 }
96
97 void cMediamvpTransceiver::Stop(void)
98 {
99         if (m_Active) {
100                 m_Active = false;
101                 usleep(50000);
102                 Cancel(0);
103         }
104 }
105
106 void cMediamvpTransceiver::Receive(uchar *Data, int Length)
107 {
108         static time_t firsterr = 0;
109         static int errcnt = 0;
110         static bool showerr = true;
111
112         if (m_Active) {
113                 int p = m_RingBuffer->Put(Data, Length);
114                 if (p != Length) {
115                         ++errcnt;
116                         if (showerr) {
117                                 if (firsterr == 0)
118                                         firsterr = time_ms();
119                                 else if (firsterr + BUFOVERTIME > time_ms() && errcnt > BUFOVERCOUNT) {
120                                         esyslog("ERROR: too many buffer overflows, logging stopped");
121                                         showerr = false;
122                                         firsterr = time_ms();
123                                 }
124                         } else if (firsterr + BUFOVERTIME < time_ms()) {
125                                 showerr = true;
126                                 firsterr = 0;
127                                 errcnt = 0;
128                         }
129
130                         if (showerr)
131                                 esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length - p);
132                         else
133                                 firsterr = time_ms();
134                 }
135         }
136 }
137
138 void cMediamvpTransceiver::Action(void)
139 {
140         int max = 0;
141
142
143         printf("Mediamvp: Transceiver thread started (pid=%d)", getpid());
144
145
146         m_Active = true;
147
148         while (m_Active) {
149                 int recvd;
150                 const uchar *block = m_RingBuffer->Get(recvd);
151
152                 if (block && recvd > 0) {
153                         const uchar *sendBlock;
154                         int bytes = 0;
155                         int taken = recvd;
156
157             sendBlock = m_Remux->Process(block, taken, bytes);
158
159                         m_RingBuffer->Del(taken);
160
161                         if (bytes > max)
162                                 max = bytes;
163       // CJT
164
165        //     write(m_Socket,sendBlock,bytes);
166       //      printf("Written %i bytes\n", bytes);
167
168
169       pthread_mutex_lock(&ringLock);
170       rb.put((unsigned char*)sendBlock, bytes);
171       pthread_mutex_unlock(&ringLock);
172 //printf("Put %i into buffer\n", bytes);
173
174
175                 } else
176                         usleep(1);
177         }
178
179
180         printf("Mediamvp: Transceiver thread ended");
181 }
182
183 unsigned long cMediamvpTransceiver::getBlock(unsigned char* buffer, unsigned long amount)
184 {
185   pthread_mutex_lock(&ringLock);
186
187   while ((unsigned long)rb.getContent() < amount)
188   {
189     pthread_mutex_unlock(&ringLock);
190     usleep(500000);
191     pthread_mutex_lock(&ringLock);
192   }
193
194   unsigned long amountReceived = rb.get(buffer, amount);
195   pthread_mutex_unlock(&ringLock);
196   return amountReceived;
197 }