背景介绍
SDL2官方已支持android了, 而git ffmpeg 上还是沿用老的SDL1.2。据目前我搜索的信息,目前还没有ffplay在sdl2上跑的实例。 能把ffplay 放到android上跑,也算是为开源社区尽一份绵薄之力。
计划
avplay -- 简单的视频播放,使用SDL2, 在PC上测试。
ffplay -- 完整的音视频播放,使用SDL2, 在PC上测试。
configure -- 修改支持SDL2自动编译。
移植SDL2 到android 手机上。
移植完整版ffmpeg/ffplay 到android手机上。
下载和准备
由于我在两个地方使用windows xp 和ubuntu14.04,而ubuntu上编译异常顺利。下面介绍xp上的编译环境。
如果想偷懒(xp上编译实在很慢):
http://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-20141204-git-5fe026f-win32-dev.7z
http://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-20141204-git-5fe026f-win32-shared.7z
都解压到/e/tools/Players/ffmpeg下面。
然后在/etc/profile 加上PATH="/e/tools/Player/ffmpeg/bin":$PATH
编译
cd SDL-2.0.4-9174
./configure --prefix=$HOME/porting/host && make && make install
./configure --with-sdl-prefix=/e/ludi/porting/host
make -- 编不过,见下面的注意事项0。
然后就是下面头文件里面的:
/*
../ffmpeg/configure --prefix=$HOME/porting/host \
--disable-outdev=sdl --disable-ffplay \
--enable-version3 --enable-nonfree --disable-optimizations \
--enable-gpl --enable-libx264
make -j16 && make install
export PKG_CONFIG_PATH=$HOME/porting/host/lib/pkgconfig
compile:
gcc avplay.c -g $(~/porting/host/bin/sdl2-config --cflags --libs) \
$(pkg-config --cflags libavcodec --libs libavcodec libavformat libavutil)
on windows:
gcc avplay.c -g $(~/porting/host/bin/sdl2-config --cflags --libs) \
-I/e/tools/Player/ffmpeg/include/ -L/e/tools/Player/ffmpeg/lib/ -lavformat -lavcodec -lswresample -lavutil -lm
*/
#include
#include
#include
#include
#include
int main(int ac, char **av) { AVFormatContext *fmtctx = NULL; int ret, i, vidx = -1; AVCodecContext *cdctx = NULL; AVCodec *dec = NULL; AVPacket pkt; AVFrame *frame; SDL_Rect rect; SDL_Window *win; SDL_Renderer *render; SDL_Texture *texture; SDL_Event evt; if(ac < 2){ return printf("usage: play infile\n"); } av_register_all(); ret = avformat_open_input(&fmtctx, av[1], NULL, NULL); if(ret < 0){ return printf("cant open %s\n", av[1]); } ret = avformat_find_stream_info(fmtctx, NULL); if(ret < 0){ return printf("cant find stream\n"); } av_dump_format(fmtctx, 0, av[1], 0); for(i = 0; i < fmtctx->nb_streams; ++i){ if(fmtctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){ vidx = i; break; } } if(-1 == vidx){ return printf("no video stream\n"); } cdctx = fmtctx->streams[vidx]->codec; if(cdctx->pix_fmt != AV_PIX_FMT_YUV420P){ return printf("unkown pix fmt %d\n", cdctx->pix_fmt); } dec = avcodec_find_decoder(cdctx->codec_id); if(!dec){ return printf("no decoder\n"); } ret = avcodec_open2(cdctx, dec, NULL); if(ret < 0){ return printf("cant open dec\n"); } frame = av_frame_alloc(); rect.x = rect.y = 0; rect.w = cdctx->width; rect.h = cdctx->height; if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)){ return printf("cant init: %s\n", SDL_GetError()); } win = SDL_CreateWindow(av[1], SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, cdctx->width, cdctx->height, 0); if(!win){ return printf("cant create win mode\n"); } render = SDL_CreateRenderer(win, -1, SDL_RENDERER_TARGETTEXTURE); texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, cdctx->width, cdctx->height); if(!texture){ return printf("cant create texture\n"); } #if 1 void *pixels = 0; int pitch = 0; unsigned char *d = NULL; SDL_LockTexture(texture, NULL, &pixels, &pitch); d = (unsigned char *)pixels;//U ? cdctx->height*pitch; printf("pixels/pitch %p/%u -- %02x %02x %02x %02x\n", pixels, pitch, d[0], d[1], d[2], d[3]); SDL_UnlockTexture(texture); #endif while(av_read_frame(fmtctx, &pkt) >= 0){ if(pkt.stream_index == vidx){ avcodec_decode_video2(cdctx, frame, &ret, &pkt); if(ret){ SDL_UpdateYUVTexture(texture, NULL, frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]); SDL_RenderClear(render); SDL_RenderCopy(render, texture, &rect, &rect); SDL_RenderPresent(render); } SDL_Delay(50); } av_free_packet(&pkt); SDL_PollEvent(&evt); if(SDL_QUIT == evt.type){ break; } } SDL_Quit(); av_free(frame); avcodec_close(cdctx); avformat_close_input(&fmtctx); return 0; }
注意事项
0. hg版本的sd2-config 需要改成:
--libs|--static-libs)
echo -L${exec_prefix}/lib -lmingw32 -lSDL2main -lSDL2 -Wl,--no-undefined -lm -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -static-libgcc
1. 要把SDL2.dll 拷贝到 SDL-2.0.4-9174/test 下面才能跑那些例子。
2.确保ffmpeg相关dll在PATH里面。
小结
第一步算是走出来了。