只做本地显示,在PeerConnection层调用流程比较简单。代码由Peerconnection_Client扣出来的。
获得摄像头 cricket::VideoCapturer* OpenVideoCaptureDevice()
设置Render StartLocalRenderer(video_track);
取并显示
//#include "talk/examples/peerconnection/client/conductor.h" #include <utility> #include <vector> #ifdef WIN32 #include <Windows.h> #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<uint8[]> image_; CRITICAL_SECTION buffer_lock_; rtc::scoped_refptr<webrtc::VideoTrackInterface> 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<VideoRenderer> 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<VideoRenderer> 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<webrtc::PeerConnectionInterface> peer_connection_; rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_connection_factory_; rtc::scoped_ptr<VideoRenderer> local_renderer_; HWND wnd = NULL; cricket::VideoCapturer* OpenVideoCaptureDevice() { rtc::scoped_ptr<cricket::DeviceManagerInterface> dev_manager( cricket::DeviceManagerFactory::Create()); if (!dev_manager->Init()) { LOG(LS_ERROR) << "Can't create device manager"; return NULL; } std::vector<cricket::Device> devs; if (!dev_manager->GetVideoCaptureDevices(&devs)) { LOG(LS_ERROR) << "Can't enumerate video devices"; return NULL; } std::vector<cricket::Device>::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<webrtc::AudioTrackInterface> audio_track( peer_connection_factory_->CreateAudioTrack( kAudioLabel, peer_connection_factory_->CreateAudioSource(NULL))); rtc::scoped_refptr<webrtc::VideoTrackInterface> 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<VideoRenderer> 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个完整的开源项目