| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/sender/audio_encoder.h" | 5 #include "media/cast/sender/audio_encoder.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/sys_byteorder.h" | 15 #include "base/sys_byteorder.h" |
| 16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 17 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
| 18 #include "media/cast/common/rtp_time.h" |
| 19 #include "media/cast/constants.h" |
| 18 | 20 |
| 19 #if !defined(OS_IOS) | 21 #if !defined(OS_IOS) |
| 20 #include "third_party/opus/src/include/opus.h" | 22 #include "third_party/opus/src/include/opus.h" |
| 21 #endif | 23 #endif |
| 22 | 24 |
| 23 #if defined(OS_MACOSX) | 25 #if defined(OS_MACOSX) |
| 24 #include <AudioToolbox/AudioToolbox.h> | 26 #include <AudioToolbox/AudioToolbox.h> |
| 25 #endif | 27 #endif |
| 26 | 28 |
| 27 namespace media { | 29 namespace media { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 52 : cast_environment_(cast_environment), | 54 : cast_environment_(cast_environment), |
| 53 codec_(codec), | 55 codec_(codec), |
| 54 num_channels_(num_channels), | 56 num_channels_(num_channels), |
| 55 samples_per_frame_(samples_per_frame), | 57 samples_per_frame_(samples_per_frame), |
| 56 callback_(callback), | 58 callback_(callback), |
| 57 operational_status_(STATUS_UNINITIALIZED), | 59 operational_status_(STATUS_UNINITIALIZED), |
| 58 frame_duration_(base::TimeDelta::FromMicroseconds( | 60 frame_duration_(base::TimeDelta::FromMicroseconds( |
| 59 base::Time::kMicrosecondsPerSecond * samples_per_frame_ / | 61 base::Time::kMicrosecondsPerSecond * samples_per_frame_ / |
| 60 sampling_rate)), | 62 sampling_rate)), |
| 61 buffer_fill_end_(0), | 63 buffer_fill_end_(0), |
| 62 frame_id_(0), | 64 frame_id_(kFirstFrameId), |
| 63 frame_rtp_timestamp_(0), | |
| 64 samples_dropped_from_buffer_(0) { | 65 samples_dropped_from_buffer_(0) { |
| 65 // Support for max sampling rate of 48KHz, 2 channels, 100 ms duration. | 66 // Support for max sampling rate of 48KHz, 2 channels, 100 ms duration. |
| 66 const int kMaxSamplesTimesChannelsPerFrame = 48 * 2 * 100; | 67 const int kMaxSamplesTimesChannelsPerFrame = 48 * 2 * 100; |
| 67 if (num_channels_ <= 0 || samples_per_frame_ <= 0 || | 68 if (num_channels_ <= 0 || samples_per_frame_ <= 0 || |
| 68 frame_duration_ == base::TimeDelta() || | 69 frame_duration_ == base::TimeDelta() || |
| 69 samples_per_frame_ * num_channels_ > kMaxSamplesTimesChannelsPerFrame) { | 70 samples_per_frame_ * num_channels_ > kMaxSamplesTimesChannelsPerFrame) { |
| 70 operational_status_ = STATUS_INVALID_CONFIGURATION; | 71 operational_status_ = STATUS_INVALID_CONFIGURATION; |
| 71 } | 72 } |
| 72 } | 73 } |
| 73 | 74 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 96 buffer_fill_end_ * frame_duration_ / samples_per_frame_; | 97 buffer_fill_end_ * frame_duration_ / samples_per_frame_; |
| 97 if (!frame_capture_time_.is_null()) { | 98 if (!frame_capture_time_.is_null()) { |
| 98 const base::TimeDelta amount_ahead_by = | 99 const base::TimeDelta amount_ahead_by = |
| 99 recorded_time - (frame_capture_time_ + buffer_fill_duration); | 100 recorded_time - (frame_capture_time_ + buffer_fill_duration); |
| 100 const int64 num_frames_missed = amount_ahead_by / frame_duration_; | 101 const int64 num_frames_missed = amount_ahead_by / frame_duration_; |
| 101 if (num_frames_missed > kUnderrunSkipThreshold) { | 102 if (num_frames_missed > kUnderrunSkipThreshold) { |
| 102 samples_dropped_from_buffer_ += buffer_fill_end_; | 103 samples_dropped_from_buffer_ += buffer_fill_end_; |
| 103 buffer_fill_end_ = 0; | 104 buffer_fill_end_ = 0; |
| 104 buffer_fill_duration = base::TimeDelta(); | 105 buffer_fill_duration = base::TimeDelta(); |
| 105 frame_rtp_timestamp_ += | 106 frame_rtp_timestamp_ += |
| 106 static_cast<uint32>(num_frames_missed * samples_per_frame_); | 107 RtpTimeDelta::FromTicks(num_frames_missed * samples_per_frame_); |
| 107 DVLOG(1) << "Skipping RTP timestamp ahead to account for " | 108 DVLOG(1) << "Skipping RTP timestamp ahead to account for " |
| 108 << num_frames_missed * samples_per_frame_ | 109 << num_frames_missed * samples_per_frame_ |
| 109 << " samples' worth of underrun."; | 110 << " samples' worth of underrun."; |
| 110 TRACE_EVENT_INSTANT2("cast.stream", "Audio Skip", | 111 TRACE_EVENT_INSTANT2("cast.stream", "Audio Skip", |
| 111 TRACE_EVENT_SCOPE_THREAD, | 112 TRACE_EVENT_SCOPE_THREAD, |
| 112 "frames missed", num_frames_missed, | 113 "frames missed", num_frames_missed, |
| 113 "samples dropped", samples_dropped_from_buffer_); | 114 "samples dropped", samples_dropped_from_buffer_); |
| 114 } | 115 } |
| 115 } | 116 } |
| 116 frame_capture_time_ = recorded_time - buffer_fill_duration; | 117 frame_capture_time_ = recorded_time - buffer_fill_duration; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 135 break; | 136 break; |
| 136 | 137 |
| 137 scoped_ptr<SenderEncodedFrame> audio_frame( | 138 scoped_ptr<SenderEncodedFrame> audio_frame( |
| 138 new SenderEncodedFrame()); | 139 new SenderEncodedFrame()); |
| 139 audio_frame->dependency = EncodedFrame::KEY; | 140 audio_frame->dependency = EncodedFrame::KEY; |
| 140 audio_frame->frame_id = frame_id_; | 141 audio_frame->frame_id = frame_id_; |
| 141 audio_frame->referenced_frame_id = frame_id_; | 142 audio_frame->referenced_frame_id = frame_id_; |
| 142 audio_frame->rtp_timestamp = frame_rtp_timestamp_; | 143 audio_frame->rtp_timestamp = frame_rtp_timestamp_; |
| 143 audio_frame->reference_time = frame_capture_time_; | 144 audio_frame->reference_time = frame_capture_time_; |
| 144 | 145 |
| 145 TRACE_EVENT_ASYNC_BEGIN2("cast.stream", "Audio Encode", audio_frame.get(), | 146 TRACE_EVENT_ASYNC_BEGIN2( |
| 146 "frame_id", frame_id_, | 147 "cast.stream", |
| 147 "rtp_timestamp", frame_rtp_timestamp_); | 148 "Audio Encode", audio_frame.get(), |
| 149 "frame_id", frame_id_, |
| 150 "rtp_timestamp", frame_rtp_timestamp_.lower_32_bits()); |
| 148 if (EncodeFromFilledBuffer(&audio_frame->data)) { | 151 if (EncodeFromFilledBuffer(&audio_frame->data)) { |
| 149 // Compute deadline utilization as the real-world time elapsed divided | 152 // Compute deadline utilization as the real-world time elapsed divided |
| 150 // by the signal duration. | 153 // by the signal duration. |
| 151 audio_frame->deadline_utilization = | 154 audio_frame->deadline_utilization = |
| 152 (base::TimeTicks::Now() - start_time).InSecondsF() / | 155 (base::TimeTicks::Now() - start_time).InSecondsF() / |
| 153 frame_duration_.InSecondsF(); | 156 frame_duration_.InSecondsF(); |
| 154 | 157 |
| 155 TRACE_EVENT_ASYNC_END1("cast.stream", "Audio Encode", audio_frame.get(), | 158 TRACE_EVENT_ASYNC_END1("cast.stream", "Audio Encode", audio_frame.get(), |
| 156 "Deadline utilization", | 159 "Deadline utilization", |
| 157 audio_frame->deadline_utilization); | 160 audio_frame->deadline_utilization); |
| 158 | 161 |
| 159 audio_frame->encode_completion_time = | 162 audio_frame->encode_completion_time = |
| 160 cast_environment_->Clock()->NowTicks(); | 163 cast_environment_->Clock()->NowTicks(); |
| 161 cast_environment_->PostTask( | 164 cast_environment_->PostTask( |
| 162 CastEnvironment::MAIN, | 165 CastEnvironment::MAIN, |
| 163 FROM_HERE, | 166 FROM_HERE, |
| 164 base::Bind(callback_, | 167 base::Bind(callback_, |
| 165 base::Passed(&audio_frame), | 168 base::Passed(&audio_frame), |
| 166 samples_dropped_from_buffer_)); | 169 samples_dropped_from_buffer_)); |
| 167 samples_dropped_from_buffer_ = 0; | 170 samples_dropped_from_buffer_ = 0; |
| 168 } | 171 } |
| 169 | 172 |
| 170 // Reset the internal buffer, frame ID, and timestamps for the next frame. | 173 // Reset the internal buffer, frame ID, and timestamps for the next frame. |
| 171 buffer_fill_end_ = 0; | 174 buffer_fill_end_ = 0; |
| 172 ++frame_id_; | 175 ++frame_id_; |
| 173 frame_rtp_timestamp_ += samples_per_frame_; | 176 frame_rtp_timestamp_ += RtpTimeDelta::FromTicks(samples_per_frame_); |
| 174 frame_capture_time_ += frame_duration_; | 177 frame_capture_time_ += frame_duration_; |
| 175 } | 178 } |
| 176 } | 179 } |
| 177 | 180 |
| 178 protected: | 181 protected: |
| 179 friend class base::RefCountedThreadSafe<ImplBase>; | 182 friend class base::RefCountedThreadSafe<ImplBase>; |
| 180 virtual ~ImplBase() {} | 183 virtual ~ImplBase() {} |
| 181 | 184 |
| 182 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, | 185 virtual void TransferSamplesIntoBuffer(const AudioBus* audio_bus, |
| 183 int source_offset, | 186 int source_offset, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 203 // buffer, this points to the position at which to populate data in a later | 206 // buffer, this points to the position at which to populate data in a later |
| 204 // call. | 207 // call. |
| 205 int buffer_fill_end_; | 208 int buffer_fill_end_; |
| 206 | 209 |
| 207 // A counter used to label EncodedFrames. | 210 // A counter used to label EncodedFrames. |
| 208 uint32 frame_id_; | 211 uint32 frame_id_; |
| 209 | 212 |
| 210 // The RTP timestamp for the next frame of encoded audio. This is defined as | 213 // The RTP timestamp for the next frame of encoded audio. This is defined as |
| 211 // the number of audio samples encoded so far, plus the estimated number of | 214 // the number of audio samples encoded so far, plus the estimated number of |
| 212 // samples that were missed due to data underruns. A receiver uses this value | 215 // samples that were missed due to data underruns. A receiver uses this value |
| 213 // to detect gaps in the audio signal data being provided. Per the spec, RTP | 216 // to detect gaps in the audio signal data being provided. |
| 214 // timestamp values are allowed to overflow and roll around past zero. | 217 RtpTimeTicks frame_rtp_timestamp_; |
| 215 uint32 frame_rtp_timestamp_; | |
| 216 | 218 |
| 217 // The local system time associated with the start of the next frame of | 219 // The local system time associated with the start of the next frame of |
| 218 // encoded audio. This value is passed on to a receiver as a reference clock | 220 // encoded audio. This value is passed on to a receiver as a reference clock |
| 219 // timestamp for the purposes of synchronizing audio and video. Its | 221 // timestamp for the purposes of synchronizing audio and video. Its |
| 220 // progression is expected to drift relative to the elapsed time implied by | 222 // progression is expected to drift relative to the elapsed time implied by |
| 221 // the RTP timestamps. | 223 // the RTP timestamps. |
| 222 base::TimeTicks frame_capture_time_; | 224 base::TimeTicks frame_capture_time_; |
| 223 | 225 |
| 224 // Set to non-zero to indicate the next output frame skipped over audio | 226 // Set to non-zero to indicate the next output frame skipped over audio |
| 225 // samples in order to recover from an input underrun. | 227 // samples in order to recover from an input underrun. |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 cast_environment_->PostTask(CastEnvironment::AUDIO, | 869 cast_environment_->PostTask(CastEnvironment::AUDIO, |
| 868 FROM_HERE, | 870 FROM_HERE, |
| 869 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, | 871 base::Bind(&AudioEncoder::ImplBase::EncodeAudio, |
| 870 impl_, | 872 impl_, |
| 871 base::Passed(&audio_bus), | 873 base::Passed(&audio_bus), |
| 872 recorded_time)); | 874 recorded_time)); |
| 873 } | 875 } |
| 874 | 876 |
| 875 } // namespace cast | 877 } // namespace cast |
| 876 } // namespace media | 878 } // namespace media |
| OLD | NEW |