Review URL: http://webrtc-codereview.appspot.com/239015
git-svn-id: http://webrtc.googlecode.com/svn/trunk@847 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
1e10bb32b9
commit
8885d22399
@ -771,6 +771,7 @@
|
||||
}],
|
||||
], #conditions
|
||||
'sources': [
|
||||
'<(libjingle_mods)/source/talk/app/webrtc_dev/test/filevideocapturemodule.cc',
|
||||
'<(libjingle_mods)/source/talk/app/webrtc_dev/mediastream_unittest.cc',
|
||||
'<(libjingle_mods)/source/talk/app/webrtc_dev/mediastreamhandler_unittest.cc',
|
||||
'<(libjingle_mods)/source/talk/app/webrtc_dev/peerconnection_unittest.cc',
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "modules/video_capture/main/interface/video_capture_factory.h"
|
||||
#include "talk/app/webrtc_dev/mediastream.h"
|
||||
#include "talk/app/webrtc_dev/peerconnection.h"
|
||||
#include "talk/app/webrtc_dev/test/filevideocapturemodule.h"
|
||||
#include "talk/base/thread.h"
|
||||
#include "talk/session/phone/videoframe.h"
|
||||
#include "talk/session/phone/videorenderer.h"
|
||||
@ -47,11 +48,10 @@ void GetAllVideoTracks(webrtc::MediaStreamInterface* media_stream,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(henrike): replace with a capture device that reads from a file/buffer.
|
||||
talk_base::scoped_refptr<webrtc::VideoCaptureModule> OpenVideoCaptureDevice() {
|
||||
webrtc::VideoCaptureModule* OpenVideoCaptureDevice() {
|
||||
webrtc::VideoCaptureModule::DeviceInfo* device_info(
|
||||
webrtc::VideoCaptureFactory::CreateDeviceInfo(0));
|
||||
talk_base::scoped_refptr<webrtc::VideoCaptureModule> video_device;
|
||||
webrtc::VideoCaptureModule* video_device;
|
||||
|
||||
const size_t kMaxDeviceNameLength = 128;
|
||||
const size_t kMaxUniqueIdLength = 256;
|
||||
@ -66,7 +66,7 @@ talk_base::scoped_refptr<webrtc::VideoCaptureModule> OpenVideoCaptureDevice() {
|
||||
// Try to open this device.
|
||||
video_device =
|
||||
webrtc::VideoCaptureFactory::Create(0, unique_id);
|
||||
if (video_device.get())
|
||||
if (video_device != NULL)
|
||||
break;
|
||||
}
|
||||
delete device_info;
|
||||
@ -183,8 +183,7 @@ class PeerConnectionP2PTestClient
|
||||
|
||||
talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> video_track(
|
||||
peer_connection_factory_->CreateLocalVideoTrack(
|
||||
"video_track",
|
||||
OpenVideoCaptureDevice()));
|
||||
"video_track", OpenVideoFileCaptureDevice()));
|
||||
|
||||
talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> stream =
|
||||
peer_connection_factory_->CreateLocalMediaStream("stream_label");
|
||||
@ -211,7 +210,7 @@ class PeerConnectionP2PTestClient
|
||||
virtual void OnMessage(const std::string&) {}
|
||||
virtual void OnSignalingMessage(const std::string& msg) {
|
||||
if (signaling_message_receiver_ == NULL) {
|
||||
ADD_FAILURE();
|
||||
// Remote party may be deleted.
|
||||
return;
|
||||
}
|
||||
signaling_message_receiver_->ReceiveMessage(msg);
|
||||
@ -242,6 +241,8 @@ class PeerConnectionP2PTestClient
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kFileNameSize = 256;
|
||||
|
||||
explicit PeerConnectionP2PTestClient(int id)
|
||||
: id_(id),
|
||||
peer_connection_(),
|
||||
@ -264,14 +265,21 @@ class PeerConnectionP2PTestClient
|
||||
return peer_connection_.get() != NULL;
|
||||
}
|
||||
|
||||
void GenerateRecordingFileName(int track, char file_name[256]) {
|
||||
void GenerateRecordingFileName(int track, char file_name[kFileNameSize]) {
|
||||
if (file_name == NULL) {
|
||||
return;
|
||||
}
|
||||
snprintf(file_name, sizeof(file_name),
|
||||
snprintf(file_name, kFileNameSize,
|
||||
"p2p_test_client_%d_videotrack_%d.yuv", id_, track);
|
||||
}
|
||||
|
||||
webrtc::VideoCaptureModule* OpenVideoFileCaptureDevice() {
|
||||
const char filename[] = "foreman_cif.yuv";
|
||||
webrtc::VideoCaptureModule* video_device =
|
||||
FileVideoCaptureModule::CreateFileVideoCaptureModule(filename);
|
||||
return video_device;
|
||||
}
|
||||
|
||||
int id_;
|
||||
talk_base::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
|
||||
talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
|
||||
@ -292,6 +300,8 @@ class P2PTestConductor {
|
||||
return conductor;
|
||||
}
|
||||
~P2PTestConductor() {
|
||||
clients[0]->set_signaling_message_receiver(NULL);
|
||||
clients[1]->set_signaling_message_receiver(NULL);
|
||||
for (int i = 0; i < kClients; ++i) {
|
||||
if (clients[i] != NULL) {
|
||||
// TODO(hellner): currently deleting the clients will trigger an assert
|
||||
|
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2011, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "talk/app/webrtc_dev/test/filevideocapturemodule.h"
|
||||
|
||||
#ifdef WEBRTC_RELATIVE_PATH
|
||||
#include "system_wrappers/interface/ref_count.h"
|
||||
#else
|
||||
#include "third_party/webrtc/files/include/ref_count.h"
|
||||
#endif
|
||||
|
||||
FileVideoCaptureModule::~FileVideoCaptureModule() {
|
||||
camera_thread_->Stop();
|
||||
if (i420_file_ != NULL) fclose(i420_file_);
|
||||
// The memory associated with video_capture_ is owned by impl_.
|
||||
}
|
||||
|
||||
webrtc::VideoCaptureModule*
|
||||
FileVideoCaptureModule::CreateFileVideoCaptureModule(const char* file_name) {
|
||||
webrtc::RefCountImpl<FileVideoCaptureModule>* capture_module =
|
||||
new webrtc::RefCountImpl<FileVideoCaptureModule>();
|
||||
if (!capture_module->Init(file_name)) {
|
||||
capture_module->Release();
|
||||
return NULL;
|
||||
}
|
||||
return capture_module;
|
||||
}
|
||||
|
||||
// TODO(henrike): deal with the rounding error.
|
||||
bool FileVideoCaptureModule::SetFrameRate(int fps) {
|
||||
fps_ = fps;
|
||||
time_per_frame_ms_ = 1000 / fps;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileVideoCaptureModule::SetSize(int width, int height) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
image_.reset(new uint8[GetI420FrameLength()]);
|
||||
}
|
||||
|
||||
FileVideoCaptureModule::FileVideoCaptureModule()
|
||||
: impl_(),
|
||||
i420_file_(NULL),
|
||||
camera_thread_(new talk_base::Thread()),
|
||||
video_capture_(NULL),
|
||||
started_(false),
|
||||
sent_frames_(0),
|
||||
next_frame_time_(0),
|
||||
time_per_frame_ms_(0),
|
||||
fps_(0),
|
||||
width_(0),
|
||||
height_(0),
|
||||
image_() {}
|
||||
|
||||
bool FileVideoCaptureModule::Init(const char* file_name) {
|
||||
impl_ = webrtc::VideoCaptureFactory::Create(0, // id
|
||||
video_capture_);
|
||||
if (impl_.get() == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (video_capture_ == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (!SetFrameRate(kStartFrameRate)) {
|
||||
return false;
|
||||
}
|
||||
SetSize(kStartWidth, kStartHeight);
|
||||
i420_file_ = fopen(file_name, "rb");
|
||||
if (i420_file_ == NULL) {
|
||||
// Not generally unexpected but for this class it is.
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
if (!camera_thread_->Start()) {
|
||||
return false;
|
||||
}
|
||||
// Only one post, no need to add any data to post.
|
||||
camera_thread_->Post(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(henrike): handle time wrapparound.
|
||||
void FileVideoCaptureModule::GenerateNewFrame() {
|
||||
if (!started_) {
|
||||
next_frame_time_ = talk_base::Time();
|
||||
started_ = true;
|
||||
}
|
||||
// Read from file.
|
||||
int read = fread(image_.get(), sizeof(uint8), GetI420FrameLength(),
|
||||
i420_file_);
|
||||
// Loop file if end is reached.
|
||||
if (read != GetI420FrameLength()) {
|
||||
fseek(i420_file_, 0, SEEK_SET);
|
||||
read = fread(image_.get(), sizeof(uint8), GetI420FrameLength(),
|
||||
i420_file_);
|
||||
if (read != GetI420FrameLength()) {
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
webrtc::VideoCaptureCapability capability;
|
||||
capability.width = width_;
|
||||
capability.height = height_;
|
||||
capability.maxFPS = 0;
|
||||
capability.expectedCaptureDelay = 0;
|
||||
capability.rawType =webrtc:: kVideoI420;
|
||||
capability.codecType = webrtc::kVideoCodecUnknown;
|
||||
capability.interlaced = false;
|
||||
video_capture_->IncomingFrame(image_.get(), GetI420FrameLength(),
|
||||
capability, GetTimestamp());
|
||||
++sent_frames_;
|
||||
next_frame_time_ += time_per_frame_ms_;
|
||||
const uint32 current_time = talk_base::Time();
|
||||
const uint32 wait_time = (next_frame_time_ > current_time) ?
|
||||
next_frame_time_ - current_time : 0;
|
||||
camera_thread_->PostDelayed(wait_time, this);
|
||||
}
|
||||
|
||||
int FileVideoCaptureModule::GetI420FrameLength() {
|
||||
return width_ * height_ * 3 >> 1;
|
||||
}
|
||||
|
||||
// TODO(henrike): use this function instead of/in addition to reading from a
|
||||
// file.
|
||||
void FileVideoCaptureModule::SetFrame(uint8* image) {
|
||||
// Set Y plane.
|
||||
memset(image, 128, width_ * height_);
|
||||
// Set U plane.
|
||||
int write_position = width_ * height_;
|
||||
memset(&image[write_position], 64, width_ * height_ / 4);
|
||||
// Set V plane.
|
||||
write_position += width_ * height_ / 4;
|
||||
memset(&image[write_position], 32, width_ * height_ / 4);
|
||||
}
|
||||
|
||||
// TODO(henrike): handle timestamp wrapparound.
|
||||
uint32 FileVideoCaptureModule::GetTimestamp() {
|
||||
return kStartTimeStamp + sent_frames_ * time_per_frame_ms_;
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* libjingle
|
||||
* Copyright 2011, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// This class implements the VideoCaptureModule interface. Instead of capturing
|
||||
// frames from a camera it captures frames from a file.
|
||||
|
||||
#ifndef TALK_APP_WEBRTC_TEST_FILEVIDEOCAPTUREMODULE_H_
|
||||
#define TALK_APP_WEBRTC_TEST_FILEVIDEOCAPTUREMODULE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include "talk/base/common.h"
|
||||
#include "talk/base/scoped_ptr.h"
|
||||
#include "talk/base/thread.h"
|
||||
#include "talk/base/time.h"
|
||||
|
||||
#ifdef WEBRTC_RELATIVE_PATH
|
||||
#include "common_types.h"
|
||||
#include "modules/video_capture/main/interface/video_capture.h"
|
||||
#include "modules/video_capture/main/interface/video_capture_defines.h"
|
||||
#include "modules/video_capture/main/interface/video_capture_factory.h"
|
||||
#include "system_wrappers/interface/ref_count.h"
|
||||
#include "system_wrappers/interface/scoped_refptr.h"
|
||||
#else
|
||||
#include "third_party/webrtc/files/include/common_types.h"
|
||||
#include "third_party/webrtc/files/include/video_capture.h"
|
||||
#include "third_party/webrtc/files/include/video_capture_defines.h"
|
||||
#include "third_party/webrtc/files/include/video_capture_factory.h"
|
||||
#include "third_party/webrtc/files/include/ref_count.h"
|
||||
#include "third_party/webrtc/files/include/scoped_refptr.h"
|
||||
#endif
|
||||
|
||||
// TODO(henrike): replace playing file with playing a buffer.
|
||||
class FileVideoCaptureModule
|
||||
: public webrtc::VideoCaptureModule,
|
||||
public talk_base::MessageHandler {
|
||||
public:
|
||||
virtual ~FileVideoCaptureModule();
|
||||
static VideoCaptureModule* CreateFileVideoCaptureModule(
|
||||
const char* file_name);
|
||||
|
||||
bool SetFrameRate(int fps);
|
||||
void SetSize(int width, int height);
|
||||
|
||||
virtual int32_t Version(char* version,
|
||||
uint32_t& remaining_buffer_in_bytes,
|
||||
uint32_t& position) const {
|
||||
return impl_->Version(version, remaining_buffer_in_bytes,
|
||||
position);
|
||||
}
|
||||
|
||||
virtual int32_t ChangeUniqueId(const int32_t id) {
|
||||
return impl_->ChangeUniqueId(id);
|
||||
}
|
||||
|
||||
virtual int32_t TimeUntilNextProcess() {
|
||||
return impl_->TimeUntilNextProcess();
|
||||
}
|
||||
|
||||
virtual int32_t Process() {
|
||||
return impl_->Process();
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 RegisterCaptureDataCallback(
|
||||
webrtc::VideoCaptureDataCallback& dataCallback) {
|
||||
return impl_->RegisterCaptureDataCallback(dataCallback);
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 DeRegisterCaptureDataCallback() {
|
||||
return impl_->DeRegisterCaptureDataCallback();
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 RegisterCaptureCallback(
|
||||
webrtc::VideoCaptureFeedBack& callBack) {
|
||||
return impl_->RegisterCaptureCallback(callBack);
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 DeRegisterCaptureCallback() {
|
||||
return impl_->DeRegisterCaptureCallback();
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 StartCapture(
|
||||
const webrtc::VideoCaptureCapability& capability) {
|
||||
return impl_->StartCapture(capability);
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 StopCapture() {
|
||||
return impl_->StopCapture();
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 StartSendImage(const webrtc::VideoFrame& videoFrame,
|
||||
WebRtc_Word32 frameRate = 1) {
|
||||
return impl_->StartSendImage(videoFrame, frameRate = 1);
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 StopSendImage() {
|
||||
return impl_->StopSendImage();
|
||||
}
|
||||
|
||||
virtual const WebRtc_UWord8* CurrentDeviceName() const {
|
||||
return impl_->CurrentDeviceName();
|
||||
}
|
||||
|
||||
virtual bool CaptureStarted() {
|
||||
return impl_->CaptureStarted();
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 CaptureSettings(
|
||||
webrtc::VideoCaptureCapability& settings) {
|
||||
return impl_->CaptureSettings(settings);
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 SetCaptureDelay(WebRtc_Word32 delayMS) {
|
||||
return impl_->SetCaptureDelay(delayMS);
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 CaptureDelay() {
|
||||
return impl_->CaptureDelay();
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 SetCaptureRotation(
|
||||
webrtc::VideoCaptureRotation rotation) {
|
||||
return impl_->SetCaptureRotation(rotation);
|
||||
}
|
||||
|
||||
virtual VideoCaptureEncodeInterface* GetEncodeInterface(
|
||||
const webrtc::VideoCodec& codec) {
|
||||
return impl_->GetEncodeInterface(codec);
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 EnableFrameRateCallback(const bool enable) {
|
||||
return impl_->EnableFrameRateCallback(enable);
|
||||
}
|
||||
virtual WebRtc_Word32 EnableNoPictureAlarm(const bool enable) {
|
||||
return impl_->EnableNoPictureAlarm(enable);
|
||||
}
|
||||
|
||||
// Inherited from MesageHandler.
|
||||
virtual void OnMessage(talk_base::Message* msg) {
|
||||
GenerateNewFrame();
|
||||
}
|
||||
|
||||
protected:
|
||||
FileVideoCaptureModule();
|
||||
|
||||
private:
|
||||
bool Init(const char* file_name);
|
||||
void GenerateNewFrame();
|
||||
int GetI420FrameLength();
|
||||
// Generate an arbitrary frame. (Will be used when file reading is replaced
|
||||
// with reading a buffer).
|
||||
void SetFrame(uint8* image);
|
||||
uint32 GetTimestamp();
|
||||
|
||||
// Module interface implementation.
|
||||
webrtc::scoped_refptr<VideoCaptureModule> impl_;
|
||||
|
||||
// File playing implementation.
|
||||
static const int kStartFrameRate = 30;
|
||||
// CIF
|
||||
static const int kStartWidth = 352;
|
||||
static const int kStartHeight = 288;
|
||||
static const uint32 kStartTimeStamp = 2000;
|
||||
|
||||
FILE* i420_file_;
|
||||
talk_base::scoped_ptr<talk_base::Thread> camera_thread_;
|
||||
webrtc::VideoCaptureExternal* video_capture_;
|
||||
|
||||
bool started_;
|
||||
int sent_frames_;
|
||||
uint32 next_frame_time_;
|
||||
uint32 time_per_frame_ms_;
|
||||
|
||||
int fps_;
|
||||
int width_;
|
||||
int height_;
|
||||
talk_base::scoped_array<uint8> image_;
|
||||
};
|
||||
|
||||
#endif // TALK_APP_WEBRTC_TEST_FILEVIDEOCAPTUREMODULE_H_
|
Loading…
Reference in New Issue
Block a user