OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/audio_sender/audio_encoder.h" | 5 #include "media/cast/audio_sender/audio_encoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 rtp_timestamp, frame_id, | 53 rtp_timestamp, frame_id, |
54 static_cast<int>(frame_size), /* key_frame - unused */ false, | 54 static_cast<int>(frame_size), /* key_frame - unused */ false, |
55 /*target_bitrate - unused*/ 0); | 55 /*target_bitrate - unused*/ 0); |
56 } | 56 } |
57 | 57 |
58 } // namespace | 58 } // namespace |
59 | 59 |
60 | 60 |
61 // Base class that handles the common problem of feeding one or more AudioBus' | 61 // Base class that handles the common problem of feeding one or more AudioBus' |
62 // data into a buffer and then, once the buffer is full, encoding the signal and | 62 // data into a buffer and then, once the buffer is full, encoding the signal and |
63 // emitting an EncodedAudioFrame via the FrameEncodedCallback. | 63 // emitting an EncodedFrame via the FrameEncodedCallback. |
64 // | 64 // |
65 // Subclasses complete the implementation by handling the actual encoding | 65 // Subclasses complete the implementation by handling the actual encoding |
66 // details. | 66 // details. |
67 class AudioEncoder::ImplBase | 67 class AudioEncoder::ImplBase |
68 : public base::RefCountedThreadSafe<AudioEncoder::ImplBase> { | 68 : public base::RefCountedThreadSafe<AudioEncoder::ImplBase> { |
69 public: | 69 public: |
70 ImplBase(const scoped_refptr<CastEnvironment>& cast_environment, | 70 ImplBase(const scoped_refptr<CastEnvironment>& cast_environment, |
71 transport::AudioCodec codec, | 71 transport::AudioCodec codec, |
72 int num_channels, | 72 int num_channels, |
73 int sampling_rate, | 73 int sampling_rate, |
74 const FrameEncodedCallback& callback) | 74 const FrameEncodedCallback& callback) |
75 : cast_environment_(cast_environment), | 75 : cast_environment_(cast_environment), |
76 codec_(codec), | 76 codec_(codec), |
77 num_channels_(num_channels), | 77 num_channels_(num_channels), |
78 samples_per_frame_(sampling_rate / kFramesPerSecond), | 78 samples_per_frame_(sampling_rate / kFramesPerSecond), |
79 callback_(callback), | 79 callback_(callback), |
80 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), | 80 cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), |
81 buffer_fill_end_(0), | 81 buffer_fill_end_(0), |
82 frame_id_(0), | 82 frame_id_(0), |
83 frame_rtp_timestamp_(0) { | 83 frame_rtp_timestamp_(0) { |
| 84 // Support for max sampling rate of 48KHz, 2 channels, 100 ms duration. |
| 85 const int kMaxSamplesTimesChannelsPerFrame = 48 * 2 * 100; |
84 if (num_channels_ <= 0 || samples_per_frame_ <= 0 || | 86 if (num_channels_ <= 0 || samples_per_frame_ <= 0 || |
85 sampling_rate % kFramesPerSecond != 0 || | 87 sampling_rate % kFramesPerSecond != 0 || |
86 samples_per_frame_ * num_channels_ > | 88 samples_per_frame_ * num_channels_ > kMaxSamplesTimesChannelsPerFrame) { |
87 transport::EncodedAudioFrame::kMaxNumberOfSamples) { | |
88 cast_initialization_status_ = STATUS_INVALID_AUDIO_CONFIGURATION; | 89 cast_initialization_status_ = STATUS_INVALID_AUDIO_CONFIGURATION; |
89 } | 90 } |
90 } | 91 } |
91 | 92 |
92 CastInitializationStatus InitializationResult() const { | 93 CastInitializationStatus InitializationResult() const { |
93 return cast_initialization_status_; | 94 return cast_initialization_status_; |
94 } | 95 } |
95 | 96 |
96 void EncodeAudio(scoped_ptr<AudioBus> audio_bus, | 97 void EncodeAudio(scoped_ptr<AudioBus> audio_bus, |
97 const base::TimeTicks& recorded_time) { | 98 const base::TimeTicks& recorded_time) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 samples_per_frame_ - buffer_fill_end_, audio_bus->frames() - src_pos); | 134 samples_per_frame_ - buffer_fill_end_, audio_bus->frames() - src_pos); |
134 DCHECK_EQ(audio_bus->channels(), num_channels_); | 135 DCHECK_EQ(audio_bus->channels(), num_channels_); |
135 TransferSamplesIntoBuffer( | 136 TransferSamplesIntoBuffer( |
136 audio_bus.get(), src_pos, buffer_fill_end_, num_samples_to_xfer); | 137 audio_bus.get(), src_pos, buffer_fill_end_, num_samples_to_xfer); |
137 src_pos += num_samples_to_xfer; | 138 src_pos += num_samples_to_xfer; |
138 buffer_fill_end_ += num_samples_to_xfer; | 139 buffer_fill_end_ += num_samples_to_xfer; |
139 | 140 |
140 if (buffer_fill_end_ < samples_per_frame_) | 141 if (buffer_fill_end_ < samples_per_frame_) |
141 break; | 142 break; |
142 | 143 |
143 scoped_ptr<transport::EncodedAudioFrame> audio_frame( | 144 scoped_ptr<transport::EncodedFrame> audio_frame( |
144 new transport::EncodedAudioFrame()); | 145 new transport::EncodedFrame()); |
145 audio_frame->codec = codec_; | 146 audio_frame->dependency = transport::EncodedFrame::KEY; |
146 audio_frame->frame_id = frame_id_; | 147 audio_frame->frame_id = frame_id_; |
| 148 audio_frame->referenced_frame_id = frame_id_; |
147 audio_frame->rtp_timestamp = frame_rtp_timestamp_; | 149 audio_frame->rtp_timestamp = frame_rtp_timestamp_; |
| 150 audio_frame->reference_time = frame_capture_time_; |
148 | 151 |
149 if (EncodeFromFilledBuffer(&audio_frame->data)) { | 152 if (EncodeFromFilledBuffer(&audio_frame->data)) { |
150 LogAudioFrameEncodedEvent(cast_environment_, | 153 LogAudioFrameEncodedEvent(cast_environment_, |
151 cast_environment_->Clock()->NowTicks(), | 154 cast_environment_->Clock()->NowTicks(), |
152 audio_frame->rtp_timestamp, | 155 audio_frame->rtp_timestamp, |
153 audio_frame->frame_id, | 156 audio_frame->frame_id, |
154 audio_frame->data.size()); | 157 audio_frame->data.size()); |
155 cast_environment_->PostTask( | 158 cast_environment_->PostTask( |
156 CastEnvironment::MAIN, | 159 CastEnvironment::MAIN, |
157 FROM_HERE, | 160 FROM_HERE, |
158 base::Bind(callback_, | 161 base::Bind(callback_, base::Passed(&audio_frame))); |
159 base::Passed(&audio_frame), | |
160 frame_capture_time_)); | |
161 } | 162 } |
162 | 163 |
163 // Reset the internal buffer, frame ID, and timestamps for the next frame. | 164 // Reset the internal buffer, frame ID, and timestamps for the next frame. |
164 buffer_fill_end_ = 0; | 165 buffer_fill_end_ = 0; |
165 ++frame_id_; | 166 ++frame_id_; |
166 frame_rtp_timestamp_ += samples_per_frame_; | 167 frame_rtp_timestamp_ += samples_per_frame_; |
167 frame_capture_time_ += frame_duration; | 168 frame_capture_time_ += frame_duration; |
168 } | 169 } |
169 } | 170 } |
170 | 171 |
(...skipping 15 matching lines...) Expand all Loading... |
186 | 187 |
187 // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED. | 188 // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED. |
188 CastInitializationStatus cast_initialization_status_; | 189 CastInitializationStatus cast_initialization_status_; |
189 | 190 |
190 private: | 191 private: |
191 // In the case where a call to EncodeAudio() cannot completely fill the | 192 // In the case where a call to EncodeAudio() cannot completely fill the |
192 // buffer, this points to the position at which to populate data in a later | 193 // buffer, this points to the position at which to populate data in a later |
193 // call. | 194 // call. |
194 int buffer_fill_end_; | 195 int buffer_fill_end_; |
195 | 196 |
196 // A counter used to label EncodedAudioFrames. | 197 // A counter used to label EncodedFrames. |
197 uint32 frame_id_; | 198 uint32 frame_id_; |
198 | 199 |
199 // The RTP timestamp for the next frame of encoded audio. This is defined as | 200 // The RTP timestamp for the next frame of encoded audio. This is defined as |
200 // the number of audio samples encoded so far, plus the estimated number of | 201 // the number of audio samples encoded so far, plus the estimated number of |
201 // samples that were missed due to data underruns. A receiver uses this value | 202 // samples that were missed due to data underruns. A receiver uses this value |
202 // to detect gaps in the audio signal data being provided. Per the spec, RTP | 203 // to detect gaps in the audio signal data being provided. Per the spec, RTP |
203 // timestamp values are allowed to overflow and roll around past zero. | 204 // timestamp values are allowed to overflow and roll around past zero. |
204 uint32 frame_rtp_timestamp_; | 205 uint32 frame_rtp_timestamp_; |
205 | 206 |
206 // The local system time associated with the start of the next frame of | 207 // The local system time associated with the start of the next frame of |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 cast_environment_->PostTask(CastEnvironment::AUDIO, | 402 cast_environment_->PostTask(CastEnvironment::AUDIO, |
402 FROM_HERE, | 403 FROM_HERE, |
403 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, | 404 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, |
404 impl_, | 405 impl_, |
405 base::Passed(&audio_bus), | 406 base::Passed(&audio_bus), |
406 recorded_time)); | 407 recorded_time)); |
407 } | 408 } |
408 | 409 |
409 } // namespace cast | 410 } // namespace cast |
410 } // namespace media | 411 } // namespace media |
OLD | NEW |