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

Side by Side Diff: ppapi/examples/media_stream_audio/media_stream_audio.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: Update 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
« no previous file with comments | « ppapi/cpp/audio_frame.cc ('k') | ppapi/examples/media_stream_audio/media_stream_audio.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <algorithm>
9 #include <limits>
10 #include <vector>
11
12 #include "ppapi/cpp/audio_frame.h"
13 #include "ppapi/cpp/dev/var_resource_dev.h"
14 #include "ppapi/cpp/graphics_2d.h"
15 #include "ppapi/cpp/image_data.h"
16 #include "ppapi/cpp/instance.h"
17 #include "ppapi/cpp/logging.h"
18 #include "ppapi/cpp/media_stream_audio_track.h"
19 #include "ppapi/cpp/module.h"
20 #include "ppapi/cpp/rect.h"
21 #include "ppapi/cpp/size.h"
22 #include "ppapi/utility/completion_callback_factory.h"
23
24 // When compiling natively on Windows, PostMessage can be #define-d to
25 // something else.
26 #ifdef PostMessage
27 #undef PostMessage
28 #endif
29
30 // This example demonstrates receiving audio samples from an AndioMediaTrack
31 // and visualizing them.
32
33 namespace {
34
35 const uint32_t kColorRed = 0xFFFF0000;
36 const uint32_t kColorGreen = 0xFF00FF00;
37 const uint32_t kColorGrey1 = 0xFF202020;
38 const uint32_t kColorGrey2 = 0xFF404040;
39 const uint32_t kColorGrey3 = 0xFF606060;
40
41 class MediaStreamAudioInstance : public pp::Instance {
42 public:
43 explicit MediaStreamAudioInstance(PP_Instance instance)
44 : pp::Instance(instance),
45 callback_factory_(this),
46 sample_count_(0),
47 channel_count_(0),
48 timer_interval_(0),
49 pending_paint_(false),
50 waiting_for_flush_completion_(false) {
51 }
52
53 virtual ~MediaStreamAudioInstance() {
54 }
55
56 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
57 if (position.size() == size_)
58 return;
59
60 size_ = position.size();
61 device_context_ = pp::Graphics2D(this, size_, false);
62 if (!BindGraphics(device_context_))
63 return;
64
65 Paint();
66 }
67
68 virtual void HandleMessage(const pp::Var& var_message) {
69 if (!var_message.is_dictionary())
70 return;
71 pp::VarDictionary var_dictionary_message(var_message);
72 pp::Var var_track = var_dictionary_message.Get("track");
73 if (!var_track.is_resource())
74 return;
75
76 pp::Resource resource_track = pp::VarResource_Dev(var_track).AsResource();
77 audio_track_ = pp::MediaStreamAudioTrack(resource_track);
78 audio_track_.GetFrame(callback_factory_.NewCallbackWithOutput(
79 &MediaStreamAudioInstance::OnGetFrame));
80 }
81
82 private:
83 void ScheduleNextTimer() {
84 PP_DCHECK(timer_interval_ > 0);
85 pp::Module::Get()->core()->CallOnMainThread(
86 timer_interval_,
87 callback_factory_.NewCallback(&MediaStreamAudioInstance::OnTimer),
88 0);
89 }
90
91 void OnTimer(int32_t) {
92 ScheduleNextTimer();
93 Paint();
94 }
95
96 void DidFlush(int32_t result) {
97 waiting_for_flush_completion_ = false;
98 if (pending_paint_)
99 Paint();
100 }
101
102 void Paint() {
103 if (waiting_for_flush_completion_) {
104 pending_paint_ = true;
105 return;
106 }
107
108 pending_paint_ = false;
109
110 if (size_.IsEmpty())
111 return; // Nothing to do.
112
113 pp::ImageData image = PaintImage(size_);
114 if (!image.is_null()) {
115 device_context_.ReplaceContents(&image);
116 waiting_for_flush_completion_ = true;
117 device_context_.Flush(
118 callback_factory_.NewCallback(&MediaStreamAudioInstance::DidFlush));
119 }
120 }
121
122 pp::ImageData PaintImage(const pp::Size& size) {
123 pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
124 if (image.is_null())
125 return image;
126
127 // Clear to dark grey.
128 for (int y = 0; y < size.height(); y++) {
129 for (int x = 0; x < size.width(); x++)
130 *image.GetAddr32(pp::Point(x, y)) = kColorGrey1;
131 }
132
133 int mid_height = size.height() / 2;
134 int max_amplitude = size.height() * 4 / 10;
135
136 // Draw some lines.
137 for (int x = 0; x < size.width(); x++) {
138 *image.GetAddr32(pp::Point(x, mid_height)) = kColorGrey3;
139 *image.GetAddr32(pp::Point(x, mid_height + max_amplitude)) = kColorGrey2;
140 *image.GetAddr32(pp::Point(x, mid_height - max_amplitude)) = kColorGrey2;
141 }
142
143
144 // Draw our samples.
145 for (int x = 0, i = 0;
146 x < std::min(size.width(), static_cast<int>(sample_count_));
147 x++, i += channel_count_) {
148 for (uint32_t ch = 0; ch < std::min(channel_count_, 2U); ++ch) {
149 int y = samples_[i + ch] * max_amplitude /
150 (std::numeric_limits<int16_t>::max() + 1) + mid_height;
151 *image.GetAddr32(pp::Point(x, y)) = (ch == 0 ? kColorRed : kColorGreen);
152 }
153 }
154
155 return image;
156 }
157
158 // Callback that is invoked when new frames are received.
159 void OnGetFrame(int32_t result, pp::AudioFrame frame) {
160 if (result != PP_OK)
161 return;
162
163 PP_DCHECK(frame.GetSampleSize() == PP_AUDIOFRAME_SAMPLESIZE_16_BITS);
164 const char* data = static_cast<const char*>(frame.GetDataBuffer());
165 uint32_t channels = frame.GetNumberOfChannels();
166 uint32_t samples = frame.GetNumberOfSamples() / channels;
167
168 if (channel_count_ == channels || sample_count_ != samples) {
yzshen1 2014/02/04 20:19:59 is it channel_count_ != channel?
Peng 2014/02/04 20:33:41 Oops! Done
169 channel_count_ = channels;
170 sample_count_ = samples;
171
172 samples_.resize(sample_count_ * channel_count_);
173 // Start the timer for the first frame.
174 if (!timer_interval_) {
175 timer_interval_ = (sample_count_ * 1000) / frame.GetSampleRate() + 5;
yzshen1 2014/02/04 20:19:59 It seems better to move this line out of if(), and
Peng 2014/02/04 20:33:41 Done.
176 ScheduleNextTimer();
177 } else {
178 timer_interval_ = (sample_count_ * 1000) / frame.GetSampleRate() + 5;
179 }
180 }
181
182 memcpy(samples_.data(), data,
183 sample_count_ * channel_count_ * sizeof(int16_t));
184
185 audio_track_.RecycleFrame(frame);
186 audio_track_.GetFrame(callback_factory_.NewCallbackWithOutput(
187 &MediaStreamAudioInstance::OnGetFrame));
188
189 }
190
191 pp::MediaStreamAudioTrack audio_track_;
192 pp::CompletionCallbackFactory<MediaStreamAudioInstance> callback_factory_;
193
194 uint32_t sample_count_;
195 uint32_t channel_count_;
196 std::vector<int16_t> samples_;
197
198 int32_t timer_interval_;
199
200 // Painting stuff.
201 pp::Size size_;
202 pp::Graphics2D device_context_;
203 bool pending_paint_;
204 bool waiting_for_flush_completion_;
205 };
206
207 class MediaStreamAudioModule : public pp::Module {
208 public:
209 virtual pp::Instance* CreateInstance(PP_Instance instance) {
210 return new MediaStreamAudioInstance(instance);
211 }
212 };
213
214 } // namespace
215
216 namespace pp {
217
218 // Factory function for your specialization of the Module object.
219 Module* CreateModule() {
220 return new MediaStreamAudioModule();
221 }
222
223 } // namespace pp
OLDNEW
« no previous file with comments | « ppapi/cpp/audio_frame.cc ('k') | ppapi/examples/media_stream_audio/media_stream_audio.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698