~ubuntu-branches/debian/jessie/spice/jessie

« back to all changes in this revision

Viewing changes to celt/tools/celtenc.c

  • Committer: Package Import Robot
  • Author(s): Liang Guo
  • Date: 2012-06-09 11:33:05 UTC
  • mfrom: (0.4.4) (2.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20120609113305-qrlv1ryo9iqbhwmd
Tags: 0.11.0-1
* New upstream release
* Breaks spice-gtk (<= 0.12-2)
* Refresh debian/libspice-server1.symbols
* debian/control:
  - Update my e-mail address
  - Add python-pyparsing to Build-Depends
* debian/patches:
  - Remove fix-error-path-return-in-snd_set_record_peer.patch, 
    applied upstream
  - Refresh make-celt-to-be-optional.patch
  - Refresh link-libspice-server-with-libm-libpthread.patch
* Simplify debian/rules, celt removed, no reason to use 
  traditional one
* Disable smartcard, not in debian yet
* Refresh debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2002-2008 Jean-Marc Valin 
2
 
   File: celtenc.c
3
 
 
4
 
   Redistribution and use in source and binary forms, with or without
5
 
   modification, are permitted provided that the following conditions
6
 
   are met:
7
 
   
8
 
   - Redistributions of source code must retain the above copyright
9
 
   notice, this list of conditions and the following disclaimer.
10
 
   
11
 
   - Redistributions in binary form must reproduce the above copyright
12
 
   notice, this list of conditions and the following disclaimer in the
13
 
   documentation and/or other materials provided with the distribution.
14
 
   
15
 
   - Neither the name of the Xiph.org Foundation nor the names of its
16
 
   contributors may be used to endorse or promote products derived from
17
 
   this software without specific prior written permission.
18
 
   
19
 
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
 
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
 
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
 
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23
 
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
 
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
 
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
 
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
 
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
 
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
 
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
 
*/
31
 
 
32
 
#ifdef HAVE_CONFIG_H
33
 
# include "config.h"
34
 
#endif
35
 
 
36
 
#include <stdio.h>
37
 
#if !defined WIN32 && !defined _WIN32
38
 
#include <unistd.h>
39
 
#endif
40
 
 
41
 
#ifdef HAVE_GETOPT_H
42
 
#include <getopt.h>
43
 
#endif
44
 
 
45
 
#ifndef HAVE_GETOPT_LONG
46
 
#include "getopt_win.h"
47
 
#endif
48
 
 
49
 
#include <stdlib.h>
50
 
#include <string.h>
51
 
#include <time.h>
52
 
 
53
 
#include "celt.h"
54
 
#include "celt_header.h"
55
 
#include <ogg/ogg.h>
56
 
#include "wav_io.h"
57
 
 
58
 
#if defined WIN32 || defined _WIN32
59
 
/* We need the following two to set stdout to binary */
60
 
#include <io.h>
61
 
#include <fcntl.h>
62
 
#endif
63
 
 
64
 
#include "skeleton.h"
65
 
 
66
 
 
67
 
void comment_init(char **comments, int* length, char *vendor_string);
68
 
void comment_add(char **comments, int* length, char *tag, char *val);
69
 
 
70
 
 
71
 
/*Write an Ogg page to a file pointer*/
72
 
int oe_write_page(ogg_page *page, FILE *fp)
73
 
{
74
 
   int written;
75
 
   written = fwrite(page->header,1,page->header_len, fp);
76
 
   written += fwrite(page->body,1,page->body_len, fp);
77
 
   
78
 
   return written;
79
 
}
80
 
 
81
 
#define MAX_FRAME_SIZE 2000
82
 
#define MAX_FRAME_BYTES 2000
83
 
 
84
 
/* Convert input audio bits, endians and channels */
85
 
static int read_samples(FILE *fin,int frame_size, int bits, int channels, int lsb, short * input, char *buff, celt_int32_t *size)
86
 
{   
87
 
   unsigned char in[MAX_FRAME_BYTES*2];
88
 
   int i;
89
 
   short *s;
90
 
   int nb_read;
91
 
 
92
 
   if (size && *size<=0)
93
 
   {
94
 
      return 0;
95
 
   }
96
 
   /*Read input audio*/
97
 
   if (size)
98
 
      *size -= bits/8*channels*frame_size;
99
 
   if (buff)
100
 
   {
101
 
      for (i=0;i<12;i++)
102
 
         in[i]=buff[i];
103
 
      nb_read = fread(in+12,1,bits/8*channels*frame_size-12, fin) + 12;
104
 
      if (size)
105
 
         *size += 12;
106
 
   } else {
107
 
      nb_read = fread(in,1,bits/8*channels* frame_size, fin);
108
 
   }
109
 
   nb_read /= bits/8*channels;
110
 
 
111
 
   /*fprintf (stderr, "%d\n", nb_read);*/
112
 
   if (nb_read==0)
113
 
      return 0;
114
 
 
115
 
   s=(short*)in;
116
 
   if(bits==8)
117
 
   {
118
 
      /* Convert 8->16 bits */
119
 
      for(i=frame_size*channels-1;i>=0;i--)
120
 
      {
121
 
         s[i]=(in[i]<<8)^0x8000;
122
 
      }
123
 
   } else
124
 
   {
125
 
      /* convert to our endian format */
126
 
      for(i=0;i<frame_size*channels;i++)
127
 
      {
128
 
         if(lsb) 
129
 
            s[i]=le_short(s[i]); 
130
 
         else
131
 
            s[i]=be_short(s[i]);
132
 
      }
133
 
   }
134
 
 
135
 
   /* FIXME: This is probably redundent now */
136
 
   /* copy to float input buffer */
137
 
   for (i=0;i<frame_size*channels;i++)
138
 
   {
139
 
      input[i]=(short)s[i];
140
 
   }
141
 
 
142
 
   for (i=nb_read*channels;i<frame_size*channels;i++)
143
 
   {
144
 
      input[i]=0;
145
 
   }
146
 
 
147
 
 
148
 
   return nb_read;
149
 
}
150
 
 
151
 
void add_fishead_packet (ogg_stream_state *os) {
152
 
 
153
 
   fishead_packet fp;
154
 
 
155
 
   memset(&fp, 0, sizeof(fp));
156
 
   fp.ptime_n = 0;
157
 
   fp.ptime_d = 1000;
158
 
   fp.btime_n = 0;
159
 
   fp.btime_d = 1000;
160
 
 
161
 
   add_fishead_to_stream(os, &fp);
162
 
}
163
 
 
164
 
/*
165
 
 * Adds the fishead packets in the skeleton output stream along with the e_o_s packet
166
 
 */
167
 
void add_fisbone_packet (ogg_stream_state *os, celt_int32_t serialno, CELT051Header *header) {
168
 
 
169
 
   fisbone_packet fp;
170
 
 
171
 
   memset(&fp, 0, sizeof(fp));
172
 
   fp.serial_no = serialno;
173
 
   fp.nr_header_packet = 2 + header->extra_headers;
174
 
   fp.granule_rate_n = header->sample_rate;
175
 
   fp.granule_rate_d = 1;
176
 
   fp.start_granule = 0;
177
 
   fp.preroll = 3;
178
 
   fp.granule_shift = 0;
179
 
 
180
 
   add_message_header_field(&fp, "Content-Type", "audio/x-celt");
181
 
 
182
 
   add_fisbone_to_stream(os, &fp);
183
 
}
184
 
 
185
 
void version(void)
186
 
{
187
 
   printf ("celtenc (CELT encoder)\n");
188
 
   printf ("Copyright (C) 2008 Jean-Marc Valin\n");
189
 
}
190
 
 
191
 
void version_short(void)
192
 
{
193
 
   printf ("celtenc (CELT encoder)\n");
194
 
   printf ("Copyright (C) 2008 Jean-Marc Valin\n");
195
 
}
196
 
 
197
 
void usage(void)
198
 
{
199
 
   printf ("Usage: celtenc [options] input_file output_file.oga\n");
200
 
   printf ("\n");
201
 
   printf ("Encodes input_file using CELT. It can read the WAV or raw files.\n");
202
 
   printf ("\n");
203
 
   printf ("input_file can be:\n");
204
 
   printf ("  filename.wav      wav file\n");
205
 
   printf ("  filename.*        Raw PCM file (any extension other than .wav)\n");
206
 
   printf ("  -                 stdin\n");
207
 
   printf ("\n");  
208
 
   printf ("output_file can be:\n");
209
 
   printf ("  filename.oga      compressed file\n");
210
 
   printf ("  -                 stdout\n");
211
 
   printf ("\n");  
212
 
   printf ("Options:\n");
213
 
   printf (" --bitrate n        Encoding bit-rate\n"); 
214
 
   printf (" --comp n           Encoding complexity (0-10)\n");
215
 
   printf (" --skeleton         Outputs ogg skeleton metadata (may cause incompatibilities)\n");
216
 
   printf (" --comment          Add the given string as an extra comment. This may be\n");
217
 
   printf ("                     used multiple times\n");
218
 
   printf (" --author           Author of this track\n");
219
 
   printf (" --title            Title for this track\n");
220
 
   printf (" -h, --help         This help\n"); 
221
 
   printf (" -v, --version      Version information\n"); 
222
 
   printf (" -V                 Verbose mode (show bit-rate)\n"); 
223
 
   printf ("Raw input options:\n");
224
 
   printf (" --rate n           Sampling rate for raw input\n"); 
225
 
   printf (" --mono             Consider raw input as mono\n"); 
226
 
   printf (" --stereo           Consider raw input as stereo\n"); 
227
 
   printf (" --le               Raw input is little-endian\n"); 
228
 
   printf (" --be               Raw input is big-endian\n"); 
229
 
   printf (" --8bit             Raw input is 8-bit unsigned\n"); 
230
 
   printf (" --16bit            Raw input is 16-bit signed\n"); 
231
 
   printf ("Default raw PCM input is 16-bit, little-endian, mono\n"); 
232
 
}
233
 
 
234
 
 
235
 
int main(int argc, char **argv)
236
 
{
237
 
   int nb_samples, total_samples=0, nb_encoded;
238
 
   int c;
239
 
   int option_index = 0;
240
 
   char *inFile, *outFile;
241
 
   FILE *fin, *fout;
242
 
   short input[MAX_FRAME_SIZE];
243
 
   celt_int32_t frame_size;
244
 
   int quiet=0;
245
 
   int nbBytes;
246
 
   CELTMode *mode;
247
 
   void *st;
248
 
   unsigned char bits[MAX_FRAME_BYTES];
249
 
   int with_skeleton = 0;
250
 
   struct option long_options[] =
251
 
   {
252
 
      {"bitrate", required_argument, NULL, 0},
253
 
      {"comp", required_argument, NULL, 0},
254
 
      {"skeleton",no_argument,NULL, 0},
255
 
      {"help", no_argument, NULL, 0},
256
 
      {"quiet", no_argument, NULL, 0},
257
 
      {"le", no_argument, NULL, 0},
258
 
      {"be", no_argument, NULL, 0},
259
 
      {"8bit", no_argument, NULL, 0},
260
 
      {"16bit", no_argument, NULL, 0},
261
 
      {"mono", no_argument, NULL, 0},
262
 
      {"stereo", no_argument, NULL, 0},
263
 
      {"rate", required_argument, NULL, 0},
264
 
      {"version", no_argument, NULL, 0},
265
 
      {"version-short", no_argument, NULL, 0},
266
 
      {"comment", required_argument, NULL, 0},
267
 
      {"author", required_argument, NULL, 0},
268
 
      {"title", required_argument, NULL, 0},
269
 
      {0, 0, 0, 0}
270
 
   };
271
 
   int print_bitrate=0;
272
 
   celt_int32_t rate=44100;
273
 
   celt_int32_t size;
274
 
   int chan=1;
275
 
   int fmt=16;
276
 
   int lsb=1;
277
 
   ogg_stream_state os;
278
 
   ogg_stream_state so; /* ogg stream for skeleton bitstream */
279
 
   ogg_page              og;
280
 
   ogg_packet            op;
281
 
   int bytes_written=0, ret, result;
282
 
   int id=-1;
283
 
   CELT051Header header;
284
 
   char vendor_string[64];
285
 
   char *comments;
286
 
   int comments_length;
287
 
   int close_in=0, close_out=0;
288
 
   int eos=0;
289
 
   celt_int32_t bitrate=-1;
290
 
   char first_bytes[12];
291
 
   int wave_input=0;
292
 
   celt_int32_t lookahead = 0;
293
 
   int bytes_per_packet=48;
294
 
   int complexity=-127;
295
 
   
296
 
   snprintf(vendor_string, sizeof(vendor_string), "Encoded with CELT\n");
297
 
   
298
 
   comment_init(&comments, &comments_length, vendor_string);
299
 
 
300
 
   /*Process command-line options*/
301
 
   while(1)
302
 
   {
303
 
      c = getopt_long (argc, argv, "hvV",
304
 
                       long_options, &option_index);
305
 
      if (c==-1)
306
 
         break;
307
 
      
308
 
      switch(c)
309
 
      {
310
 
      case 0:
311
 
         if (strcmp(long_options[option_index].name,"bitrate")==0)
312
 
         {
313
 
            bitrate = atoi (optarg);
314
 
         } else if (strcmp(long_options[option_index].name,"skeleton")==0)
315
 
         {
316
 
            with_skeleton=1;
317
 
         } else if (strcmp(long_options[option_index].name,"help")==0)
318
 
         {
319
 
            usage();
320
 
            exit(0);
321
 
         } else if (strcmp(long_options[option_index].name,"quiet")==0)
322
 
         {
323
 
            quiet = 1;
324
 
         } else if (strcmp(long_options[option_index].name,"version")==0)
325
 
         {
326
 
            version();
327
 
            exit(0);
328
 
         } else if (strcmp(long_options[option_index].name,"version-short")==0)
329
 
         {
330
 
            version_short();
331
 
            exit(0);
332
 
         } else if (strcmp(long_options[option_index].name,"le")==0)
333
 
         {
334
 
            lsb=1;
335
 
         } else if (strcmp(long_options[option_index].name,"be")==0)
336
 
         {
337
 
            lsb=0;
338
 
         } else if (strcmp(long_options[option_index].name,"8bit")==0)
339
 
         {
340
 
            fmt=8;
341
 
         } else if (strcmp(long_options[option_index].name,"16bit")==0)
342
 
         {
343
 
            fmt=16;
344
 
         } else if (strcmp(long_options[option_index].name,"stereo")==0)
345
 
         {
346
 
            chan=2;
347
 
         } else if (strcmp(long_options[option_index].name,"mono")==0)
348
 
         {
349
 
            chan=1;
350
 
         } else if (strcmp(long_options[option_index].name,"rate")==0)
351
 
         {
352
 
            rate=atoi (optarg);
353
 
         } else if (strcmp(long_options[option_index].name,"comp")==0)
354
 
         {
355
 
            complexity=atoi (optarg);
356
 
         } else if (strcmp(long_options[option_index].name,"comment")==0)
357
 
         {
358
 
           if (!strchr(optarg, '='))
359
 
           {
360
 
             fprintf (stderr, "Invalid comment: %s\n", optarg);
361
 
             fprintf (stderr, "Comments must be of the form name=value\n");
362
 
             exit(1);
363
 
           }
364
 
           comment_add(&comments, &comments_length, NULL, optarg); 
365
 
         } else if (strcmp(long_options[option_index].name,"author")==0)
366
 
         {
367
 
           comment_add(&comments, &comments_length, "author=", optarg); 
368
 
         } else if (strcmp(long_options[option_index].name,"title")==0)
369
 
         {
370
 
           comment_add(&comments, &comments_length, "title=", optarg); 
371
 
         }
372
 
 
373
 
         break;
374
 
      case 'h':
375
 
         usage();
376
 
         exit(0);
377
 
         break;
378
 
      case 'v':
379
 
         version();
380
 
         exit(0);
381
 
         break;
382
 
      case 'V':
383
 
         print_bitrate=1;
384
 
         break;
385
 
      case '?':
386
 
         usage();
387
 
         exit(1);
388
 
         break;
389
 
      }
390
 
   }
391
 
 
392
 
   fprintf(stderr,"\nWARNING: This encoder is a CELT *PRERELEASE*. It produces streams that are\n"
393
 
           "         not decodable by ANY OTHER VERSION.  These streams will NOT be\n"
394
 
           "         supported or decodable by any future CELT release.\n\n");
395
 
 
396
 
   if (argc-optind!=2)
397
 
   {
398
 
      usage();
399
 
      exit(1);
400
 
   }
401
 
   inFile=argv[optind];
402
 
   outFile=argv[optind+1];
403
 
 
404
 
   /*Initialize Ogg stream struct*/
405
 
   srand(time(NULL));
406
 
   if (ogg_stream_init(&os, rand())==-1)
407
 
   {
408
 
      fprintf(stderr,"Error: stream init failed\n");
409
 
      exit(1);
410
 
   }
411
 
   if (with_skeleton && ogg_stream_init(&so, rand())==-1)
412
 
   {
413
 
      fprintf(stderr,"Error: stream init failed\n");
414
 
      exit(1);
415
 
   }
416
 
 
417
 
   if (strcmp(inFile, "-")==0)
418
 
   {
419
 
#if defined WIN32 || defined _WIN32
420
 
         _setmode(_fileno(stdin), _O_BINARY);
421
 
#elif defined OS2
422
 
         _fsetmode(stdin,"b");
423
 
#endif
424
 
      fin=stdin;
425
 
   }
426
 
   else 
427
 
   {
428
 
      fin = fopen(inFile, "rb");
429
 
      if (!fin)
430
 
      {
431
 
         perror(inFile);
432
 
         exit(1);
433
 
      }
434
 
      close_in=1;
435
 
   }
436
 
 
437
 
   {
438
 
      fread(first_bytes, 1, 12, fin);
439
 
      if (strncmp(first_bytes,"RIFF",4)==0 && strncmp(first_bytes,"RIFF",4)==0)
440
 
      {
441
 
         if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1)
442
 
            exit(1);
443
 
         wave_input=1;
444
 
         lsb=1; /* CHECK: exists big-endian .wav ?? */
445
 
      }
446
 
   }
447
 
 
448
 
   if (chan == 1)
449
 
   {
450
 
      if (bitrate < 0)
451
 
         bitrate = 64;
452
 
      if (bitrate < 32)
453
 
         bitrate = 32;
454
 
      if (bitrate > 110)
455
 
         bitrate = 110;
456
 
   }
457
 
   else if (chan == 2)
458
 
   {
459
 
      if (bitrate < 0)
460
 
         bitrate = 128;
461
 
      if (bitrate < 64)
462
 
         bitrate = 64;
463
 
      if (bitrate > 150)
464
 
         bitrate = 150;
465
 
   } else {
466
 
      fprintf (stderr, "Only mono and stereo are supported\n");
467
 
      return 1;
468
 
   }
469
 
 
470
 
   mode = celt051_mode_create(rate, chan, 256, NULL);
471
 
   if (!mode)
472
 
      return 1;
473
 
   celt051_mode_info(mode, CELT_GET_FRAME_SIZE, &frame_size);
474
 
   
475
 
   bytes_per_packet = (bitrate*1000*frame_size/rate+4)/8;
476
 
   
477
 
   celt051_header_init(&header, mode);
478
 
   header.nb_channels = chan;
479
 
 
480
 
   {
481
 
      char *st_string="mono";
482
 
      if (chan==2)
483
 
         st_string="stereo";
484
 
      if (!quiet)
485
 
         fprintf (stderr, "Encoding %d Hz audio using %s (%d bytes per packet)\n", 
486
 
               header.sample_rate, st_string, bytes_per_packet);
487
 
   }
488
 
   /*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n", 
489
 
     header.rate, mode->bitrate, mode->modeName);*/
490
 
 
491
 
   /*Initialize CELT encoder*/
492
 
   st = celt051_encoder_create(mode);
493
 
 
494
 
   if (complexity!=-127) {
495
 
     if (celt051_encoder_ctl(st, CELT_SET_COMPLEXITY(complexity)) != CELT_OK)
496
 
     {
497
 
        fprintf (stderr, "Only complexity 0 through 10 is supported\n");
498
 
        return 1;
499
 
     }
500
 
   }
501
 
 
502
 
   if (strcmp(outFile,"-")==0)
503
 
   {
504
 
#if defined WIN32 || defined _WIN32
505
 
      _setmode(_fileno(stdout), _O_BINARY);
506
 
#endif
507
 
      fout=stdout;
508
 
   }
509
 
   else 
510
 
   {
511
 
      fout = fopen(outFile, "wb");
512
 
      if (!fout)
513
 
      {
514
 
         perror(outFile);
515
 
         exit(1);
516
 
      }
517
 
      close_out=1;
518
 
   }
519
 
 
520
 
   if (with_skeleton) {
521
 
      fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n");
522
 
   }
523
 
 
524
 
   /* first packet should be the skeleton header. */
525
 
   if (with_skeleton) {
526
 
      add_fishead_packet(&so);
527
 
      if ((ret = flush_ogg_stream_to_file(&so, fout))) {
528
 
         fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n");
529
 
         exit(1);
530
 
      } else
531
 
         bytes_written += ret;
532
 
   }
533
 
 
534
 
   /*Write header*/
535
 
   {
536
 
      unsigned char header_data[100];
537
 
      int packet_size = celt051_header_to_packet(&header, header_data, 100);
538
 
      op.packet = header_data;
539
 
      op.bytes = packet_size;
540
 
      op.b_o_s = 1;
541
 
      op.e_o_s = 0;
542
 
      op.granulepos = 0;
543
 
      op.packetno = 0;
544
 
      ogg_stream_packetin(&os, &op);
545
 
 
546
 
      while((result = ogg_stream_flush(&os, &og)))
547
 
      {
548
 
         if(!result) break;
549
 
         ret = oe_write_page(&og, fout);
550
 
         if(ret != og.header_len + og.body_len)
551
 
         {
552
 
            fprintf (stderr,"Error: failed writing header to output stream\n");
553
 
            exit(1);
554
 
         }
555
 
         else
556
 
            bytes_written += ret;
557
 
      }
558
 
 
559
 
      op.packet = (unsigned char *)comments;
560
 
      op.bytes = comments_length;
561
 
      op.b_o_s = 0;
562
 
      op.e_o_s = 0;
563
 
      op.granulepos = 0;
564
 
      op.packetno = 1;
565
 
      ogg_stream_packetin(&os, &op);
566
 
   }
567
 
 
568
 
   /* fisbone packet should be write after all bos pages */
569
 
   if (with_skeleton) {
570
 
      add_fisbone_packet(&so, os.serialno, &header);
571
 
      if ((ret = flush_ogg_stream_to_file(&so, fout))) {
572
 
         fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n");
573
 
         exit(1);
574
 
      } else
575
 
         bytes_written += ret;
576
 
   }
577
 
 
578
 
   /* writing the rest of the celt header packets */
579
 
   while((result = ogg_stream_flush(&os, &og)))
580
 
   {
581
 
      if(!result) break;
582
 
      ret = oe_write_page(&og, fout);
583
 
      if(ret != og.header_len + og.body_len)
584
 
      {
585
 
         fprintf (stderr,"Error: failed writing header to output stream\n");
586
 
         exit(1);
587
 
      }
588
 
      else
589
 
         bytes_written += ret;
590
 
   }
591
 
 
592
 
   free(comments);
593
 
 
594
 
   /* write the skeleton eos packet */
595
 
   if (with_skeleton) {
596
 
      add_eos_packet_to_stream(&so);
597
 
      if ((ret = flush_ogg_stream_to_file(&so, fout))) {
598
 
         fprintf (stderr,"Error: failed writing skeleton header to output stream\n");
599
 
         exit(1);
600
 
      } else
601
 
         bytes_written += ret;
602
 
   }
603
 
 
604
 
 
605
 
   if (!wave_input)
606
 
   {
607
 
      nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL);
608
 
   } else {
609
 
      nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
610
 
   }
