Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(852)

Side by Side Diff: webrtc/modules/utility/source/file_recorder.cc

Issue 2622493002: Move FilePlayer and FileRecorder to Voice Engine (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 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 #include "webrtc/modules/utility/include/file_recorder.h"
12
13 #include <list>
14
15 #include "webrtc/base/platform_thread.h"
16 #include "webrtc/common_audio/resampler/include/resampler.h"
17 #include "webrtc/common_types.h"
18 #include "webrtc/modules/include/module_common_types.h"
19 #include "webrtc/modules/media_file/media_file.h"
20 #include "webrtc/modules/media_file/media_file_defines.h"
21 #include "webrtc/modules/utility/source/coder.h"
22 #include "webrtc/system_wrappers/include/event_wrapper.h"
23 #include "webrtc/system_wrappers/include/logging.h"
24 #include "webrtc/typedefs.h"
25
26 namespace webrtc {
27
28 namespace {
29
30 // The largest decoded frame size in samples (60ms with 32kHz sample rate).
31 enum { MAX_AUDIO_BUFFER_IN_SAMPLES = 60 * 32 };
32 enum { MAX_AUDIO_BUFFER_IN_BYTES = MAX_AUDIO_BUFFER_IN_SAMPLES * 2 };
33 enum { kMaxAudioBufferQueueLength = 100 };
34
35 class CriticalSectionWrapper;
36
37 class FileRecorderImpl : public FileRecorder {
38 public:
39 FileRecorderImpl(uint32_t instanceID, FileFormats fileFormat);
40 ~FileRecorderImpl() override;
41
42 // FileRecorder functions.
43 int32_t RegisterModuleFileCallback(FileCallback* callback) override;
44 FileFormats RecordingFileFormat() const override;
45 int32_t StartRecordingAudioFile(const char* fileName,
46 const CodecInst& codecInst,
47 uint32_t notificationTimeMs) override;
48 int32_t StartRecordingAudioFile(OutStream* destStream,
49 const CodecInst& codecInst,
50 uint32_t notificationTimeMs) override;
51 int32_t StopRecording() override;
52 bool IsRecording() const override;
53 int32_t codec_info(CodecInst* codecInst) const override;
54 int32_t RecordAudioToFile(const AudioFrame& frame) override;
55
56 private:
57 int32_t WriteEncodedAudioData(const int8_t* audioBuffer, size_t bufferLength);
58
59 int32_t SetUpAudioEncoder();
60
61 uint32_t _instanceID;
62 FileFormats _fileFormat;
63 MediaFile* _moduleFile;
64
65 CodecInst codec_info_;
66 int8_t _audioBuffer[MAX_AUDIO_BUFFER_IN_BYTES];
67 AudioCoder _audioEncoder;
68 Resampler _audioResampler;
69 };
70
71 FileRecorderImpl::FileRecorderImpl(uint32_t instanceID, FileFormats fileFormat)
72 : _instanceID(instanceID),
73 _fileFormat(fileFormat),
74 _moduleFile(MediaFile::CreateMediaFile(_instanceID)),
75 codec_info_(),
76 _audioBuffer(),
77 _audioEncoder(instanceID),
78 _audioResampler() {}
79
80 FileRecorderImpl::~FileRecorderImpl() {
81 MediaFile::DestroyMediaFile(_moduleFile);
82 }
83
84 FileFormats FileRecorderImpl::RecordingFileFormat() const {
85 return _fileFormat;
86 }
87
88 int32_t FileRecorderImpl::RegisterModuleFileCallback(FileCallback* callback) {
89 if (_moduleFile == NULL) {
90 return -1;
91 }
92 return _moduleFile->SetModuleFileCallback(callback);
93 }
94
95 int32_t FileRecorderImpl::StartRecordingAudioFile(const char* fileName,
96 const CodecInst& codecInst,
97 uint32_t notificationTimeMs) {
98 if (_moduleFile == NULL) {
99 return -1;
100 }
101 codec_info_ = codecInst;
102 int32_t retVal = 0;
103 retVal = _moduleFile->StartRecordingAudioFile(fileName, _fileFormat,
104 codecInst, notificationTimeMs);
105
106 if (retVal == 0) {
107 retVal = SetUpAudioEncoder();
108 }
109 if (retVal != 0) {
110 LOG(LS_WARNING) << "Failed to initialize file " << fileName
111 << " for recording.";
112
113 if (IsRecording()) {
114 StopRecording();
115 }
116 }
117 return retVal;
118 }
119
120 int32_t FileRecorderImpl::StartRecordingAudioFile(OutStream* destStream,
121 const CodecInst& codecInst,
122 uint32_t notificationTimeMs) {
123 codec_info_ = codecInst;
124 int32_t retVal = _moduleFile->StartRecordingAudioStream(
125 *destStream, _fileFormat, codecInst, notificationTimeMs);
126
127 if (retVal == 0) {
128 retVal = SetUpAudioEncoder();
129 }
130 if (retVal != 0) {
131 LOG(LS_WARNING) << "Failed to initialize outStream for recording.";
132
133 if (IsRecording()) {
134 StopRecording();
135 }
136 }
137 return retVal;
138 }
139
140 int32_t FileRecorderImpl::StopRecording() {
141 memset(&codec_info_, 0, sizeof(CodecInst));
142 return _moduleFile->StopRecording();
143 }
144
145 bool FileRecorderImpl::IsRecording() const {
146 return _moduleFile->IsRecording();
147 }
148
149 int32_t FileRecorderImpl::RecordAudioToFile(
150 const AudioFrame& incomingAudioFrame) {
151 if (codec_info_.plfreq == 0) {
152 LOG(LS_WARNING) << "RecordAudioToFile() recording audio is not "
153 << "turned on.";
154 return -1;
155 }
156 AudioFrame tempAudioFrame;
157 tempAudioFrame.samples_per_channel_ = 0;
158 if (incomingAudioFrame.num_channels_ == 2 && !_moduleFile->IsStereo()) {
159 // Recording mono but incoming audio is (interleaved) stereo.
160 tempAudioFrame.num_channels_ = 1;
161 tempAudioFrame.sample_rate_hz_ = incomingAudioFrame.sample_rate_hz_;
162 tempAudioFrame.samples_per_channel_ =
163 incomingAudioFrame.samples_per_channel_;
164 for (size_t i = 0; i < (incomingAudioFrame.samples_per_channel_); i++) {
165 // Sample value is the average of left and right buffer rounded to
166 // closest integer value. Note samples can be either 1 or 2 byte.
167 tempAudioFrame.data_[i] = ((incomingAudioFrame.data_[2 * i] +
168 incomingAudioFrame.data_[(2 * i) + 1] + 1) >>
169 1);
170 }
171 } else if (incomingAudioFrame.num_channels_ == 1 && _moduleFile->IsStereo()) {
172 // Recording stereo but incoming audio is mono.
173 tempAudioFrame.num_channels_ = 2;
174 tempAudioFrame.sample_rate_hz_ = incomingAudioFrame.sample_rate_hz_;
175 tempAudioFrame.samples_per_channel_ =
176 incomingAudioFrame.samples_per_channel_;
177 for (size_t i = 0; i < (incomingAudioFrame.samples_per_channel_); i++) {
178 // Duplicate sample to both channels
179 tempAudioFrame.data_[2 * i] = incomingAudioFrame.data_[i];
180 tempAudioFrame.data_[2 * i + 1] = incomingAudioFrame.data_[i];
181 }
182 }
183
184 const AudioFrame* ptrAudioFrame = &incomingAudioFrame;
185 if (tempAudioFrame.samples_per_channel_ != 0) {
186 // If ptrAudioFrame is not empty it contains the audio to be recorded.
187 ptrAudioFrame = &tempAudioFrame;
188 }
189
190 // Encode the audio data before writing to file. Don't encode if the codec
191 // is PCM.
192 // NOTE: stereo recording is only supported for WAV files.
193 // TODO(hellner): WAV expect PCM in little endian byte order. Not
194 // "encoding" with PCM coder should be a problem for big endian systems.
195 size_t encodedLenInBytes = 0;
196 if (_fileFormat == kFileFormatPreencodedFile ||
197 STR_CASE_CMP(codec_info_.plname, "L16") != 0) {
198 if (_audioEncoder.Encode(*ptrAudioFrame, _audioBuffer,
199 &encodedLenInBytes) == -1) {
200 LOG(LS_WARNING) << "RecordAudioToFile() codec " << codec_info_.plname
201 << " not supported or failed to encode stream.";
202 return -1;
203 }
204 } else {
205 size_t outLen = 0;
206 _audioResampler.ResetIfNeeded(ptrAudioFrame->sample_rate_hz_,
207 codec_info_.plfreq,
208 ptrAudioFrame->num_channels_);
209 _audioResampler.Push(
210 ptrAudioFrame->data_,
211 ptrAudioFrame->samples_per_channel_ * ptrAudioFrame->num_channels_,
212 reinterpret_cast<int16_t*>(_audioBuffer), MAX_AUDIO_BUFFER_IN_BYTES,
213 outLen);
214 encodedLenInBytes = outLen * sizeof(int16_t);
215 }
216
217 // Codec may not be operating at a frame rate of 10 ms. Whenever enough
218 // 10 ms chunks of data has been pushed to the encoder an encoded frame
219 // will be available. Wait until then.
220 if (encodedLenInBytes) {
221 if (WriteEncodedAudioData(_audioBuffer, encodedLenInBytes) == -1) {
222 return -1;
223 }
224 }
225 return 0;
226 }
227
228 int32_t FileRecorderImpl::SetUpAudioEncoder() {
229 if (_fileFormat == kFileFormatPreencodedFile ||
230 STR_CASE_CMP(codec_info_.plname, "L16") != 0) {
231 if (_audioEncoder.SetEncodeCodec(codec_info_) == -1) {
232 LOG(LS_ERROR) << "SetUpAudioEncoder() codec " << codec_info_.plname
233 << " not supported.";
234 return -1;
235 }
236 }
237 return 0;
238 }
239
240 int32_t FileRecorderImpl::codec_info(CodecInst* codecInst) const {
241 if (codec_info_.plfreq == 0) {
242 return -1;
243 }
244 *codecInst = codec_info_;
245 return 0;
246 }
247
248 int32_t FileRecorderImpl::WriteEncodedAudioData(const int8_t* audioBuffer,
249 size_t bufferLength) {
250 return _moduleFile->IncomingAudioData(audioBuffer, bufferLength);
251 }
252
253 } // namespace
254
255 std::unique_ptr<FileRecorder> FileRecorder::CreateFileRecorder(
256 uint32_t instanceID,
257 FileFormats fileFormat) {
258 return std::unique_ptr<FileRecorder>(
259 new FileRecorderImpl(instanceID, fileFormat));
260 }
261
262 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698