ffmpeg常用api介绍

av_log_set_callback

函数原型:

void av_log_set_callback(void(*)(void *, int, const char *, va_list) callback)  

设置日志打印的回调。

av_log

函数原型:

void av_log(void* avcl, int level, const char *fmt, ...)

输出日志。

av_malloc

av_malloc()就是简单的封装了系统函数malloc(),并做了一些错误检查工作。

avformat_alloc_output_context2()

函数原型

int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat * oformat, const char * format_name, const char * filename)

初始化一个用于输出的AVFormatContext结构体

avformat_network_init

全局地初始化网络组件,需要用到网络功能的时候需要调用。

av_register_all

初始化libavformat和注册所有的复用器和解复用器和协议。
如果不调用这个函数,可以使用av_register_input_format()和av_register_out_format()来选择支持的格式。

AVPacket

AVPacket是存储压缩编码数据的数据结构。
通常是解复用器的输出,然后被传递给解码器。或者是编码器的输出,然后被传递给复用器。
AVPacket.size:data的大小。
AVPacket.dts:解码时间戳。
AVPacket.stream_index:标识该AVPacket所属的视频/音频流。

av_copy_packet

函数原型:

int av_copy_packet(AVPacket * dst, const AVPacket * src)    

复制packet,包含内容。

av_packet_unref

函数原型:

void av_packet_unref(AVPacket * pkt)    

解除packet引用的buffer,并且将其余的字段重置为默认值。

AVCodecContext

这是一个描述解码器上下文的数据结构,包含了众多编解码器需要的参数信息。

AVCodec

存储编码器信息的结构体。
主要包含以下信息:

const char *name:编解码器的名字的简称

const char *long_name:编解码器名字的全称

enum AVMediaType type:指明了类型,是视频,音频,还是字幕

enum AVCodecID id:ID,不重复

const AVRational *supported_framerates:支持的帧率(仅视频)

const enum AVPixelFormat *pix_fmts:支持的像素格式(仅视频),如RGB24、YUV420P等。

const int *supported_samplerates:支持的采样率(仅音频)

const enum AVSampleFormat *sample_fmts:支持的采样格式(仅音频)

const uint64_t *channel_layouts:支持的声道数(仅音频)

int priv_data_size:私有数据的大小

avcodec_send_packet

将原始分组数据作为解码器的输入。
在函数内部,会拷贝相关的AVCodecContext结构变量,将这些结构变量应用到解码的每一个包。例如
AVCodecContext.skip_frame参数通知解码器扔掉包含该帧的包。

avcodec_alloc_context3()

创建AVCodecContext结构体。

avcodec_parameters_to_context

将音频流信息拷贝到新的AVCodecContext结构体中。

avcodec_free_context

释放AVCodecContext和与之相关联的所有内容,并且把指针置空。

avcodec_open2

原型:

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)  

使用给定的AVCodec初始化AVCodecContext。
在使用这个函数之前需要使用avcodec_alloc_context3()分配的context。

av_frame_alloc

原型

AVFrame* av_frame_alloc(void)   

分配一个avframe和设置字段的默认值。分配出来的AVFrame必须使用av_frame_free()释放。

avcodec_receive_frame

原型

int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)    

返回解码器输出的解码数据

av_read_pause

原型

int av_read_pause(AVFormatContext *s)   

暂停网络流(例如RSTP流),使用av_read_play()重新开始。

av_read_play

原型

int av_read_play(AVFrameContext *s)

从当前的位置开始播放网络流(例如RSTP流)。

av_seek_frame

原型

int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)   

seek到某个时间点的关键帧。

av_read_frame

原型

int av_read_frame(AVFormatContext *s, AVPacket *pkt)    

读取码流中的音频若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码。

AVFormatContext

这个结构体描述了一个媒体文件或媒体流的构成和基本信息。
这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象。

avformat_alloc_context

分配一个AVFormatContext,使用avformat_free_context来释放分配出来的AVFormatContext。

avformat_open_input

原型

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options) 

