diff --git a/Makefile b/Makefile index 4dbe069..55f1e68 100644 --- a/Makefile +++ b/Makefile @@ -134,7 +134,8 @@ PROG_OBJS = \ $(OBJDIR)/tsserve.o \ $(OBJDIR)/ts_packet_insert.o \ $(OBJDIR)/m2ts2ts.o \ - $(OBJDIR)/pcapreport.o + $(OBJDIR)/pcapreport.o \ + $(OBJDIR)/tsfilter.o #\ # $(OBJDIR)/test_ps.o @@ -175,7 +176,8 @@ PROGS = \ $(BINDIR)/tsserve \ $(BINDIR)/ts_packet_insert \ $(BINDIR)/m2ts2ts \ - $(BINDIR)/pcapreport + $(BINDIR)/pcapreport \ + $(BINDIR)/tsfilter #\ # $(BINDIR)/test_ps @@ -269,6 +271,9 @@ $(BINDIR)/m2ts2ts: $(OBJDIR)/m2ts2ts.o $(STATIC_LIB) $(BINDIR)/pcapreport: $(OBJDIR)/pcapreport.o $(STATIC_LIB) $(CC) $< -o $(BINDIR)/pcapreport $(LDFLAGS) $(LIBOPTS) +$(BINDIR)/tsfilter: $(OBJDIR)/tsfilter.o $(STATIC_LIB) + $(CC) $< -o $(BINDIR)/tsfilter $(LDFLAGS) $(LIBOPTS) + @@ -354,6 +359,9 @@ $(OBJDIR)/m2ts2ts.o: m2ts2ts.c $(TS_H) misc_fns.h version.h $(OBJDIR)/pcapreport.o: pcapreport.c pcap.h version.h misc_fns.h $(CC) -c $< -o $@ $(CFLAGS) +$(OBJDIR)/tsfilter.o: tsfilter.c version.h misc_fns.h + $(CC) -c $< -o $@ $(CFLAGS) + $(OBJDIR)/test_pes.o: test_pes.c $(TS_H) $(PS_H) $(ES_H) misc_fns.h $(PES_H) version.h $(CC) -c $< -o $@ $(CFLAGS) $(OBJDIR)/test_printing.o: test_printing.c $(TS_H) $(PS_H) $(ES_H) version.h diff --git a/ts.c b/ts.c index a2194b1..9610636 100755 --- a/ts.c +++ b/ts.c @@ -1400,6 +1400,7 @@ static int read_next_TS_packets(TS_reader_p tsreader, length = read(tsreader->file, &(tsreader->read_ahead[total]), TS_READ_AHEAD_BYTES - total); + if (length == 0) // EOF - no more data to read break; else if (length == -1) diff --git a/tsfilter.c b/tsfilter.c new file mode 100644 index 0000000..e8748c8 --- /dev/null +++ b/tsfilter.c @@ -0,0 +1,247 @@ +/* + * Filter a transport stream by a list of pids. + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the MPEG TS, PS and ES tools. + * + * The Initial Developer of the Original Code is Amino Communications Ltd. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. +* + * Contributor(s): + * Amino Communications Ltd, Swavesey, Cambridge UK + * + * ***** END LICENSE BLOCK ***** + */ + +#ifdef _WIN32 +#include +#else // _WIN32 +#include +#endif // _WIN32 + +#include +#include +#include +#include "compat.h" +#include "ts_fns.h" +#include "misc_fns.h" +#include "printing_fns.h" +#include "pidint_fns.h" +#include "version.h" +#include "tswrite_defns.h" +#include "tswrite_fns.h" + +/** List of PIDs to filter in */ +int *pidList = NULL; +int pidListAlloc = 0, pidListUsed = 0; + +static void print_usage(void); + +void ensurePidList(int nr) +{ + if (pidListAlloc > nr) { return; } + pidListAlloc = nr; + pidList = realloc(pidList, pidListAlloc * sizeof(int)); +} + + + +int main(int argn, char *args[]) +{ + int ii = 1; + int verbose = FALSE; + const char *input_file = NULL, *output_file = NULL; + + + if (argn < 2) + { + print_usage(); + return 0; + } + + ensurePidList(1024); + + while (ii < argn) + { + if (args[ii][0] == '-') + { + if (!strcmp("--help", args[ii]) || !strcmp("-h", args[ii]) || + !strcmp("-help", args[ii])) + { + print_usage(); + return 0; + } + else if (!strcmp("-verbose", args[ii]) || !strcmp("-v", args[ii])) + { + verbose = TRUE; + } + else if (!strcmp("-i", args[ii]) || !strcmp("-input", args[ii])) + { + if (argn <= ii) + { + fprint_err("### tsfilter: -input requires an argument\n"); + return 1; + } + input_file = args[ii+1]; + ++ii; + } + else if (!strcmp("-o", args[ii]) || !strcmp("-output", args[ii])) + { + if (argn <= ii) + { + fprint_err("### tsfilter: -output requires an argument\n"); + return 1; + } + output_file = args[ii+1]; + ++ii; + } + else + { + fprint_err("### tsfilter: " + "Unrecognised command line switch '%s'\n", args[ii]); + return 1; + } + } + else + { + char *p = NULL; + // It's a pid. + if (pidListUsed >= pidListAlloc) + { + ensurePidList(pidListAlloc + 1024); + } + + pidList[pidListUsed] = strtoul(args[ii], &p, 0); + if (!(p && *p == '\0')) + { + fprint_err("### tsfilter: '%s' wasn't a valid number. \n", + args[ii]); + return 1; + } + ++pidListUsed; + } + ++ii; + } + + if (!pidListUsed) + { + fprint_err("### tsfilter: No pids to filter. \n"); + return 1; + } + + // Now .. + { + int err; + TS_reader_p tsreader; + TS_writer_p tswriter; + byte *pkt = NULL; + + unsigned int pid; + int pusi, adapt_len, payload_len; + byte *adapt, *payload; + + + err = open_file_for_TS_read((char *)input_file, &tsreader); + if (err) + { + fprint_err("## tsfilter: Unable to open stdin for reading TS.\n"); + return 1; + } + if (output_file) + { + err = tswrite_open(TS_W_FILE, (char *)output_file, NULL, 0, 1, &tswriter); + } + else + { + err = tswrite_open(TS_W_STDOUT, NULL, NULL, 0, 1, &tswriter); + } + if (err) + { + fprint_err("## tsfilter: Unable to open stdout for writing TS. \n"); + return 1; + } + + while (1) + { + err = read_next_TS_packet(tsreader, &pkt); + if (err == EOF) + { + /* We're done */ + break; + } + + err = split_TS_packet(pkt, &pid, &pusi, &adapt, &adapt_len, &payload, + &payload_len); + if (err) + { + fprint_err("### Error splitting TS packet - continuing. \n"); + } + else + { + int i; + int found = 0; + + for (i = 0 ;i < pidListUsed; ++i) + { + if (pid == pidList[i]) + { + ++found; // Yes! + break; + } + } + if (found) + { + // Write it out. + err = tswrite_write(tswriter, + pkt, + pid, + 0, 0); + + if (err) + { + fprint_err("### Error writing output - %d \n", err); + return 2; + } + } + } + } + + // It's the end! + tswrite_close(tswriter, 1); + close_TS_reader(&tsreader); + return 0; + } +} + +static void print_usage(void) +{ + print_msg( + "Usage: tsfilter [switches] ... \n" + "\n"); + REPORT_VERSION("tsfilter"); + print_msg( + "\n" + " Filter the given pids out of stdin and write the result on stdout.\n" + "\n" + "Switches:\n" + " -i Take input from this file and not stdin.\n" + " -o Send output to this file and not stdout.\n" + " -verbose, -v Be verbose.\n" + ); +} + +/* End file */ +