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

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

[cpp]
#include <stdio.h>  
#include <android/log.h>  
 
#ifdef __MINGW32__  
#undef main /* Prevents SDL from overriding main() */  
#endif  
 
#include "../SDL/include/SDL.h"  
#include "../SDL/include/SDL_thread.h"  
 
#include "VideoPlayerDecode.h"  
#include "../ffmpeg/libavutil/avutil.h"  
#include "../ffmpeg/libavcodec/avcodec.h"  
#include "../ffmpeg/libavformat/avformat.h"  
#include "../ffmpeg/libswscale/swscale.h"  
 
AVFormatContext *pFormatCtx; 
int             i, videoStream; 
AVCodecContext  *pCodecCtx; 
AVCodec         *pCodec; 
AVFrame         *pFrame; 
AVPacket        packet; 
int             frameFinished; 
float           aspect_ratio; 
 
static struct SwsContext *img_convert_ctx; 
SDL_Surface     *screen; 
SDL_Overlay *bmp; 
SDL_Rect        rect; 
SDL_Event       event; 
 
 
JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer 
(JNIEnv *env, jclass clz, jstring fileName) 

    const char* local_title = (*env)->GetStringUTFChars(env, fileName, NULL); 
    av_register_all();//注册所有支持的文件格式以及编解码器  
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { 
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); 
        exit(1); 
    } 
    if(avformat_open_input(&pFormatCtx, local_title, NULL, NULL) != 0) 
                return -1; 
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0) 
                return -1; 
    av_dump_format(pFormatCtx, -1, local_title, 0); 
    videoStream=-1; 
    for(i=0; i<pFormatCtx->nb_streams; i++) 
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) { 
            videoStream=i; 
            break; 
        } 
    if(videoStream==-1) 
        return -1; // Didn't find a video stream  
    // Get a pointer to the codec context for the video stream  
    pCodecCtx=pFormatCtx->streams[videoStream]->codec; 
 
    // Find the decoder for the video stream  
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id); 
    if(pCodec==NULL) { 
        fprintf(stderr, "Unsupported codec!\n"); 
        return -1; // Codec not found  
    } 
    if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)return -1; 
    pFrame = avcodec_alloc_frame(); 
    if(pFrame == NULL)return -1; 
    // Make a screen to put our video  
#ifndef __DARWIN__  
    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0); 
#else  
    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0); 
#endif  
    if(!screen) { 
        fprintf(stderr, "SDL: could not set video mode - exiting\n"); 
        exit(1); 
    } 
    // Allocate a place to put our YUV image on that screen  
    bmp = SDL_CreateYUVOverlay(pCodecCtx->width, 
            pCodecCtx->height, 
            SDL_YV12_OVERLAY, 
            screen); 
    img_convert_ctx = sws_getContext(pCodecCtx->width,   
                          pCodecCtx->height, pCodecCtx->pix_fmt,   
                          pCodecCtx->width, pCodecCtx->height,   
                          PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);   
 
    // Read frames and save first five frames to disk  
    i=0; 
    while(av_read_frame(pFormatCtx, &packet)>=0) { 
        // Is this a packet from the video stream?  
        if(packet.stream_index==videoStream) { 
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); 
            // Did we get a video frame?  
            if(frameFinished) { 
                SDL_LockYUVOverlay(bmp); 
                 
                AVPicture *pict; 
                pict->data[0] = bmp->pixels[0]; 
                pict->data[1] = bmp->pixels[2]; 
                pict->data[2] = bmp->pixels[1]; 
 
                pict->linesize[0] = bmp->pitches[0]; 
                pict->linesize[1] = bmp->pitches[2]; 
                pict->linesize[2] = bmp->pitches[1]; 
                 
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pict->data, pict->linesize); 
                SDL_UnlockYUVOverlay(bmp); 
 
                rect.x = 0; 
                rect.y = 0; 
                rect.w = pCodecCtx->width; 
                rect.h = pCodecCtx->height; 
                SDL_DisplayYUVOverlay(bmp, &rect); 
 
            } 
        } 
        // Free the packet that was allocated by av_read_frame  
        av_free_packet(&packet); 
        SDL_PollEvent(&event); 
        switch(event.type) { 
            case SDL_QUIT: 
                SDL_Quit(); 
                exit(0); 
                break; 
            default: 
                break; 
        } 
 
    } 
    // Free the YUV frame  
    av_free(pFrame); 
 
    // Close the codec  
    avcodec_close(pCodecCtx); 
 
    // Close the video file  
    av_close_input_file(pFormatCtx); 
}

