Statistics
| Branch: | Tag: | Revision:

dvbd / src / demuxer.cpp @ 59be6a47

History | View | Annotate | Download (3.75 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "config.h"
20
#include "demuxer.h"
21
#include "tuner.h"
22
#include "connection.h"
23

    
24
#include <iostream>
25
#include <cstdlib>
26
#include <climits>
27

    
28
#include <sys/ioctl.h>
29
#include <stdio.h>
30
#include <stdint.h>
31
#include <sys/types.h>
32
#include <sys/stat.h>
33
#include <fcntl.h>
34
#include <time.h>
35
#include <unistd.h>
36

    
37
#include <linux/dvb/dmx.h>
38

    
39
static void set_ts_filt(int fd,uint16_t pid, dmx_pes_type_t pestype);
40

    
41
Demuxer::Demuxer(Tuner *tuner, int pid, Demuxer::PESType pestype)
42
  : tuner(tuner), pid(pid), demuxFD(-1)
43
{
44
  switch (pestype) {
45
  case Video: this->pesType = int(DMX_PES_VIDEO); break;
46
  case Audio: this->pesType = int(DMX_PES_AUDIO); break;
47
  case Teletext: this->pesType = int(DMX_PES_TELETEXT); break;
48
  }
49
}
50

    
51
Demuxer::~Demuxer()
52
{
53
  unsubscribeAll();
54
}
55

    
56
bool Demuxer::openDemux()
57
{
58
  std::string demuxDev = tuner->getDemuxerDevice();
59
  demuxFD = open(demuxDev.c_str(), O_RDWR);
60
  return (demuxFD >= 0);
61
}
62

    
63
void Demuxer::closeDemux()
64
{
65
  if (demuxFD >= 0) {
66
    ::close(demuxFD);
67
    demuxFD = -1;
68
  }
69
}
70

    
71
void Demuxer::setTSFilt( bool dmxOther )
72
{
73
  dmx_pes_type_t thePesType = 
74
    (dmxOther ? dmx_pes_type_t(pesType) : DMX_PES_OTHER);
75

    
76
  set_ts_filt(demuxFD, pid, thePesType);
77
}
78

    
79
bool Demuxer::subscribe(Sink *s)
80
{
81
  if (getNumSubscribers() == 0) {
82

    
83
    if (!openDemux()) {
84
      std::cerr << "Failed to open demuxer\n";
85
      return false;
86
    }
87

    
88
    // DVB Seems to like AUDIO / VIDEO only for the first two PIDs
89
    // otherwise OTHER must be used.
90

    
91
    bool dmxOther = (tuner->getNumSubscribers() >= 2);
92

    
93
    if (!tuner->subscribe(this)) {
94
      closeDemux();
95
      return false;
96
    }
97

    
98
    setTSFilt(dmxOther);
99

    
100
  }
101
  return Source::subscribe(s);
102
}
103

    
104
void Demuxer::unsubscribe(Sink *s) 
105
{
106
  Source::unsubscribe(s);
107
  if (getNumSubscribers() == 0) {
108
    close(demuxFD);
109
    tuner->unsubscribe(this);
110
  }
111
}
112

    
113
void Demuxer::notifyUnsubscribe(Source *)
114
{
115
  // This method is called when the tuner manager
116
  // forcefully unsubscribes demuxers from the channel.
117

    
118
  // Since our source is no longer available
119
  // we should unsubscribe the clients.
120

    
121
  unsubscribeAll();
122
}
123

    
124

    
125
// From transform.c (Marcus Metzler)
126
#define PID_MASK_HI 0x1F
127
static inline uint16_t get_pid(uint8_t *pid)
128
{
129
  uint16_t pp = 0;
130

    
131
  pp = (pid[0] & PID_MASK_HI)<<8;
132
  pp |= pid[1];
133

    
134
  return pp;
135
}
136

    
137
void Demuxer::receiveData(unsigned char *data, unsigned size)
138
{
139
  if (get_pid(data + 1) == pid)
140
    sendData(data, (unsigned) size);
141
}
142

    
143
static void set_ts_filt(int fd,uint16_t pid, dmx_pes_type_t pestype)
144
{
145
  // From Dave Chapman's dvbstream.c
146
  struct dmx_pes_filter_params pesFilterParams;
147

    
148
  pesFilterParams.pid     = pid;
149
  pesFilterParams.input   = DMX_IN_FRONTEND;
150
  pesFilterParams.output  = DMX_OUT_TS_TAP;
151
#ifdef NEWSTRUCT
152
  pesFilterParams.pes_type = pestype;
153
#else
154
  pesFilterParams.pesType = pestype;
155
#endif
156
  pesFilterParams.flags   = 0;
157

    
158
  if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0)  {
159
    fprintf(stderr,"FILTER %i: ",pid);
160
    perror("DMX SET PES FILTER");
161
  }
162

    
163
  if (ioctl(fd, DMX_START, &pesFilterParams) < 0)  {
164
    fprintf(stderr,"FILTER %i: ",pid);
165
    perror("DMX START");
166
  }
167
}