Chromium Code Reviews| Index: ppapi/examples/media_stream_video/media_stream_video.cc |
| diff --git a/ppapi/examples/video_capture/video_capture.cc b/ppapi/examples/media_stream_video/media_stream_video.cc |
| similarity index 56% |
| copy from ppapi/examples/video_capture/video_capture.cc |
| copy to ppapi/examples/media_stream_video/media_stream_video.cc |
| index b95fcace928b9ee31fffedc2ab75e9c73d4d4be6..ac256e949141bb9cd4300e8f4232a4c0df3fd016 100644 |
| --- a/ppapi/examples/video_capture/video_capture.cc |
| +++ b/ppapi/examples/media_stream_video/media_stream_video.cc |
| @@ -1,27 +1,19 @@ |
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Copyright (c) 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 <map> |
| -#include <vector> |
| - |
| -#include "ppapi/c/dev/ppb_video_capture_dev.h" |
| #include "ppapi/c/pp_errors.h" |
| #include "ppapi/c/ppb_opengles2.h" |
| -#include "ppapi/cpp/dev/buffer_dev.h" |
| -#include "ppapi/cpp/dev/device_ref_dev.h" |
| -#include "ppapi/cpp/dev/video_capture_dev.h" |
| -#include "ppapi/cpp/dev/video_capture_client_dev.h" |
| #include "ppapi/cpp/completion_callback.h" |
| -#include "ppapi/cpp/graphics_3d_client.h" |
| +#include "ppapi/cpp/dev/var_resource_dev.h" |
| #include "ppapi/cpp/graphics_3d.h" |
| +#include "ppapi/cpp/graphics_3d_client.h" |
| #include "ppapi/cpp/instance.h" |
| +#include "ppapi/cpp/media_stream_video_track.h" |
| #include "ppapi/cpp/module.h" |
| #include "ppapi/cpp/rect.h" |
| #include "ppapi/cpp/var.h" |
| +#include "ppapi/cpp/video_frame.h" |
| #include "ppapi/lib/gl/include/GLES2/gl2.h" |
| #include "ppapi/utility/completion_callback_factory.h" |
| @@ -38,24 +30,21 @@ |
| namespace { |
| -const char* const kDelimiter = "#__#"; |
| - |
| // This object is the global object representing this plugin library as long |
| // as it is loaded. |
| -class VCDemoModule : public pp::Module { |
| +class MSVDemoModule : public pp::Module { |
| public: |
| - VCDemoModule() : pp::Module() {} |
| - virtual ~VCDemoModule() {} |
| + MSVDemoModule() : pp::Module() {} |
| + virtual ~MSVDemoModule() {} |
| virtual pp::Instance* CreateInstance(PP_Instance instance); |
| }; |
| -class VCDemoInstance : public pp::Instance, |
| - public pp::Graphics3DClient, |
| - public pp::VideoCaptureClient_Dev { |
| +class MSVDemoInstance : public pp::Instance, |
| + public pp::Graphics3DClient { |
| public: |
| - VCDemoInstance(PP_Instance instance, pp::Module* module); |
| - virtual ~VCDemoInstance(); |
| + MSVDemoInstance(PP_Instance instance, pp::Module* module); |
| + virtual ~MSVDemoInstance(); |
| // pp::Instance implementation (see PPP_Instance). |
| virtual void DidChangeView(const pp::Rect& position, |
| @@ -69,51 +58,6 @@ class VCDemoInstance : public pp::Instance, |
| Render(); |
| } |
| - virtual void OnDeviceInfo(PP_Resource resource, |
| - const PP_VideoCaptureDeviceInfo_Dev& info, |
| - const std::vector<pp::Buffer_Dev>& buffers) { |
| - capture_info_ = info; |
| - buffers_ = buffers; |
| - CreateYUVTextures(); |
| - } |
| - |
| - virtual void OnStatus(PP_Resource resource, uint32_t status) { |
| - } |
| - |
| - virtual void OnError(PP_Resource resource, uint32_t error) { |
| - } |
| - |
| - virtual void OnBufferReady(PP_Resource resource, uint32_t buffer) { |
| - const char* data = static_cast<const char*>(buffers_[buffer].data()); |
| - int32_t width = capture_info_.width; |
| - int32_t height = capture_info_.height; |
| - gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); |
| - gles2_if_->TexSubImage2D( |
| - context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| - |
| - data += width * height; |
| - width /= 2; |
| - height /= 2; |
| - |
| - gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1); |
| - gles2_if_->TexSubImage2D( |
| - context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| - |
| - data += width * height; |
| - gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2); |
| - gles2_if_->TexSubImage2D( |
| - context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| - |
| - video_capture_.ReuseBuffer(buffer); |
| - if (is_painting_) |
| - needs_paint_ = true; |
| - else |
| - Render(); |
| - } |
| - |
| private: |
| void Render(); |
| @@ -124,17 +68,7 @@ class VCDemoInstance : public pp::Instance, |
| void CreateShader(GLuint program, GLenum type, const char* source, int size); |
| void PaintFinished(int32_t result); |
| void CreateYUVTextures(); |
| - |
| - void Open(const pp::DeviceRef_Dev& device); |
| - void Stop(); |
| - void Start(); |
| - void EnumerateDevicesFinished(int32_t result, |
| - std::vector<pp::DeviceRef_Dev>& devices); |
| - void OpenFinished(int32_t result); |
| - |
| - static void MonitorDeviceChangeCallback(void* user_data, |
| - uint32_t device_count, |
| - const PP_Resource devices[]); |
| + void OnGetFrame(int32_t result, pp::VideoFrame frame); |
| pp::Size position_size_; |
| bool is_painting_; |
| @@ -142,10 +76,8 @@ class VCDemoInstance : public pp::Instance, |
| GLuint texture_y_; |
| GLuint texture_u_; |
| GLuint texture_v_; |
| - pp::VideoCapture_Dev video_capture_; |
| - PP_VideoCaptureDeviceInfo_Dev capture_info_; |
| - std::vector<pp::Buffer_Dev> buffers_; |
| - pp::CompletionCallbackFactory<VCDemoInstance> callback_factory_; |
| + pp::MediaStreamVideoTrack video_track_; |
| + pp::CompletionCallbackFactory<MSVDemoInstance> callback_factory_; |
| // Unowned pointers. |
| const struct PPB_OpenGLES2* gles2_if_; |
| @@ -153,37 +85,29 @@ class VCDemoInstance : public pp::Instance, |
| // Owned data. |
| pp::Graphics3D* context_; |
| - std::vector<pp::DeviceRef_Dev> enumerate_devices_; |
| - std::vector<pp::DeviceRef_Dev> monitor_devices_; |
| + pp::Size frame_size_; |
| }; |
| -VCDemoInstance::VCDemoInstance(PP_Instance instance, pp::Module* module) |
| +MSVDemoInstance::MSVDemoInstance(PP_Instance instance, pp::Module* module) |
| : pp::Instance(instance), |
| pp::Graphics3DClient(this), |
| - pp::VideoCaptureClient_Dev(this), |
| is_painting_(false), |
| needs_paint_(false), |
| texture_y_(0), |
| texture_u_(0), |
| texture_v_(0), |
| - video_capture_(this), |
| callback_factory_(this), |
| context_(NULL) { |
| gles2_if_ = static_cast<const struct PPB_OpenGLES2*>( |
| module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); |
| PP_DCHECK(gles2_if_); |
| - |
| - capture_info_.width = 320; |
| - capture_info_.height = 240; |
| - capture_info_.frames_per_second = 30; |
| } |
| -VCDemoInstance::~VCDemoInstance() { |
| - video_capture_.MonitorDeviceChange(NULL, NULL); |
| +MSVDemoInstance::~MSVDemoInstance() { |
| delete context_; |
| } |
| -void VCDemoInstance::DidChangeView( |
| +void MSVDemoInstance::DidChangeView( |
| const pp::Rect& position, const pp::Rect& clip_ignored) { |
| if (position.width() == 0 || position.height() == 0) |
| return; |
| @@ -194,50 +118,26 @@ void VCDemoInstance::DidChangeView( |
| // Initialize graphics. |
| InitGL(); |
| - |
| Render(); |
| } |
| -void VCDemoInstance::HandleMessage(const pp::Var& message_data) { |
| - if (message_data.is_string()) { |
| - std::string event = message_data.AsString(); |
| - if (event == "PageInitialized") { |
| - int32_t result = video_capture_.MonitorDeviceChange( |
| - &VCDemoInstance::MonitorDeviceChangeCallback, this); |
| - if (result != PP_OK) |
| - PostMessage(pp::Var("MonitorDeviceChangeFailed")); |
| - |
| - pp::CompletionCallbackWithOutput<std::vector<pp::DeviceRef_Dev> > |
| - callback = callback_factory_.NewCallbackWithOutput( |
| - &VCDemoInstance::EnumerateDevicesFinished); |
| - result = video_capture_.EnumerateDevices(callback); |
| - if (result != PP_OK_COMPLETIONPENDING) |
| - PostMessage(pp::Var("EnumerationFailed")); |
| - } else if (event == "UseDefault") { |
| - Open(pp::DeviceRef_Dev()); |
| - } else if (event == "Stop") { |
| - Stop(); |
| - } else if (event == "Start") { |
| - Start(); |
| - } else if (event.find("Monitor:") == 0) { |
| - std::string index_str = event.substr(strlen("Monitor:")); |
| - int index = atoi(index_str.c_str()); |
| - if (index >= 0 && index < static_cast<int>(monitor_devices_.size())) |
| - Open(monitor_devices_[index]); |
| - else |
| - PP_NOTREACHED(); |
| - } else if (event.find("Enumerate:") == 0) { |
| - std::string index_str = event.substr(strlen("Enumerate:")); |
| - int index = atoi(index_str.c_str()); |
| - if (index >= 0 && index < static_cast<int>(enumerate_devices_.size())) |
| - Open(enumerate_devices_[index]); |
| - else |
| - PP_NOTREACHED(); |
| - } |
| - } |
| +void MSVDemoInstance::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(); |
| + |
| + video_track_ = pp::MediaStreamVideoTrack(resource_track); |
| + |
| + video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( |
| + &MSVDemoInstance::OnGetFrame)); |
| } |
| -void VCDemoInstance::InitGL() { |
| +void MSVDemoInstance::InitGL() { |
| PP_DCHECK(position_size_.width() && position_size_.height()); |
| is_painting_ = false; |
| @@ -270,7 +170,7 @@ void VCDemoInstance::InitGL() { |
| CreateGLObjects(); |
| } |
| -void VCDemoInstance::Render() { |
| +void MSVDemoInstance::Render() { |
| PP_DCHECK(!is_painting_); |
| is_painting_ = true; |
| needs_paint_ = false; |
| @@ -280,17 +180,17 @@ void VCDemoInstance::Render() { |
| gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); |
| } |
| pp::CompletionCallback cb = callback_factory_.NewCallback( |
| - &VCDemoInstance::PaintFinished); |
| + &MSVDemoInstance::PaintFinished); |
| context_->SwapBuffers(cb); |
| } |
| -void VCDemoInstance::PaintFinished(int32_t result) { |
| +void MSVDemoInstance::PaintFinished(int32_t result) { |
| is_painting_ = false; |
| if (needs_paint_) |
| Render(); |
| } |
| -GLuint VCDemoInstance::CreateTexture(int32_t width, int32_t height, int unit) { |
| +GLuint MSVDemoInstance::CreateTexture(int32_t width, int32_t height, int unit) { |
| GLuint texture_id; |
| gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); |
| AssertNoGLError(); |
| @@ -318,7 +218,7 @@ GLuint VCDemoInstance::CreateTexture(int32_t width, int32_t height, int unit) { |
| return texture_id; |
| } |
| -void VCDemoInstance::CreateGLObjects() { |
| +void MSVDemoInstance::CreateGLObjects() { |
| // Code and constants for shader. |
| static const char kVertexShader[] = |
| "varying vec2 v_texCoord; \n" |
| @@ -403,7 +303,7 @@ void VCDemoInstance::CreateGLObjects() { |
| AssertNoGLError(); |
| } |
| -void VCDemoInstance::CreateShader( |
| +void MSVDemoInstance::CreateShader( |
| GLuint program, GLenum type, const char* source, int size) { |
| PP_Resource context = context_->pp_resource(); |
| GLuint shader = gles2_if_->CreateShader(context, type); |
| @@ -413,9 +313,11 @@ void VCDemoInstance::CreateShader( |
| gles2_if_->DeleteShader(context, shader); |
| } |
| -void VCDemoInstance::CreateYUVTextures() { |
| - int32_t width = capture_info_.width; |
| - int32_t height = capture_info_.height; |
| +void MSVDemoInstance::CreateYUVTextures() { |
| + int32_t width = frame_size_.width(); |
| + int32_t height = frame_size_.height(); |
| + if (width == 0 || height == 0) |
| + return; |
| texture_y_ = CreateTexture(width, height, 0); |
| width /= 2; |
| @@ -424,74 +326,51 @@ void VCDemoInstance::CreateYUVTextures() { |
| texture_v_ = CreateTexture(width, height, 2); |
| } |
| -void VCDemoInstance::Open(const pp::DeviceRef_Dev& device) { |
| - pp::CompletionCallback callback = callback_factory_.NewCallback( |
| - &VCDemoInstance::OpenFinished); |
| - int32_t result = video_capture_.Open(device, capture_info_, 4, callback); |
| - if (result != PP_OK_COMPLETIONPENDING) |
| - PostMessage(pp::Var("OpenFailed")); |
| -} |
| +void MSVDemoInstance::OnGetFrame(int32_t result, pp::VideoFrame frame) { |
| + if (result != PP_OK) |
| + return; |
| + const char* data = static_cast<const char*>(frame.GetDataBuffer()); |
| + pp::Size size; |
| + PP_DCHECK(frame.GetSize(&size)); |
| + if (size != frame_size_) { |
| + frame_size_ = size; |
| + CreateYUVTextures(); |
|
bbudge
2014/01/10 21:39:28
Shouldn't we DeleteTextures for the old ones befor
Peng
2014/01/10 22:40:24
Yes. It is better to delete them.
Done
|
| + } |
| -void VCDemoInstance::Stop() { |
| - if (video_capture_.StopCapture() != PP_OK) |
| - PostMessage(pp::Var("StopFailed")); |
| -} |
| + int32_t width = frame_size_.width(); |
| + int32_t height = frame_size_.height(); |
| + gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); |
| + gles2_if_->TexSubImage2D( |
| + context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| -void VCDemoInstance::Start() { |
| - if (video_capture_.StartCapture() != PP_OK) |
| - PostMessage(pp::Var("StartFailed")); |
| -} |
| + data += width * height; |
| + width /= 2; |
| + height /= 2; |
| -void VCDemoInstance::EnumerateDevicesFinished( |
| - int32_t result, |
| - std::vector<pp::DeviceRef_Dev>& devices) { |
| - if (result == PP_OK) { |
| - enumerate_devices_.swap(devices); |
| - std::string device_names = "Enumerate:"; |
| - for (size_t index = 0; index < enumerate_devices_.size(); ++index) { |
| - pp::Var name = enumerate_devices_[index].GetName(); |
| - PP_DCHECK(name.is_string()); |
| - |
| - if (index != 0) |
| - device_names += kDelimiter; |
| - device_names += name.AsString(); |
| - } |
| - PostMessage(pp::Var(device_names)); |
| - } else { |
| - PostMessage(pp::Var("EnumerationFailed")); |
| - } |
| -} |
| + gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1); |
| + gles2_if_->TexSubImage2D( |
| + context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| + |
| + data += width * height; |
| + gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2); |
| + gles2_if_->TexSubImage2D( |
| + context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, |
| + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| -void VCDemoInstance::OpenFinished(int32_t result) { |
| - if (result == PP_OK) |
| - Start(); |
| + if (is_painting_) |
| + needs_paint_ = true; |
| else |
| - PostMessage(pp::Var("OpenFailed")); |
| -} |
| + Render(); |
| -// static |
| -void VCDemoInstance::MonitorDeviceChangeCallback(void* user_data, |
| - uint32_t device_count, |
| - const PP_Resource devices[]) { |
| - VCDemoInstance* thiz = static_cast<VCDemoInstance*>(user_data); |
| - |
| - std::string device_names = "Monitor:"; |
| - thiz->monitor_devices_.clear(); |
| - thiz->monitor_devices_.reserve(device_count); |
| - for (size_t index = 0; index < device_count; ++index) { |
| - thiz->monitor_devices_.push_back(pp::DeviceRef_Dev(devices[index])); |
| - pp::Var name = thiz->monitor_devices_.back().GetName(); |
| - PP_DCHECK(name.is_string()); |
| - |
| - if (index != 0) |
| - device_names += kDelimiter; |
| - device_names += name.AsString(); |
| - } |
| - thiz->PostMessage(pp::Var(device_names)); |
| + video_track_.RecycleFrame(frame); |
| + video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( |
| + &MSVDemoInstance::OnGetFrame)); |
| } |
| -pp::Instance* VCDemoModule::CreateInstance(PP_Instance instance) { |
| - return new VCDemoInstance(instance, this); |
| +pp::Instance* MSVDemoModule::CreateInstance(PP_Instance instance) { |
| + return new MSVDemoInstance(instance, this); |
| } |
| } // anonymous namespace |
| @@ -499,6 +378,6 @@ pp::Instance* VCDemoModule::CreateInstance(PP_Instance instance) { |
| namespace pp { |
| // Factory function for your specialization of the Module object. |
| Module* CreateModule() { |
| - return new VCDemoModule(); |
| + return new MSVDemoModule(); |
| } |
| } // namespace pp |