如何在Android用FFmpeg解码jpeg图像解码

1228人阅读
Android(4)
ffmpeg(1)
代码地址:
csdn code:
准备条件:
1.编译出了FFMPEG的Android版本,没有的话请看我的博客:
该篇博客的目的:
1.熟悉FFMPEG的基本函数。
2.解码指定视频的帧图片,并且保存在sdcard上。
第一步:新建一个tutorrial.c文件。代码如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include &jni.h&
#include &libavcodec/avcodec.h&
#include &libavformat/avformat.h&
#include &libswscale/swscale.h&
#include &android/log.h&
#include &stdio.h&
#define LOG_TAG
&JNILOG& // 这个是自定义的LOG的标识
#undef LOG // 取消默认的LOG
#define LOGD(...)
__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) // 定义LOG类型
#define LOGI(...)
__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) // 定义LOG类型
#define LOGW(...)
__android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) // 定义LOG类型
#define LOGE(...)
__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) // 定义LOG类型
#define LOGF(...)
__android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) // 定义LOG类型
#define file_name &mnt/sdcard/2_new.mp4&
//定义视频名字,可以随意更改
/* Header for class com_cmm_app_nativeMethod */
void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) //保存每一帧的数据位ppm图片
LOGD(&in SaveFrame&);
char szFilename[128];
// Open file
sprintf(szFilename, &mnt/sdcard/tmp/frame%d.ppm&, iFrame);
pFile=fopen(szFilename, &wb&);
if(pFile==NULL)
LOGD(&SaveFrame is NULL&);
// Write header
fprintf(pFile, &P6\n%d %d\n255\n&, width, height);
// Write pixel data
for(y=0; y& y++)
fwrite(pFrame-&data[0]+y*pFrame-&linesize[0], 1, width*3, pFile);
// Close file
fclose(pFile);
#ifndef _Included_com_cmm_app_nativeMethod
#define _Included_com_cmm_app_nativeMethod
#ifdef __cplusplus
extern &C& {
com_cmm_app_nativeMethod
tutorial_1
* Signature: ()V
JNIEXPORT void JNICALL Java_com_cmm_app_nativeMethod_tutorial_11
(JNIEnv * env, jobject obj)
LOGD(&Hello JNILog&);
//变量声明
AVFormatContext *pFormatCtx = NULL;
AVCodecContext
*pCodecCtx = NULL;
*pCodec = NULL;
*pFrame = NULL;
*pFrameRGB = NULL;
*buffer = NULL;
AVDictionary
*optionsDict = NULL;
struct SwsContext
*sws_ctx = NULL;
//注册所有的格式和解码器
av_register_all();
//打开多媒体文件
if(avformat_open_input(&pFormatCtx, file_name, NULL, NULL)!=0)
return -1; // Couldn't open file
//获取多媒体文件信息
if(avformat_find_stream_info(pFormatCtx, NULL)&0)
return -1; // Couldn't find stream information
//输出文件信息,可以删除改行
av_dump_format(pFormatCtx, 0, file_name, 0);
//找到第一个视频流
videoStream=-1;
for(i=0; i&pFormatCtx-&nb_ i++)
if(pFormatCtx-&streams[i]-&codec-&codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
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]-&
//查找解码器
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, &optionsDict)&0)
return -1; // Could not open codec
// Allocate video frame
pFrame=avcodec_alloc_frame();
// Allocate an AVFrame structure
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return -1;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx-&width,
pCodecCtx-&height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
//图片格式转换需要的结构体
sws_getContext
pCodecCtx-&width,
pCodecCtx-&height,
pCodecCtx-&pix_fmt,
pCodecCtx-&width,
pCodecCtx-&height,
PIX_FMT_RGB24,
SWS_BILINEAR,
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx-&width, pCodecCtx-&height);
// Read frames and save first five frames to disk
while(av_read_frame(pFormatCtx, &packet)&=0) {
// Is this a packet from the video stream?
if(packet.stream_index==videoStream) {
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
// Did we get a video frame?
if(frameFinished) {
// Convert the image from its native format to RGB
(uint8_t const * const *)pFrame-&data,
pFrame-&linesize,
pCodecCtx-&height,
pFrameRGB-&data,
pFrameRGB-&linesize
// Save the frame to disk
if(++i&=5)
LOGD(&111&);
SaveFrame(pFrameRGB, pCodecCtx-&width, pCodecCtx-&height,
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
// Free the RGB image
av_free(buffer);
av_free(pFrameRGB);
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
avformat_close_input(&pFormatCtx);
#ifdef __cplusplus
2.添加Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE
:= cmm_app
LOCAL_SRC_FILES := tutorrial.c
LOCAL_LDLIBS := &/home/cmm/code/FFmpeg-Android/build/ffmpeg/neon/libffmpeg.so&
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
需要注意的是:LOCAL_LDLIBS需要加入libffmpeg.so,也就是编译ffmpeg出来的so文件。
3.新建文件夹jni,把第一步和第二部得到的.c文件和mk放入jni文件夹,运行:
ndk-build clean
4.第三步会得到libcmm_app.so文件,把cmm_app.so和libffmepg.so放入eclipse工程的libs/armeabi文件夹下即可
5.第五步骤:载入so文件
System.loadLibrary(&ffmpeg&);
System.loadLibrary(&cmm_app&);
public native void tutorial_1();
6.万事俱备,只差东风。现在你就可以在Java代码中使用C中写的函数了,调用tutorial_1()函数即可。
小结:写的不好还请见谅,不懂得可以留言或者下载工程。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:10726次
排名:千里之外
原创:15篇
评论:12条
(1)(5)(6)(3)Android Studio FFmpeg视频解码播放 - 简书
Android Studio FFmpeg视频解码播放
Android FFmpeg视频播放
本文介绍了使用Native Window和FFmpeg在Android平台上实现音频解码播放功能的方法。
Native Window简介
从Android API level 9开始,Android NDK支持native代码直接操控native window的像素缓存。这无疑方便了我们直接在native层操控界面显示。
在工程的AndroidManifest中加入权限&!-- RECORD_AUDIO is needed to create an audio recorder --&
&uses-permission android:name="android.permission.RECORD_AUDIO"/&
&!-- MODIFY_AUDIO_SETTINGS is needed to use audio effects such as environmental reverb --&
&uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/&
&!-- INTERNET is needed to use a URI-based audio player, depending on the URI --&
&uses-permission android:name="android.permission.INTERNET"/&
&uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&
FFmpeg视频解码播放
在native-lib中加入相关的库extern "C"{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
声明变量static AVPacket *vP
static AVFrame *vFrame, *pFrameRGBA;
static AVCodecContext *vCodecC
struct SwsContext *img_convert_
static AVFormatContext *pFormatC
ANativeWindow* nativeW
ANativeWindow_Buffer windowB
uint8_t *v_out_
初始化FFmpeg,读取音频文件,创建解码器并解码播放
extern "C"
Java_cn_jx_audiotest_MainActivity_play(JNIEnv* env, jclass clazz, jstring url, jobject surface) {
AVCodec *vC
char input_str[500]={0};
//读取输入的视频频文件地址
sprintf(input_str, "%s", env-&GetStringUTFChars(url, NULL));
av_register_all();
//分配一个AVFormatContext结构
pFormatCtx = avformat_alloc_context();
//打开文件
if(avformat_open_input(&pFormatCtx,input_str,NULL,NULL)!=0){
LOGD("Couldn't open input stream.\n");
return -1;
//查找文件的流信息
if(avformat_find_stream_info(pFormatCtx,NULL)&0){
LOGD("Couldn't find stream information.\n");
return -1;
//在流信息中找到视频流
int videoindex = -1;
for(i=0; i&pFormatCtx-&nb_ i++) {
if (pFormatCtx-&streams[i]-&codecpar-&codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex =
if(videoindex == -1){
LOGD("Couldn't find a video stream.\n");
return -1;
//获取相应视频流的解码器
vCodecCtx=pFormatCtx-&streams[videoindex]-&
vCodec = avcodec_find_decoder(vCodecCtx-&codec_id);
assert(vCodec != NULL);
//打开解码器
if(avcodec_open2(vCodecCtx, vCodec,NULL)&0){
LOGD("Couldn't open codec.\n");
return -1;
//获取界面传下来的surface
nativeWindow = ANativeWindow_fromSurface(env, surface);
if (0 == nativeWindow){
LOGD("Couldn't get native window from surface.\n");
return -1;
int width = vCodecCtx-&
int height = vCodecCtx-&
//分配一个帧指针,指向解码后的原始帧
vFrame = av_frame_alloc();
vPacket = (AVPacket *)av_malloc(sizeof(AVPacket));
pFrameRGBA = av_frame_alloc();
//绑定输出buffer
int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGBA, width, height, 1);
v_out_buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
av_image_fill_arrays(pFrameRGBA-&data, pFrameRGBA-&linesize, v_out_buffer, AV_PIX_FMT_RGBA, width, height, 1);
img_convert_ctx = sws_getContext(width, height, vCodecCtx-&pix_fmt,
width, height, AV_PIX_FMT_RGBA, SWS_BICUBIC, NULL, NULL, NULL);
if (0 & ANativeWindow_setBuffersGeometry(nativeWindow,width,height,WINDOW_FORMAT_RGBA_8888)){
LOGD("Couldn't set buffers geometry.\n");
ANativeWindow_release(nativeWindow);
return -1;
while(av_read_frame(pFormatCtx, vPacket)&=0){
if(vPacket-&stream_index==videoindex){
//视频解码
int ret = avcodec_send_packet(vCodecCtx, vPacket);
if (ret & 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
return -1;
ret = avcodec_receive_frame(vCodecCtx, vFrame);
if (ret & 0 && ret != AVERROR_EOF)
return -1;
//转化格式
sws_scale(img_convert_ctx, (const uint8_t* const*)vFrame-&data, vFrame-&linesize, 0, vCodecCtx-&height,
pFrameRGBA-&data, pFrameRGBA-&linesize);
if (ANativeWindow_lock(nativeWindow, &windowBuffer, NULL) & 0) {
LOGD("cannot lock window");
//将图像绘制到界面上,注意这里pFrameRGBA一行的像素和windowBuffer一行的像素长度可能不一致
//需要转换好,否则可能花屏
uint8_t *dst = (uint8_t *) windowBuffer.
for (int h = 0; h & h++)
memcpy(dst + h * windowBuffer.stride * 4,
v_out_buffer + h * pFrameRGBA-&linesize[0],
pFrameRGBA-&linesize[0]);
ANativeWindow_unlockAndPost(nativeWindow);
av_packet_unref(vPacket);
//释放内存
sws_freeContext(img_convert_ctx);
av_free(vPacket);
av_free(pFrameRGBA);
avcodec_close(vCodecCtx);
avformat_close_input(&pFormatCtx);
JAVA层调用
我们在JAVA层定义好JNI接口,并按照顺序调用即可开始播放视频文件了。
加载so库,定义JNI接口static {
System.loadLibrary("native-lib");
public native void play(String url, Surface surface);
界面创建一个SurfaceView,当界面准备好时传到native层供播放使用surfaceView = (SurfaceView) findViewById(R.id.surface);
surfaceViewHolder = surfaceView.getHolder();
surfaceViewHolder.addCallback(new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
//获取文件路径,这里将文件放置在手机根目录下
String folderurl = Environment.getExternalStorageDirectory().getPath();
String inputurl = folderurl+"/someVideo.mp4";
play(inputurl, surfaceViewHolder.getSurface());
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
public void surfaceDestroyed(SurfaceHolder holder) {
将图像绘制到界面上时,pFrameRGBA一行的像素和windowBuffer一行的像素长度可能不一致,需要一行一行的复制,否则会花屏或者显示多个重叠的图像。
I won't stop,cause time won't stop查看:4280|回复:6
我从网络SOCKET得到一个h264的流文件(见附件0.h264)
然后使用eseye打开这个流文件,没有任何问题(没有任何马赛克),但是我自己使用ffmpeg解码时,
发现运动部分全是马赛克 ,而静止部分没有问题。
运动部分有很严重拖影,静止1s后可以清晰
(313.41 KB)
11:47, 下载次数: 221
助理工程师
能知道LZ是在什么中解析并播放的么?
╰☆╮听悲伤的歌,看幸福的戏…年少轻狂…幸福时光......
是在eyecard streameye里看的是正常的。把收到的数据存成文件,用读文件的形式在手机上用ffmpeg解码播放也是正常的,但是实时播放的时候,直接把一帧的数据送到ffmpeg解码,动态的图像就会有拖影
检查ffmpeg的shellscript是否有问题
引用:原帖由 firedragon8 于
11:03 发表
检查ffmpeg的shellscript是否有问题 请问怎么检查shellscript,我是菜鸟,都不懂啊
引用:原帖由 emmamaoamoa 于
16:12 发表
请问怎么检查shellscript,我是菜鸟,都不懂啊 我还以为你自己写解码程序呢,算了,这样就说来话长了,不解释
楼主好,请问你的问题解决了么,我也出现这个问题,运动部分出现马赛克,求楼主赐教~在Android上怎么使用ffmpeg命令行将图片合成视频? - 知乎2被浏览129分享邀请回答还没有回答Android零基础学习视频解码系列(9)
libavcodec/log2_tab.o
libavutil/log2_tab.o
libswresample/log2_tab.o
libavcodec/libavcodec.a
libavutil/libavutil.so.52
libavutil/libavutil.a
libswresample/libswresample.a
libavcodec/libavcodec.so.55
libswresample/libswresample.so.0
libswscale/libswscale.so.2
libavformat/libavformat.so.55
libavformat/libavformat.a
libavformat/libavformat.so
install-libavformat-shared
libavcodec/libavcodec.a
libavcodec/libavcodec.so
install-libavcodec-shared
libswresample/libswresample.a
libswresample/libswresample.so
install-libswresample-shared
libswscale/libswscale.a
libswscale/libswscale.so
install-libswscale-shared
libavutil/libavutil.a
libavutil/libavutil.so
install-libavutil-shared
libavformat/avformat.h
libavformat/avio.h
libavformat/version.h
libavformat/libavformat.pc
libavcodec/avcodec.h
libavcodec/avfft.h
libavcodec/dxva2.h
libavcodec/old_codec_ids.h
libavcodec/vaapi.h
libavcodec/vda.h
libavcodec/vdpau.h
libavcodec/version.h
libavcodec/xvmc.h
libavcodec/libavcodec.pc
libswresample/swresample.h
libswresample/version.h
libswresample/libswresample.pc
libswscale/swscale.h
libswscale/version.h
libswscale/libswscale.pc
libavutil/adler32.h
libavutil/aes.h
libavutil/attributes.h
libavutil/audio_fifo.h
libavutil/audioconvert.h
libavutil/avassert.h
libavutil/avstring.h
libavutil/avutil.h
libavutil/base64.h
libavutil/blowfish.h
libavutil/bprint.h
libavutil/bswap.h
libavutil/buffer.h
libavutil/channel_layout.h
libavutil/common.h
libavutil/cpu.h
libavutil/crc.h
libavutil/error.h
libavutil/eval.h
libavutil/fifo.h
libavutil/file.h
libavutil/frame.h
libavutil/hmac.h
libavutil/imgutils.h
libavutil/intfloat.h
libavutil/intfloat_readwrite.h
libavutil/intreadwrite.h
libavutil/lfg.h
libavutil/log.h
libavutil/mathematics.h
libavutil/md5.h
libavutil/mem.h
libavutil/murmur3.h
libavutil/dict.h
libavutil/old_pix_fmts.h
libavutil/opt.h
libavutil/parseutils.h
libavutil/pixdesc.h
libavutil/pixfmt.h
libavutil/random_seed.h
libavutil/rational.h
libavutil/ripemd.h
libavutil/samplefmt.h
libavutil/sha.h
libavutil/sha512.h
libavutil/time.h
libavutil/timecode.h
libavutil/timestamp.h
libavutil/version.h
libavutil/xtea.h
libavutil/lzo.h
libavutil/avconfig.h
libavutil/libavutil.pc
link ffmpeg.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := /path/to/build/output/libffmpeg.so
include $(PREBUILT_SHARED_LIBRARY)
Application.mk
APP_ABI := armeabi
APP_PLATFORM := android-9
Android.mk
include $(call all-subdir-makefiles)
* ffmpeg_jni.c
Created on: Sep 1, 2014
Author: clarck
#include &stdlib.h&
#include &string.h&
#include &stdio.h&
#include &jni.h&
#include &../include/ffmpeg_logger.h&
#include &../include/ffmpeg.h&
// 指定要注册的类,对应完整的java类名
#define JNIREG_CLASS &com/clarck/android/ffmpeg/MainActivity&
JNIEXPORT void JNICALL native_setDataSource(JNIEnv *env, jclass classzz, jstring path) {
char *filepath = ffmpeg_jstringTostr(env, path);
ffmpeg_setDataSource(filepath);
//Java和JNI函数的绑定
static JNINativeMethod method_table[] = {
{ &setDataSource&, &(Ljava/lang/S)V&, native_setDataSource }
//注冊native方法到java中
static int registerNativeMethods(JNIEnv *env, const char *className,
JNINativeMethod *gMethods, int numMethods) {
clazz = (*env)-&FindClass(env, className);
if (clazz == NULL) {
return JNI_FALSE;
if ((*env)-&RegisterNatives(env, clazz, gMethods, numMethods) & 0) {
return JNI_FALSE;
return JNI_TRUE;
//調用註冊方法
int register_ndk_load(JNIEnv *env) {
return registerNativeMethods(env, JNIREG_CLASS, method_table,
(int) (sizeof(method_table) / sizeof(method_table[0])));
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
jint result = -1;
if ((*vm)-&GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) {
register_ndk_load(env);
//返回JNI的版本
return JNI_VERSION_1_6;
* ffmpeg.c
Created on: Sep 1, 2014
Author: clarck
#include &jni.h&
#include &android/native_window_jni.h&
#include &../include/ffmpeg.h&
#include &../include/ffmpeg_logger.h&
#include &../ffmpeg/include/libavcodec/avcodec.h&
#include &../ffmpeg/include/libavformat/avformat.h&
#include &../ffmpeg/include/libavutil/pixfmt.h&
#include &../ffmpeg/include/libswscale/swscale.h&
char* ffmpeg_jstringTostr(JNIEnv* env, jstring jstr) {
char* pStr = NULL;
jclass jstrObj = (*env)-&FindClass(env, &java/lang/String&);
jstring encode = (*env)-&NewStringUTF(env, &utf-8&);
jmethodID methodId = (*env)-&GetMethodID(env, jstrObj, &getBytes&,
&(Ljava/lang/S)[B&);
jbyteArray byteArray = (jbyteArray) (*env)-&CallObjectMethod(env, jstr,
methodId, encode);
jsize strLen = (*env)-&GetArrayLength(env, byteArray);
jbyte *jBuf = (*env)-&GetByteArrayElements(env, byteArray, JNI_FALSE);
if (jBuf & 0) {
pStr = (char*) malloc(strLen + 1);
if (!pStr) {
return NULL ;
memcpy(pStr, jBuf, strLen);
pStr[strLen] = 0;
(*env)-&ReleaseByteArrayElements(env, byteArray, jBuf, 0);
void ffmpeg_setDataSource(char *file_path) {
LOGI(&ffmpeg_setDataSource:%s&, file_path);
AVFormatContext *pFormatC
AVCodecContext *pCodecC
AVCodec *pC
AVFrame *pFrame, *pFrameYUV;
AVPacket *
uint8_t *out_
static struct SwsContext *img_convert_
int videoStream, i, numB
int ret, got_
av_register_all();
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) {
LOGE(&can't open the file. \n&);
if (avformat_find_stream_info(pFormatCtx, NULL) & 0) {
LOGE(&Could't find stream infomation.\n&);
videoStream = 1;
for (i = 0; i & pFormatCtx-&nb_ i++) {
if (pFormatCtx-&streams[i]-&codec-&codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream =
if (videoStream == -1) {
LOGE(&Didn't find a video stream.\n&);
pCodecCtx = pFormatCtx-&streams[videoStream]-&
pCodec = avcodec_find_decoder(pCodecCtx-&codec_id);
if (pCodec == NULL) {
LOGE(&Codec not found.\n&);
if (avcodec_open2(pCodecCtx, pCodec, NULL) & 0) {
LOGE(&Could not open codec.\n&);
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx-&width,
pCodecCtx-&height);
out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P,
pCodecCtx-&width, pCodecCtx-&height);
int y_size = pCodecCtx-&width * pCodecCtx-&
packet = (AVPacket *) malloc(sizeof(AVPacket));
av_new_packet(packet, y_size);
av_dump_format(pFormatCtx, 0, file_path, 0);
while (av_read_frame(pFormatCtx, packet) &= 0) {
if (packet-&stream_index == videoStream) {
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,
LOGI(&avcodec_decode_video2 ret:%d&, ret);
if (ret & 0) {
LOGE(&decode error.\n&);
if (got_picture) {
//TODO 此处可以将解码出来的图片保存起来。
av_free_packet(packet);
av_free(out_buffer);
av_free(pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
FFMPEG_PATH := ../ffmpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(FFMPEG_PATH)/include
LOCAL_MODULE
:= ffmpeg_player
LOCAL_SRC_FILES += ffmpeg_jni.c
LOCAL_SRC_FILES += ffmpeg.c
LOCAL_SHARED_LIBRARIES := ffmpeg
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
package com.clarck.android.
import android.app.A
import android.os.B
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setDataSource(&/sdcard/a.mp4&);
public native void setDataSource(String path);
System.loadLibrary(&ffmpeg&);
System.loadLibrary(&ffmpeg_player&);
}八、执行结果如下图:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:76587次
积分:1137
积分:1137
排名:千里之外
原创:84篇
转载:32篇
评论:11条
(1)(2)(2)(3)(1)(2)(18)(1)(86)}

我要回帖

更多关于 图像解码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信