只做本地显示,在PeerConnection层调用流程比较简单。代码由Peerconnection_Client扣出来的。
获得摄像头
cricket::VideoCapturer* OpenVideoCaptureDevice()
设置Render
StartLocalRenderer(video_track);
取并显示
//#include "talk/examples/peerconnection/client/conductor.h"
#include
#include
#ifdef WIN32
#include
#endif
//#include "opencv2\opencv.hpp"
#include "talk/app/webrtc/videosourceinterface.h"
#include "talk/app/webrtc/mediastreaminterface.h"
#include "talk/app/webrtc/peerconnectioninterface.h"
#include "talk/media/devices/devicemanager.h"
//#include "talk/app/webrtc/test/fakeconstraints.h"
#include "talk/media/base/videorenderer.h"
#include "talk/media/base/videoframe.h"
#include "webrtc/base/common.h"
#include "webrtc/base/json.h"
#include "webrtc/base/logging.h"
//#pragma comment(lib, "opencv_world300d.lib")
#define DTLS_ON true
#define DTLS_OFF false
// Names used for a IceCandidate JSON object.
const char kCandidateSdpMidName[] = "sdpMid";
const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
const char kCandidateSdpName[] = "candidate";
// Names used for a SessionDescription JSON object.
const char kSessionDescriptionTypeName[] = "type";
const char kSessionDescriptionSdpName[] = "sdp";
const char kAudioLabel[] = "audio_label";
const char kVideoLabel[] = "video_label";
const char kStreamLabel[] = "stream_label";
// A little helper class to make sure we always to proper locking and
// unlocking when working with VideoRenderer buffers.
template <typename T>
class AutoLock {
public:
explicit AutoLock(T* obj) : obj_(obj) { obj_->Lock(); }
~AutoLock() { obj_->Unlock(); }
protected:
T* obj_;
};
class VideoRenderer : public webrtc::VideoRendererInterface {
public:
VideoRenderer(HWND wnd, int width, int height,
webrtc::VideoTrackInterface* track_to_render);
virtual ~VideoRenderer();
void Lock() {
::EnterCriticalSection(&buffer_lock_);
}
void Unlock() {
::LeaveCriticalSection(&buffer_lock_);
}
// VideoRendererInterface implementation
virtual void SetSize(int width, int height);
virtual void RenderFrame(const cricket::VideoFrame* frame);
const BITMAPINFO& bmi() const { return bmi_; }
const uint8* image() const { return image_.get(); }
protected:
enum {
SET_SIZE,
RENDER_FRAME,
};
HWND wnd_;
BITMAPINFO bmi_;
rtc::scoped_ptr image_;
CRITICAL_SECTION buffer_lock_;
rtc::scoped_refptr rendered_track_;
};
//
// VideoRenderer
//
VideoRenderer::VideoRenderer(
HWND wnd, int width, int height,
webrtc::VideoTrackInterface* track_to_render)
: wnd_(wnd), rendered_track_(track_to_render) {
::InitializeCriticalSection(&buffer_lock_);
ZeroMemory(&bmi_, sizeof(bmi_));
bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi_.bmiHeader.biPlanes = 1;
bmi_.bmiHeader.biBitCount = 32;
bmi_.bmiHeader.biCompression = BI_RGB;
bmi_.bmiHeader.biWidth = width;
bmi_.bmiHeader.biHeight = -height;
bmi_.bmiHeader.biSizeImage = width * height *
(bmi_.bmiHeader.biBitCount >> 3);
rendered_track_->AddRenderer(this);
}
VideoRenderer::~VideoRenderer() {
rendered_track_->RemoveRenderer(this);
::DeleteCriticalSection(&buffer_lock_);
}
void VideoRenderer::SetSize(int width, int height) {
AutoLock lock(this);
if (width == bmi_.bmiHeader.biWidth && height == bmi_.bmiHeader.biHeight) {
return;
}
bmi_.bmiHeader.biWidth = width;
bmi_.bmiHeader.biHeight = -height;
bmi_.bmiHeader.biSizeImage = width * height *
(bmi_.bmiHeader.biBitCount >> 3);
image_.reset(new uint8[bmi_.bmiHeader.biSizeImage]);
}
int ii = 0;
void VideoRenderer::RenderFrame(
const cricket::VideoFrame* video_frame) {
if (!video_frame)
return;
{
AutoLock lock(this);
const cricket::VideoFrame* frame =
video_frame->GetCopyWithRotationApplied();
SetSize(static_cast<int>(frame->GetWidth()),
static_cast<int>(frame->GetHeight()));
ASSERT(image_.get() != NULL);
frame->ConvertToRgbBuffer(cricket::FOURCC_ARGB,
image_.get(),
bmi_.bmiHeader.biSizeImage,
bmi_.bmiHeader.biWidth *
bmi_.bmiHeader.biBitCount / 8);
}
InvalidateRect(wnd_, NULL, TRUE);
}
rtc::scoped_refptr peer_connection_;
rtc::scoped_refptr peer_connection_factory_;
rtc::scoped_ptr local_renderer_;
HWND wnd = NULL;
cricket::VideoCapturer* OpenVideoCaptureDevice() {
rtc::scoped_ptr dev_manager(
cricket::DeviceManagerFactory::Create());
if (!dev_manager->Init()) {
LOG(LS_ERROR) << "Can't create device manager";
return NULL;
}
std::vector devs;
if (!dev_manager->GetVideoCaptureDevices(&devs)) {
LOG(LS_ERROR) << "Can't enumerate video devices";
return NULL;
}
std::vector ::iterator dev_it = devs.begin();
cricket::VideoCapturer* capturer = NULL;
for (; dev_it != devs.end(); ++dev_it) {
capturer = dev_manager->CreateVideoCapturer(*dev_it);
if (capturer != NULL)
break;
}
return capturer;
}
void StartLocalRenderer(webrtc::VideoTrackInterface* local_video) {
local_renderer_.reset(new VideoRenderer(wnd, 1, 1, local_video));
}
void AddStreams() {
rtc::scoped_refptr audio_track(
peer_connection_factory_->CreateAudioTrack(
kAudioLabel, peer_connection_factory_->CreateAudioSource(NULL)));
rtc::scoped_refptr video_track(
peer_connection_factory_->CreateVideoTrack(
kVideoLabel,
peer_connection_factory_->CreateVideoSource(OpenVideoCaptureDevice(),
NULL)));
StartLocalRenderer(video_track);
}
bool InitializePeerConnection() {
ASSERT(peer_connection_factory_.get() == NULL);
ASSERT(peer_connection_.get() == NULL);
peer_connection_factory_ = webrtc::CreatePeerConnectionFactory();
if (!peer_connection_factory_.get()) {
return false;
}
AddStreams();
return peer_connection_.get() != NULL;
}
void Show()
{
VideoRenderer* local_renderer = local_renderer_.get();
if (local_renderer)
{
AutoLock local_lock(local_renderer);
const BITMAPINFO& bmi = local_renderer->bmi();
const uint8* image = local_renderer->image();
//printf("height=%d width=%d biSizeImage=%d \n", bmi.bmiHeader.biHeight, bmi.bmiHeader.biWidth, bmi.bmiHeader.biSizeImage);
//GetBitmapFromScreen("c:\\aa.bmp", (BITMAPINFO)bmi, (uint8*)image);
int rows = abs(bmi.bmiHeader.biHeight);;
int cols = bmi.bmiHeader.biWidth;
static int i = 0;
printf("%d\n", i++);
//cv::Mat img(rows, cols, CV_8UC4, (void*)image, 0U);
//cv::imshow("Video Capture", img);
//cvWaitKey(1);
}
}
void ThreadProc(LPVOID lpParam)
{
while (true)
{
Show();
Sleep(33);
}
}
int main()
{
getchar();
//wnd = FindWindow(L"ConsoleWindowClass", NULL);
if (!InitializePeerConnection())
printf("error\n");
DWORD dwThreadId;
CreateThread(
NULL,//defaultsecurityattributes
0,//usedefaultstacksize
(LPTHREAD_START_ROUTINE)ThreadProc,//threadfunction
NULL,//argumenttothreadfunction
0,//usedefaultcreationflags
&dwThreadId);//returnsthethreadidentifier
getchar();
return 0;
}
使用这个so文件会需要的配置
1,下载并安装msysgit和Tortoisegit
2, 下载并安装Python,当我版本为3.3的时候执行py脚本出现了错误,后来我又将版本改为2.7的那个版本才可以。将python可执行文件的目录加入到环境变量。
3,需要SVN命令,但是由于我下载的是TortoiseSVN,它有图形界面,但是我在它的安装目录下却没有找到SVN命令,这样在执行后面的gclinet脚本的时候会提示svn命令找不到。于是又重新下载了一个可以在cmd下使用svn命令的软件,我安装的是Setup-Subversion-1.6.16.msi。别忘了将它的执行命令添加到环境变量中。
4,下载depot_tools工具,里面有一个gclient的脚本,后面的很多命令都涉及到这个脚本。因此需要将其加入到环境变量中。
可以通过svn co http://src.chromium.org/svn/trunk/tools/depot_tools这样的命令下载它。它会在cmd当前目录下创建一个depot_tools的文件夹。
5,执行Git安装目录下(我的在C:\Program Files\git )的GitBash快捷方式,就会打开一个类似于cmd的shell窗口,在这里可以切换到相应的目录下,新建一个空白目录,准备下载webrtc的源码。
6,切换到空白目录下,执行gclient config http://libjingle.googlecode.com/svn/trunk
7,等待一会儿输入gclient sync --force(下载源代码中)
8,执行gclient runhooks --force 将源代码转换成visual studio工程中。
访问http://www.webrtc.org/reference/getting-started/prerequisite-sw获取准备过程的详细内容
这个里面有两个重要的东西,一个是7.1的sdk,还有一个directxSdk,文件都不小。需要很长时间下载,当转换成工程之后还需要将它们的bin,include,lib文件夹加入到vs的工具->选项->项目和解决方案->vc++一栏的包含文件中。
访问http://www.webrtc.org/reference/getting-started获取安装过程的详细内容
由于是第一次安装webrtc,上面的步骤时有执行不对的。我遇到就是下载jingle执行gclient sync --force出错了,然后下面的需要将其转换成vs工程的时候就会失败,怎么弄都不行。后来我直接愤怒了,删除掉整个文件夹,新建一个文件夹,重新config,sync,然后runhooks才可以。
我认为必须安装的几个是:
depot_tools:执行gclient命令的时候需要,它里面有gclient脚本。加入到环境变量。
Subversion:执行svn命令的时候需要,加入到环境变量。
msysgit:gclient的命令的执行放在GitBash的shell窗口中执行。如果执行在cmd窗口中执行gclient命令,总会提示安装git,安装svn,不知道是什么原因,虽然我已经装过了。
不明白为什么需要安装TortoiseSVN和TortoiseGit,这两个感觉用途不大。
我最想安装之后就可以看到结果,于是决定立刻编译执行各种网站都会提到的peerconnection的工程。
1,编译libjingle_peerconnection_unittest工程,出现libjingle库连接失败
2,跟踪到libjingle库的生成中,libjingle.lib生成失败,发现是缺少secur32.lib和另外两个库链接失败。
3,查看libjingle库的工程的库包含目录,发现已经包含了目录,库也包含了。后来经过仔细查验,发现crypt32.lib;iphlpapi.lib;secur32.lib这三个库是以分号分隔的,而应该以空格分隔。将分号删掉,libjingle库生成成功。
4,继续编译libjingle_media库,同样有这样的问题,删除掉分号,OK。
针对我的电脑可以在E:\webrtc\trunk\trunk\build\Debug目录下找到peerconnection_client.exe文件,peerconnection_server.exe文件,运行服务器端和客户端,可以正常连接。还没有测试通话。
参考博客
主要用于播放网络视频
参考博客
websocket以及心跳包
参考博客
网格和Web分析器,经纬度和web分析,没有清楚的答案,暂且搁下
微信登录分享的jar包,百度搜索有很多
小米推送
视频直播的jar包,可百度搜索
https://github.com/ShuaiJing/AndroidNote/tree/master/AdavancedPart
https://github.com/ShuaiJing/LearningNotes
http://itlanbao.com/codes.aspx#2,0 android开源源码网站
https://github.com/AbrahamCaiJin/CommonUILibrary UI效果库
http://www.jianshu.com/p/72494773aace 工具类
http://blog.csdn.net/liuqz2009/article/details/53507472 9个完整的开源项目