SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

在1.3的版本已经可以完美兼容Android

SDL1.3的源码可以到这个网址下载:http://download.csdn.net/detail/yqiang5152/5017621。

YUV测试序列下载地址:

下面是具体步骤:

1.将下载下来的zip包,解压,将文件名改为SDL,将SDL文件夹中的android-project拷贝出来。将SDL中的src和include以及根目录下的Android.mk文件,拷贝到android-project/jni 中。

2.将yuv测试序列拷贝到虚拟机或手机的sdcard上

3.通过分析SDL/src/main/SDL_android_main.cpp文件,我们可以发现,在java层调用nativeInit时,c层会执行SDL_main(),方法,而这个方法是在SDL_main.h中,将我们写的main函数重定义为SDL_main(),所以,我们自己的C代码中的main函数,即是入口。

4.播放yuv数据的C函数如下,写好的文件放在 android-project/jni/src中

#include "SDL.h"

#include

#include

#include

#include

#include

#include

#include

#include "MySDL.h"

#define LOG_TAG "JNI MYSDL"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

extern SDL_Surface* screen = NULL;

extern SDL_Overlay* overlay = NULL;

int play_SDL(int w, int h, char* pYuv, int zoom,int cutedW,int cutedH,int offsetX,int offsetY) {

//播放一帧的YUV数据,这里的yuv数据只的是YUV420

if (NULL == pYuv || w <= 0 || h <= 0)

{

return -1;

}

SDL_Rect rectSrc;

if(cutedW>0 || cutedH>0)

{

change_Overlay(cutedW,cutedH);

}

SDL_LockSurface(screen);

SDL_LockYUVOverlay(overlay);

if(cutedW==0 && cutedH==0)

{

memcpy(overlay->pixels[0], pYuv, w * h);

memcpy(overlay->pixels[2], pYuv + w * h, w * h / 4);

memcpy(overlay->pixels[1], pYuv + w * h + w * h / 4, w * h / 4);

rectSrc.w = w*zoom;

rectSrc.h = h*zoom;

rectSrc.x = rectSrc.y = 0;

}

else

{

int count=0,count1=0,count2=0;

int x=0,xU=0,xV=0;

int len=0,len1=0,len2=0;

char tempY[cutedW*cutedH];

char tempU[cutedW*cutedH/4];

char tempV[cutedW*cutedH/4];

x=w*offsetY+offsetX;

for(count;count

{

memcpy(tempY+len, pYuv+x,cutedW);

x+=w;

len+=cutedW;

}

xU=w/2*offsetY/2+offsetX/2;

for(count1;count1

{

memcpy(tempU+len1, pYuv+w*h+xU,cutedW/2);

xU+=w/2;

len1+=cutedW/2;

}

xV=w/2*offsetY/2+offsetX/2;

for(count2;count2

{

memcpy(tempV+len2, pYuv+w*h+w*h/4+xV,cutedW/2);

xV+=w/2;

len2+=cutedW/2;

}

memcpy(overlay->pixels[0], (const char *)tempY, cutedW * cutedH);

memcpy(overlay->pixels[2], (const char *)tempU, cutedW * cutedH/4);

memcpy(overlay->pixels[1], (const char *)tempV, cutedW * cutedH/4);

rectSrc.w = cutedW*zoom;

rectSrc.h = cutedH*zoom;

rectSrc.x = rectSrc.y = 0;

}

SDL_UnlockYUVOverlay(overlay);

SDL_UnlockSurface(screen);

SDL_DisplayYUVOverlay(overlay, &rectSrc);

return 0;

}

int init_SDL(int w, int h, char* pYuv, int swidth, int sheight, int zoom) {//初始化SDL 注意SDLScreen 如果创建后再更改会各种出问题,

//我建议直接创建手机或虚拟机屏幕大小,后面改变overlay就可以了

if (SDL_Init(SDL_INIT_VIDEO) < 0) {

fprintf(stderr, "can not initialize SDL:%s\n", SDL_GetError());

LOGI("can not initialize SDL");

exit(1);

}

atexit(SDL_Quit);

screen = SDL_SetVideoMode(swidth, sheight, 0, 0); //创建屏幕

LOGI("2!\n");

LOGI("screen creat success");

if (screen == NULL ) {

LOGI("create surface error!\n");

exit(1);

}

overlay = SDL_CreateYUVOverlay(w, h, SDL_YV12_OVERLAY, screen);

LOGI("overlay creat success");

if (overlay == NULL ) {

fprintf(stderr, "create overlay error!\n");

exit(1);

}

return 0;

}

int change_Overlay(int newWidth, int newHeight) {

if (overlay) {

SDL_FreeYUVOverlay(overlay);

}

overlay = SDL_CreateYUVOverlay(newWidth, newHeight, SDL_YV12_OVERLAY, screen);

return 0;

}

int release_SDL() {

if (overlay) {

SDL_FreeYUVOverlay(overlay);

}

if (screen) {

SDL_FreeSurface(screen);

}

LOGI("RELEASE SUCCESS");

return 2;

}

5.在int main()函数中,读取sdcard中的yuv测试序列,传入相关的宽高,如果需要切割部分图片,可以传入offetX、Y cutedX、Y。

6.修改android-project/jni/src中的Android.mk文件,将yoursoruce.c 替换为自己写的C文件名即可。

7. 命令行进入工程根目录,ndk-build 成功后会生成两个库 libSDL.so和libMain.so,如第二次编译不成功先把根目录下的obj文件删了试试

注:移植后,曾想将SDL库和main库分开编译,这样便于移植和管理。但是,由于main库编译的时候需要SDL库中的内容,没有找到在Android.mk文件中,直接指向动态库的方法,所以放弃了,有高人懂的,可以告诉我不胜感激。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