611
 
   if (nb_samples==0)
612
 
      eos=1;
613
 
   total_samples += nb_samples;
614
 
   nb_encoded = -lookahead;
615
 
   /*Main encoding loop (one frame per iteration)*/
616
 
   while (!eos || total_samples>nb_encoded)
617
 
   {
618
 
      id++;
619
 
      /*Encode current frame*/
620
 
 
621
 
      nbBytes = celt051_encode(st, input, NULL, bits, bytes_per_packet);
622
 
      if (nbBytes<0)
623
 
      {
624
 
         fprintf(stderr, "Got error %d while encoding. Aborting.\n", nbBytes);
625
 
         break;
626
 
      }
627
 
      nb_encoded += frame_size;
628
 
 
629
 
      if (wave_input)
630
 
      {
631
 
         nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
632
 
      } else {
633
 
         nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL);
634
 
      }
635
 
      if (nb_samples==0)
636
 
      {
637
 
         eos=1;
638
 
      }
639
 
      if (eos && total_samples<=nb_encoded)
640
 
         op.e_o_s = 1;
641
 
      else
642
 
         op.e_o_s = 0;
643
 
      total_samples += nb_samples;
644
 
 
645
 
      op.packet = (unsigned char *)bits;
646
 
      op.bytes = nbBytes;
