views:

551

answers:

0

Hi Experts,

I am trying to run surfaceflinger client code for Android 2.0 platform. It is supposed to post frames on android surfaceflinger. It is resulting in crash of the Android OS and resulting in restart of the emulator.

Please help. Many thanks.

Kind Regards -Durgesh O Mishra

Here is the code.

int main(int argc, char** argv) { VideoFlingerDeviceHandle videodev = NULL; short framebuf[WIDTH*HEIGHT];

LOGE("surface_test, enter\n");

// create surface flinger
videodev = videoflinger_device_create(NULL);
LOGE("surface_test, after device create\n");
// register buffer
videoflinger_device_register_framebuffers(videodev, WIDTH, HEIGHT, VIDEO_FLINGER_RGB_565);
LOGE("surface_test, after device register\n");
for (int step=0; step<MAX_STEP; step++)
{
    for (int i=0; i< WIDTH*HEIGHT; i++)
    {
        framebuf[i] = (short)(i + step*16) ;
    }
    // post buffer
    LOGE("surface_test, before device post\n");
    videoflinger_device_post(videodev, framebuf, WIDTH*HEIGHT*sizeof(short));
    LOGE("surface_test, after device post\n");
    usleep(5*1000*10);
}

// unregister buffer
videoflinger_device_unregister_framebuffers(videodev);

// free buffer
videoflinger_device_release(videodev);

LOGE("surface_test, leave\n");

return 0;

}

////////////////////////////////////////////

include

include

include

//Durgesh ported to 2.0 //#include //#include

include

include

include

include "surfaceflinger_wrap.h"

include

/* max frame buffers */

define MAX_FRAME_BUFFERS 2

using namespace android;

typedef struct { sp frame_heap; sp isurface; //sp surface; sp surface; int32_t hor_stride; int32_t ver_stride; uint32_t width; uint32_t height; PixelFormat format; int frame_offset[MAX_FRAME_BUFFERS]; int buf_index; } VideoFlingerDevice;

static int videoflinger_device_create_new_surface(VideoFlingerDevice* videodev);

/* * The only purpose of class "MediaPlayer" is to call Surface::getISurface() * in frameworks/base/include/ui/Surface.h, which is private function and accessed * by friend class MediaPlayer. * * We define a fake one to cheat compiler / namespace android { class MediaPlayer { public: static sp getSurface(const SurfaceControl surface) { return surface->getISurface(); }; }; };

VideoFlingerDeviceHandle videoflinger_device_create(void* isurface) { VideoFlingerDevice *videodev = NULL;

GST_PLAYER_INFO("Enter\n");
videodev = new VideoFlingerDevice;
if (videodev == NULL)
{
    return NULL;
}
videodev->frame_heap.clear();
videodev->isurface = (ISurface*)isurface;
videodev->surface.clear();
//videodev->surface_control.clear();
videodev->format = -1;
videodev->width = 0;
videodev->height = 0;
videodev->hor_stride = 0;
videodev->ver_stride = 0;
videodev->buf_index = 0;
for ( int i = 0; i<MAX_FRAME_BUFFERS; i++)
{
    videodev->frame_offset[i] = 0;
}

GST_PLAYER_INFO("Leave\n");
return (VideoFlingerDeviceHandle)videodev;    

}

int videoflinger_device_create_new_surface(VideoFlingerDevice* videodev) { status_t state; int pid = getpid();

GST_PLAYER_INFO("Enter\n");

/* Create a new Surface object with 320x240
 * TODO: Create surface according to device's screen size and rotate it
 * 90, but not a pre-defined value.
 */
sp<SurfaceComposerClient> videoClient = new SurfaceComposerClient;
if (videoClient.get() == NULL)
{
    GST_PLAYER_ERROR("Fail to create SurfaceComposerClient\n");
    return -1;
}

/* release privious surface */
if(videodev->surface != NULL && videodev->surface->getSurface()!=NULL) videodev->surface->getSurface().clear();

videodev->surface.clear();
videodev->isurface.clear();


int width = (videodev->width) > 320 ? 320 : videodev->width;
int height = (videodev->height) > 320 ? 320 : videodev->height;

videodev->surface = videoClient->createSurface(
        pid, 
        0, 
        width, 
        height, 
        PIXEL_FORMAT_RGB_565, 
        ISurfaceComposer::eFXSurfaceNormal|ISurfaceComposer::ePushBuffers);



if (videodev->surface.get() == NULL)
{
    GST_PLAYER_ERROR("Fail to create Surface\n");
    return -1;
}

videoClient->openTransaction();

/* set Surface toppest z-order, this will bypass all isurface created 
 * in java side and make sure this surface displaied in toppest */
state =  videodev->surface->setLayer(INT_MAX);
if (state != NO_ERROR)
{
    GST_PLAYER_INFO("videoSurface->setLayer(), state = %d", state);
    videodev->surface.clear();
    return -1;
}

/* show surface */

state =  videodev->surface->show();
state =  videodev->surface->setLayer(INT_MAX);
if (state != NO_ERROR)
{
    GST_PLAYER_INFO("videoSurface->show(), state = %d", state);
    videodev->surface.clear();
    return -1;
}

/* get ISurface interface */
videodev->isurface = MediaPlayer::getSurface(videodev->surface.get());

videoClient->closeTransaction();

/* Smart pointer videoClient shall be deleted automatically
 * when function exists
 */
GST_PLAYER_INFO("Leave\n");
return 0;

}

