应用共享疑难问题:
添加内容提供者信息.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
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
/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
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
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
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