Android本地视频播放器开发--视频解码


在上一章 Android本地视频播放器开发--SDL编译 编译中编译出sdl的支持库,当时我们使用的2.0,但是有些api被更改了,所以在以下的使用者中我们使用SDL1.3的库,这个库我会传上源码以及编译出的库,接下来这张我们使用ffmpeg解码视频文件中的视频帧同时使用SDL去显示。

1、Decodec_Video.c 这是我视频解码的文件,其中内容如下:

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <android/log.h>  
  3.   
  4. #ifdef __MINGW32__  
  5. #undef main /* Prevents SDL from overriding main() */  
  6. #endif  
  7.   
  8. #include "../SDL/include/SDL.h"  
  9. #include "../SDL/include/SDL_thread.h"  
  10.   
  11. #include "VideoPlayerDecode.h"  
  12. #include "../ffmpeg/libavutil/avutil.h"  
  13. #include "../ffmpeg/libavcodec/avcodec.h"  
  14. #include "../ffmpeg/libavformat/avformat.h"  
  15. #include "../ffmpeg/libswscale/swscale.h"  
  16.   
  17. AVFormatContext *pFormatCtx;  
  18. int             i, videoStream;  
  19. AVCodecContext  *pCodecCtx;  
  20. AVCodec         *pCodec;  
  21. AVFrame         *pFrame;  
  22. AVPacket        packet;  
  23. int             frameFinished;  
  24. float           aspect_ratio;  
  25.   
  26. static struct SwsContext *img_convert_ctx;  
  27. SDL_Surface     *screen;  
  28. SDL_Overlay *bmp;  
  29. SDL_Rect        rect;  
  30. SDL_Event       event;  
  31.   
  32.   
  33. JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer  
  34. (JNIEnv *env, jclass clz, jstring fileName)  
  35. {  
  36.     const char* local_title = (*env)->GetStringUTFChars(env, fileName, NULL);  
  37.     av_register_all();//注册所有支持的文件格式以及编解码器  
  38.     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {  
  39.         fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());  
  40.         exit(1);  
  41.     }  
  42.     if(avformat_open_input(&pFormatCtx, local_title, NULL, NULL) != 0)  
  43.                 return -1;  
  44.     if(avformat_find_stream_info(pFormatCtx, NULL) < 0)  
  45.                 return -1;  
  46.     av_dump_format(pFormatCtx, -1, local_title, 0);  
  47.     videoStream=-1;  
  48.     for(i=0; i<pFormatCtx->nb_streams; i++)  
  49.         if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {  
  50.             videoStream=i;  
  51.             break;  
  52.         }  
  53.     if(videoStream==-1)  
  54.         return -1; // Didn't find a video stream  
  55.     // Get a pointer to the codec context for the video stream  
  56.     pCodecCtx=pFormatCtx->streams[videoStream]->codec;  
  57.   
  58.     // Find the decoder for the video stream  
  59.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
  60.     if(pCodec==NULL) {  
  61.         fprintf(stderr, "Unsupported codec!\n");  
  62.         return -1; // Codec not found  
  63.     }  
  64.     if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)return -1;  
  65.     pFrame = avcodec_alloc_frame();  
  66.     if(pFrame == NULL)return -1;  
  67.     // Make a screen to put our video  
  68. #ifndef __DARWIN__  
  69.     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);  
  70. #else  
  71.     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);  
  72. #endif  
  73.     if(!screen) {  
  74.         fprintf(stderr, "SDL: could not set video mode - exiting\n");  
  75.         exit(1);  
  76.     }  
  77.     // Allocate a place to put our YUV image on that screen  
  78.     bmp = SDL_CreateYUVOverlay(pCodecCtx->width,  
  79.             pCodecCtx->height,  
  80.             SDL_YV12_OVERLAY,  
  81.             screen);  
  82.     img_convert_ctx = sws_getContext(pCodecCtx->width,    
  83.                           pCodecCtx->height, pCodecCtx->pix_fmt,    
  84.                           pCodecCtx->width, pCodecCtx->height,    
  85.                           PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);    
  86.   
  87.     // Read frames and save first five frames to disk  
  88.     i=0;  
  89.     while(av_read_frame(pFormatCtx, &packet)>=0) {  
  90.         // Is this a packet from the video stream?  
  91.         if(packet.stream_index==videoStream) {  
  92.             avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);  
  93.             // Did we get a video frame?  
  94.             if(frameFinished) {  
  95.                 SDL_LockYUVOverlay(bmp);  
  96.                   
  97.                 AVPicture *pict;  
  98.                 pict->data[0] = bmp->pixels[0];  
  99.                 pict->data[1] = bmp->pixels[2];  
  100.                 pict->data[2] = bmp->pixels[1];  
  101.   
  102.                 pict->linesize[0] = bmp->pitches[0];  
  103.                 pict->linesize[1] = bmp->pitches[2];  
  104.                 pict->linesize[2] = bmp->pitches[1];  
  105.                   
  106. sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pict->data, pict->linesize);  
  107.                 SDL_UnlockYUVOverlay(bmp);  
  108.   
  109.                 rect.x = 0;  
  110.                 rect.y = 0;  
  111.                 rect.w = pCodecCtx->width;  
  112.                 rect.h = pCodecCtx->height;  
  113.                 SDL_DisplayYUVOverlay(bmp, &rect);  
  114.   
  115.             }  
  116.         }  
  117.         // Free the packet that was allocated by av_read_frame  
  118.         av_free_packet(&packet);  
  119.         SDL_PollEvent(&event);  
  120.         switch(event.type) {  
  121.             case SDL_QUIT:  
  122.                 SDL_Quit();  
  123.                 exit(0);  
  124.                 break;  
  125.             default:  
  126.                 break;  
  127.         }  
  128.   
  129.     }  
  130.     // Free the YUV frame  
  131.     av_free(pFrame);  
  132.   
  133.     // Close the codec  
  134.     avcodec_close(pCodecCtx);  
  135.   
  136.     // Close the video file  
  137.     av_close_input_file(pFormatCtx);  
  138. }  

