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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ppapi/examples/media_stream_audio/media_stream_audio.cc
diff --git a/ppapi/examples/media_stream_audio/media_stream_audio.cc b/ppapi/examples/media_stream_audio/media_stream_audio.cc
new file mode 100644
index 0000000000000000000000000000000000000000..efc95569dc37b7e588d19edd3b2432d6af6b45c8
--- /dev/null
+++ b/ppapi/examples/media_stream_audio/media_stream_audio.cc
@@ -0,0 +1,223 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <limits>
+#include <vector>
+
+#include "ppapi/cpp/audio_frame.h"
+#include "ppapi/cpp/dev/var_resource_dev.h"
+#include "ppapi/cpp/graphics_2d.h"
+#include "ppapi/cpp/image_data.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/media_stream_audio_track.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+// When compiling natively on Windows, PostMessage can be #define-d to
+// something else.
+#ifdef PostMessage
+#undef PostMessage
+#endif
+
+// This example demonstrates receiving audio samples from an AndioMediaTrack
+// and visualizing them.
+
+namespace {
+
+const uint32_t kColorRed = 0xFFFF0000;
+const uint32_t kColorGreen = 0xFF00FF00;
+const uint32_t kColorGrey1 = 0xFF202020;
+const uint32_t kColorGrey2 = 0xFF404040;
+const uint32_t kColorGrey3 = 0xFF606060;
+
+class MediaStreamAudioInstance : public pp::Instance {
+ public:
+ explicit MediaStreamAudioInstance(PP_Instance instance)
+ : pp::Instance(instance),
+ callback_factory_(this),
+ sample_count_(0),
+ channel_count_(0),
+ timer_interval_(0),
+ pending_paint_(false),
+ waiting_for_flush_completion_(false) {
+ }
+
+ virtual ~MediaStreamAudioInstance() {
+ }
+
+ virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
+ if (position.size() == size_)
+ return;
+
+ size_ = position.size();
+ device_context_ = pp::Graphics2D(this, size_, false);
+ if (!BindGraphics(device_context_))
+ return;
+
+ Paint();
+ }
+
+ virtual void HandleMessage(const pp::Var& var_message) {
+ if (!var_message.is_dictionary())
+ return;
+ pp::VarDictionary var_dictionary_message(var_message);
+ pp::Var var_track = var_dictionary_message.Get("track");
+ if (!var_track.is_resource())
+ return;
+
+ pp::Resource resource_track = pp::VarResource_Dev(var_track).AsResource();
+ audio_track_ = pp::MediaStreamAudioTrack(resource_track);
+ audio_track_.GetFrame(callback_factory_.NewCallbackWithOutput(
+ &MediaStreamAudioInstance::OnGetFrame));
+ }
+
+ private:
+ void ScheduleNextTimer() {
+ PP_DCHECK(timer_interval_ > 0);
+ pp::Module::Get()->core()->CallOnMainThread(
+ timer_interval_,
+ callback_factory_.NewCallback(&MediaStreamAudioInstance::OnTimer),
+ 0);
+ }
+
+ void OnTimer(int32_t) {
+ ScheduleNextTimer();
+ Paint();
+ }
+
+ void DidFlush(int32_t result) {
+ waiting_for_flush_completion_ = false;
+ if (pending_paint_)
+ Paint();
+ }
+
+ void Paint() {
+ if (waiting_for_flush_completion_) {
+ pending_paint_ = true;
+ return;
+ }
+
+ pending_paint_ = false;
+
+ if (size_.IsEmpty())
+ return; // Nothing to do.
+
+ pp::ImageData image = PaintImage(size_);
+ if (!image.is_null()) {
+ device_context_.ReplaceContents(&image);
+ waiting_for_flush_completion_ = true;
+ device_context_.Flush(
+ callback_factory_.NewCallback(&MediaStreamAudioInstance::DidFlush));
+ }
+ }
+
+ pp::ImageData PaintImage(const pp::Size& size) {
+ pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
+ if (image.is_null())
+ return image;
+
+ // Clear to dark grey.
+ for (int y = 0; y < size.height(); y++) {
+ for (int x = 0; x < size.width(); x++)
+ *image.GetAddr32(pp::Point(x, y)) = kColorGrey1;
+ }
+
+ int mid_height = size.height() / 2;
+ int max_amplitude = size.height() * 4 / 10;
+
+ // Draw some lines.
+ for (int x = 0; x < size.width(); x++) {
+ *image.GetAddr32(pp::Point(x, mid_height)) = kColorGrey3;
+ *image.GetAddr32(pp::Point(x, mid_height + max_amplitude)) = kColorGrey2;
+ *image.GetAddr32(pp::Point(x, mid_height - max_amplitude)) = kColorGrey2;
+ }
+
+
+ // Draw our samples.
+ for (int x = 0, i = 0;
+ x < std::min(size.width(), static_cast<int>(sample_count_));
+ x++, i += channel_count_) {
+ for (uint32_t ch = 0; ch < std::min(channel_count_, 2U); ++ch) {
+ int y = samples_[i + ch] * max_amplitude /
+ (std::numeric_limits<int16_t>::max() + 1) + mid_height;
+ *image.GetAddr32(pp::Point(x, y)) = (ch == 0 ? kColorRed : kColorGreen);
+ }
+ }
+
+ return image;
+ }
+
+ // Callback that is invoked when new frames are received.
+ void OnGetFrame(int32_t result, pp::AudioFrame frame) {
+ if (result != PP_OK)
+ return;
+
+ PP_DCHECK(frame.GetSampleSize() == PP_AUDIOFRAME_SAMPLESIZE_16_BITS);
+ const char* data = static_cast<const char*>(frame.GetDataBuffer());
+ uint32_t channels = frame.GetNumberOfChannels();
+ uint32_t samples = frame.GetNumberOfSamples() / channels;
+
+ 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
+ channel_count_ = channels;
+ sample_count_ = samples;
+
+ samples_.resize(sample_count_ * channel_count_);
+ // Start the timer for the first frame.
+ if (!timer_interval_) {
+ 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.
+ ScheduleNextTimer();
+ } else {
+ timer_interval_ = (sample_count_ * 1000) / frame.GetSampleRate() + 5;
+ }
+ }
+
+ memcpy(samples_.data(), data,
+ sample_count_ * channel_count_ * sizeof(int16_t));
+
+ audio_track_.RecycleFrame(frame);
+ audio_track_.GetFrame(callback_factory_.NewCallbackWithOutput(
+ &MediaStreamAudioInstance::OnGetFrame));
+
+ }
+
+ pp::MediaStreamAudioTrack audio_track_;
+ pp::CompletionCallbackFactory<MediaStreamAudioInstance> callback_factory_;
+
+ uint32_t sample_count_;
+ uint32_t channel_count_;
+ std::vector<int16_t> samples_;
+
+ int32_t timer_interval_;
+
+ // Painting stuff.
+ pp::Size size_;
+ pp::Graphics2D device_context_;
+ bool pending_paint_;
+ bool waiting_for_flush_completion_;
+};
+
+class MediaStreamAudioModule : public pp::Module {
+ public:
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new MediaStreamAudioInstance(instance);
+ }
+};
+
+} // namespace
+
+namespace pp {
+
+// Factory function for your specialization of the Module object.
+Module* CreateModule() {
+ return new MediaStreamAudioModule();
+}
+
+} // namespace pp
« 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