打开输出的流和读取头信息。需要使用avformat_close_input关闭打开的流。

avformat_close_input

原型

void avformat_close_input(AVFormatContext **s)  

关闭一个打开的输入AVFormatContext,释放它得很所有内容和把指针(*s)置空。

av_dump_format

原型

void av_dump_format(AVFormatContext *ic, int index, const char * url, int is_output)

打印输入或者输出格式的详细信息,比如duration, bitrate, streams, container, programs, metadata, side data, codec and time base。

avformat_new_stream

原型

AVStream* avformat_new_stream(AVFormatContext *s, const AVCodec* c)

添加一个stream到媒体文件中。

avformat_write_header

原型

int avformat_write_header(AVFormatContext *s, AVDictionary ** options)

分配一个stream的私有数据而且写stream的header到一个输出的媒体文件。

AVPixelFormat

像素格式的枚举类型,例如AV_PIX_FMT_YUV420P、AV_PIX_FMT_RGB24

AVMediaType

媒体类型的枚举类型,如AVMEDIA_TYPE_VIDEO(视频)、AVMEDIA_TYPE_AUDIO(音频)、AVMEDIA_TYPE_SUBTITLE(字幕)

avformat_find_stream_info

原型

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)  

读取视音频数据来获取一些相关的信息。

av_file_map

原型:

av_file_map(const char *filename, uint8_t **bufptr, size_t * size, int log_offset, void * log_ctx)

读取文件名为filename的文件,并将其内容放入新分配的缓冲区中。
如果成功,则将bufptr设置为读缓冲区或映射缓冲区,并将size设置为*bufptr中缓冲区的字节大小。返回的缓冲区必须使用av_file_unmap()释放。

AVInputFormat

AVInputFormat为FFMPEG的解复用器对象。

AVStream

该结构体描述一个媒体流。

AVCodecParameters

该结构体描述了编码的流的属性。

avcodec_parameters_copy

原型

int avcodec_parameters_copy(AVCodecParameter *dst, const AVCodecParameter* src)

把src中的内容拷贝到dst中。

AVRational

这个结构标识一个分数,num为分数,den为分母。

AVCodecID

解码器标识ID的枚举类型。

swr_alloc

原型

struct SwrContext* swr_alloc(void)  

分配一个SwrContext,如果你使用这个函数,需要在调用swr_init()之前设置SwrContext的参数(手工的或者调用swr_alloc_set_opts())

SwrContext

libswresample 的上下文信息。
不像libavcodec和libavformat,这个结构是不透明的,如果你需要设置选项,你必须使用AVOptions而不能直接给这个结构的成员赋值。

swr_alloc_set_opts

原型

struct SwrContext* swr_alloc_set_opts(struct SwrContext *s,
int64_t out_ch_layout,
enum AVSampleFormat out_sample_fmt,
int out_sample_rate,
int64_t in_ch_layout,
enum AVSampleFormat in_sample_fmt,
int in_sample_rate,
int log_offset,
void *log_ctx 
)   

设置通用的参数,如果SwrContext为空则分配一个SwrContext。

swr_init

原型

init swr_init(struct SwrContext *s)

在参数设置好以后初始化context。

swr_free

原型

void swr_free(struct SwrContext **  s)  

释放给定的SwrContext,并且把指针置为空。

sws_getContext

原型


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。

avio_open

原型

int avio_open(AVIOContext **s, const char* filename, int flags)

创建和初始化一个AVIOContext用于访问filename指示的资源。

avio_closep

原型

int avio_closep(AVIOContext **s)

关闭AVIOContext** s打开的资源,释放它并且把指针置为空。

AV_ROUND

AV_ROUND_ZERO     = 0, // Round toward zero.      趋近于0  
AV_ROUND_INF      = 1, // Round away from zero.   趋远于0  
AV_ROUND_DOWN     = 2, // Round toward -infinity. 趋于更小的整数  
AV_ROUND_UP       = 3, // Round toward +infinity. 趋于更大的整数  
AV_ROUND_NEAR_INF = 5, // Round to nearest and halfway cases away from zero.  
                       //                         四舍五入,小于0.5取值趋向0,大于0.5取值趋远于0  

