Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/crc32.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
* it contains the precomputed table
*/

#include "crc32.h"

#include <stdint.h>
#include "ts.h"

/**CRC table for PAT rebuilding, cam support and autoconfiguration*/
uint32_t crc32_table[256] =
Expand Down Expand Up @@ -98,3 +101,34 @@ uint32_t crc32_table[256] =
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};

/**
* @brief CRC32 calculation inspired by the xine project
* @param data to be hashed
* @param len of data
* @return CRC32 value of data
*/
unsigned long calculateCRC32(const unsigned char *data, int len)
{
// Now we must adjust the CRC32
unsigned long crc32 = 0xffffffff;
for (int i = 0; i < len; ++i) {
crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ data[i]) & 0xff];
}
return crc32;
}

/**
* @brief Calculates and sets CRC32 for PAT, EIT, SDT, PMT, NIT
* @param data pointer to table
*/
void setCRC32(unsigned char *data)
{
tbl_h_t *table = (tbl_h_t *)data;
int len = 3 + HILO(table->section_length) - 4; // CRC for complete section but CRC (4 Bytes)
unsigned long crc32 = calculateCRC32(data, len);
// We write the CRC32 to the buffer
data[len] = (crc32 >> 24) & 0xff;
data[len + 1] = (crc32 >> 16) & 0xff;
data[len + 2] = (crc32 >> 8) & 0xff;
data[len + 3] = crc32 & 0xff;
}
12 changes: 12 additions & 0 deletions src/crc32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef _CRC32_H
#define _CRC32_H

#include <stdint.h>

extern uint32_t crc32_table[256];

unsigned long calculateCRC32(const unsigned char *data, int len);

void setCRC32(unsigned char *data);

#endif //_CRC32_H
3 changes: 2 additions & 1 deletion src/mumudvb.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,8 @@ int main (int argc, char **argv)
exit(666); //Right code for a bad daemon no ?
}

//If the user didn't defined a preferred logging way, and we daemonize, we set to syslog (except windows, where we don't, and log to console)
//If the user didn't define a preferred logging way, and we daemonize,
//we set to syslog (except windows, where we don't, and log to console)
if (!no_daemon)
{
if(log_params.log_type==LOGGING_UNDEFINED)
Expand Down
35 changes: 35 additions & 0 deletions src/rewrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,38 @@ void set_continuity_counter(unsigned char *buf,int continuity_counter)
ts_header->continuity_counter=continuity_counter;
}

/** @brief Determines if the table has a newer version than the currently recorded one
*
* In the table there is a field to say if the table was updated
* This function checks if it has changed (in order to rewrite the table only once)
* @note Note in case it change during streaming, it can be a problem,
* and we would have to deal with re-autoconfiguration
* @note Note this function can give false positive since it doesn't check the CRC32
*
* @param mod_log_module The log module of the calling function
* @param stored_version The current version to be checked against
* @param buf the received packet that is to be checked
* @param table_condition pass either NULL or a function that checks the table for preconditions
* @returns true if the packet is the beginning of an applicable table and contains a new version, otherwise false
*/
bool table_needs_update(char *mod_log_module, const int stored_version, unsigned char *buf,
bool (*table_condition)(tbl_h_t *table)) {
tbl_h_t *table=(tbl_h_t *)(get_ts_begin(buf));

// Check if it's the beginning of a new table
if (!table) return false;
/* current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the table
sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable
and shall be the next table to become valid. */
if (table->current_next_indicator == 0) {
return false;
}
if (table_condition != NULL && table_condition(table) == false) {
return false;
}
if (table->version_number!=stored_version) {
log_message(mod_log_module, MSG_DEBUG,"Need update. stored version : %d, new: %d\n",stored_version,table->version_number);
return true;
}
return false;
}
2 changes: 2 additions & 0 deletions src/rewrite.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,6 @@ void eit_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_
void eit_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel,
unicast_parameters_t *unicast_vars, void *scam_vars_v);