647
 
      op.b_o_s = 0;
648
 
      /*Is this redundent?*/
649
 
      if (eos && total_samples<=nb_encoded)
650
 
         op.e_o_s = 1;
651
 
      else
652
 
         op.e_o_s = 0;
653
 
      op.granulepos = (id+1)*frame_size-lookahead;
654
 
      if (op.granulepos>total_samples)
655
 
         op.granulepos = total_samples;
656
 
      /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/
657
 
      op.packetno = 2+id;
658
 
      ogg_stream_packetin(&os, &op);
659
 
 
660
 
      /*Write all new pages (most likely 0 or 1)*/
661
 
      while (ogg_stream_pageout(&os,&og))
662
 
      {
663
 
         ret = oe_write_page(&og, fout);
664
 
         if(ret != og.header_len + og.body_len)
665
 
         {
666
 
            fprintf (stderr,"Error: failed writing header to output stream\n");
667
 
            exit(1);
668
 
         }
669
 
         else
670
 
            bytes_written += ret;
671
 
      }
672
 
   }
673
 
   /*Flush all pages left to be written*/
674
 
   while (ogg_stream_flush(&os, &og))
675
 
   {
676
 
      ret = oe_write_page(&og, fout);
677
 
      if(ret != og.header_len + og.body_len)
678
 
      {
679
 
         fprintf (stderr,"Error: failed writing header to output stream\n");
680
 
         exit(1);
681
 
      }
682
 
      else
683
 
         bytes_written += ret;
684
 
   }
