在前面,我们已经将ffmpeg引入到Android工程中去了,如果你还不知道如何在Android中使用ffmpeg,可以回头看看这篇文章:将ffmpeg引入到Android Studio工程中
那么如何使用ffmeg对音视频做一些开发工作呢?今天我们学习来学习一下使用ffmpeg对音视频进行解封装。
我们先来看一张图:
从图中可以看出要想对音视频进行解码,首先需要的是对音视频进行解封装。
解封装主要是为了获取一些音视频的信息,比如时长,视频所使用的编码器,音频流的索引、视频流的索引等等。
我们用一张图展示一下解封装的步骤以及需要用到的一些相关API:
首先引入log库,定义一个宏,方便后面打印日志。
#ifndef FLYPLAYER_FLYLOG_H
#define FLYPLAYER_FLYLOG_H
#include <android/log.h>
//定义一个宏,使用log库输出日志
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"FFMPEG",__VA_ARGS__)
#endif //FLYPLAYER_FLYLOG_H
解封装的主要代码:
//引入ffmpeg的头文件
// 因为ffmpeg是纯C代码,要在cpp中使用则需要使用 extern "C"
extern "C" {
#include "libavutil/avutil.h"
#include <libavformat/avformat.h>
}
/**
* 将数据转换成double类型的一个方法
* @param r
* @return
*/
static double r2d(AVRational r)
{
return r.num==0||r.den == 0 ? 0 :(double)r.num/(double)r.den;
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_flyer_ffmpeg_FFmpegUtils_analyzeMedia(JNIEnv *env, jclass clazz, jstring media_path) {
//初始化解封装
av_register_all();
//初始化网络
avformat_network_init();
//打开文件
AVFormatContext *ic = NULL;
const char *path = env->GetStringUTFChars(media_path, 0);
int re = avformat_open_input(&ic,path,0,0);
if(re != 0)
{
LOGE("avformat_open_input failed!:%s",av_err2str(re));
return -1;
}
LOGE("avformat_open_input %s success!",path);
//获取流信息
re = avformat_find_stream_info(ic,0);
if(re != 0)
{
LOGE("avformat_find_stream_info failed!");
return -3;
}
LOGE("duration = %lld nb_streams = %d",ic->duration,ic->nb_streams);
int fps = 0;
int videoStream = -1;
int audioStream = -1;
// 有两个方法获取视频或者视频流的索引,一种是遍历,一种是使用自动探测的api
// 通过遍历的方法获取索引
for(int i = 0; i < ic->nb_streams; i++)
{
AVStream *as = ic->streams[i];
if(as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
LOGE("视频数据");
videoStream = i;
fps = r2d(as->avg_frame_rate);
LOGE("videoStream=%d,fps = %d,width=%d height=%d codeid=%d pixformat=%d",
videoStream,fps,
as->codecpar->width,
as->codecpar->height,
as->codecpar->codec_id,
as->codecpar->format
);
}
else if(as->codecpar->codec_type ==AVMEDIA_TYPE_AUDIO )
{
LOGE("音频数据");
audioStream = i;
LOGE("audioStream=%d,sample_rate=%d channels=%d sample_format=%d",
audioStream,
as->codecpar->sample_rate,
as->codecpar->channels,
as->codecpar->format
);
}
}
// 通过探测的方式获取索引
//获取音频流信息
audioStream = av_find_best_stream(ic,AVMEDIA_TYPE_AUDIO,-1,-1,NULL,0);
LOGE("av_find_best_stream audioStream = %d",audioStream);
env->ReleaseStringUTFChars(media_path, path);
//关闭上下文
avformat_close_input(&ic);
LOGE("解封装成功","");
return 0;
}
运行看看打印的日志有没有解封装成功:
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/19839.html