bool table_needs_update(char *mod_log_module, int stored_version, unsigned char *buf,
bool (*table_condition)(tbl_h_t *table));
#endif
59 changes: 4 additions & 55 deletions src/rewrite_pat.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,48 +33,15 @@
#include <stdlib.h>
#include <string.h>

#include "crc32.h"
#include "mumudvb.h"
#include "ts.h"
#include "rewrite.h"
#include "log.h"
#include <stdint.h>

extern uint32_t crc32_table[256];
static char *log_module="PAT Rewrite: ";

/** @brief, tell if the pat have a newer version than the one recorded actually
* In the PAT pid there is a field to say if the PAT was updated
* This function check if it has changed (in order to rewrite the pat only once)
* General Note : in case it change during streaming it can be a problem ane we would have to deal with re-autoconfiguration
* Note this function can give flase positive since it doesn't check the CRC32
*
*@param rewrite_vars the parameters for pat rewriting
*@param buf : the received buffer
*/
int pat_need_update(rewrite_parameters_t *rewrite_vars, unsigned char *buf)
{
pat_t *pat=(pat_t*)(get_ts_begin(buf));


if(pat) //It's the beginning of a new packet
{
/*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table
sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable
and shall be the next table to become valid.*/
if(pat->current_next_indicator == 0)
{
return 0;
}
if(pat->version_number!=rewrite_vars->pat_version)
{
log_message( log_module, MSG_DEBUG,"Need update. stored version : %d, new: %d\n",rewrite_vars->pat_version,pat->version_number);
return 1;
}
}
return 0;

}

/** @brief update the version using the dowloaded pat*/
void update_pat_version(rewrite_parameters_t *rewrite_vars)
{
Expand Down Expand Up @@ -187,26 +154,8 @@ int pat_channel_rewrite(rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *c
buf_dest[1+TS_HEADER_LEN]=(((new_section_length)&0x0f00)>>8) | (0xf0 & buf_dest[1+TS_HEADER_LEN]);
buf_dest[2+TS_HEADER_LEN]=new_section_length & 0xff;


//CRC32 calculation inspired by the xine project
//Now we must adjust the CRC32
//we compute the CRC32
crc32=0xffffffff;
for(i = 0; i < new_section_length-1; i++) {
crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ buf_dest[i+TS_HEADER_LEN])&0xff];
}


//We write the CRC32 to the buffer
buf_dest[buf_dest_pos]=(crc32>>24) & 0xff;
buf_dest_pos+=1;
buf_dest[buf_dest_pos]=(crc32>>16) & 0xff;
buf_dest_pos+=1;
buf_dest[buf_dest_pos]=(crc32>>8) & 0xff;
buf_dest_pos+=1;
buf_dest[buf_dest_pos]=crc32 & 0xff;
buf_dest_pos+=1;

setCRC32(buf_dest + TS_HEADER_LEN);
buf_dest_pos += 4;

//Padding with 0xFF
memset(buf_dest+buf_dest_pos,0xFF,TS_PACKET_SIZE-buf_dest_pos);
Expand All @@ -226,7 +175,7 @@ void pat_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_
/*Check the version before getting the full packet*/
if(!rewrite_vars->pat_needs_update)
{
rewrite_vars->pat_needs_update=pat_need_update(rewrite_vars,ts_packet);
rewrite_vars->pat_needs_update=table_needs_update(log_module, rewrite_vars->pat_version, ts_packet, NULL);
}
/*We need to update the full packet, we download it*/
if(rewrite_vars->pat_needs_update)
Expand Down
20 changes: 3 additions & 17 deletions src/rewrite_pmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <string.h>
#include <math.h>

#include "crc32.h"
#include "mumudvb.h"
#include "ts.h"
#include "rewrite.h"
Expand Down Expand Up @@ -179,23 +180,8 @@ int pmt_channel_rewrite(mumudvb_channel_t *channel) {
buf_dest[1 + TS_HEADER_LEN] = (((new_section_length) & 0x0f00) >> 8) | (0xf0 & buf_dest[1 + TS_HEADER_LEN]);
buf_dest[2 + TS_HEADER_LEN] = new_section_length & 0xff;

//CRC32 calculation inspired by the xine project
//Now we must adjust the CRC32
//we compute the CRC32
crc32 = 0xffffffff;
for (i = 0; i < new_section_length - 1; i++) {
crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ buf_dest[i + TS_HEADER_LEN]) & 0xff];
}

