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

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: 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 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
29 class MediaStreamAudioInstance : public pp::Instance {
30 public:
31 explicit MediaStreamAudioInstance(PP_Instance instance)
32 : pp::Instance(instance),
33 callback_factory_(this),
34 sample_count_(0),
35 channel_count_(0),
36 samples_(NULL),
37 timer_interval_(0),
38 pending_paint_(false),
39 waiting_for_flush_completion_(false) {
40 }
41 virtual ~MediaStreamAudioInstance() {
42 delete[] samples_;
43 }
44
45 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
46 if (position.size() == size_)
47 return;
48
49 size_ = position.size();
50 device_context_ = pp::Graphics2D(this, size_, false);
51 if (!BindGraphics(device_context_))
52 return;
53
54 Paint();
55 }
56
57 virtual void HandleMessage(const pp::Var& var_message) {
58 if (!var_message.is_dictionary())
59 return;
60 pp::VarDictionary var_dictionary_message(var_message);
61 pp::Var var_track = var_dictionary_message.Get("track");
62 if (!var_track.is_resource())
63 return;
64
65 pp::Resource resource_track = pp::VarResource_Dev(var_track).AsResource();
66 audio_track_ = pp::MediaStreamAudioTrack(resource_track);
67 audio_track_.GetFrame(callback_factory_.NewCallbackWithOutput(
68 &MediaStreamAudioInstance::OnGetFrame));
69 }
70
71 private:
72 void ScheduleNextTimer() {
73 PP_DCHECK(timer_interval_ > 0);
74 pp::Module::Get()->core()->CallOnMainThread(
75 timer_interval_,
76 callback_factory_.NewCallback(&MediaStreamAudioInstance::OnTimer),
77 0);
78 }
79
80 void OnTimer(int32_t) {
81 ScheduleNextTimer();
82 Paint();
83 }
84
85 void DidFlush(int32_t result) {
86 waiting_for_flush_completion_ = false;
87 if (pending_paint_)
88 Paint();
89 }
90
91 void Paint() {
92 if (waiting_for_flush_completion_) {
93 pending_paint_ = true;
94 return;
95 }
96
97 pending_paint_ = false;
98
99 if (size_.IsEmpty())
100 return; // Nothing to do.
101
102 pp::ImageData image = PaintImage(size_);
103 if (!image.is_null()) {
104 device_context_.ReplaceContents(&image);
105 waiting_for_flush_completion_ = true;
106 device_context_.Flush(
107 callback_factory_.NewCallback(&MediaStreamAudioInstance::DidFlush));
108 }
109 }
110
111 pp::ImageData PaintImage(const pp::Size& size) {
112 pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
113 if (image.is_null())
114 return image;
115
116 // Clear to dark grey.
117 for (int y = 0; y < size.height(); y++) {
118 for (int x = 0; x < size.width(); x++)
119 *image.GetAddr32(pp::Point(x, y)) = 0xff202020;
bbudge 2014/01/31 22:13:01 It might be nice to define constants to indicate w
Peng 2014/02/02 02:11:26 Done.
120 }
121
122 int mid_height = size.height() / 2;
123 int max_amplitude = size.height() * 4 / 10;
124
125 // Draw some lines.
126 for (int x = 0; x < size.width(); x++) {
127 *image.GetAddr32(pp::Point(x, mid_height)) = 0xff606060;
128 *image.GetAddr32(pp::Point(x, mid_height + max_amplitude)) = 0xff404040;
129 *image.GetAddr32(pp::Point(x, mid_height - max_amplitude)) = 0xff404040;
130 }
131
132 // Draw our samples.
133 for (int x = 0, i = 0;
134 x < std::min(size.width(), static_cast<int>(sample_count_));
135 x++, i += channel_count_) {
bbudge 2014/01/31 22:13:01 Could we draw all the channels?
Peng 2014/02/02 02:11:26 Done.
136 int y = samples_[i] * max_amplitude /
137 (std::numeric_limits<int16_t>::max() + 1) + mid_height;
138 *image.GetAddr32(pp::Point(x, y)) = 0xffffffff;
139 }
140
141 return image;
142 }
143
144 // Callback that is invoked when new frames are recevied.
bbudge 2014/01/31 22:13:01 s/recevied/received
Peng 2014/02/02 02:11:26 Done.
145 void OnGetFrame(int32_t result, pp::AudioFrame frame) {
146 if (result != PP_OK)
147 return;
148 const char* data = static_cast<const char*>(frame.GetDataBuffer());
149
150 if (!samples_) {
151 channel_count_ = frame.GetNumberOfChannels();
152 sample_count_ = frame.GetNumberOfSamples() / channel_count_;
153 samples_ = new int16_t[sample_count_ * channel_count_];
154 timer_interval_ = (sample_count_ * 1000) / frame.GetSampleRate() + 5;
155 // Start the timer
156 ScheduleNextTimer();
157 }
158
159 memcpy(samples_, data, sample_count_ * channel_count_ * sizeof(int16_t));
160
161 audio_track_.RecycleFrame(frame);
162 audio_track_.GetFrame(callback_factory_.NewCallbackWithOutput(
163 &MediaStreamAudioInstance::OnGetFrame));
164
165 }
166
167 pp::MediaStreamAudioTrack audio_track_;
168 pp::CompletionCallbackFactory<MediaStreamAudioInstance> callback_factory_;
169
170 uint32_t sample_count_;
171 uint32_t channel_count_;
172 int16_t* samples_;
173
174 int32_t timer_interval_;
175
176 // Painting stuff.
177 pp::Size size_;
178 pp::Graphics2D device_context_;
179 bool pending_paint_;
180 bool waiting_for_flush_completion_;
181 };
182
183 class MediaStreamAudioModule : public pp::Module {
184 public:
185 virtual pp::Instance* CreateInstance(PP_Instance instance) {
186 return new MediaStreamAudioInstance(instance);
187 }
188 };
189
190 namespace pp {
191
192 // Factory function for your specialization of the Module object.
193 Module* CreateModule() {
194 return new MediaStreamAudioModule();
195 }
196
197 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698