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

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 // TODO(penghuang): make this configurable.
21 const int32_t kNumberOfFrames = 4;
22
23 } // namespace
24
25 namespace content {
26
27 PepperMediaStreamAudioTrackHost::AudioSink::AudioSink(
28 PepperMediaStreamAudioTrackHost* host)
29 : host_(host),
30 frame_data_size_(0),
31 main_message_loop_proxy_(base::MessageLoopProxy::current()) {
32 }
33
34 PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() {
35 DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
36 }
37
38 void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueFrame(int32_t index) {
no longer working on chromium 2014/02/01 21:28:09 The thread model is very complicated in this class
Peng 2014/02/02 02:11:26 Done.
39 DCHECK_GE(index, 0);
40 DCHECK_LT(index, host_->frame_buffer()->number_of_frames());
41 base::AutoLock lock(mutex_);
42 frames_.push_back(index);
43 }
44
45 void PepperMediaStreamAudioTrackHost::AudioSink::InitFramesOnMainThread(
46 uint32_t number_of_frames, uint32_t frame_size) {
bbudge 2014/01/31 22:13:01 DCHECK_EQ(main_message_loop_proxy_, base::MessageL
no longer working on chromium 2014/02/01 21:28:09 The number_of_frames here and number_of_frames in
Peng 2014/02/02 02:11:26 Done.
Peng 2014/02/02 02:11:26 Because the base class is used for both Audio and
no longer working on chromium 2014/02/03 09:50:44 sgtm.
no longer working on chromium 2014/02/03 09:50:44 Curiously, does the overall pepper code prefer int
Peng 2014/02/03 14:38:54 I think so. I did not find size_t in ppapi/api.
47 bool result = host_->InitFrames(number_of_frames, frame_size);
48 DCHECK(result);
49 base::AutoLock lock(mutex_);
50 for (uint32_t i = 0; i < number_of_frames; ++i) {
51 int32_t index = host_->frame_buffer()->DequeueFrame();
52 DCHECK_GE(index, 0);
53 frames_.push_back(index);
54 }
55 }
56
57 void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data,
58 int sample_rate,
59 int number_of_channels,
60 int number_of_frames) {
61 DCHECK(audio_data);
62 DCHECK_EQ(sample_rate, audio_params_.sample_rate());
63 DCHECK_EQ(number_of_channels, audio_params_.channels());
64 DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer());
65 int32_t index = -1;
66 {
67 base::AutoLock lock(mutex_);
68 if (!frames_.empty()) {
69 index = frames_.front();
70 frames_.pop_front();
71 }
72 }
73
74 if (index != -1) {
75 // TODO(penghuang): support re-sampling, etc.
76 ppapi::MediaStreamFrame::Audio* frame =
no longer working on chromium 2014/02/01 21:28:09 in OnSetFormat() you post a task InitFramesOnMainT
Peng 2014/02/02 02:11:26 I remember you told me the OnSetFormat will only b
no longer working on chromium 2014/02/03 09:50:44 No, today this can be called more than once. Every
Peng 2014/02/03 14:38:54 That is a bad news. Could you give me some real ca
no longer working on chromium 2014/02/03 20:23:59 Each time if a WebRtcAudioCapturer::SetCapturerSou
77 &(host_->frame_buffer()->GetFramePointer(index)->audio);
78 frame->header.size = host_->frame_buffer()->frame_size();
79 frame->header.type = ppapi::MediaStreamFrame::TYPE_AUDIO;
80 frame->timestamp = timestamp_.InMillisecondsF();
81 frame->sample_rate = static_cast<PP_AudioFrame_SampleRate>(sample_rate);
82 frame->number_of_channels = number_of_channels;
83 frame->number_of_samples = number_of_channels * number_of_frames;
84 frame->data_size = frame_data_size_;
85 memcpy(frame->data, audio_data, frame_data_size_);
86
87 // This function is called from the audio thread, but
88 // |SendEnqueueFrameMessageToPlugin()| doesn't use any sync IPC,
89 // so it is safe to call it from the audio thread directly.
90 host_->SendEnqueueFrameMessageToPlugin(index);
91 }
92 timestamp_ += frame_duration_;
no longer working on chromium 2014/02/01 21:28:09 nit, you don't need this frame_duration_ member, f
Peng 2014/02/02 02:11:26 I think we need calculate duration from the number
no longer working on chromium 2014/02/03 09:50:44 OK, it is fine to use the member then.
93 }
94
95 void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
96 const AudioParameters& params) {
97 DCHECK(!audio_params_.IsValid());
98 DCHECK(params.IsValid());
99 DCHECK_EQ(params.bits_per_sample(), 16);
100 DCHECK((params.sample_rate() == AudioParameters::kTelephoneSampleRate) ||
101 (params.sample_rate() == AudioParameters::kAudioCDSampleRate));
102
103 COMPILE_ASSERT(AudioParameters::kTelephoneSampleRate == 8000,
104 audio_sample_rate_does_not_match);
105 COMPILE_ASSERT(AudioParameters::kAudioCDSampleRate == 44100,
106 audio_sample_rate_does_not_match);
107
108 // TODO(penghuang): support setting format more than once.
109 audio_params_ = params;
110 frame_duration_ = audio_params_.GetBufferDuration();
111 frame_data_size_ = audio_params_.GetBytesPerBuffer();
112
113 // The size is slightly bigger than necessary, because 8 extra bytes are added
114 // into the struct. Also see |MediaStreamFrame|.
115 int32_t size = sizeof(ppapi::MediaStreamFrame::Audio) + frame_data_size_;
bbudge 2014/01/31 22:13:01 since sizeof is a size_t, this may not compile on
Peng 2014/02/02 02:11:26 Done.
116
117 // This function is called from the audio thread and |InitFrames()| uses some
118 // sync IPC. So we have to call |InitFrames()| from the main thread.
no longer working on chromium 2014/02/01 21:28:09 I think you need some synchronization between OnSe
Peng 2014/02/02 02:11:26 I assume this function will be only called once. A
119 main_message_loop_proxy_->PostTask(
120 FROM_HERE,
121 base::Bind(&AudioSink::InitFramesOnMainThread,
122 AsWeakPtr(), kNumberOfFrames, size));
123 }
124
125 PepperMediaStreamAudioTrackHost::PepperMediaStreamAudioTrackHost(
126 RendererPpapiHost* host,
127 PP_Instance instance,
128 PP_Resource resource,
129 const blink::WebMediaStreamTrack& track)
130 : PepperMediaStreamTrackHostBase(host, instance, resource),
131 track_(track),
132 connected_(false),
133 audio_sink_(this) {
134 DCHECK(!track_.isNull());
135 }
136
137 PepperMediaStreamAudioTrackHost::~PepperMediaStreamAudioTrackHost() {
138 OnClose();
139 }
140
141 void PepperMediaStreamAudioTrackHost::OnClose() {
142 if (connected_) {
143 MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_);
144 connected_ = false;
145 }
146 }
147
148 void PepperMediaStreamAudioTrackHost::OnNewFrameEnqueued() {
149 int32_t index = frame_buffer()->DequeueFrame();
150 DCHECK_GE(index, 0);
151 audio_sink_.EnqueueFrame(index);
152 }
153
154 void PepperMediaStreamAudioTrackHost::DidConnectPendingHostToResource() {
155 if (!connected_) {
156 MediaStreamAudioSink::AddToAudioTrack(&audio_sink_, track_);
157 connected_ = true;
158 }
159 }
160
161 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698