3b59b07a91f78efcaf171e31c908e859348ec0b0
[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 "Utils.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 = 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 = get_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         if (fd != -1) {
83                 if (state == ENCODER_STAT_STARTED) {
84                         DEBUG("stop transcoding..");
85                         ioctl(IOCTL_STOP_TRANSCODING, 0);
86                 }
87                 close(fd);
88                 fd = -1;
89         }
90 }
91 //----------------------------------------------------------------------
92
93 bool Encoder::encoder_open()
94 {
95         std::string path = "/dev/bcm_enc" + ultostr(encoder_id);
96         fd = ::open(path.c_str(), O_RDWR, 0);
97         if (fd >= 0) {
98                 state = ENCODER_STAT_OPENED;
99         }
100         DEBUG("open encoder : %s, fd : %d", path.c_str(), fd);
101         return (state == ENCODER_STAT_OPENED) ? true : false;
102 }
103 //----------------------------------------------------------------------
104
105 bool Encoder::retry_open(int retry_count, int sleep_time)
106 {
107         for (int i = 0; i < retry_count; ++i) {
108                 if (encoder_open()) {
109                         DEBUG("encoder-%d open success..", encoder_id);
110                         return true;
111                 }
112                 WARNING("encoder%d open fail, retry count : %d/%d", encoder_id, i, retry_count);
113                 sleep(sleep_time);
114         }
115         ERROR("encoder open fail : %s (%d)", strerror(errno), errno);
116         return false;
117 }
118 //----------------------------------------------------------------------
119
120 bool Encoder::ioctl(int cmd, int value)
121 {
122         int result = ::ioctl(fd, cmd, value);
123         DEBUG("ioctl command : %d -> %x, result : %d", cmd, value, result);
124
125         if (result == 0) {
126                 switch (cmd) {
127                 case IOCTL_START_TRANSCODING: state = ENCODER_STAT_STARTED; break;
128                 case IOCTL_STOP_TRANSCODING:  state = ENCODER_STAT_STOPED;  break;
129                 }
130         }
131
132         return (result == 0) ? true : false;
133 }
134 //----------------------------------------------------------------------
135
136 int Encoder::get_fd()
137 {
138         return fd;
139 }
140 //----------------------------------------------------------------------
141
142 void Encoder::session_dump(const char* aMessage)
143 {
144         DUMMY(" >> %s", aMessage);
145         DUMMY("-------- [ DUMP HOST INFO ] ---------");
146         for (int i = 0; i < max_encodr_count; i++) {
147                 DUMMY("%d : ip [%s], pid [%d]", i,  mShmData[i].ip, mShmData[i].pid);
148         }
149         DUMMY("-------------------------------------");
150 }
151 //----------------------------------------------------------------------
152
153 bool Encoder::session_terminated(std::vector<int>& aList, int aPid)
154 {
155         for (int i = 0; i < aList.size(); ++i) {
156                 if (aList[i] == aPid) {
157                         return false;
158                 }
159         }
160         return true;
161 }
162 //----------------------------------------------------------------------
163
164 int Encoder::session_register(std::string aIpAddr, int aPid)
165 {
166         int i = 0;
167         bool result = false;
168
169         Wait();
170         for (; i < max_encodr_count; i++) {
171                 if (mShmData[i].pid == 0) {
172                         result = true;
173                         mShmData[i].pid = aPid;
174                         strcpy(mShmData[i].ip, aIpAddr.c_str());
175                         break;
176                 }
177         }
178         Post();
179         session_dump("after register.");
180
181         return result ? i : -1;
182 }
183 //----------------------------------------------------------------------
184
185 void Encoder::session_unregister(std::string aIpAddr)
186 {
187         Wait();
188         for (int i = 0; i < max_encodr_count; i++) {
189                 if (strcmp(mShmData[i].ip, aIpAddr.c_str()) == 0) {
190                         memset(mShmData[i].ip, 0, 16);
191                         mShmData[i].pid = 0;
192                         break;
193                 }
194         }
195         Post();
196         session_dump("after unregister.");
197 }
198 //----------------------------------------------------------------------
199
200 void Encoder::session_erase(int aPid)
201 {
202         for (int i = 0; i < max_encodr_count; i++) {
203                 if (mShmData[i].pid == aPid) {
204                         DEBUG("erase.. %s : %d", mShmData[i].ip, mShmData[i].pid);
205                         memset(mShmData[i].ip, 0, 16);
206                         mShmData[i].pid = 0;
207                         break;
208                 }
209         }
210 }
211 //----------------------------------------------------------------------
212
213 int Encoder::session_update(std::string aIpAddr, int aPid)
214 {
215         int i = 0;
216         bool result = false;
217
218         session_dump("before update.");
219         Wait();
220         for (; i < max_encodr_count; i++) {
221                 if (strcmp(mShmData[i].ip, aIpAddr.c_str()) == 0) {
222                         result = true;
223                         kill_process(mShmData[i].pid);
224                         memset(mShmData[i].ip, 0, 16);
225                         mShmData[i].pid = 0;
226                         break;
227                 }
228         }
229         Post();
230         session_register(aIpAddr, aPid);
231         return result ? i : -1;
232 }
233 //----------------------------------------------------------------------
234
235 int Encoder::session_already_exist(std::string aIpAddr)
236 {
237         int existCount = 0;
238         Wait();
239         for (int i = 0; i < max_encodr_count; i++) {
240                 if (strcmp(mShmData[i].ip, aIpAddr.c_str()) == 0) {
241                         existCount++;
242                 }
243         }
244         Post();
245         return existCount;
246 }
247 //----------------------------------------------------------------------