在Android平台上實現H264解碼,一般采用開源的ffmpeg來實現,那麼這就涉及一個問題:如何在android平台上移植ffmpeg?
這個移植的方法在網上有一大推,本人看得頭暈,所以采用了一個取巧的辦法:在android平台上編譯XBMC的時候,編譯成功後,在目錄~/xbmc-android/tools/android/packaging/xbmc/lib/armeabi-v7a/ 下面就有編譯好的ffmpeg的庫,直接提取出來用就可以了
注:關於如何在android平台上編譯XBMC,請看我之前的博文: http://www.linuxidc.com/Linux/2013-08/88544.htm
那麼有了android平台上ffmpeg的庫,如何在android平台上測試H264解碼呢?
新建android app工程ffmpeg_android
gedit ./.bashrc
將 /opt/android-sdk-linux/tools 添加到 "PATH"環境變量中
android list targets
android create project --target 1 --name ffmpeg_android --path ~/workspace/ffmpeg_android --package com.modukaikai.ffmpeg --activity ffmpegActivity
將xbmc中的ffmpeg源碼拷貝到工程ffmpeg_android的jni目錄下
mkdir ~/workspace/ffmpeg_android/jni
cp -R ~/xbmc-android/lib/ffmpeg ~/workspace/ffmpeg_android/jni/
H264解碼器的實現
vim ~/workspace/ffmpeg_android/jni/h264_decoder.h
以下是h264_decoder.h的代碼:
#ifndef h264_decoder_h
#define h264_decoder_h
extern "C"
{
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavcodec/avcodec.h"
typedef void (*tp_avcodec_register_all)(void);
typedef AVCodec *(*tp_avcodec_find_decoder)(enum AVCodecID id);
typedef AVCodecContext *(*tp_avcodec_alloc_context3)(const AVCodec *codec);
typedef int (*tp_avcodec_open2)(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
typedef AVFrame *(*tp_avcodec_alloc_frame)(void);
typedef void (*tp_avcodec_free_frame)(AVFrame **frame);
typedef int (*tp_avcodec_decode_video2)(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt);
typedef int (*tp_avcodec_close)(AVCodecContext *avctx);
typedef void (*tp_av_free)(void *ptr);
typedef void (*tp_av_init_packet)(AVPacket *pkt);
class H264DecoderInterface
{
public:
H264DecoderInterface()
{
p_avcodec_register_all = NULL;
p_avcodec_find_decoder = NULL;
p_avcodec_alloc_context3 = NULL;
p_avcodec_open2 = NULL;
p_avcodec_alloc_frame = NULL;
p_avcodec_free_frame = NULL;
p_avcodec_decode_video2 = NULL;
p_avcodec_close = NULL;
p_av_free = NULL;
p_av_init_packet = NULL;
};
~H264DecoderInterface()
{
};
void (*p_avcodec_register_all)(void);
AVCodec *(*p_avcodec_find_decoder)(enum AVCodecID id);
AVCodecContext *(*p_avcodec_alloc_context3)(const AVCodec *codec);
int (*p_avcodec_open2)(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
AVFrame *(*p_avcodec_alloc_frame)(void);
void (*p_avcodec_free_frame)(AVFrame **frame);
int (*p_avcodec_decode_video2)(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt);
int (*p_avcodec_close)(AVCodecContext *avctx);
void (*p_av_free)(void *ptr);
void (*p_av_init_packet)(AVPacket *pkt);
};
class h264_decoder
{
public:
static bool loadLibrary(const char *libDir);
static bool unloadLibrary();
h264_decoder();
~h264_decoder();
bool open_h264_decoder();
unsigned long h264_decoder_process(unsigned char* pSrcData, unsigned long srcDataLen, unsigned char* pDstData, bool& bNoOutputDecData);
bool close_h264_decoder();
void setFrameRate(int frameRate);
void setResolution(int width, int height);
private:
static void* avcodec_handle;
static void* avfilter_handle;
static void* avformat_handle;
static void* avutil_handle;
static void* postproc_handle;
static void* swresample_handle;
static void* swscale_handle;
static H264DecoderInterface *p_H264DecoderInterface;
struct AVCodec *p_AVCodec;
struct AVCodecContext *p_AVCodecContext;
struct AVFrame *p_AVFrame;
struct AVPacket avPacket;
int got_frame;
bool isOpened;
int video_frameRate;
int video_width;
int video_height;
};
}
#endif
接下來請看第2頁精彩內容:http://www.linuxidc.com/Linux/2013-08/88545p2.htm