#define LOG_TAG "Android_Overlay" #include <android/api-level.h> //android threads #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> //for android surface and overlay #if __ANDROID_API__ >= 9 #include <surfaceflinger/Surface.h> #include <surfaceflinger/ISurface.h> #include <surfaceflinger/SurfaceComposerClient.h> #include <surfaceflinger/ISurfaceComposer.h> #include <surfaceflinger/ISurfaceComposerClient.h> #include <ui/IOverlay.h> #else #include <ui/Surface.h> #include <ui/ISurface.h> #include <ui/SurfaceComposerClient.h> #endif #include <utils/log.h> #include <ui/Overlay.h> #include "media_Overlays.h" // ------------------------------micro and variable---------------------------------------------- #define CACHEABLE_BUFFERS 0x1 //mobile type //#define MOBILE_OPHONE #define MOBILE_ANDROID //android threads android_thread_id_t g_ThreadID; bool g_Thread_keep; // define in V412_utils.h typedef struct { int fd; size_t length; uint32_t offset; void *ptr; } mapping_data_t; mapping_data_t *mdata; // define it for video data typedef struct{ int index; int buf_count; uint16_t* buf_addr; uint16_t* address[8]; } packet_data; packet_data pdata; //image format typedef struct{ int index; int left; int top; uint32_t width; uint32_t height; int32_t format; int format_yuv; } image_format; image_format imgfmt; //view size typedef struct{ int left; int top; int width; int height; }view_size; view_size viewfmt; typedef enum{ Unknown_size = -1, Normal_ver_and_hor, Normal_ver_enlarge_hor, Normal_ver_full_hor, Enlarge_ver_and_hor, Enlarge_ver_full_hor }ScreenType; using namespace android; sp<SurfaceComposerClient> client; sp<SurfaceControl> sc; sp<ISurface> mSurface; sp<Overlay> mOverlay; namespace android { class Test { public: static const sp<ISurface>& getISurface(const sp<Surface>& s) { Surface* p; p=s.get(); ISurface*q = (p->mSurface).get(); // LOGI("sur->mSurface=0x%x\n",q); return s->getISurface(); } }; } // ----------------------------------implement------------------------------------------ sp<Overlay> InitOverlay(int screentype, int format) { Video_Overlay_Stop(); int left,top,width,height; // LOGI("Starting"); // set up the thread-pool sp<ProcessState> proc(android::ProcessState::self()); android::ProcessState::self()->startThreadPool(); // create a client to surfaceflinger, // LOGI("SurfaceComposerClient format = %d\n", format); client = new SurfaceComposerClient(); if(client == NULL){ return 0; } // create pushbuffer surface sc = client->createSurface(getpid(), 0, imgfmt.width,imgfmt.height,imgfmt.format, ISurfaceComposer::ePushBuffers); if(sc == NULL){ return 0; } // LOGI("createSurface,pid %d, %d x %d, %d\n",getpid(),imgfmt.width,imgfmt.height,imgfmt.format); Video_Overlay_Set_Screen(screentype); sp<Surface> surface = sc->getSurface(); // get to the isurface sp<ISurface> isurface = Test::getISurface(surface); // LOGI("getISurface = %p\n", isurface.get()); sp<ISurface> mSurface = isurface.get(); // LOGI("createOverlaying %d x %d, %d",imgfmt.width,imgfmt.height,imgfmt.format); #if __ANDROID_API__ >= 9 sp<OverlayRef> ref = mSurface->createOverlay(imgfmt.width,imgfmt.height,imgfmt.format,0); #else sp<OverlayRef> ref = mSurface->createOverlay(imgfmt.width,imgfmt.height,imgfmt.format); #endif if(ref.get()==NULL){ return 0; } sp<Overlay> overlay = new Overlay(ref); LOGI("init End"); return overlay; } /* video format: OVERLAY_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565, 4 OVERLAY_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, 1 OVERLAY_FORMAT_YCbCr_422_SP = HAL_PIXEL_FORMAT_YCbCr_422_SP, 16 OVERLAY_FORMAT_YCbCr_420_SP = HAL_PIXEL_FORMAT_YCbCr_420_SP, 17 OVERLAY_FORMAT_YCbYCr_422_I = HAL_PIXEL_FORMAT_YCbCr_422_I, 20 OVERLAY_FORMAT_YCbYCr_420_I = HAL_PIXEL_FORMAT_YCbCr_420_I, 21 OVERLAY_FORMAT_CbYCrY_422_I = HAL_PIXEL_FORMAT_CbYCrY_422_I, 22 OVERLAY_FORMAT_CbYCrY_420_I = HAL_PIXEL_FORMAT_CbYCrY_420_I, 23 OVERLAY_FORMAT_DEFAULT = 99 */ int Video_Overlay_Init(int screentype, int format) { imgfmt.index = 0; if(0 == format) { imgfmt.format = OVERLAY_FORMAT_RGB_565; } else if(1 == format) { imgfmt.format = OVERLAY_FORMAT_BGRA_8888; } else if(4 == format) { imgfmt.format = OVERLAY_FORMAT_YCbYCr_422_I; } else if(6 == format) { imgfmt.format = OVERLAY_FORMAT_CbYCrY_422_I; } else if(8 == format) { imgfmt.format = OVERLAY_FORMAT_DEFAULT; } #if __ANDROID_API__ < 9 else if(2 == format) { imgfmt.format = OVERLAY_FORMAT_YCbCr_422_SP; } else if(3 == format) { imgfmt.format = OVERLAY_FORMAT_YCbCr_420_SP; } else if(5 == format) { imgfmt.format = OVERLAY_FORMAT_YCbYCr_420_I; } else if(7 == format) { imgfmt.format = OVERLAY_FORMAT_CbYCrY_420_I; } #endif pdata.index = 0; pdata.buf_count = 0; pdata.buf_addr = NULL; mOverlay = InitOverlay(screentype, format); if(mOverlay == NULL) { LOGE("Maybe the device did not support overlay mode.\n"); return 0; } else { pdata.buf_count = mOverlay->getBufferCount(); for(int i = 0;i<pdata.buf_count;i++) { mdata = (mapping_data_t*)mOverlay->getBufferAddress((void*)i); pdata.address[i] = (uint16_t*)mdata->ptr; LOGI("buffer count (%d),i(%d),pdata.address(%p)\n",pdata.buf_count,i,pdata.address[i]); } return 1; } } void* Video_Overlay_WriteData(int screentype) { if(mOverlay == NULL){ return NULL; } if(pdata.index >= pdata.buf_count) { pdata.index = 0; } Video_Overlay_Set_Screen(screentype); overlay_buffer_t overlay_buffer; mOverlay->dequeueBuffer(&overlay_buffer); LOGI("WriteData index (%d),pdata.address(%p)\n",pdata.index,pdata.address[pdata.index]); return pdata.address[pdata.index]; } void set_screen_size(int left, int top, int width, int height, int nSec) { // if(imgfmt.width <= viewfmt.width) { client->openTransaction(); // client->freezeDisplay(1); sc->setSize(width,height); sc->setPosition(left,top); // client->unfreezeDisplay(1); client->closeTransaction(); usleep(nSec * 1000); } } void Video_Overlay_Set_Screen(int screentype) { int left,top,width,height; if(screentype == 0){//Normal_ver_and_hor width = imgfmt.width; height = imgfmt.height; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 1); } else if(screentype == 1){//Normal_ver_enlarge_hor if(viewfmt.width < viewfmt.height){ width = imgfmt.width; height = imgfmt.height; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 1); } else{ height = viewfmt.height; width = (height * imgfmt.width)/imgfmt.height; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 1); } } else if(screentype == 2){//Normal_ver_full_hor if(viewfmt.width < viewfmt.height){ width = imgfmt.width; height = imgfmt.height; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 1); } else{ width = viewfmt.width; height = viewfmt.height; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 2); } } else if(screentype == 3){//Enlarge_ver_and_hor #ifdef MOBILE_OPHONE if(viewfmt.width < viewfmt.height){ width = viewfmt.width; height = (width * imgfmt.height)/imgfmt.width; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 1); } else{ height = viewfmt.height; width = (height * imgfmt.width)/imgfmt.height; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 2); } #else #ifdef MOBILE_ANDROID if(viewfmt.width <= viewfmt.height){ if(imgfmt.width <= viewfmt.width){ width = viewfmt.width; height = (width * imgfmt.height)/imgfmt.width; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 1); LOGI("Set_Screen 1 view(%d x %d x %d x %d)\n",left,top,width,height); }else{ width = viewfmt.width; height = viewfmt.height-60; left = 0; top = 60; set_screen_size(left, top, width, height, 2); LOGI("Set_Screen 2 view(%d x %d x %d x %d)\n",left,top,width,height); } }else{//viewfmt.width > viewfmt.height if(imgfmt.width > viewfmt.width){ width = imgfmt.width; height = imgfmt.height; left = 0; top = 60; set_screen_size(left, top, width, height, 2); LOGI("Set_Screen 3 view(%d x %d x %d x %d)\n",left,top,width,height); }else{//imgfmt.width <= viewfmt.width height = viewfmt.height; width = (height * imgfmt.width)/imgfmt.height; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2; set_screen_size(left, top, width, height, 2); LOGI("Set_Screen 4 view(%d x %d x %d x %d)\n",left,top,width,height); } } #endif #endif } else if(screentype == 4){//Enlarge_ver_full_hor if(viewfmt.width < viewfmt.height){ width = viewfmt.width; height = (width * imgfmt.height)/imgfmt.width; left = (viewfmt.width-width)/2; top = (viewfmt.height-height)/2/2; LOGI("Set_Screen 5 view(%d x %d x %d x %d)\n",left,top,width,height); set_screen_size(left, top, width, height, 1); }else{ if (viewfmt.width >= 800) { width = viewfmt.width; height = viewfmt.height; left = 0;//(viewfmt.width-width)/2; top = 0;//(viewfmt.height-height)/2; LOGI("Set_Screen 6 view(%d x %d x %d x %d)\n",left,top,width,height); set_screen_size(left, top, width, height, 2); } else { width = viewfmt.width; height = viewfmt.height; left = viewfmt.left;//(viewfmt.width-width)/2; top = viewfmt.top;//(viewfmt.height-height)/2; LOGI("Set_Screen 7 view(%d x %d x %d x %d)\n",left,top,width,height); set_screen_size(left, top, width, height, 1); } } } LOGI("Set_Screen end view(%d x %d x %d x %d)\n",left,top,width,height); } void Video_Overlay_GetViewSize(int contrl_x, int contrl_y, int contrl_w, int contrl_h) { viewfmt.left = contrl_x; viewfmt.top = contrl_y; viewfmt.width = contrl_w; viewfmt.height = contrl_h; LOGI("Get Data view(%d x %d, %d x %d)\n",viewfmt.left,viewfmt.top,viewfmt.width,viewfmt.height); } void Video_Overlay_GetFrameSize(int video_w, int video_h) { imgfmt.width = video_w; imgfmt.height = video_h; LOGI("Get Frame Data", "video(%d x %d)\n",imgfmt.width,imgfmt.height); } void Video_Overlay_Display() { mOverlay->queueBuffer((void*)pdata.index); LOGI("Display pdata.index(%d),width(%d),height(%d)\n",pdata.index,imgfmt.width,imgfmt.height); pdata.index++; if(pdata.index > pdata.buf_count) { pdata.index = 0; } // usleep(50000); } void Video_Overlay_Stop() { // g_Thread_keep = false; if (mOverlay != NULL) { mOverlay->destroy(); mOverlay = NULL; } } void yuv420_convert(uint8_t * src[3], uint8_t * yuv420, int width, int height) { unsigned int w,h; for (h=0; h<height; h++){ memcpy(yuv420, src[0], width); src[0] += width+32; yuv420 += width; } for (h=0; h<height/2; h++){ memcpy(yuv420, src[1], width/2); memcpy(yuv420 + width/2, src[1], width/2); src[1] += (width+32)/2; yuv420 += width; } for (h=0; h<height/2; h++){ memcpy(yuv420, src[2], width/2); memcpy(yuv420 + width/2, src[2], width/2); src[2] += (width+32)/2; yuv420 += width; } } /* convert 4:2:0 to yuv 4:2:0sp */ void yuv420p_to_yuv420sp(uint8_t * src[3], uint8_t * yuv420sp, int width, int height) { unsigned int w,h; for (h=0; h<height; h++){ memcpy(yuv420sp, src[0], width); src[0] += width+32; yuv420sp += width; } for (h=0; h<height/2; h++){ memcpy(yuv420sp, src[1], width/2);memcpy(yuv420sp, src[2], width/2); memcpy(yuv420sp + width/2, src[1], width/2);memcpy(yuv420sp + width/2, src[2], width/2); src[1] += (width+32)/2;src[2] += (width+32)/2; yuv420sp += width;yuv420sp += width; } } void yuyv422_to_yuv420sp(unsigned char *bufsrc, unsigned char *bufdest, int width, int height) { unsigned char *ptrsrcy1, *ptrsrcy2; unsigned char *ptrsrcy3, *ptrsrcy4; unsigned char *ptrsrccb1, *ptrsrccb2; unsigned char *ptrsrccb3, *ptrsrccb4; unsigned char *ptrsrccr1, *ptrsrccr2; unsigned char *ptrsrccr3, *ptrsrccr4; int srcystride, srcccstride; ptrsrcy1 = bufsrc ; ptrsrcy2 = bufsrc + (width<<1) ; ptrsrcy3 = bufsrc + (width<<1)*2 ; ptrsrcy4 = bufsrc + (width<<1)*3 ; ptrsrccb1 = bufsrc + 1; ptrsrccb2 = bufsrc + (width<<1) + 1; ptrsrccb3 = bufsrc + (width<<1)*2 + 1; ptrsrccb4 = bufsrc + (width<<1)*3 + 1; ptrsrccr1 = bufsrc + 3; ptrsrccr2 = bufsrc + (width<<1) + 3; ptrsrccr3 = bufsrc + (width<<1)*2 + 3; ptrsrccr4 = bufsrc + (width<<1)*3 + 3; srcystride = (width<<1)*3; srcccstride = (width<<1)*3; unsigned char *ptrdesty1, *ptrdesty2; unsigned char *ptrdesty3, *ptrdesty4; unsigned char *ptrdestcb1, *ptrdestcb2; unsigned char *ptrdestcr1, *ptrdestcr2; int destystride, destccstride; ptrdesty1 = bufdest; ptrdesty2 = bufdest + width; ptrdesty3 = bufdest + width*2; ptrdesty4 = bufdest + width*3; ptrdestcb1 = bufdest + width*height; ptrdestcb2 = bufdest + width*height + width; ptrdestcr1 = bufdest + width*height + 1; ptrdestcr2 = bufdest + width*height + width + 1; destystride = (width)*3; destccstride = width; int i, j; for(j=0; j<(height/4); j++) { for(i=0;i<(width/2);i++) { (*ptrdesty1++) = (*ptrsrcy1); (*ptrdesty2++) = (*ptrsrcy2); (*ptrdesty3++) = (*ptrsrcy3); (*ptrdesty4++) = (*ptrsrcy4); ptrsrcy1 += 2; ptrsrcy2 += 2; ptrsrcy3 += 2; ptrsrcy4 += 2; (*ptrdesty1++) = (*ptrsrcy1); (*ptrdesty2++) = (*ptrsrcy2); (*ptrdesty3++) = (*ptrsrcy3); (*ptrdesty4++) = (*ptrsrcy4); ptrsrcy1 += 2; ptrsrcy2 += 2; ptrsrcy3 += 2; ptrsrcy4 += 2; (*ptrdestcb1) = (*ptrsrccb1); (*ptrdestcb2) = (*ptrsrccb3); ptrdestcb1 += 2; ptrdestcb2 += 2; ptrsrccb1 += 4; ptrsrccb3 += 4; (*ptrdestcr1) = (*ptrsrccr1); (*ptrdestcr2) = (*ptrsrccr3); ptrdestcr1 += 2; ptrdestcr2 += 2; ptrsrccr1 += 4; ptrsrccr3 += 4; } /* Update src pointers */ ptrsrcy1 += srcystride; ptrsrcy2 += srcystride; ptrsrcy3 += srcystride; ptrsrcy4 += srcystride; ptrsrccb1 += srcccstride; ptrsrccb3 += srcccstride; ptrsrccr1 += srcccstride; ptrsrccr3 += srcccstride; /* Update dest pointers */ ptrdesty1 += destystride; ptrdesty2 += destystride; ptrdesty3 += destystride; ptrdesty4 += destystride; ptrdestcb1 += destccstride; ptrdestcb2 += destccstride; ptrdestcr1 += destccstride; ptrdestcr2 += destccstride; } } /* convert 4:2:0 to yuv 4:2:2 */ /* *UYVY *YUYV *YVYU *VYUY */ void yuv420p_to_yuv422(uint8_t * yuv420[3], uint8_t * dest, int width, int height, int yuv_tab) { unsigned int x, y; for (y = 0; y < height; ++y) { uint8_t *Y = yuv420[0] + y * (width+32); uint8_t *U = yuv420[1] + (y / 2) * ((width+32) / 2); uint8_t *V = yuv420[2] + (y / 2) * ((width+32) / 2); for (x = 0; x < width; x += 2) { if(yuv_tab == YUV_UYVY){ *(dest + 0) = U[0]; *(dest + 1) = Y[0]; *(dest + 2) = V[0]; *(dest + 3) = Y[1]; } else if(yuv_tab == YUV_YUYV){ *(dest + 0) = Y[0]; *(dest + 1) = U[0]; *(dest + 2) = Y[1]; *(dest + 3) = V[0]; }else if(yuv_tab == YUV_YVYU){ *(dest + 0) = Y[0]; *(dest + 1) = V[0]; *(dest + 2) = Y[1]; *(dest + 3) = U[0]; }else if(yuv_tab == YUV_VYUY){ *(dest + 0) = V[0]; *(dest + 1) = Y[0]; *(dest + 2) = U[1]; *(dest + 3) = Y[1]; } dest += 4; Y += 2; ++U; ++V; } } } |
|
來自: 傳真閱覽室 > 《多媒體開發(fā)篇》