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

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

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

Powered by Google App Engine
This is Rietveld 408576698