001/* JOrbis
002 * Copyright (C) 2000 ymnk, JCraft,Inc.
003 *  
004 * Written by: 2000 ymnk<ymnk@jcaft.com>
005 *   
006 * Many thanks to 
007 *   Monty <monty@xiph.org> and 
008 *   The XIPHOPHORUS Company http://www.xiph.org/ .
009 * JOrbis has been based on their awesome works, Vorbis codec.
010 *   
011 * This program is free software; you can redistribute it and/or
012 * modify it under the terms of the GNU Library General Public License
013 * as published by the Free Software Foundation; either version 2 of
014 * the License, or (at your option) any later version.
015   
016 * This program is distributed in the hope that it will be useful,
017 * but WITHOUT ANY WARRANTY; without even the implied warranty of
018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
019 * GNU Library General Public License for more details.
020 * 
021 * You should have received a copy of the GNU Library General Public
022 * License along with this program; if not, write to the Free Software
023 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
024 */
025
026package com.jcraft.jogg;
027
028public class Page{
029  private static int[] crc_lookup=new int[256];
030  static {
031    for(int i=0; i<crc_lookup.length; i++){
032      crc_lookup[i]=crc_entry(i);
033    }
034  }
035
036  private static int crc_entry(int index){
037    int r=index<<24;
038    for(int i=0; i<8; i++){
039      if((r& 0x80000000)!=0){
040        r=(r << 1)^0x04c11db7; /* The same as the ethernet generator
041                                  polynomial, although we use an
042                                  unreflected alg and an init/final
043                                  of 0, not 0xffffffff */
044      }
045      else{
046        r<<=1;
047      }
048    }
049    return(r&0xffffffff);
050  }
051
052  public byte[] header_base;
053  public int header;
054  public int header_len;
055  public byte[] body_base;
056  public int body;
057  public int body_len;
058
059  int version(){
060    return header_base[header+4]&0xff;
061  }
062  int continued(){
063    return (header_base[header+5]&0x01);
064  }
065  public int bos(){
066    return (header_base[header+5]&0x02);
067  }
068  public int eos(){
069    return (header_base[header+5]&0x04);
070  }
071  public long granulepos(){
072    long foo=header_base[header+13]&0xff;
073    foo=(foo<<8)|(header_base[header+12]&0xff);
074    foo=(foo<<8)|(header_base[header+11]&0xff);
075    foo=(foo<<8)|(header_base[header+10]&0xff);
076    foo=(foo<<8)|(header_base[header+9]&0xff);
077    foo=(foo<<8)|(header_base[header+8]&0xff);
078    foo=(foo<<8)|(header_base[header+7]&0xff);
079    foo=(foo<<8)|(header_base[header+6]&0xff);
080    return(foo);
081  }
082  public int serialno(){
083    return (header_base[header+14]&0xff)|
084           ((header_base[header+15]&0xff)<<8)|
085           ((header_base[header+16]&0xff)<<16)|
086           ((header_base[header+17]&0xff)<<24);
087  }
088  int pageno(){
089    return (header_base[header+18]&0xff)|
090           ((header_base[header+19]&0xff)<<8)|
091           ((header_base[header+20]&0xff)<<16)|
092           ((header_base[header+21]&0xff)<<24);
093  }
094
095  void checksum(){
096    int crc_reg=0;
097
098//  for(int i=0;i<header_len;i++){
099//    System.err.println("chksum: "+Integer.toHexString(header_base[header+i]&0xff));
100//  }
101    
102    for(int i=0;i<header_len;i++){
103      crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg>>>24)&0xff)^(header_base[header+i]&0xff)];
104    }
105    for(int i=0;i<body_len;i++){
106      crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg>>>24)&0xff)^(body_base[body+i]&0xff)];
107    }
108    header_base[header+22]=(byte)crc_reg/*&0xff*/;
109    header_base[header+23]=(byte)(crc_reg>>>8)/*&0xff*/;
110    header_base[header+24]=(byte)(crc_reg>>>16)/*&0xff*/;
111    header_base[header+25]=(byte)(crc_reg>>>24)/*&0xff*/;
112  }
113
114  /*
115  // TEST
116  static StreamState os_en, os_de;
117  static SyncState oy;
118  void check_page(byte[] data_base, int data, int[] _header){
119    // Test data
120    for(int j=0;j<body_len;j++)
121      if(body_base[body+j]!=data_base[data+j]){
122        System.err.println("body data mismatch at pos "+j+": "+data_base[data+j]+"!="+body_base[body+j]+"!\n");
123      System.exit(1);
124    }
125
126    // Test header
127    for(int j=0;j<header_len;j++){
128      if((header_base[header+j]&0xff)!=_header[j]){
129        System.err.println("header content mismatch at pos "+j);
130        for(int jj=0;jj<_header[26]+27;jj++)
131          System.err.print(" ("+jj+")"+Integer.toHexString(_header[jj])+":"+Integer.toHexString(header_base[header+jj]));
132        System.err.println("");
133        System.exit(1);
134      }
135    }
136    if(header_len!=_header[26]+27){
137      System.err.print("header length incorrect! ("+header_len+"!="+(_header[26]+27)+")");
138      System.exit(1);
139    }
140  }
141
142  void print_header(){
143    System.err.println("\nHEADER:");
144    System.err.println("  capture: "+
145                       (header_base[header+0]&0xff)+" "+
146                       (header_base[header+1]&0xff)+" "+
147                       (header_base[header+2]&0xff)+" "+
148                       (header_base[header+3]&0xff)+" "+
149                       " version: "+(header_base[header+4]&0xff)+"  flags: "+
150                       (header_base[header+5]&0xff));
151    System.err.println("  pcmpos: "+
152                       (((header_base[header+9]&0xff)<<24)|
153                        ((header_base[header+8]&0xff)<<16)|
154                        ((header_base[header+7]&0xff)<<8)|
155                        ((header_base[header+6]&0xff)))+
156                       "  serialno: "+
157                       (((header_base[header+17]&0xff)<<24)|
158                        ((header_base[header+16]&0xff)<<16)|
159                        ((header_base[header+15]&0xff)<<8)|
160                        ((header_base[header+14]&0xff)))+
161                       "  pageno: "+
162                       (((header_base[header+21]&0xff)<<24)|
163                        ((header_base[header+20]&0xff)<<16)|
164                        ((header_base[header+19]&0xff)<<8)|
165                        ((header_base[header+18]&0xff))));
166
167    System.err.println("  checksum: "+
168                       (header_base[header+22]&0xff)+":"+
169                       (header_base[header+23]&0xff)+":"+
170                       (header_base[header+24]&0xff)+":"+
171                       (header_base[header+25]&0xff)+"\n  segments: "+
172                       (header_base[header+26]&0xff)+" (");
173    for(int j=27;j<header_len;j++){
174      System.err.println((header_base[header+j]&0xff)+" ");
175    }
176    System.err.println(")\n");
177  }
178
179  void copy_page(){
180    byte[] tmp=new byte[header_len];
181    System.arraycopy(header_base, header, tmp, 0, header_len);
182    header_base=tmp;
183    header=0;
184    tmp=new byte[body_len];
185    System.arraycopy(body_base, body, tmp, 0, body_len);
186    body_base=tmp;
187    body=0;
188  }
189
190  static void test_pack(int[] pl, int[][] headers){
191    byte[] data=new byte[1024*1024]; // for scripted test cases only
192    int inptr=0;
193    int outptr=0;
194    int deptr=0;
195    int depacket=0;
196    int pcm_pos=7;
197    int packets,pageno=0,pageout=0;
198    int eosflag=0;
199    int bosflag=0;
200
201    os_en.reset();
202    os_de.reset();
203    oy.reset();
204
205    for(packets=0;;packets++){
206      if(pl[packets]==-1)break;
207    }
208
209    for(int i=0;i<packets;i++){
210      // construct a test packet
211      Packet op=new Packet();
212      int len=pl[i];
213      op.packet_base=data;
214      op.packet=inptr;
215      op.bytes=len;
216      op.e_o_s=(pl[i+1]<0?1:0);
217      op.granulepos=pcm_pos;
218
219      pcm_pos+=1024;
220
221      for(int j=0;j<len;j++){
222        data[inptr++]=(byte)(i+j);
223      }
224
225      // submit the test packet
226      os_en.packetin(op);
227
228      // retrieve any finished pages
229      {
230        Page og=new Page();
231      
232        while(os_en.pageout(og)!=0){
233          // We have a page.  Check it carefully
234          //System.err.print(pageno+", ");
235          if(headers[pageno]==null){
236            System.err.println("coded too many pages!");
237            System.exit(1);
238          }
239          og.check_page(data, outptr, headers[pageno]);
240
241          outptr+=og.body_len;
242          pageno++;
243
244//System.err.println("1# pageno="+pageno+", pageout="+pageout);
245
246          // have a complete page; submit it to sync/decode
247          
248          {
249            Page og_de=new Page();
250            Packet op_de=new Packet();
251            int index=oy.buffer(og.header_len+og.body_len);
252            byte[] buf=oy.data;
253           System.arraycopy(og.header_base, og.header, buf, index, og.header_len);
254           System.arraycopy(og.body_base, og.body, buf, index+og.header_len, og.body_len);
255            oy.wrote(og.header_len+og.body_len);
256
257//System.err.println("2# pageno="+pageno+", pageout="+pageout);
258
259            while(oy.pageout(og_de)>0){
260              // got a page.  Happy happy.  Verify that it's good.
261            
262              og_de.check_page(data, deptr, headers[pageout]);
263              deptr+=og_de.body_len;
264              pageout++;
265
266              // submit it to deconstitution
267              os_de.pagein(og_de);
268
269              // packets out?
270              while(os_de.packetout(op_de)>0){
271              
272                // verify the packet!
273                // check data
274                boolean check=false;
275                for(int ii=0; ii<op_de.bytes; ii++){
276                  if(data[depacket+ii]!=op_de.packet_base[op_de.packet+ii]){
277                    check=true;
278                    break;
279                  }
280                }
281                if(check){
282                  System.err.println("packet data mismatch in decode! pos="+
283                                     depacket);
284                  System.exit(1);
285                }
286
287                // check bos flag
288                if(bosflag==0 && op_de.b_o_s==0){
289                  System.err.println("b_o_s flag not set on packet!");
290                  System.exit(1);
291                }
292                if(bosflag!=0 && op_de.b_o_s!=0){
293                  System.err.println("b_o_s flag incorrectly set on packet!");
294                  System.exit(1);
295                }
296              
297                bosflag=1;
298                depacket+=op_de.bytes;
299              
300                // check eos flag
301                if(eosflag!=0){
302                  System.err.println("Multiple decoded packets with eos flag!");
303                  System.exit(1);
304                }
305
306                if(op_de.e_o_s!=0)eosflag=1;
307
308                // check pcmpos flag
309                if(op_de.granulepos!=-1){
310                  System.err.print(" pcm:"+op_de.granulepos+" ");
311                }
312              }
313            }
314          }
315        }
316      }
317    }
318    //free(data);
319    if(headers[pageno]!=null){
320      System.err.println("did not write last page!");
321      System.exit(1);
322    }
323    if(headers[pageout]!=null){
324      System.err.println("did not decode last page!");
325      System.exit(1);
326    }
327    if(inptr!=outptr){
328      System.err.println("encoded page data incomplete!");
329      System.exit(1);
330    }
331    if(inptr!=deptr){
332      System.err.println("decoded page data incomplete!");
333      System.exit(1);
334    }
335    if(inptr!=depacket){
336      System.err.println("decoded packet data incomplete!");
337      System.exit(1);
338    }
339    if(eosflag==0){
340      System.err.println("Never got a packet with EOS set!");
341    }
342    System.err.println("ok.");
343  }
344
345  static void error(){
346    System.err.println("error!");
347    System.exit(1);
348  }
349  public static void main(String[] arg){
350
351    os_en=new StreamState(0x04030201);
352    os_de=new StreamState(0x04030201);
353
354    oy=new SyncState();
355
356    // Exercise each code path in the framing code.  Also verify that
357    // the checksums are working.
358
359    {
360      // 17 only
361      int[] packets={17, -1};
362      int[] head1={0x4f,0x67,0x67,0x53,0,0x06,
363                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
364                   0x01,0x02,0x03,0x04,0,0,0,0,
365                   0x15,0xed,0xec,0x91,
366                   1,
367                   17};
368      int[][] headret={head1, null};
369    
370      System.err.print("testing single page encoding... ");
371      test_pack(packets,headret);
372    }
373
374    {
375      // 17, 254, 255, 256, 500, 510, 600 byte, pad
376      int[] packets={17, 254, 255, 256, 500, 510, 600, -1};
377      int[] head1={0x4f,0x67,0x67,0x53,0,0x02,
378                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
379                   0x01,0x02,0x03,0x04,0,0,0,0,
380                   0x59,0x10,0x6c,0x2c,
381                   1,
382                   17};
383      int[] head2={0x4f,0x67,0x67,0x53,0,0x04,
384                   0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
385                   0x01,0x02,0x03,0x04,1,0,0,0,
386                   0x89,0x33,0x85,0xce,
387                   13,
388                   254,255,0,255,1,255,245,255,255,0,
389                   255,255,90};
390      int[][] headret={head1,head2,null};
391
392      System.err.print("testing basic page encoding... ");
393      test_pack(packets,headret);
394    }
395
396    {
397      // nil packets; beginning,middle,end
398      int[] packets={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
399
400      int[] head1={0x4f,0x67,0x67,0x53,0,0x02,
401                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
402                   0x01,0x02,0x03,0x04,0,0,0,0,
403                   0xff,0x7b,0x23,0x17,
404                   1,
405                   0};
406      int[] head2={0x4f,0x67,0x67,0x53,0,0x04,
407                   0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
408                   0x01,0x02,0x03,0x04,1,0,0,0,
409                   0x5c,0x3f,0x66,0xcb,
410                   17,
411                   17,254,255,0,0,255,1,0,255,245,255,255,0,
412                   255,255,90,0};
413      int[][] headret={head1,head2,null};
414
415      System.err.print("testing basic nil packets... ");
416      test_pack(packets,headret);
417    }
418
419    {
420      // large initial packet
421      int[] packets={4345,259,255,-1};
422
423      int[] head1={0x4f,0x67,0x67,0x53,0,0x02,
424                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
425                   0x01,0x02,0x03,0x04,0,0,0,0,
426                   0x01,0x27,0x31,0xaa,
427                   18,
428                   255,255,255,255,255,255,255,255,
429                   255,255,255,255,255,255,255,255,255,10};
430
431      int[] head2={0x4f,0x67,0x67,0x53,0,0x04,
432                   0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
433                   0x01,0x02,0x03,0x04,1,0,0,0,
434                   0x7f,0x4e,0x8a,0xd2,
435                   4,
436                   255,4,255,0};
437      int[][] headret={head1,head2,null};
438
439      System.err.print("testing initial-packet lacing > 4k... ");
440      test_pack(packets,headret);
441    }
442
443    {
444      // continuing packet test
445      int[] packets={0,4345,259,255,-1};
446
447      int[] head1={0x4f,0x67,0x67,0x53,0,0x02,
448                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
449                   0x01,0x02,0x03,0x04,0,0,0,0,
450                   0xff,0x7b,0x23,0x17,
451                   1,
452                   0};
453
454      int[] head2={0x4f,0x67,0x67,0x53,0,0x00,
455                   0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
456                   0x01,0x02,0x03,0x04,1,0,0,0,
457                   0x34,0x24,0xd5,0x29,
458                   17,
459                   255,255,255,255,255,255,255,255,
460                   255,255,255,255,255,255,255,255,255};
461
462      int[] head3={0x4f,0x67,0x67,0x53,0,0x05,
463                   0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
464                   0x01,0x02,0x03,0x04,2,0,0,0,
465                   0xc8,0xc3,0xcb,0xed,
466                   5,
467                   10,255,4,255,0};
468      int[][] headret={head1,head2,head3,null};
469
470      System.err.print("testing single packet page span... ");
471      test_pack(packets,headret);
472    }
473
474    // page with the 255 segment limit
475    {
476
477      int[] packets={0,10,10,10,10,10,10,10,10,
478                     10,10,10,10,10,10,10,10,
479                     10,10,10,10,10,10,10,10,
480                     10,10,10,10,10,10,10,10,
481                   10,10,10,10,10,10,10,10,
482                   10,10,10,10,10,10,10,10,
483                   10,10,10,10,10,10,10,10,
484                   10,10,10,10,10,10,10,10,
485                   10,10,10,10,10,10,10,10,
486                   10,10,10,10,10,10,10,10,
487                   10,10,10,10,10,10,10,10,
488                   10,10,10,10,10,10,10,10,
489                   10,10,10,10,10,10,10,10,
490                   10,10,10,10,10,10,10,10,
491                   10,10,10,10,10,10,10,10,
492                   10,10,10,10,10,10,10,10,
493                   10,10,10,10,10,10,10,10,
494                   10,10,10,10,10,10,10,10,
495                   10,10,10,10,10,10,10,10,
496                   10,10,10,10,10,10,10,10,
497                   10,10,10,10,10,10,10,10,
498                   10,10,10,10,10,10,10,10,
499                   10,10,10,10,10,10,10,10,
500                   10,10,10,10,10,10,10,10,
501                   10,10,10,10,10,10,10,10,
502                   10,10,10,10,10,10,10,10,
503                   10,10,10,10,10,10,10,10,
504                   10,10,10,10,10,10,10,10,
505                   10,10,10,10,10,10,10,10,
506                   10,10,10,10,10,10,10,10,
507                   10,10,10,10,10,10,10,10,
508                   10,10,10,10,10,10,10,50,-1};
509
510      int[] head1={0x4f,0x67,0x67,0x53,0,0x02,
511                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
512                   0x01,0x02,0x03,0x04,0,0,0,0,
513                   0xff,0x7b,0x23,0x17,
514                   1,
515                   0};
516
517      int[] head2={0x4f,0x67,0x67,0x53,0,0x00,
518                   0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
519                   0x01,0x02,0x03,0x04,1,0,0,0,
520                   0xed,0x2a,0x2e,0xa7,
521                   255,
522                   10,10,10,10,10,10,10,10,
523                   10,10,10,10,10,10,10,10,
524                   10,10,10,10,10,10,10,10,
525                   10,10,10,10,10,10,10,10,
526                   10,10,10,10,10,10,10,10,
527                   10,10,10,10,10,10,10,10,
528                   10,10,10,10,10,10,10,10,
529                   10,10,10,10,10,10,10,10,
530                   10,10,10,10,10,10,10,10,
531                   10,10,10,10,10,10,10,10,
532                   10,10,10,10,10,10,10,10,
533                   10,10,10,10,10,10,10,10,
534                   10,10,10,10,10,10,10,10,
535                   10,10,10,10,10,10,10,10,
536                   10,10,10,10,10,10,10,10,
537                   10,10,10,10,10,10,10,10,
538                   10,10,10,10,10,10,10,10,
539                   10,10,10,10,10,10,10,10,
540                   10,10,10,10,10,10,10,10,
541                   10,10,10,10,10,10,10,10,
542                   10,10,10,10,10,10,10,10,
543                   10,10,10,10,10,10,10,10,
544                   10,10,10,10,10,10,10,10,
545                   10,10,10,10,10,10,10,10,
546                   10,10,10,10,10,10,10,10,
547                   10,10,10,10,10,10,10,10,
548                   10,10,10,10,10,10,10,10,
549                   10,10,10,10,10,10,10,10,
550                   10,10,10,10,10,10,10,10,
551                   10,10,10,10,10,10,10,10,
552                   10,10,10,10,10,10,10,10,
553                   10,10,10,10,10,10,10};
554
555      int[] head3={0x4f,0x67,0x67,0x53,0,0x04,
556                   0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
557                   0x01,0x02,0x03,0x04,2,0,0,0,
558                   0x6c,0x3b,0x82,0x3d,
559                   1,
560                   50};
561      int[][] headret={head1,head2,head3,null};
562
563      System.err.print("testing max packet segments... ");
564      test_pack(packets,headret);
565    }
566
567    {
568      // packet that overspans over an entire page
569
570      int[] packets={0,100,9000,259,255,-1};
571
572      int[] head1={0x4f,0x67,0x67,0x53,0,0x02,
573                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
574                   0x01,0x02,0x03,0x04,0,0,0,0,
575                   0xff,0x7b,0x23,0x17,
576                   1,
577                   0};
578
579      int[] head2={0x4f,0x67,0x67,0x53,0,0x00,
580                   0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
581                   0x01,0x02,0x03,0x04,1,0,0,0,
582                   0x3c,0xd9,0x4d,0x3f,
583                   17,
584                   100,255,255,255,255,255,255,255,255,
585                   255,255,255,255,255,255,255,255};
586
587      int[] head3={0x4f,0x67,0x67,0x53,0,0x01,
588                   0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
589                   0x01,0x02,0x03,0x04,2,0,0,0,
590                   0xbd,0xd5,0xb5,0x8b,
591                   17,
592                   255,255,255,255,255,255,255,255,
593                   255,255,255,255,255,255,255,255,255};
594
595      int[] head4={0x4f,0x67,0x67,0x53,0,0x05,
596                   0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
597                   0x01,0x02,0x03,0x04,3,0,0,0,
598                   0xef,0xdd,0x88,0xde,
599                   7,
600                   255,255,75,255,4,255,0};
601      int[][] headret={head1,head2,head3,head4,null};
602
603      System.err.print("testing very large packets... ");
604      test_pack(packets,headret);
605    }
606
607    {
608      // term only page.  why not?
609
610      int[] packets={0,100,4080,-1};
611
612      int[] head1={0x4f,0x67,0x67,0x53,0,0x02,
613                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
614                   0x01,0x02,0x03,0x04,0,0,0,0,
615                   0xff,0x7b,0x23,0x17,
616                   1,
617                   0};
618
619      int[] head2={0x4f,0x67,0x67,0x53,0,0x00,
620                   0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
621                   0x01,0x02,0x03,0x04,1,0,0,0,
622                   0x3c,0xd9,0x4d,0x3f,
623                   17,
624                   100,255,255,255,255,255,255,255,255,
625                   255,255,255,255,255,255,255,255};
626
627      int[] head3={0x4f,0x67,0x67,0x53,0,0x05,
628                   0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
629                   0x01,0x02,0x03,0x04,2,0,0,0,
630                   0xd4,0xe0,0x60,0xe5,
631                   1,0};
632
633      int[][] headret={head1,head2,head3,null};
634
635      System.err.print("testing zero data page (1 nil packet)... ");
636      test_pack(packets,headret);
637    }
638
639    {
640      // build a bunch of pages for testing
641      byte[] data=new byte[1024*1024];
642      int[] pl={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
643      int inptr=0;
644      Page[] og=new Page[5];
645      for(int i=0; i<5; i++){
646        og[i]=new Page();
647      }
648    
649      os_en.reset();
650
651      for(int i=0;pl[i]!=-1;i++){
652        Packet op=new Packet();
653        int len=pl[i];
654      
655        op.packet_base=data;
656        op.packet=inptr;
657        op.bytes=len;
658        op.e_o_s=(pl[i+1]<0?1:0);
659        op.granulepos=(i+1)*1000;
660        
661        for(int j=0;j<len;j++)data[inptr++]=(byte)(i+j);
662        os_en.packetin(op);
663      }    
664
665//    free(data);
666
667      // retrieve finished pages
668      for(int i=0;i<5;i++){
669        if(os_en.pageout(og[i])==0){
670          System.err.print("Too few pages output building sync tests!\n");
671          System.exit(1);
672        }
673        og[i].copy_page();
674      }
675
676      // Test lost pages on pagein/packetout: no rollback
677      {
678        Page temp=new Page();
679        Packet test=new Packet();
680
681        System.err.print("Testing loss of pages... ");
682
683        oy.reset();
684        os_de.reset();
685        for(int i=0;i<5;i++){
686          int index=oy.buffer(og[i].header_len);
687          System.arraycopy(og[i].header_base, og[i].header,
688                           oy.data, index, og[i].header_len);
689          oy.wrote(og[i].header_len);
690          index=oy.buffer(og[i].body_len);
691          System.arraycopy(og[i].body_base, og[i].body,
692                           oy.data, index, og[i].body_len);
693          oy.wrote(og[i].body_len);
694        }
695
696        oy.pageout(temp);
697        os_de.pagein(temp);
698        oy.pageout(temp);
699        os_de.pagein(temp);
700        oy.pageout(temp);
701
702        // skip
703        oy.pageout(temp);
704        os_de.pagein(temp);
705
706        // do we get the expected results/packets?
707      
708        if(os_de.packetout(test)!=1)error();
709        test.checkpacket(0,0,0);
710        if(os_de.packetout(test)!=1)error();
711        test.checkpacket(100,1,-1);
712        if(os_de.packetout(test)!=1)error();
713        test.checkpacket(4079,2,3000);
714        if(os_de.packetout(test)!=-1){
715          System.err.println("Error: loss of page did not return error");
716          System.exit(1);
717        }
718        if(os_de.packetout(test)!=1)error();
719        test.checkpacket(76,5,-1);
720        if(os_de.packetout(test)!=1)error();
721        test.checkpacket(34,6,-1);
722        System.err.println("ok.");
723      }
724
725      // Test lost pages on pagein/packetout: rollback with continuation
726      {
727        Page temp=new Page();
728        Packet test=new Packet();
729
730        System.err.print("Testing loss of pages (rollback required)... ");
731
732        oy.reset();
733        os_de.reset();
734        for(int i=0;i<5;i++){
735          int index=oy.buffer(og[i].header_len);
736          System.arraycopy(og[i].header_base, og[i].header,
737                           oy.data, index, og[i].header_len);
738          oy.wrote(og[i].header_len);
739          index=oy.buffer(og[i].body_len);
740          System.arraycopy(og[i].body_base, og[i].body,
741                           oy.data, index, og[i].body_len);
742          oy.wrote(og[i].body_len);
743        }
744
745        oy.pageout(temp);
746        os_de.pagein(temp);
747        oy.pageout(temp);
748        os_de.pagein(temp);
749        oy.pageout(temp);
750        os_de.pagein(temp);
751        oy.pageout(temp);
752        // skip
753        oy.pageout(temp);
754        os_de.pagein(temp);
755
756        // do we get the expected results/packets?
757      
758        if(os_de.packetout(test)!=1)error();
759        test.checkpacket(0,0,0);
760        if(os_de.packetout(test)!=1)error();
761        test.checkpacket(100,1,-1);
762        if(os_de.packetout(test)!=1)error();
763        test.checkpacket(4079,2,3000);
764        if(os_de.packetout(test)!=1)error();
765        test.checkpacket(2956,3,4000);
766        if(os_de.packetout(test)!=-1){
767          System.err.println("Error: loss of page did not return error");
768          System.exit(1);
769        }
770        if(os_de.packetout(test)!=1)error();
771        test.checkpacket(300,13,14000);
772        System.err.println("ok.");
773      }
774
775      // the rest only test sync
776      {
777        Page og_de=new Page();
778        // Test fractional page inputs: incomplete capture
779        System.err.print("Testing sync on partial inputs... ");
780        oy.reset();
781        int index=oy.buffer(og[1].header_len);
782        System.arraycopy(og[1].header_base, og[1].header, 
783                         oy.data, index, 3);
784        oy.wrote(3);
785        if(oy.pageout(og_de)>0)error();
786      
787        // Test fractional page inputs: incomplete fixed header
788        index=oy.buffer(og[1].header_len);
789        System.arraycopy(og[1].header_base, og[1].header+3, 
790                         oy.data, index, 20);
791    
792        oy.wrote(20);
793        if(oy.pageout(og_de)>0)error();
794    
795        // Test fractional page inputs: incomplete header
796        index=oy.buffer(og[1].header_len);
797        System.arraycopy(og[1].header_base, og[1].header+23, 
798                         oy.data, index, 5);
799        oy.wrote(5);
800        if(oy.pageout(og_de)>0)error();
801    
802        // Test fractional page inputs: incomplete body
803        index=oy.buffer(og[1].header_len);
804        System.arraycopy(og[1].header_base, og[1].header+28, 
805                         oy.data, index, og[1].header_len-28);
806        oy.wrote(og[1].header_len-28);
807        if(oy.pageout(og_de)>0)error();
808    
809        index=oy.buffer(og[1].body_len);
810        System.arraycopy(og[1].body_base, og[1].body,
811                         oy.data, index, 1000);
812        oy.wrote(1000);
813        if(oy.pageout(og_de)>0)error();
814
815        index=oy.buffer(og[1].body_len);
816        System.arraycopy(og[1].body_base, og[1].body+1000,
817                         oy.data, index, og[1].body_len-1000);
818        oy.wrote(og[1].body_len-1000);
819        if(oy.pageout(og_de)<=0)error();
820        System.err.println("ok.");
821      }
822
823      // Test fractional page inputs: page + incomplete capture
824      {
825        Page og_de=new Page();
826        System.err.print("Testing sync on 1+partial inputs... ");
827        oy.reset(); 
828
829        int index=oy.buffer(og[1].header_len);
830        System.arraycopy(og[1].header_base, og[1].header,
831                         oy.data, index, og[1].header_len);
832        oy.wrote(og[1].header_len);
833
834        index=oy.buffer(og[1].body_len);
835        System.arraycopy(og[1].body_base, og[1].body,
836                         oy.data, index, og[1].body_len);
837        oy.wrote(og[1].body_len);
838
839        index=oy.buffer(og[1].header_len);
840        System.arraycopy(og[1].header_base, og[1].header,
841                         oy.data, index, 20);
842        oy.wrote(20);
843        if(oy.pageout(og_de)<=0)error();
844        if(oy.pageout(og_de)>0)error();
845
846        index=oy.buffer(og[1].header_len);
847        System.arraycopy(og[1].header_base, og[1].header+20,
848                         oy.data, index, og[1].header_len-20);
849        oy.wrote(og[1].header_len-20);
850        index=oy.buffer(og[1].body_len);
851        System.arraycopy(og[1].body_base, og[1].body,
852                         oy.data, index, og[1].body_len);
853             
854        oy.wrote(og[1].body_len);
855        if(oy.pageout(og_de)<=0)error();
856    
857        System.err.println("ok.");
858      }
859
860//    //    //    //    //    //    //    //    //    
861      // Test recapture: garbage + page
862      {
863        Page og_de=new Page();
864        System.err.print("Testing search for capture... ");
865        oy.reset(); 
866      
867        // 'garbage'
868        int index=oy.buffer(og[1].body_len);
869        System.arraycopy(og[1].body_base, og[1].body,
870                         oy.data, index, og[1].body_len);
871        oy.wrote(og[1].body_len);
872
873        index=oy.buffer(og[1].header_len);
874        System.arraycopy(og[1].header_base, og[1].header,
875                         oy.data, index, og[1].header_len);
876        oy.wrote(og[1].header_len);
877
878        index=oy.buffer(og[1].body_len);
879        System.arraycopy(og[1].body_base, og[1].body,
880                         oy.data, index, og[1].body_len);
881        oy.wrote(og[1].body_len);
882
883        index=oy.buffer(og[2].header_len);
884        System.arraycopy(og[2].header_base, og[2].header,
885                         oy.data, index, 20);
886
887        oy.wrote(20);
888        if(oy.pageout(og_de)>0)error();
889        if(oy.pageout(og_de)<=0)error();
890        if(oy.pageout(og_de)>0)error();
891
892        index=oy.buffer(og[2].header_len);
893        System.arraycopy(og[2].header_base, og[2].header+20,
894                         oy.data, index, og[2].header_len-20);
895        oy.wrote(og[2].header_len-20);
896        index=oy.buffer(og[2].body_len);
897        System.arraycopy(og[2].body_base, og[2].body,
898                         oy.data, index, og[2].body_len);
899        oy.wrote(og[2].body_len);
900        if(oy.pageout(og_de)<=0)error();
901
902        System.err.println("ok.");
903      }
904
905      // Test recapture: page + garbage + page
906      {
907        Page og_de=new Page();
908        System.err.print("Testing recapture... ");
909        oy.reset(); 
910
911        int index=oy.buffer(og[1].header_len);
912        System.arraycopy(og[1].header_base, og[1].header,
913                         oy.data, index, og[1].header_len);
914        oy.wrote(og[1].header_len);
915
916        index=oy.buffer(og[1].body_len);
917        System.arraycopy(og[1].body_base, og[1].body,
918                         oy.data, index, og[1].body_len);
919        oy.wrote(og[1].body_len);
920
921        index=oy.buffer(og[2].header_len);
922        System.arraycopy(og[2].header_base, og[2].header,
923                         oy.data, index, og[2].header_len);
924        oy.wrote(og[2].header_len);
925
926        index=oy.buffer(og[2].header_len);
927        System.arraycopy(og[2].header_base, og[2].header,
928                         oy.data, index, og[2].header_len);
929        oy.wrote(og[2].header_len);
930
931        if(oy.pageout(og_de)<=0)error();
932
933        index=oy.buffer(og[2].body_len);
934        System.arraycopy(og[2].body_base, og[2].body,
935                         oy.data, index, og[2].body_len-5);
936        oy.wrote(og[2].body_len-5);
937
938        index=oy.buffer(og[3].header_len);
939        System.arraycopy(og[3].header_base, og[3].header,
940                         oy.data, index, og[3].header_len);
941        oy.wrote(og[3].header_len);
942
943        index=oy.buffer(og[3].body_len);
944        System.arraycopy(og[3].body_base, og[3].body,
945                         oy.data, index, og[3].body_len);
946        oy.wrote(og[3].body_len);
947
948        if(oy.pageout(og_de)>0)error();
949        if(oy.pageout(og_de)<=0)error();
950
951        System.err.println("ok.");
952      }
953    }    
954    //return(0);
955  }
956  */
957}