首页 > 其他分享 >FFmpeg 基本操作摘要(一) (转流、解码、编码)

FFmpeg 基本操作摘要(一) (转流、解码、编码)

时间:2023-02-11 17:22:46浏览次数:66  
标签:AVPacket FFmpeg 转流 int avcodec avformat av 基本操作

PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

前置说明

  本文作为本人csdn blog的主站的备份。(BlogID=061)
  本文发布于 2018-05-11 15:47:25,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=061)

环境说明

  无

前言


  近一段时间来,自己的主要工作都在是在做数据源端(设备端)音视频传输、编解码相关的事情,于是逐渐又和FFmpeg打上了交到,用到了其中的一些常见的内容,同时也解决了一些不常见的事情。

同时这里表达对“”“”雷神“”“”的敬意(一路走好,雷神),其blog上相关的FFmpeg教程是我学习FFmpeg的启蒙教程,其的blog可以不夸张的说,是国内非常非常非常好非常非常非常好非常非常非常好的音视频相关入门教程了,建议搞音视频的人可以多参考。这里提供一个链接指向雷神的博客地址,供大家参考(需从零学习FFmpeg,请参考其FFmpeg专栏):https://blog.csdn.net/leixiaohua1020





FFmpeg 相关内容简介




FFmpeg常用结构体
AVFormatContext   
//Format I/O context.(FFmpeg中的IO流的格式容器,具体来说就是用来记录打开的流的格式相关信息,列如:记录打开的rtsp流中的音视频流格式信息、MP4
文件的流格式信息等等)
AVCodecContext    //FFmpeg中记录编码器相关信息的容器

AVCodec  //FFmpeg 中编码器容器

AVFrame //This structure describes decoded (raw) audio or video data.(FFmpeg中用于描述裸音视频数据的容器,列如:视频中的YUV数据,音频中的PCM数据)

AVPacket  // This structure stores compressed data. It is typically exported by demuxers
 //and then passed as input to decoders, or received as output from encoders and
 //then passed to muxers.(此结构体用于描述音视频编码后的数据,主要用在把编码后的数据送入解码器或者接收编码器输出的数据,列如:视频中的H264数据, 音频中的:G711A数据)

SwsContext //图像缩放和变换的关键容器



FFmpeg中常见调用
void av_register_all(void); // Initialize libavformat and register all the muxers, demuxers and
 // protocols. If you do not call this function, then you can select
 // exactly which formats you want to support.
 //FFmpeg 中用于初始化libavformat 库,注册音视频复用器,各种协议等等。 这里需要注意的是,许多没有用到了内容都注册了,可能造成浪费,若需要指定注册哪些内容,可参考av_register_output_format()、av_register_input_format()


int avformat_network_init(void); //此函数用于初始化网络相关的组件,列如:你要解析RTSP流,需要先调用此函数
/**
 * Do global initialization of network components. This is optional,
 * but recommended, since it avoids the overhead of implicitly
 * doing the setup for each session.
 *
 * Calling this function will become mandatory if using network
 * protocols at some major version bump.
 */

AVFormatContext *avformat_alloc_context(void); //为AVFormatContext分配空间
void avformat_free_context(AVFormatContext *s); //释放AVFormatContext空间

int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options);//Open an input stream and read the header.


int avio_open(AVIOContext **s, const char *url, int flags); // 用于初始化AVIOContext,此结构体用于文件的读写操作
 //* Create and initialize a AVIOContext for accessing the
 //* resource indicated by url.

int avio_close(AVIOContext *s); //释放一个AVIOContext对象

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); //读取流数据,分析流信息
//Read packets of a media file to get stream information. 

void av_dump_format(AVFormatContext *ic,
                    int index,
                    const char *url,
                    int is_output);//就是打印一下AVFormatContext 里面存放的一些我们关心的信息
 /*
  * Print detailed information about the input or output format, such as
 * duration, bitrate, streams, container, programs, metadata, side data,
 * codec and time base.
*/


AVCodec *avcodec_find_decoder(enum AVCodecID id);查找一个解码器
//Find a registered decoder with a matching codec ID.

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);//初始化一个编码器,初始化此结构体AVCodecContext 