2、编译结果如下:

[cpp]  view plain copy
  1. root@zhangjie:/Graduation/jni# ndk-build  
  2. Install        : libSDL.so => libs/armeabi/libSDL.so  
  3. Install        : libffmpeg-neon.so => libs/armeabi/libffmpeg-neon.so  
  4. Compile arm    : ffmpeg-test-neon <= Decodec_Video.c  
  5. /Graduation/jni/jniffmpeg/Decodec_Video.c: In function 'Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer':  
  6. /Graduation/jni/jniffmpeg/Decodec_Video.c:106:1: warning: passing argument 2 of 'sws_scale' from incompatible pointer type [enabled by default]  
  7. /Graduation/jni/jniffmpeg/../ffmpeg/libswscale/swscale.h:237:5: note: expected 'uint8_t const * const*' but argument is of type 'uint8_t **'  
  8. /Graduation/jni/jniffmpeg/Decodec_Video.c:137:2: warning: 'av_close_input_file' is deprecated (declared at /Graduation/jni/jniffmpeg/../ffmpeg/libavformat/avformat.h:1533) [-Wdeprecated-declarations]  
  9. SharedLibrary  : libffmpeg-test-neon.so  
  10. Install        : libffmpeg-test-neon.so => libs/armeabi/libffmpeg-test-neon.so  
3、SDL1.3源码

http://download.csdn.net/detail/heng615975867/7038535

4、之前在Android本地视频播放器开发--NDK编译FFmpeg中没有添加swscale功能,所以需要重新编译ffmpeg,其脚本如下:

[plain]  view plain copy
  1. NDK=/opt/android-ndk-r8d  
  2. PLATFORM=$NDK/platforms/android-8/arch-arm/  
  3. PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86  
  4. LOCAL_ARM_NEON=true  
  5. CPU=armv7-a  
  6. OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -mcpu=cortex-a8"  
  7. PREFIX=./android/$CPU  
  8. ./configure --target-os=linux \  
  9.     --prefix=$PREFIX \  
  10.     --enable-cross-compile \  
  11.     --arch=arm \  
  12.     --enable-nonfree \  
  13.     --enable-asm \  
  14.     --cpu=cortex-a8 \  
  15.     --enable-neon \  
  16.     --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \  
  17.     --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \  
  18.     --nm=$PREBUILT/bin/arm-linux-androideabi-nm \  
  19.     --sysroot=$PLATFORM \  
  20.     --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 $OPTIMIZE_CFLAGS " \  
  21.     --disable-shared \  
  22.     --enable-static \  
  23.     --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -nostdlib -lc -lm -ldl -llog" \  
  24.     --disable-ffmpeg \  
  25.     --disable-ffplay \  
  26.     --disable-ffprobe \  
  27.     --disable-ffserver \  
  28.     --disable-encoders \  
  29.     --enable-avformat \  
  30.     --disable-optimizations \  
  31.     --disable-doc \  
  32.     --enable-pthreads \  
  33.     --disable-yasm \  
  34.     --enable-zlib \  
  35.     --enable-pic \  
  36.     --enable-small  
  37.   
  38. #make clean  
  39. make  -j4 install  
  40.   
  41. $PREBUILT/bin/arm-linux-androideabi-ar d libavcodec/libavcodec.a inverse.o  
  42.   
  43. $PREBUILT/bin/arm-linux-androideabi-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -soname libffmpeg-neon.so -shared -nostdlib  -z noexecstack -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg-neon.so libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a  libavfilter/libavfilter.a libswresample/libswresample.a libswscale/libswscale.a libavdevice/libavdevice.a -lc -lm -lz -ldl -llog  --warn-once  --dynamic-linker=/system/bin/linker $PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值