The previous article is mainly to participate in the Awesomeplayer directly with the Softwarerenderer class to display YUV, in order to use this class, at all costs of relying on libstagefright, libstagefright_color_ Conversion and other dynamic static library, which causes the program to have very high coupling degree, also does not facilitate us to understand the YUV data direct display of the deep-seated reasons.
So I began to study the detailed implementation of Softwarerenderer, we have to extract the core code of Softwarerenderer, to implement the YUV display.
Softwarerenderer has only three methods, one constructor, one destructor, and the other is the Render method that is responsible for the display. There is a very important place in the construction method Native_window_set_buffers_geometry here is the configuration of the application of the graphics buffer width and color space, ignoring this place, the screen will be displayed with the default value, will cause the display is not correct. The three most important places in the render function, one dequebuffer, one is mapper, the other is Queue_buffer.
native_window_set_buffers_geometry;//Setting the width height and color space yuv420native_window_dequeue_buffer_and_wait;// According to the above configuration request graphics buffer Mapper.lock (buf->handle, Gralloc_usage_sw_write_often, Bounds, &DST));// Maps the requested graphics buffer across processes to the user space memcpy (DST, data, dst_y_size + dst_c_size*2);//fills YUV data to the graphics buffer mnativewindow->queuebuffer;//display
The above five steps are an essential five step for surface display graphics.
With the above analysis, we directly on the code: (YUV Data Click Open Link, put to sdcard)
Main.cpp
#include <cutils/memory.h> #include <unistd.h> #include <utils/Log.h> #include <binder/ ipcthreadstate.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include < media/stagefright/foundation/adebug.h> #include <gui/Surface.h> #include <gui/surfacecomposerclient.h > #include <gui/ISurfaceComposer.h> #include <ui/DisplayInfo.h> #include <android/native_window.h > #include <system/window.h> #include <ui/graphicbuffermapper.h>//anativewindow is surface, The Codeusing namespace android;//in the corresponding surface.cpp is structured as a multiple of Y, that is, X is aligned by y to static int ALIGN (int x, int y) {//Y must be a power O F 2. return (x + y-1) & ~ (y-1);} void render (const void *data, size_t size, const sp<anativewindow> &nativewindow,int width,int height) { sp<anativewindow> Mnativewindow = NativeWindow; int Err;int Mcropwidth = width;int Mcropheight = height;int Halformat = hal_pixel_format_yv12;//color space int bUfwidth = (mcropwidth + 1) & ~1;//Press 2 to align int bufheight = (mcropheight + 1) & to; Check_eq (0, Native_window_set_usage (Mnativewindow.get (), Gralloc_usage_sw_read_never | G Ralloc_usage_sw_write_often | Gralloc_usage_hw_texture | GRALLOC_USAGE_EXTERNAL_DISP)); Check_eq (0, Native_window_set_scaling_mode (Mnativewindow.get (), Native_window_scaling_mo De_scale_to_window)); Width must be multiple of??? Very important, configure the width and height and specify the color space yuv420//assuming this is not configured here, the following deque_buffer can only apply for a default wide-height graphics buffer check_eq (0, Native_window_set_buffers_ Geometry (Mnativewindow.get (), Bufwidth, Bufheight, Halformat) ); Anativewindowbuffer *buf;//Descriptive narrative buffer//apply for a piece of spare graphics buffer if (err = native_window_dequeue_buffer_and_wait ( Mnativewindow.get (), &buf))! = 0) {ALOGW ("Surface::d Equeuebuffer returned error%d", err); Return } graphicbuffermapper &mapper = Graphicbuffermapper::get (); Rect bounds (mcropwidth, mcropheight); void *dst; Check_eq (0, Mapper.lock (//used to lock a graphics buffer and map buffers to user processes Buf->handle, gralloc_usage_sw_write_often, Bounds, &am P;DST));//dst points to the first address of the graphics buffer if (true) {size_t dst_y_size = buf->stride * buf->height; size_t dst_c_stride = ALIGN (BUF->STRIDE/2, 16);//1 line v/u size size_t dst_c_size = dst_c_stride * Buf->height/ 2;//u/v size memcpy (DST, data, dst_y_size + dst_c_size*2);//copy YUV data to graphics buffer} check_eq (0, Mapper.unloc K (Buf->handle)); if (err = Mnativewindow->queuebuffer (Mnativewindow.get (), buf,-1))! = 0) {ALOGW ("Surface::queuebuf Fer returned error%d ", err); } buf = NULL;} BOOL Getyv12data (const char *path,unsigned char * pyuvdata,int size) {FILE *FP = fopen (path, "RB"), if (fp = = NULL) {printf ("Re Ad%s fail!!!!!!!!!!!!!!!!!!! \ n ", path); return false;} Fread (PYUVDATA,SIZE,1,FP); fclose (FP); return true;} int main (void) {//Set up the Thread-pool sp<processstate> proc (processstate::self ()); Processstate::self ()->startthreadpool ();//Create a client to Surfaceflinger sp<surfacecomposerclient> Client = new Surfacecomposerclient ();sp<ibinder> Dtoken (Surfacecomposerclient::getbuiltindisplay (ISURFAC Ecomposer::edisplayidmain));D isplayinfo dinfo;//Gets the width and high information of the screen status_t status = Surfacecomposerclient::getdisplayinfo ( Dtoken, &dinfo);p rintf ("w=%d,h=%d,xdpi=%f,ydpi=%f,fps=%f,ds=%f\n", DINFO.W, Dinfo.h, dinfo.xdpi, dinfo.ydpi, D Info.fps, dinfo.density); if (status) return-1;//Create surface sp<surfacecontrol> Surfacecontrol = Client->createsurface (String8 ("Te Stsurface "), DINFO.W, Dinfo.h, pixel_format_rgba_8888, 0);/*************************get YUV data from file;**** /printf ("[%s][%d]\n", __file__,__line__); int width,height;width = 320;height = 240;int size = width * Height * 3/2;unsigned char *data= new unsigned char[size];const char *path = "/MNT/SDCARD/YUV_320_240.YUV"; Getyv12data (path,data,size);//get YUV Data From file;/********************* configuration surface*******************************************************************/ Surfacecomposerclient::openglobaltransaction (); Surfacecontrol->setlayer (100000);//Set z-coordinate surfacecontrol->setposition (100, 100);//with upper left corner (0,0) Set the display position surfacecontrol->setsize (width, height);//Set the video display size surfacecomposerclient::closeglobaltransaction (); SP <Surface> Surface = Surfacecontrol->getsurface ();p rintf ("[%s][%d]\n", __file__,__line__);/*************** Displays YUV data ******************************************************************/render (Data,size,surface, Width,height);p rintf ("[%s][%d]\n", __file__,__line__); Ipcthreadstate::self ()->jointhreadpool ();//To ensure that the screen is always displayed, Otherwise instantly disappears ipcthreadstate::self ()->stopprocess (); return 0;}
Android.mk (this time the library relies on a lot less)
Local_path:= $ (call My-dir) include $ (clear_vars) local_src_files:= main.cpplocal_shared_libraries: = Libcutils Libutils libbinder libui libgui libstagefright_foundationlocal_module:= myshowyuvlocal_module_tags: = Testsinclude $ (build_executable)
Reprint please specify the source http://blog.csdn.net/tung214/article/details/37651825
Android displays YUV data directly with surface (ii)