Android视频慢慢来1

时间:2022-12-15 07:30:23

本来是没什么想写的意思,不过,有个观众天天关注我,没办法,还是起一个无聊的名字吧,应该不会被人搜到吧。

自从完成了自己的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


这个是它自己的结构:

Filename Size Rev Date Author
CameraView.java 5.3 KB r58 Feb 24, 2012 achang.zhou
MainActivity.java 11.3 KB r55 Feb 5, 2012 achang.zhou
NanoHTTPD.java 33.1 KB r60 Mar 19, 2012 achang.zhou
NativeAgent.java 1.3 KB r47 Jan 29, 2012 achang.zhou
NetInfoAdapter.java 4.5 KB r17 Dec 25, 2011 achang.zhou
StreamingLoop.java 1.9 KB r40 Jan 16, 2012 achang.zhou
StreamingServer.java 2.3 KB r51 Jan 30, 2012 achang.zhou


CameraView 就是按照 android developer - camera中的步骤,负责对摄像头配置,打开等操作,才发现Google developer改版了,变的漂亮了。。。
摘一下谷歌的文档:

  1. Open Camera - Use the Camera.open() to get an instance of the camera object.
  2. Connect Preview - Prepare a live camera image preview by connecting a SurfaceView to the camera usingCamera.setPreviewDisplay().
  3. Start Preview - Call Camera.startPreview() to begin displaying the live camera images.
  4. Start Recording Video - The following steps must be completed in order to successfully record video:
    1. Unlock the Camera - Unlock the camera for use by MediaRecorder by calling Camera.unlock().
    2. Configure MediaRecorder - Call in the following MediaRecorder methods in this order. For more information, see the MediaRecorder reference documentation.
      1. setCamera() - Set the camera to be used for video capture, use your application's current instance ofCamera.
      2. setAudioSource() - Set the audio source, use MediaRecorder.AudioSource.CAMCORDER.
      3. setVideoSource() - Set the video source, use MediaRecorder.VideoSource.CAMERA.
      4. Set the video output format and encoding. For Android 2.2 (API Level 8) and higher, use theMediaRecorder.setProfile method, and get a profile instance using CamcorderProfile.get(). For versions of Android prior to 2.2, you must set the video output format and encoding parameters:
        1. setOutputFormat() - Set the output format, specify the default setting orMediaRecorder.OutputFormat.MPEG_4.
        2. setAudioEncoder() - Set the sound encoding type, specify the default setting orMediaRecorder.AudioEncoder.AMR_NB.
        3. setVideoEncoder() - Set the video encoding type, specify the default setting orMediaRecorder.VideoEncoder.MPEG_4_SP.
      5. setOutputFile() - Set the output file, usegetOutputMediaFile(MEDIA_TYPE_VIDEO).toString() from the example method in the Saving Media Files section.
      6. setPreviewDisplay() - Specify the SurfaceView 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.

    3. Prepare MediaRecorder - Prepare the MediaRecorder with provided configuration settings by callingMediaRecorder.prepare().
    4. Start MediaRecorder - Start recording video by calling MediaRecorder.start().
  5. Stop Recording Video - Call the following methods in order, to successfully complete a video recording:
    1. Stop MediaRecorder - Stop recording video by calling MediaRecorder.stop().
    2. Reset MediaRecorder - Optionally, remove the configuration settings from the recorder by callingMediaRecorder.reset().
    3. Release MediaRecorder - Release the MediaRecorder by calling MediaRecorder.release().
    4. 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.
  6. Stop the Preview - When your activity has finished using the camera, stop the preview usingCamera.stopPreview().
  7. Release Camera - Release the camera so that other applications can use it by calling Camera.release().
NativeAgent里面载了两个Lib
 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:

    • call   This is a voice chat sample application.
    • pcp   This is a file-sharing sample application.
既然那么厉害,我当然要好好学习一下了,首先看到设计的几个概念: https://developers.google.com/talk/libjingle/important_concepts
里面总共有这么几个重要的概念:
Signals,用了Sigslot来传递消息,在对象中(模块)传递消息,关于SigSlot,这个是他的官网( http://sigslot.sourceforge.net/),作者在文中首先就是对着MFC喷了一通,模块之间是那么的难以通讯,所以才借鉴了QT,写了这个Sigslot。
如果有过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视频预览