Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 // Commandline tool to unpack audioproc debug files.
     12 //
     13 // The debug files are dumped as protobuf blobs. For analysis, it's necessary
     14 // to unpack the file into its component parts: audio and other data.
     15 
     16 #include <stdio.h>
     17 
     18 #include "google/gflags.h"
     19 #include "scoped_ptr.h"
     20 #include "typedefs.h"
     21 #include "webrtc/audio_processing/debug.pb.h"
     22 
     23 using webrtc::scoped_array;
     24 
     25 using webrtc::audioproc::Event;
     26 using webrtc::audioproc::ReverseStream;
     27 using webrtc::audioproc::Stream;
     28 using webrtc::audioproc::Init;
     29 
     30 // TODO(andrew): unpack more of the data.
     31 DEFINE_string(input_file, "input.pcm", "The name of the input stream file.");
     32 DEFINE_string(output_file, "ref_out.pcm",
     33               "The name of the reference output stream file.");
     34 DEFINE_string(reverse_file, "reverse.pcm",
     35               "The name of the reverse input stream file.");
     36 DEFINE_string(delay_file, "delay.int32", "The name of the delay file.");
     37 DEFINE_string(drift_file, "drift.int32", "The name of the drift file.");
     38 DEFINE_string(level_file, "level.int32", "The name of the level file.");
     39 DEFINE_string(settings_file, "settings.txt", "The name of the settings file.");
     40 DEFINE_bool(full, false,
     41             "Unpack the full set of files (normally not needed).");
     42 
     43 // TODO(andrew): move this to a helper class to share with process_test.cc?
     44 // Returns true on success, false on error or end-of-file.
     45 bool ReadMessageFromFile(FILE* file,
     46                         ::google::protobuf::MessageLite* msg) {
     47   // The "wire format" for the size is little-endian.
     48   // Assume process_test is running on a little-endian machine.
     49   int32_t size = 0;
     50   if (fread(&size, sizeof(int32_t), 1, file) != 1) {
     51     return false;
     52   }
     53   if (size <= 0) {
     54     return false;
     55   }
     56   const size_t usize = static_cast<size_t>(size);
     57 
     58   scoped_array<char> array(new char[usize]);
     59   if (fread(array.get(), sizeof(char), usize, file) != usize) {
     60     return false;
     61   }
     62 
     63   msg->Clear();
     64   return msg->ParseFromArray(array.get(), usize);
     65 }
     66 
     67 int main(int argc, char* argv[]) {
     68   std::string program_name = argv[0];
     69   std::string usage = "Commandline tool to unpack audioproc debug files.\n"
     70     "Example usage:\n" + program_name + " debug_dump.pb\n";
     71   google::SetUsageMessage(usage);
     72   google::ParseCommandLineFlags(&argc, &argv, true);
     73 
     74   if (argc < 2) {
     75     printf("%s", google::ProgramUsage());
     76     return 1;
     77   }
     78 
     79   FILE* debug_file = fopen(argv[1], "rb");
     80   if (debug_file == NULL) {
     81     printf("Unable to open %s\n", argv[1]);
     82     return 1;
     83   }
     84   FILE* input_file = fopen(FLAGS_input_file.c_str(), "wb");
     85   if (input_file == NULL) {
     86     printf("Unable to open %s\n", FLAGS_input_file.c_str());
     87     return 1;
     88   }
     89   FILE* output_file = fopen(FLAGS_output_file.c_str(), "wb");
     90   if (output_file == NULL) {
     91     printf("Unable to open %s\n", FLAGS_output_file.c_str());
     92     return 1;
     93   }
     94   FILE* reverse_file = fopen(FLAGS_reverse_file.c_str(), "wb");
     95   if (reverse_file == NULL) {
     96     printf("Unable to open %s\n", FLAGS_reverse_file.c_str());
     97     return 1;
     98   }
     99   FILE* settings_file = fopen(FLAGS_settings_file.c_str(), "wb");
    100   if (settings_file == NULL) {
    101     printf("Unable to open %s\n", FLAGS_settings_file.c_str());
    102     return 1;
    103   }
    104 
    105   FILE* delay_file = NULL;
    106   FILE* drift_file = NULL;
    107   FILE* level_file = NULL;
    108   if (FLAGS_full) {
    109     delay_file = fopen(FLAGS_delay_file.c_str(), "wb");
    110     if (delay_file == NULL) {
    111       printf("Unable to open %s\n", FLAGS_delay_file.c_str());
    112       return 1;
    113     }
    114     drift_file = fopen(FLAGS_drift_file.c_str(), "wb");
    115     if (drift_file == NULL) {
    116       printf("Unable to open %s\n", FLAGS_drift_file.c_str());
    117       return 1;
    118     }
    119     level_file = fopen(FLAGS_level_file.c_str(), "wb");
    120     if (level_file == NULL) {
    121       printf("Unable to open %s\n", FLAGS_level_file.c_str());
    122       return 1;
    123     }
    124   }
    125 
    126   Event event_msg;
    127   int frame_count = 0;
    128   while (ReadMessageFromFile(debug_file, &event_msg)) {
    129     if (event_msg.type() == Event::REVERSE_STREAM) {
    130       if (!event_msg.has_reverse_stream()) {
    131         printf("Corrupted input file: ReverseStream missing.\n");
    132         return 1;
    133       }
    134 
    135       const ReverseStream msg = event_msg.reverse_stream();
    136       if (msg.has_data()) {
    137         if (fwrite(msg.data().data(), msg.data().size(), 1, reverse_file) !=
    138             1) {
    139           printf("Error when writing to %s\n", FLAGS_reverse_file.c_str());
    140           return 1;
    141         }
    142       }
    143     } else if (event_msg.type() == Event::STREAM) {
    144       frame_count++;
    145       if (!event_msg.has_stream()) {
    146         printf("Corrupted input file: Stream missing.\n");
    147         return 1;
    148       }
    149 
    150       const Stream msg = event_msg.stream();
    151       if (msg.has_input_data()) {
    152         if (fwrite(msg.input_data().data(), msg.input_data().size(), 1,
    153                    input_file) != 1) {
    154           printf("Error when writing to %s\n", FLAGS_input_file.c_str());
    155           return 1;
    156         }
    157       }
    158 
    159       if (msg.has_output_data()) {
    160         if (fwrite(msg.output_data().data(), msg.output_data().size(), 1,
    161                    output_file) != 1) {
    162           printf("Error when writing to %s\n", FLAGS_output_file.c_str());
    163           return 1;
    164         }
    165       }
    166 
    167       if (FLAGS_full) {
    168         if (msg.has_delay()) {
    169           int32_t delay = msg.delay();
    170           if (fwrite(&delay, sizeof(int32_t), 1, delay_file) != 1) {
    171             printf("Error when writing to %s\n", FLAGS_delay_file.c_str());
    172             return 1;
    173           }
    174         }
    175 
    176         if (msg.has_drift()) {
    177           int32_t drift = msg.drift();
    178           if (fwrite(&drift, sizeof(int32_t), 1, drift_file) != 1) {
    179             printf("Error when writing to %s\n", FLAGS_drift_file.c_str());
    180             return 1;
    181           }
    182         }
    183 
    184         if (msg.has_level()) {
    185           int32_t level = msg.level();
    186           if (fwrite(&level, sizeof(int32_t), 1, level_file) != 1) {
    187             printf("Error when writing to %s\n", FLAGS_level_file.c_str());
    188             return 1;
    189           }
    190         }
    191       }
    192     } else if (event_msg.type() == Event::INIT) {
    193       if (!event_msg.has_init()) {
    194         printf("Corrupted input file: Init missing.\n");
    195         return 1;
    196       }
    197 
    198       const Init msg = event_msg.init();
    199       // These should print out zeros if they're missing.
    200       fprintf(settings_file, "Init at frame: %d\n", frame_count);
    201       fprintf(settings_file, "  Sample rate: %d\n", msg.sample_rate());
    202       fprintf(settings_file, "  Device sample rate: %d\n",
    203               msg.device_sample_rate());
    204       fprintf(settings_file, "  Input channels: %d\n",
    205               msg.num_input_channels());
    206       fprintf(settings_file, "  Output channels: %d\n",
    207               msg.num_output_channels());
    208       fprintf(settings_file, "  Reverse channels: %d\n",
    209               msg.num_reverse_channels());
    210 
    211       fprintf(settings_file, "\n");
    212     }
    213   }
    214 
    215   return 0;
    216 }
    217