#include <stdio.h>
#include <android/log.h>

#ifdef __MINGW32__
#undef main /* Prevents SDL from overriding main() */
#endif

#include "../SDL/include/SDL.h"
#include "../SDL/include/SDL_thread.h"

#include "VideoPlayerDecode.h"
#include "../ffmpeg/libavutil/avutil.h"
#include "../ffmpeg/libavcodec/avcodec.h"
#include "../ffmpeg/libavformat/avformat.h"
#include "../ffmpeg/libswscale/swscale.h"

AVFormatContext *pFormatCtx;
int             i, videoStream;
AVCodecContext  *pCodecCtx;
AVCodec         *pCodec;
AVFrame         *pFrame;
AVPacket        packet;
int             frameFinished;
float           aspect_ratio;

static struct SwsContext *img_convert_ctx;
SDL_Surface     *screen;
SDL_Overlay *bmp;
SDL_Rect        rect;
SDL_Event       event;

JNIEXPORT jint JNICALL Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer
(JNIEnv *env, jclass clz, jstring fileName)
{
 const char* local_title = (*env)->GetStringUTFChars(env, fileName, NULL);
 av_register_all();//注册所有支持的文件格式以及编解码器
 if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
  fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
  exit(1);
 }
 if(avformat_open_input(&pFormatCtx, local_title, NULL, NULL) != 0)
                return -1;
 if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
                return -1;
 av_dump_format(pFormatCtx, -1, local_title, 0);
 videoStream=-1;
 for(i=0; i<pFormatCtx->nb_streams; i++)
  if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
   videoStream=i;
   break;
  }
 if(videoStream==-1)
  return -1; // Didn't find a video stream
 // Get a pointer to the codec context for the video stream
 pCodecCtx=pFormatCtx->streams[videoStream]->codec;

// Find the decoder for the video stream
 pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
 if(pCodec==NULL) {
  fprintf(stderr, "Unsupported codec!\n");
  return -1; // Codec not found
 }
 if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)return -1;
 pFrame = avcodec_alloc_frame();
 if(pFrame == NULL)return -1;
 // Make a screen to put our video
#ifndef __DARWIN__
 screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
#else
 screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);
#endif
 if(!screen) {
  fprintf(stderr, "SDL: could not set video mode - exiting\n");
  exit(1);
 }
 // Allocate a place to put our YUV image on that screen
 bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
   pCodecCtx->height,
   SDL_YV12_OVERLAY,
   screen);
  img_convert_ctx = sws_getContext(pCodecCtx->width, 
                          pCodecCtx->height, pCodecCtx->pix_fmt, 
                          pCodecCtx->width, pCodecCtx->height, 
                          PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

// Read frames and save first five frames to disk
 i=0;
 while(av_read_frame(pFormatCtx, &packet)>=0) {
  // Is this a packet from the video stream?
  if(packet.stream_index==videoStream) {
   avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
   // Did we get a video frame?
   if(frameFinished) {
    SDL_LockYUVOverlay(bmp);
    
    AVPicture *pict;
    pict->data[0] = bmp->pixels[0];
    pict->data[1] = bmp->pixels[2];
    pict->data[2] = bmp->pixels[1];

pict->linesize[0] = bmp->pitches[0];
    pict->linesize[1] = bmp->pitches[2];
    pict->linesize[2] = bmp->pitches[1];
    
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pict->data, pict->linesize);
    SDL_UnlockYUVOverlay(bmp);

rect.x = 0;
    rect.y = 0;
    rect.w = pCodecCtx->width;
    rect.h = pCodecCtx->height;
    SDL_DisplayYUVOverlay(bmp, &rect);

}
  }
  // Free the packet that was allocated by av_read_frame
  av_free_packet(&packet);
  SDL_PollEvent(&event);
  switch(event.type) {
   case SDL_QUIT:
    SDL_Quit();
    exit(0);
    break;
   default:
    break;
  }

}
 // Free the YUV frame
 av_free(pFrame);

// Close the codec
 avcodec_close(pCodecCtx);

// Close the video file
 av_close_input_file(pFormatCtx);
}
2、编译结果如下:

