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

Side by Side Diff: content/renderer/media/webrtc/media_stream_remote_audio_track.cc

Issue 1514143003: Add support for unmixed audio from remote WebRTC remote tracks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix other include Created 5 years 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "content/renderer/media/webrtc/media_stream_remote_audio_track.h" 5 #include "content/renderer/media/webrtc/media_stream_remote_audio_track.h"
6 6
7 #include <list>
8
7 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "content/public/renderer/media_stream_audio_sink.h"
8 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" 11 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
9 12
10 namespace content { 13 namespace content {
11 14
15 class MediaStreamRemoteAudioTrack::AudioSink
16 : public webrtc::AudioTrackSinkInterface {
17 public:
18 AudioSink() {
19 }
20 ~AudioSink() override {
21 DCHECK(sinks_.empty());
22 }
23
24 void Add(MediaStreamAudioSink* sink) {
25 DCHECK(thread_checker_.CalledOnValidThread());
26 base::AutoLock lock(lock_);
27 sinks_.push_back(sink);
28 }
29
30 void Remove(MediaStreamAudioSink* sink) {
31 DCHECK(thread_checker_.CalledOnValidThread());
32 base::AutoLock lock(lock_);
33 sinks_.remove(sink);
34 }
35
36 bool IsNeeded() const {
37 DCHECK(thread_checker_.CalledOnValidThread());
38 return !sinks_.empty();
39 }
40
41 const media::AudioParameters GetOutputFormat() const {
42 base::AutoLock lock(lock_);
43 return params_;
44 }
45
46 private:
47 void OnData(const void* audio_data, int bits_per_sample, int sample_rate,
48 int number_of_channels, size_t number_of_frames) override {
49 if (!audio_bus_ || audio_bus_->channels() != number_of_channels ||
50 audio_bus_->frames() != static_cast<int>(number_of_frames)) {
51 audio_bus_ = media::AudioBus::Create(number_of_channels,
52 number_of_frames);
53 }
54
55 audio_bus_->FromInterleaved(audio_data, number_of_frames,
56 bits_per_sample / 8);
57
58 bool format_changed = false;
59 if (params_.format() != media::AudioParameters::AUDIO_PCM_LOW_LATENCY ||
60 params_.channels() != number_of_channels ||
61 params_.sample_rate() != sample_rate ||
62 params_.frames_per_buffer() != static_cast<int>(number_of_frames)) {
63 base::AutoLock lock(lock_); // Only lock on this thread when writing.
64 params_ = media::AudioParameters(
65 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
66 media::GuessChannelLayout(number_of_channels),
67 sample_rate, 16, number_of_frames);
68 format_changed = true;
69 }
70
71 // TODO(tommi): We should get the timestamp from WebRTC.
72 base::TimeTicks estimated_capture_time(base::TimeTicks::Now());
73
74 base::AutoLock lock(lock_);
75 for (auto* sink : sinks_) {
76 if (format_changed)
77 sink->OnSetFormat(params_);
78 sink->OnData(*audio_bus_.get(), estimated_capture_time);
79 }
80 }
81
82 mutable base::Lock lock_;
83 std::list<MediaStreamAudioSink*> sinks_;
84 base::ThreadChecker thread_checker_;
85 media::AudioParameters params_;
86 scoped_ptr<media::AudioBus> audio_bus_; // Only used on the callback thread.
87 };
88
12 MediaStreamRemoteAudioTrack::MediaStreamRemoteAudioTrack( 89 MediaStreamRemoteAudioTrack::MediaStreamRemoteAudioTrack(
13 const scoped_refptr<webrtc::AudioTrackInterface>& track) 90 const scoped_refptr<webrtc::AudioTrackInterface>& track)
14 : MediaStreamTrack(false), track_(track) { 91 : MediaStreamAudioTrack(false), track_(track) {
15 } 92 }
16 93
17 MediaStreamRemoteAudioTrack::~MediaStreamRemoteAudioTrack() { 94 MediaStreamRemoteAudioTrack::~MediaStreamRemoteAudioTrack() {
18 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 95 DCHECK(main_render_thread_checker_.CalledOnValidThread());
19 } 96 }
20 97
21 void MediaStreamRemoteAudioTrack::SetEnabled(bool enabled) { 98 void MediaStreamRemoteAudioTrack::SetEnabled(bool enabled) {
22 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 99 DCHECK(main_render_thread_checker_.CalledOnValidThread());
23 track_->set_enabled(enabled); 100 track_->set_enabled(enabled);
24 } 101 }
25 102
26 void MediaStreamRemoteAudioTrack::Stop() { 103 void MediaStreamRemoteAudioTrack::Stop() {
27 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 104 DCHECK(main_render_thread_checker_.CalledOnValidThread());
28 // Stop means that a track should be stopped permanently. But 105 // Stop means that a track should be stopped permanently. But
29 // since there is no proper way of doing that on a remote track, we can 106 // since there is no proper way of doing that on a remote track, we can
30 // at least disable the track. Blink will not call down to the content layer 107 // at least disable the track. Blink will not call down to the content layer
31 // after a track has been stopped. 108 // after a track has been stopped.
32 SetEnabled(false); 109 SetEnabled(false);
33 } 110 }
34 111
112 void MediaStreamRemoteAudioTrack::AddSink(MediaStreamAudioSink* sink) {
113 DCHECK(main_render_thread_checker_.CalledOnValidThread());
114
115 if (!sink_) {
116 sink_.reset(new AudioSink());
117 track_->AddSink(sink_.get());
118 }
119
120 sink_->Add(sink);
121 }
122
123 void MediaStreamRemoteAudioTrack::RemoveSink(MediaStreamAudioSink* sink) {
124 DCHECK(main_render_thread_checker_.CalledOnValidThread());
125
126 DCHECK(sink_);
127
128 sink_->Remove(sink);
129
130 if (!sink_->IsNeeded()) {
131 track_->RemoveSink(sink_.get());
132 sink_.reset();
133 }
134 }
135
136 media::AudioParameters MediaStreamRemoteAudioTrack::GetOutputFormat() const {
137 DCHECK(main_render_thread_checker_.CalledOnValidThread());
138 return sink_ ? sink_->GetOutputFormat() : media::AudioParameters();
139 }
140
35 webrtc::AudioTrackInterface* MediaStreamRemoteAudioTrack::GetAudioAdapter() { 141 webrtc::AudioTrackInterface* MediaStreamRemoteAudioTrack::GetAudioAdapter() {
36 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 142 DCHECK(main_render_thread_checker_.CalledOnValidThread());
37 return track_.get(); 143 return track_.get();
38 } 144 }
39 145
40 } // namespace content 146 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698