New VideoEngine API implementation on top of old one, first steps.
BUG=1668 R=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1360004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4044 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
2038214c77
commit
29d5839233
186
webrtc/video_engine/internal/video_call.cc
Normal file
186
webrtc/video_engine/internal/video_call.cc
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/internal/video_call.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||
#include "webrtc/video_engine/include/vie_base.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
||||
#include "webrtc/video_engine/new_include/common.h"
|
||||
#include "webrtc/video_engine/new_include/video_engine.h"
|
||||
#include "webrtc/video_engine/internal/video_receive_stream.h"
|
||||
#include "webrtc/video_engine/internal/video_send_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace internal {
|
||||
|
||||
VideoCall::VideoCall(webrtc::VideoEngine* video_engine,
|
||||
newapi::Transport* send_transport)
|
||||
: send_transport(send_transport), video_engine_(video_engine) {
|
||||
assert(video_engine != NULL);
|
||||
assert(send_transport != NULL);
|
||||
|
||||
rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
|
||||
assert(rtp_rtcp_ != NULL);
|
||||
|
||||
codec_ = ViECodec::GetInterface(video_engine_);
|
||||
assert(codec_ != NULL);
|
||||
}
|
||||
|
||||
VideoCall::~VideoCall() {
|
||||
rtp_rtcp_->Release();
|
||||
codec_->Release();
|
||||
}
|
||||
|
||||
newapi::PacketReceiver* VideoCall::Receiver() { return this; }
|
||||
|
||||
std::vector<VideoCodec> VideoCall::GetVideoCodecs() {
|
||||
std::vector<VideoCodec> codecs;
|
||||
|
||||
VideoCodec codec;
|
||||
for (size_t i = 0; i < static_cast<size_t>(codec_->NumberOfCodecs()); ++i) {
|
||||
if (codec_->GetCodec(i, codec) == 0) {
|
||||
codecs.push_back(codec);
|
||||
}
|
||||
}
|
||||
return codecs;
|
||||
}
|
||||
|
||||
void VideoCall::GetDefaultSendConfig(
|
||||
newapi::VideoSendStreamConfig* send_stream_config) {
|
||||
*send_stream_config = newapi::VideoSendStreamConfig();
|
||||
codec_->GetCodec(0, send_stream_config->codec);
|
||||
}
|
||||
|
||||
newapi::VideoSendStream* VideoCall::CreateSendStream(
|
||||
const newapi::VideoSendStreamConfig& send_stream_config) {
|
||||
assert(send_stream_config.rtp.ssrcs.size() > 0);
|
||||
assert(send_stream_config.codec.numberOfSimulcastStreams == 0 ||
|
||||
send_stream_config.codec.numberOfSimulcastStreams ==
|
||||
send_stream_config.rtp.ssrcs.size());
|
||||
VideoSendStream* send_stream =
|
||||
new VideoSendStream(send_transport, video_engine_, send_stream_config);
|
||||
for (size_t i = 0; i < send_stream_config.rtp.ssrcs.size(); ++i) {
|
||||
uint32_t ssrc = send_stream_config.rtp.ssrcs[i];
|
||||
// SSRC must be previously unused!
|
||||
assert(send_ssrcs_[ssrc] == NULL &&
|
||||
receive_ssrcs_.find(ssrc) == receive_ssrcs_.end());
|
||||
send_ssrcs_[ssrc] = send_stream;
|
||||
}
|
||||
return send_stream;
|
||||
}
|
||||
|
||||
newapi::SendStreamState* VideoCall::DestroySendStream(
|
||||
newapi::VideoSendStream* send_stream) {
|
||||
if (send_stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
// TODO(pbos): Remove it properly! Free the SSRCs!
|
||||
delete static_cast<VideoSendStream*>(send_stream);
|
||||
|
||||
// TODO(pbos): Return its previous state
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VideoCall::GetDefaultReceiveConfig(
|
||||
newapi::VideoReceiveStreamConfig* receive_stream_config) {
|
||||
// TODO(pbos): This is not the default config.
|
||||
*receive_stream_config = newapi::VideoReceiveStreamConfig();
|
||||
}
|
||||
|
||||
newapi::VideoReceiveStream* VideoCall::CreateReceiveStream(
|
||||
const newapi::VideoReceiveStreamConfig& receive_stream_config) {
|
||||
assert(receive_ssrcs_[receive_stream_config.rtp.ssrc] == NULL);
|
||||
|
||||
VideoReceiveStream* receive_stream = new VideoReceiveStream(
|
||||
video_engine_, receive_stream_config, send_transport);
|
||||
|
||||
receive_ssrcs_[receive_stream_config.rtp.ssrc] = receive_stream;
|
||||
|
||||
return receive_stream;
|
||||
}
|
||||
|
||||
void VideoCall::DestroyReceiveStream(
|
||||
newapi::VideoReceiveStream* receive_stream) {
|
||||
if (receive_stream == NULL) {
|
||||
return;
|
||||
}
|
||||
// TODO(pbos): Remove its SSRCs!
|
||||
delete static_cast<VideoReceiveStream*>(receive_stream);
|
||||
}
|
||||
|
||||
uint32_t VideoCall::SendBitrateEstimate() {
|
||||
// TODO(pbos): Return send-bitrate estimate
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t VideoCall::ReceiveBitrateEstimate() {
|
||||
// TODO(pbos): Return receive-bitrate estimate
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool VideoCall::DeliverRtcp(ModuleRTPUtility::RTPHeaderParser* rtp_parser,
|
||||
const void* packet, size_t length) {
|
||||
// TODO(pbos): Figure out what channel needs it actually.
|
||||
// Do NOT broadcast! Also make sure it's a valid packet.
|
||||
bool rtcp_delivered = false;
|
||||
for (std::map<uint32_t, newapi::VideoReceiveStream*>::iterator it =
|
||||
receive_ssrcs_.begin();
|
||||
it != receive_ssrcs_.end(); ++it) {
|
||||
if (static_cast<VideoReceiveStream*>(it->second)
|
||||
->DeliverRtcp(packet, length)) {
|
||||
rtcp_delivered = true;
|
||||
}
|
||||
}
|
||||
return rtcp_delivered;
|
||||
}
|
||||
|
||||
bool VideoCall::DeliverRtp(ModuleRTPUtility::RTPHeaderParser* rtp_parser,
|
||||
const void* packet, size_t length) {
|
||||
WebRtcRTPHeader rtp_header;
|
||||
|
||||
// TODO(pbos): ExtensionMap if there are extensions
|
||||
if (!rtp_parser->Parse(rtp_header)) {
|
||||
// TODO(pbos): Should this error be reported and trigger something?
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ssrc = rtp_header.header.ssrc;
|
||||
if (receive_ssrcs_.find(ssrc) == receive_ssrcs_.end()) {
|
||||
// TODO(pbos): Log some warning, SSRC without receiver.
|
||||
return false;
|
||||
}
|
||||
|
||||
VideoReceiveStream* receiver =
|
||||
static_cast<VideoReceiveStream*>(receive_ssrcs_[ssrc]);
|
||||
return receiver->DeliverRtp(packet, length);
|
||||
}
|
||||
|
||||
bool VideoCall::DeliverPacket(const void* packet, size_t length) {
|
||||
// TODO(pbos): Respect the constness of packet.
|
||||
ModuleRTPUtility::RTPHeaderParser rtp_parser(
|
||||
const_cast<uint8_t*>(static_cast<const uint8_t*>(packet)), length);
|
||||
|
||||
if (rtp_parser.RTCP()) {
|
||||
return DeliverRtcp(&rtp_parser, packet, length);
|
||||
}
|
||||
|
||||
return DeliverRtp(&rtp_parser, packet, length);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
85
webrtc/video_engine/internal/video_call.h
Normal file
85
webrtc/video_engine/internal/video_call.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_VIDEO_CALL_IMPL_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_VIDEO_CALL_IMPL_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||
#include "webrtc/video_engine/new_include/common.h"
|
||||
#include "webrtc/video_engine/new_include/video_engine.h"
|
||||
#include "webrtc/video_engine/internal/video_receive_stream.h"
|
||||
#include "webrtc/video_engine/internal/video_send_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VideoEngine;
|
||||
class ViERTP_RTCP;
|
||||
class ViECodec;
|
||||
|
||||
namespace internal {
|
||||
|
||||
// TODO(pbos): Split out the packet receiver, should be sharable between
|
||||
// VideoEngine and VoiceEngine.
|
||||
class VideoCall : public newapi::VideoCall, public newapi::PacketReceiver {
|
||||
public:
|
||||
VideoCall(webrtc::VideoEngine* video_engine,
|
||||
newapi::Transport* send_transport);
|
||||
virtual ~VideoCall();
|
||||
|
||||
virtual newapi::PacketReceiver* Receiver() OVERRIDE;
|
||||
virtual std::vector<VideoCodec> GetVideoCodecs() OVERRIDE;
|
||||
|
||||
virtual void GetDefaultSendConfig(
|
||||
newapi::VideoSendStreamConfig* send_stream_config) OVERRIDE;
|
||||
|
||||
virtual newapi::VideoSendStream* CreateSendStream(
|
||||
const newapi::VideoSendStreamConfig& send_stream_config) OVERRIDE;
|
||||
|
||||
virtual newapi::SendStreamState* DestroySendStream(
|
||||
newapi::VideoSendStream* send_stream) OVERRIDE;
|
||||
|
||||
virtual void GetDefaultReceiveConfig(
|
||||
newapi::VideoReceiveStreamConfig* receive_stream_config) OVERRIDE;
|
||||
|
||||
virtual newapi::VideoReceiveStream* CreateReceiveStream(
|
||||
const newapi::VideoReceiveStreamConfig& receive_stream_config) OVERRIDE;
|
||||
|
||||
virtual void DestroyReceiveStream(newapi::VideoReceiveStream* receive_stream)
|
||||
OVERRIDE;
|
||||
|
||||
virtual uint32_t SendBitrateEstimate() OVERRIDE;
|
||||
virtual uint32_t ReceiveBitrateEstimate() OVERRIDE;
|
||||
|
||||
virtual bool DeliverPacket(const void* packet, size_t length) OVERRIDE;
|
||||
|
||||
private:
|
||||
bool DeliverRtp(ModuleRTPUtility::RTPHeaderParser* rtp_parser,
|
||||
const void* packet, size_t length);
|
||||
bool DeliverRtcp(ModuleRTPUtility::RTPHeaderParser* rtp_parser,
|
||||
const void* packet, size_t length);
|
||||
|
||||
newapi::Transport* send_transport;
|
||||
|
||||
std::map<uint32_t, newapi::VideoReceiveStream*> receive_ssrcs_;
|
||||
std::map<uint32_t, newapi::VideoSendStream*> send_ssrcs_;
|
||||
|
||||
webrtc::VideoEngine* video_engine_;
|
||||
ViERTP_RTCP* rtp_rtcp_;
|
||||
ViECodec* codec_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(VideoCall);
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_INTERNAL_VIDEO_CALL_H_
|
||||
59
webrtc/video_engine/internal/video_engine.cc
Normal file
59
webrtc/video_engine/internal/video_engine.cc
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/new_include/video_engine.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "webrtc/video_engine/include/vie_base.h"
|
||||
#include "webrtc/video_engine/internal/video_call.h"
|
||||
#include "webrtc/video_engine/vie_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace internal {
|
||||
|
||||
class VideoEngine : public newapi::VideoEngine {
|
||||
public:
|
||||
explicit VideoEngine(const newapi::VideoEngineConfig& engine_config)
|
||||
: config_(engine_config) {
|
||||
video_engine_ = webrtc::VideoEngine::Create();
|
||||
assert(video_engine_ != NULL);
|
||||
|
||||
ViEBase* video_engine_base = ViEBase::GetInterface(video_engine_);
|
||||
assert(video_engine_base != NULL);
|
||||
if (video_engine_base->Init() != 0) {
|
||||
abort();
|
||||
}
|
||||
video_engine_base->Release();
|
||||
}
|
||||
|
||||
virtual ~VideoEngine() { webrtc::VideoEngine::Delete(video_engine_); }
|
||||
|
||||
virtual newapi::VideoCall* CreateCall(newapi::Transport* transport) OVERRIDE {
|
||||
return new VideoCall(video_engine_, transport);
|
||||
}
|
||||
|
||||
private:
|
||||
newapi::VideoEngineConfig config_;
|
||||
webrtc::VideoEngine* video_engine_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(VideoEngine);
|
||||
};
|
||||
} // internal
|
||||
|
||||
namespace newapi {
|
||||
|
||||
VideoEngine* VideoEngine::Create(const VideoEngineConfig& engine_config) {
|
||||
return new internal::VideoEngine(engine_config);
|
||||
}
|
||||
|
||||
const char* Version() { return WEBRTC_SVNREVISION " (" BUILDINFO ")"; }
|
||||
} // newapi
|
||||
} // webrtc
|
||||
157
webrtc/video_engine/internal/video_receive_stream.cc
Normal file
157
webrtc/video_engine/internal/video_receive_stream.cc
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/internal/video_receive_stream.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
#include "webrtc/video_engine/include/vie_base.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_network.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
||||
#include "webrtc/video_engine/new_include/video_receive_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace internal {
|
||||
|
||||
VideoReceiveStream::VideoReceiveStream(
|
||||
webrtc::VideoEngine* video_engine,
|
||||
const newapi::VideoReceiveStreamConfig& config,
|
||||
newapi::Transport* transport)
|
||||
: transport_(transport), config_(config) {
|
||||
video_engine_base_ = ViEBase::GetInterface(video_engine);
|
||||
// TODO(mflodman): Use the other CreateChannel method.
|
||||
video_engine_base_->CreateChannel(channel_);
|
||||
assert(channel_ != -1);
|
||||
|
||||
rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
|
||||
assert(rtp_rtcp_ != NULL);
|
||||
|
||||
assert(config_.rtp.ssrc != 0);
|
||||
|
||||
network_ = ViENetwork::GetInterface(video_engine);
|
||||
assert(network_ != NULL);
|
||||
|
||||
network_->RegisterSendTransport(channel_, *this);
|
||||
|
||||
codec_ = ViECodec::GetInterface(video_engine);
|
||||
|
||||
for (size_t i = 0; i < config_.codecs.size(); ++i) {
|
||||
if (codec_->SetReceiveCodec(channel_, config_.codecs[i]) != 0) {
|
||||
// TODO(pbos): Abort gracefully, this can be a runtime error.
|
||||
// Factor out to an Init() method.
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
render_ = webrtc::ViERender::GetInterface(video_engine);
|
||||
assert(render_ != NULL);
|
||||
|
||||
if (render_->AddRenderer(channel_, kVideoI420, this) != 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
clock_ = Clock::GetRealTimeClock();
|
||||
}
|
||||
|
||||
VideoReceiveStream::~VideoReceiveStream() {
|
||||
network_->DeregisterSendTransport(channel_);
|
||||
|
||||
video_engine_base_->Release();
|
||||
codec_->Release();
|
||||
network_->Release();
|
||||
render_->Release();
|
||||
rtp_rtcp_->Release();
|
||||
}
|
||||
|
||||
void VideoReceiveStream::StartReceive() {
|
||||
if (render_->StartRender(channel_)) {
|
||||
abort();
|
||||
}
|
||||
if (video_engine_base_->StartReceive(channel_) != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoReceiveStream::StopReceive() {
|
||||
if (render_->StopRender(channel_)) {
|
||||
abort();
|
||||
}
|
||||
if (video_engine_base_->StopReceive(channel_) != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
|
||||
// TODO(pbos): Implement
|
||||
}
|
||||
|
||||
void VideoReceiveStream::GetReceiveStatistics(
|
||||
newapi::ReceiveStatistics* statistics) {
|
||||
// TODO(pbos): Implement
|
||||
}
|
||||
|
||||
bool VideoReceiveStream::DeliverRtcp(const void* packet, size_t length) {
|
||||
return network_->ReceivedRTCPPacket(channel_, packet, length) == 0;
|
||||
}
|
||||
|
||||
bool VideoReceiveStream::DeliverRtp(const void* packet, size_t length) {
|
||||
return network_->ReceivedRTPPacket(channel_, packet, length) == 0;
|
||||
}
|
||||
|
||||
int VideoReceiveStream::FrameSizeChange(unsigned int width, unsigned int height,
|
||||
unsigned int /*number_of_streams*/) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VideoReceiveStream::DeliverFrame(uint8_t* frame, int buffer_size,
|
||||
uint32_t time_stamp, int64_t render_time) {
|
||||
if (config_.renderer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
I420VideoFrame video_frame;
|
||||
video_frame.CreateEmptyFrame(width_, height_, width_, height_, height_);
|
||||
ConvertToI420(kI420, frame, 0, 0, width_, height_, buffer_size,
|
||||
webrtc::kRotateNone, &video_frame);
|
||||
|
||||
if (config_.post_decode_callback != NULL) {
|
||||
config_.post_decode_callback->FrameCallback(&video_frame);
|
||||
}
|
||||
|
||||
if (config_.renderer != NULL) {
|
||||
// TODO(pbos): Add timing to RenderFrame call
|
||||
config_.renderer
|
||||
->RenderFrame(video_frame, render_time - clock_->TimeInMilliseconds());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VideoReceiveStream::SendPacket(int /*channel*/, const void* packet,
|
||||
int length) {
|
||||
assert(length >= 0);
|
||||
return transport_->SendRTP(packet, static_cast<size_t>(length)) ? 0 : -1;
|
||||
}
|
||||
|
||||
int VideoReceiveStream::SendRTCPPacket(int /*channel*/, const void* packet,
|
||||
int length) {
|
||||
assert(length >= 0);
|
||||
return transport_->SendRTCP(packet, static_cast<size_t>(length)) ? 0 : -1;
|
||||
}
|
||||
} // internal
|
||||
} // webrtc
|
||||
83
webrtc/video_engine/internal/video_receive_stream.h
Normal file
83
webrtc/video_engine/internal/video_receive_stream.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_VIDEO_RECEIVE_STREAM_IMPL_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_VIDEO_RECEIVE_STREAM_IMPL_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
#include "webrtc/video_engine/new_include/video_receive_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VideoEngine;
|
||||
class ViEBase;
|
||||
class ViECodec;
|
||||
class ViENetwork;
|
||||
class ViERender;
|
||||
class ViERTP_RTCP;
|
||||
|
||||
namespace internal {
|
||||
|
||||
class VideoReceiveStream : public newapi::VideoReceiveStream,
|
||||
public webrtc::ExternalRenderer,
|
||||
public webrtc::Transport {
|
||||
public:
|
||||
VideoReceiveStream(webrtc::VideoEngine* video_engine,
|
||||
const newapi::VideoReceiveStreamConfig& config,
|
||||
newapi::Transport* transport);
|
||||
virtual ~VideoReceiveStream();
|
||||
|
||||
virtual void StartReceive() OVERRIDE;
|
||||
virtual void StopReceive() OVERRIDE;
|
||||
|
||||
virtual void GetCurrentReceiveCodec(VideoCodec* receive_codec) OVERRIDE;
|
||||
virtual void GetReceiveStatistics(newapi::ReceiveStatistics* statistics)
|
||||
OVERRIDE;
|
||||
|
||||
virtual bool DeliverRtcp(const void* packet, size_t length);
|
||||
virtual bool DeliverRtp(const void* packet, size_t length);
|
||||
|
||||
virtual int FrameSizeChange(unsigned int width, unsigned int height,
|
||||
unsigned int /*number_of_streams*/) OVERRIDE;
|
||||
|
||||
virtual int DeliverFrame(uint8_t* frame, int buffer_size, uint32_t time_stamp,
|
||||
int64_t render_time) OVERRIDE;
|
||||
|
||||
virtual int SendPacket(int /*channel*/, const void* packet, int length)
|
||||
OVERRIDE;
|
||||
|
||||
virtual int SendRTCPPacket(int /*channel*/, const void* packet, int length)
|
||||
OVERRIDE;
|
||||
|
||||
private:
|
||||
newapi::Transport* transport_;
|
||||
newapi::VideoReceiveStreamConfig config_;
|
||||
Clock* clock_;
|
||||
|
||||
ViEBase* video_engine_base_;
|
||||
ViECodec* codec_;
|
||||
ViENetwork* network_;
|
||||
ViERender* render_;
|
||||
ViERTP_RTCP* rtp_rtcp_;
|
||||
|
||||
int channel_;
|
||||
|
||||
// TODO(pbos): Remove VideoReceiveStream can operate on I420 frames directly.
|
||||
unsigned int height_;
|
||||
unsigned int width_;
|
||||
};
|
||||
} // internal
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_INTERNAL_VIDEO_RECEIVE_STREAM_H_
|
||||
145
webrtc/video_engine/internal/video_send_stream.cc
Normal file
145
webrtc/video_engine/internal/video_send_stream.cc
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/internal/video_send_stream.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/video_engine/include/vie_base.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_network.h"
|
||||
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
||||
#include "webrtc/video_engine/new_include/video_send_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace internal {
|
||||
|
||||
VideoSendStream::VideoSendStream(
|
||||
newapi::Transport* transport, webrtc::VideoEngine* video_engine,
|
||||
const newapi::VideoSendStreamConfig& send_stream_config)
|
||||
: transport_(transport), config_(send_stream_config) {
|
||||
|
||||
if (config_.codec.numberOfSimulcastStreams > 0) {
|
||||
assert(config_.rtp.ssrcs.size() == config_.codec.numberOfSimulcastStreams);
|
||||
} else {
|
||||
assert(config_.rtp.ssrcs.size() == 1);
|
||||
}
|
||||
|
||||
video_engine_base_ = ViEBase::GetInterface(video_engine);
|
||||
video_engine_base_->CreateChannel(channel_);
|
||||
assert(channel_ != -1);
|
||||
|
||||
rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
|
||||
assert(rtp_rtcp_ != NULL);
|
||||
|
||||
assert(config_.rtp.ssrcs.size() == 1);
|
||||
rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.ssrcs[0]);
|
||||
|
||||
capture_ = ViECapture::GetInterface(video_engine);
|
||||
capture_->AllocateExternalCaptureDevice(capture_id_, external_capture_);
|
||||
capture_->ConnectCaptureDevice(capture_id_, channel_);
|
||||
|
||||
network_ = ViENetwork::GetInterface(video_engine);
|
||||
assert(network_ != NULL);
|
||||
|
||||
network_->RegisterSendTransport(channel_, *this);
|
||||
|
||||
codec_ = ViECodec::GetInterface(video_engine);
|
||||
if (codec_->SetSendCodec(channel_, config_.codec) != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
VideoSendStream::~VideoSendStream() {
|
||||
network_->DeregisterSendTransport(channel_);
|
||||
video_engine_base_->DeleteChannel(channel_);
|
||||
|
||||
capture_->DisconnectCaptureDevice(channel_);
|
||||
capture_->ReleaseCaptureDevice(capture_id_);
|
||||
|
||||
video_engine_base_->Release();
|
||||
capture_->Release();
|
||||
codec_->Release();
|
||||
network_->Release();
|
||||
rtp_rtcp_->Release();
|
||||
}
|
||||
|
||||
void VideoSendStream::PutFrame(const I420VideoFrame& frame,
|
||||
int32_t delta_capture_time) {
|
||||
I420VideoFrame frame_copy;
|
||||
frame_copy.CopyFrame(frame);
|
||||
|
||||
if (config_.pre_encode_callback != NULL) {
|
||||
config_.pre_encode_callback->FrameCallback(&frame_copy);
|
||||
}
|
||||
|
||||
ViEVideoFrameI420 vf;
|
||||
|
||||
// TODO(pbos): This represents a memcpy step and is only required because
|
||||
// external_capture_ only takes ViEVideoFrameI420s.
|
||||
vf.y_plane = frame_copy.buffer(kYPlane);
|
||||
vf.u_plane = frame_copy.buffer(kUPlane);
|
||||
vf.v_plane = frame_copy.buffer(kVPlane);
|
||||
vf.y_pitch = frame.stride(kYPlane);
|
||||
vf.u_pitch = frame.stride(kUPlane);
|
||||
vf.v_pitch = frame.stride(kVPlane);
|
||||
vf.width = frame.width();
|
||||
vf.height = frame.height();
|
||||
|
||||
external_capture_->IncomingFrameI420(vf, frame.timestamp());
|
||||
|
||||
if (config_.local_renderer != NULL) {
|
||||
config_.local_renderer->RenderFrame(frame, 0);
|
||||
}
|
||||
}
|
||||
|
||||
newapi::VideoSendStreamInput* VideoSendStream::Input() { return this; }
|
||||
|
||||
void VideoSendStream::StartSend() {
|
||||
if (video_engine_base_->StartSend(channel_) != 0) abort();
|
||||
}
|
||||
|
||||
void VideoSendStream::StopSend() {
|
||||
if (video_engine_base_->StopSend(channel_) != 0) abort();
|
||||
}
|
||||
|
||||
void VideoSendStream::GetSendStatistics(
|
||||
std::vector<newapi::SendStatistics>* statistics) {
|
||||
// TODO(pbos): Implement
|
||||
}
|
||||
|
||||
bool VideoSendStream::SetTargetBitrate(
|
||||
int min_bitrate, int max_bitrate,
|
||||
const std::vector<SimulcastStream>& streams) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void VideoSendStream::GetSendCodec(VideoCodec* send_codec) {
|
||||
*send_codec = config_.codec;
|
||||
}
|
||||
|
||||
int VideoSendStream::SendPacket(int /*channel*/, const void* packet,
|
||||
int length) {
|
||||
// TODO(pbos): Lock these methods and the destructor so it can't be processing
|
||||
// a packet when the destructor has been called.
|
||||
assert(length >= 0);
|
||||
return transport_->SendRTP(packet, static_cast<size_t>(length)) ? 0 : -1;
|
||||
}
|
||||
|
||||
int VideoSendStream::SendRTCPPacket(int /*channel*/, const void* packet,
|
||||
int length) {
|
||||
assert(length >= 0);
|
||||
return transport_->SendRTCP(packet, static_cast<size_t>(length)) ? 0 : -1;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
82
webrtc/video_engine/internal/video_send_stream.h
Normal file
82
webrtc/video_engine/internal/video_send_stream.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_VIDEO_SEND_STREAM_IMPL_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_VIDEO_SEND_STREAM_IMPL_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/video_engine/new_include/video_send_stream.h"
|
||||
#include "webrtc/video_engine/new_include/video_receive_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VideoEngine;
|
||||
class ViEBase;
|
||||
class ViECapture;
|
||||
class ViECodec;
|
||||
class ViEExternalCapture;
|
||||
class ViENetwork;
|
||||
class ViERTP_RTCP;
|
||||
|
||||
namespace internal {
|
||||
class VideoSendStream : public newapi::VideoSendStream,
|
||||
public newapi::VideoSendStreamInput,
|
||||
public webrtc::Transport {
|
||||
public:
|
||||
VideoSendStream(newapi::Transport* transport,
|
||||
webrtc::VideoEngine* video_engine,
|
||||
const newapi::VideoSendStreamConfig& send_stream_config);
|
||||
|
||||
virtual ~VideoSendStream();
|
||||
|
||||
virtual void PutFrame(const I420VideoFrame& frame, int32_t delta_capture_time)
|
||||
OVERRIDE;
|
||||
|
||||
virtual newapi::VideoSendStreamInput* Input() OVERRIDE;
|
||||
|
||||
virtual void StartSend() OVERRIDE;
|
||||
|
||||
virtual void StopSend() OVERRIDE;
|
||||
|
||||
virtual void GetSendStatistics(
|
||||
std::vector<newapi::SendStatistics>* statistics) OVERRIDE;
|
||||
|
||||
virtual bool SetTargetBitrate(int min_bitrate, int max_bitrate,
|
||||
const std::vector<SimulcastStream>& streams)
|
||||
OVERRIDE;
|
||||
|
||||
virtual void GetSendCodec(VideoCodec* send_codec) OVERRIDE;
|
||||
|
||||
virtual int SendPacket(int /*channel*/, const void* packet, int length)
|
||||
OVERRIDE;
|
||||
|
||||
virtual int SendRTCPPacket(int /*channel*/, const void* packet, int length)
|
||||
OVERRIDE;
|
||||
|
||||
private:
|
||||
newapi::Transport* transport_;
|
||||
newapi::VideoSendStreamConfig config_;
|
||||
|
||||
ViEBase* video_engine_base_;
|
||||
ViECapture* capture_;
|
||||
ViECodec* codec_;
|
||||
ViEExternalCapture* external_capture_;
|
||||
ViENetwork* network_;
|
||||
ViERTP_RTCP* rtp_rtcp_;
|
||||
|
||||
int channel_;
|
||||
int capture_id_;
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_INTERNAL_VIDEO_SEND_STREAM_H_
|
||||
@ -19,7 +19,6 @@
|
||||
#include "webrtc/video_engine/new_include/video_receive_stream.h"
|
||||
#include "webrtc/video_engine/new_include/video_send_stream.h"
|
||||
|
||||
|
||||
namespace webrtc {
|
||||
namespace newapi {
|
||||
|
||||
@ -51,7 +50,7 @@ struct VideoEngineConfig {
|
||||
// estimates etc.
|
||||
class VideoCall {
|
||||
public:
|
||||
virtual void GetVideoCodecs(std::vector<VideoCodec>* codecs) = 0;
|
||||
virtual std::vector<VideoCodec> GetVideoCodecs() = 0;
|
||||
|
||||
virtual void GetDefaultSendConfig(VideoSendStreamConfig* config) = 0;
|
||||
|
||||
@ -82,7 +81,6 @@ class VideoCall {
|
||||
// differ from the actual receive bitrate.
|
||||
virtual uint32_t ReceiveBitrateEstimate() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VideoCall() {}
|
||||
};
|
||||
|
||||
@ -91,11 +89,9 @@ class VideoCall {
|
||||
class VideoEngine {
|
||||
public:
|
||||
static VideoEngine* Create(const VideoEngineConfig& engine_config);
|
||||
virtual ~VideoEngine() {}
|
||||
|
||||
virtual VideoCall* CreateCall(Transport* send_transport) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VideoEngine() {}
|
||||
};
|
||||
|
||||
} // namespace newapi
|
||||
|
||||
39
webrtc/video_engine/test/common/direct_transport.h
Normal file
39
webrtc/video_engine/test/common/direct_transport.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_DIRECT_TRANSPORT_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_DIRECT_TRANSPORT_H_
|
||||
|
||||
#include "webrtc/video_engine/new_include/common.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class DirectTransport : public newapi::Transport {
|
||||
public:
|
||||
explicit DirectTransport(newapi::PacketReceiver* receiver)
|
||||
: receiver_(receiver) {}
|
||||
|
||||
void SetReceiver(newapi::PacketReceiver* receiver) { receiver_ = receiver; }
|
||||
|
||||
bool SendRTP(const void* data, size_t length) OVERRIDE {
|
||||
return receiver_->DeliverPacket(data, length);
|
||||
}
|
||||
|
||||
bool SendRTCP(const void* data, size_t length) OVERRIDE {
|
||||
return SendRTP(data, length);
|
||||
}
|
||||
|
||||
private:
|
||||
newapi::PacketReceiver* receiver_;
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_DIRECT_TRANSPORT_H_
|
||||
51
webrtc/video_engine/test/common/generate_ssrcs.h
Normal file
51
webrtc/video_engine/test/common/generate_ssrcs.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_GENERATE_SSRCS_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_GENERATE_SSRCS_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/video_engine/new_include/video_send_stream.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
void GenerateRandomSsrcs(newapi::VideoSendStreamConfig* config,
|
||||
std::map<uint32_t, bool>* reserved_ssrcs) {
|
||||
size_t num_ssrcs = config->codec.numberOfSimulcastStreams;
|
||||
std::vector<uint32_t>* ssrcs = &config->rtp.ssrcs;
|
||||
assert(ssrcs->size() == 0);
|
||||
|
||||
if (num_ssrcs == 0) {
|
||||
num_ssrcs = 1;
|
||||
}
|
||||
|
||||
while (ssrcs->size() < num_ssrcs) {
|
||||
uint32_t rand_ssrc = static_cast<uint32_t>(rand() + 1); // NOLINT
|
||||
|
||||
// Make sure the ssrc is unique per-call
|
||||
while (true) {
|
||||
if (!(*reserved_ssrcs)[rand_ssrc]) {
|
||||
(*reserved_ssrcs)[rand_ssrc] = true;
|
||||
break;
|
||||
}
|
||||
++rand_ssrc;
|
||||
}
|
||||
|
||||
ssrcs->push_back(rand_ssrc);
|
||||
}
|
||||
}
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_GENERATE_SSRCS_H_
|
||||
112
webrtc/video_engine/test/common/gl/gl_renderer.cc
Normal file
112
webrtc/video_engine/test/common/gl/gl_renderer.cc
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/test/common/gl/gl_renderer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
GlRenderer::GlRenderer()
|
||||
: is_init_(false), buffer_(NULL), width_(0), height_(0) {}
|
||||
|
||||
void GlRenderer::Init() {
|
||||
assert(!is_init_);
|
||||
is_init_ = true;
|
||||
|
||||
glGenTextures(1, &texture_);
|
||||
}
|
||||
|
||||
void GlRenderer::Destroy() {
|
||||
if (!is_init_) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_init_ = false;
|
||||
|
||||
delete[] buffer_;
|
||||
buffer_ = NULL;
|
||||
|
||||
glDeleteTextures(1, &texture_);
|
||||
}
|
||||
|
||||
void GlRenderer::ResizeViewport(size_t width, size_t height) {
|
||||
// TODO(pbos): Aspect ratio, letterbox the video.
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glOrtho(0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void GlRenderer::ResizeVideo(size_t width, size_t height) {
|
||||
assert(is_init_);
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
|
||||
buffer_size_ = width * height * 4; // BGRA
|
||||
|
||||
delete[] buffer_;
|
||||
buffer_ = new uint8_t[buffer_size_];
|
||||
assert(buffer_ != NULL);
|
||||
memset(buffer_, 0, buffer_size_);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8, static_cast<GLvoid*>(buffer_));
|
||||
}
|
||||
|
||||
void GlRenderer::RenderFrame(const webrtc::I420VideoFrame& frame,
|
||||
int /*render_delay_ms*/) {
|
||||
assert(is_init_);
|
||||
|
||||
if (static_cast<size_t>(frame.width()) != width_ ||
|
||||
static_cast<size_t>(frame.height()) != height_) {
|
||||
ResizeVideo(frame.width(), frame.height());
|
||||
}
|
||||
|
||||
webrtc::ConvertFromI420(frame, kBGRA, 0, buffer_);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8, buffer_);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
{
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glVertex3f(0.0f, 1.0f, 0.0f);
|
||||
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, 0.0f);
|
||||
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex3f(1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glFlush();
|
||||
}
|
||||
} // test
|
||||
} // webrtc
|
||||
45
webrtc/video_engine/test/common/gl/gl_renderer.h
Normal file
45
webrtc/video_engine/test/common/gl/gl_renderer.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_GL_GL_RENDERER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_GL_GL_RENDERER_H_
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "webrtc/video_engine/test/common/video_renderer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class GlRenderer : public VideoRenderer {
|
||||
public:
|
||||
virtual void RenderFrame(const webrtc::I420VideoFrame& frame,
|
||||
int time_to_render_ms) OVERRIDE;
|
||||
|
||||
protected:
|
||||
GlRenderer();
|
||||
|
||||
void Init();
|
||||
void Destroy();
|
||||
|
||||
void ResizeViewport(size_t width, size_t height);
|
||||
|
||||
private:
|
||||
bool is_init_;
|
||||
uint8_t* buffer_;
|
||||
GLuint texture_;
|
||||
size_t width_, height_, buffer_size_;
|
||||
|
||||
void ResizeVideo(size_t width, size_t height);
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_GL_GL_RENDERER_H_
|
||||
180
webrtc/video_engine/test/common/linux/glx_renderer.cc
Normal file
180
webrtc/video_engine/test/common/linux/glx_renderer.cc
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/test/common/linux/glx_renderer.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
GlxRenderer::GlxRenderer(size_t width, size_t height)
|
||||
: is_init_(false),
|
||||
width_(width),
|
||||
height_(height),
|
||||
display_(NULL),
|
||||
context_(NULL) {
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
}
|
||||
|
||||
bool GlxRenderer::Init(const char* window_title) {
|
||||
if ((display_ = XOpenDisplay(NULL)) == NULL) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
int screen = DefaultScreen(display_);
|
||||
|
||||
XVisualInfo* vi;
|
||||
int attr_list[] = { GLX_DOUBLEBUFFER, GLX_RGBA, GLX_RED_SIZE, 4,
|
||||
GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16,
|
||||
None, };
|
||||
|
||||
if ((vi = glXChooseVisual(display_, screen, attr_list)) == NULL) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
context_ = glXCreateContext(display_, vi, 0, true);
|
||||
if (context_ == NULL) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
XSetWindowAttributes window_attributes;
|
||||
window_attributes.colormap = XCreateColormap(
|
||||
display_, RootWindow(display_, vi->screen), vi->visual, AllocNone);
|
||||
window_attributes.border_pixel = 0;
|
||||
window_attributes.event_mask = StructureNotifyMask | ExposureMask;
|
||||
window_ = XCreateWindow(display_, RootWindow(display_, vi->screen), 0, 0,
|
||||
width_, height_, 0, vi->depth, InputOutput,
|
||||
vi->visual, CWBorderPixel | CWColormap | CWEventMask,
|
||||
&window_attributes);
|
||||
XFree(vi);
|
||||
|
||||
XSetStandardProperties(display_, window_, window_title, window_title, None,
|
||||
NULL, 0, NULL);
|
||||
|
||||
Atom wm_delete = XInternAtom(display_, "WM_DELETE_WINDOW", True);
|
||||
if (wm_delete != None) {
|
||||
XSetWMProtocols(display_, window_, &wm_delete, 1);
|
||||
}
|
||||
|
||||
XMapRaised(display_, window_);
|
||||
|
||||
if (!glXMakeCurrent(display_, window_, context_)) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
GlRenderer::Init();
|
||||
if (!glXMakeCurrent(display_, None, NULL)) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
Resize(width_, height_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlxRenderer::Destroy() {
|
||||
if (!is_init_) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_init_ = false;
|
||||
|
||||
if (context_ != NULL) {
|
||||
glXMakeCurrent(display_, window_, context_);
|
||||
GlRenderer::Destroy();
|
||||
glXMakeCurrent(display_, None, NULL);
|
||||
glXDestroyContext(display_, context_);
|
||||
context_ = NULL;
|
||||
}
|
||||
|
||||
if (display_ != NULL) {
|
||||
XCloseDisplay(display_);
|
||||
display_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GlxRenderer* GlxRenderer::Create(const char* window_title, size_t width,
|
||||
size_t height) {
|
||||
GlxRenderer* glx_renderer = new GlxRenderer(width, height);
|
||||
if (!glx_renderer->Init(window_title)) {
|
||||
// TODO(pbos): Add GLX-failed warning here?
|
||||
delete glx_renderer;
|
||||
return NULL;
|
||||
}
|
||||
return glx_renderer;
|
||||
}
|
||||
|
||||
GlxRenderer::~GlxRenderer() { Destroy(); }
|
||||
|
||||
void GlxRenderer::Resize(size_t width, size_t height) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
if (!glXMakeCurrent(display_, window_, context_)) {
|
||||
abort();
|
||||
}
|
||||
GlRenderer::ResizeViewport(width_, height_);
|
||||
if (!glXMakeCurrent(display_, None, NULL)) {
|
||||
abort();
|
||||
}
|
||||
|
||||
XSizeHints* size_hints = XAllocSizeHints();
|
||||
if (size_hints == NULL) {
|
||||
abort();
|
||||
}
|
||||
size_hints->flags = PAspect;
|
||||
size_hints->min_aspect.x = size_hints->max_aspect.x = width_;
|
||||
size_hints->min_aspect.y = size_hints->max_aspect.y = height_;
|
||||
XSetWMNormalHints(display_, window_, size_hints);
|
||||
XFree(size_hints);
|
||||
}
|
||||
|
||||
void GlxRenderer::RenderFrame(const webrtc::I420VideoFrame& frame,
|
||||
int /*render_delay_ms*/) {
|
||||
if (static_cast<size_t>(frame.width()) != width_ ||
|
||||
static_cast<size_t>(frame.height()) != height_) {
|
||||
Resize(static_cast<size_t>(frame.width()),
|
||||
static_cast<size_t>(frame.height()));
|
||||
}
|
||||
|
||||
XEvent event;
|
||||
if (!glXMakeCurrent(display_, window_, context_)) {
|
||||
abort();
|
||||
}
|
||||
while (XPending(display_)) {
|
||||
XNextEvent(display_, &event);
|
||||
switch (event.type) {
|
||||
case ConfigureNotify:
|
||||
GlRenderer::ResizeViewport(event.xconfigure.width,
|
||||
event.xconfigure.height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GlRenderer::RenderFrame(frame, 0);
|
||||
glXSwapBuffers(display_, window_);
|
||||
|
||||
if (!glXMakeCurrent(display_, None, NULL)) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
} // test
|
||||
} // webrtc
|
||||
47
webrtc/video_engine/test/common/linux/glx_renderer.h
Normal file
47
webrtc/video_engine/test/common/linux/glx_renderer.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_LINUX_GLX_RENDERER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_LINUX_GLX_RENDERER_H_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include "webrtc/video_engine/test/common/gl/gl_renderer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class GlxRenderer : public GlRenderer {
|
||||
public:
|
||||
static GlxRenderer* Create(const char* window_title, size_t width,
|
||||
size_t height);
|
||||
virtual ~GlxRenderer();
|
||||
|
||||
virtual void RenderFrame(const webrtc::I420VideoFrame& frame, int delta)
|
||||
OVERRIDE;
|
||||
private:
|
||||
GlxRenderer(size_t width, size_t height);
|
||||
|
||||
bool Init(const char* window_title);
|
||||
void Resize(size_t width, size_t height);
|
||||
void Destroy();
|
||||
|
||||
bool is_init_;
|
||||
size_t width_, height_;
|
||||
|
||||
Display* display_;
|
||||
Window window_;
|
||||
GLXContext context_;
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_LINUX_GLX_RENDERER_H_
|
||||
210
webrtc/video_engine/test/common/linux/xv_renderer.cc
Normal file
210
webrtc/video_engine/test/common/linux/xv_renderer.cc
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/test/common/linux/xv_renderer.h"
|
||||
|
||||
#include <sys/shm.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/Xvlib.h>
|
||||
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
|
||||
#define GUID_I420_PLANAR 0x30323449
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
XvRenderer::XvRenderer(size_t width, size_t height)
|
||||
: width(width),
|
||||
height(height),
|
||||
is_init(false),
|
||||
display(NULL),
|
||||
gc(NULL),
|
||||
image(NULL) {
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
}
|
||||
|
||||
bool XvRenderer::Init(const char* window_title) {
|
||||
assert(!is_init);
|
||||
is_init = true;
|
||||
if ((display = XOpenDisplay(NULL)) == NULL) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
int screen = DefaultScreen(display);
|
||||
|
||||
XVisualInfo vinfo;
|
||||
if (!XMatchVisualInfo(display, screen, 24, TrueColor, &vinfo)) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
XSetWindowAttributes xswa;
|
||||
xswa.colormap = XCreateColormap(display, DefaultRootWindow(display),
|
||||
vinfo.visual, AllocNone);
|
||||
xswa.event_mask = StructureNotifyMask | ExposureMask;
|
||||
xswa.background_pixel = 0;
|
||||
xswa.border_pixel = 0;
|
||||
|
||||
window = XCreateWindow(display, DefaultRootWindow(display), 0, 0, width,
|
||||
height, 0, vinfo.depth, InputOutput, vinfo.visual,
|
||||
CWBackPixel | CWBorderPixel | CWColormap | CWEventMask,
|
||||
&xswa);
|
||||
|
||||
XStoreName(display, window, window_title);
|
||||
XSetIconName(display, window, window_title);
|
||||
|
||||
XSelectInput(display, window, StructureNotifyMask);
|
||||
|
||||
XMapRaised(display, window);
|
||||
|
||||
XEvent event;
|
||||
do {
|
||||
XNextEvent(display, &event);
|
||||
} while (event.type != MapNotify || event.xmap.event != window);
|
||||
|
||||
if (!XShmQueryExtension(display)) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
xv_complete = XShmGetEventBase(display) + ShmCompletion;
|
||||
|
||||
XvAdaptorInfo* ai;
|
||||
unsigned int p_num_adaptors;
|
||||
|
||||
if (XvQueryAdaptors(display, DefaultRootWindow(display), &p_num_adaptors,
|
||||
&ai) !=
|
||||
Success) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
if (p_num_adaptors <= 0) {
|
||||
XvFreeAdaptorInfo(ai);
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
xv_port = ai[p_num_adaptors - 1].base_id;
|
||||
XvFreeAdaptorInfo(ai);
|
||||
|
||||
if (xv_port == -1) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
gc = XCreateGC(display, window, 0, 0);
|
||||
if (gc == NULL) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
Resize(width, height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XvRenderer::Destroy() {
|
||||
if (image != NULL) {
|
||||
XFree(image);
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
if (gc != NULL) {
|
||||
XFreeGC(display, gc);
|
||||
gc = NULL;
|
||||
}
|
||||
|
||||
if (display != NULL) {
|
||||
XCloseDisplay(display);
|
||||
display = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
XvRenderer* XvRenderer::Create(const char* window_title, size_t width,
|
||||
size_t height) {
|
||||
XvRenderer* xv_renderer = new XvRenderer(width, height);
|
||||
if (!xv_renderer->Init(window_title)) {
|
||||
// TODO(pbos): Add Xv-failed warning here?
|
||||
delete xv_renderer;
|
||||
return NULL;
|
||||
}
|
||||
return xv_renderer;
|
||||
}
|
||||
|
||||
XvRenderer::~XvRenderer() { Destroy(); }
|
||||
|
||||
void XvRenderer::Resize(size_t width, size_t height) {
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
|
||||
if (image != NULL) {
|
||||
XFree(image);
|
||||
}
|
||||
image = XvShmCreateImage(display, xv_port, GUID_I420_PLANAR, 0, width, height,
|
||||
&shm_info);
|
||||
assert(image != NULL);
|
||||
|
||||
shm_info.shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
|
||||
shm_info.shmaddr = image->data =
|
||||
reinterpret_cast<char*>(shmat(shm_info.shmid, 0, 0));
|
||||
shm_info.readOnly = False;
|
||||
|
||||
if (!XShmAttach(display, &shm_info)) {
|
||||
abort();
|
||||
}
|
||||
|
||||
XSizeHints* size_hints = XAllocSizeHints();
|
||||
if (size_hints == NULL) {
|
||||
abort();
|
||||
}
|
||||
size_hints->flags = PAspect;
|
||||
size_hints->min_aspect.x = size_hints->max_aspect.x = width;
|
||||
size_hints->min_aspect.y = size_hints->max_aspect.y = height;
|
||||
XSetWMNormalHints(display, window, size_hints);
|
||||
XFree(size_hints);
|
||||
|
||||
XWindowChanges wc;
|
||||
wc.width = width;
|
||||
wc.height = height;
|
||||
XConfigureWindow(display, window, CWWidth | CWHeight, &wc);
|
||||
}
|
||||
|
||||
void XvRenderer::RenderFrame(const webrtc::I420VideoFrame& frame,
|
||||
int /*render_delay_ms*/) {
|
||||
int size = webrtc::ExtractBuffer(frame, image->data_size,
|
||||
reinterpret_cast<uint8_t*>(image->data));
|
||||
if (static_cast<size_t>(frame.width()) != width ||
|
||||
static_cast<size_t>(frame.height()) != height) {
|
||||
Resize(static_cast<size_t>(frame.width()),
|
||||
static_cast<size_t>(frame.height()));
|
||||
}
|
||||
assert(size > 0);
|
||||
Window root;
|
||||
int temp;
|
||||
unsigned int window_width, window_height, u_temp;
|
||||
|
||||
XGetGeometry(display, window, &root, &temp, &temp, &window_width,
|
||||
&window_height, &u_temp, &u_temp);
|
||||
|
||||
XvShmPutImage(display, xv_port, window, gc, image, 0, 0, image->width,
|
||||
image->height, 0, 0, window_width, window_height, True);
|
||||
|
||||
XFlush(display);
|
||||
|
||||
XEvent event;
|
||||
while (XPending(display)) {
|
||||
XNextEvent(display, &event);
|
||||
}
|
||||
}
|
||||
} // test
|
||||
} // webrtc
|
||||
54
webrtc/video_engine/test/common/linux/xv_renderer.h
Normal file
54
webrtc/video_engine/test/common/linux/xv_renderer.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_LINUX_XV_RENDERER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_LINUX_XV_RENDERER_H_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include <X11/extensions/Xvlib.h>
|
||||
|
||||
#include "webrtc/video_engine/new_include/common.h"
|
||||
#include "webrtc/video_engine/test/common/video_renderer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class XvRenderer : public VideoRenderer {
|
||||
public:
|
||||
~XvRenderer();
|
||||
|
||||
virtual void RenderFrame(const webrtc::I420VideoFrame& frame, int delta)
|
||||
OVERRIDE;
|
||||
|
||||
static XvRenderer* Create(const char *window_title, size_t width,
|
||||
size_t height);
|
||||
|
||||
private:
|
||||
XvRenderer(size_t width, size_t height);
|
||||
|
||||
bool Init(const char *window_title);
|
||||
void Resize(size_t width, size_t height);
|
||||
void Destroy();
|
||||
|
||||
size_t width, height;
|
||||
bool is_init;
|
||||
|
||||
Display* display;
|
||||
Window window;
|
||||
GC gc;
|
||||
XvImage* image;
|
||||
XShmSegmentInfo shm_info;
|
||||
int xv_port, xv_complete;
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_LINUX_XV_RENDERER_H_
|
||||
108
webrtc/video_engine/test/common/vcm_capturer.cc
Normal file
108
webrtc/video_engine/test/common/vcm_capturer.cc
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/test/common/vcm_capturer.h"
|
||||
|
||||
#include "webrtc/modules/video_capture/include/video_capture_factory.h"
|
||||
#include "webrtc/video_engine/new_include/video_send_stream.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
VcmCapturer::VcmCapturer(webrtc::newapi::VideoSendStreamInput* input)
|
||||
: VideoCapturer(input), started_(false), vcm(NULL), last_timestamp(0) {}
|
||||
|
||||
bool VcmCapturer::Init(size_t width, size_t height, size_t target_fps) {
|
||||
VideoCaptureModule::DeviceInfo* device_info =
|
||||
VideoCaptureFactory::CreateDeviceInfo(42); // Any ID (42) will do.
|
||||
|
||||
char device_name[256];
|
||||
char unique_name[256];
|
||||
if (device_info->GetDeviceName(0, device_name, sizeof(device_name),
|
||||
unique_name, sizeof(unique_name)) !=
|
||||
0) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
vcm = webrtc::VideoCaptureFactory::Create(0, unique_name);
|
||||
vcm->RegisterCaptureDataCallback(*this);
|
||||
|
||||
device_info->GetCapability(vcm->CurrentDeviceName(), 0, capability_);
|
||||
delete device_info;
|
||||
|
||||
capability_.width = static_cast<int32_t>(width);
|
||||
capability_.height = static_cast<int32_t>(height);
|
||||
capability_.maxFPS = static_cast<int32_t>(target_fps);
|
||||
capability_.rawType = kVideoI420;
|
||||
|
||||
if (vcm->StartCapture(capability_) != 0) {
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(vcm->CaptureStarted());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VcmCapturer* VcmCapturer::Create(newapi::VideoSendStreamInput* input,
|
||||
size_t width, size_t height,
|
||||
size_t target_fps) {
|
||||
VcmCapturer* vcm_capturer = new VcmCapturer(input);
|
||||
if (!vcm_capturer->Init(width, height, target_fps)) {
|
||||
// TODO(pbos): Log a warning that this failed.
|
||||
delete vcm_capturer;
|
||||
return NULL;
|
||||
}
|
||||
return vcm_capturer;
|
||||
}
|
||||
|
||||
|
||||
void VcmCapturer::Start() { started_ = true; }
|
||||
|
||||
void VcmCapturer::Stop() { started_ = false; }
|
||||
|
||||
void VcmCapturer::Destroy() {
|
||||
if (vcm == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
vcm->StopCapture();
|
||||
vcm->DeRegisterCaptureDataCallback();
|
||||
vcm->Release();
|
||||
|
||||
// TODO(pbos): How do I destroy the VideoCaptureModule? This still leaves
|
||||
// non-freed memory.
|
||||
vcm = NULL;
|
||||
}
|
||||
|
||||
VcmCapturer::~VcmCapturer() { Destroy(); }
|
||||
|
||||
void VcmCapturer::OnIncomingCapturedFrame(const int32_t id,
|
||||
I420VideoFrame& frame) {
|
||||
if (last_timestamp == 0 || frame.timestamp() < last_timestamp) {
|
||||
last_timestamp = frame.timestamp();
|
||||
}
|
||||
|
||||
if (started_) {
|
||||
input_->PutFrame(frame, frame.timestamp() - last_timestamp);
|
||||
}
|
||||
last_timestamp = frame.timestamp();
|
||||
}
|
||||
|
||||
void VcmCapturer::OnIncomingCapturedEncodedFrame(const int32_t id,
|
||||
VideoFrame& frame,
|
||||
VideoCodecType codec_type) {}
|
||||
|
||||
void VcmCapturer::OnCaptureDelayChanged(const int32_t id, const int32_t delay) {
|
||||
}
|
||||
} // test
|
||||
} // webrtc
|
||||
53
webrtc/video_engine/test/common/vcm_capturer.h
Normal file
53
webrtc/video_engine/test/common/vcm_capturer.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_VCM_CAPTURER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_VCM_CAPTURER_H_
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/modules/video_capture/include/video_capture.h"
|
||||
#include "webrtc/video_engine/test/common/video_capturer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class VcmCapturer : public VideoCapturer, public VideoCaptureDataCallback {
|
||||
public:
|
||||
static VcmCapturer* Create(newapi::VideoSendStreamInput* input, size_t width,
|
||||
size_t height, size_t target_fps);
|
||||
virtual ~VcmCapturer();
|
||||
|
||||
virtual void Start() OVERRIDE;
|
||||
virtual void Stop() OVERRIDE;
|
||||
|
||||
virtual void OnIncomingCapturedFrame(const int32_t id, I420VideoFrame& frame)
|
||||
OVERRIDE;
|
||||
virtual void OnIncomingCapturedEncodedFrame(const int32_t id,
|
||||
VideoFrame& frame,
|
||||
VideoCodecType codec_type)
|
||||
OVERRIDE;
|
||||
virtual void OnCaptureDelayChanged(const int32_t id, const int32_t delay)
|
||||
OVERRIDE;
|
||||
|
||||
private:
|
||||
explicit VcmCapturer(newapi::VideoSendStreamInput* input);
|
||||
bool Init(size_t width, size_t height, size_t target_fps);
|
||||
void Destroy();
|
||||
|
||||
bool started_;
|
||||
VideoCaptureModule* vcm;
|
||||
VideoCaptureCapability capability_;
|
||||
|
||||
uint32_t last_timestamp;
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_VCM_CAPTURER_H_
|
||||
47
webrtc/video_engine/test/common/video_capturer.cc
Normal file
47
webrtc/video_engine/test/common/video_capturer.cc
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/test/common/video_capturer.h"
|
||||
#include "webrtc/video_engine/test/common/vcm_capturer.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class NullCapturer : public VideoCapturer {
|
||||
public:
|
||||
NullCapturer() : VideoCapturer(NULL) {}
|
||||
virtual ~NullCapturer() {}
|
||||
|
||||
virtual void Start() {}
|
||||
virtual void Stop() {}
|
||||
};
|
||||
|
||||
VideoCapturer::VideoCapturer(newapi::VideoSendStreamInput* input)
|
||||
: input_(input) {}
|
||||
|
||||
VideoCapturer* VideoCapturer::Create(newapi::VideoSendStreamInput* input) {
|
||||
// TODO(pbos): These should be specified by command-line parameters.
|
||||
size_t width = 640;
|
||||
size_t height = 480;
|
||||
size_t target_fps = 30;
|
||||
|
||||
VcmCapturer* vcm_capturer = VcmCapturer::Create(input, width, height,
|
||||
target_fps);
|
||||
if (vcm_capturer != NULL) {
|
||||
return vcm_capturer;
|
||||
}
|
||||
// TODO(pbos): Log a warning that this failed.
|
||||
|
||||
// TODO(pbos): Add a pseudocapturer which generates frames.
|
||||
|
||||
return new NullCapturer();
|
||||
}
|
||||
} // test
|
||||
} // webrtc
|
||||
36
webrtc/video_engine/test/common/video_capturer.h
Normal file
36
webrtc/video_engine/test/common/video_capturer.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_CAPTURER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_CAPTURER_H_
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace newapi {
|
||||
class VideoSendStreamInput;
|
||||
} // newapi
|
||||
|
||||
namespace test {
|
||||
|
||||
class VideoCapturer {
|
||||
public:
|
||||
static VideoCapturer* Create(newapi::VideoSendStreamInput* input);
|
||||
virtual ~VideoCapturer() {}
|
||||
|
||||
virtual void Start() = 0;
|
||||
virtual void Stop() = 0;
|
||||
|
||||
protected:
|
||||
explicit VideoCapturer(newapi::VideoSendStreamInput* input);
|
||||
newapi::VideoSendStreamInput* input_;
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_CAPTURER_H
|
||||
63
webrtc/video_engine/test/common/video_renderer.cc
Normal file
63
webrtc/video_engine/test/common/video_renderer.cc
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/video_engine/test/common/video_renderer.h"
|
||||
|
||||
#include "webrtc/modules/video_capture/include/video_capture_factory.h"
|
||||
#include "webrtc/video_engine/new_include/video_send_stream.h"
|
||||
|
||||
#ifdef WEBRTC_TEST_XV
|
||||
#include "webrtc/video_engine/test/common/linux/xv_renderer.h"
|
||||
#endif // WEBRTC_TEST_XV
|
||||
|
||||
// Platform-specific renderers preferred over NullRenderer
|
||||
#ifdef WEBRTC_TEST_GLX
|
||||
#include "webrtc/video_engine/test/common/linux/glx_renderer.h"
|
||||
#endif // WEBRTC_TEST_GLX
|
||||
|
||||
// TODO(pbos): Mac renderer
|
||||
// TODO(pbos): Windows renderer
|
||||
// TODO(pbos): Android renderer
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class NullRenderer : public VideoRenderer {
|
||||
virtual void RenderFrame(const I420VideoFrame& video_frame,
|
||||
int time_to_render_ms) OVERRIDE {}
|
||||
};
|
||||
|
||||
VideoRenderer* VideoRenderer::Create(const char* window_title) {
|
||||
// TODO(pbos): Get these from command-line parameters.
|
||||
int width = 640;
|
||||
int height = 480;
|
||||
|
||||
#ifdef WEBRTC_TEST_XV
|
||||
XvRenderer* xv_renderer = XvRenderer::Create(window_title, width, height);
|
||||
if (xv_renderer != NULL) {
|
||||
return xv_renderer;
|
||||
}
|
||||
#endif // WEBRTC_TEST_XV
|
||||
#ifdef WEBRTC_TEST_GLX
|
||||
GlxRenderer* glx_renderer = GlxRenderer::Create(window_title, width, height);
|
||||
if (glx_renderer != NULL) {
|
||||
return glx_renderer;
|
||||
}
|
||||
#endif // WEBRTC_TEST_GLX
|
||||
|
||||
// Avoid initialized-but-not-referenced errors when only building a
|
||||
// NullRenderer
|
||||
(void) width;
|
||||
(void) height;
|
||||
|
||||
return new NullRenderer();
|
||||
}
|
||||
} // test
|
||||
} // webrtc
|
||||
26
webrtc/video_engine/test/common/video_renderer.h
Normal file
26
webrtc/video_engine/test/common/video_renderer.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_RENDERER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_RENDERER_H_
|
||||
|
||||
#include "webrtc/video_engine/new_include/common.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class VideoRenderer : public newapi::VideoRenderer {
|
||||
public:
|
||||
static VideoRenderer* Create(const char* window_title);
|
||||
virtual ~VideoRenderer() {}
|
||||
};
|
||||
} // test
|
||||
} // webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_COMMON_VIDEO_RENDERER_H_
|
||||
103
webrtc/video_engine/test/loopback.cc
Normal file
103
webrtc/video_engine/test/loopback.cc
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include "webrtc/video_engine/new_include/video_engine.h"
|
||||
#include "webrtc/video_engine/test/common/direct_transport.h"
|
||||
#include "webrtc/video_engine/test/common/generate_ssrcs.h"
|
||||
#include "webrtc/video_engine/test/common/video_capturer.h"
|
||||
#include "webrtc/video_engine/test/common/video_renderer.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class LoopbackTest : public ::testing::Test {
|
||||
protected:
|
||||
std::map<uint32_t, bool> reserved_ssrcs;
|
||||
};
|
||||
|
||||
TEST_F(LoopbackTest, Test) {
|
||||
test::VideoRenderer* local_preview =
|
||||
test::VideoRenderer::Create("Local Preview");
|
||||
test::VideoRenderer* loopback_video =
|
||||
test::VideoRenderer::Create("Loopback Video");
|
||||
|
||||
newapi::VideoEngine* video_engine =
|
||||
newapi::VideoEngine::Create(webrtc::newapi::VideoEngineConfig());
|
||||
|
||||
test::DirectTransport transport(NULL);
|
||||
newapi::VideoCall* call = video_engine->CreateCall(&transport);
|
||||
|
||||
// Loopback, call sends to itself.
|
||||
transport.SetReceiver(call->Receiver());
|
||||
|
||||
newapi::VideoSendStreamConfig send_config;
|
||||
call->GetDefaultSendConfig(&send_config);
|
||||
test::GenerateRandomSsrcs(&send_config, &reserved_ssrcs);
|
||||
|
||||
send_config.local_renderer = local_preview;
|
||||
|
||||
// TODO(pbos): Should be specified by command-line parameters. And not even
|
||||
// visible in the test. Break it out to some get-test-defaults
|
||||
// class
|
||||
send_config.codec.width = 640;
|
||||
send_config.codec.height = 480;
|
||||
send_config.codec.minBitrate = 1000;
|
||||
send_config.codec.startBitrate = 1500;
|
||||
send_config.codec.maxBitrate = 2000;
|
||||
|
||||
newapi::VideoSendStream* send_stream = call->CreateSendStream(send_config);
|
||||
|
||||
test::VideoCapturer* camera =
|
||||
test::VideoCapturer::Create(send_stream->Input());
|
||||
|
||||
newapi::VideoReceiveStreamConfig receive_config;
|
||||
call->GetDefaultReceiveConfig(&receive_config);
|
||||
receive_config.rtp.ssrc = send_config.rtp.ssrcs[0];
|
||||
receive_config.renderer = loopback_video;
|
||||
|
||||
newapi::VideoReceiveStream* receive_stream =
|
||||
call->CreateReceiveStream(receive_config);
|
||||
|
||||
receive_stream->StartReceive();
|
||||
send_stream->StartSend();
|
||||
|
||||
camera->Start();
|
||||
|
||||
// TODO(pbos): Run this time limited (optionally), so it can run automated.
|
||||
std::cout << ">> Press ENTER to continue..." << std::endl;
|
||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
receive_stream->StopReceive();
|
||||
send_stream->StopSend();
|
||||
|
||||
// Stop sending
|
||||
delete camera;
|
||||
|
||||
call->DestroyReceiveStream(receive_stream);
|
||||
call->DestroySendStream(send_stream);
|
||||
|
||||
delete call;
|
||||
delete video_engine;
|
||||
|
||||
delete loopback_video;
|
||||
delete local_preview;
|
||||
}
|
||||
} // webrtc
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
115
webrtc/video_engine/test/tests.gypi
Normal file
115
webrtc/video_engine/test/tests.gypi
Normal file
@ -0,0 +1,115 @@
|
||||
# Copyright (c) 2013 The WebRTC project authors.All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS.All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'xv_renderer%': 0,
|
||||
},
|
||||
'conditions': [
|
||||
['OS=="linux"', {
|
||||
'variables': {
|
||||
'glx_renderer%': 1,
|
||||
},
|
||||
}, {
|
||||
# OS != "linux"
|
||||
'variables': {
|
||||
'glx_renderer%': 0,
|
||||
},
|
||||
}],
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'video_tests_common',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'common/generate_ssrcs.h',
|
||||
'common/vcm_capturer.h',
|
||||
'common/vcm_capturer.cc',
|
||||
'common/video_capturer.cc',
|
||||
'common/video_capturer.h',
|
||||
'common/video_renderer.cc',
|
||||
'common/video_renderer.h',
|
||||
],
|
||||
'conditions': [
|
||||
['glx_renderer==1', {
|
||||
'defines': [
|
||||
'WEBRTC_TEST_GLX',
|
||||
],
|
||||
'sources' : [
|
||||
'common/gl/gl_renderer.cc',
|
||||
'common/gl/gl_renderer.h',
|
||||
'common/linux/glx_renderer.cc',
|
||||
'common/linux/glx_renderer.h',
|
||||
],
|
||||
}],
|
||||
['xv_renderer==1', {
|
||||
'defines': [
|
||||
'WEBRTC_TEST_XV',
|
||||
],
|
||||
'sources': [
|
||||
'common/linux/xv_renderer.cc',
|
||||
'common/linux/xv_renderer.h',
|
||||
],
|
||||
}],
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'conditions': [
|
||||
['OS=="linux"', {
|
||||
'libraries': [
|
||||
'-lXext',
|
||||
'-lX11',
|
||||
'-lGL',
|
||||
],
|
||||
}],
|
||||
['xv_renderer==1', {
|
||||
'libraries': [
|
||||
'-lXv',
|
||||
],
|
||||
}],
|
||||
#TODO(pbos) : These dependencies should not have to be here, they
|
||||
# aren't used by test code directly, only by components
|
||||
# used by the tests.
|
||||
['OS=="android"', {
|
||||
'libraries' : [
|
||||
'-lGLESv2', '-llog',
|
||||
],
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
'xcode_settings' : {
|
||||
'OTHER_LDFLAGS' : [
|
||||
'-framework Foundation',
|
||||
'-framework AppKit',
|
||||
'-framework Cocoa',
|
||||
'-framework OpenGL',
|
||||
'-framework CoreVideo',
|
||||
'-framework CoreAudio',
|
||||
'-framework AudioToolbox',
|
||||
],
|
||||
},
|
||||
}],
|
||||
],
|
||||
},
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/modules/modules.gyp:video_capture_module',
|
||||
'video_engine_core',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'video_loopback',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'loopback.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/testing/gtest.gyp:gtest',
|
||||
'<(webrtc_root)/modules/modules.gyp:video_capture_module',
|
||||
'video_tests_common',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@ -17,6 +17,7 @@
|
||||
'includes': [
|
||||
'test/libvietest/libvietest.gypi',
|
||||
'test/auto_test/vie_auto_test.gypi',
|
||||
'test/tests.gypi',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="android"', {
|
||||
|
||||
@ -128,6 +128,19 @@
|
||||
'vie_render_manager.cc',
|
||||
'vie_sender.cc',
|
||||
'vie_sync_module.cc',
|
||||
|
||||
# New VideoEngine API
|
||||
'new_include/common.h',
|
||||
'new_include/video_engine.h',
|
||||
'new_include/video_receive_stream.h',
|
||||
'new_include/video_send_stream.h',
|
||||
'internal/video_engine.cc',
|
||||
'internal/video_call.cc',
|
||||
'internal/video_call.h',
|
||||
'internal/video_receive_stream.cc',
|
||||
'internal/video_receive_stream.h',
|
||||
'internal/video_send_stream.cc',
|
||||
'internal/video_send_stream.h',
|
||||
], # source
|
||||
# TODO(jschuh): Bug 1348: fix size_t to int truncations.
|
||||
'msvs_disabled_warnings': [ 4267, ],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user