Fix backward compatibility.
[vuplus_transtreamproxy] / src / Encoder.cpp
1 /*
2  * Encoder.cpp
3  *
4  *  Created on: 2014. 6. 12.
5  *      Author: oskwon
6  */
7
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <errno.h>
11 #include <dirent.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <sys/ioctl.h>
16
17 #include "Util.h"
18 #include "Logger.h"
19 #include "Encoder.h"
20
21 using namespace std;
22 //----------------------------------------------------------------------
23
24 Encoder::Encoder() throw(trap)
25 {
26         encoder_id = fd = -1;
27         max_encodr_count = state = ENCODER_STAT_INIT;
28
29         DIR* d = opendir("/dev");
30         if (d != 0) {
31                 struct dirent* de;
32                 while ((de = readdir(d)) != 0) {
33                         if (strncmp("bcm_enc", de->d_name, 7) == 0) {
34                                 max_encodr_count++;
35                         }
36                 }
37                 closedir(d);
38         }
39
40         mSemId = 0;
41         mShmFd = 0;
42         mShmData = 0;
43
44         mSemName = "/tsp_session_sem";
45         mShmName = "/tsp_session_shm";
46         mShmSize = sizeof(Session) * max_encodr_count;
47
48         if (Open() == false)
49                 throw(trap("session ctrl init fail."));
50         DEBUG("shm-info : fd [%d], name [%s], size [%d], data [%p]", mShmFd, mShmName.c_str(), mShmSize, mShmData);
51         DEBUG("sem-info : id [%p], name [%s]", mSemId, mSemName.c_str());
52
53         std::vector<int> pidlist = Util::find_process_by_name("transtreamproxy", 0);
54
55         session_dump("before init.");
56
57         Wait();
58         for (int i = 0; i < max_encodr_count; i++) {
59                 if (mShmData[i].pid != 0) {
60                         int pid = mShmData[i].pid;
61                         if(session_terminated(pidlist, pid)) {
62                                 session_erase(pid);
63                         }
64                 }
65         }
66         Post();
67
68         int mypid = getpid();
69         std::string ipaddr = Util::host_addr();
70         if (session_already_exist(ipaddr) > 0) {
71                 encoder_id = session_update(ipaddr, mypid);
72         }
73         else {
74                 encoder_id = session_register(ipaddr, mypid);
75         }
76         DEBUG("encoder_device_id : %d", encoder_id);
77 }
78 //----------------------------------------------------------------------
79
80 Encoder::~Encoder()
81 {
82         Post();
83         if (fd != -1) {
84                 if (state == ENCODER_STAT_STARTED) {
85                         DEBUG("stop transcoding..");
86                         ioctl(IOCTL_STOP_TRANSCODING, 0);
87                 }
88                 close(fd);
89                 fd = -1;
90         }
91 }
92 //----------------------------------------------------------------------
93
94 bool Encoder::encoder_open()
95 {
96         std::string path = "/dev/bcm_enc" + Util::ultostr(encoder_id);
97         fd = ::open(path.c_str(), O_RDWR, 0);
98         if (fd >= 0) {
99                 state = ENCODER_STAT_OPENED;
100         }
101         DEBUG("open encoder : %s, fd : %d", path.c_str(), fd);
102         return (state == ENCODER_STAT_OPENED) ? true : false;
103 }
104 //----------------------------------------------------------------------
105
106 bool Encoder::retry_open(int retry_count, int sleep_time)
107 {
108         for (int i = 0; i < retry_count; ++i) {
109                 if (encoder_open()) {
110                         DEBUG("encoder-%d open success..", encoder_id);
111                         return true;
112                 }
113                 WARNING("encoder%d open fail, retry count : %d/%d", encoder_id, i, retry_count);
114                 sleep(sleep_time);
115         }
116         ERROR("encoder open fail : %s (%d)", strerror(errno), errno);
117         return false;
118 }
119 //----------------------------------------------------------------------
120
121 bool Encoder::ioctl(int cmd, int value)
122 {
123         int result = ::ioctl(fd, cmd, value);
124         DEBUG("ioctl command : %d -> %x, result : %d", cmd, value, result);
125
126         if (result == 0) {
127                 switch (cmd) {
128                 case IOCTL_START_TRANSCODING: state = ENCODER_STAT_STARTED; break;
129                 case IOCTL_STOP_TRANSCODING:  state = ENCODER_STAT_STOPED;  break;
130                 }
131         }
132
133         return (result == 0) ? true : false;
134 }
135 //----------------------------------------------------------------------
136
137 int Encoder::get_fd()
138 {
139         return fd;
140 }
141 //----------------------------------------------------------------------
142
143 void Encoder::session_dump(const char* aMessage)
144 {
145         if (Logger::instance()->get_level() >= Logger::INFO) {
146                 DUMMY(" >> %s", aMessage);
147                 DUMMY("-------- [ DUMP HOST INFO ] ---------");
148                 for (int i = 0; i < max_encodr_count; i++) {
149                         DUMMY("%d : ip [%s], pid [%d]", i,  mShmData[i].ip, mShmData[i].pid);
150                 }
151                 DUMMY("-------------------------------------");
152         }
153 }
154 //----------------------------------------------------------------------
155
156 bool Encoder::session_terminated(std::vector<int>& aList, int aPid)
157 {
158         for (int i = 0; i < aList.size(); ++i) {
159                 if (aList[i] == aPid) {
160                         return false;
161                 }
162         }
163         return true;
164 }
165 //----------------------------------------------------------------------
166
167 int Encoder::session_register(std::string aIpAddr, int aPid)
168 {
169         int i = 0;
170         bool result = false;
171
172         Wait();
173         for (; i < max_encodr_count; i++) {
174                 if (mShmData[i].pid == 0) {
175                         result = true;
176                         mShmData[i].pid = aPid;
177                         strcpy(mShmData[i].ip, aIpAddr.c_str());
178                         break;
179                 }
180         }
181         Post();
182         session_dump("after register.");
183
184         return result ? i : -1;
185 }
186 //----------------------------------------------------------------------
187
188 void Encoder::session_unregister(std::string aIpAddr)
189 {
190         Wait();
191         for (int i = 0; i < max_encodr_count; i++) {
192                 if (strcmp(mShmData[i].ip, aIpAddr.c_str()) == 0) {
193                         memset(mShmData[i].ip, 0, 16);
194                         mShmData[i].pid = 0;
195                         break;
196                 }
197         }
198         Post();
199         session_dump("after unregister.");
200 }
201 //----------------------------------------------------------------------
202
203 void Encoder::session_erase(int aPid)
204 {
205         for (int i = 0; i < max_encodr_count; i++) {
206                 if (mShmData[i].pid == aPid) {
207                         DEBUG("erase.. %s : %d", mShmData[i].ip, mShmData[i].pid);
208                         memset(mShmData[i].ip, 0, 16);
209                         mShmData[i].pid = 0;
210                         break;
211                 }
212         }
213 }
214 //----------------------------------------------------------------------
215
216 int Encoder::session_update(std::string aIpAddr, int aPid)
217 {
218         int i = 0;
219         bool result = false;
220
221         session_dump("before update.");
222         Wait();
223         for (; i < max_encodr_count; i++) {
224                 if (strcmp(mShmData[i].ip, aIpAddr.c_str()) == 0) {
225                         result = true;
226                         Util::kill_process(mShmData[i].pid);
227                         memset(mShmData[i].ip, 0, 16);
228                         mShmData[i].pid = 0;
229                         break;
230                 }
231         }
232         Post();
233         session_register(aIpAddr, aPid);
234         return result ? i : -1;
235 }
236 //----------------------------------------------------------------------
237
238 int Encoder::session_already_exist(std::string aIpAddr)
239 {
240         int existCount = 0;
241         Wait();
242         for (int i = 0; i < max_encodr_count; i++) {
243                 if (strcmp(mShmData[i].ip, aIpAddr.c_str()) == 0) {
244                         existCount++;
245                 }
246         }
247         Post();
248         return existCount;
249 }
250 //----------------------------------------------------------------------