685
 
 
686
 
   celt051_encoder_destroy(st);
687
 
   celt051_mode_destroy(mode);
688
 
   ogg_stream_clear(&os);
689
 
 
690
 
   if (close_in)
691
 
      fclose(fin);
692
 
   if (close_out)
693
 
      fclose(fout);
694
 
   return 0;
695
 
}
696
 
 
697
 
/*                 
698
 
 Comments will be stored in the Vorbis style.            
699
 
 It is describled in the "Structure" section of
700
 
    http://www.xiph.org/ogg/vorbis/doc/v-comment.html
701
 
 
702
 
The comment header is decoded as follows:
703
 
  1) [vendor_length] = read an unsigned integer of 32 bits
704
 
  2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
705
 
  3) [user_comment_list_length] = read an unsigned integer of 32 bits
706
 
  4) iterate [user_comment_list_length] times {
707
 
     5) [length] = read an unsigned integer of 32 bits
708
 
     6) this iteration's user comment = read a UTF-8 vector as [length] octets
709
 
     }
710
 
  7) [framing_bit] = read a single bit as boolean
711
 
  8) if ( [framing_bit]  unset or end of packet ) then ERROR
712
 
  9) done.
713
 
 
714
 
  If you have troubles, please write to ymnk@jcraft.com.
715
 
 */