//We write the CRC32 to the buffer
buf_dest[buf_dest_pos] = (crc32 >> 24) & 0xff;
buf_dest_pos += 1;
buf_dest[buf_dest_pos] = (crc32 >> 16) & 0xff;
buf_dest_pos += 1;
buf_dest[buf_dest_pos] = (crc32 >> 8) & 0xff;
buf_dest_pos += 1;
buf_dest[buf_dest_pos] = crc32 & 0xff;
buf_dest_pos += 1;
setCRC32(buf_dest);
buf_dest_pos += 4;

//Padding with 0xFF
memset(buf_dest + buf_dest_pos, 0xFF, TS_PACKET_SIZE - buf_dest_pos);
Expand Down
77 changes: 20 additions & 57 deletions src/rewrite_sdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>

#include "crc32.h"
#include "mumudvb.h"
#include "ts.h"
#include "rewrite.h"
Expand All @@ -57,40 +58,16 @@ int sdt_rewrite_all_sections_seen(rewrite_parameters_t *rewrite_vars)
return all_seen;
}



/** @brief, tell if the sdt have a newer version than the one recorded actually
* In the SDT pid there is a field to say if the SDT was updated
* This function check if it has changed (in order to rewrite the sdt only once)
* General Note : in case it change during streaming it can be a problem ane we would have to deal with re-autoconfiguration
* Note this function can give flase positive since it doesn't check the CRC32
*
*@param rewrite_vars the parameters for sdt rewriting
*@param buf : the received buffer
/**
* @brief Check if sdt section describes actual transport stream
*/
int sdt_need_update(rewrite_parameters_t *rewrite_vars, unsigned char *buf)
bool actual_subtable_id(tbl_h_t *section)
{
sdt_t *sdt=(sdt_t*)(get_ts_begin(buf));
if(sdt) //It's the beginning of a new packet
if((sdt->version_number!=rewrite_vars->sdt_version) && (sdt->table_id==0x42))
{
/*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table
sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable
and shall be the next table to become valid.*/
if(sdt->current_next_indicator == 0)
{
return 0;
}
log_message( log_module, MSG_DEBUG,"Need update. stored version : %d, new: %d\n",rewrite_vars->sdt_version,sdt->version_number);
if(rewrite_vars->sdt_version!=-1)
log_message( log_module, MSG_INFO,"The SDT version changed, so the channels names changed probably.\n");
return 1;
}
return 0;

const sdt_t *sdt_section = (sdt_t*)section;
return sdt_section->table_id == SDT_ACTUAL_TS;
}

