本来是没什么想写的意思,不过,有个观众天天关注我,没办法,还是起一个无聊的名字吧,应该不会被人搜到吧。
自从完成了自己的android voip的音频部分,就开始准备看视频的,H.264的编解码,正好之前看到了一个开源项目,做的是android 的视频监控的,用的也是H,264,不过多了一个远程访问监控网页,也就是自己搭了个httpd server?或许吧,它用到了两个Lib,一个是谷歌的开源项目libjingle,等下面会详细介绍,另外一个是NanoHttpd
1. Google's libjingle, multiple threads, signal/slot, event loop, sockets in NDK.
2. NanoHTTPD, building web server
这个是它自己的结构:
CameraView 就是按照 android developer - camera中的步骤,负责对摄像头配置,打开等操作,才发现Google developer改版了,变的漂亮了。。。
摘一下谷歌的文档:
- Open Camera - Use the
Camera.open()
to get an instance of the camera object. - Connect Preview - Prepare a live camera image preview by connecting a
SurfaceView
to the camera usingCamera.setPreviewDisplay()
. - Start Preview - Call
Camera.startPreview()
to begin displaying the live camera images. - Start Recording Video - The following steps must be completed in order to successfully record video:
- Unlock the Camera - Unlock the camera for use by
MediaRecorder
by callingCamera.unlock()
. - Configure MediaRecorder - Call in the following
MediaRecorder
methods in this order. For more information, see theMediaRecorder
reference documentation.-
setCamera()
- Set the camera to be used for video capture, use your application's current instance ofCamera
. -
setAudioSource()
- Set the audio source, useMediaRecorder.AudioSource.CAMCORDER
. -
setVideoSource()
- Set the video source, useMediaRecorder.VideoSource.CAMERA
. - Set the video output format and encoding. For Android 2.2 (API Level 8) and higher, use the
MediaRecorder.setProfile
method, and get a profile instance usingCamcorderProfile.get()
. For versions of Android prior to 2.2, you must set the video output format and encoding parameters:-
setOutputFormat()
- Set the output format, specify the default setting orMediaRecorder.OutputFormat.MPEG_4
. -
setAudioEncoder()
- Set the sound encoding type, specify the default setting orMediaRecorder.AudioEncoder.AMR_NB
. -
setVideoEncoder()
- Set the video encoding type, specify the default setting orMediaRecorder.VideoEncoder.MPEG_4_SP
.
-
-
setOutputFile()
- Set the output file, usegetOutputMediaFile(MEDIA_TYPE_VIDEO).toString()
from the example method in the Saving Media Files section. -
setPreviewDisplay()
- Specify theSurfaceView
preview layout element for your application. Use the same object you specified for Connect Preview.
Caution: You must call these
MediaRecorder
configuration methods in this order, otherwise your application will encounter errors and the recording will fail. -
- Prepare MediaRecorder - Prepare the
MediaRecorder
with provided configuration settings by callingMediaRecorder.prepare()
. - Start MediaRecorder - Start recording video by calling
MediaRecorder.start()
.
- Unlock the Camera - Unlock the camera for use by
- Stop Recording Video - Call the following methods in order, to successfully complete a video recording:
- Stop MediaRecorder - Stop recording video by calling
MediaRecorder.stop()
. - Reset MediaRecorder - Optionally, remove the configuration settings from the recorder by calling
MediaRecorder.reset()
. - Release MediaRecorder - Release the
MediaRecorder
by callingMediaRecorder.release()
. - Lock the Camera - Lock the camera so that future
MediaRecorder
sessions can use it by callingCamera.lock()
. Starting with Android 4.0 (API level 14), this call is not required unless theMediaRecorder.prepare()
call fails.
- Stop MediaRecorder - Stop recording video by calling
- Stop the Preview - When your activity has finished using the camera, stop the preview using
Camera.stopPreview()
. - Release Camera - Release the camera so that other applications can use it by calling
Camera.release()
.
publicstaticvoidLoadLibraries(){
//Local library .so files before this activity created.
System.loadLibrary("teaonly");
System.loadLibrary("ipcamera");
然后我在jni/android.mk中,看了一下,貌似libteaonly的源文件就是一个叫talk的文件夹,结果发现其实是libjingle的lib,恩,接着就去看libjingle为何物
没看还好,一看吓一跳,这家伙难道是已经把我已经做好的都做好了吗,下面的四点是它号称能够做到的:
-
- A multi-user voice chat application
- A multi-user video conferencing application
- A multi-user live music streaming application
- A peer-to-peer file sharing application
原来大名鼎鼎的Google Talk就是由这个库开发的,提供了开发手册以及几个实例程序:
Libjingle ships with two command-line sample applications:
既然那么厉害,我当然要好好学习一下了,首先看到设计的几个概念:
https://developers.google.com/talk/libjingle/important_concepts
里面总共有这么几个重要的概念:
如果有过QT编程经验的人可以知道,譬如我按下一个按钮,如果按钮按下的消息和func()连接在一起,那么就会触发这个函数,这个用法在模块与模块之间通信会十分的有用,而且移植十分方便,只有一个头文件Sigslot.h。如果编译出错 ,在419行,改为"typedef typename sender_set::const_iterator const_iterator;"
关于用法,很简单,列举一个文档中的小例子:
class Switch { public: signal0<> Clicked; }; class Light : public has_slots<> { public: void ToggleState(); void TurnOn(); void TurnOff(); }; Switch sw1, sw2; Light lp1, lp2;
这是一个开关和灯的类,Switch 中只有个公有成员 类型为 signal0<>(0代表构造参数的个数)Clicked,Light继承了public has_slots<> ,这样子signal才能和light绑定。
Switch sw3, sw4, all_on, all_off; Light lp3, lp4; sw3.Clicked.connect(&lp3, &Light::ToggleState); sw4.Clicked.connect(&lp4, &Light::ToggleState); all_on.Clicked.connect(&lp1, &Light::TurnOn()); all_on.Clicked.connect(&lp2, &Light::TurnOn()); all_on.Clicked.connect(&lp3, &Light::TurnOn()); all_on.Clicked.connect(&lp4, &Light::TurnOn()); all_off.Clicked.connect(&lp1, &Light::TurnOff()); all_off.Clicked.connect(&lp2, &Light::TurnOff()); all_off.Clicked.connect(&lp3, &Light::TurnOff()); all_off.Clicked.connect(&lp4, &Light::TurnOff());通过connect函数,就可以将信号绑定在相应的槽函数上了。譬如运行sw3.clicked(),那么就会触发ToggleState,同理,all_on.Clicked(),那么所有的灯都亮了。。。
今天就到这里吧,下次再放上简单的Android视频预览