一、解封装基本流程

  ①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. CodeForces 785 D Anton and School - 2 范德蒙恒等式

    Anton and School - 2 题解: 枚举每个左括号作为必选的. 那么方案数就应该是下面的 1 , 然后不断化简, 通过范德蒙恒等式 , 可以将其化为一个组合数. 代码: #include ...

  2. bzoj 1146 网络管理Network (CDQ 整体二分 + 树刨)

    题目传送门 题意:求树上路径可修改的第k大值是多少. 题解:CDQ整体二分+树刨. 每一个位置上的数都会有一段持续区间 根据CDQ拆的思维,可以将这个数拆成出现的时间点和消失的时间点. 然后通过整体二 ...

  3. UVA - 315 Network(tarjan求割点的个数)

    题目链接:https://vjudge.net/contest/67418#problem/B 题意:给一个无向连通图,求出割点的数量.首先输入一个N(多实例,0结束),下面有不超过N行的数,每行的第 ...

  4. 树莓派的Respbian或者ubuntu系统下安装opencv最有效的方法

    第一种方法当然首选和其他安装包相同的方法pip install opencv-python安装失败后果断选择第二种方法,这第二种方法尝试过很多次了,屡试不爽 第二种方法:sudo apt-get in ...

  5. 【Offer】[28] 【对称的二叉树】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 请实现一个函数,用来判断一-棵二叉树是不是对称的.如果一棵二叉树和它的镜像一样,那么它是对称的.  牛客网刷题地址 思路分析 利用前序 ...

  6. 深入理解 ThreadLocal

    前言 上篇文章 深入理解 Handler 消息机制 中提到了获取线程的 Looper 是通过 ThreadLocal 来实现的: public static @Nullable Looper myLo ...

  7. 详细的漏洞复现:Shellshock CVE-2014-6271 CVE-2014-7169

    目录 前言 漏洞原理 利用方式 复现过程 1. 环境准备 (1) 为容器配置固定IP地址 (2) 查看bash版本 2. 本地验证:测试镜像系统是否存在漏洞 3. 远程模拟验证(原理验证) (1) 查 ...

  8. instanceof运算符与引用变量的强制类型转换

    一.instanceof运算符 instanceof是Java语言中的一个二元运算符,它的作用是判断一个引用类型的变量所指向的对象是否是一个类(或接口.抽象类.父类)的实例,即它左边的对象是否是它右边 ...

  9. springmvc两种非注解的处理器映射器

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  10. Spring错误

    今天在学习spring的aop操作时碰到了一个问题: Caused by: org.springframework.aop.framework.AopConfigException: Cannot p ...