[cpp]
root@zhangjie:/Graduation/jni# ndk-build 
Install        : libSDL.so => libs/armeabi/libSDL.so 
Install        : libffmpeg-neon.so => libs/armeabi/libffmpeg-neon.so 
Compile arm    : ffmpeg-test-neon <= Decodec_Video.c 
/Graduation/jni/jniffmpeg/Decodec_Video.c: In function 'Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer': 
/Graduation/jni/jniffmpeg/Decodec_Video.c:106:1: warning: passing argument 2 of 'sws_scale' from incompatible pointer type [enabled by default] 
/Graduation/jni/jniffmpeg/../ffmpeg/libswscale/swscale.h:237:5: note: expected 'uint8_t const * const*' but argument is of type 'uint8_t **' 
/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] 
SharedLibrary  : libffmpeg-test-neon.so 
Install        : libffmpeg-test-neon.so => libs/armeabi/libffmpeg-test-neon.so

root@zhangjie:/Graduation/jni# ndk-build
Install        : libSDL.so => libs/armeabi/libSDL.so
Install        : libffmpeg-neon.so => libs/armeabi/libffmpeg-neon.so
Compile arm    : ffmpeg-test-neon <= Decodec_Video.c
/Graduation/jni/jniffmpeg/Decodec_Video.c: In function 'Java_com_zhangjie_graduation_videopalyer_jni_VideoPlayerDecode_VideoPlayer':
/Graduation/jni/jniffmpeg/Decodec_Video.c:106:1: warning: passing argument 2 of 'sws_scale' from incompatible pointer type [enabled by default]
/Graduation/jni/jniffmpeg/../ffmpeg/libswscale/swscale.h:237:5: note: expected 'uint8_t const * const*' but argument is of type 'uint8_t **'
/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]
SharedLibrary  : libffmpeg-test-neon.so
Install        : libffmpeg-test-neon.so => libs/armeabi/libffmpeg-test-neon.so3、SDL1.3源码

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

[plain]
NDK=/opt/android-ndk-r8d 
PLATFORM=$NDK/platforms/android-8/arch-arm/ 
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86 
LOCAL_ARM_NEON=true 
CPU=armv7-a 
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -mcpu=cortex-a8" 
PREFIX=./android/$CPU 
./configure --target-os=linux \ 
    --prefix=$PREFIX \ 
    --enable-cross-compile \ 
    --arch=arm \ 
    --enable-nonfree \ 
    --enable-asm \ 
    --cpu=cortex-a8 \ 
    --enable-neon \ 
    --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \ 
    --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \ 
    --nm=$PREBUILT/bin/arm-linux-androideabi-nm \ 
    --sysroot=$PLATFORM \ 
    --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 $OPTIMIZE_CFLAGS " \ 
    --disable-shared \ 
    --enable-static \ 
    --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -nostdlib -lc -lm -ldl -llog" \ 
    --disable-ffmpeg \ 
    --disable-ffplay \ 
    --disable-ffprobe \ 
    --disable-ffserver \ 
    --disable-encoders \ 
    --enable-avformat \ 
    --disable-optimizations \ 
    --disable-doc \ 
    --enable-pthreads \ 
    --disable-yasm \ 
    --enable-zlib \ 
    --enable-pic \ 
    --enable-small 
 
#make clean 
make  -j4 install 
 
$PREBUILT/bin/arm-linux-androideabi-ar d libavcodec/libavcodec.a inverse.o 
 
$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

NDK=/opt/android-ndk-r8d
PLATFORM=$NDK/platforms/android-8/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86
LOCAL_ARM_NEON=true
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -mcpu=cortex-a8"
PREFIX=./android/$CPU
./configure --target-os=linux \
    --prefix=$PREFIX \
    --enable-cross-compile \
    --arch=arm \
    --enable-nonfree \
    --enable-asm \
    --cpu=cortex-a8 \
    --enable-neon \
    --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
    --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
    --nm=$PREBUILT/bin/arm-linux-androideabi-nm \
    --sysroot=$PLATFORM \
    --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 $OPTIMIZE_CFLAGS " \
    --disable-shared \
    --enable-static \
    --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -nostdlib -lc -lm -ldl -llog" \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-encoders \
    --enable-avformat \
    --disable-optimizations \
    --disable-doc \
    --enable-pthreads \
    --disable-yasm \
    --enable-zlib \
    --enable-pic \
    --enable-small

#make clean
make  -j4 install

$PREBUILT/bin/arm-linux-androideabi-ar d libavcodec/libavcodec.a inverse.o