avio_alloc_context

原型

AVIOContext* avio_alloc_context(unsigned char* buffer,
                                                      int                     buffer_size,
                                                      int                     write_flag,
                                                      void*                 opaque,
                int(*)(void *opaque, uint8_t *buf, int buf_size) read_packet,
                int(*)(void *opaque, uint8_t *buf, int buf_size) write_packet,
                int64_t(*)(void *opaque, int64_t offset, int whence) seek)

分配和初始化一个AVIOContext用于缓冲的I/O。之后需要使用avio_context_free()释放。

av_file_unmap

原型

void av_file_unmap(uint8_t *bufptr, size_t size)

取消映射或释放av_file_map()创建的缓冲区bufptr。



作者:smallest_one
链接:https://www.jianshu.com/p/b6b8c185a617
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

=======================================================

//打开一个封装文件
avformat_open_input(&fmt_ctx, input_filename, NULL, NULL);

//获得封装文件的streamer流信息
avformat_find_stream_info(fmt_ctx, NULL);

//获得封装文件中音频或者视频流的id号
av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);

//获得音频或视频的codec
pCodecCtx = pFormatCtx->streams[0]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id); /
origin_par = fmt_ctx->streams[video_stream]->codecpar;
codec = avcodec_find_decoder(origin_par->codec_id);

avcodec_find_encoder(AV_CODEC_ID_FLAC);

//打开codec
avcodec_open2(pCodecCtx, pCodec, NULL);

//根据AVCodec创建AVCodecContext
AVCodecContext* ctx = avcodec_alloc_context3((AVCodec*)enc);

//申请一帧画面的大小
byte_buffer_size = av_image_get_buffer_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 16);
byte_buffer = av_malloc(byte_buffer_size);

//申请音频的大小
byte_buffer_size = av_samples_get_buffer_size(NULL, pCodecCtx->channels, pCodecCtx->sample_rate, pCodecCtx->sample_fmt, 1);

//读取封装文件里的一包数据
av_read_frame(pFormatCtx, &rd_packet);
保存此一包数据(比如h264压缩数据)
fwrite(rd_packet.data, 1, rd_packet.size, video_fp);

//AVPAcket/AVFrame的申请以及初始化操作
av_init_packet(&pkt);
fr = av_frame_alloc();

//解码成yuv的AVFrame
avcodec_decode_video2(ctx, fr, &got_frame, &pkt);

//将AVFrame结构体保存的一帧yuv数据转换成unsigned char*
number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size, (const uint8_t* const *)fr->data, (const int*) fr->linesize, ctx->pix_fmt, ctx->width, ctx->height, 1);/
out_frame_bytes = out_frame->nb_samples * out_frame->channels * sizeof(uint16_t);
memcpy(raw_out + out_offset, out_frame->data[0], out_frame_bytes);
out_offset += out_frame_bytes;

//AVFrame中buffer分配的两种方式(只是分配空间)
msg.frame->format = AV_PIX_FMT_RGBA;
msg.frame->width  = 320;
msg.frame->height = 240;
ret = av_frame_get_buffer(msg.frame, 32);        //int av_frame_get_buffer(AVFrame *frame, int align);
av_frame_get_buffer(in_frame, 32);
int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align);
out_frame = av_frame_alloc();
avcodec_encode_audio2(enc_ctx, &enc_pkt, in_frame, &got_output);    //编码
avcodec_decode_audio4(dec_ctx, out_frame, &got_output, &enc_pkt);    //解码

//线程相关
av_thread_message_queue_send(wd->queue, &msg, 0);
av_thread_message_queue_recv(rd->queue, &msg, 0);

//FFmpeg进行H.264编码
yuv->pts = vpts;
vpts++;
avcodec_send_frame(vc, yuv);
avcodec_receive_packet(vc, &pack);

