FFmpeg编写的代码
//初始化解封装
av_register_all();
avformat_network_init();
avcodec_register_all();
//封装文件的上下文
AVFormatContext *ic = NULL;
char path[] = "sdcard/shape.mp4";
//打开文件并且解析
int re = avformat_open_input(&ic, path, NULL, NULL);
if(re != 0)
{
Logw("avformat_open_input %s failed", av_err2str(re));
return env->NewStringUTF(hello.c_str());
}
Logw("duration = %lld nb_stream = %d", ic->duration , ic->nb_streams);
//找到流的信息
int re1 = avformat_find_stream_info(ic, NULL);
if(re1!=0)
{
Logw("avformat_find_stream_info failed");
}
Logw("duration = %lld nb_stream = %d" , ic->duration , ic->nb_streams);
//找流的信息有两种方案
//1.遍历整个信息
int fps = 0 ;
int wigth = 0;
int height = 0;
int videoStream = 0;
int audioStream = 0;
for (int i = 0; i < ic->nb_streams; i++)
{
AVStream *as = ic->streams[i];
if(as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
Logw("视频数据");
videoStream = i;
fps = r2d(as->avg_frame_rate);
Logw("fps = %d width = %d height = %d codeid = %d" , fps , as->codecpar->width ,
as->codecpar->height , as->codecpar->codec_id);
Logw("tag = %d format = %d" , as->codecpar->codec_tag , as->codecpar->format);
}
else if(as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
Logw("音频数据");
audioStream = i;
Logw("sample_rate = %d channel = %d format = %d" , as->codecpar->sample_rate ,
as->codecpar->channels , as->codecpar->format);
}
}
//av_find_best_stream()来找到对应的流
audioStream = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
Logw("av_find_best_stream audioStream = %d " , audioStream);
Logw("sample_rate = %d channel = %d format = %d" , ic->streams[audioStream]->codecpar->sample_rate ,
ic->streams[audioStream]->codecpar->channels , ic->streams[audioStream]->codecpar->format);
/*****************打开视频解码器*********************************/
//找到软解码器
AVCodec *codec = avcodec_find_decoder(ic->streams[videoStream]->codecpar->codec_id);
//找到硬解码器
codec = avcodec_find_decoder_by_name("h264_mediacodec");
//解码器初始化
AVCodecContext *vc = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(vc, ic->streams[videoStream]->codecpar);
vc->thread_count = 4;
//打开解码器
re = avcodec_open2(vc, 0, 0);
if(re != 0)
{
Logw("avcodec open failed");
return env->NewStringUTF(hello.c_str());
}
/*****************打开音频解码器*********************************/
AVCodec *avCodec = avcodec_find_decoder(ic->streams[audioStream]->codecpar->codec_id);
//初始化软解码器
AVCodecContext *av = avcodec_alloc_context3(avCodec);
avcodec_parameters_to_context(av, ic->streams[audioStream]->codecpar);
av->thread_count = 4;
//打开音视频解码器
re = avcodec_open2(av, 0, 0);
if(re != 0)
{
Logw("avcodec open failed");
return env->NewStringUTF(hello.c_str());
}
//读取帧数据
AVPacket *pkt = av_packet_alloc();
AVFrame *frame = av_frame_alloc();
long long start = GetNowMs();
int frameCount = 0;
for(;;)
{
//时间超过3秒
if(GetNowMs() - start >= 3000)
{
Logw("now decodec fps is %d", frameCount / 3);
start = GetNowMs();
frameCount = 0;
}
int re = av_read_frame(ic, pkt);
if(re != 0)
{
Logw("读取到结尾处");
// int pos = 10 * r2d(ic->streams[videoStream]->time_base);
// av_seek_frame(ic, videoStream, pos,
// AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
break;
}
AVCodecContext *cc = vc;
if(pkt->stream_index == audioStream) {
cc = av;
}
//把数据发送到数据缓冲空间去
re = avcodec_send_packet(cc, pkt);
av_packet_unref(pkt);
if(re != 0)
{
Logw("avcodec_send_packet failed");
continue;
}
for(;;)
{
re = avcodec_receive_frame(cc, frame);
if(re != 0)
{
//Logw("avcodec_receive_frame failed");
break;
}
//Logw("avcodec_receive_frame %lld " , frame->pts);
//如果是视频帧
if(cc == vc)
{
frameCount++;
}
}
}
avformat_close_input(&ic);
return env->NewStringUTF(hello.c_str());
}
最新文章
- [PHP] - Laravel - 修改laravel_session的cookie名称
- 【原】js 签到用日历
- Activity之间传递数据的方式及常见问题总结
- Viewdraghelper解析
- 【WPF】控件使用-宽度自动适应窗口大小
- JavaScript String(字符串)对象 实例
- SQLServer中登录名的用户名配置
- css经典布局学习
- java 面对对象(抽象 继承 接口 多态)
- 关于jQuery表单选择中prop和attr的区别。
- angularJS directive详解(自定义指令)
- C# ref与out
- oracle客户端安装
- href和src的区别
- python查看及修改当前的工作路径
- Hive数据类型及文本文件数据编码
- cookie工具包
- jQuery插件之ajaxFileUpload[转载]
- 20165203 第6周《Java程序设计》学习
- PAT 1061 Dating[简单]
热门文章
- javascript正则表达式验证密码(必须含数字字符特殊符号,长度4-16位之间)
- web前端js 实现打印操作
- linux-radhat-gitlab服务搭建
- POJ3687.Labeling Balls 拓扑排序
- eclipse新建web项目,发布 run as 方式和 new server然后添加项目方式。 后者无法自动编译java 成class文件到classes包下。
- 2018.10.19 NOIP训练 变化的序列(线性dp)
- mysql 查询表 的所有字段名称
- spring boot2.0冷知识
- jdk10运行springboot项目出现:Type javax.xml.bind.JAXBContext not present
- Java 注解概要