From: Stefan H. <ho...@us...> - 2002-12-12 22:14:58
|
Update of /cvsroot/xine/xine-lib/src/input/libreal In directory sc8-pr-cvs1:/tmp/cvs-serv806/libreal Added Files: Makefile.am asmrp.c asmrp.h real.c real.h rmff.c rmff.h Log Message: The rest of rtsp input plugin; sorry. --- NEW FILE: Makefile.am --- REAL_CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE AM_CFLAGS = $(REAL_CFLAGS) @ANSI_FLAGS@ noinst_LTLIBRARIES = libreal.la libreal_la_SOURCES = \ real.c \ asmrp.c \ rmff.c libreal_la_LDFLAGS = $(THREAD_LIBS) -avoid-version -module noinst_HEADERS = \ real.h \ asmrp.h \ rmff.h debug: @$(MAKE) CFLAGS="$(DEBUG_CFLAGS) $(DVD_CFLAGS)" install-debug: debug @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am mostlyclean-generic: -rm -f *~ \#* .*~ .\#* maintainer-clean-generic: -@echo "This command is intended for maintainers to use;" -@echo "it deletes files that may require special tools to rebuild." -rm -f Makefile.in --- NEW FILE: asmrp.c --- /* * Copyright (C) 2002 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * $Id: asmrp.c,v 1.1 2002/12/12 22:14:54 holstsn Exp $ * * a parser for real's asm rules * * grammar for these rules: * rule_book = { rule } rule = ( '#' condition { ',' assignment } | [ assignment {',' assignment} ]) ';' assignment = id '=' const const = ( number | string ) condition = comp_expr { ( '&&' | '||' ) comp_expr } comp_expr = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand } operand = ( '$' id | num | '(' condition ')' ) */ #include <stdlib.h> #include <stdio.h> #include <string.h> /* #define LOG */ #define ASMRP_SYM_NONE 0 #define ASMRP_SYM_EOF 1 #define ASMRP_SYM_NUM 2 #define ASMRP_SYM_ID 3 #define ASMRP_SYM_STRING 4 #define ASMRP_SYM_HASH 10 #define ASMRP_SYM_SEMICOLON 11 #define ASMRP_SYM_COMMA 12 #define ASMRP_SYM_EQUALS 13 #define ASMRP_SYM_AND 14 #define ASMRP_SYM_OR 15 #define ASMRP_SYM_LESS 16 #define ASMRP_SYM_LEQ 17 #define ASMRP_SYM_GEQ 18 #define ASMRP_SYM_GREATER 19 #define ASMRP_SYM_DOLLAR 20 #define ASMRP_SYM_LPAREN 21 #define ASMRP_SYM_RPAREN 22 #define ASMRP_MAX_ID 1024 #define ASMRP_MAX_SYMTAB 10 typedef struct { char *id; int v; } asmrp_sym_t; typedef struct { /* public part */ int sym; int num; char str[ASMRP_MAX_ID]; /* private part */ char *buf; int pos; char ch; asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB]; int sym_tab_num; } asmrp_t; static asmrp_t *asmrp_new () { asmrp_t *p; p = malloc (sizeof (asmrp_t)); p->sym_tab_num = 0; p->sym = ASMRP_SYM_NONE; return p; } static void asmrp_dispose (asmrp_t *p) { int i; for (i=0; i<p->sym_tab_num; i++) free (p->sym_tab[i].id); free (p); } static void asmrp_getch (asmrp_t *p) { p->ch = p->buf[p->pos]; p->pos++; #ifdef LOG printf ("%c\n", p->ch); #endif } static void asmrp_init (asmrp_t *p, const char *str) { p->buf = strdup (str); p->pos = 0; asmrp_getch (p); } static void asmrp_number (asmrp_t *p) { int num; num = 0; while ( (p->ch>='0') && (p->ch<='9') ) { num = num*10 + (p->ch - '0'); asmrp_getch (p); } p->sym = ASMRP_SYM_NUM; p->num = num; } static void asmrp_string (asmrp_t *p) { int l; l = 0; while ( (p->ch!='"') && (p->ch>=32) ) { p->str[l] = p->ch; l++; asmrp_getch (p); } p->str[l]=0; if (p->ch=='"') asmrp_getch (p); p->sym = ASMRP_SYM_STRING; } static void asmrp_identifier (asmrp_t *p) { int l; l = 0; while ( ((p->ch>='A') && (p->ch<='z')) || ((p->ch>='0') && (p->ch<='9'))) { p->str[l] = p->ch; l++; asmrp_getch (p); } p->str[l]=0; p->sym = ASMRP_SYM_ID; } #ifdef LOG static void asmrp_print_sym (asmrp_t *p) { printf ("symbol: "); switch (p->sym) { case ASMRP_SYM_NONE: printf ("NONE\n"); break; case ASMRP_SYM_EOF: printf ("EOF\n"); break; case ASMRP_SYM_NUM: printf ("NUM %d\n", p->num); break; case ASMRP_SYM_ID: printf ("ID '%s'\n", p->str); break; case ASMRP_SYM_STRING: printf ("STRING \"%s\"\n", p->str); break; case ASMRP_SYM_HASH: printf ("#\n"); break; case ASMRP_SYM_SEMICOLON: printf (";\n"); break; case ASMRP_SYM_COMMA: printf (",\n"); break; case ASMRP_SYM_EQUALS: printf ("==\n"); break; case ASMRP_SYM_AND: printf ("&&\n"); break; case ASMRP_SYM_OR: printf ("||\n"); break; case ASMRP_SYM_LESS: printf ("<\n"); break; case ASMRP_SYM_LEQ: printf ("<=\n"); break; case ASMRP_SYM_GEQ: printf (">=\n"); break; case ASMRP_SYM_GREATER: printf (">\n"); break; case ASMRP_SYM_DOLLAR: printf ("$\n"); break; case ASMRP_SYM_LPAREN: printf ("(\n"); break; case ASMRP_SYM_RPAREN: printf (")\n"); break; default: printf ("unknown symbol %d\n", p->sym); } } #endif static void asmrp_get_sym (asmrp_t *p) { while (p->ch <= 32) { if (p->ch == 0) { p->sym = ASMRP_SYM_EOF; return; } asmrp_getch (p); } if (p->ch == '\\') asmrp_getch (p); switch (p->ch) { case '#': p->sym = ASMRP_SYM_HASH; asmrp_getch (p); break; case ';': p->sym = ASMRP_SYM_SEMICOLON; asmrp_getch (p); break; case ',': p->sym = ASMRP_SYM_COMMA; asmrp_getch (p); break; case '=': p->sym = ASMRP_SYM_EQUALS; asmrp_getch (p); if (p->ch=='=') asmrp_getch (p); break; case '&': p->sym = ASMRP_SYM_AND; asmrp_getch (p); if (p->ch=='&') asmrp_getch (p); break; case '|': p->sym = ASMRP_SYM_OR; asmrp_getch (p); if (p->ch=='|') asmrp_getch (p); break; case '<': p->sym = ASMRP_SYM_LESS; asmrp_getch (p); if (p->ch=='=') { p->sym = ASMRP_SYM_LEQ; asmrp_getch (p); } break; case '>': p->sym = ASMRP_SYM_GREATER; asmrp_getch (p); if (p->ch=='=') { p->sym = ASMRP_SYM_GEQ; asmrp_getch (p); } break; case '$': p->sym = ASMRP_SYM_DOLLAR; asmrp_getch (p); break; case '(': p->sym = ASMRP_SYM_LPAREN; asmrp_getch (p); break; case ')': p->sym = ASMRP_SYM_RPAREN; asmrp_getch (p); break; case '"': asmrp_getch (p); asmrp_string (p); break; case '0' ... '9': asmrp_number (p); break; default: asmrp_identifier (p); } #ifdef LOG asmrp_print_sym (p); #endif } static int asmrp_find_id (asmrp_t *p, char *s) { int i; for (i=0; i<p->sym_tab_num; i++) { if (!strcmp (s, p->sym_tab[i].id)) return i; } return -1; } static int asmrp_set_id (asmrp_t *p, char *s, int v) { int i; i = asmrp_find_id (p, s); if (i<0) { i = p->sym_tab_num; p->sym_tab_num++; p->sym_tab[i].id = strdup (s); #ifdef LOG printf ("new symbol '%s'\n", s); #endif } p->sym_tab[i].v = v; #ifdef LOG printf ("symbol '%s' assigned %d\n", s, v); #endif return i; } static int asmrp_condition (asmrp_t *p) ; static int asmrp_operand (asmrp_t *p) { int i, ret; #ifdef LOG printf ("operand\n"); #endif ret = 0; switch (p->sym) { case ASMRP_SYM_DOLLAR: asmrp_get_sym (p); if (p->sym != ASMRP_SYM_ID) { printf ("error: identifier expected.\n"); abort(); } i = asmrp_find_id (p, p->str); if (i<0) { printf ("error: unknown identifier %s\n", p->str); } ret = p->sym_tab[i].v; asmrp_get_sym (p); break; case ASMRP_SYM_NUM: ret = p->num; asmrp_get_sym (p); break; case ASMRP_SYM_LPAREN: asmrp_get_sym (p); ret = asmrp_condition (p); if (p->sym != ASMRP_SYM_RPAREN) { printf ("error: ) expected.\n"); abort(); } asmrp_get_sym (p); break; default: printf ("syntax error, $ number or ( expected\n"); abort(); } #ifdef LOG printf ("operand done, =%d\n", ret); #endif return ret; } static int asmrp_comp_expression (asmrp_t *p) { int a; #ifdef LOG printf ("comp_expression\n"); #endif a = asmrp_operand (p); while ( (p->sym == ASMRP_SYM_LESS) || (p->sym == ASMRP_SYM_LEQ) || (p->sym == ASMRP_SYM_EQUALS) || (p->sym == ASMRP_SYM_GEQ) || (p->sym == ASMRP_SYM_GREATER) ) { int op = p->sym; int b; asmrp_get_sym (p); b = asmrp_operand (p); switch (op) { case ASMRP_SYM_LESS: a = a<b; break; case ASMRP_SYM_LEQ: a = a<=b; break; case ASMRP_SYM_EQUALS: a = a==b; break; case ASMRP_SYM_GEQ: a = a>=b; break; case ASMRP_SYM_GREATER: a = a>b; break; } } #ifdef LOG printf ("comp_expression done = %d\n", a); #endif return a; } static int asmrp_condition (asmrp_t *p) { int a; #ifdef LOG printf ("condition\n"); #endif a = asmrp_comp_expression (p); while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) { int op, b; op = p->sym; asmrp_get_sym (p); b = asmrp_comp_expression (p); switch (op) { case ASMRP_SYM_AND: a = a & b; break; case ASMRP_SYM_OR: a = a | b; break; } } #ifdef LOG printf ("condition done = %d\n", a); #endif return a; } static void asmrp_assignment (asmrp_t *p) { #ifdef LOG printf ("assignment\n"); #endif if (p->sym != ASMRP_SYM_ID) { printf ("error: identifier expected\n"); abort (); } asmrp_get_sym (p); if (p->sym != ASMRP_SYM_EQUALS) { printf ("error: = expected\n"); abort (); } asmrp_get_sym (p); if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) && (p->sym != ASMRP_SYM_ID)) { printf ("error: number or string expected\n"); abort (); } asmrp_get_sym (p); #ifdef LOG printf ("assignment done\n"); #endif } static int asmrp_rule (asmrp_t *p) { int ret; #ifdef LOG printf ("rule\n"); #endif ret = 1; if (p->sym == ASMRP_SYM_HASH) { asmrp_get_sym (p); ret = asmrp_condition (p); while (p->sym == ASMRP_SYM_COMMA) { asmrp_get_sym (p); asmrp_assignment (p); } } else if (p->sym != ASMRP_SYM_SEMICOLON) { asmrp_assignment (p); while (p->sym == ASMRP_SYM_COMMA) { asmrp_get_sym (p); asmrp_assignment (p); } } #ifdef LOG printf ("rule done = %d\n", ret); #endif if (p->sym != ASMRP_SYM_SEMICOLON) { printf ("semicolon expected.\n"); abort (); } asmrp_get_sym (p); return ret; } static int asmrp_eval (asmrp_t *p, int *matches) { int rule_num, num_matches; #ifdef LOG printf ("eval\n"); #endif asmrp_get_sym (p); rule_num = 0; num_matches = 0; while (p->sym != ASMRP_SYM_EOF) { if (asmrp_rule (p)) { #ifdef LOG printf ("rule #%d is true\n", rule_num); #endif matches[num_matches] = rule_num; num_matches++; } rule_num++; } matches[num_matches] = -1; return num_matches; } int asmrp_match (const char *rules, int bandwidth, int *matches) { asmrp_t *p; int num_matches; p = asmrp_new (); asmrp_init (p, rules); asmrp_set_id (p, "Bandwidth", bandwidth); asmrp_set_id (p, "OldPNMPlayer", 0); num_matches = asmrp_eval (p, matches); asmrp_dispose (p); return num_matches; } --- NEW FILE: asmrp.h --- /* * Copyright (C) 2002 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * $Id: asmrp.h,v 1.1 2002/12/12 22:14:54 holstsn Exp $ * * a parser for real's asm rules * * grammar for these rules: * rule_book = { '#' rule ';'} rule = condition {',' assignment} assignment = id '=' const const = ( number | string ) condition = comp_expr { ( '&&' | '||' ) comp_expr } comp_expr = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand } operand = ( '$' id | num | '(' condition ')' ) */ #ifndef HAVE_ASMRP_H #define HAVE_ASMRP_H int asmrp_match (const char *rules, int bandwidth, int *matches) ; #endif --- NEW FILE: real.c --- /* * Copyright (C) 2002 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * $Id: real.c,v 1.1 2002/12/12 22:14:55 holstsn Exp $ * * special functions for real streams. * adopted from joschkas real tools. * */ #include <stdio.h> #include <string.h> #include "real.h" #include "asmrp.h" /* #define LOG */ const unsigned char xor_table[] = { 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53, 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70, 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09, 0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02, 0x10, 0x57, 0x05, 0x18, 0x54, 0x00, 0x00, 0x00 }; #define BE_32C(x,y) x[3]=(char)(y & 0xff);\ x[2]=(char)((y >> 8) & 0xff);\ x[1]=(char)((y >> 16) & 0xff);\ x[0]=(char)((y >> 24) & 0xff); #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ (((uint8_t*)(x))[1] << 16) | \ (((uint8_t*)(x))[2] << 8) | \ ((uint8_t*)(x))[3]) #define MAX(x,y) ((x>y) ? x : y) #ifdef LOG static void hexdump (const char *buf, int length) { int i; printf (" hexdump> "); for (i = 0; i < length; i++) { unsigned char c = buf[i]; printf ("%02x", c); if ((i % 16) == 15) printf ("\n "); if ((i % 2) == 1) printf (" "); } printf ("\n"); } #endif static void hash(char *field, char *param) { uint32_t a, b, c, d; /* fill variables */ memcpy(&a, field, sizeof(uint32_t)); memcpy(&b, &field[4], sizeof(uint32_t)); memcpy(&c, &field[8], sizeof(uint32_t)); memcpy(&d, &field[12], sizeof(uint32_t)); #ifdef LOG printf("real: hash input: %x %x %x %x\n", a, b, c, d); printf("real: hash parameter:\n"); hexdump(param, 64); #endif a = ((b & c) | (~b & d)) + *((uint32_t*)(param+0x00)) + a - 0x28955B88; a = ((a << 0x07) | (a >> 0x19)) + b; d = ((a & b) | (~a & c)) + *((uint32_t*)(param+0x04)) + d - 0x173848AA; d = ((d << 0x0c) | (d >> 0x14)) + a; c = ((d & a) | (~d & b)) + *((uint32_t*)(param+0x08)) + c + 0x242070DB; c = ((c << 0x11) | (c >> 0x0f)) + d; b = ((c & d) | (~c & a)) + *((uint32_t*)(param+0x0c)) + b - 0x3E423112; b = ((b << 0x16) | (b >> 0x0a)) + c; a = ((b & c) | (~b & d)) + *((uint32_t*)(param+0x10)) + a - 0x0A83F051; a = ((a << 0x07) | (a >> 0x19)) + b; d = ((a & b) | (~a & c)) + *((uint32_t*)(param+0x14)) + d + 0x4787C62A; d = ((d << 0x0c) | (d >> 0x14)) + a; c = ((d & a) | (~d & b)) + *((uint32_t*)(param+0x18)) + c - 0x57CFB9ED; c = ((c << 0x11) | (c >> 0x0f)) + d; b = ((c & d) | (~c & a)) + *((uint32_t*)(param+0x1c)) + b - 0x02B96AFF; b = ((b << 0x16) | (b >> 0x0a)) + c; a = ((b & c) | (~b & d)) + *((uint32_t*)(param+0x20)) + a + 0x698098D8; a = ((a << 0x07) | (a >> 0x19)) + b; d = ((a & b) | (~a & c)) + *((uint32_t*)(param+0x24)) + d - 0x74BB0851; d = ((d << 0x0c) | (d >> 0x14)) + a; c = ((d & a) | (~d & b)) + *((uint32_t*)(param+0x28)) + c - 0x0000A44F; c = ((c << 0x11) | (c >> 0x0f)) + d; b = ((c & d) | (~c & a)) + *((uint32_t*)(param+0x2C)) + b - 0x76A32842; b = ((b << 0x16) | (b >> 0x0a)) + c; a = ((b & c) | (~b & d)) + *((uint32_t*)(param+0x30)) + a + 0x6B901122; a = ((a << 0x07) | (a >> 0x19)) + b; d = ((a & b) | (~a & c)) + *((uint32_t*)(param+0x34)) + d - 0x02678E6D; d = ((d << 0x0c) | (d >> 0x14)) + a; c = ((d & a) | (~d & b)) + *((uint32_t*)(param+0x38)) + c - 0x5986BC72; c = ((c << 0x11) | (c >> 0x0f)) + d; b = ((c & d) | (~c & a)) + *((uint32_t*)(param+0x3c)) + b + 0x49B40821; b = ((b << 0x16) | (b >> 0x0a)) + c; a = ((b & d) | (~d & c)) + *((uint32_t*)(param+0x04)) + a - 0x09E1DA9E; a = ((a << 0x05) | (a >> 0x1b)) + b; d = ((a & c) | (~c & b)) + *((uint32_t*)(param+0x18)) + d - 0x3FBF4CC0; d = ((d << 0x09) | (d >> 0x17)) + a; c = ((d & b) | (~b & a)) + *((uint32_t*)(param+0x2c)) + c + 0x265E5A51; c = ((c << 0x0e) | (c >> 0x12)) + d; b = ((c & a) | (~a & d)) + *((uint32_t*)(param+0x00)) + b - 0x16493856; b = ((b << 0x14) | (b >> 0x0c)) + c; a = ((b & d) | (~d & c)) + *((uint32_t*)(param+0x14)) + a - 0x29D0EFA3; a = ((a << 0x05) | (a >> 0x1b)) + b; d = ((a & c) | (~c & b)) + *((uint32_t*)(param+0x28)) + d + 0x02441453; d = ((d << 0x09) | (d >> 0x17)) + a; c = ((d & b) | (~b & a)) + *((uint32_t*)(param+0x3c)) + c - 0x275E197F; c = ((c << 0x0e) | (c >> 0x12)) + d; b = ((c & a) | (~a & d)) + *((uint32_t*)(param+0x10)) + b - 0x182C0438; b = ((b << 0x14) | (b >> 0x0c)) + c; a = ((b & d) | (~d & c)) + *((uint32_t*)(param+0x24)) + a + 0x21E1CDE6; a = ((a << 0x05) | (a >> 0x1b)) + b; d = ((a & c) | (~c & b)) + *((uint32_t*)(param+0x38)) + d - 0x3CC8F82A; d = ((d << 0x09) | (d >> 0x17)) + a; c = ((d & b) | (~b & a)) + *((uint32_t*)(param+0x0c)) + c - 0x0B2AF279; c = ((c << 0x0e) | (c >> 0x12)) + d; b = ((c & a) | (~a & d)) + *((uint32_t*)(param+0x20)) + b + 0x455A14ED; b = ((b << 0x14) | (b >> 0x0c)) + c; a = ((b & d) | (~d & c)) + *((uint32_t*)(param+0x34)) + a - 0x561C16FB; a = ((a << 0x05) | (a >> 0x1b)) + b; d = ((a & c) | (~c & b)) + *((uint32_t*)(param+0x08)) + d - 0x03105C08; d = ((d << 0x09) | (d >> 0x17)) + a; c = ((d & b) | (~b & a)) + *((uint32_t*)(param+0x1c)) + c + 0x676F02D9; c = ((c << 0x0e) | (c >> 0x12)) + d; b = ((c & a) | (~a & d)) + *((uint32_t*)(param+0x30)) + b - 0x72D5B376; b = ((b << 0x14) | (b >> 0x0c)) + c; a = (b ^ c ^ d) + *((uint32_t*)(param+0x14)) + a - 0x0005C6BE; a = ((a << 0x04) | (a >> 0x1c)) + b; d = (a ^ b ^ c) + *((uint32_t*)(param+0x20)) + d - 0x788E097F; d = ((d << 0x0b) | (d >> 0x15)) + a; c = (d ^ a ^ b) + *((uint32_t*)(param+0x2c)) + c + 0x6D9D6122; c = ((c << 0x10) | (c >> 0x10)) + d; b = (c ^ d ^ a) + *((uint32_t*)(param+0x38)) + b - 0x021AC7F4; b = ((b << 0x17) | (b >> 0x09)) + c; a = (b ^ c ^ d) + *((uint32_t*)(param+0x04)) + a - 0x5B4115BC; a = ((a << 0x04) | (a >> 0x1c)) + b; d = (a ^ b ^ c) + *((uint32_t*)(param+0x10)) + d + 0x4BDECFA9; d = ((d << 0x0b) | (d >> 0x15)) + a; c = (d ^ a ^ b) + *((uint32_t*)(param+0x1c)) + c - 0x0944B4A0; c = ((c << 0x10) | (c >> 0x10)) + d; b = (c ^ d ^ a) + *((uint32_t*)(param+0x28)) + b - 0x41404390; b = ((b << 0x17) | (b >> 0x09)) + c; a = (b ^ c ^ d) + *((uint32_t*)(param+0x34)) + a + 0x289B7EC6; a = ((a << 0x04) | (a >> 0x1c)) + b; d = (a ^ b ^ c) + *((uint32_t*)(param+0x00)) + d - 0x155ED806; d = ((d << 0x0b) | (d >> 0x15)) + a; c = (d ^ a ^ b) + *((uint32_t*)(param+0x0c)) + c - 0x2B10CF7B; c = ((c << 0x10) | (c >> 0x10)) + d; b = (c ^ d ^ a) + *((uint32_t*)(param+0x18)) + b + 0x04881D05; b = ((b << 0x17) | (b >> 0x09)) + c; a = (b ^ c ^ d) + *((uint32_t*)(param+0x24)) + a - 0x262B2FC7; a = ((a << 0x04) | (a >> 0x1c)) + b; d = (a ^ b ^ c) + *((uint32_t*)(param+0x30)) + d - 0x1924661B; d = ((d << 0x0b) | (d >> 0x15)) + a; c = (d ^ a ^ b) + *((uint32_t*)(param+0x3c)) + c + 0x1fa27cf8; c = ((c << 0x10) | (c >> 0x10)) + d; b = (c ^ d ^ a) + *((uint32_t*)(param+0x08)) + b - 0x3B53A99B; b = ((b << 0x17) | (b >> 0x09)) + c; a = ((~d | b) ^ c) + *((uint32_t*)(param+0x00)) + a - 0x0BD6DDBC; a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + *((uint32_t*)(param+0x1c)) + d + 0x432AFF97; d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + *((uint32_t*)(param+0x38)) + c - 0x546BDC59; c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + *((uint32_t*)(param+0x14)) + b - 0x036C5FC7; b = ((b << 0x15) | (b >> 0x0b)) + c; a = ((~d | b) ^ c) + *((uint32_t*)(param+0x30)) + a + 0x655B59C3; a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + *((uint32_t*)(param+0x0C)) + d - 0x70F3336E; d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + *((uint32_t*)(param+0x28)) + c - 0x00100B83; c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + *((uint32_t*)(param+0x04)) + b - 0x7A7BA22F; b = ((b << 0x15) | (b >> 0x0b)) + c; a = ((~d | b) ^ c) + *((uint32_t*)(param+0x20)) + a + 0x6FA87E4F; a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + *((uint32_t*)(param+0x3c)) + d - 0x01D31920; d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + *((uint32_t*)(param+0x18)) + c - 0x5CFEBCEC; c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + *((uint32_t*)(param+0x34)) + b + 0x4E0811A1; b = ((b << 0x15) | (b >> 0x0b)) + c; a = ((~d | b) ^ c) + *((uint32_t*)(param+0x10)) + a - 0x08AC817E; a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + *((uint32_t*)(param+0x2c)) + d - 0x42C50DCB; d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + *((uint32_t*)(param+0x08)) + c + 0x2AD7D2BB; c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + *((uint32_t*)(param+0x24)) + b - 0x14792C6F; b = ((b << 0x15) | (b >> 0x0b)) + c; #ifdef LOG printf("real: hash output: %x %x %x %x\n", a, b, c, d); #endif *((uint32_t *)(field+0)) += a; *((uint32_t *)(field+4)) += b; *((uint32_t *)(field+8)) += c; *((uint32_t *)(field+12)) += d; } static void call_hash (char *key, char *challenge, int len) { uint32_t *ptr1, *ptr2; uint32_t a, b, c, d; ptr1=(uint32_t*)(key+16); ptr2=(uint32_t*)(key+20); a = *ptr1; b = (a >> 3) & 0x3f; a += len * 8; *ptr1 = a; if (a < (len << 3)) { #ifdef LOG printf("not verified: (len << 3) > a true\n"); #endif ptr2 += 4; } *ptr2 += (len >> 0x1d); a = 64 - b; c = 0; if (a <= len) { memcpy(key+b+24, challenge, a); hash(key, key+24); c = a; d = c + 0x3f; while ( d < len ) { #ifdef LOG printf("not verified: while ( d < len )\n"); #endif hash(key, challenge+d-0x3f); d += 64; c += 64; } b = 0; } memcpy(key+b+24, challenge+c, len-c); } static void calc_response (char *result, char *field) { char buf1[128]; char buf2[128]; int i; memset (buf1, 0, 64); *buf1 = 128; memcpy (buf2, field+16, 8); i = ( *((uint32_t*)(buf2)) >> 3 ) & 0x3f; if (i < 56) { i = 56 - i; } else { #ifdef LOG printf("not verified: ! (i < 56)\n"); #endif i = 120 - i; } call_hash (field, buf1, i); call_hash (field, buf2, 8); memcpy (result, field, 16); } static void calc_response_string (char *result, char *challenge) { char field[128]; char zres[20]; int i; /* initialize our field */ BE_32C (field, 0x01234567); BE_32C ((field+4), 0x89ABCDEF); BE_32C ((field+8), 0xFEDCBA98); BE_32C ((field+12), 0x76543210); BE_32C ((field+16), 0x00000000); BE_32C ((field+20), 0x00000000); /* calculate response */ call_hash(field, challenge, 64); calc_response(zres,field); /* convert zres to ascii string */ for (i=0; i<16; i++ ) { char a, b; a = (zres[i] >> 4) & 15; b = zres[i] & 15; result[i*2] = ((a<10) ? (a+48) : (a+87)) & 255; result[i*2+1] = ((b<10) ? (b+48) : (b+87)) & 255; } } void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) { int ch_len, table_len, resp_len; int i; char *ptr; char buf[128]; /* initialize return values */ memset(response, 0, 64); memset(chksum, 0, 34); /* initialize buffer */ memset(buf, 0, 128); ptr=buf; BE_32C(ptr, 0xa1e9149d); ptr+=4; BE_32C(ptr, 0x0e6b3b59); ptr+=4; /* some (length) checks */ if (challenge != NULL) { ch_len = strlen (challenge); if (ch_len == 40) /* what a hack... */ { challenge[32]=0; ch_len=32; } if ( ch_len > 56 ) ch_len=56; /* copy challenge to buf */ memcpy(ptr, challenge, ch_len); } if (xor_table != NULL) { table_len = strlen(xor_table); if (table_len > 56) table_len=56; /* xor challenge bytewise with xor_table */ for (i=0; i<table_len; i++) ptr[i] = ptr[i] ^ xor_table[i]; } calc_response_string (response, buf); /* add tail */ resp_len = strlen (response); strcpy (&response[resp_len], "01d0a8e3"); /* calculate checksum */ for (i=0; i<resp_len/4; i++) chksum[i] = response[i*4]; } /* * takes a MLTI-Chunk and a rule number got from match_asm_rule, * returns a pointer to selected data and number of bytes in that. */ static int select_mlti_data(const char *mlti_chunk, int selection, char *out) { int numrules, codec, size; int i; /* MLTI chunk should begin with MLTI */ if ((mlti_chunk[0] != 'M') ||(mlti_chunk[1] != 'L') ||(mlti_chunk[2] != 'T') ||(mlti_chunk[3] != 'I')) { printf("libreal: MLTI tag not detected\n"); return 0; } mlti_chunk+=4; /* next 16 bits are the number of rules */ numrules=BE_16(mlti_chunk); if (selection >= numrules) return 0; /* now <numrules> indices of codecs follows */ /* we skip to selection */ mlti_chunk+=(selection+1)*2; /* get our index */ codec=BE_16(mlti_chunk); /* skip to number of codecs */ mlti_chunk+=(numrules-selection)*2; /* get number of codecs */ numrules=BE_16(mlti_chunk); if (codec >= numrules) { printf("codec index >= number of codecs. %i %i\n", codec, numrules); return 0; } mlti_chunk+=2; /* now seek to selected codec */ for (i=0; i<codec; i++) { size=BE_32(mlti_chunk); mlti_chunk+=size+4; } size=BE_32(mlti_chunk); #ifdef LOG hexdump(mlti_chunk+4, size); #endif memcpy(out,mlti_chunk+4, size); return size; } /* * Decodes base64 strings (based upon b64 package) */ static char *b64_decode(const char *in) { char dtable[256]; /* Encode / decode table */ int i,j,k; char *out=malloc(sizeof(char)*strlen(in)); for (i = 0; i < 255; i++) { dtable[i] = 0x80; } for (i = 'A'; i <= 'Z'; i++) { dtable[i] = 0 + (i - 'A'); } for (i = 'a'; i <= 'z'; i++) { dtable[i] = 26 + (i - 'a'); } for (i = '0'; i <= '9'; i++) { dtable[i] = 52 + (i - '0'); } dtable['+'] = 62; dtable['/'] = 63; dtable['='] = 0; k=0; /*CONSTANTCONDITION*/ for (j=0; j<strlen(in); j+=4) { char a[4], b[4]; for (i = 0; i < 4; i++) { int c = in[i+j]; if (dtable[c] & 0x80) { printf("Illegal character '%c' in input.\n", c); exit(1); } a[i] = (char) c; b[i] = (char) dtable[c]; } out[k++] = (b[0] << 2) | (b[1] >> 4); out[k++] = (b[1] << 4) | (b[2] >> 2); out[k++] = (b[2] << 6) | b[3]; i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3); if (i < 3) { out[k]=0; return out; } } out[k]=0; return out; } /* * looking at stream description. */ static int sdp_filter(const char *in, const char *filter, char *out) { int flen=strlen(filter); int len=strchr(in,'\n')-in; if (!strncmp(in,filter,flen)) { if(in[flen]=='"') flen++; if(in[len-1]=='"') len--; memcpy(out, &in[flen], len-flen); out[len-flen]=0; return len-flen; } return 0; } rmff_header_t *real_parse_sdp(const char *data, char *stream_rules, uint32_t bandwidth) { rmff_header_t *h=malloc(sizeof(rmff_header_t)); rmff_mdpr_t *media=NULL; char buf[4096]; int rulematches[16]; int n; int len; int have_audio=0, have_video=0, stream, sr[2]; stream_rules[0]=0; h=malloc(sizeof(rmff_header_t)); h->streams=malloc(sizeof(rmff_mdpr_t*)*3); h->streams[0]=NULL; h->streams[1]=NULL; h->streams[2]=NULL; h->prop=malloc(sizeof(rmff_prop_t)); h->streams[0]=malloc(sizeof(rmff_mdpr_t)); h->streams[1]=malloc(sizeof(rmff_mdpr_t)); h->cont=malloc(sizeof(rmff_cont_t)); h->data=malloc(sizeof(rmff_data_t)); h->fileheader=malloc(sizeof(rmff_fileheader_t)); h->fileheader->object_id=RMF_TAG; h->fileheader->size=18; h->fileheader->object_version=0; h->fileheader->file_version=0; h->fileheader->num_headers=6; h->prop->object_version=0; h->streams[0]->object_version=0; h->streams[1]->object_version=0; h->cont->object_version=0; h->data->object_version=0; h->prop->object_id=PROP_TAG; h->streams[0]->object_id=MDPR_TAG; h->streams[1]->object_id=MDPR_TAG; h->cont->object_id=CONT_TAG; h->data->object_id=DATA_TAG; h->prop->size=50; h->data->size=18; h->data->next_data_header=0; h->cont->title=NULL; h->cont->author=NULL; h->cont->copyright=NULL; h->cont->comment=NULL; while (*data) { if(sdp_filter(data,"m=audio",buf)) { media=h->streams[0]; have_audio=1; stream=0; } if(sdp_filter(data,"m=video",buf)) { media=h->streams[1]; have_video=1; stream=1; } /* cont stuff */ len=sdp_filter(data,"a=Title:buffer;",buf); if (len) h->cont->title=b64_decode(buf); len=sdp_filter(data,"a=Author:buffer;",buf); if (len) h->cont->author=b64_decode(buf); len=sdp_filter(data,"a=Copyright:buffer;",buf); if (len) h->cont->copyright=b64_decode(buf); len=sdp_filter(data,"a=Abstract:buffer;",buf); if (len) h->cont->comment=b64_decode(buf); /* prop stuff */ len=sdp_filter(data,"a=StreamCount:integer;",buf); if (len) h->prop->num_streams=atoi(buf); len=sdp_filter(data,"a=Flags:integer;",buf); if (len) h->prop->flags=atoi(buf); /* mdpr stuff */ if (media) { len=sdp_filter(data,"a=control:streamid=",buf); if (len) media->stream_number=atoi(buf); len=sdp_filter(data,"a=MaxBitRate:integer;",buf); if (len) { media->max_bit_rate=atoi(buf); media->avg_bit_rate=media->max_bit_rate; } len=sdp_filter(data,"a=MaxPacketSize:integer;",buf); if (len) { media->max_packet_size=atoi(buf); media->avg_packet_size=media->max_packet_size; } len=sdp_filter(data,"a=StartTime:integer;",buf); if (len) media->start_time=atoi(buf); len=sdp_filter(data,"a=Preroll:integer;",buf); if (len) media->preroll=atoi(buf); len=sdp_filter(data,"a=length:npt=",buf); if (len) media->duration=(uint32_t)(atof(buf)*1000); len=sdp_filter(data,"a=StreamName:string;",buf); if (len) { media->stream_name=strdup(buf); media->stream_name_size=strlen(media->stream_name); } len=sdp_filter(data,"a=mimetype:string;",buf); if (len) { media->mime_type=strdup(buf); media->mime_type_size=strlen(media->mime_type); } len=sdp_filter(data,"a=OpaqueData:buffer;",buf); if (len) { media->mlti_data=b64_decode(buf); } len=sdp_filter(data,"a=ASMRuleBook:string;",buf); if (len) { int i=0; char b[64]; #ifdef LOG printf("calling asmrp_match with:\n%s\n%u\n", buf, bandwidth); #endif n=asmrp_match(buf, bandwidth, rulematches); sr[stream]=rulematches[0]; for (i=0; i<n; i++) { #ifdef LOG printf("asmrp rule match: %u for stream %u\n", rulematches[i], stream); #endif sprintf(b,"stream=%u;rule=%u,", stream, rulematches[i]); strcat(stream_rules, b); } } } data+=strchr(data,'\n')-data+1; } if (strlen(stream_rules)>0); stream_rules[strlen(stream_rules)-1]=0; /* delete last , */ /* we have to reconstruct some data in prop */ h->prop->max_bit_rate=0; h->prop->avg_bit_rate=0; h->prop->max_packet_size=0; h->prop->avg_packet_size=0; h->prop->num_packets=0; h->prop->duration=0; h->prop->preroll=0; h->prop->index_offset=0; if(have_video) { h->prop->max_bit_rate=h->streams[1]->max_bit_rate; h->prop->avg_bit_rate=h->streams[1]->avg_bit_rate; h->prop->max_packet_size=h->streams[1]->max_packet_size; h->prop->avg_packet_size=h->streams[1]->avg_packet_size; h->prop->duration=h->streams[1]->duration; /* h->prop->preroll=h->streams[1]->preroll; */ /* select a codec */ h->streams[1]->type_specific_len=select_mlti_data( h->streams[1]->mlti_data, sr[1], buf); h->streams[1]->type_specific_data=malloc(sizeof(char)*h->streams[1]->type_specific_len); memcpy(h->streams[1]->type_specific_data, buf, h->streams[1]->type_specific_len); } else { free(h->streams[1]); h->streams[1]=NULL; } if(have_audio) { h->prop->max_bit_rate+=h->streams[0]->max_bit_rate; h->prop->avg_bit_rate+=h->streams[0]->avg_bit_rate; h->prop->max_packet_size=MAX(h->prop->max_packet_size, h->streams[0]->max_packet_size); if (have_video) h->prop->avg_packet_size=(h->streams[1]->avg_packet_size +h->streams[0]->avg_packet_size) / 2; else h->prop->avg_packet_size=h->streams[0]->avg_packet_size; h->prop->duration=MAX(h->prop->duration,h->streams[0]->duration); /* h->prop->preroll=MAX(h->streams[1]->preroll,h->streams[0]->preroll); */ /* select a codec */ h->streams[0]->type_specific_len=select_mlti_data( h->streams[0]->mlti_data, sr[0], buf); h->streams[0]->type_specific_data=malloc(sizeof(char)*h->streams[0]->type_specific_len); memcpy(h->streams[0]->type_specific_data, buf, h->streams[0]->type_specific_len); } else { free(h->streams[0]); h->streams[0]=NULL; } /* fix sizes */ h->cont->title_len=0; h->cont->author_len=0; h->cont->copyright_len=0; h->cont->comment_len=0; if (h->cont->title) h->cont->title_len=strlen(h->cont->title); if (h->cont->author) h->cont->author_len=strlen(h->cont->author); if (h->cont->copyright) h->cont->copyright_len=strlen(h->cont->copyright); if (h->cont->comment) h->cont->comment_len=strlen(h->cont->comment); h->cont->size=18 +h->cont->title_len +h->cont->author_len +h->cont->copyright_len +h->cont->comment_len; if (have_audio) h->streams[0]->size=12+7*4+6 +h->streams[0]->stream_name_size +h->streams[0]->mime_type_size +h->streams[0]->type_specific_len; if (have_video) h->streams[1]->size=12+7*4+6 +h->streams[1]->stream_name_size +h->streams[1]->mime_type_size +h->streams[1]->type_specific_len; /* fix data offset */ h->prop->data_offset=RMFF_HEADER_SIZE +h->cont->size +h->prop->size; if (have_video) h->prop->data_offset+=h->streams[1]->size; if (have_audio) h->prop->data_offset+=h->streams[0]->size; return h; } int real_get_rdt_chunk(rtsp_t *rtsp_session, char *buffer) { int n=1; uint8_t header[8]; rmff_pheader_t ph; int size; int flags1; int unknown1; uint32_t ts; n=rtsp_read_data(rtsp_session, header, 8); if (n<8) return 0; if (header[0] != 0x24) { printf("rdt chunk not recognized: got 0x%02x\n", header[0]); return 0; } size=(header[1]<<12)+(header[2]<<8)+(header[3]); flags1=header[4]; if ((flags1!=0x40)&&(flags1!=0x42)) { #ifdef LOG printf("got flags1: 0x%02x\n",flags1); #endif header[0]=header[5]; header[1]=header[6]; header[2]=header[7]; n=rtsp_read_data(rtsp_session, header+3, 5); if (n<5) return 0; #ifdef LOG printf("ignoring bytes:\n"); hexdump(header, 8); #endif n=rtsp_read_data(rtsp_session, header+4, 4); if (n<4) return 0; flags1=header[4]; size-=9; } unknown1=(header[5]<<12)+(header[6]<<8)+(header[7]); n=rtsp_read_data(rtsp_session, header, 6); if (n<6) return 0; ts=BE_32(header); #ifdef LOG printf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n", ts, size, flags1, unknown1, header[4], header[5]); #endif size+=2; ph.object_version=0; ph.length=size; ph.stream_number=(flags1>>1)&1; ph.timestamp=ts; ph.reserved=0; ph.flags=0; /* TODO: determine keyframe flag and insert here? */ rmff_dump_pheader(&ph, buffer); size-=12; n=rtsp_read_data(rtsp_session, buffer+12, size); return n+12; } rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth) { char *description=NULL; char *session_id=NULL; rmff_header_t *h; char *challenge1; char challenge2[64]; char checksum[34]; char subscribe[256]; char buf[256]; char *mrl=rtsp_get_mrl(rtsp_session); unsigned int size; /* get challenge */ challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1")); #ifdef LOG printf("real: Challenge1: %s\n", challenge1); #endif /* request stream description */ rtsp_schedule_field(rtsp_session, "Accept: application/sdp"); sprintf(buf, "Bandwidth: %u", bandwidth); rtsp_schedule_field(rtsp_session, buf); rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup"); rtsp_request_describe(rtsp_session,NULL); /* receive description */ size=atoi(rtsp_search_answers(rtsp_session,"Content-length")); if (!rtsp_search_answers(rtsp_session,"ETag")) printf("real: got no ETag!\n"); else session_id=strdup(rtsp_search_answers(rtsp_session,"ETag")); #ifdef LOG printf("real: Stream description size: %i\n", size); #endif description=malloc(sizeof(char)*(size+1)); rtsp_read_data(rtsp_session, description, size); description[size]=0; /* parse sdp (sdpplin) and create a header and a subscribe string */ strcpy(subscribe, "Subscribe: "); h=real_parse_sdp(description, subscribe+11, bandwidth); rmff_fix_header(h); #ifdef LOG printf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n", h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams); #endif /* setup our 2 streams */ real_calc_response_and_checksum (challenge2, checksum, challenge1); sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum); rtsp_schedule_field(rtsp_session, buf); sprintf(buf, "If-Match: %s", session_id); rtsp_schedule_field(rtsp_session, buf); rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); sprintf(buf, "%s/streamid=0", mrl); rtsp_request_setup(rtsp_session,buf); rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); sprintf(buf, "If-Match: %s", session_id); rtsp_schedule_field(rtsp_session, buf); sprintf(buf, "%s/streamid=1", mrl); rtsp_request_setup(rtsp_session,buf); /* set stream parameter (bandwidth) with our subscribe string */ rtsp_schedule_field(rtsp_session, subscribe); rtsp_request_setparameter(rtsp_session,NULL); /* and finally send a play request */ rtsp_schedule_field(rtsp_session, "Range: npt=0-"); rtsp_request_play(rtsp_session,NULL); return h; } --- NEW FILE: real.h --- /* * Copyright (C) 2002 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * $Id: real.h,v 1.1 2002/12/12 22:14:55 holstsn Exp $ * * special functions for real streams. * adopted from joschkas real tools. * */ #ifndef HAVE_REAL_H #define HAVE_REAL_H #include "rmff.h" #include "../librtsp/rtsp.h" #ifdef __CYGWIN__ #define uint32_t unsigned int #define uint16_t unsigned short int #define uint8_t unsigned char #endif /* * calculates response and checksum of a given challenge * (RealChallenge1 in rtsp). See implementation for details. */ void real_calc_response_and_checksum (char *response, char *chksum, char *challenge); int real_get_rdt_chunk(rtsp_t *rtsp_session, char *buffer); rmff_header_t *real_parse_sdp(const char *data, char *stream_rules, uint32_t bandwidth); rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwidth); #endif --- NEW FILE: rmff.c --- /* * Copyright (C) 2002 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * $Id: rmff.c,v 1.1 2002/12/12 22:14:55 holstsn Exp $ * * functions for real media file format * adopted from joschkas real tools */ #include "rmff.h" /* #define LOG */ #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ (((uint8_t*)(x))[1] << 16) | \ (((uint8_t*)(x))[2] << 8) | \ ((uint8_t*)(x))[3]) static void hexdump (const char *buf, int length) { int i; printf ("rmff: ascii>"); for (i = 0; i < length; i++) { unsigned char c = buf[i]; if ((c >= 32) && (c <= 128)) printf ("%c", c); else printf ("."); } printf ("\n"); printf ("rmff: hexdump> "); for (i = 0; i < length; i++) { unsigned char c = buf[i]; printf ("%02x", c); if ((i % 16) == 15) printf ("\nrmff: "); if ((i % 2) == 1) printf (" "); } printf ("\n"); } /* * writes header data to a buffer */ static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) { if (!fileheader) return; fileheader->object_id=BE_32(&fileheader->object_id); fileheader->size=BE_32(&fileheader->size); fileheader->object_version=BE_16(&fileheader->object_version); fileheader->file_version=BE_32(&fileheader->file_version); fileheader->num_headers=BE_32(&fileheader->num_headers); memcpy(buffer, fileheader, 8); memcpy(&buffer[8], &fileheader->object_version, 2); memcpy(&buffer[10], &fileheader->file_version, 8); fileheader->size=BE_32(&fileheader->size); fileheader->object_version=BE_16(&fileheader->object_version); fileheader->file_version=BE_32(&fileheader->file_version); fileheader->num_headers=BE_32(&fileheader->num_headers); fileheader->object_id=BE_32(&fileheader->object_id); } static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) { if (!prop) return; prop->object_id=BE_32(&prop->object_id); prop->size=BE_32(&prop->size); prop->object_version=BE_16(&prop->object_version); prop->max_bit_rate=BE_32(&prop->max_bit_rate); prop->avg_bit_rate=BE_32(&prop->avg_bit_rate); prop->max_packet_size=BE_32(&prop->max_packet_size); prop->avg_packet_size=BE_32(&prop->avg_packet_size); prop->num_packets=BE_32(&prop->num_packets); prop->duration=BE_32(&prop->duration); prop->preroll=BE_32(&prop->preroll); prop->index_offset=BE_32(&prop->index_offset); prop->data_offset=BE_32(&prop->data_offset); prop->num_streams=BE_16(&prop->num_streams); prop->flags=BE_16(&prop->flags); memcpy(buffer, prop, 8); memcpy(&buffer[8], &prop->object_version, 2); memcpy(&buffer[10], &prop->max_bit_rate, 36); memcpy(&buffer[46], &prop->num_streams, 2); memcpy(&buffer[48], &prop->flags, 2); prop->size=BE_32(&prop->size); prop->object_version=BE_16(&prop->object_version); prop->max_bit_rate=BE_32(&prop->max_bit_rate); prop->avg_bit_rate=BE_32(&prop->avg_bit_rate); prop->max_packet_size=BE_32(&prop->max_packet_size); prop->avg_packet_size=BE_32(&prop->avg_packet_size); prop->num_packets=BE_32(&prop->num_packets); prop->duration=BE_32(&prop->duration); prop->preroll=BE_32(&prop->preroll); prop->index_offset=BE_32(&prop->index_offset); prop->data_offset=BE_32(&prop->data_offset); prop->num_streams=BE_16(&prop->num_streams); prop->flags=BE_16(&prop->flags); prop->object_id=BE_32(&prop->object_id); } static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) { int s1, s2, s3; if (!mdpr) return; mdpr->object_id=BE_32(&mdpr->object_id); mdpr->size=BE_32(&mdpr->size); mdpr->object_version=BE_16(&mdpr->object_version); mdpr->stream_number=BE_16(&mdpr->stream_number); mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate); mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate); mdpr->max_packet_size=BE_32(&mdpr->max_packet_size); mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size); mdpr->start_time=BE_32(&mdpr->start_time); mdpr->preroll=BE_32(&mdpr->preroll); mdpr->duration=BE_32(&mdpr->duration); memcpy(buffer, mdpr, 8); memcpy(&buffer[8], &mdpr->object_version, 2); memcpy(&buffer[10], &mdpr->stream_number, 2); memcpy(&buffer[12], &mdpr->max_bit_rate, 28); memcpy(&buffer[40], &mdpr->stream_name_size, 1); s1=mdpr->stream_name_size; memcpy(&buffer[41], mdpr->stream_name, s1); memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1); s2=mdpr->mime_type_size; memcpy(&buffer[42+s1], mdpr->mime_type, s2); mdpr->type_specific_len=BE_32(&mdpr->type_specific_len); memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4); mdpr->type_specific_len=BE_32(&mdpr->type_specific_len); s3=mdpr->type_specific_len; memcpy(&buffer[46+s1+s2], mdpr->type_specific_data, s3); mdpr->size=BE_32(&mdpr->size); mdpr->stream_number=BE_16(&mdpr->stream_number); mdpr->max_bit_rate=BE_32(&mdpr->max_bit_rate); mdpr->avg_bit_rate=BE_32(&mdpr->avg_bit_rate); mdpr->max_packet_size=BE_32(&mdpr->max_packet_size); mdpr->avg_packet_size=BE_32(&mdpr->avg_packet_size); mdpr->start_time=BE_32(&mdpr->start_time); mdpr->preroll=BE_32(&mdpr->preroll); mdpr->duration=BE_32(&mdpr->duration); mdpr->object_id=BE_32(&mdpr->object_id); } static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) { int p; if (!cont) return; cont->object_id=BE_32(&cont->object_id); cont->size=BE_32(&cont->size); cont->object_version=BE_16(&cont->object_version); memcpy(buffer, cont, 8); memcpy(&buffer[8], &cont->object_version, 2); cont->title_len=BE_16(&cont->title_len); memcpy(&buffer[10], &cont->title_len, 2); cont->title_len=BE_16(&cont->title_len); memcpy(&buffer[12], cont->title, cont->title_len); p=12+cont->title_len; cont->author_len=BE_16(&cont->author_len); memcpy(&buffer[p], &cont->author_len, 2); cont->author_len=BE_16(&cont->author_len); memcpy(&buffer[p+2], cont->author, cont->author_len); p+=2+cont->author_len; cont->copyright_len=BE_16(&cont->copyright_len); memcpy(&buffer[p], &cont->copyright_len, 2); cont->copyright_len=BE_16(&cont->copyright_len); memcpy(&buffer[p+2], cont->copyright, cont->copyright_len); p+=2+cont->copyright_len; cont->comment_len=BE_16(&cont->comment_len); memcpy(&buffer[p], &cont->comment_len, 2); cont->comment_len=BE_16(&cont->comment_len); memcpy(&buffer[p+2], cont->comment, cont->comment_len); cont->size=BE_32(&cont->size); cont->object_version=BE_16(&cont->object_version); cont->object_id=BE_32(&cont->object_id); } static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) { if (!data) return; data->object_id=BE_32(&data->object_id); data->size=BE_32(&data->size); data->object_version=BE_16(&data->object_version); data->num_packets=BE_32(&data->num_packets); data->next_data_header=BE_32(&data->next_data_header); memcpy(buffer, data, 8); memcpy(&buffer[8], &data->object_version, 2); memcpy(&buffer[10], &data->num_packets, 8); data->num_packets=BE_32(&data->num_packets); data->next_data_header=BE_32(&data->next_data_header); data->size=BE_32(&data->size); data->object_version=BE_16(&data->object_version); data->object_id=BE_32(&data->object_id); } int rmff_dump_header(rmff_header_t *h, char *buffer, int max) { int written=0; rmff_mdpr_t **stream=h->streams; rmff_dump_fileheader(h->fileheader, &buffer[written]); written+=h->fileheader->size; rmff_dump_prop(h->prop, &buffer[written]); written+=h->prop->size; rmff_dump_cont(h->cont, &buffer[written]); written+=h->cont->size; if (stream) { while(*stream) { rmff_dump_mdpr(*stream, &buffer[written]); written+=(*stream)->size; stream++; } } rmff_dump_dataheader(h->data, &buffer[written]); written+=18; return written; } void rmff_dump_pheader(rmff_pheader_t *h, char *data) { data[0]=(h->object_version>>8) & 0xff; data[1]=h->object_version & 0xff; data[2]=(h->length>>8) & 0xff; data[3]=h->length & 0xff; data[4]=(h->stream_number>>8) & 0xff; data[5]=h->stream_number & 0xff; data[6]=(h->timestamp>>24) & 0xff; data[7]=(h->timestamp>>16) & 0xff; data[8]=(h->timestamp>>8) & 0xff; data[9]=h->timestamp & 0xff; data[10]=h->reserved; data[11]=h->flags; } static rmff_fileheader_t *rmff_scan_fileheader(const char *data) { rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t)); fileheader->object_id=BE_32(data); fileheader->size=BE_32(&data[4]); fileheader->object_version=BE_16(&data[8]); if (fileheader->object_version != 0) { printf("warning: unknown object version in .RMF: 0x%04x\n", fileheader->object_version); } fileheader->file_version=BE_32(&data[10]); fileheader->num_headers=BE_32(&data[14]); return fileheader; } static rmff_prop_t *rmff_scan_prop(const char *data) { rmff_prop_t *prop=malloc(sizeof(rmff_prop_t)); prop->object_id=BE_32(data); prop->size=BE_32(&data[4]); prop->object_version=BE_16(&data[8]); if (prop->object_version != 0) { printf("warning: unknown object version in PROP: 0x%04x\n", prop->object_version); } prop->max_bit_rate=BE_32(&data[10]); prop->avg_bit_rate=BE_32(&data[14]); prop->max_packet_size=BE_32(&data[18]); prop->avg_packet_size=BE_32(&data[22]); prop->num_packets=BE_32(&data[26]); prop->duration=BE_32(&data[30]); prop->preroll=BE_32(&data[34]); prop->index_offset=BE_32(&data[38]); prop->data_offset=BE_32(&data[42]); prop->num_streams=BE_16(&data[46]); prop->flags=BE_16(&data[48]); return prop; } static rmff_mdpr_t *rmff_scan_mdpr(const char *data) { rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t)); mdpr->object_id=BE_32(data); mdpr->size=BE_32(&data[4]); mdpr->object_version=BE_16(&data[8]); if (mdpr->object_version != 0) { printf("warning: unknown object version in MDPR: 0x%04x\n", mdpr->object_version); } mdpr->stream_number=BE_16(&data[10]); mdpr->max_bit_rate=BE_32(&data[12]); mdpr->avg_bit_rate=BE_32(&data[16]); mdpr->max_packet_size=BE_32(&data[20]); mdpr->avg_packet_size=BE_32(&data[24]); mdpr->start_time=BE_32(&data[28]); mdpr->preroll=BE_32(&data[32]); mdpr->duration=BE_32(&data[36]); mdpr->stream_name_size=data[40]; mdpr->stream_name=malloc(sizeof(char)*(mdpr->stream_name_size+1)); memcpy(mdpr->stream_name, &data[41], mdpr->stream_name_size); mdpr->stream_name[mdpr->stream_name_size]=0; mdpr->mime_type_size=data[41+mdpr->stream_name_size]; mdpr->mime_type=malloc(sizeof(char)*(mdpr->mime_type_size+1)); memcpy(mdpr->mime_type, &data[42+mdpr->stream_name_size], mdpr->mime_type_size); mdpr->mime_type[mdpr->mime_type_size]=0; mdpr->type_specific_len=BE_32(&data[42+mdpr->stream_name_size+mdpr->mime_type_size]); mdpr->type_specific_data=malloc(sizeof(char)*(mdpr->type_specific_len)); memcpy(mdpr->type_specific_data, &data[46+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len); return mdpr; } static rmff_cont_t *rmff_scan_cont(const char *data) { rmff_cont_t *cont=malloc(sizeof(rmff_cont_t)); int pos; cont->object_id=BE_32(data); cont->size=BE_32(&data[4]); cont->object_version=BE_16(&data[8]); if (cont->object_version != 0) { printf("warning: unknown object version in CONT: 0x%04x\n", cont->object_version); } cont->title_len=BE_16(&data[10]); cont->title=malloc(sizeof(char)*(cont->title_len+1)); memcpy(cont->title, &data[12], cont->title_len); cont->title[cont->title_len]=0; pos=cont->title_len+12; cont->author_len=BE_16(&data[pos]); cont->author=malloc(sizeof(char)*(cont->author_len+1)); memcpy(cont->author, &data[pos+2], cont->author_len); cont->author[cont->author_len]=0; pos=pos+2+cont->author_len; cont->copyright_len=BE_16(&data[pos]); cont->copyright=malloc(sizeof(char)*(cont->copyright_len+1)); memcpy(cont->copyright, &data[pos+2], cont->copyright_len); cont->copyright[cont->copyright_len]=0; pos=pos+2+cont->copyright_len; cont->comment_len=BE_16(&data[pos]); cont->comment=malloc(sizeof(char)*(cont->comment_len+1)); memcpy(cont->comment, &data[pos+2], cont->comment_len); cont->comment[cont->comment_len]=0; return cont; } static rmff_data_t *rmff_scan_dataheader(const char *data) { rmff_data_t *dh=malloc(sizeof(rmff_data_t)); dh->object_id=BE_32(data); dh->size=BE_32(&data[4]); dh->object_version=BE_16(&data[8]); if (dh->object_version != 0) { printf("warning: unknown object version in DATA: 0x%04x\n", dh->object_version); } dh->num_packets=BE_32(&data[10]); dh->next_data_header=BE_32(&data[14]); return dh; } rmff_header_t *rmff_scan_header(const char *data) { rmff_header_t *header=malloc(sizeof(rmff_header_t)); rmff_mdpr_t *mdpr=NULL; int chunk_size; uint32_t chunk_type; const char *ptr=data; int i; header->fileheader=NULL; header->prop=NULL; header->cont=NULL; header->data=NULL; chunk_type = BE_32(ptr); if (chunk_type != RMF_TAG) { printf("rmff: not an real media file header (.RMF tag not found).\n"); free(header); return NULL; } header->fileheader=rmff_scan_fileheader(ptr); ptr += header->fileheader->size; header->streams=malloc(sizeof(rmff_mdpr_t*)*(header->fileheader->num_headers)); for (i=0; i<header->fileheader->num_headers; i++) { header->streams[i]=NULL; } for (i=1; i<header->fileheader->num_headers; i++) { chunk_type = BE_32(ptr); if (ptr[0] == 0) { printf("rmff: warning: only %d of %d header found.\n", i, header->fileheader->num_headers); break; } chunk_size=1; switch (chunk_type) { case PROP_TAG: header->prop=rmff_scan_prop(ptr); chunk_size=header->prop->size; break; case MDPR_TAG: mdpr=rmff_scan_mdpr(ptr); chunk_size=mdpr->size; header->streams[mdpr->stream_number]=mdpr; break; case CONT_TAG: header->cont=rmff_scan_cont(ptr); chunk_size=header->cont->size; break; case DATA_TAG: header->data=rmff_scan_dataheader(ptr); chunk_size=34; /* hard coded header size */ break; default: printf("unknown chunk\n"); hexdump(ptr,10); chunk_size=1; break; } ptr+=chunk_size; } return header; } rmff_header_t *rmff_scan_header_stream(int fd) { rmff_header_t *header; char *buf=malloc(sizeof(char)*1024); int fill=0; int size=1024; uint32_t chunk_type; uint32_t chunk_size; char *ptr=buf; do { if (size-fill < 8) { size+=1024; buf=realloc(buf, sizeof(char)*size); ptr=buf+fill; } read(fd, ptr, 8); chunk_type=BE_32(ptr); ptr+=4; fill+=4; chunk_size=BE_32(ptr); ptr+=4; fill+=4; switch (chunk_type) { case DATA_TAG: chunk_size=18; case MDPR_TAG: case CONT_TAG: case RMF_TAG: case PROP_TAG: if (size-fill < (chunk_size-8)) { size+=1024; buf=realloc(buf, sizeof(char)*size); ptr=buf+fill; } read(fd, ptr, (chunk_size-8)); ptr+=(chunk_size-8); fill+=(chunk_size-8); break; default: printf("rmff_scan_header_stream: unknown chunk"); hexdump(ptr-8, 8); chunk_type=DATA_TAG; } } while (chunk_type != DATA_TAG); header = rmff_scan_header(buf); free(buf); return header; } void rmff_scan_pheader(rmff_pheader_t *h, char *data) { h->object_version=BE_16(data); h->length=BE_16(data+2); h->stream_number=BE_16(data+4); h->timestamp=BE_32(data+6); h->reserved=(uint8_t)data[10]; h->flags=(uint8_t)data[11]; } rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) { rmff_fileheader_t *fileheader=malloc(sizeof(rmff_fileheader_t)); fileheader->object_id=RMF_TAG; fileheader->size=18; fileheader->object_version=0; fileheader->file_version=0; fileheader->num_headers=num_headers; return fileheader; } rmff_prop_t *rmff_new_prop ( uint32_t max_bit_rate, uint32_t avg_bit_rate, uint32_t max_packet_size, uint32_t avg_packet_size, uint32_t num_packets, uint32_t duration, uint32_t preroll, uint32_t index_offset, uint32_t data_offset, uint16_t num_streams, uint16_t flags ) { rmff_prop_t *prop=malloc(sizeof(rmff_prop_t)); prop->object_id=PROP_TAG; prop->size=50; prop->object_version=0; prop->max_bit_rate=max_bit_rate; prop->avg_bit_rate=avg_bit_rate; prop->max_packet_size=max_packet_size; prop->avg_packet_size=avg_packet_size; prop->num_packets=num_packets; prop->duration=duration; prop->preroll=preroll; prop->index_offset=index_offset; prop->data_offset=data_offset; prop->num_streams=num_streams; prop->flags=flags; return prop; } rmff_mdpr_t *rmff_new_mdpr( uint16_t stream_number, uint32_t max_bit_rate, uint32_t avg_bit_rate, uint32_t max_packet_size, uint32_t avg_packet_size, uint32_t start_time, uint32_t preroll, uint32_t duration, const char *stream_name, const char *mime_type, uint32_t type_specific_len, const char *type_specific_data ) { rmff_mdpr_t *mdpr=malloc(sizeof(rmff_mdpr_t)); mdpr->object_id=MDPR_TAG; mdpr->object_version=0; mdpr->stream_number=stream_number; mdpr->max_bit_rate=max_bit_rate; mdpr->avg_bit_rate=avg_bit_rate; mdpr->max_packet_size=max_packet_size; mdpr->avg_packet_size=avg_packet_size; mdpr->start_time=start_time; mdpr->preroll=preroll; mdpr->duration=duration; mdpr->stream_name_size=0; if (stream_name)... [truncated message content] |