Commit 66f1e9dd authored by Jean-Paul Saman's avatar Jean-Paul Saman

Fix several memory leaks and do a bit of coding style cleanup.

parent 3143ebce
......@@ -47,17 +47,16 @@ const unsigned char xor_table[] = {
#define MAX(x,y) ((x>y) ? x : y)
static void hash(char *field, char *param) {
static void hash(char *field, char *param)
{
uint32_t a, b, c, d;
/* fill variables */
a = LE_32(field);
b = LE_32(field+4);
c = LE_32(field+8);
d = LE_32(field+12);
lprintf("hash input: %x %x %x %x\n", a, b, c, d);
lprintf("hash parameter:\n");
......@@ -126,7 +125,7 @@ static void hash(char *field, char *param) {
c = ((c << 0x0e) | (c >> 0x12)) + d;
b = ((c & a) | (~a & d)) + LE_32((param+0x30)) + b - 0x72D5B376;
b = ((b << 0x14) | (b >> 0x0c)) + c;
a = (b ^ c ^ d) + LE_32((param+0x14)) + a - 0x0005C6BE;
a = ((a << 0x04) | (a >> 0x1c)) + b;
d = (a ^ b ^ c) + LE_32((param+0x20)) + d - 0x788E097F;
......@@ -159,7 +158,7 @@ static void hash(char *field, char *param) {
c = ((c << 0x10) | (c >> 0x10)) + d;
b = (c ^ d ^ a) + LE_32((param+0x08)) + b - 0x3B53A99B;
b = ((b << 0x17) | (b >> 0x09)) + c;
a = ((~d | b) ^ c) + LE_32((param+0x00)) + a - 0x0BD6DDBC;
a = ((a << 0x06) | (a >> 0x1a)) + b;
d = ((~c | a) ^ b) + LE_32((param+0x1c)) + d + 0x432AFF97;
......@@ -194,7 +193,7 @@ static void hash(char *field, char *param) {
b = ((b << 0x15) | (b >> 0x0b)) + c;
lprintf("hash output: %x %x %x %x\n", a, b, c, d);
a += LE_32(field);
b += LE_32(field+4);
c += LE_32(field+8);
......@@ -210,15 +209,15 @@ static void call_hash (char *key, char *challenge, int len) {
uint8_t *ptr1, *ptr2;
uint32_t a, b, c, d, tmp;
ptr1=(key+16);
ptr2=(key+20);
a = LE_32(ptr1);
b = (a >> 3) & 0x3f;
a += len * 8;
LE_32C(ptr1, a);
if (a < (len << 3))
{
lprintf("not verified: (len << 3) > a true\n");
......@@ -228,15 +227,14 @@ static void call_hash (char *key, char *challenge, int len) {
tmp = LE_32(ptr2) + (len >> 0x1d);
LE_32C(ptr2, tmp);
a = 64 - b;
c = 0;
c = 0;
if (a <= len)
{
memcpy(key+b+24, challenge, a);
hash(key, key+24);
c = a;
d = c + 0x3f;
while ( d < len ) {
lprintf("not verified: while ( d < len )\n");
hash(key, challenge+d-0x3f);
......@@ -245,44 +243,43 @@ static void call_hash (char *key, char *challenge, int len) {
}
b = 0;
}
memcpy(key+b+24, challenge+c, len-c);
}
static void calc_response (char *result, char *field) {
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 = ( LE_32((buf2)) >> 3 ) & 0x3f;
if (i < 56) {
if (i < 56)
{
i = 56 - i;
} else {
} else
{
lprintf("not verified: ! (i < 56)\n");
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) {
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);
......@@ -294,11 +291,11 @@ static void calc_response_string (char *result, char *challenge) {
/* 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;
......@@ -307,8 +304,8 @@ static void calc_response_string (char *result, char *challenge) {
}
}
void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) {
void real_calc_response_and_checksum (char *response, char *chksum, char *challenge)
{
int ch_len, table_len, resp_len;
int i;
char *ptr;
......@@ -337,11 +334,11 @@ void real_calc_response_and_checksum (char *response, char *chksum, char *challe
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);
......@@ -369,14 +366,12 @@ void real_calc_response_and_checksum (char *response, char *chksum, char *challe
* 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 mlti_size, int selection, char **out) {
static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection, char **out)
{
int numrules, codec, size;
int i;
/* MLTI chunk should begin with MLTI */
/* MLTI chunk should begin with MLTI */
if ((mlti_chunk[0] != 'M')
||(mlti_chunk[1] != 'L')
||(mlti_chunk[2] != 'T')
......@@ -412,13 +407,12 @@ static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection
}
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);
memcpy(*out, mlti_chunk+4, size);
......@@ -429,301 +423,343 @@ static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection
* looking at stream description.
*/
rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {
sdpplin_t *desc;
rmff_header_t *header;
char *buf;
int len, i;
int max_bit_rate=0;
int avg_bit_rate=0;
int max_packet_size=0;
int avg_packet_size=0;
int duration=0;
if (!data) return NULL;
desc=sdpplin_parse(data);
if (!desc) return NULL;
buf=malloc(2048);
header = malloc(sizeof(rmff_header_t));
memset(header, 0, sizeof(rmff_header_t));
header->fileheader=rmff_new_fileheader(4+desc->stream_count);
header->cont=rmff_new_cont(
desc->title,
desc->author,
desc->copyright,
desc->abstract);
header->data=rmff_new_dataheader(0,0);
header->streams = malloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
memset(header->streams, 0, sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
lprintf("number of streams: %u\n", desc->stream_count);
for (i=0; i<desc->stream_count; i++) {
int j=0;
int n;
char b[64];
int rulematches[16];
lprintf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth)
{
sdpplin_t *desc = NULL;
rmff_header_t *header = NULL;
char *buf = NULL;
int len, i;
int max_bit_rate=0;
int avg_bit_rate=0;
int max_packet_size=0;
int avg_packet_size=0;
int duration=0;
if( !data ) return NULL;
desc=sdpplin_parse(data);
if( !desc ) return NULL;
buf= (char *)malloc(sizeof(char)*2048);
if( !buf ) goto error;
header = (rmff_header_t*)malloc(sizeof(rmff_header_t));
if( !header ) goto error;
memset(header, 0, sizeof(rmff_header_t));
header->fileheader=rmff_new_fileheader(4+desc->stream_count);
header->cont=rmff_new_cont(
desc->title,
desc->author,
desc->copyright,
desc->abstract);
header->data=rmff_new_dataheader(0,0);
if( !header->data ) goto error;
header->streams = (rmff_mdpr_t*)malloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
if( !header->streams ) goto error;
memset(header->streams, 0, sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
lprintf("number of streams: %u\n", desc->stream_count);
for (i=0; i<desc->stream_count; i++)
{
int j=0;
int n;
char b[64];
int rulematches[16];
lprintf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
for (j=0; j<n; j++)
{
lprintf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
strcat(*stream_rules, b);
}
if (!desc->stream[i]->mlti_data)
{
len = 0;
if( buf ) free( buf );
buf = NULL;
}
else
len=select_mlti_data(desc->stream[i]->mlti_data,
desc->stream[i]->mlti_data_size, rulematches[0], &buf);
header->streams[i]=rmff_new_mdpr(
desc->stream[i]->stream_id,
desc->stream[i]->max_bit_rate,
desc->stream[i]->avg_bit_rate,
desc->stream[i]->max_packet_size,
desc->stream[i]->avg_packet_size,
desc->stream[i]->start_time,
desc->stream[i]->preroll,
desc->stream[i]->duration,
desc->stream[i]->stream_name,
desc->stream[i]->mime_type,
len,
buf);
if( !header->streams[i] ) goto error;
duration=MAX(duration,desc->stream[i]->duration);
max_bit_rate+=desc->stream[i]->max_bit_rate;
avg_bit_rate+=desc->stream[i]->avg_bit_rate;
max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size);
if (avg_packet_size)
avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2;
else
avg_packet_size=desc->stream[i]->avg_packet_size;
}
n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
for (j=0; j<n; j++) {
lprintf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
strcat(*stream_rules, b);
if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
(*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
header->prop=rmff_new_prop(
max_bit_rate,
avg_bit_rate,
max_packet_size,
avg_packet_size,
0,
duration,
0,
0,
0,
desc->stream_count,
desc->flags);
if( !header->prop ) goto error;
rmff_fix_header(header);
if( desc )
{
sdpplin_free( desc );
free( desc );
}
if( buf ) free(buf);
return header;
if (!desc->stream[i]->mlti_data) {
len = 0;
buf = NULL;
error:
if( desc )
{
sdpplin_free( desc );
free( desc );
}
else
len=select_mlti_data(desc->stream[i]->mlti_data, desc->stream[i]->mlti_data_size, rulematches[0], &buf);
header->streams[i]=rmff_new_mdpr(
desc->stream[i]->stream_id,
desc->stream[i]->max_bit_rate,
desc->stream[i]->avg_bit_rate,
desc->stream[i]->max_packet_size,
desc->stream[i]->avg_packet_size,
desc->stream[i]->start_time,
desc->stream[i]->preroll,
desc->stream[i]->duration,
desc->stream[i]->stream_name,
desc->stream[i]->mime_type,
len,
buf);
duration=MAX(duration,desc->stream[i]->duration);
max_bit_rate+=desc->stream[i]->max_bit_rate;
avg_bit_rate+=desc->stream[i]->avg_bit_rate;
max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size);
if (avg_packet_size)
avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2;
else
avg_packet_size=desc->stream[i]->avg_packet_size;
}
if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',')
(*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */
header->prop=rmff_new_prop(
max_bit_rate,
avg_bit_rate,
max_packet_size,
avg_packet_size,
0,
duration,
0,
0,
0,
desc->stream_count,
desc->flags);
rmff_fix_header(header);
free(buf);
return header;
if( header )
{
rmff_free_header( header );
free( header );
}
if( buf ) free( buf );
return NULL;
}
int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session, rmff_pheader_t *ph)
{
int n=1;
uint8_t header[8];
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)
{
lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]);
return 0;
}
size=(header[1]<<16)+(header[2]<<8)+(header[3]);
flags1=header[4];
if ((flags1!=0x40)&&(flags1!=0x42))
{
lprintf("got flags1: 0x%02x\n",flags1);
if (header[6]==0x06)
int n=1;
uint8_t header[8];
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)
{
lprintf("got end of stream packet\n");
return 0;
lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]);
return 0;
}
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;
lprintf("ignoring bytes:\n");
n=rtsp_read_data(rtsp_session, header+4, 4);
if (n<4) return 0;
size=(header[1]<<16)+(header[2]<<8)+(header[3]);
flags1=header[4];
size-=9;
}
unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
n=rtsp_read_data(rtsp_session, header, 6);
if (n<6) return 0;
ts=BE_32(header);
if ((flags1!=0x40)&&(flags1!=0x42))
{
lprintf("got flags1: 0x%02x\n",flags1);
if (header[6]==0x06)
{
lprintf("got end of stream packet\n");
return 0;
}
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;
lprintf("ignoring bytes:\n");
n=rtsp_read_data(rtsp_session, header+4, 4);
if (n<4)
return 0;
flags1=header[4];
size-=9;
}
unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]);
n=rtsp_read_data(rtsp_session, header, 6);
if (n<6)
return 0;
ts=BE_32(header);
#if 0
lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n",
ts, size, flags1, unknown1, header[4], header[5]);
lprintf("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? */
return size;
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? */
return size;
}
int real_get_rdt_chunk(rtsp_client_t *rtsp_session, rmff_pheader_t *ph,
unsigned char **buffer)
{
int n;
rmff_dump_pheader(ph, *buffer);
n=rtsp_read_data(rtsp_session, *buffer + 12, ph->length - 12);
return (n <= 0) ? 0 : n+12;
int n;
rmff_dump_pheader(ph, *buffer);
n=rtsp_read_data(rtsp_session, *buffer + 12, ph->length - 12);
return (n <= 0) ? 0 : n+12;
}
//! maximum size of the rtsp description, must be < INT_MAX
#define MAX_DESC_BUF (20 * 1024 * 1024)
rmff_header_t *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandwidth) {
char *description=NULL;
char *session_id=NULL;
rmff_header_t *h;
char *challenge1;
char challenge2[64];
char checksum[34];
char *subscribe;
char *buf=malloc(256);
char *mrl=rtsp_get_mrl(rtsp_session);
unsigned int size;
int status;
/* get challenge */
challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
lprintf("Challenge1: %s\n", challenge1);
/* 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, "GUID: 00000000-0000-0000-0000-000000000000");
rtsp_schedule_field(rtsp_session, "RegionData: 0");
rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
rtsp_schedule_field(rtsp_session, "Language: en-US");
rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
status=rtsp_request_describe(rtsp_session,NULL);
if ( status<200 || status>299 )
{
char *alert=rtsp_search_answers(rtsp_session,"Alert");
if (alert) {
lprintf("real: got message from server:\n%s\n", alert);
rmff_header_t *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandwidth)
{
char *description=NULL;
char *session_id=NULL;
rmff_header_t *h;
char *challenge1 = NULL;
char challenge2[64];
char checksum[34];
char *subscribe=NULL;
char *buf=(char*)malloc(sizeof(char)*256);
char *mrl=rtsp_get_mrl(rtsp_session);
unsigned int size;
int status;
/* get challenge */
challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));
lprintf("Challenge1: %s\n", challenge1);
/* 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, "GUID: 00000000-0000-0000-0000-000000000000");
rtsp_schedule_field(rtsp_session, "RegionData: 0");
rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586");
rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1");
rtsp_schedule_field(rtsp_session, "Language: en-US");
rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup");
status=rtsp_request_describe(rtsp_session,NULL);
if ( status<200 || status>299 )
{
char *alert=rtsp_search_answers(rtsp_session,"Alert");
if (alert) {
lprintf("real: got message from server:\n%s\n", alert);
}
printf( "bou\n");
rtsp_send_ok(rtsp_session);
if( challenge1 ) free(challenge1);
if( alert ) free(alert);
if( buf ) free(buf);
return NULL;
}
printf( "bou\n");
rtsp_send_ok(rtsp_session);
free(buf);
return NULL;
}
/* receive description */
size=0;
if (!rtsp_search_answers(rtsp_session,"Content-length"))
lprintf("real: got no Content-length!\n");
else
size=atoi(rtsp_search_answers(rtsp_session,"Content-length"));
if (size > MAX_DESC_BUF) {
printf("real: Content-length for description too big (> %uMB)!\n",
MAX_DESC_BUF/(1024*1024) );
free(buf);
return NULL;
}
if (!rtsp_search_answers(rtsp_session,"ETag"))
lprintf("real: got no ETag!\n");
else
session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
lprintf("Stream description size: %i\n", size);
description = malloc(sizeof(char)*(size+1));
/* receive description */
size=0;
if (!rtsp_search_answers(rtsp_session,"Content-length"))
lprintf("real: got no Content-length!\n");
else
size=atoi(rtsp_search_answers(rtsp_session,"Content-length"));
if( rtsp_read_data(rtsp_session, description, size) <= 0) {
free(buf);
return NULL;
}
description[size]=0;
fprintf(stderr,description);
/* parse sdp (sdpplin) and create a header and a subscribe string */
subscribe=malloc(256);
strcpy(subscribe, "Subscribe: ");
h=real_parse_sdp(description, &subscribe, bandwidth);
if (!h) {
free(subscribe);
free(buf);
return NULL;
}
rmff_fix_header(h);
if (size > MAX_DESC_BUF) {
printf("real: Content-length for description too big (> %uMB)!\n",
MAX_DESC_BUF/(1024*1024) );
goto error;
}
#if 0
fprintf("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 streams */
real_calc_response_and_checksum (challenge2, checksum, challenge1);
buf = realloc(buf, strlen(challenge2) + strlen(checksum) + 32);
sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum);
rtsp_schedule_field(rtsp_session, buf);
buf = realloc(buf, strlen(session_id) + 32);
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");
buf = realloc(buf, strlen(mrl) + 32);
sprintf(buf, "%s/streamid=0", mrl);
rtsp_request_setup(rtsp_session,buf);
if (h->prop->num_streams > 1) {
rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
if (!rtsp_search_answers(rtsp_session,"ETag"))
lprintf("real: got no ETag!\n");
else
session_id=strdup(rtsp_search_answers(rtsp_session,"ETag"));
lprintf("Stream description size: %i\n", size);
description = (char*)malloc(sizeof(char)*(size+1));
if( !description )
goto error;
if( rtsp_read_data(rtsp_session, description, size) <= 0)
goto error;
description[size]=0;
fprintf(stderr,description);
/* parse sdp (sdpplin) and create a header and a subscribe string */
subscribe = (char *) malloc(sizeof(char)*256);
if( !subscribe )
goto error;
strcpy(subscribe, "Subscribe: ");
h=real_parse_sdp(description, &subscribe, bandwidth);
if (!h)
goto error;
rmff_fix_header(h);
#if 0
fprintf("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 streams */
real_calc_response_and_checksum (challenge2, checksum, challenge1);
buf = realloc(buf, strlen(challenge2) + strlen(checksum) + 32);
sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum);
rtsp_schedule_field(rtsp_session, buf);
buf = realloc(buf, strlen(session_id) + 32);
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");
buf = realloc(buf, strlen(mrl) + 32);
sprintf(buf, "%s/streamid=1", mrl);
sprintf(buf, "%s/streamid=0", 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);
free(subscribe);
free(buf);
return h;
if (h->prop->num_streams > 1) {
rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play");
buf = realloc(buf, strlen(session_id) + 32);
sprintf(buf, "If-Match: %s", session_id);
rtsp_schedule_field(rtsp_session, buf);
buf = realloc(buf, strlen(mrl) + 32);
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);
if( challenge1 ) free( challenge1 );
if( session_id ) free( session_id );
if( description ) free(description);
if( subscribe ) free(subscribe);
if( buf ) free(buf);
return h;
error:
if( h ) rmff_free_header( h );
if( challenge1 ) free( challenge1 );
if( session_id ) free( session_id );
if( description ) free(description);
if( subscribe ) free(subscribe);
if( buf ) free(buf);
return NULL;
}
......@@ -43,7 +43,7 @@ static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) {
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);
......@@ -78,7 +78,7 @@ static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) {
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);
......@@ -123,7 +123,7 @@ static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) {
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);
......@@ -154,7 +154,7 @@ static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) {
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);
......@@ -183,24 +183,25 @@ static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) {
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);
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) {
......@@ -223,7 +224,7 @@ int rmff_dump_header(rmff_header_t *h, char *buffer, int max) {
stream++;
}
}
rmff_dump_dataheader(h->data, &buffer[written]);
written+=18;
......@@ -246,18 +247,19 @@ void rmff_dump_pheader(rmff_pheader_t *h, char *data) {
data[11]=h->flags;
}
rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers) {
rmff_fileheader_t *fileheader = malloc(sizeof(rmff_fileheader_t));
memset(fileheader, 0, sizeof(rmff_fileheader_t));
rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers)
{
rmff_fileheader_t *fileheader = malloc(sizeof(rmff_fileheader_t));
if( !filehandler ) return NULL;
fileheader->object_id=RMF_TAG;
fileheader->size=18;
fileheader->object_version=0;
fileheader->file_version=0;
fileheader->num_headers=num_headers;
memset(fileheader, 0, 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;
return fileheader;
}
rmff_prop_t *rmff_new_prop (
......@@ -271,28 +273,28 @@ rmff_prop_t *rmff_new_prop (
uint32_t index_offset,
uint32_t data_offset,
uint16_t num_streams,
uint16_t flags ) {
rmff_prop_t *prop = malloc(sizeof(rmff_prop_t));
memset(prop, 0, 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;
uint16_t flags )
{
rmff_prop_t *prop = malloc(sizeof(rmff_prop_t));
if( !prop ) return NULL;
memset(prop, 0, 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(
......@@ -307,304 +309,317 @@ rmff_mdpr_t *rmff_new_mdpr(
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));
memset(mdpr, 0, 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) {
mdpr->stream_name=strdup(stream_name);
mdpr->stream_name_size=strlen(stream_name);
}
mdpr->mime_type_size=0;
if (mime_type) {
mdpr->mime_type=strdup(mime_type);
mdpr->mime_type_size=strlen(mime_type);
}
mdpr->type_specific_len=type_specific_len;
mdpr->type_specific_data = malloc(sizeof(char)*type_specific_len);
memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len);
mdpr->mlti_data=NULL;
mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46;
return mdpr;
}
rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment) {
rmff_cont_t *cont = malloc(sizeof(rmff_cont_t));
memset(cont, 0, sizeof(rmff_cont_t));
cont->object_id=CONT_TAG;
cont->object_version=0;
cont->title=NULL;
cont->author=NULL;
cont->copyright=NULL;
cont->comment=NULL;
cont->title_len=0;
cont->author_len=0;
cont->copyright_len=0;
cont->comment_len=0;
if (title) {
cont->title_len=strlen(title);
cont->title=strdup(title);
}
if (author) {
cont->author_len=strlen(author);
cont->author=strdup(author);
}
if (copyright) {
cont->copyright_len=strlen(copyright);
cont->copyright=strdup(copyright);
}
if (comment) {
cont->comment_len=strlen(comment);
cont->comment=strdup(comment);
}
cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18;
const char *type_specific_data )
{
rmff_mdpr_t *mdpr = malloc(sizeof(rmff_mdpr_t));
if( !mdpr ) return NULL;
memset(mdpr, 0, 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)
{
mdpr->stream_name=strdup(stream_name);
mdpr->stream_name_size=strlen(stream_name);
}
mdpr->mime_type_size=0;
if (mime_type)
{
mdpr->mime_type=strdup(mime_type);
mdpr->mime_type_size=strlen(mime_type);
}
mdpr->type_specific_len=type_specific_len;
return cont;
mdpr->type_specific_data = malloc(sizeof(char)*type_specific_len);
if( !mdpr->type_specific_data )
{
if( mdpr->stream_name ) free( mdpr->stream_name );
free( mdpr );
return NULL;
}
memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len);
mdpr->mlti_data=NULL;
mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46;
return mdpr;
}
rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header) {
rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *copyright, const char *comment)
{
rmff_cont_t *cont = malloc(sizeof(rmff_cont_t));
if( !cont ) return NULL;
memset(cont, 0, sizeof(rmff_cont_t));
cont->object_id=CONT_TAG;
cont->object_version=0;
cont->title=NULL;
cont->author=NULL;
cont->copyright=NULL;
cont->comment=NULL;
cont->title_len=0;
cont->author_len=0;
cont->copyright_len=0;
cont->comment_len=0;
if (title)
{
cont->title_len=strlen(title);
cont->title=strdup(title);
}
if (author)
{
cont->author_len=strlen(author);
cont->author=strdup(author);
}
if (copyright)
{
cont->copyright_len=strlen(copyright);
cont->copyright=strdup(copyright);
}
if (comment)
{
cont->comment_len=strlen(comment);
cont->comment=strdup(comment);
}
cont->size=cont->title_len+cont->author_len+cont->copyright_len+cont->comment_len+18;
return cont;
}
rmff_data_t *data = malloc(sizeof(rmff_data_t));
memset(data, 0, sizeof(rmff_data_t));
rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header)
{
rmff_data_t *data = malloc(sizeof(rmff_data_t));
if( !data ) return NULL;
data->object_id=DATA_TAG;
data->size=18;
data->object_version=0;
data->num_packets=num_packets;
data->next_data_header=next_data_header;
memset(data, 0, sizeof(rmff_data_t));
data->object_id=DATA_TAG;
data->size=18;
data->object_version=0;
data->num_packets=num_packets;
data->next_data_header=next_data_header;
return data;
return data;
}
void rmff_print_header(rmff_header_t *h) {
void rmff_print_header(rmff_header_t *h)
{
rmff_mdpr_t **stream;
if(!h) {
printf("rmff_print_header: NULL given\n");
return;
}
if(h->fileheader)
{
printf("\nFILE:\n");
printf("file version : %d\n", h->fileheader->file_version);
printf("number of headers : %d\n", h->fileheader->num_headers);
}
if(h->cont)
{
printf("\nCONTENT:\n");
printf("title : %s\n", h->cont->title);
printf("author : %s\n", h->cont->author);
printf("copyright : %s\n", h->cont->copyright);
printf("comment : %s\n", h->cont->comment);
}
if(h->prop)
{
printf("\nSTREAM PROPERTIES:\n");
printf("bit rate (max/avg) : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate);
printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size);
printf("packets : %i\n", h->prop->num_packets);
printf("duration : %i ms\n", h->prop->duration);
printf("pre-buffer : %i ms\n", h->prop->preroll);
printf("index offset : %i bytes\n", h->prop->index_offset);
printf("data offset : %i bytes\n", h->prop->data_offset);
printf("media streams : %i\n", h->prop->num_streams);
printf("flags : ");
if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled ");
if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled ");
if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast ");
printf("\n");
}
stream=h->streams;
if(stream)
{
while (*stream)
if(!h)
{
printf("\nSTREAM %i:\n", (*stream)->stream_number);
printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type);
printf("bit rate (max/avg) : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate);
printf("packet size (max/avg) : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size);
printf("start time : %i\n", (*stream)->start_time);
printf("pre-buffer : %i ms\n", (*stream)->preroll);
printf("duration : %i ms\n", (*stream)->duration);
printf("type specific data:\n");
stream++;
printf("rmff_print_header: NULL given\n");
return;
}
if(h->fileheader)
{
printf("\nFILE:\n");
printf("file version : %d\n", h->fileheader->file_version);
printf("number of headers : %d\n", h->fileheader->num_headers);
}
if(h->cont)
{
printf("\nCONTENT:\n");
printf("title : %s\n", h->cont->title);
printf("author : %s\n", h->cont->author);
printf("copyright : %s\n", h->cont->copyright);
printf("comment : %s\n", h->cont->comment);
}
if(h->prop)
{
printf("\nSTREAM PROPERTIES:\n");
printf("bit rate (max/avg) : %i/%i\n", h->prop->max_bit_rate, h->prop->avg_bit_rate);
printf("packet size (max/avg) : %i/%i bytes\n", h->prop->max_packet_size, h->prop->avg_packet_size);
printf("packets : %i\n", h->prop->num_packets);
printf("duration : %i ms\n", h->prop->duration);
printf("pre-buffer : %i ms\n", h->prop->preroll);
printf("index offset : %i bytes\n", h->prop->index_offset);
printf("data offset : %i bytes\n", h->prop->data_offset);
printf("media streams : %i\n", h->prop->num_streams);
printf("flags : ");
if (h->prop->flags & PN_SAVE_ENABLED) printf("save_enabled ");
if (h->prop->flags & PN_PERFECT_PLAY_ENABLED) printf("perfect_play_enabled ");
if (h->prop->flags & PN_LIVE_BROADCAST) printf("live_broadcast ");
printf("\n");
}
stream=h->streams;
if(stream)
{
while (*stream)
{
printf("\nSTREAM %i:\n", (*stream)->stream_number);
printf("stream name [mime type] : %s [%s]\n", (*stream)->stream_name, (*stream)->mime_type);
printf("bit rate (max/avg) : %i/%i\n", (*stream)->max_bit_rate, (*stream)->avg_bit_rate);
printf("packet size (max/avg) : %i/%i bytes\n", (*stream)->max_packet_size, (*stream)->avg_packet_size);
printf("start time : %i\n", (*stream)->start_time);
printf("pre-buffer : %i ms\n", (*stream)->preroll);
printf("duration : %i ms\n", (*stream)->duration);
printf("type specific data:\n");
stream++;
}
}
if(h->data)
{
printf("\nDATA:\n");
printf("size : %i\n", h->data->size);
printf("packets : %i\n", h->data->num_packets);
printf("next DATA : 0x%08x\n", h->data->next_data_header);
}
}
if(h->data)
{
printf("\nDATA:\n");
printf("size : %i\n", h->data->size);
printf("packets : %i\n", h->data->num_packets);
printf("next DATA : 0x%08x\n", h->data->next_data_header);
}
}
void rmff_fix_header(rmff_header_t *h) {
int num_headers=0;
int header_size=0;
rmff_mdpr_t **streams;
int num_streams=0;
if (!h) {
lprintf("rmff_fix_header: fatal: no header given.\n");
return;
}
void rmff_fix_header(rmff_header_t *h)
{
int num_headers=0;
int header_size=0;
rmff_mdpr_t **streams;
int num_streams=0;
if (!h->streams) {
lprintf("rmff_fix_header: warning: no MDPR chunks\n");
} else
{
streams=h->streams;
while (*streams)
if (!h)
{
num_streams++;
num_headers++;
header_size+=(*streams)->size;
streams++;
lprintf("rmff_fix_header: fatal: no header given.\n");
return;
}
}
if (h->prop) {
if (h->prop->size != 50)
if (!h->streams)
{
lprintf("rmff_fix_header: correcting prop.size from %i to %i\n", h->prop->size, 50);
h->prop->size=50;
lprintf("rmff_fix_header: warning: no MDPR chunks\n");
}
if (h->prop->num_streams != num_streams)
else
{
lprintf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h->prop->num_streams, num_streams);
streams=h->streams;
while (*streams)
{
num_streams++;
num_headers++;
header_size+=(*streams)->size;
streams++;
}
}
if (h->prop)
{
if (h->prop->size != 50)
{
lprintf("rmff_fix_header: correcting prop.size from %i to %i\n", h->prop->size, 50);
h->prop->size=50;
}
if (h->prop->num_streams != num_streams)
{
lprintf("rmff_fix_header: correcting prop.num_streams from %i to %i\n", h->prop->num_streams, num_streams);
h->prop->num_streams=num_streams;
}
num_headers++;
header_size+=50;
}
else lprintf("rmff_fix_header: warning: no PROP chunk.\n");
h->prop->num_streams=num_streams;
if (h->cont)
{
num_headers++;
header_size+=h->cont->size;
}
num_headers++;
header_size+=50;
} else
lprintf("rmff_fix_header: warning: no PROP chunk.\n");
else lprintf("rmff_fix_header: warning: no CONT chunk.\n");
if (h->cont) {
if (!h->data)
{
lprintf("rmff_fix_header: no DATA chunk, creating one\n");
h->data = malloc(sizeof(rmff_data_t));
if( h->data )
{
memset(h->data, 0, sizeof(rmff_data_t));
h->data->object_id=DATA_TAG;
h->data->object_version=0;
h->data->size=34;
h->data->num_packets=0;
h->data->next_data_header=0;
}
}
num_headers++;
header_size+=h->cont->size;
} else
lprintf("rmff_fix_header: warning: no CONT chunk.\n");
if (!h->data) {
lprintf("rmff_fix_header: no DATA chunk, creating one\n");
h->data = malloc(sizeof(rmff_data_t));
memset(h->data, 0, sizeof(rmff_data_t));
h->data->object_id=DATA_TAG;
h->data->object_version=0;
h->data->size=34;
h->data->num_packets=0;
h->data->next_data_header=0;
}
num_headers++;
if (!h->fileheader) {
lprintf("rmff_fix_header: no fileheader, creating one");
h->fileheader = malloc(sizeof(rmff_fileheader_t));
memset(h->fileheader, 0, sizeof(rmff_fileheader_t));
h->fileheader->object_id=RMF_TAG;
h->fileheader->size=34;
h->fileheader->object_version=0;
h->fileheader->file_version=0;
h->fileheader->num_headers=num_headers+1;
}
header_size+=h->fileheader->size;
num_headers++;
if(h->fileheader->num_headers != num_headers) {
lprintf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers);
h->fileheader->num_headers=num_headers;
}
if(h->prop) {
if (h->prop->data_offset != header_size) {
lprintf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size);
h->prop->data_offset=header_size;
if (!h->fileheader)
{
lprintf("rmff_fix_header: no fileheader, creating one");
h->fileheader = malloc(sizeof(rmff_fileheader_t));
if( h->fileheader )
{
memset(h->fileheader, 0, sizeof(rmff_fileheader_t));
h->fileheader->object_id=RMF_TAG;
h->fileheader->size=34;
h->fileheader->object_version=0;
h->fileheader->file_version=0;
h->fileheader->num_headers=num_headers+1;
}
}
if (h->prop->num_packets == 0) {
int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size);
lprintf("rmff_fix_header: assuming prop.num_packets=%i\n", p);
header_size+=h->fileheader->size;
num_headers++;
h->prop->num_packets=p;
if(h->fileheader->num_headers != num_headers)
{
lprintf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers);
h->fileheader->num_headers=num_headers;
}
if (h->data->num_packets == 0) {
lprintf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets);
h->data->num_packets=h->prop->num_packets;
if(h->prop)
{
if (h->prop->data_offset != header_size)
{
lprintf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size);
h->prop->data_offset=header_size;
}
if (h->prop->num_packets == 0)
{
int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size);
lprintf("rmff_fix_header: assuming prop.num_packets=%i\n", p);
h->prop->num_packets=p;
}
if (h->data->num_packets == 0)
{
lprintf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets);
h->data->num_packets=h->prop->num_packets;
}
lprintf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size);
h->data->size=h->prop->num_packets*h->prop->avg_packet_size;
}
lprintf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size);
h->data->size=h->prop->num_packets*h->prop->avg_packet_size;
}
}
int rmff_get_header_size(rmff_header_t *h) {
if (!h) return 0;
if (!h->prop) return -1;
return h->prop->data_offset+18;
int rmff_get_header_size(rmff_header_t *h)
{
if (!h) return 0;
if (!h->prop) return -1;
return h->prop->data_offset+18;
}
void rmff_free_header(rmff_header_t *h) {
void rmff_free_header(rmff_header_t *h)
{
if (!h) return;
if (!h) return;
if (h->fileheader) free(h->fileheader);
if (h->prop) free(h->prop);
if (h->data) free(h->data);
if (h->cont)
{
free(h->cont->title);
free(h->cont->author);
free(h->cont->copyright);
free(h->cont->comment);
free(h->cont);
}
if (h->streams)
{
rmff_mdpr_t **s=h->streams;
while(*s) {
free((*s)->stream_name);
free((*s)->mime_type);
free((*s)->type_specific_data);
free(*s);
s++;
if (h->fileheader) free(h->fileheader);
if (h->prop) free(h->prop);
if (h->data) free(h->data);
if (h->cont)
{
free(h->cont->title);
free(h->cont->author);
free(h->cont->copyright);
free(h->cont->comment);
free(h->cont);
}
free(h->streams);
}
free(h);
if (h->streams)
{
rmff_mdpr_t **s=h->streams;
while(*s)
{
free((*s)->stream_name);
free((*s)->mime_type);
free((*s)->type_specific_data);
free(*s);
s++;
}
free(h->streams);
}
free(h);
}
......@@ -82,7 +82,6 @@ typedef struct {
uint32_t data_offset;
uint16_t num_streams;
uint16_t flags;
} rmff_prop_t;
typedef struct {
......@@ -125,11 +124,11 @@ typedef struct {
char *copyright;
uint16_t comment_len;
char *comment;
} rmff_cont_t;
typedef struct {
uint32_t object_id;
uint32_t size;
uint16_t object_version;
......@@ -162,7 +161,7 @@ typedef struct {
/*
* constructors for header structs
*/
rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers);
rmff_prop_t *rmff_new_prop (
......
......@@ -31,280 +31,297 @@
static char *b64_decode(const char *in, char *out, int *size)
{
char dtable[256]; /* Encode / decode table */
int i,j,k;
char dtable[256]; /* Encode / decode table */
int i,j,k;
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];
for (i = 0; i < 255; i++) {
dtable[i] = 0x80;
}
for (i = 'A'; i <= 'Z'; i++) {
dtable[i] = 0 + (i - 'A');
}
//xine_buffer_ensure_size(out, k+3);
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;
*size=k;
return out;
for (i = 'a'; i <= 'z'; i++) {
dtable[i] = 26 + (i - 'a');
}
}
out[k]=0;
*size=k;
return out;
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];
}
//xine_buffer_ensure_size(out, k+3);
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;
*size=k;
return out;
}
}
out[k]=0;
*size=k;
return out;
}
static char *nl(char *data) {
char *nlptr = (data) ? strchr(data,'\n') : NULL;
return (nlptr) ? nlptr + 1 : NULL;
static char *nl(char *data)
{
char *nlptr = (data) ? strchr(data,'\n') : NULL;
return (nlptr) ? nlptr + 1 : NULL;
}
static int filter(const char *in, const char *filter, char **out) {
static int filter(const char *in, const char *filter, char **out)
{
int flen=strlen(filter);
int len;
if (!in)
return 0;
len = (strchr(in,'\n')) ? strchr(in,'\n')-in : strlen(in);
if (!strncmp(in,filter,flen))
{
if(in[flen]=='"') flen++;
if(in[len-1]==13) len--;
if(in[len-1]=='"') len--;
memcpy(*out, in+flen, len-flen+1);
(*out)[len-flen]=0;
return len-flen;
}
int flen=strlen(filter);
int len;
if (!in)
return 0;
len = (strchr(in,'\n')) ? strchr(in,'\n')-in : strlen(in);
if (!strncmp(in,filter,flen))
{
if(in[flen]=='"') flen++;
if(in[len-1]==13) len--;
if(in[len-1]=='"') len--;
memcpy(*out, in+flen, len-flen+1);
(*out)[len-flen]=0;
return len-flen;
}
return 0;
}
static sdpplin_stream_t *sdpplin_parse_stream(char **data) {
sdpplin_stream_t *desc = malloc(sizeof(sdpplin_stream_t));
char *buf=malloc(32000);
char *decoded=malloc(32000);
int handled;
memset(desc, 0, sizeof(sdpplin_stream_t));
if (filter(*data, "m=", &buf)) {
desc->id = strdup(buf);
} else
{
lprintf("sdpplin: no m= found.\n");
free(desc);
free(buf);
return NULL;
}
*data=nl(*data);
while (*data && **data && *data[0]!='m') {
handled=0;
if(filter(*data,"a=control:streamid=",&buf)) {
desc->stream_id=atoi(buf);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=MaxBitRate:integer;",&buf)) {
desc->max_bit_rate=atoi(buf);
if (!desc->avg_bit_rate)
desc->avg_bit_rate=desc->max_bit_rate;
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=MaxPacketSize:integer;",&buf)) {
desc->max_packet_size=atoi(buf);
if (!desc->avg_packet_size)
desc->avg_packet_size=desc->max_packet_size;
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=StartTime:integer;",&buf)) {
desc->start_time=atoi(buf);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=Preroll:integer;",&buf)) {
desc->preroll=atoi(buf);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=length:npt=",&buf)) {
desc->duration=(uint32_t)(atof(buf)*1000);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=StreamName:string;",&buf)) {
desc->stream_name=strdup(buf);
desc->stream_name_size=strlen(desc->stream_name);
handled=1;
*data=nl(*data);
}
static sdpplin_stream_t *sdpplin_parse_stream(char **data)
{
sdpplin_stream_t *desc = malloc(sizeof(sdpplin_stream_t));
char *buf = malloc(32000);
char *decoded = malloc(32000);
int handled;
if(filter(*data,"a=mimetype:string;",&buf)) {
desc->mime_type=strdup(buf);
desc->mime_type_size=strlen(desc->mime_type);
handled=1;
*data=nl(*data);
}
if( !desc ) goto error;
memset(desc, 0, sizeof(sdpplin_stream_t));
if(filter(*data,"a=OpaqueData:buffer;",&buf)) {
decoded = b64_decode(buf, decoded, &(desc->mlti_data_size));
desc->mlti_data = malloc(sizeof(char)*desc->mlti_data_size);
memcpy(desc->mlti_data, decoded, desc->mlti_data_size);
handled=1;
*data=nl(*data);
lprintf("mlti_data_size: %i\n", desc->mlti_data_size);
if (filter(*data, "m=", &buf))
{
desc->id = strdup(buf);
}
if(filter(*data,"a=ASMRuleBook:string;",&buf)) {
desc->asm_rule_book=strdup(buf);
handled=1;
*data=nl(*data);
else
{
lprintf("sdpplin: no m= found.\n");
if( decoded ) free(decoded);
if( desc ) free( desc );
if( buf ) free( buf );
return NULL;
}
if(!handled) {
*data=nl(*data);
while (*data && **data && *data[0]!='m')
{
handled=0;
if(filter(*data,"a=control:streamid=",&buf))
{
desc->stream_id=atoi(buf);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=MaxBitRate:integer;",&buf))
{
desc->max_bit_rate=atoi(buf);
if (!desc->avg_bit_rate)
desc->avg_bit_rate=desc->max_bit_rate;
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=MaxPacketSize:integer;",&buf))
{
desc->max_packet_size=atoi(buf);
if (!desc->avg_packet_size)
desc->avg_packet_size=desc->max_packet_size;
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=StartTime:integer;",&buf))
{
desc->start_time=atoi(buf);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=Preroll:integer;",&buf))
{
desc->preroll=atoi(buf);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=length:npt=",&buf))
{
desc->duration=(uint32_t)(atof(buf)*1000);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=StreamName:string;",&buf))
{
desc->stream_name=strdup(buf);
desc->stream_name_size=strlen(desc->stream_name);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=mimetype:string;",&buf))
{
desc->mime_type=strdup(buf);
desc->mime_type_size=strlen(desc->mime_type);
handled=1;
*data=nl(*data);
}
if(filter(*data,"a=OpaqueData:buffer;",&buf))
{
decoded = b64_decode(buf, decoded, &(desc->mlti_data_size));
desc->mlti_data = malloc(sizeof(char)*desc->mlti_data_size);
memcpy(desc->mlti_data, decoded, desc->mlti_data_size);
handled=1;
*data=nl(*data);
lprintf("mlti_data_size: %i\n", desc->mlti_data_size);
}
if(filter(*data,"a=ASMRuleBook:string;",&buf))
{
desc->asm_rule_book=strdup(buf);
handled=1;
*data=nl(*data);
}
if(!handled)
{
#ifdef LOG
int len=strchr(*data,'\n')-(*data);
memcpy(buf, *data, len+1);
buf[len]=0;
printf("libreal: sdpplin: not handled: '%s'\n", buf);
int len=strchr(*data,'\n')-(*data);
memcpy(buf, *data, len+1);
buf[len]=0;
printf("libreal: sdpplin: not handled: '%s'\n", buf);
#endif
*data=nl(*data);
*data=nl(*data);
}
}
}
free(buf);
free(decoded);
return desc;
if( buf ) free(buf);
if( decoded )free(decoded);
return desc;
}
sdpplin_t *sdpplin_parse(char *data) {
sdpplin_t *desc = malloc(sizeof(sdpplin_t));
sdpplin_stream_t *stream;
char *buf=malloc(3200);
char *decoded=malloc(3200);
int handled;
int len;
memset(desc, 0, sizeof(sdpplin_t));
while (data && *data) {
handled=0;
if (filter(data, "m=", &buf)) {
stream=sdpplin_parse_stream(&data);
lprintf("got data for stream id %u\n", stream->stream_id);
desc->stream[stream->stream_id]=stream;
continue;
}
if(filter(data,"a=Title:buffer;",&buf)) {
decoded=b64_decode(buf, decoded, &len);
desc->title=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=Author:buffer;",&buf)) {
decoded=b64_decode(buf, decoded, &len);
desc->author=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=Copyright:buffer;",&buf)) {
decoded=b64_decode(buf, decoded, &len);
desc->copyright=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=Abstract:buffer;",&buf)) {
decoded=b64_decode(buf, decoded, &len);
desc->abstract=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=StreamCount:integer;",&buf)) {
desc->stream_count=atoi(buf);
desc->stream = malloc(sizeof(sdpplin_stream_t*)*desc->stream_count);
handled=1;
data=nl(data);
sdpplin_t *sdpplin_parse(char *data)
{
sdpplin_t *desc = malloc(sizeof(sdpplin_t));
sdpplin_stream_t *stream;
char *buf=malloc(3200);
char *decoded=malloc(3200);
int handled;
int len;
if( !desc ) return NULL;
if( !buf )
{
free( desc );
return NULL;
}
if(filter(data,"a=Flags:integer;",&buf)) {
desc->flags=atoi(buf);
handled=1;
data=nl(data);
if( !decoded )
{
free( buf );
free( desc );
return NULL;
}
if(!handled) {
memset(desc, 0, sizeof(sdpplin_t));
while (data && *data)
{
handled=0;
if (filter(data, "m=", &buf))
{
stream=sdpplin_parse_stream(&data);
lprintf("got data for stream id %u\n", stream->stream_id);
desc->stream[stream->stream_id]=stream;
continue;
}
if(filter(data,"a=Title:buffer;",&buf))
{
decoded=b64_decode(buf, decoded, &len);
desc->title=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=Author:buffer;",&buf))
{
decoded=b64_decode(buf, decoded, &len);
desc->author=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=Copyright:buffer;",&buf))
{
decoded=b64_decode(buf, decoded, &len);
desc->copyright=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=Abstract:buffer;",&buf))
{
decoded=b64_decode(buf, decoded, &len);
desc->abstract=strdup(decoded);
handled=1;
data=nl(data);
}
if(filter(data,"a=StreamCount:integer;",&buf))
{
desc->stream_count=atoi(buf);
desc->stream = malloc(sizeof(sdpplin_stream_t*)*desc->stream_count);
handled=1;
data=nl(data);
}
if(filter(data,"a=Flags:integer;",&buf))
{
desc->flags=atoi(buf);
handled=1;
data=nl(data);
}
if(!handled)
{
#ifdef LOG
int len=strchr(data,'\n')-data;
memcpy(buf, data, len+1);
buf[len]=0;
printf("libreal: sdpplin: not handled: '%s'\n", buf);
int len=strchr(data,'\n')-data;
memcpy(buf, data, len+1);
buf[len]=0;
printf("libreal: sdpplin: not handled: '%s'\n", buf);
#endif
data=nl(data);
data=nl(data);
}
}
}
free(buf);
free(decoded);
return desc;
free(decoded);
free(buf);
return desc;
}
void sdpplin_free(sdpplin_t *description) {
void sdpplin_free(sdpplin_t *description)
{
/* TODO: free strings */
free(description);
}
......@@ -103,7 +103,7 @@ static char *rtsp_get( rtsp_client_t *rtsp )
/*
* rtsp_put puts a line on stream
*/
static int rtsp_put( rtsp_client_t *rtsp, const char *psz_string )
{
int i_buffer = strlen( psz_string );
......@@ -128,7 +128,7 @@ static int rtsp_get_status_code( rtsp_client_t *rtsp, const char *psz_string )
{
char psz_buffer[4];
int i_code = 0;
if( !strncmp( psz_string, "RTSP/1.0", sizeof("RTSP/1.0") - 1 ) )
{
memcpy( psz_buffer, psz_string + sizeof("RTSP/1.0"), 3 );
......@@ -202,7 +202,7 @@ static void rtsp_schedule_standard( rtsp_client_t *rtsp )
/*
* get the answers, if server responses with something != 200, return NULL
*/
static int rtsp_get_answers( rtsp_client_t *rtsp )
{
char *answer = NULL;
......@@ -210,7 +210,7 @@ static int rtsp_get_answers( rtsp_client_t *rtsp )
char **answer_ptr = rtsp->p_private->answers;
int code;
int ans_count = 0;
answer = rtsp_get( rtsp );
if( !answer ) return 0;
code = rtsp_get_status_code( rtsp, answer );
......@@ -222,7 +222,7 @@ static int rtsp_get_answers( rtsp_client_t *rtsp )
answer = rtsp_get( rtsp );
if( !answer ) return 0;
if( !strncasecmp( answer, "Cseq:", 5 ) )
{
sscanf( answer, "%*s %u", &answer_seq );
......@@ -283,7 +283,7 @@ static int rtsp_get_answers( rtsp_client_t *rtsp )
int rtsp_send_ok( rtsp_client_t *rtsp )
{
char cseq[16];
rtsp_put( rtsp, "RTSP/1.0 200 OK" );
sprintf( cseq, "CSeq: %u", rtsp->p_private->cseq );
rtsp_put( rtsp, cseq );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment