4 * Created on: 2014. 6. 11.
12 #include <sys/ioctl.h>
13 #include <arpa/inet.h>
14 #include <netinet/ip.h>
15 #include <linux/dvb/dmx.h>
16 #include <linux/dvb/version.h>
23 //-------------------------------------------------------------------------------
25 std::string Demuxer::webif_reauest(std::string service, std::string auth) throw(trap)
27 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
28 throw(trap("webif create socket fail."));
30 struct sockaddr_in sock_addr;
31 sock_addr.sin_family = AF_INET;
32 sock_addr.sin_port = htons(80);
33 sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
34 if (connect(sock, (struct sockaddr*)&sock_addr, sizeof(struct sockaddr_in)))
35 throw(trap("webif connect fail."));
37 std::string request = string("GET /web/stream?StreamService=") + service + " HTTP/1.0\r\n";
39 request += "Authorization: " + auth + "\r\n";
42 if (write(sock, request.c_str(), request.length()) != request.length())
43 throw(trap("webif send(request) fail."));
44 DEBUG("webif request :\n", request.c_str());
46 std::string response = "";
47 struct pollfd pollevt[2];
49 pollevt[0].events = POLLIN;
51 char buffer[1024] = {0};
53 pollevt[0].revents = 0;
54 int poll_state = poll(pollevt, 1, 1000);
57 else if (poll_state < 0) {
58 ERROR("webif receive poll error : %s (%d)", strerror(errno), errno);
59 throw(trap("webif receive response error."));
61 if (pollevt[0].revents & POLLIN) {
62 if (read(sock, buffer, 1024) <= 0) {
70 //-------------------------------------------------------------------------------
72 bool Demuxer::already_exist(std::vector<unsigned long> &pidlist, int pid)
74 for(int i = 0; i < pidlist.size(); ++i) {
80 //-------------------------------------------------------------------------------
82 void Demuxer::set_filter(std::vector<unsigned long> &new_pids) throw(trap)
84 struct dmx_pes_filter_params filter;
85 ioctl(fd, DMX_SET_BUFFER_SIZE, 1024*1024);
87 filter.pid = new_pids[0];
88 filter.input = DMX_IN_FRONTEND;
89 #if DVB_API_VERSION > 3
90 filter.output = DMX_OUT_TSDEMUX_TAP;
91 filter.pes_type = DMX_PES_OTHER;
93 filter.output = DMX_OUT_TAP;
94 filter.pes_type = DMX_TAP_TS;
96 filter.flags = DMX_IMMEDIATE_START;
98 if (::ioctl(fd, DMX_SET_PES_FILTER, &filter) < 0)
99 throw(trap("demux filter setting failed."));
100 DEBUG("demux filter setting ok.");
102 for(int i = 0; i < new_pids.size(); ++i) {
103 uint16_t pid = new_pids[i];
105 if(already_exist(pids, pid))
107 LOG("demux add pid (%x).", pid);
109 #if DVB_API_VERSION > 3
110 if (::ioctl(fd, DMX_ADD_PID, &pid) < 0)
111 throw(trap("demux add pid failed."));
113 if (::ioctl(fd, DMX_ADD_PID, pid) < 0)
114 throw(trap("demux add pid failed."));
118 for(int i = 0; i < pids.size(); ++i) {
119 uint16_t pid = pids[i];
120 if(already_exist(new_pids, pid))
124 LOG("demux remove pid (%x).", pid);
125 #if DVB_API_VERSION > 3
126 ::ioctl(fd, DMX_REMOVE_PID, &pid);
128 ::ioctl(fd, DMX_REMOVE_PID, pid);
131 DEBUG("demux setting PID ok.");
134 //-------------------------------------------------------------------------------
136 bool Demuxer::parse_webif_response(std::string& response, std::vector<unsigned long> &new_pids)
138 int start_idx, end_idx;
139 if ((start_idx = response.rfind('+')) == string::npos)
141 if ((end_idx = response.find('\n', start_idx)) == string::npos)
144 std::string line = response.substr(start_idx, end_idx - start_idx);
145 if (line.length() < 3 || line.at(0) != '+')
148 /*+0:0:pat,17d4:pmt,17de:video,17e8:audio,17e9:audio,17eb:audio,17ea:audio,17f3:subtitle,17de:pcr,17f2:text*/
149 demux_id = atoi(line.substr(1,1).c_str());
151 std::vector<std::string> pidtokens;
152 if (split(line.c_str() + 3, ',', pidtokens)) {
153 for (int i = 0; i < pidtokens.size(); ++i) {
154 std::string pidstr, pidtype;
155 std::string toekn = pidtokens[i];
156 if (!split_key_value(toekn, ":", pidstr, pidtype))
159 unsigned long pid = strtoul(pidstr.c_str(), 0, 0x10);
160 if (pid == -1) continue;
162 if (!video_pid || !audio_pid || !pmt_pid) {
163 if (pidtype == "pat") {
166 else if (pidtype == "pmt") {
169 else if (pidtype == "video") {
172 else if (pidtype == "audio") {
176 if (!already_exist(new_pids, pid)) {
177 new_pids.push_back(pid);
179 DEBUG("find pid : %s - %04X", toekn.c_str(), pid);
184 //-------------------------------------------------------------------------------
186 Demuxer::Demuxer(RequestHeader *header) throw(trap)
188 demux_id = pat_pid = fd = sock = -1;
189 pmt_pid = audio_pid = video_pid = 0;
191 std::string auth = header->params["WWW-Authenticate"];
192 std::string service = header->path.substr(1);
193 std::string webif_response = webif_reauest(service, auth);
194 DEBUG("webif response :\n%s", webif_response.c_str());
196 std::vector<unsigned long> new_pids;
197 if (!parse_webif_response(webif_response, new_pids))
198 throw(trap("webif response parsing fail."));
200 std::string demuxpath = "/dev/dvb/adapter0/demux" + ultostr(demux_id);
201 if ((fd = open(demuxpath.c_str(), O_RDWR | O_NONBLOCK)) < 0) {
202 throw(trap(std::string("demux open fail : ") + demuxpath));
204 INFO("demux open success : %s", demuxpath.c_str());
206 set_filter(new_pids);
208 //-------------------------------------------------------------------------------
210 Demuxer::~Demuxer() throw()
212 if (fd != -1) close(fd);
213 if (sock != -1) close(sock);
217 //-------------------------------------------------------------------------------
219 int Demuxer::get_fd() const throw()
223 //-------------------------------------------------------------------------------