/** @brief update the version using the dowloaded SDT*/
/** @brief update the version using the downloaded SDT*/
void update_sdt_version(rewrite_parameters_t *rewrite_vars)
{
sdt_t *sdt=(sdt_t*)(rewrite_vars->full_sdt->data_full);
Expand Down Expand Up @@ -154,7 +131,8 @@ int sdt_channel_rewrite(rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *c

if(!channel->service_id)
{
log_message( log_module, MSG_WARN,"Cannot rewrite a program without the service_id set. We deactivate SDT rewrititng for this channel %d : \"%s\"\n", curr_channel, channel->name);
log_message( log_module, MSG_WARN,"Cannot rewrite a program without the service_id set. "
"We deactivate SDT rewrititng for this channel %d : \"%s\"\n", curr_channel, channel->name);
channel->sdt_rewrite_skip=1;
return 0;
}
Expand Down Expand Up @@ -234,7 +212,7 @@ int sdt_channel_rewrite(rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *c
else
{
log_message( log_module, MSG_DETAIL,"NEW program for channel %d : \"%s\". service_id : %d\n", curr_channel, channel->name,channel->service_id);
//we found a announce for a program in our stream, we keep it
//we found an announcement for a program in our stream, we keep it
//We fill the descriptor loop length
t_buffer_ptr->descriptors_loop_length_lo = (loop_length & 0x00FF);
t_buffer_ptr->descriptors_loop_length_hi = (loop_length & 0xFF00)>>8;
Expand Down Expand Up @@ -274,27 +252,8 @@ int sdt_channel_rewrite(rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *c
buf_dest[1+TS_HEADER_LEN]=(((new_section_length)&0x0f00)>>8) | (0xf0 & buf_dest[1+TS_HEADER_LEN]);
buf_dest[2+TS_HEADER_LEN]=new_section_length & 0xff;


//CRC32 calculation inspired by the xine project
//Now we must adjust the CRC32
//we compute the CRC32
crc32=0xffffffff;
int i;
for(i = 0; i < new_section_length-1; i++) {
crc32 = (crc32 << 8) ^ crc32_table[((crc32 >> 24) ^ buf_dest[i+TS_HEADER_LEN])&0xff];
}


//We write the CRC32 to the buffer
buf_dest[buf_dest_pos]=(crc32>>24) & 0xff;
buf_dest_pos+=1;
buf_dest[buf_dest_pos]=(crc32>>16) & 0xff;
buf_dest_pos+=1;
buf_dest[buf_dest_pos]=(crc32>>8) & 0xff;
buf_dest_pos+=1;
buf_dest[buf_dest_pos]=crc32 & 0xff;
buf_dest_pos+=1;

setCRC32(buf_dest + TS_HEADER_LEN);
buf_dest_pos += 4;

//Padding with 0xFF
memset(buf_dest+buf_dest_pos,0xFF,TS_PACKET_SIZE-buf_dest_pos);
Expand Down Expand Up @@ -337,9 +296,12 @@ int sdt_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t
/*Check the version before getting the full packet*/
if(!rewrite_vars->sdt_needs_update)
{
rewrite_vars->sdt_needs_update=sdt_need_update(rewrite_vars,ts_packet);
if(rewrite_vars->sdt_needs_update) //It needs update we mark the packet as empty and we clear the sections seen
rewrite_vars->sdt_needs_update = table_needs_update(log_module, rewrite_vars->sdt_version,
ts_packet, actual_subtable_id);
if(rewrite_vars->sdt_needs_update) //It needs update we mark the packet as empty, and we clear the sections seen
{
if(rewrite_vars->sdt_version != -1)
log_message( log_module, MSG_INFO,"The SDT version changed, so the channels names changed probably.");
//We clear the section numbers seen
memset(&rewrite_vars->sdt_section_numbers_seen,0,sizeof(rewrite_vars->sdt_section_numbers_seen));
}
Expand Down Expand Up @@ -393,8 +355,9 @@ int sdt_rewrite_new_global_packet(unsigned char *ts_packet, rewrite_parameters_t
}


/** @brief This function is called when a new SDT packet for a channel is there and we asked for rewrite
* This function copy the rewritten SDT to the buffer. And checks if the SDT was changed so the rewritten version have to be updated
/** @brief This function is called when a new SDT packet for a channel is there, and we asked for rewrite
* This function copies the rewritten SDT to the buffer and checks if the SDT was changed
* so the rewritten version has to be updated
*/
int sdt_rewrite_new_channel_packet(unsigned char *ts_packet, rewrite_parameters_t *rewrite_vars, mumudvb_channel_t *channel, int curr_channel)
{
Expand Down
4 changes: 2 additions & 2 deletions src/ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ void add_ts_packet_data(unsigned char *buf, mumudvb_ts_packet_t *pkt, int data_l
* * the continuity counter which is incremented for each packet
* * The payload_unit_start_indicator which says if it's the first packet
*
* When a packet is splitted in 188 bytes packets, there must be no other PID between two sub packets
* When a packet is split in 188 bytes packets, there must be no other PID between two sub packets
*
* Return 1 when there is one packet full and OK
*
* @param buf : the received buffer from the card
* @param ts_packet : the packet to be completed
* @param pkt : the packet to be completed
*/
int get_ts_packet(unsigned char *buf, mumudvb_ts_packet_t *pkt)
{
Expand Down
Loading