Mercurial > mplayer.hg
annotate TOOLS/netstream.c @ 32860:77dd2bb3fd02
Make sure we don't store the same stats twice by nulling the first byte of the stats_out string once we have written it.
I've verified that this is necessary, without it at normally at least the last stats line is duplicated, it could also happen when we call encode_video more often due to encoder delay as Reimar noted.
Sample encode was with default -ovc lavc -lavcopts vpass=1:
--- pass1stats.log 2011-02-21 15:44:42.314259000 +0100
+++ pass1stats.log.dedup_patch 2011-02-21 15:41:51.262778000 +0100
@@ -6421,4 +6421,3 @@
in:6420 out:6420 type:2 q:239 itex:0 ptex:15905 mv:441 misc:1911 fcode:1 bcode:1 mc-var:989 var:350603 icount:0 skipcount:373 hbits:55;
in:6421 out:6421 type:2 q:247 itex:0 ptex:13020 mv:422 misc:1863 fcode:1 bcode:1 mc-var:953 var:352607 icount:0 skipcount:379 hbits:55;
in:6422 out:6422 type:2 q:252 itex:0 ptex:3162 mv:258 misc:1293 fcode:1 bcode:1 mc-var:837 var:352872 icount:0 skipcount:449 hbits:55;
-in:6422 out:6422 type:2 q:252 itex:0 ptex:3162 mv:258 misc:1293 fcode:1 bcode:1 mc-var:837 var:352872 icount:0 skipcount:449 hbits:55;
author | ranma |
---|---|
date | Mon, 21 Feb 2011 14:52:25 +0000 |
parents | 3fd6746f539c |
children | 08d53b704b88 |
rev | line source |
---|---|
22855 | 1 /* |
26743
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
2 * Copyright (C) Alban Bedel - 04/2003 |
22855 | 3 * |
26743
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
4 * This file is part of MPlayer. |
22855 | 5 * |
26743
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
6 * MPlayer is free software; you can redistribute it and/or modify |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
7 * it under the terms of the GNU General Public License as published by |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
8 * the Free Software Foundation; either version 2 of the License, or |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
9 * (at your option) any later version. |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
10 * |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
11 * MPlayer is distributed in the hope that it will be useful, |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
14 * GNU General Public License for more details. |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
15 * |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
16 * You should have received a copy of the GNU General Public License along |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
22855 | 19 */ |
20 | |
21 #include <stdlib.h> | |
22 #include <stdio.h> | |
23 #include <unistd.h> | |
24 #include <inttypes.h> | |
25 #include <errno.h> | |
26 #include <signal.h> | |
27 #include <sys/types.h> | |
28 | |
29 #include "config.h" | |
30 | |
28408 | 31 #if !HAVE_WINSOCK2_H |
22855 | 32 #include <sys/socket.h> |
33 #include <netinet/in.h> | |
34 #include <arpa/inet.h> | |
35 #else | |
36 #include <winsock2.h> | |
37 #include <ws2tcpip.h> | |
38 #endif | |
39 | |
40 #include "stream/stream.h" | |
41 #include "libmpdemux/demuxer.h" | |
42 #include "mp_msg.h" | |
43 #include "libavutil/common.h" | |
44 #include "mpbswap.h" | |
45 | |
46 /// Netstream packets def and some helpers | |
27745
a5ed200519dc
Rename stream/netstream.h to stream/stream_netstream.h; netstream.h to make it
diego
parents:
27663
diff
changeset
|
47 #include "stream/stream_netstream.h" |
22855 | 48 |
26963
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
49 // linking hacks |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
50 char *info_name; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
51 char *info_artist; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
52 char *info_genre; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
53 char *info_subject; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
54 char *info_copyright; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
55 char *info_sourceform; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
56 char *info_comment; |
22855 | 57 |
26963
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
58 char* out_filename = NULL; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
59 char* force_fourcc=NULL; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
60 char* passtmpfile="divx2pass.log"; |
22855 | 61 |
62 static unsigned short int port = 10000; | |
63 | |
64 typedef struct client_st client_t; | |
65 struct client_st { | |
66 int fd; | |
67 stream_t* stream; | |
68 client_t* next; | |
69 client_t* prev; | |
70 }; | |
71 | |
72 static int write_error(int fd,char* msg) { | |
73 int len = strlen(msg) + 1; | |
74 return write_packet(fd,NET_STREAM_ERROR,msg,len); | |
75 } | |
76 | |
77 static int net_stream_open(client_t* cl,char* url) { | |
78 int file_format=DEMUXER_TYPE_UNKNOWN; | |
79 mp_net_stream_opened_t ret; | |
80 | |
81 if(cl->stream) { | |
82 if(!write_error(cl->fd,"A stream is currently opened\n")) | |
83 return 0; | |
84 return 1; | |
85 } | |
86 | |
87 mp_msg(MSGT_NETST,MSGL_V,"Open stream %s\n",url); | |
88 cl->stream = open_stream(url,NULL,&file_format); | |
89 if(!cl->stream) { | |
90 if(!write_error(cl->fd,"Open failed\n")) | |
91 return 0; | |
92 return 1; | |
93 } | |
94 stream_reset(cl->stream); | |
95 stream_seek(cl->stream,cl->stream->start_pos); | |
96 ret.file_format = file_format; | |
97 ret.flags = cl->stream->flags; | |
98 ret.sector_size = cl->stream->sector_size; | |
99 ret.start_pos = cl->stream->start_pos; | |
100 ret.end_pos = cl->stream->end_pos; | |
101 net_stream_opened_2_me(&ret); | |
102 | |
103 if(!write_packet(cl->fd,NET_STREAM_OK,(char*)&ret,sizeof(mp_net_stream_opened_t))) | |
104 return 0; | |
105 return 1; | |
106 } | |
107 | |
108 static int net_stream_fill_buffer(client_t* cl,uint16_t max_len) { | |
109 int r; | |
110 mp_net_stream_packet_t *pack; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28408
diff
changeset
|
111 |
22855 | 112 if(!cl->stream) { |
113 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
114 return 0; | |
115 return 1; | |
116 } | |
117 if(max_len == 0) { | |
24595 | 118 if(!write_error(cl->fd,"Fill buffer called with 0 length\n")) |
22855 | 119 return 0; |
120 return 1; | |
121 } | |
122 pack = malloc(max_len + sizeof(mp_net_stream_packet_t)); | |
123 pack->cmd = NET_STREAM_OK; | |
124 r = stream_read(cl->stream,pack->data,max_len); | |
125 pack->len = le2me_16(r + sizeof(mp_net_stream_packet_t)); | |
126 if(!net_write(cl->fd,(char*)pack,le2me_16(pack->len))) { | |
127 free(pack); | |
128 return 0; | |
129 } | |
130 free(pack); | |
131 return 1; | |
132 } | |
133 | |
134 static int net_stream_seek(client_t* cl, uint64_t pos) { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28408
diff
changeset
|
135 |
22855 | 136 if(!cl->stream) { |
137 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
138 return 0; | |
139 return 1; | |
140 } | |
141 | |
142 if(!stream_seek(cl->stream,(off_t)pos)) { | |
143 if(!write_error(cl->fd,"Seek failed\n")) | |
144 return 0; | |
145 return 1; | |
146 } | |
147 if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) | |
148 return 0; | |
149 return 1; | |
150 } | |
151 | |
152 static int net_stream_reset(client_t* cl) { | |
153 if(!cl->stream) { | |
154 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
155 return 0; | |
156 return 1; | |
157 } | |
158 stream_reset(cl->stream); | |
159 if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) | |
160 return 0; | |
161 return 1; | |
162 } | |
163 | |
164 static int net_stream_close(client_t* cl) { | |
165 if(!cl->stream) { | |
166 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
167 return 0; | |
168 return 1; | |
169 } | |
170 | |
171 free_stream(cl->stream); | |
172 cl->stream = NULL; | |
173 | |
174 if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) | |
175 return 0; | |
176 return 1; | |
177 } | |
178 | |
26575
1ca484e74f18
Mark all functions that are only used within the file as static.
diego
parents:
25310
diff
changeset
|
179 static int handle_client(client_t* cl,mp_net_stream_packet_t* pack) { |
22855 | 180 |
181 if(!pack) | |
182 return 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28408
diff
changeset
|
183 |
22855 | 184 switch(pack->cmd) { |
185 case NET_STREAM_OPEN: | |
186 if(((char*)pack)[pack->len-1] != '\0') { | |
187 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid open packet\n"); | |
188 return 0; | |
189 } | |
190 return net_stream_open(cl,pack->data); | |
191 case NET_STREAM_FILL_BUFFER: | |
192 if(pack->len != sizeof(mp_net_stream_packet_t) + 2) { | |
193 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); | |
194 return 0; | |
195 } | |
196 return net_stream_fill_buffer(cl,le2me_16(*((uint16_t*)pack->data))); | |
197 case NET_STREAM_SEEK: | |
198 if(pack->len != sizeof(mp_net_stream_packet_t) + 8) { | |
199 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); | |
200 return 0; | |
201 } | |
202 return net_stream_seek(cl,le2me_64(*((uint64_t*)pack->data))); | |
203 case NET_STREAM_RESET: | |
204 return net_stream_reset(cl); | |
205 case NET_STREAM_CLOSE: | |
206 if(pack->len != sizeof(mp_net_stream_packet_t)){ | |
207 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); | |
208 return 0; | |
209 } | |
210 return net_stream_close(cl); | |
211 default: | |
212 mp_msg(MSGT_NETST,MSGL_WARN,"Got unknown command %d\n",pack->cmd); | |
213 if(!write_error(cl->fd,"Unknown command\n")) | |
214 return 0; | |
215 } | |
216 return 0; | |
217 } | |
218 | |
219 static client_t* add_client(client_t *head,int fd) { | |
220 client_t *new = calloc(1,sizeof(client_t)); | |
221 new->fd = fd; | |
222 if(!head) return new; | |
223 new->next = head; | |
224 head->prev = new; | |
225 return new; | |
226 } | |
227 | |
228 static int make_fd_set(fd_set* fds, client_t** _cl, int listen) { | |
229 int max_fd = listen; | |
230 client_t *cl = *_cl; | |
231 FD_ZERO(fds); | |
232 FD_SET(listen,fds); | |
233 while(cl) { | |
234 // Remove this client | |
235 if(cl->fd < 0) { | |
236 client_t* f = cl; | |
237 if(cl->prev) cl->prev->next = cl->next; | |
238 if(cl->next) cl->next->prev = cl->prev; | |
239 if(cl->stream) free_stream(cl->stream); | |
240 if(!cl->prev) // Remove the head | |
241 *_cl = cl->next; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28408
diff
changeset
|
242 cl = cl->next; |
22855 | 243 free(f); |
244 continue; | |
245 } | |
246 FD_SET(cl->fd,fds); | |
247 if(cl->fd > max_fd) max_fd = cl->fd; | |
248 cl = cl->next; | |
249 } | |
250 return max_fd+1; | |
251 } | |
252 | |
253 /// Hack to 'cleanly' exit | |
254 static int run_server = 1; | |
255 | |
31337
3fd6746f539c
Mark exit_sig() function as static; it is only used within the file.
diego
parents:
29263
diff
changeset
|
256 static void exit_sig(int sig) { |
22855 | 257 static int count = 0; |
258 sig++; // gcc warning | |
259 count++; | |
260 if(count==3) exit(1); | |
261 if(count > 3) | |
262 #ifdef __MINGW32__ | |
263 WSACleanup(); | |
264 #else | |
265 kill(getpid(),SIGKILL); | |
266 #endif | |
267 run_server = 0; | |
268 } | |
269 | |
270 static int main_loop(int listen_fd) { | |
271 client_t *clients = NULL,*iter; | |
272 fd_set fds; | |
273 | |
274 signal(SIGTERM,exit_sig); // kill | |
275 #ifndef __MINGW32__ | |
276 signal(SIGHUP,exit_sig); // kill -HUP / xterm closed | |
277 signal(SIGINT,exit_sig); // Interrupt from keyboard | |
278 signal(SIGQUIT,exit_sig); // Quit from keyboard | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28408
diff
changeset
|
279 #endif |
22855 | 280 |
281 while(run_server) { | |
282 int sel_n = make_fd_set(&fds,&clients,listen_fd); | |
283 int n = select(sel_n,&fds,NULL,NULL,NULL); | |
284 if(n < 0) { | |
285 if(errno == EINTR) | |
286 continue; | |
287 mp_msg(MSGT_NETST,MSGL_FATAL,"Select error: %s\n",strerror(errno)); | |
288 return 1; | |
289 } | |
290 // New connection | |
291 if(FD_ISSET(listen_fd,&fds)) { | |
292 struct sockaddr_in addr; | |
293 socklen_t slen = sizeof(struct sockaddr_in); | |
294 int client_fd = accept(listen_fd,(struct sockaddr*)&addr,&slen); | |
295 if(client_fd < 0) { | |
296 mp_msg(MSGT_NETST,MSGL_ERR,"accept failed: %s\n",strerror(errno)); | |
297 continue; | |
298 } | |
299 mp_msg(MSGT_NETST,MSGL_V,"New client from %s\n",inet_ntoa(addr.sin_addr)); | |
300 clients = add_client(clients,client_fd); | |
301 if(n == 1) continue; | |
302 } | |
303 // Look for the clients | |
304 for(iter = clients ; iter ; iter = iter->next) { | |
305 mp_net_stream_packet_t* pack; | |
306 if(!FD_ISSET(iter->fd,&fds)) continue; | |
307 pack = read_packet(iter->fd); | |
308 if(!pack) { | |
309 close(iter->fd); | |
310 iter->fd = -1; | |
311 continue; | |
312 } | |
313 if(!handle_client(iter,pack)) { | |
314 close(iter->fd); | |
315 iter->fd = -1; | |
316 } | |
317 free(pack); | |
318 } | |
319 } | |
320 mp_msg(MSGT_NETST,MSGL_INFO,"Exit ....\n"); | |
321 close(listen_fd); | |
322 #ifdef __MINGW32__ | |
323 WSACleanup(); | |
324 #endif | |
325 while(clients) { | |
326 client_t* f = clients; | |
327 if(f->stream) free_stream(f->stream); | |
328 if(f->fd > 0) close(f->fd); | |
329 free(f); | |
330 clients = clients->next; | |
331 } | |
332 return 0; | |
333 } | |
334 | |
25310
e3c5cd98d59a
Remove unused parameters from main(), fixes the warnings:
diego
parents:
24595
diff
changeset
|
335 int main(void) { |
22855 | 336 int listen_fd; |
337 struct sockaddr_in addr; | |
338 | |
339 mp_msg_init(); | |
340 // mp_msg_set_level(verbose+MSGL_STATUS); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28408
diff
changeset
|
341 |
22855 | 342 #ifdef __MINGW32__ |
343 WSADATA wsaData; | |
344 WSAStartup(MAKEWORD(1,1), &wsaData); | |
345 #endif | |
346 listen_fd = socket(AF_INET, SOCK_STREAM, 0); | |
347 if(listen_fd < 0) { | |
348 mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to create listen_fd: %s\n",strerror(errno)); | |
349 return -1; | |
350 } | |
351 memset(&addr,0,sizeof(struct sockaddr)); | |
352 addr.sin_addr.s_addr = INADDR_ANY; | |
353 addr.sin_port = htons(port); | |
354 addr.sin_family = AF_INET; | |
355 if(bind(listen_fd,(struct sockaddr*)&addr,sizeof(struct sockaddr))) { | |
356 mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to bind listen socket: %s\n",strerror(errno)); | |
357 return -1; | |
358 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28408
diff
changeset
|
359 |
22855 | 360 |
361 if(listen(listen_fd,1)) { | |
362 mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to turn the socket in listen state: %s\n",strerror(errno)); | |
363 return -1; | |
364 } | |
365 return main_loop(listen_fd); | |
366 } |