Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2011 Xiph.Org Foundation
      2    Written by Jean-Marc Valin */
      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    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     18    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     19    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     23    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     24    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     25    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 */
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include "opus.h"
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 
     37 #define MAX_PACKETOUT 32000
     38 
     39 void usage(char *argv0)
     40 {
     41    fprintf(stderr, "usage: %s [options] input_file output_file\n", argv0);
     42 }
     43 
     44 static void int_to_char(opus_uint32 i, unsigned char ch[4])
     45 {
     46     ch[0] = i>>24;
     47     ch[1] = (i>>16)&0xFF;
     48     ch[2] = (i>>8)&0xFF;
     49     ch[3] = i&0xFF;
     50 }
     51 
     52 static opus_uint32 char_to_int(unsigned char ch[4])
     53 {
     54     return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
     55          | ((opus_uint32)ch[2]<< 8) |  (opus_uint32)ch[3];
     56 }
     57 
     58 int main(int argc, char *argv[])
     59 {
     60    int i, eof=0;
     61    FILE *fin, *fout;
     62    unsigned char packets[48][1500];
     63    int len[48];
     64    int rng[48];
     65    OpusRepacketizer *rp;
     66    unsigned char output_packet[MAX_PACKETOUT];
     67    int merge = 1, split=0;
     68 
     69    if (argc < 3)
     70    {
     71       usage(argv[0]);
     72       return EXIT_FAILURE;
     73    }
     74    for (i=1;i<argc-2;i++)
     75    {
     76       if (strcmp(argv[i], "-merge")==0)
     77       {
     78          merge = atoi(argv[i+1]);
     79          if(merge<1)
     80          {
     81             fprintf(stderr, "-merge parameter must be at least 1.\n");
     82             return EXIT_FAILURE;
     83          }
     84          if(merge>48)
     85          {
     86             fprintf(stderr, "-merge parameter must be less than 48.\n");
     87             return EXIT_FAILURE;
     88          }
     89          i++;
     90       } else if (strcmp(argv[i], "-split")==0)
     91          split = 1;
     92       else
     93       {
     94          fprintf(stderr, "Unknown option: %s\n", argv[i]);
     95          usage(argv[0]);
     96          return EXIT_FAILURE;
     97       }
     98    }
     99    fin = fopen(argv[argc-2], "r");
    100    if(fin==NULL)
    101    {
    102      fprintf(stderr, "Error opening input file: %s\n", argv[argc-2]);
    103      return EXIT_FAILURE;
    104    }
    105    fout = fopen(argv[argc-1], "w");
    106    if(fout==NULL)
    107    {
    108      fprintf(stderr, "Error opening output file: %s\n", argv[argc-1]);
    109      fclose(fin);
    110      return EXIT_FAILURE;
    111    }
    112 
    113    rp = opus_repacketizer_create();
    114    while (!eof)
    115    {
    116       int err;
    117       int nb_packets=merge;
    118       opus_repacketizer_init(rp);
    119       for (i=0;i<nb_packets;i++)
    120       {
    121          unsigned char ch[4];
    122          err = fread(ch, 1, 4, fin);
    123          len[i] = char_to_int(ch);
    124          /*fprintf(stderr, "in len = %d\n", len[i]);*/
    125          if (len[i]>1500 || len[i]<0)
    126          {
    127              if (feof(fin))
    128              {
    129                 eof = 1;
    130              } else {
    131                 fprintf(stderr, "Invalid payload length\n");
    132                 fclose(fin);
    133                 fclose(fout);
    134                 return EXIT_FAILURE;
    135              }
    136              break;
    137          }
    138          err = fread(ch, 1, 4, fin);
    139          rng[i] = char_to_int(ch);
    140          err = fread(packets[i], 1, len[i], fin);
    141          if (feof(fin))
    142          {
    143             eof = 1;
    144             break;
    145          }
    146          err = opus_repacketizer_cat(rp, packets[i], len[i]);
    147          if (err!=OPUS_OK)
    148          {
    149             fprintf(stderr, "opus_repacketizer_cat() failed: %s\n", opus_strerror(err));
    150             break;
    151          }
    152       }
    153       nb_packets = i;
    154 
    155       if (eof)
    156          break;
    157 
    158       if (!split)
    159       {
    160          err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT);
    161          if (err>0) {
    162             unsigned char int_field[4];
    163             int_to_char(err, int_field);
    164             if(fwrite(int_field, 1, 4, fout)!=4){
    165                fprintf(stderr, "Error writing.\n");
    166                return EXIT_FAILURE;
    167             }
    168             int_to_char(rng[nb_packets-1], int_field);
    169             if (fwrite(int_field, 1, 4, fout)!=4) {
    170                fprintf(stderr, "Error writing.\n");
    171                return EXIT_FAILURE;
    172             }
    173             if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) {
    174                fprintf(stderr, "Error writing.\n");
    175                return EXIT_FAILURE;
    176             }
    177             /*fprintf(stderr, "out len = %d\n", err);*/
    178          } else {
    179             fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
    180          }
    181       } else {
    182          int nb_frames = opus_repacketizer_get_nb_frames(rp);
    183          for (i=0;i<nb_frames;i++)
    184          {
    185             err = opus_repacketizer_out_range(rp, i, i+1, output_packet, MAX_PACKETOUT);
    186             if (err>0) {
    187                unsigned char int_field[4];
    188                int_to_char(err, int_field);
    189                if (fwrite(int_field, 1, 4, fout)!=4) {
    190                   fprintf(stderr, "Error writing.\n");
    191                   return EXIT_FAILURE;
    192                }
    193                if (i==nb_frames-1)
    194                   int_to_char(rng[nb_packets-1], int_field);
    195                else
    196                   int_to_char(0, int_field);
    197                if (fwrite(int_field, 1, 4, fout)!=4) {
    198                   fprintf(stderr, "Error writing.\n");
    199                   return EXIT_FAILURE;
    200                }
    201                if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) {
    202                   fprintf(stderr, "Error writing.\n");
    203                   return EXIT_FAILURE;
    204                }
    205                /*fprintf(stderr, "out len = %d\n", err);*/
    206             } else {
    207                fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
    208             }
    209 
    210          }
    211       }
    212    }
    213 
    214    fclose(fin);
    215    fclose(fout);
    216    return EXIT_SUCCESS;
    217 }
    218