android_系统provider/文件描述符/H264/openGl/读取fb0截屏


  应用共享疑难问题:
  添加内容提供者信息.Provider运行在子线程中.
  View的屏幕信息,Bitmap的mBuffer.
  访问者获取内容提供者的数据,ParcelFileDescriptor的formData/createPipe.
  数据的H264压缩,MediaCodec的Buffer大小设置/编码方式.MediaCodec编码解码运行在子线程.
  传入Bitmap,绘制到MediaCode的Surface上.  

  桌面共享:
  client端,4.3采用mMediaCodec解码,解码后的数据直接mSurfaceView的mSurfaceHolder的mSurface;4.2等,JNILib.OpenDecoder(*);JNILib.DecodeRender(*);//4.2那些api是隐藏的;    
  server端,JNI获取COLOR_FormatYUV420SemiPlanar格式的数据;之后采用H264编码进行压缩;
  server端,调用SurfaceComposerClient.h的getBuiltInDisplay(*)获取sp; 通过SurfaceComposerClient.h中内部类ScreenshotClient获取截屏数据; 把结果通过ffpmeg编码为COLOR_FormatYUV420SemiPlanar格式的数据;
   ScreenshotClient.update(*);ScreenshotClient.getPixels();
  java.lang.UnsatisfiedLinkError:no *.so in library path;//native库路径没有设置正确;





  为所有应用添加内容提供者,并通知观察者:
  android.content.pm包下PackageParser.java类,private Provider parseProvider(**){***},添加内容提供者。
  android.view包下ViewRootImpl.java类,private void performTraversals(){***},通知观察者。
  view.setDrawingCacheEnabled(true);
  ShareAppProvider.setBitmap(view.getDrawingCache() );
  String mUriStr="auth."+view.getContext().getApplicationInfo().packageName;
  view.getContext().getContentResolver().notifyChange(Uri.parse(mUriStr),null);
  BroadCastReceiver对象onReceive():The function is normally called within the main thread of its process, so you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed).
  ContentObserver对象onChange():运行在Handler所在的的进程。

  mView对象->文件描述符: 获取Bitmap.java的mBuffer;ParcelFileDescriptor.createPipe(),一个用于写,另一个给读;
  android.view包下,public class Surface implements Parcelable{ *** }
    public class SurfaceView extends View{ *** };
    mView.getDrawingCache()内部调用mBitmap=Bitmap.createBitmap(*); View的内部静态类: static class AttachInfo{ *** }
  android.graphics包下,public class Canvas{ *** }
  java.lang.ref包下,public class WeakReference extends Reference{ *** }
  /frameworks/base/graphics/java/android/graphics路径,android.graphics包下,public final class Bitmap implements Parcelable{ *** } //Bitmap对象可以直接通过Intent传递.
  /libcore/luni/src/main/java/java/io路径,java.io包下,public class FileInputStream extends InputStream implements Closeable{ *** }
    public final class FileDescriptor{ *** }
  android.os包下,public class ParcelFileDescriptor implements Parcelable, Closeable{ *** }
  ParcelFileDescriptor.createPipe(); //返回一个描述对,一个用于写,一个用于读;  AutoCloseOutputStream stream = new ParcelFileDescriptor.AutoCloseOutputStream(pacelPipe[1]);
    public static class AutoCloseInputStream extends FileInputStream{ *** }  //ParcelFileDescriptor的内部静态类。  //先关闭文件描述符,再调父类关闭.
    public class FileInputStream extends InputStream implements Closeable{ *** }
    public abstract class InputStream extends Object implements Closeable{ *** }
  ParcelFileDescriptor.fromData(**);//隐藏api,已废弃,内部new MemoryFile();
    mMemoryFile.deactivate(); //隐藏api;  Unmaps the memory file from the process's memory space, but does not close it.
    mMemoryFile.getFileDescriptor(); //隐藏api;  Gets a FileDescriptor for the memory file.The returned file descriptor is not duplicated.
  ParcelFileDescriptor.dup(FileDescriptor orig); //Create a new ParcelFileDescriptor that is a dup of an existing FileDescriptor. This obeys standard POSIX semantics.
  ParcelFileDescriptor open(File file, int mode); //内部转换调用的Pacel的静态方法.Pacel有2300行代码.

  视频图像编码/解码:必须在子线程中去运行。
  H.263是国际电联ITU-T的一个标准草案,是为低码流通信而设计的。
  264发展了263,264缺点:由于264的算法更加复杂,程序实现烦琐,运行它需要更多的处理器和内存资源;264的实现更加灵活,它把一些实现留给了厂商自己去实现,互通性较差;
  MIME多功能Internet邮件扩展;每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类。
  YUV格式:Y表示明亮度,U色度,V浓度.
  MediaCodec能够处理ByteBuffer和Surface两种输入.ByteBuffer仅支持YUV模式.RGBA到YUV422转换非常耗时,Surface的Demo在/cts/tests/tests/media/src/android/media/cts/InputSurface.java.
  OpenGL绘制surface,作为编码的输入。
  frameworks/base/media/java/android/media路径,android.media包下,final public class MediaCodec{ *** }
    public final class MediaFormat{ *** } //内部有private Map mMap;//音频/视频等参数.
    public final class MediaCodecInfo{ *** }
    mMediaCodec.getCodecInfo(); //通过createDecoderByType/createEncoderByType创建MediaCodec,不能提前知道component信息,因此调用者没有MediaCodecInfo.
    mMediaCodec.configure(**); //压缩编码时,传入CONFIGURE_FLAG_ENCODE. //解码时,直接传入mSurface对象. mSurfaceView.getHolder(); mSurfaceHolder.getSurface();
    mMediaCodec.createEncoderByType("video/avc");     MediaCodec.createDecoderByType("video/avc");  //MediaCodec的静态方法.
    mMediaCodec.dequeueInputBuffer(**); //start成功后,client端还没有拥有input和output,需调用dequeue**Buffer使拥有者转换到client.
    mMediaCodec.queueInputBuffer(**); //inputBuffer填好数据后,输入到组件中.
    mMediaCodec.releaseOutputBuffer(**); //获取解码后的数据/直接输出绘制到mSurface中.
    mMediaCodec.flush();//flush组件中input和output;所有的dequeue*Buffer都不可用.
    MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;//表明数据为图形缓存.indicates that the data will be a GraphicBuffer metadata reference.
    mEncoderMediaCodec.createInputSurface();//使用surface作为编码的输入. requests a Surface to use as the input to an encoder, in place of input buffers.
    mEncoderMediaCodec.getOutputBuffers();//Call this after start() returns and whenever dequeueOutputBuffer signals an output buffer change by returning {@link #INFO_OUTPUT_BUFFERS_CHANGED}
    mEncoderMediaCodec.signalEndOfInputStream(); // Signals end-of-stream on input.
    decoder.dequeueOutputBuffer(*);//
  public abstract class ByteBuffer extends Buffer implements Comparable{ *** } //内部封装了ByteArrayBuffer(new byte[capacity]);  //ByteArrayBuffer内部使用byte[]数组存储数据.
    public abstract class Buffer{ *** }; //

  openGL的使用:
  android.opengl包下,public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback{ *** } //实现了SurfaceView的绘制OpenGL的显示.
    //内部类class GLThread extends Thread{ *** } //内部类private static class GLThreadManager{ *** }
    public class Matrix{ *** } //Matrix math utilities. These methods operate on OpenGL ES format matrices and vectors stored in float arrays.
  android.view包下,public class SurfaceView extends View{ *** } //把绘制的任务接口提供出来. //Provides a dedicated drawing surface embedded inside of a view hierarchy.
  android.media包下,public class MediaPlayer{ *** }  //初始化线程的Looper来初始化事件处理handler.  //内部类,private class EventHandler extends Handler{ *** }
    //mMediaPlayer.setDisplay(mSurfaceHolder); //mMediaPlayer.setSurface(mSurface); //mSurfaceView.getHolder();//mSurfaceHolder.lockCanvas(*);
  javax.microedition.khronos.opengles.GL包下,public abstract class EGLContext{ *** }//与Actvity的context没有关系;
  javax.microedition.khronos.egl包下,public abstract class EGLSurface{ *** } //与Surface,SurfaceView,GLSurfaceView没有关系;
    EGLWindowSurfaceFactory.createWindowSurface(*);//内部调用mEGL10.eglCreateWindowSurface(*);//参数可以传入Object的数据载体,可以为Surface;
    public abstract class EGLDisplay{ *** } //空;
  GLES20.glGenTextures(GLsizei n,GLuint *textures);//n,用来生成纹理的数量;textures:存储纹理索引的; //用来产生你要操作的纹理对象的索引的,比如你告诉OpenGL,我需要5个纹理对象,它会从没有用到的整数里返回5个给你;
  GLES20.glBindTexture(*);//它告诉OpenGL下面对纹理的任何操作都是对它所绑定的纹理对象的;//比如glBindTexture(GL_TEXTURE_2D,1)告诉OpenGL下面代码中对2D纹理的任何设置都是针对索引为1的纹理的;
  GLES20.glEnable(*);//启用各种功能; 使用glIsEnabled或者glGet来确定当前各项功能的开启情况; glEnable不能写在glBegin和glEnd两个函数中间;
  GLES20.glScissor(*);//defines a rectangle, called the scissor box, in window coordinates.
  GLES20.glClearColor(*);//通过glClear使用红/绿/蓝以及AFA值来清除颜色缓冲区的,并且都被归一化在(0,1)之间的值;
  GLES20.glClear(*);//可以使用|运算符组合不同的缓冲标志位,表明需要清除的缓冲;例如glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)表示要清除颜色缓冲以及深度缓冲;
  glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); //第一条语句表示清除颜色设为黑色,第二条语句表示把整个窗口清除为当前的清除颜色,glClear()的唯一参数表示需要被清除的缓冲区。
  GLES20.glActiveTexture(*); //
  GLES20.glUniformMatrix4fv(*); //
  GLES20.glDrawArrays(*); //绘制功能; //当采用顶点数组方式绘制图形时使用; //调用该函数之前需要,调用glEnableVertexAttribArray/glVertexAttribPointer等设置顶点属性和数据; //相似功能的函数是glDrawElements;

  openGL向mEncoderMediaCodec的Surface中绘制bitmap:
  GLFrame的像素数据存储在GPU;使用Textures和Frame Buffer Objects (FBOs)两种容器; // /frameworks/base/media/mca/filterfw/native/core/gl_frame.cpp
    Textures are used whenever pixel data needs to be read into a shader or the host program, and when pixel data is uploaded to a GLFrame. The FBO is used as a rendering target for shaders.



  读取/dev/graphics/fb0截屏:
  android4.1可以通过/dev/graphics/fb0完成屏幕采集;android4.3,发现/dev/graphics/fb0的方法行不通了,改采用SurfaceFlinger服务。
  使用方法,$ndk-build; $adb push libs/armeabi/save /data/local;  #chmod 777 save;   #./save;
  #include      #include     #include     #include    #include     #include
  fb->fd=open("/dev/graphics/fb0",O_RDONLY);
  if(ioctl(fb->fd,FBIOGET_FSCREENINFO,&fb->fi)<0){printf("FBIOGET_FSCREENINFO failed!\n");} //ioctl是设备驱动程序中对设备的I/O通道进行管理的函数;就是对设备的一些特性进行控制,如串口的传输波特率/马达转速等;
  fb->bits=mmap(0,fb_virtual_size(fb),PROT_READ,MAP_SHARED,fb->fd,0);  //mmap将一个文件或者其它对象映射进内存;mmap()必须以PAGE_SIZE()为单位进行映射,而内存也只能以页为单位进行映射;
  android显示设备都是基于framebuffer的,直接将framebuffer中数据存为rawData再转换;#cat /dev/graphics/fb0 > /data/screen.raw;然后用图片转换工具将pnm格式的screen.raw文件转换成png或者jpg.
  有硬件加速,则view.buildDrawingCache()不起作用;也这样Bitmap bitmap=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);Canvas canvas=new Canvas(bitmap); view.dispatchDraw(canvas);
  视频的显示是用OVerlay来实现的,不是framebuffer,所以上层不能获取当前帧的内容;
  #adb pull /dev/graphics/fb0 fb0  #ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 1920x1200 -i fb0 -f image2 -vcodec png image.png

  FrameBuffer是一种机制的实现;这种机制是把屏幕上的每个点映射成一段线性内存空间,程序可以简单的改变这段内存的值来改变屏幕上某一点的颜色;/dev/fb0是FrameBuffer的设备文件;
  ioctl()是I/O操作的杂货箱,很多事情都要依靠它来完成;
  #include   //多线程.
  在单线程中,有两种基本的数据:全局变量和局部变量; 在多线程里,还有第三种数据类型,线程数据(TSD:Thread-Specific Data); 线程内,各个函数可以象使用全局变量一样调用它,但它对线程外部的其它线程是不可见的;
  #include   //信号量在进程是以有名信号量进行通信的,在线程是以无名信号进行通信的;无名使用,有名信号量,无名信号量不能用进程间通信;



你可能感兴趣的:(理论方面的)