blob: 3c024b817b44c600ca38ffecdfedea0c49b15c7c [file] [log] [blame]
Cody Schuffelen134ff032019-11-22 00:25:32 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "common/vsoc/lib/audio_data_region_view.h"
18#include "common/vsoc/lib/circqueue_impl.h"
19#include "common/vsoc/lib/vsoc_audio_message.h"
20#include "host/libs/config/cuttlefish_config.h"
21
22#include "WaveWriter.h"
23
24#include <android-base/logging.h>
25#include <gflags/gflags.h>
26#include <iostream>
27#include <signal.h>
28
29using AudioDataRegionView = vsoc::audio_data::AudioDataRegionView;
30using WaveWriter = android::WaveWriter;
31
32DEFINE_string(output_file, "", "Location of the output audio file.");
33DEFINE_bool(verbose, false, "Enable verbose logging.");
34
35volatile bool gDone = false;
36static void SigIntHandler(int /* sig */) {
37 gDone = true;
38}
39
40int main(int argc, char **argv) {
41 ::android::base::InitLogging(argv, android::base::StderrLogger);
42 google::ParseCommandLineFlags(&argc, &argv, true);
43
44 LOG_IF(FATAL, FLAGS_output_file.empty())
45 << "--output_file must be specified.";
46
47 AudioDataRegionView *audio_data_rv =
48 AudioDataRegionView::GetInstance(vsoc::GetDomain().c_str());
49
50 auto worker = audio_data_rv->StartWorker();
51
52 std::unique_ptr<WaveWriter> writer;
53 int64_t frameCount = 0LL;
54
55 // The configuration the writer is setup for.
56 gce_audio_message writer_hdr;
57
58 uint8_t buffer[4096];
59
60 gDone = false;
61
62 struct sigaction act;
63 sigemptyset(&act.sa_mask);
64 act.sa_flags = 0;
65 act.sa_handler = SigIntHandler;
66
67 struct sigaction oact;
68 sigaction(SIGINT, &act, &oact);
69
70 while (!gDone) {
71 intptr_t res = audio_data_rv->data()->audio_queue.Read(
72 audio_data_rv,
73 reinterpret_cast<char *>(buffer),
74 sizeof(buffer));
75
76 if (res < 0) {
77 std::cerr << "CircularPacketQueue::Read returned " << res << std::endl;
78 continue;
79 }
80
81 CHECK_GE(static_cast<size_t>(res), sizeof(gce_audio_message));
82
83 gce_audio_message hdr;
84 std::memcpy(&hdr, buffer, sizeof(gce_audio_message));
85
86 if (hdr.message_type != gce_audio_message::DATA_SAMPLES) {
87 continue;
88 }
89
90 const size_t payloadSize = res - sizeof(gce_audio_message);
91
92 if (FLAGS_verbose) {
93 std::cerr
94 << "stream "
95 << hdr.stream_number
96 << ", frame "
97 << hdr.frame_num
98 << ", rate "
99 << hdr.frame_rate
100 << ", channel_mask "
101 << hdr.channel_mask
102 << ", format "
103 << hdr.format
104 << ", payload_size "
105 << payloadSize
106 << std::endl;
107 }
108
109 if (!writer) {
110 const size_t numChannels = hdr.frame_size / sizeof(int16_t);
111
112 writer.reset(
113 new WaveWriter(FLAGS_output_file.c_str(), numChannels, hdr.frame_rate));
114
115 frameCount = hdr.frame_num;
116 writer_hdr = hdr;
117 } else if (writer_hdr.frame_size != hdr.frame_size
118 || writer_hdr.frame_rate != hdr.frame_rate
119 || writer_hdr.stream_number != hdr.stream_number) {
120 std::cerr << "Audio configuration changed. Aborting." << std::endl;
121 break;
122 }
123
124 int64_t framesMissing = hdr.frame_num - frameCount;
125 if (framesMissing > 0) {
126 // TODO(andih): Insert silence here, if necessary.
127 }
128
129 frameCount = hdr.frame_num;
130
131 writer->Append(&buffer[sizeof(gce_audio_message)], payloadSize);
132 }
133
134 std::cout << "DONE" << std::endl;
135
136 return 0;
137}
138