Mercurial > mplayer.hg
annotate libmpdemux/realrtsp/asmrp.c @ 13738:39004f891def
seeking based on the largest timestamp in an mpeg stream
It is often more accurate than the current seeking and it has the
additional benefit of giving the (almost) precise total time of the movie.
patch by Michael Behrisch < behrisch at informatik.hu-berlin.de >
author | aurel |
---|---|
date | Sat, 23 Oct 2004 00:05:38 +0000 |
parents | 0d38a501c6a5 |
children | f580a7755ac5 |
rev | line source |
---|---|
9922 | 1 /* |
2 * This file was ported to MPlayer from xine CVS asmrp.c,v 1.2 2002/12/17 16:49:48 | |
3 */ | |
4 | |
5 /* | |
6 * Copyright (C) 2002 the xine project | |
7 * | |
8 * This file is part of xine, a free video player. | |
9 * | |
10 * xine is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * xine is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
23 * | |
24 * | |
25 * a parser for real's asm rules | |
26 * | |
27 * grammar for these rules: | |
28 * | |
29 | |
30 rule_book = { rule } | |
31 rule = ( '#' condition { ',' assignment } | [ assignment {',' assignment} ]) ';' | |
32 assignment = id '=' const | |
33 const = ( number | string ) | |
34 condition = comp_expr { ( '&&' | '||' ) comp_expr } | |
35 comp_expr = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand } | |
36 operand = ( '$' id | num | '(' condition ')' ) | |
37 | |
38 */ | |
39 | |
40 #include <stdlib.h> | |
41 #include <stdio.h> | |
42 #include <string.h> | |
43 | |
44 /* | |
45 #define LOG | |
46 */ | |
47 | |
48 #define ASMRP_SYM_NONE 0 | |
49 #define ASMRP_SYM_EOF 1 | |
50 | |
51 #define ASMRP_SYM_NUM 2 | |
52 #define ASMRP_SYM_ID 3 | |
53 #define ASMRP_SYM_STRING 4 | |
54 | |
55 #define ASMRP_SYM_HASH 10 | |
56 #define ASMRP_SYM_SEMICOLON 11 | |
57 #define ASMRP_SYM_COMMA 12 | |
58 #define ASMRP_SYM_EQUALS 13 | |
59 #define ASMRP_SYM_AND 14 | |
60 #define ASMRP_SYM_OR 15 | |
61 #define ASMRP_SYM_LESS 16 | |
62 #define ASMRP_SYM_LEQ 17 | |
63 #define ASMRP_SYM_GEQ 18 | |
64 #define ASMRP_SYM_GREATER 19 | |
65 #define ASMRP_SYM_DOLLAR 20 | |
66 #define ASMRP_SYM_LPAREN 21 | |
67 #define ASMRP_SYM_RPAREN 22 | |
68 | |
69 #define ASMRP_MAX_ID 1024 | |
70 | |
71 #define ASMRP_MAX_SYMTAB 10 | |
72 | |
73 typedef struct { | |
74 char *id; | |
75 int v; | |
76 } asmrp_sym_t; | |
77 | |
78 typedef struct { | |
79 | |
80 /* public part */ | |
81 | |
82 int sym; | |
83 int num; | |
84 | |
85 char str[ASMRP_MAX_ID]; | |
86 | |
87 /* private part */ | |
88 | |
89 char *buf; | |
90 int pos; | |
91 char ch; | |
92 | |
93 asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB]; | |
94 int sym_tab_num; | |
95 | |
96 } asmrp_t; | |
97 | |
98 static asmrp_t *asmrp_new () { | |
99 | |
100 asmrp_t *p; | |
101 | |
102 p = malloc (sizeof (asmrp_t)); | |
103 | |
104 p->sym_tab_num = 0; | |
105 p->sym = ASMRP_SYM_NONE; | |
106 | |
107 return p; | |
108 } | |
109 | |
110 static void asmrp_dispose (asmrp_t *p) { | |
111 | |
112 int i; | |
113 | |
114 for (i=0; i<p->sym_tab_num; i++) | |
115 free (p->sym_tab[i].id); | |
116 | |
117 free (p); | |
118 } | |
119 | |
120 static void asmrp_getch (asmrp_t *p) { | |
121 p->ch = p->buf[p->pos]; | |
122 p->pos++; | |
123 | |
124 #ifdef LOG | |
125 printf ("%c\n", p->ch); | |
126 #endif | |
127 | |
128 } | |
129 | |
130 static void asmrp_init (asmrp_t *p, const char *str) { | |
131 | |
132 p->buf = strdup (str); | |
133 p->pos = 0; | |
134 | |
135 asmrp_getch (p); | |
136 } | |
137 | |
138 static void asmrp_number (asmrp_t *p) { | |
139 | |
140 int num; | |
141 | |
142 num = 0; | |
143 while ( (p->ch>='0') && (p->ch<='9') ) { | |
144 | |
145 num = num*10 + (p->ch - '0'); | |
146 | |
147 asmrp_getch (p); | |
148 } | |
149 | |
150 p->sym = ASMRP_SYM_NUM; | |
151 p->num = num; | |
152 } | |
153 | |
154 static void asmrp_string (asmrp_t *p) { | |
155 | |
156 int l; | |
157 | |
158 l = 0; | |
159 | |
160 while ( (p->ch!='"') && (p->ch>=32) ) { | |
161 | |
162 p->str[l] = p->ch; | |
163 | |
164 l++; | |
165 asmrp_getch (p); | |
166 } | |
167 p->str[l]=0; | |
168 | |
169 if (p->ch=='"') | |
170 asmrp_getch (p); | |
171 | |
172 p->sym = ASMRP_SYM_STRING; | |
173 } | |
174 | |
175 static void asmrp_identifier (asmrp_t *p) { | |
176 | |
177 int l; | |
178 | |
179 l = 0; | |
180 | |
181 while ( ((p->ch>='A') && (p->ch<='z')) | |
182 || ((p->ch>='0') && (p->ch<='9'))) { | |
183 | |
184 p->str[l] = p->ch; | |
185 | |
186 l++; | |
187 asmrp_getch (p); | |
188 } | |
189 p->str[l]=0; | |
190 | |
191 p->sym = ASMRP_SYM_ID; | |
192 } | |
193 | |
194 #ifdef LOG | |
195 static void asmrp_print_sym (asmrp_t *p) { | |
196 | |
197 printf ("symbol: "); | |
198 | |
199 switch (p->sym) { | |
200 | |
201 case ASMRP_SYM_NONE: | |
202 printf ("NONE\n"); | |
203 break; | |
204 | |
205 case ASMRP_SYM_EOF: | |
206 printf ("EOF\n"); | |
207 break; | |
208 | |
209 case ASMRP_SYM_NUM: | |
210 printf ("NUM %d\n", p->num); | |
211 break; | |
212 | |
213 case ASMRP_SYM_ID: | |
214 printf ("ID '%s'\n", p->str); | |
215 break; | |
216 | |
217 case ASMRP_SYM_STRING: | |
218 printf ("STRING \"%s\"\n", p->str); | |
219 break; | |
220 | |
221 case ASMRP_SYM_HASH: | |
222 printf ("#\n"); | |
223 break; | |
224 | |
225 case ASMRP_SYM_SEMICOLON: | |
226 printf (";\n"); | |
227 break; | |
228 case ASMRP_SYM_COMMA: | |
229 printf (",\n"); | |
230 break; | |
231 case ASMRP_SYM_EQUALS: | |
232 printf ("==\n"); | |
233 break; | |
234 case ASMRP_SYM_AND: | |
235 printf ("&&\n"); | |
236 break; | |
237 case ASMRP_SYM_OR: | |
238 printf ("||\n"); | |
239 break; | |
240 case ASMRP_SYM_LESS: | |
241 printf ("<\n"); | |
242 break; | |
243 case ASMRP_SYM_LEQ: | |
244 printf ("<=\n"); | |
245 break; | |
246 case ASMRP_SYM_GEQ: | |
247 printf (">=\n"); | |
248 break; | |
249 case ASMRP_SYM_GREATER: | |
250 printf (">\n"); | |
251 break; | |
252 case ASMRP_SYM_DOLLAR: | |
253 printf ("$\n"); | |
254 break; | |
255 case ASMRP_SYM_LPAREN: | |
256 printf ("(\n"); | |
257 break; | |
258 case ASMRP_SYM_RPAREN: | |
259 printf (")\n"); | |
260 break; | |
261 | |
262 default: | |
263 printf ("unknown symbol %d\n", p->sym); | |
264 } | |
265 } | |
266 #endif | |
267 | |
268 static void asmrp_get_sym (asmrp_t *p) { | |
269 | |
270 while (p->ch <= 32) { | |
271 if (p->ch == 0) { | |
272 p->sym = ASMRP_SYM_EOF; | |
273 return; | |
274 } | |
275 | |
276 asmrp_getch (p); | |
277 } | |
278 | |
279 if (p->ch == '\\') | |
280 asmrp_getch (p); | |
281 | |
282 switch (p->ch) { | |
283 | |
284 case '#': | |
285 p->sym = ASMRP_SYM_HASH; | |
286 asmrp_getch (p); | |
287 break; | |
288 case ';': | |
289 p->sym = ASMRP_SYM_SEMICOLON; | |
290 asmrp_getch (p); | |
291 break; | |
292 case ',': | |
293 p->sym = ASMRP_SYM_COMMA; | |
294 asmrp_getch (p); | |
295 break; | |
296 case '=': | |
297 p->sym = ASMRP_SYM_EQUALS; | |
298 asmrp_getch (p); | |
299 if (p->ch=='=') | |
300 asmrp_getch (p); | |
301 break; | |
302 case '&': | |
303 p->sym = ASMRP_SYM_AND; | |
304 asmrp_getch (p); | |
305 if (p->ch=='&') | |
306 asmrp_getch (p); | |
307 break; | |
308 case '|': | |
309 p->sym = ASMRP_SYM_OR; | |
310 asmrp_getch (p); | |
311 if (p->ch=='|') | |
312 asmrp_getch (p); | |
313 break; | |
314 case '<': | |
315 p->sym = ASMRP_SYM_LESS; | |
316 asmrp_getch (p); | |
317 if (p->ch=='=') { | |
318 p->sym = ASMRP_SYM_LEQ; | |
319 asmrp_getch (p); | |
320 } | |
321 break; | |
322 case '>': | |
323 p->sym = ASMRP_SYM_GREATER; | |
324 asmrp_getch (p); | |
325 if (p->ch=='=') { | |
326 p->sym = ASMRP_SYM_GEQ; | |
327 asmrp_getch (p); | |
328 } | |
329 break; | |
330 case '$': | |
331 p->sym = ASMRP_SYM_DOLLAR; | |
332 asmrp_getch (p); | |
333 break; | |
334 case '(': | |
335 p->sym = ASMRP_SYM_LPAREN; | |
336 asmrp_getch (p); | |
337 break; | |
338 case ')': | |
339 p->sym = ASMRP_SYM_RPAREN; | |
340 asmrp_getch (p); | |
341 break; | |
342 | |
343 case '"': | |
344 asmrp_getch (p); | |
345 asmrp_string (p); | |
346 break; | |
347 | |
348 case '0': case '1': case '2': case '3': case '4': | |
349 case '5': case '6': case '7': case '8': case '9': | |
350 asmrp_number (p); | |
351 break; | |
352 | |
353 default: | |
354 asmrp_identifier (p); | |
355 } | |
356 | |
357 #ifdef LOG | |
358 asmrp_print_sym (p); | |
359 #endif | |
360 | |
361 } | |
362 | |
363 static int asmrp_find_id (asmrp_t *p, char *s) { | |
364 | |
365 int i; | |
366 | |
367 for (i=0; i<p->sym_tab_num; i++) { | |
368 if (!strcmp (s, p->sym_tab[i].id)) | |
369 return i; | |
370 } | |
371 | |
372 return -1; | |
373 } | |
374 | |
375 static int asmrp_set_id (asmrp_t *p, char *s, int v) { | |
376 | |
377 int i; | |
378 | |
379 i = asmrp_find_id (p, s); | |
380 | |
381 if (i<0) { | |
382 i = p->sym_tab_num; | |
383 p->sym_tab_num++; | |
384 p->sym_tab[i].id = strdup (s); | |
385 | |
386 #ifdef LOG | |
387 printf ("new symbol '%s'\n", s); | |
388 #endif | |
389 | |
390 } | |
391 | |
392 p->sym_tab[i].v = v; | |
393 | |
394 #ifdef LOG | |
395 printf ("symbol '%s' assigned %d\n", s, v); | |
396 #endif | |
397 | |
398 return i; | |
399 } | |
400 | |
401 static int asmrp_condition (asmrp_t *p) ; | |
402 | |
403 static int asmrp_operand (asmrp_t *p) { | |
404 | |
405 int i, ret; | |
406 | |
407 #ifdef LOG | |
408 printf ("operand\n"); | |
409 #endif | |
410 | |
411 ret = 0; | |
412 | |
413 switch (p->sym) { | |
414 | |
415 case ASMRP_SYM_DOLLAR: | |
416 | |
417 asmrp_get_sym (p); | |
418 | |
419 if (p->sym != ASMRP_SYM_ID) { | |
420 printf ("error: identifier expected.\n"); | |
421 abort(); | |
422 } | |
423 | |
424 i = asmrp_find_id (p, p->str); | |
425 if (i<0) { | |
426 printf ("error: unknown identifier %s\n", p->str); | |
427 } | |
428 ret = p->sym_tab[i].v; | |
429 | |
430 asmrp_get_sym (p); | |
431 break; | |
432 | |
433 case ASMRP_SYM_NUM: | |
434 ret = p->num; | |
435 | |
436 asmrp_get_sym (p); | |
437 break; | |
438 | |
439 case ASMRP_SYM_LPAREN: | |
440 asmrp_get_sym (p); | |
441 | |
442 ret = asmrp_condition (p); | |
443 | |
444 if (p->sym != ASMRP_SYM_RPAREN) { | |
445 printf ("error: ) expected.\n"); | |
446 abort(); | |
447 } | |
448 | |
449 asmrp_get_sym (p); | |
450 break; | |
451 | |
452 default: | |
453 printf ("syntax error, $ number or ( expected\n"); | |
454 abort(); | |
455 } | |
456 | |
457 #ifdef LOG | |
458 printf ("operand done, =%d\n", ret); | |
459 #endif | |
460 | |
461 return ret; | |
462 } | |
463 | |
464 static int asmrp_comp_expression (asmrp_t *p) { | |
465 | |
466 int a; | |
467 | |
468 #ifdef LOG | |
469 printf ("comp_expression\n"); | |
470 #endif | |
471 | |
472 a = asmrp_operand (p); | |
473 | |
474 while ( (p->sym == ASMRP_SYM_LESS) | |
475 || (p->sym == ASMRP_SYM_LEQ) | |
476 || (p->sym == ASMRP_SYM_EQUALS) | |
477 || (p->sym == ASMRP_SYM_GEQ) | |
478 || (p->sym == ASMRP_SYM_GREATER) ) { | |
479 int op = p->sym; | |
480 int b; | |
481 | |
482 asmrp_get_sym (p); | |
483 | |
484 b = asmrp_operand (p); | |
485 | |
486 switch (op) { | |
487 case ASMRP_SYM_LESS: | |
488 a = a<b; | |
489 break; | |
490 case ASMRP_SYM_LEQ: | |
491 a = a<=b; | |
492 break; | |
493 case ASMRP_SYM_EQUALS: | |
494 a = a==b; | |
495 break; | |
496 case ASMRP_SYM_GEQ: | |
497 a = a>=b; | |
498 break; | |
499 case ASMRP_SYM_GREATER: | |
500 a = a>b; | |
501 break; | |
502 } | |
503 | |
504 } | |
505 | |
506 #ifdef LOG | |
507 printf ("comp_expression done = %d\n", a); | |
508 #endif | |
509 return a; | |
510 } | |
511 | |
512 static int asmrp_condition (asmrp_t *p) { | |
513 | |
514 int a; | |
515 | |
516 #ifdef LOG | |
517 printf ("condition\n"); | |
518 #endif | |
519 | |
520 a = asmrp_comp_expression (p); | |
521 | |
522 while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) { | |
523 int op, b; | |
524 | |
525 op = p->sym; | |
526 | |
527 asmrp_get_sym (p); | |
528 | |
529 b = asmrp_comp_expression (p); | |
530 | |
531 switch (op) { | |
532 case ASMRP_SYM_AND: | |
533 a = a & b; | |
534 break; | |
535 case ASMRP_SYM_OR: | |
536 a = a | b; | |
537 break; | |
538 } | |
539 } | |
540 | |
541 #ifdef LOG | |
542 printf ("condition done = %d\n", a); | |
543 #endif | |
544 return a; | |
545 } | |
546 | |
547 static void asmrp_assignment (asmrp_t *p) { | |
548 | |
549 #ifdef LOG | |
550 printf ("assignment\n"); | |
551 #endif | |
552 | |
13203
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
553 if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) { |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
554 #ifdef LOG |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
555 printf ("empty assignment\n"); |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
556 #endif |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
557 return; |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
558 } |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
559 |
9922 | 560 if (p->sym != ASMRP_SYM_ID) { |
561 printf ("error: identifier expected\n"); | |
562 abort (); | |
563 } | |
564 asmrp_get_sym (p); | |
565 | |
566 if (p->sym != ASMRP_SYM_EQUALS) { | |
567 printf ("error: = expected\n"); | |
568 abort (); | |
569 } | |
570 asmrp_get_sym (p); | |
571 | |
572 if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) | |
573 && (p->sym != ASMRP_SYM_ID)) { | |
574 printf ("error: number or string expected\n"); | |
575 abort (); | |
576 } | |
577 asmrp_get_sym (p); | |
578 | |
579 #ifdef LOG | |
580 printf ("assignment done\n"); | |
581 #endif | |
582 } | |
583 | |
584 static int asmrp_rule (asmrp_t *p) { | |
585 | |
586 int ret; | |
587 | |
588 #ifdef LOG | |
589 printf ("rule\n"); | |
590 #endif | |
591 | |
592 ret = 1; | |
593 | |
594 if (p->sym == ASMRP_SYM_HASH) { | |
595 | |
596 asmrp_get_sym (p); | |
597 ret = asmrp_condition (p); | |
598 | |
599 while (p->sym == ASMRP_SYM_COMMA) { | |
600 | |
601 asmrp_get_sym (p); | |
602 | |
603 asmrp_assignment (p); | |
604 } | |
605 | |
606 } else if (p->sym != ASMRP_SYM_SEMICOLON) { | |
607 | |
608 asmrp_assignment (p); | |
609 | |
610 while (p->sym == ASMRP_SYM_COMMA) { | |
611 | |
612 asmrp_get_sym (p); | |
613 asmrp_assignment (p); | |
614 } | |
615 } | |
616 | |
617 #ifdef LOG | |
618 printf ("rule done = %d\n", ret); | |
619 #endif | |
620 | |
621 if (p->sym != ASMRP_SYM_SEMICOLON) { | |
622 printf ("semicolon expected.\n"); | |
623 abort (); | |
624 } | |
625 | |
626 asmrp_get_sym (p); | |
627 | |
628 return ret; | |
629 } | |
630 | |
631 static int asmrp_eval (asmrp_t *p, int *matches) { | |
632 | |
633 int rule_num, num_matches; | |
634 | |
635 #ifdef LOG | |
636 printf ("eval\n"); | |
637 #endif | |
638 | |
639 asmrp_get_sym (p); | |
640 | |
641 rule_num = 0; num_matches = 0; | |
642 while (p->sym != ASMRP_SYM_EOF) { | |
643 | |
644 if (asmrp_rule (p)) { | |
645 #ifdef LOG | |
646 printf ("rule #%d is true\n", rule_num); | |
647 #endif | |
648 matches[num_matches] = rule_num; | |
649 num_matches++; | |
650 } | |
651 | |
652 rule_num++; | |
653 } | |
654 | |
655 matches[num_matches] = -1; | |
656 return num_matches; | |
657 } | |
658 | |
659 int asmrp_match (const char *rules, int bandwidth, int *matches) { | |
660 | |
661 asmrp_t *p; | |
662 int num_matches; | |
663 | |
664 p = asmrp_new (); | |
665 | |
666 asmrp_init (p, rules); | |
667 | |
668 asmrp_set_id (p, "Bandwidth", bandwidth); | |
669 asmrp_set_id (p, "OldPNMPlayer", 0); | |
670 | |
671 num_matches = asmrp_eval (p, matches); | |
672 | |
673 asmrp_dispose (p); | |
674 | |
675 return num_matches; | |
676 } | |
677 |