The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
// VERSION = "1.000"
//
// Standard C code loaded outside XS space. Contains useful routines used by ts TS parsing functions

// VERSION 1.01

#include "ts_split.h"

//========================================================================================================
// SPLIT
//========================================================================================================

//---------------------------------------------------------------------------------------------------------
//
static void next_split_file(struct TS_cut_data *hook_data, unsigned pktnum)
{
	// close currently open
	if (hook_data->cut_file)
	{
		if (pktnum > hook_data->split_pkt)
		{
			close(hook_data->cut_file) ;
			hook_data->cut_file = 0 ;
		}
	}

	// open next
	if (!hook_data->cut_file)
	{
	char cutname[256] ;

		hook_data->split_pkt = pktnum ;

		sprintf(cutname, "%s-%04u.ts",
				hook_data->ofname, ++hook_data->split_count) ;

		if (hook_data->debug) printf("New split file %s at pkt %d\n", cutname, pktnum) ;


		hook_data->cut_file = open(cutname, O_CREAT | O_TRUNC | O_WRONLY | O_LARGEFILE, 0666);

		if (hook_data->debug >= 10) printf("-> save cut sequence: %s [%d]\n", cutname, hook_data->cut_file) ;
	}

}

//---------------------------------------------------------------------------------------------------------
// void (*tsparse_ts_hook)(unsigned long, unsigned, const uint8_t *, unsigned, unsigned, unsigned) ;
static void ts_split_hook(struct TS_pidinfo *pidinfo, uint8_t *packet, unsigned packet_len, void *user_data)
{
struct TS_cut_data *hook_data = (struct TS_cut_data *)user_data ;
//static unsigned prev_ok=1;
//unsigned ok = 1 ;

	if (hook_data->debug >= 10)
	{
		printf("-> TS PID 0x%x (%u) [%u] :: start=%d err=%d\n",
				pidinfo->pid, pidinfo->pid,
				pidinfo->pktnum,
				pidinfo->pes_start ? 1 : 0,
				pidinfo->pid_error ? 1 : 0) ;
	}

	// check cut
	if (hook_data->current_cut == UNSET_CUT_LIST)
	{
	struct list_head *item;

		list_for_each(item, hook_data->cut_list)
		{
			hook_data->current_cut = list_entry(item, struct TS_cut, next);
//			next_split_file(hook_data) ;
//			if (hook_data->debug) printf("New split file %04d at pkt %d\n", hook_data->split_count, pidinfo->pktnum) ;
			break;
		}
	}

	if (hook_data->current_cut != END_CUT_LIST)
	{
		// check current
		if (pidinfo->pktnum < hook_data->current_cut->start)
		{
			// still before start of next band
		}
		else
		{
			// Now >= start

			// New file at start of region
			if ( pidinfo->pktnum == hook_data->current_cut->start )
			{
				// save next band into new file
				next_split_file(hook_data, pidinfo->pktnum) ;
			}

			// writing : start -> end
			else if (pidinfo->pktnum < hook_data->current_cut->end)
			{
			}

			// writing : end
			else if (pidinfo->pktnum == hook_data->current_cut->end)
			{
//				// save next band into new file
//				next_split_file(hook_data, pidinfo->pktnum) ;
			}

			// beyond end
			else
			{
			struct list_head *item;

				// ok, beyond this cut band - find next cut region
				do
				{
					list_next_each(hook_data->current_cut, END_CUT_LIST, item, hook_data->cut_list)
					{
						hook_data->current_cut = list_entry(item, struct TS_cut, next);
						break;
					}
				} while ( (hook_data->current_cut != END_CUT_LIST) && (pidinfo->pktnum > hook_data->current_cut->start) ) ;

//				prev_ok=1;

//				// save next band into new file
				next_split_file(hook_data, pidinfo->pktnum) ;
//				if (hook_data->debug) printf("New split file %04d at pkt %d\n", hook_data->split_count, pidinfo->pktnum) ;
			}
		}
	}

	if (hook_data->debug >= 10)
	{
		printf("-> TS PID 0x%x (%u) [%u]\n",
				pidinfo->pid, pidinfo->pid,
				pidinfo->pktnum) ;
	}

	// write if allowed to
	if (hook_data->cut_file)
	{
		write(hook_data->cut_file, packet, packet_len);
	}
}



//---------------------------------------------------------------------------------------------------------
int ts_split(char *filename, char *ofilename, struct list_head *cuts_array, unsigned debug)
{
int file;
struct TS_cut_data hook_data ;
struct TS_reader *tsreader ;

	hook_data.cut_list = cuts_array ;

	hook_data.current_cut = UNSET_CUT_LIST ;
	hook_data.debug = debug ;
	hook_data.ofile = 0 ;
	hook_data.split_count = 0 ;
	hook_data.cut_file = 0 ;
    hook_data.ofile = 0 ;

	tsreader = tsreader_new(filename) ;
    if (!tsreader)
    {
    	return(dvb_error_code);
    }
	tsreader->ts_hook = ts_split_hook ;
	tsreader->user_data = &hook_data ;
	tsreader->debug = debug ;

	remove_ext(filename, hook_data.fname) ;
	remove_ext(ofilename, hook_data.ofname) ;

	// start first file
	next_split_file(&hook_data, 0) ;

	// parse data
    ts_parse(tsreader) ;

    if (hook_data.cut_file)
    	close(hook_data.cut_file) ;

	tsreader_free(tsreader) ;
	free_cut_list(hook_data.cut_list) ;

	return(dvb_error_code) ;
}