fixed bug that audio in some of files does not played.
[vuplus_transtreamproxy] / src / main.cpp
1 /*
2  * main.cpp
3  *
4  *  Created on: 2013. 9. 12.
5  *      Author: kos
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <poll.h>
12 #include <stdlib.h>
13 #include <sys/ioctl.h>
14
15 #include <vector>
16 #include <string>
17 #include <iterator>
18 #include <fstream>
19
20 #include "ePreDefine.h"
21 #include "eURIDecoder.h"
22 #include "eFilePumpThread.h"
23 #include "eNetworkPumpThread.h"
24
25 #ifdef DEBUG_LOG
26 FILE* fpLog = fopen("/tmp/filestreamproxy.log", "w");
27 //#undef LOG
28 //#define LOG(X,...) { do{}while(0); }
29 #endif
30
31 using namespace std;
32 //-------------------------------------------------------------------------------
33
34 int gDeviceFd = 0;
35
36 char* ReadRequest(char* aRequest)
37 {
38         return fgets(aRequest, MAX_LINE_LENGTH-1, stdin);
39 }
40 //-------------------------------------------------------------------------------
41
42 namespace eParser {
43         int gVideoPid = 0, gAudioPid = 0;
44         std::vector<string> Split(std::string aBuffer, char aDelimiter);
45         void FileName(char* aRequest, char* aHttp, std::string& aOutData);
46         bool MetaData(std::string aMediaFileName);
47 };
48 using namespace eParser;
49 //-------------------------------------------------------------------------------
50
51 /* GET /file?file=/home/kos/work/workspace/filestreamproxy/data/20131023%200630%20-%20FASHION%20TV%20-%20instant%20record.ts HTTP/1.0 */
52 int main(int argc, char** argv)
53 {
54         char request[MAX_LINE_LENGTH] = {0};
55
56         if (!ReadRequest(request)) {
57                 RETURN_ERR_400();
58         }
59 #ifdef DEBUG_LOG
60         LOG("%s", request);
61 #endif
62
63         if (strncmp(request, "GET /", 5)) {
64                 RETURN_ERR_400();
65         }
66
67         char* http = strchr(request + 5, ' ');
68         if (!http || strncmp(http, " HTTP/1.", 7)) {
69                 RETURN_ERR_400("Not support request (%s).", http);
70         }
71
72         std::string srcfilename = "";
73         eParser::FileName(request, http, srcfilename);
74
75         bool isSuccessMeta = eParser::MetaData(srcfilename);
76
77 #ifdef DEBUG_LOG
78         LOG("meta parsing result : %d, video : %d, audio : %d", isSuccessMeta, eParser::gVideoPid, eParser::gAudioPid);
79 #endif
80
81         gDeviceFd = open("/dev/bcm_enc0", O_RDWR);
82         if(gDeviceFd < 0 ) {
83                 close(gDeviceFd);
84                 RETURN_ERR_502("Fail to opne device.");
85         }
86
87         if(isSuccessMeta) {
88                 if(ioctl(gDeviceFd, 1, eParser::gVideoPid)) {
89                         RETURN_ERR_502("Fail to set video pid");
90                 }
91                 if(ioctl(gDeviceFd, 2, eParser::gAudioPid)) {
92                         RETURN_ERR_502("Fail to set audio pid");
93                 }
94         }
95
96         eFilePumpThread filepump(gDeviceFd, srcfilename);
97         filepump.Start();
98
99         sleep(1);
100
101         if(ioctl(gDeviceFd, 100, 0)) {
102                 RETURN_ERR_502("Fail to start transcoding.");
103         }
104         eNetworkPumpThread networkpump(gDeviceFd);
105         networkpump.Start();
106
107         networkpump.Join();
108         filepump.Stop();
109         filepump.Join();
110
111         close(gDeviceFd);
112
113 #ifdef DEBUG_LOG
114         fclose(fpLog);
115 #endif
116         return 0;
117 }
118 //-------------------------------------------------------------------------------
119
120 std::vector<string> eParser::Split(std::string aBuffer, char aDelimiter)
121 {
122         int b = 0, i = 0, l = aBuffer.length();
123         std::vector<string> t;
124
125         while (i++ < l) {
126                 if (aBuffer[i] == aDelimiter) {
127                         t.push_back(aBuffer.substr(b, i-b));
128                         b = i + 1;
129                         continue;
130                 }
131                 if (i == (l - 1)) {
132                         t.push_back(aBuffer.substr(b, l));
133                 }
134         }
135         return t;
136 }
137 //-------------------------------------------------------------------------------
138
139 void eParser::FileName(char* aRequest, char* aHttp, std::string& aOutData)
140 {
141         char tmp[256] = {0};
142         char* file = aRequest + 5;
143         if (strncmp(file, "file?file=", strlen("file?file="))) {
144                 return;
145         }
146         strncpy(tmp, file+10, aHttp-file-10);
147         aOutData = eURIDecoder().Decode(tmp);
148 }
149 //-------------------------------------------------------------------------------
150
151 namespace eCacheID {
152         enum {
153                 cVPID = 0,
154                 cAPID,
155                 cTPID,
156                 cPCRPID,
157                 cAC3PID,
158                 cVTYPE,
159                 cACHANNEL,
160                 cAC3DELAY,
161                 cPCMDELAY,
162                 cSUBTITLE,
163                 cacheMax
164         };
165 };
166 //-------------------------------------------------------------------------------
167
168 /* f:40,c:00007b,c:01008f,c:03007b */
169 bool eParser::MetaData(std::string aMediaFileName)
170 {
171         std::string metafilename = aMediaFileName;
172         metafilename += ".meta";
173
174         std::ifstream ifs(metafilename.c_str());
175
176         if (!ifs.is_open()) {
177 #ifdef DEBUG_LOG
178                 LOG("metadata is not exists..");
179 #endif
180                 return false;
181         }
182
183         size_t rc = 0, i = 0;
184         char buffer[1024] = {0};
185         while (!ifs.eof()) {
186                 ifs.getline(buffer, 1024);
187                 if (i++ == 7) {
188 #ifdef DEBUG_LOG
189                                 LOG("%d [%s]", i, buffer);
190 #endif
191                         std::vector<string> tokens = eParser::Split(buffer, ',');
192                         if(tokens.size() < 3) {
193 #ifdef DEBUG_LOG
194                                 LOG("pid count size error : %d", tokens.size());
195 #endif
196                                 return false;
197                         }
198
199                         int setting_done = false;
200                         for (int ii = 0; ii < tokens.size(); ++ii) {
201                                 std::string token = tokens[ii];
202                                 if(token.at(0) != 'c') continue;
203
204                                 int cache_id = atoi(token.substr(2,2).c_str());
205 #ifdef DEBUG_LOG
206                                 LOG("token : %d [%s], chcke_id : [%d]", ii, token.c_str(), cache_id);
207 #endif
208                                 switch(cache_id) {
209                                         case(eCacheID::cVPID):
210                                                 gVideoPid = strtol(token.substr(4,4).c_str(), NULL, 16);
211 #ifdef DEBUG_LOG
212                                                 LOG("video pid : %d", gVideoPid);
213 #endif
214                                                 setting_done = (gVideoPid && gAudioPid) ? true : false;
215                                                 break;
216                                         case(eCacheID::cAC3PID):
217                                                 gAudioPid = strtol(token.substr(4,4).c_str(), NULL, 16);
218 #ifdef DEBUG_LOG
219                                                 LOG("audio pid : %d", gAudioPid);
220 #endif
221                                                 break;
222                                         case(eCacheID::cAPID):
223                                                 gAudioPid = strtol(token.substr(4,4).c_str(), NULL, 16);
224 #ifdef DEBUG_LOG
225                                                 LOG("audio pid : %d", gAudioPid);
226 #endif
227                                                 setting_done = (gVideoPid && gAudioPid) ? true : false;
228                                                 break;
229                                 }
230                                 if(setting_done) break;
231                         }
232                         break;
233                 }
234         }
235         ifs.close();
236         return true;
237 }
238 //-------------------------------------------------------------------------------