//FFmpeg进行视频格式封装和推流
pack.pts = av_rescale_q(pack.pts, vc->time_base, vs->time_base);
pack.dts = av_rescale_q(pack.dts, vc->time_base, vs->time_base);
pack.duration = av_rescale_q(pack.duration, vc->time_base, vs->time_base);

//像素格式转换
sws_getCachedContext()
sws_scale()


///////////////////////////////////////实例介绍////////////////////////////////////////////////////////////
https://linux.cn/article-10932-1.html
//封装格式变换:
ffmpeg -i z.flv -strict -2 z.mp4
ffmpeg -i z.flv -qscale 0 -strict -2 z.avi    //-qscale 0 维持你的源视频文件的质量

//视频封装文件保存为音频文件
ffmpeg -i z.flv -vn -ar 44100 -ac 2 -ab 320 -f mp3 output.mp3
ffmpeg -i z.flv -vn(禁止视频) -ar 44100(采样率) -ac(通道数) 2 -ab(比特率) 320 -f(输出文件格式) mp3 output.mp3

//更改视频文件的分辨率
ffmpeg -i z.mp4 -filter:v scale=1280:720 -c:a copy output.mp4
ffmpeg -i input.mp4 -s 1280x720 -c:a copy output.mp4
ffmpeg -i z.mp4 -filter:v(视频过滤器) scale(拉伸过滤器)=1280:720 -c:a copy output.mp4
ffmpeg -i input.mp4 -s(尺寸裁剪) 1280x720 -c:a copy output.mp4

//压缩视频文件

//压缩音频文件(减少通道数,采样率,比特率等)
ffmpeg -i input.mp3 -ab 128 output.mp3

//从封装文件中获取视频流
ffmpeg -i z.mp4 -an video.mp4

//从封装文件中获取音频流
ffmpeg -i z.mp4 -vn audio.mp4
ffmpeg -i z.mp4 -vn -ab 256 -ar 48000 audio.mp3

//从视频中提取图片
ffmpeg -i input.mp4 -r 1 -f image2 image-%2d.png
ffmpeg -i input.mp4 -r(每秒钟提取一张图片(视频30s,则会提取30张图片)) 1 -f image2 image-%2d.png

//裁剪视频
ffmpeg -i input.mp4 -filter:v crop=320:120:200:150 output.mp4
ffmpeg -i input.mp4 -filter:v(视频过滤器) "crop(裁剪过滤器)=w:h:x:y" output.mp4

//转换一个视频的具体的部分(比如从视频开始到指定时间转换为其它格式)
ffmpeg -i input.mp4 -t 10.10 output.avi
ffmpeg -i input.mp4 -t(从视频开始到10s10ms处保存为avi格式) 10.10 output.avi

//使用开始和停止时间剪下一段媒体文件
ffmpeg -i z.mp4 -ss 00:00:10 -codec copy -t 50 output.mp4
ffmpeg -i z.mp4 -ss 00:00:10 -codec copy -t 50 output.avi

//设置视频的屏幕高宽比
ffmpeg -i input.mp4 -aspect 16:9 output.mp4
ffmpeg -i input.mp4 -aspect(设置宽高比) 16:9 output.mp4

//添加海报图像到音频文件
ffmpeg -loop 1 -i image-15.png -i audio.mp3 -c:v libx264 -c:a aac -strict experimental -b:a 192k -shortest output.mp4
ffmpeg -loop 1 -i inputimage.jpg -i inputaudio.mp3 -c:v(指定视频编解码模块) libx264 -c:a((指定音频编解码模块)) aac -strict experimental -b:a(?) 192k -shortest output.mp4

//切分视频文件为多个部分
ffmpeg -i input.mp4 -t 00:00:30 -c copy part1.mp4 -ss 00:00:30 -codec copy part2.mp4    //-c 和 -codec 同一个效果

//接合或合并多个视频部分到一个
ffmpeg -f concat -safe 0 -i join.txt -c copy output.mp4

//添加字幕到一个视频文件
ffmpeg -i input.mp4 -i subtitle.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4

