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

Side by Side Diff: content/renderer/pepper/pepper_media_stream_audio_track_host.cc

Issue 140783004: [PPAPI] Pepper MediaStream API audio track implementation and example. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix review issues Created 6 years, 10 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 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/pepper/pepper_media_stream_audio_track_host.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/macros.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/ppb_audio_frame.h"
14 #include "ppapi/shared_impl/media_stream_frame.h"
15
16 using media::AudioParameters;
17
18 namespace {
19
20 // Max audio buffer duration in milliseconds.
21 const uint32_t kMaxDuration = 10;
22
23 // TODO(penghuang): make this configurable.
24 const int32_t kNumberOfFrames = 4;
25
26 } // namespace
27
28 namespace content {
29
30 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink(
31 PepperMediaStreamAudioTrackHost* host)
32 : host_(host),
33 frame_data_size_(0),
34 main_message_loop_proxy_(base::MessageLoopProxy::current()),
35 weak_factory_(this) {
36 }
37
38 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() {
39 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
40 }
41
42 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueFrame(int32_t index) {
43 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
44 DCHECK_GE(index, 0);
45 DCHECK_LT(index, host_->frame_buffer()->number_of_frames());
46 base::AutoLock lock(lock_);
47 frames_.push_back(index);
48 }
49
50 void PepperMediaStreamAudioTrackHost::AudioSink::InitFramesOnMainThread(
51 int32_t number_of_frames, int32_t frame_size) {
52 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
53 bool result = host_->InitFrames(number_of_frames, frame_size);
54 // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin.
55 CHECK(result);
56 base::AutoLock lock(lock_);
57 for (int32_t i = 0; i < number_of_frames; ++i) {
58 int32_t index = host_->frame_buffer()->DequeueFrame();
59 DCHECK_GE(index, 0);
60 frames_.push_back(index);
61 }
62 }
63
64 void
65 PepperMediaStreamAudioTrackHost::AudioSink::SendEnqueueFrameMessageOnMainThread(
66 int32_t index) {
67 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
68 host_->SendEnqueueFrameMessageToPlugin(index);
69 }
70
71 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data,
72 int sample_rate,
73 int number_of_channels,
74 int number_of_frames) {
75 DCHECK(audio_thread_checker_.CalledOnValidThread());
76 DCHECK(audio_data);
77 DCHECK_EQ(sample_rate, audio_params_.sample_rate());
78 DCHECK_EQ(number_of_channels, audio_params_.channels());
79 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer());
80 int32_t index = -1;
81 {
82 base::AutoLock lock(lock_);
83 if (!frames_.empty()) {
84 index = frames_.front();
85 frames_.pop_front();
86 }
87 }
88
89 if (index != -1) {
90 // TODO(penghuang): support re-sampling, etc.
91 ppapi::MediaStreamFrame::Audio* frame =
92 &(host_->frame_buffer()->GetFramePointer(index)->audio);
93 frame->header.size = host_->frame_buffer()->frame_size();
94 frame->header.type = ppapi::MediaStreamFrame::TYPE_AUDIO;
95 frame->timestamp = timestamp_.InMillisecondsF();
96 frame->sample_rate = static_cast<PP_AudioFrame_SampleRate>(sample_rate);
97 frame->number_of_channels = number_of_channels;
98 frame->number_of_samples = number_of_channels * number_of_frames;
99 frame->data_size = frame_data_size_;
100 memcpy(frame->data, audio_data, frame_data_size_);
101
102 main_message_loop_proxy_->PostTask(
103 FROM_HERE,
104 base::Bind(&AudioSink::SendEnqueueFrameMessageOnMainThread,
105 weak_factory_.GetWeakPtr(), index));
106 }
107 timestamp_ += frame_duration_;
108 }
109
110 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
111 const AudioParameters& params) {
112 DCHECK(params.IsValid());
113 DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration);
114 DCHECK_EQ(params.bits_per_sample(), 16);
115 DCHECK((params.sample_rate() == AudioParameters::kTelephoneSampleRate) ||
116 (params.sample_rate() == AudioParameters::kAudioCDSampleRate));
117
118 COMPILE_ASSERT(AudioParameters::kTelephoneSampleRate ==
119 static_cast<int32_t>(PP_AUDIOFRAME_SAMPLERATE_8000),
120 audio_sample_rate_does_not_match);
121 COMPILE_ASSERT(AudioParameters::kAudioCDSampleRate ==
122 static_cast<int32_t>(PP_AUDIOFRAME_SAMPLERATE_44100),
123 audio_sample_rate_does_not_match);
124 audio_params_ = params;
125
126 // TODO(penghuang): support setting format more than once.
127 frame_duration_ = params.GetBufferDuration();
128 frame_data_size_ = params.GetBytesPerBuffer();
129
130 if (original_audio_params_.IsValid()) {
131 DCHECK_EQ(params.sample_rate(), original_audio_params_.sample_rate());
132 DCHECK_EQ(params.bits_per_sample(),
133 original_audio_params_.bits_per_sample());
134 DCHECK_EQ(params.channels(), original_audio_params_.channels());
135 } else {
136 audio_thread_checker_.DetachFromThread();
137 original_audio_params_ = params;
138 // The size is slightly bigger than necessary, because 8 extra bytes are
139 // added into the struct. Also see |MediaStreamFrame|.
140 size_t max_frame_size =
141 params.sample_rate() * params.bits_per_sample() / 8 *
142 params.channels() * kMaxDuration / 1000;
143 size_t size = sizeof(ppapi::MediaStreamFrame::Audio) + max_frame_size;
144
145 main_message_loop_proxy_->PostTask(
146 FROM_HERE,
147 base::Bind(&AudioSink::InitFramesOnMainThread,
148 weak_factory_.GetWeakPtr(),
149 kNumberOfFrames,
150 static_cast<int32_t>(size)));
151 }
152 }
153
154 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost(
155 RendererPpapiHost* host,
156 PP_Instance instance,
157 PP_Resource resource,
158 const blink::WebMediaStreamTrack& track)
159 : PepperMediaStreamTrackHostBase(host, instance, resource),
160 track_(track),
161 connected_(false),
162 audio_sink_(this) {
163 DCHECK(!track_.isNull());
164 }
165
166 PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() {
167 OnClose();
168 }
169
170 void PepperMediaStreamAudioTrackHost::OnClose() {
171 if (connected_) {
172 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_);
173 connected_ = false;
174 }
175 }
176
177 void PepperMediaStreamAudioTrackHost::OnNewFrameEnqueued() {
178 int32_t index = frame_buffer()->DequeueFrame();
179 DCHECK_GE(index, 0);
180 audio_sink_.EnqueueFrame(index);
181 }
182
183 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() {
184 if (!connected_) {
185 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_);
186 connected_ = true;
187 }
188 }
189
190 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698