一、解封装基本流程

  ①av_register_All()////初始化解封装,注册解析和封装的格式。
  ②avformat_netword_init()//初始化网络,解析rtsp协议
  ③avformat_open_init()//打开
  ④avformat_find_stream_info()//探测
  ⑤av_find_best_stream() //获取音视频的索引
  ⑥av_read_Frame()//读一帧数据,音频可能好几帧、视频是I帧
  ⑦av_seek_frame()//跳转

二、函数介绍

  ①av_register_all();
    初始化解封装,注册解封装格式
    在最开始编译FFmpeg的时候,我们做了一个configure的配置,其中开启或者关闭了很多选项。configure的配置会生成两个文件:config.mk和config.h。
      config.mk:就是makefile文件需要包含进去的子模块,会作用在编译阶段,帮助开发者编译出正确的库。
      config.h:作用在运行阶段,主要是确定需要注册那些容器及编解码格式到FFmpeg框架中。
    调用 av_register_all 就可以注册config.h里面开发的编解码器,然后会注册所有的Muxer和Demuxer(封装格式),最后注册所有的Protocol(协议)。

  ②avformat_network_init();
    初始化网络,rtsp流

  ③avformat_open_input(&ic,path,0,0);
    打开文件并解析视频流、音频流、流的参数,
      参数:AVFormactContext **ps;
           const char *URL;
           AVInputFormat *fmt;
           AVDictionary *options;

  ④avformat_find_stream_info()
    探测

  ⑤av_find_best_stream()
    获取对应的视频流或者视频流 还有一种方式:遍历返回值的一个成员(Stream数组),根据标志位判断是音频还是视频。

  ⑥av_read_frame();
    从AVPacket中,读取帧信息,av_read_packet函数读出的是包,其可能是半帧或者多帧,不保证帧的完整性。
    av_read_frame对av_read_packet进行了封装,使其读出的数据总是完整的帧,av_read_frame函数调用了read_fram_internal。读取码流中若干个音频帧或者I帧视频。例如,在解码视频的时候,每解码一个视频,需要先调用av_read_frame获得一帧视频的压缩数据,然后才能对该数据进行解码
    返回值有三种结果:
      ①如果packet_buffer存在数据,根据PTS返回AVPacket。
      ②如果packet_buffer不存在数据,调用av_read_frame_internal函数。
      ③(待补充)

代码展示:

/*****************************FILE INFOMATION***********************************
** av_register_all();
//初始化解封装,注册解封装格式
在最开始编译FFmpeg的时候,我们做了一个configure的配置,其中开启或者关闭了很多选项。configure的配置会生成两个文件:config.mk和config.h。
config.mk:就是makefile文件需要包含进去的子模块,会作用在编译阶段,帮助开发者编译出正确的库。
config.h:作用在运行阶段,主要是确定需要注册那些容器及编解码格式到FFmpeg框架中。
调用 av_register_all 就可以注册config.h里面开发的编解码器,然后会注册所有的Muxer和Demuxer(封装格式),最后注册所有的Protocol(协议)。 avformat_network_init();
//初始化网络,rtsp流 avformat_open_input(&ic,path,0,0);
//打开文件并解析视频流、音频流、流的参数,
参数:AVFormactContext **ps;
const char *URL;
AVInputFormat *fmt;
AVDictionary *options; avformat_find_stream_info()
//探测 av_find_best_stream()
//获取对应的视频流或者视频流 还有一种方式:遍历返回值的一个成员(Stream数组),根据标志位判断是音频还是视频。 av_read_frame();
从AVPacket中,读取帧信息,av_read_packet函数读出的是包,其可能是半帧或者多帧,不保证帧的完整性。
av_read_frame对av_read_packet进行了封装,使其读出的数据总是完整的帧,av_read_frame函数调用了read_fram_internal。
读取码流中若干个音频帧或者I帧视频。例如,在解码视频的时候,每解码一个视频,需要先调用av_read_frame获得一帧视频的压缩数据,然后才能对该数据进行解码
返回值有三种结果:
①如果packet_buffer存在数据,根据PTS返回AVPacket。
②如果packet_buffer不存在数据,调用av_read_frame_internal函数。
③不够清晰?(android视频开发书) **
*******************************************************************************/ #include <jni.h>
#include <string>
#include <android/log.h>
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__) extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
#include<iostream>
using namespace std; static double r2d(AVRational r)
{
return r.num==||r.den == ? :(double)r.num/(double)r.den;
} extern "C"
JNIEXPORT jstring
JNICALL
Java_aplay_testffmpeg_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++ ";
hello += avcodec_configuration();
//初始化解封装
av_register_all();
//初始化网络
avformat_network_init(); //打开文件
AVFormatContext *ic = NULL;
char path[] = "/sdcard/1080.mp4";
//char path[] = "/sdcard/video.flv";
int re = avformat_open_input(&ic,path,,);
if(re != )
{
LOGW("avformat_open_input failed!:%s",av_err2str(re));
return env->NewStringUTF(hello.c_str());
}
LOGW("avformat_open_input %s success!",path);
//获取流信息
re = avformat_find_stream_info(ic,);
if(re != )
{
LOGW("avformat_find_stream_info failed!");
}
LOGW("duration = %lld nb_streams = %d",ic->duration,ic->nb_streams); int fps = ;
int videoStream = ;
int audioStream = ; for(int i = ; 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 pixformat=%d",fps,
as->codecpar->width,
as->codecpar->height,
as->codecpar->codec_id,
as->codecpar->format
);
}
else if(as->codecpar->codec_type ==AVMEDIA_TYPE_AUDIO )
{
LOGW("音频数据");
audioStream = i;
LOGW("sample_rate=%d channels=%d sample_format=%d",
as->codecpar->sample_rate,
as->codecpar->channels,
as->codecpar->format
);
}
}
//ic->streams[videoStream];
//获取音频流信息
audioStream = av_find_best_stream(ic,AVMEDIA_TYPE_AUDIO,-,-,NULL,);
LOGW("av_find_best_stream audioStream = %d",audioStream); //读取帧数据
AVPacket *pkt = av_packet_alloc();
for(;;)
{
int re = av_read_frame(ic,pkt);
if(re != )
{ LOGW("读取到结尾处!");
int pos = * r2d(ic->streams[videoStream]->time_base);
av_seek_frame(ic,videoStream,pos,AVSEEK_FLAG_BACKWARD|AVSEEK_FLAG_FRAME );
continue;
}
LOGW("stream = %d size =%d pts=%lld flag=%d",
pkt->stream_index,pkt->size,pkt->pts,pkt->flags
);
////////////////////// av_packet_unref(pkt);
} //关闭上下文
avformat_close_input(&ic);
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jboolean JNICALL
Java_aplay_testffmpeg_MainActivity_Open(JNIEnv *env, jobject instance, jstring url_,
jobject handle) {
const char *url = env->GetStringUTFChars(url_, ); // TODO
FILE *fp = fopen(url,"rb");
if(!fp)
{
LOGW("File %s open failed!",url);
}
else
{
LOGW("File %s open succes!",url);
fclose(fp);
}
env->ReleaseStringUTFChars(url_, url);
return true;
}
												