//增加/减少视频播放速度
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output.mp4

//创建动画的 GIF
ffmpeg -ss 00:00:20 -i sample.mp4 -to 10 -r 10 -vf scale=200:-1 cutekid_cry.gif

===================================================================

av_register_all

该函数在所有基于FFmpeg的应用程序中几乎都是第一个被调用的
这个函数把全局的解码器,编码器等结构体注册到一些全局的对象表里,以便后面跑表调用
注册的类型:复用器,解复用器,编码器,解码器,包解析器,BitStreamFilter(位流处理器)等
av_register_all调用了avcodec_register_allavcodec_register_all注册了和编解码器有关的组件:硬件加速器,解码器,编码器,Parser,Bitstream Filter。av_register_all除了调用avcodec_register_all之外,还注册了复用器,解复用器,协议处理器

下面附上复用器,解复用器,协议处理器的代码

  • 注册复用器的函数是av_register_output_format
  • 注册解复用器的函数是av_register_input_format
  • 注册协议处理器的函数是ffurl_register_protocol

avcodec_register_all()

avcodec_register_all注册了和编解码器有关的组件:硬件加速器,解码器,编码器,Parser,Bitstream Filter。

  • 硬件加速器注册函数:av_register_hwaccel()
  • 编码器注册函数:avcodec_register()
  • parser注册函数:av_register_parser()
  • Bitstream Filter注册函数:av_register_bitstream_filter()

内存的分配和释放

内存操作的几个常见函数位于 libavutil\mem.c

先说下size_t,这个类型在FFmpeg中多次出现,它的作用其实就是为了增强程序的可移植性而定义的,不同系统上,定义size_t可能不一样,它实际上就是unsigned int

为什么要内存对齐:内存对齐是什么就不说了,c语言的,很多也有点忘记了,直接看结论吧:内存不对齐对cpu对性能是有影响的

  • av_malloc()
    源码也自己去看,除去源码中一大推宏类似于CONFIG_MEMORY_POISONING,因为这个宏默认都是为0的,源码函数可精简为

void *av_malloc(size_t size)
{
    void *ptr = NULL;
    /* let's disallow possibly ambiguous cases */
    if (size > (max_alloc_size - 32))
        return NULL;
    ptr = malloc(size);
    if(!ptr && !size) {
        size = 1;
        ptr= av_malloc(1);
    }
    return ptr;

所以可以看出来,av_malloc()只是封装了系统的malloc(),并且做了一些错误检查的工作

  • av_realloc
    用于对申请的内存的大小进行调整
    av_malloc()一样,除去没用的宏,精简为

void *av_realloc(void *ptr, size_t size)
{
    /* let's disallow possibly ambiguous cases */
    if (size > (max_alloc_size - 32))
        return NULL;
    return realloc(ptr, size + !size);
}

可以看出来,av_realloc()其实就是封装系统的realloc()

  • av_mallocz()
    av_mallocz()可以理解为av_mallocz()+zeromemory
    精简后

void *av_mallocz(size_t size)
{
    void *ptr = av_malloc(size);
    if (ptr)
        memset(ptr, 0, size);
    return ptr;
}

可以看出来就是调用了av_malloc(size)之后,又调用memset()将分配的内存设置为0

  • av_calloc()
    它是简单的封装了av_mallocz()

void *av_calloc(size_t nmemb, size_t size)
{
    if (size <= 0 || nmemb >= INT_MAX / size)
        return NULL;
    return av_mallocz(nmemb * size);
}

从代码中可以看出,它调用av_mallocz()分配了nmemb * size个字节的内存

  • av_free()
    用于释放申请的内存,除去没用的宏之外,代码如下
void av_free(void *ptr)
{
    free(ptr);
}

就是封装了free()

  • av_freep()
    简单了封装了av_free(),并且在释放内存之后将目标指针设置为NULL

void av_freep(void *arg)
{
    void **ptr = (void **)arg;
    av_free(*ptr);
    *ptr = NULL;
}

 

你可能感兴趣的:(嵌入式linux)