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

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

Powered by Google App Engine
This is Rietveld 408576698