| 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 |