/*
 * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
 * function the context has to be allocated with avcodec_alloc_context3().
*/

int avcodec_close(AVCodecContext *avctx);//释放AVCodecContext 空间

int av_read_frame(AVFormatContext *s, AVPacket *pkt);//返回下一帧,数据(编码后的数据)存放到pkt里面,这里会给AVPacket 分配空间,此处一定要释放,否则将会发生内存泄漏
//Return the next frame of a stream.

int av_new_packet(AVPacket *pkt, int size);//给AVPacket buf成员分配空间,同理上文
/*
 * Allocate the payload of a packet and initialize its fields with
 * default values.
*/
void av_free_packet(AVPacket *pkt);//释放AVPacket 

AVFrame *av_frame_alloc(void);//申请AVFrame空间 
void av_frame_free(AVFrame **frame);//释放AVFrame空间 

void *av_malloc(size_t size);//ffmpeg中申请一定大小的内存空间
void av_free(void *ptr);//释放空间
//av_malloc  av_free是对malloc和free的封装,本质就是基础内存操作

struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
                                  int dstW, int dstH, enum AVPixelFormat dstFormat,
                                  int flags, SwsFilter *srcFilter,
                                  SwsFilter *dstFilter, const double *param);//创建一个指定大小和颜色空间的SwsContext 
/*
 * Allocate and return an SwsContext. You need it to perform
 * scaling/conversion operations using sws_scale().
*/

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
              const int srcStride[], int srcSliceY, int srcSliceH,
              uint8_t *const dst[], const int dstStride[]);//根据指定SwsContext ,来对原始图像进行变换
/*
 * Scale the image slice in srcSlice and put the resulting scaled
 * slice in the image in dst. A slice is a sequence of consecutive
 * rows in an image.
*/

int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                         int *got_picture_ptr,
                         const AVPacket *avpkt);//对一帧数据进行解码
/ * Decode the video frame of size avpkt->size from avpkt->data into picture.
 * Some decoders may support multiple frames in a single AVPacket, such
 * decoders would then just decode the first frame.
 * /
int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,
                          const AVFrame *frame, int *got_packet_ptr);//对一帧数据进行编码
                          



FFmpeg中需要注意的事项

  FFmpeg中除了正常使用外,需要我们注意的就是内存泄漏的问题了。

  这里我们需要关注几个问题:

/*
对于以下的结构体,一定要重点关注,申请了内存,一定要释放,否则在循环调用一些内容时,一定会发生内存泄漏。
AVFormatContext   
AVCodecContext    
AVCodec  
AVFrame 
AVPacket  

其中我们需要核心关注AVPacket这个结构体,这个结构体很容易让我们懵逼,出现内存泄漏。
av_read_frame
av_new_packet
上面两个都会申请内存,需要我们释放内存
av_free_packet
av_packet_unref
由于AVPacket 设计为缓冲区计数的方式,实现了一定的数据共享,方便FFmpeg管理内存,但是这里也给我们埋下了地雷:那就是AVPacket的生命周期就不好确定了,因为你调用了以上的函数,而内存不一定释放了。关于AVPacket还有许多函数,比如av_copy_packet、av_packet_ref、av_init_packet等,使用它们一定要小心,如果需要深入研究,建议查看它们的源码,这样就能够对这些调用有了更深刻的理解。
*/

  这里我再多说一句:由于FFmpeg2 和FFmpeg3有巨大的区别,很多东西也发生了变化,网上的教程很多是FFmpeg3以后的,使用的时候需要注意。同时,FFmpeg真的一不留神就发生内存泄漏了,需要我们注意。





FFmpeg 使用的一般流程




解码过程
	av_register_all  
	avformat_network_init
	avformat_alloc_context//初始化AVFormatContext
	avformat_open_input //打开流
	avformat_find_stream_info //读取流信息
	avcodec_find_decoder //根据上调用来确定编码器id,然后来查找相关编码器
	avcodec_open2 //打开编码器,初始化AVCodecContext    
	av_read_frame //读取一帧压缩数据
	avcodec_decode_video2 //解压一帧数据
	sws_scale //数据转换
	//后续对原始音视频数据进行相关处理