FFmpeg(二) 解封装相关函数理解的更多相关文章

  1. FFmpeg4.0笔记:封装ffmpeg的解封装功能类CDemux

    Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDemux.h /*********************** ...

  2. FFmpeg(三) 编解码相关函数理解

    一.编解码基本流程 主要流程: 打开视频解码器(音频一样) 软解码.硬解码 进行编解码 下面先来看打开视频解码器 ①avcodec_register_all()//初始化解码 ②先找到解码器. 找解码 ...

  3. FFmpeg(四) 像素转换相关函数理解

    一.基本流程 1.sws_getCachedContext();//得到像素转换的上下文 2.sws_scale()://进行转换 二.函数说明 1.SwsContext *vctx = NULL;  ...

  4. FFmpeg音视频解封装

    一 . 解封装用到的函数和结构体 1.av_register_all() : open 一次就调用一次 2.avformat_network_init() : 网络模块初始化 3.avformat_o ...

  5. 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步

    深入理解MVC   MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...

  6. 《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)

    1.简介 上一篇宏哥介绍了如何设计支持不同浏览器测试,宏哥的方法就是通过来切换配置文件设置的浏览器名称的值,来确定启动什么浏览器进行脚本测试.宏哥将这个叫做浏览器引擎类.这个类负责获取浏览器类型和启动 ...

  7. FFmpeg软硬解和多线程解码

    一. AVCodecContext解码上下文 1.avcodec_register_all() : 注册所有的解码器 2.AVCodec *avcodec_find_decoder(enum AVCo ...

  8. ffmpeg 详解

    来源:http://blog.itpub.net/9399028/viewspace-1242300/ FFMPEG详解   认识FFMPEG FFMPEG堪称自由软件中最完备的一套多媒体支持库,它几 ...

  9. element el-table表格的vue组件二次封装(附表格高度自适应)

    基于vue的el-table表格二次封装组件方法 前言 在公司实习使用vue+element-ui框架进行前端开发,使用表格el-table较为多,有些业务逻辑比较相似,有些地方使用的重复性高,如果多 ...

随机推荐

  1. lightoj 1173 - The Vindictive Coach(dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1173 题解:像这种题目显然可以想到n为几时一共有几种排列可以递推出来.然后就是 ...

  2. Atcoder E - Meaningful Mean(线段树+思维)

    题目链接:http://arc075.contest.atcoder.jp/tasks/arc075_c 题意:问数组a有多少子区间平均值为k 题解:一开始考虑过dp,但是显然不可行,其实将每一个数都 ...

  3. Atcoder D - 3N Numbers(优先队列+dp)

    题目链接:http://abc062.contest.atcoder.jp/tasks/arc074_b 题意:给出3*n个数要求去掉n个数使得剩下的前n个数-后n个数的差最大. 题解:显然是一道如果 ...

  4. java 中for循环中断的办法

    /* 中断for循环的办法: 1.break ***2.return是结束方法的,不是结束循环的. 3.标签的方法. 格式: 表签名:语句 运行结果:D:\test\day0413>java T ...

  5. ReentrantLock分析

    主要分析下ReentrantLock锁的占用和释放过程. 一.几个核心变量 AbstractOwnableSynchronizer{ /** * 表示当前占有独占锁的线程,为null时说明锁未被占用 ...

  6. Ubuntu系统添加用户权限

    一.首先创建一个新用户: sudo adduser hadoop 其次设置密码: sudo passwd hadoop 如果无法使用root密码,请输入如下命令: sudo passwd root 二 ...

  7. Linux OOM-killer(内存不足时kill高内存进程的策略)

    OOM_killer是Linux自我保护的方式,当内存不足时不至于出现太严重问题,有点壮士断腕的意味 在kernel 2.6,内存不足将唤醒oom_killer,挑出/proc/<pid> ...

  8. springboot数据库主从方案

    本篇分享数据库主从方案,案例采用springboot+mysql+mybatis演示:要想在代码中做主从选择,通常需要明白什么时候切换数据源,怎么切换数据源,下面以代码示例来做阐述: 搭建测试环境(1 ...

  9. MySQL5.7初始化后5种密码重置方法

    前言:由于好几次安装MySQL5.7后一直被重置密码所困扰,因此特意整理重置的方法 安装MySQL5.7 [root@node1 db]# ll 以下的rpm安装包可以随处下载 total 40235 ...

  10. Redis相关安装TCL

    安装相关命令 wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gzsudo tar -xzvf tcl8.6.1-src.tar. ...