$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

怎样在Android本地视频播放器开发的更多相关文章

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

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

  2. Android本地视频播放器开发--简易播放器原型

    在以前的基础上,将音视频进行合并,音频播放采用OpenSL ES,视频播放采用OpenGL ES2.0进行显示,这次的版本其中音频和视频是在同一个线程,会造成音频断断续续,后续会采用音频使用SDL,视 ...

  3. React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发

    React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发   2016/09/23 |  React Native技术文章 |  Sky丶清|  4 条评论 |  1 ...

  4. android音乐播放器开发教程

    android音乐播放器开发教程 Android扫描sd卡和系统文件 Android 关于录音文件的编解码 实现米聊 微信一类的录音上传的功能 android操作sdcard中的多媒体文件——音乐列表 ...

  5. android视频播放器开发

    http://blog.csdn.net/u010181592/article/details/49301703 http://blog.csdn.net/qq_33291295/article/de ...

  6. 22_Android中的本地音乐播放器和网络音乐播放器的编写,本地视频播放器和网络视频播放器,照相机案例,偷拍案例实现

    1 编写以下案例: 当点击了"播放"之后,在手机上的/mnt/sdcard2/natural.mp3就会播放. 2 编写布局文件activity_main.xml <Line ...

  7. android音乐播放器开发 SweetMusicPlayer 载入歌曲列表

    上一篇写了播放器的总体实现思路,http://blog.csdn.net/huweigoodboy/article/details/39855653,如今来总结下载入歌曲列表. 代码地址:https: ...

  8. android音乐播放器开发 SweetMusicPlayer 播放本地音乐

    上一篇写了载入歌曲列表,http://blog.csdn.net/huweigoodboy/article/details/39856411,如今来总结下播放本地音乐. 一,MediaPlayer 首 ...

  9. android音乐播放器开发 SweetMusicPlayer 智能匹配本地歌词

    上一篇写了使用MediaPlayer播放音乐,http://blog.csdn.net/huweigoodboy/article/details/39861539. 代码地址:https://gith ...

随机推荐

  1. urllib模块

    python爬虫-urllib模块   urllib 模块是一个高级的 web 交流库,其核心功能就是模仿web浏览器等客户端,去请求相应的资源,并返回一个类文件对象.urllib 支持各种 web ...

  2. Swing Dance!摇摆舞!小组

    Swing Dance!摇摆舞!小组 Swing Dance!摇摆舞

  3. Bitmap Style Designer非官方说明

    Bitmap Style Designer Bitmap Style Designer给我的第一印象就是简陋,估计也是为了赶工.大致体会了一下,还是能够使用.因为目前没有对此有比较详细的中文资料,就把 ...

  4. PHP中遍历stdclass object 及 json 总结[中国航天神舟十号以json形式向地面返回数据]

    $test=Array ( [0] => stdClass Object ( [tags] => 最快的车,Bloodhound,SSC [id] => 48326888 11 从网 ...

  5. DDD领域驱动设计的理解

    DDD领域驱动设计的理解 从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能 ...

  6. MFC 在对话框显示图片的多种方法(四种方法)

    我们先从简单的开始吧.先分一个类: (一) 非动态显示图片(即图片先通过资源管理器载入,有一个固定ID) (二) 动态载入图片(即只需要在程序中指定图片的路径即可载入) 为方便说明,我们已经建好一个基 ...

  7. 认识axure组件区域

    组件区域也叫做部件区域,英文为widgets,还有人称之为控件区域,组件是axure事先准备好的网站项目常用的零件,比如一些基本的页面元素 Axure默认存在2个组件库,分别为线框图和流程图.同时我们 ...

  8. 8天玩转并行开发——第二天 Task的使用

    原文 8天玩转并行开发——第二天 Task的使用 在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于 “任务的编程模型”所冲击, ...

  9. [Unity3D]Unity3D游戏开发之《愤慨的小鸟》弹弓实现

    各位朋友,大家晚上好, 我是秦元培.欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei.今天我们来做一个高端大气上档次的东西. 我相信大家都玩过一款叫做<愤慨的 ...

  10. JSTL解析——001

    JSTL 全称jsp standard tag library ,即jsp标准标签库. 是不是想问标签是什么东西? 标签就是jsp专门用于显示数据的,可重复利用的类库: 是不是想问标签由那些部分组成的 ...