The following code excerpt is the "engine" of NullPacketStripper, made public on request.
Look at the function doOne() for a starting point. As you can see, it's pretty trivial.

Olli
nps@hometheatersoftware.com

=====8<=====

	private class DoThread extends Thread
	{
		byte inblock[]=new byte[188];
		
		private class PGUpdater implements Runnable
		{
			long offs;
			public void run()
			{
				pg.setValue((int)(offs/188));
			}
		}
		PGUpdater upd=new PGUpdater();
		
		private BufferedOutputStream fos;
		private long fos_segsize, fos_segoffs;
		private int fos_segcnt;
		private String fos_name;
		private void prepareFOS()
		{
			try
			{
				String spec=comb_split.getEditor().getItem().toString();
				StringBuffer sb=new StringBuffer();
				boolean b_found=false, k_found=false, g_found=false;
				for(int c=0;c<spec.length();c++)
				{
					if(Character.isDigit(spec.charAt(c)))
					{
						sb.append(spec.charAt(c));
					}
					else
						switch(spec.charAt(c))
						{
							case 'b':
							case 'B':
								b_found=true;
								break;
							
							case 'k':
							case 'K':
								k_found=true;
								break;
							
							case 'g':
							case 'G':
								g_found=true;
								break;
								
							case 'm':
							case 'M':
								c=Integer.MAX_VALUE-1;
								continue;
						}
				}
				fos_segsize=Long.parseLong(sb.toString());
				if(k_found)
					fos_segsize*=1024;
				else if(g_found)
					fos_segsize*=1024*1024*1024;
				else if(!b_found)
					fos_segsize*=1024*1024;
				addLog("Splitting files at "+fos_segsize+" bytes");
			}
			catch(Exception e)
			{
				fos_segsize=0;
			}	
			fos_segoffs=0;
			fos_segcnt=0;
			fos_name=tf_output.getText();
			if(fos_segsize>0)
			{
				// already remove .ts if present
				if(fos_name.toLowerCase().endsWith(".ts"))
					fos_name=fos_name.substring(0,fos_name.length()-2);
			}
		}
		
		private void createFOS() throws Exception
		{
			String name=fos_name;
			if(fos_segsize>0)
			{
				if(fos!=null)
					fos.close();
				// Create new name
				name=name+(new DecimalFormat("0000")).format(fos_segcnt)+".ts";
				fos_segcnt++;
				fos_segoffs=0;
			}
			else if(fos!=null)
				return;
			
			File f=new File(name);
			if(f.exists())
			{
				String msg="<HTML>File <B>"+name+"</B> already exists.\nSize: "+f.length()+"\nDate: "+(new Date(f.lastModified()))+"\n\nDo you want to overwrite the existing file?";
				
				if(JOptionPane.showConfirmDialog(Main.this,msg,"Please confirm",JOptionPane.YES_NO_OPTION,JOptionPane.WARNING_MESSAGE)!=JOptionPane.YES_OPTION)
					throw new RuntimeException("User abort");
			}
			
			addLog("Writing to "+name);
			fos=new BufferedOutputStream(new FileOutputStream(name), 256*1024);
		}
		
		private void doOne(File inf,int skipms) throws Exception
		{	
			BufferedInputStream fis=new BufferedInputStream(new FileInputStream(inf),512*1024);
			HashMap ptsByPid=new HashMap();
			
			if(fos==null)
				createFOS();
			
			int readblocks=0, wroteblocks=0, errors=0, skipped_1fff=0, skipped_1fef=0, skipped_blocks=0;
			
			final long filesize=inf.length();
			
			SwingUtilities.invokeLater(new Runnable(){
				public void run()
				{
					pg.setValue(0);
					pg.setMaximum((int)(filesize/188));
				}
			});
			
			upd.offs=0;
			for(;;)
			{
				fis.mark(188);
				int rc=fis.read(inblock);
				if(rc<0)
					break; // End of tile
				upd.offs+=188;
				if(rc!=inblock.length)
				{
					addLog(" Only read "+rc+" bytes, looks like an incomplete or badly cut file");
					errors++;
					break;
				}
				readblocks++;
				
				if(inblock[0]!=0x47)
				{
					fis.reset();
					int ch,skipped=0;
					do
					{
						fis.mark(1);
						ch=fis.read();
						skipped++;
					} while(ch>=0&&ch!=0x47);
					upd.offs+=skipped-188;
					addLog(" Sync error; got 0x"+Integer.toHexString(inblock[0])+" instead of 0x47 at block "+readblocks+"; skipped "+skipped+" bytes");
					fis.reset();
					errors++;
					continue;
				}
				
				int pid=((inblock[1]<<8)|(inblock[2]&0xff))&0x1fff;
				//int pid=((inblock[2]<<8)+inblock[1])&0x1fff;
				//addLog("pid:"+Integer.toHexString(pid)+" "+inblock[1]+" "+inblock[2]);
				//Thread.yield();
				
				// Check adaption present
				if(skipms>0)
				{
					if(((inblock[3]&(1<<5))!=0))
					{
						// and PCR present
						if((inblock[5]&(1<<4))!=0)
						{
							long pts=
								  ((inblock[6]&0xffl)<<24)
								| ((inblock[7]&0xffl)<<16)
								| ((inblock[8]&0xffl)<<8)
								| ((inblock[9]&0xffl)<<0)
							;

							Long oldptsLong=(Long)ptsByPid.get(new Integer(pid));
							if(oldptsLong!=null)
							{
								long oldpts=oldptsLong.longValue();
								if(pts-oldpts>(skipms*90))
								{
									addLog("Skipped "+skipms+"ms after "+skipped_blocks+" blocks");
									skipms=0;
									ptsByPid=null;
								}
								else if(oldpts>pts)
									ptsByPid.put(new Integer(pid),new Long(pts));
							}
							else
								ptsByPid.put(new Integer(pid),new Long(pts));
						}
					}
					if(skipms>0)
					{
						skipped_blocks++;
						continue;
					}
				}
				
			
				if(pid!=0x1fff&&pid!=0x1fef)
				{
					fos.write(inblock);
					wroteblocks++;
					
					if(wroteblocks%5000==0)
						SwingUtilities.invokeLater(upd);
					if(fos_segsize>0)
					{
						fos_segoffs+=188;
						if(fos_segoffs>fos_segsize)
							createFOS();
					}
				}
				else if(pid==0x1fff)
					skipped_1fff++;
				else if(pid==0x1fef)
					skipped_1fef++;
					
				if(Thread.interrupted())
					throw new RuntimeException("User abort");
			}
			double perc=0;
			if(readblocks>0)
				perc=(wroteblocks*100.0)/readblocks;
			String errortxt="";
			if(errors>0)
				errortxt+=", "+errors+" sync errors";
			addLog("Done with that file; read "+readblocks+" TS packets, wrote "+wroteblocks+" TS packets ("+(new DecimalFormat("0.00")).format(perc)+"%, dropped "+skipped_1fef+" 0x1fef and "+skipped_1fff+" 0x1fff)"+errortxt);
			fis.close();
		}
		
		private void doIt() throws Exception
		{
			String currentname=tf_input.getText();
			File currentfile=new File(currentname);
			File files[];
			if(currentname.matches(".*\\.\\d{4}\\.ts"))
			{
				File dir=currentfile.getParentFile();
				String pattern=currentfile.getName();
				final String matchpattern="\\Q"+pattern.replaceAll("\\d{4}", "\\\\E\\\\d{4}\\\\Q")+"\\E";
				files=dir.listFiles(new FilenameFilter(){
					public boolean accept(File f,String name)
					{
						return name.matches(matchpattern);
					}
				});
				if(files==null)
				{
					throw new RuntimeException("No input files found");
				}
				//currentname=currentname.replaceAll("\\.\\d{4}\\."
				Arrays.sort(files);
			}
			else
			{
				files=new File[1];
				files[0]=currentfile;
			}
			prepareFOS();
			
			long totalsize=0;
			for(int fix=0;fix<files.length;fix++)
			{
				totalsize+=files[fix].length();
			}
			addLog("Processing "+files.length+" file(s), total size "+(totalsize/1024/1024)+"MB");
			
			int skipms=((Number)tf_skip.getValue()).intValue();
			
			for(int fix=0;fix<files.length;fix++)
			{
				addLog("Processing "+files[fix]);
				doOne(files[fix],skipms);
				skipms=0;
			}
			addLog("Done");
		}
		
		public DoThread()
		{
			super("Processing Thread");
			setDaemon(true);
			setPriority(NORM_PRIORITY-1);
		}
		
		public void run()
		{
			try
			{
				doIt();
			}
			catch(Exception e)
			{
				addLog("\nError: "+e.getMessage());
			}
			if(fos!=null)
			{
				try
				{
					fos.close();
					fos=null;
				}
				catch(Exception e2){}
			}
			
			working=null;
			SwingUtilities.invokeLater(new Runnable(){
				public void run()
				{
					tf_input.setEnabled(true);
					tf_output.setEnabled(true);
					pop_input.setEnabled(true);
					pop_output.setEnabled(true);
					comb_split.setEnabled(true);
					bt_go.setText("Start processing");
				}
			});
		}
	}