编码过程
	av_register_all  
	avformat_network_init
	avformat_alloc_context
	avio_open
	avformat_new_stream
	//这里通过相关方法把原始音视频数据准备好
	avcodec_find_decoder //根据上调用来确定编码器id,然后来查找相关编码器
	avcodec_open2 //打开编码器,初始化AVCodecContext   
	avcodec_encode_video2 //编码
	//后续处理编码后的事情 


转流过程
	av_register_all  
	avformat_network_init
	avformat_alloc_context//初始化AVFormatContext
	avformat_open_input //打开流
	avformat_find_stream_info //读取流信息
	avcodec_find_decoder //根据上调用来确定编码器id,然后来查找相关编码器
	avcodec_open2 //打开编码器,初始化AVCodecContext    
	av_read_frame //读取一帧压缩数据
	//这里对av_read_frame 中的pkt data数据域和size数据域进行处理即可




后记


  无

参考文献




打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
qrc_img

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

标签:AVPacket,FFmpeg,转流,int,avcodec,avformat,av,基本操作
From: https://www.cnblogs.com/Iflyinsky/p/17112146.html

相关文章

  • es数据库的基本操作
     ES数据库的基本常识关系型数据库(比如Mysql)非关系型数据库(Elasticsearch)数据库Database索引Index表Table类型Type数据行Row文档Docume......
  • FFmpeg静态编译
    在以往的文章中,编译出来的 ​​ffmpeg.exe​​​ 都不是完全静态的,总会依赖一些动态库,例如 ​​libm.dll​​​ ,​​libz.dll​​​,​​libc.dll​​ 等等。虽然FFmpe......
  • FFmpeg引入NVIDIA硬件编解码扩展
    本文主要介绍如何在window10的环境下编译ffmpeg的NVIDIAGPU硬件编解码器h264_nvenc跟h264_cuvid。并不是所有的NVIDIA显卡都支持h.264跟h.265编解码的,有些......
  • linux篇-linux下ffmpeg安装
    1最近自己搭建的公司服务端转化视频不可以,我想应该是ffmpeg的问题,头痛准备这两个源码包2安装,先解压ffmpeg-4.1.4.tar.bz2yasm-1.3.0.tar.gz3先安装yasm-1.3.0.tar.gz......
  • 【Web】emscripten编译ffmpeg
    编译命令:emconfigure./configure--cc="emcc"--cxx="em++"--ar="emar"--ranlib=emranlib--prefix=$(pwd)/dist--enable-cross-compile--target-os=none--arch=x86......
  • 基于MyBatis3.0.6的基本操作介绍
    每一个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心。SqlSessionFactory本身是由SqlSessionFactoryBuilder创建的,一般而言,在一个应......
  • cmd合并多个ts文件,ffmpeg快速转ts为mp4文件,通过m3u8合并文件
    1、如何合并多个ts文件进入目录执行如下cmd命令即可copy/b*.tsnew.ts2、如何将ts转为mp4ffmpeg下载官网:https://ffmpeg.org/github下载稳定版:https://github.com/Btb......
  • FFmpeg导出指定条件的视频文件
    FFmpeg导出指定条件的视频文件本地拥有一个m3u8文件(附带.ts文件),文件解析出视频起止时间:00:00:00~23:59:59若想导出12:30:00至12:33:00共3分钟时长的视频,可利用ffm......
  • C#使用FFmpeg录制视频
    FFmpeg通过控制台命令可以方便地录制USB摄像头和屏幕,本文使用C#中的Process类调用FFmpeg命令,并通过获取控制台输出参数实现录制视频的完整功能。Gitee完整代码:FFmpegWrapp......
  • ffmpeg安装(linux)
    Linux下安装ffmpeg下载安装包#在下载目录中下载文件wgethttps://johnvansickle.com/ffmpeg/release-source/ffmpeg-4.1.tar.xz新建安装目录cd/usr/local/#切换......