1 /*
2 * H.264 Plugin codec for OpenH323/OPAL
3 *
4 * Copyright (C) 2007 Matthias Schneider, All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #include "plugin-config.h"
23
24 #include "shared/pipes.h"
25 #include "enc-ctx.h"
26 #include <sys/stat.h>
27 #include <fstream>
28 #include "trace.h"
29 #include <stdlib.h>
30
31 #ifndef X264_LINK_STATIC
32 #include "x264loader_unix.h"
33 #endif
34
35 std::ifstream dlStream;
36 std::ofstream ulStream;
37
38 unsigned msg;
39 unsigned val;
40
41 unsigned srcLen = 0;
42 unsigned dstLen = 0;
43 unsigned headerLen;
44 unsigned frameBufferSize = 0;
45 unsigned char * src = NULL;
46 unsigned char * dst = NULL;
47 unsigned flags;
48 int ret;
49
50 X264EncoderContext* x264;
51
52 #ifndef X264_LINK_STATIC
53 extern X264Library X264Lib;
54 #endif
55
closeAndExit()56 void closeAndExit()
57 {
58 dlStream.close();
59 ulStream.close();
60 exit(1);
61 }
62
writeStream(std::ofstream & stream,const char * data,unsigned bytes)63 void writeStream (std::ofstream & stream, const char* data, unsigned bytes)
64 {
65 stream.write(data, bytes);
66 if (stream.bad()) { TRACE (1, "H264\tIPC\tCP: Bad flag set on writing - terminating"); closeAndExit(); }
67 }
68
readStream(std::ifstream & stream,char * data,unsigned bytes)69 void readStream (std::ifstream & stream, char* data, unsigned bytes)
70 {
71 stream.read(data, bytes);
72 if (stream.fail()) { TRACE (1, "H264\tIPC\tCP: Terminating"); closeAndExit(); }
73 if (stream.bad()) { TRACE (1, "H264\tIPC\tCP: Bad flag set on reading - terminating"); closeAndExit(); }
74 if (stream.eof()) { TRACE (1, "H264\tIPC\tCP: Received EOF - terminating"); closeAndExit(); }
75 }
76
flushStream(std::ofstream & stream)77 void flushStream (std::ofstream & stream)
78 {
79 stream.flush();
80 if (stream.bad()) { TRACE (1, "H264\tIPC\tCP: Bad flag set on flushing - terminating"); closeAndExit(); }
81 }
82
83
main(int argc,char * argv[])84 int main(int argc, char *argv[])
85 {
86 unsigned status;
87 if (argc != 3) { fprintf(stderr, "Not to be executed directly - exiting\n"); exit (1); }
88
89 char * debug_level = getenv ("PTLIB_TRACE_CODECS");
90 if (debug_level!=NULL) {
91 Trace::SetLevel(atoi(debug_level));
92 }
93 else {
94 Trace::SetLevel(0);
95 }
96
97 debug_level = getenv ("PTLIB_TRACE_CODECS_USER_PLANE");
98 if (debug_level!=NULL) {
99 Trace::SetLevelUserPlane(atoi(debug_level));
100 }
101 else {
102 Trace::SetLevelUserPlane(0);
103 }
104
105 x264 = NULL;
106 dstLen = 1400;
107 dlStream.open(argv[1], std::ios::binary);
108 if (dlStream.fail()) { TRACE (1, "H264\tIPC\tCP: Error when opening DL named pipe"); exit (1); }
109 ulStream.open(argv[2],std::ios::binary);
110 if (ulStream.fail()) { TRACE (1, "H264\tIPC\tCP: Error when opening UL named pipe"); exit (1); }
111
112 #ifndef X264_LINK_STATIC
113 if (X264Lib.Load())
114 status = 1;
115 else
116 status = 0;
117 #else
118 status = 1;
119 #endif
120
121 readStream(dlStream, (char*)&msg, sizeof(msg));
122 writeStream(ulStream,(char*)&msg, sizeof(msg));
123 writeStream(ulStream,(char*)&status, sizeof(status));
124 flushStream(ulStream);
125
126 if (status == 0) {
127 TRACE (1, "H264\tIPC\tCP: Failed to load dynamic library - exiting");
128 closeAndExit();
129 }
130
131 while (1) {
132 readStream(dlStream, (char*)&msg, sizeof(msg));
133
134 switch (msg) {
135 case H264ENCODERCONTEXT_CREATE:
136 x264 = new X264EncoderContext();
137 writeStream(ulStream,(char*)&msg, sizeof(msg));
138 flushStream(ulStream);
139 break;
140 case H264ENCODERCONTEXT_DELETE:
141 delete x264;
142 x264 = NULL;
143 writeStream(ulStream,(char*)&msg, sizeof(msg));
144 flushStream(ulStream);
145 break;
146 case APPLY_OPTIONS:
147 if (x264) {
148 x264->ApplyOptions ();
149 writeStream(ulStream,(char*)&msg, sizeof(msg));
150 flushStream(ulStream);
151 } else {
152 TRACE (1, "H264\tIPC\tCodec not created, yet");
153 }
154 break;
155 case SET_TARGET_BITRATE:
156 readStream(dlStream, (char*)&val, sizeof(val));
157 if (x264) {
158 x264->SetTargetBitrate (val);
159 writeStream(ulStream,(char*)&msg, sizeof(msg));
160 flushStream(ulStream);
161 } else {
162 TRACE (1, "H264\tIPC\tCodec not created, yet");
163 }
164 break;
165 case SET_FRAME_RATE:
166 readStream(dlStream, (char*)&val, sizeof(val));
167 if (x264) {
168 x264->SetFrameRate (val);
169 writeStream(ulStream,(char*)&msg, sizeof(msg));
170 flushStream(ulStream);
171 } else {
172 TRACE (1, "H264\tIPC\tCodec not created, yet");
173 }
174 break;
175 case SET_FRAME_WIDTH:
176 readStream(dlStream, (char*)&val, sizeof(val));
177 if (x264) {
178 x264->SetFrameWidth (val);
179 writeStream(ulStream,(char*)&msg, sizeof(msg));
180 flushStream(ulStream);
181 } else {
182 TRACE (1, "H264\tIPC\tCodec not created, yet");
183 }
184 break;
185 case SET_FRAME_HEIGHT:
186 readStream(dlStream, (char*)&val, sizeof(val));
187 if (x264) {
188 x264->SetFrameHeight (val);
189 writeStream(ulStream,(char*)&msg, sizeof(msg));
190 flushStream(ulStream);
191 } else {
192 TRACE (1, "H264\tIPC\tCodec not created, yet");
193 }
194 break;
195 case SET_MAX_KEY_FRAME_PERIOD:
196 readStream(dlStream, (char*)&val, sizeof(val));
197 if (x264) {
198 x264->SetMaxKeyFramePeriod (val);
199 writeStream(ulStream,(char*)&msg, sizeof(msg));
200 flushStream(ulStream);
201 } else {
202 TRACE (1, "H264\tIPC\tCodec not created, yet");
203 }
204 break;
205 case SET_TSTO:
206 readStream(dlStream, (char*)&val, sizeof(val));
207 if (x264) {
208 x264->SetTSTO (val);
209 writeStream(ulStream,(char*)&msg, sizeof(msg));
210 flushStream(ulStream);
211 } else {
212 TRACE (1, "H264\tIPC\tCodec not created, yet");
213 }
214 break;
215 case SET_PROFILE_LEVEL:
216 readStream(dlStream, (char*)&val, sizeof(val));
217 if (x264) {
218 x264->SetProfileLevel (val);
219 writeStream(ulStream,(char*)&msg, sizeof(msg));
220 flushStream(ulStream);
221 } else {
222 TRACE (1, "H264\tIPC\tCodec not created, yet");
223 }
224 break;
225 case ENCODE_FRAMES:
226 readStream(dlStream, (char*)&srcLen, sizeof(srcLen));
227 if (srcLen > frameBufferSize) {
228 // only grow, never shrink, memory isn't given back to OS anyway
229 TRACE (1, "H264\tIPC\tGrowing frame buffer to " << srcLen);
230 free(src);
231 free(dst);
232 frameBufferSize = srcLen;
233 src = (unsigned char*)malloc(frameBufferSize);
234 dst = (unsigned char*)malloc(frameBufferSize);
235 }
236 readStream(dlStream, (char*)src, srcLen);
237 readStream(dlStream, (char*)&headerLen, sizeof(headerLen));
238 readStream(dlStream, (char*)dst, headerLen);
239 readStream(dlStream, (char*)&flags, sizeof(flags));
240 // fall through intended
241 case ENCODE_FRAMES_BUFFERED:
242 if (x264) {
243 ret = (x264->EncodeFrames( src, srcLen, dst, dstLen, flags));
244 writeStream(ulStream,(char*)&msg, sizeof(msg));
245 writeStream(ulStream,(char*)&dstLen, sizeof(dstLen));
246 writeStream(ulStream,(char*)dst, dstLen);
247 writeStream(ulStream,(char*)&flags, sizeof(flags));
248 writeStream(ulStream,(char*)&ret, sizeof(ret));
249 flushStream(ulStream);
250 } else {
251 TRACE (1, "H264\tIPC\tCodec not created, yet");
252 }
253 break;
254 case SET_MAX_FRAME_SIZE:
255 readStream(dlStream, (char*)&val, sizeof(val));
256 if (x264) {
257 x264->SetMaxRTPFrameSize (val);
258 writeStream(ulStream,(char*)&msg, sizeof(msg));
259 flushStream(ulStream);
260 } else {
261 TRACE (1, "H264\tIPC\tCodec not created, yet");
262 }
263 break;
264 case FASTUPDATE_REQUESTED:
265 if (x264) {
266 x264->fastUpdateRequested();
267 writeStream(ulStream,(char*)&msg, sizeof(msg));
268 flushStream(ulStream);
269 } else {
270 TRACE (1, "H264\tIPC\tCodec not created, yet");
271 }
272 break;
273 case SET_MAX_NALSIZE:
274 readStream(dlStream, (char*)&val, sizeof(val));
275 if (x264) {
276 x264->SetMaxNALSize (val);
277 writeStream(ulStream,(char*)&msg, sizeof(msg));
278 flushStream(ulStream);
279 } else {
280 TRACE (1, "H264\tIPC\tCodec not created, yet");
281 }
282 break;
283 default:
284 break;
285 }
286 }
287 return 0;
288 }
289