int videoflinger_device_release(VideoFlingerDeviceHandle handle) { GST_PLAYER_INFO("Enter");

if (handle == NULL)
{
    return -1;
}

/* unregister frame buffer */
videoflinger_device_unregister_framebuffers(handle); 

/* release ISurface & Surface */
VideoFlingerDevice *videodev = (VideoFlingerDevice*)handle;
videodev->isurface.clear();
videodev->surface.clear();

/* delete device */
delete videodev;

GST_PLAYER_INFO("Leave");
return 0;

}

int videoflinger_device_register_framebuffers(VideoFlingerDeviceHandle handle, int w, int h, VIDEO_FLINGER_PIXEL_FORMAT format) { int surface_format = 0;

//LOGE("1\n");
GST_PLAYER_INFO("Enter");
if (handle == NULL)
{
    GST_PLAYER_ERROR("videodev is NULL");
    return -1;
}

/* TODO: Now, only PIXEL_FORMAT_RGB_565 is supported. Change here to support
 * more pixel type
 */
//LOGE("2\n");
if (format !=  VIDEO_FLINGER_RGB_565 )
{
    GST_PLAYER_ERROR("Unsupport format: %d", format);
    return -1;
}
surface_format = PIXEL_FORMAT_RGB_565;

VideoFlingerDevice *videodev = (VideoFlingerDevice*)handle;
//LOGE("3\n");
/* unregister previous buffers */
if (videodev->frame_heap.get())
{
    videoflinger_device_unregister_framebuffers(handle);
}
//LOGE("4\n");
/* reset framebuffers */
videodev->format = surface_format;
videodev->width = (w + 1) & -2;
videodev->height = (h + 1) & -2;
videodev->hor_stride = videodev->width;
videodev->ver_stride =  videodev->height;

/* create isurface internally, if no ISurface interface input */
//LOGE("5\n");
if (videodev->isurface == NULL || videodev->isurface.get() == NULL)
{
    videoflinger_device_create_new_surface(videodev);
}
//LOGE("6\n");
/* use double buffer in post */
int frameSize = videodev->width * videodev->height * 2;
//LOGE("7\n");

GST_PLAYER_INFO( 
    "format=%d, width=%d, height=%d, hor_stride=%d, ver_stride=%d, frameSize=%d",
    videodev->format,
    videodev->width,
    videodev->height,
    videodev->hor_stride,
    videodev->ver_stride,
    frameSize);
//LOGE("8\n");
/* create frame buffer heap base */
videodev->frame_heap = new MemoryHeapBase(frameSize * MAX_FRAME_BUFFERS);
//LOGE("9\n");
if (videodev->frame_heap->heapID() < 0) 
{
    GST_PLAYER_ERROR("Error creating frame buffer heap!");
    return -1;
}
//LOGE("10\n");
/* create frame buffer heap and register with surfaceflinger */
ISurface::BufferHeap buffers(
    videodev->width,
    videodev->height,
    videodev->hor_stride,
    videodev->ver_stride,
    videodev->format,
    videodev->frame_heap);
//LOGE("11\n");
if (videodev->isurface->registerBuffers(buffers) < 0 )
{
    GST_PLAYER_ERROR("Cannot register frame buffer!");
    videodev->frame_heap.clear();
    return -1;
}
//LOGE("12\n");
for ( int i = 0; i<MAX_FRAME_BUFFERS; i++)
{
    videodev->frame_offset[i] = i*frameSize;
}
//LOGE("13\n");
videodev->buf_index = 0;
GST_PLAYER_INFO("Leave");

return 0;

}

void videoflinger_device_unregister_framebuffers(VideoFlingerDeviceHandle handle) { GST_PLAYER_INFO("Enter");

if (handle == NULL)
{
    return;
}

VideoFlingerDevice* videodev = (VideoFlingerDevice*)handle;
if (videodev->frame_heap.get())
{
    GST_PLAYER_INFO("Unregister frame buffers.  videodev->isurface = %p", videodev->isurface.get());

    /* release ISurface */
    GST_PLAYER_INFO("Unregister frame buffer");
    videodev->isurface->unregisterBuffers();

    /* release MemoryHeapBase */
    GST_PLAYER_INFO("Clear frame buffers.");
    videodev->frame_heap.clear();

    /* reset offset */
    for (int i = 0; i<MAX_FRAME_BUFFERS; i++)
    {
        videodev->frame_offset[i] = 0;
    }

    videodev->format = -1;
    videodev->width = 0;
    videodev->height = 0;
    videodev->hor_stride = 0;
    videodev->ver_stride = 0;
    videodev->buf_index = 0;
}

GST_PLAYER_INFO("Leave");

}

void videoflinger_device_post(VideoFlingerDeviceHandle handle, void * buf, int bufsize) { GST_PLAYER_INFO("Enter"); LOGE("1\n"); if (handle == NULL) { return; } LOGE("2\n"); VideoFlingerDevice* videodev = (VideoFlingerDevice*)handle;

if (++videodev->buf_index == MAX_FRAME_BUFFERS) 
    videodev->buf_index = 0;
LOGE("3\n");
memcpy (static_cast<unsigned char *>(videodev->frame_heap->base()) + videodev->frame_offset[videodev->buf_index],  buf, bufsize);
LOGE("4\n");
GST_PLAYER_INFO ("Post buffer[%d].\n", videodev->buf_index);
videodev->isurface->postBuffer(videodev->frame_offset[videodev->buf_index]);
LOGE("5\n");
GST_PLAYER_INFO("Leave");

}