716
 
 
717
 
#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
718
 
                           ((buf[base+2]<<16)&0xff0000)| \
719
 
                           ((buf[base+1]<<8)&0xff00)| \
720
 
                            (buf[base]&0xff))
721
 
#define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \
722
 
                                     buf[base+2]=((val)>>16)&0xff; \
723
 
                                     buf[base+1]=((val)>>8)&0xff; \
724
 
                                     buf[base]=(val)&0xff; \
725
 
                                 }while(0)
726
 
 
727
 
void comment_init(char **comments, int* length, char *vendor_string)
728
 
{
729
 
  int vendor_length=strlen(vendor_string);
730
 
  int user_comment_list_length=0;
731
 
  int len=4+vendor_length+4;
732
 
  char *p=(char*)malloc(len);
733
 
  if(p==NULL){
734
 
     fprintf (stderr, "malloc failed in comment_init()\n");
735
 
     exit(1);
736
 
  }
737
 
  writeint(p, 0, vendor_length);
738
 
  memcpy(p+4, vendor_string, vendor_length);
739
 
  writeint(p, 4+vendor_length, user_comment_list_length);
740
 
  *length=len;
741
 
  *comments=p;
742
 
}
743
 
void comment_add(char **comments, int* length, char *tag, char *val)
744
 
{
745
 
  char* p=*comments;
746
 
  int vendor_length=readint(p, 0);
747
 
  int user_comment_list_length=readint(p, 4+vendor_length);
748
 
  int tag_len=(tag?strlen(tag):0);
749
 
  int val_len=strlen(val);
750
 
  int len=(*length)+4+tag_len+val_len;
751
 
 
752
 
  p=(char*)realloc(p, len);
753
 
  if(p==NULL){
754
 
     fprintf (stderr, "realloc failed in comment_add()\n");
755
 
     exit(1);
756
 
  }
757
 
 
758
 
  writeint(p, *length, tag_len+val_len);      /* length of comment */
759
 
  if(tag) memcpy(p+*length+4, tag, tag_len);  /* comment */
760
 
  memcpy(p+*length+4+tag_len, val, val_len);  /* comment */
761
 
  writeint(p, 4+vendor_length, user_comment_list_length+1);
762
 
 
763
 
  *comments=p;
764
 
  *length=len;
765
 
}
766
 
#undef readint
767
 
#undef writeint