blob: fb8d25af035e074a1cdd96a39cd2debc7201be71 [file] [log] [blame]
Andreas Hubercc1cd952018-01-18 12:57:33 -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 "vsoc_audio_message.h"
18
19#include "common/vsoc/lib/audio_data_region_view.h"
20#include "common/vsoc/lib/circqueue_impl.h"
21
22#include "WaveWriter.h"
23
24#include <cstdlib>
25#include <cstring>
26#include <iostream>
27#include <unistd.h>
28
29using AudioDataRegionView = vsoc::audio_data::AudioDataRegionView;
30using WaveWriter = android::WaveWriter;
31
32static void usage(const char *me) {
33 std::cerr << "usage: " << me << " -o filename [-v(erbose)]" << std::endl;
34 std::exit(1);
35}
36
37volatile bool gDone = false;
38static void SigIntHandler(int /* sig */) {
39 gDone = true;
40}
41
42int main(int argc, char **argv) {
43 const char *me = argv[0];
44
45 std::string outputPath;
46 bool verbose = false;
47
48 int res;
49 while ((res = getopt(argc, argv, "ho:v")) >= 0) {
50 switch (res) {
51 case 'o':
52 {
53 outputPath = optarg;
54 break;
55 }
56
57 case 'v' :
58 {
59 verbose = true;
60 break;
61 }
62
63 case '?':
64 case 'h':
65 default:
66 {
67 usage(me);
68 break;
69 }
70 }
71 }
72
73 argc -= optind;
74 argv += optind;
75
76 if (outputPath.empty()) {
77 usage(me);
78 }
79
Jorge E. Moreira4b9bbb12017-12-28 15:49:06 -080080 auto audio_data_rv = AudioDataRegionView::GetInstance();
Ryan Haining59063a92018-02-08 17:32:22 -080081 CHECK(audio_data_rv != nullptr);
Andreas Hubercc1cd952018-01-18 12:57:33 -080082
83 /* std::unique_ptr<vsoc::RegionWorker> audio_worker = */
Ryan Haining59063a92018-02-08 17:32:22 -080084 audio_data_rv->StartWorker();
Andreas Hubercc1cd952018-01-18 12:57:33 -080085
86 std::unique_ptr<WaveWriter> writer;
87 int64_t frameCount = 0ll;
88
89 // The configuration the writer is setup for.
90 gce_audio_message writer_hdr;
91
92 uint8_t buffer[4096];
93
94 gDone = false;
95
96 struct sigaction act;
97 sigemptyset(&act.sa_mask);
98 act.sa_flags = 0;
99 act.sa_handler = SigIntHandler;
100
101 struct sigaction oact;
102 sigaction(SIGINT, &act, &oact);
103
104 while (!gDone) {
105 intptr_t res = audio_data_rv->data()->audio_queue.Read(
Ryan Haining59063a92018-02-08 17:32:22 -0800106 audio_data_rv,
Andreas Hubercc1cd952018-01-18 12:57:33 -0800107 reinterpret_cast<char *>(buffer),
108 sizeof(buffer));
109
110 if (res < 0) {
111 std::cerr << "CircularPacketQueue::Read returned " << res << std::endl;
112 continue;
113 }
114
115 CHECK_GE(static_cast<size_t>(res), sizeof(gce_audio_message));
116
117 gce_audio_message hdr;
118 std::memcpy(&hdr, buffer, sizeof(gce_audio_message));
119
120 if (hdr.message_type != gce_audio_message::DATA_SAMPLES) {
121 continue;
122 }
123
124 const size_t payloadSize = res - sizeof(gce_audio_message);
125
126 if (verbose) {
127 std::cout
128 << "stream "
129 << hdr.stream_number
130 << ", frame "
131 << hdr.frame_num
132 << ", rate "
133 << hdr.frame_rate
134 << ", channel_mask "
135 << hdr.channel_mask
136 << ", format "
137 << hdr.format
138 << ", payload_size "
139 << payloadSize
140 << std::endl;
141 }
142
143 if (!writer) {
144 const size_t numChannels = hdr.frame_size / sizeof(int16_t);
145
146 writer.reset(
147 new WaveWriter(outputPath.c_str(), numChannels, hdr.frame_rate));
148
149 frameCount = hdr.frame_num;
150 writer_hdr = hdr;
151 } else if (writer_hdr.frame_size != hdr.frame_size
152 || writer_hdr.frame_rate != hdr.frame_rate
153 || writer_hdr.stream_number != hdr.stream_number) {
154 std::cerr << "Audio configuration changed. Aborting." << std::endl;
155 break;
156 }
157
158 int64_t framesMissing = hdr.frame_num - frameCount;
159 if (framesMissing > 0) {
160 // TODO(andih): Insert silence here, if necessary.
161 }
162
163 frameCount = hdr.frame_num;
164
165 writer->Append(&buffer[sizeof(gce_audio_message)], payloadSize);
166 }
167
168 std::cout << "Done." << std::endl;
169
170 return 0;
171}