目录
1. av_register_all()——弃用
2. avformat_alloc_context()
3.avformat_open_input()
4.avformat_find_stream_info()
5.av_read_frame()
6.avcodec_send_packet
7.avcodec_receive_frame()
8.avcodec_open2
9. sws_getContext()
10.sws_scale()
初始化 libavformat 和注册所有的复用器、解复用器和协议处理器。如果不调用这个函数,可以调用下面的三个函数来选择支持的格式。
• 注册复用器的函数是av_register_output_format()。
• 注册解复用器的函数是av_register_input_format()。
• 注册协议处理器的函数是ffurl_register_protocol()。
注:FFmpeg4.0 以上的版本,这个函数已经被废弃。
当使用AVFormatContext时, avformat_alloc_context()函数用来对AVFormatContext分配空间,
AVFormatContext *avFormatContext = avformat_alloc_context();//获取上下文
avformat_open_input的主要功能是打开一个文件,读取header,不会涉及打开编码器。
与之对应的是通过avformat_close_input函数关闭文件。
示例代码:
int error;
//打开视频地址并获取里面的内容(解封装)
error = avformat_open_input(&avFormatContext, inputPath, NULL, NULL);
if (error < 0) {
LOGE("打开视频失败")
return;
}
读取音视频数据来获取一些相关的信息。
示例代码:
if (avformat_find_stream_info(avFormatContext, NULL) < 0) {
LOGE("获取内容失败")
return;
}
在FFmpeg中av_read_frame函数的作用是读取码流中的若干音频帧或者1帧数据。在解码视频时,每解码一个视频帧,需要先调用av_read_frame获取1帧视频的压缩数据,然后才能对该数据进行解码。
示例代码:
while(1) {
int ret = av_read_frame(avFormatContext, packet);
if (ret != 0) {
av_strerror(ret, buf, sizeof(buf));
LOGE("--%s--\n", buf);
av_packet_unref(packet);
break;
}
if (ret >= 0 && packet->stream_index != mVideoStreamIdx) {
av_packet_unref(packet);
continue;
}
//省略...
}
发送数据到ffmepg,放到解码队列中
// 发送待解码包
int result = avcodec_send_packet(mAvContext, packet);
将成功的解码队列中取出1个frame
示例代码:
while (result >= 0) {
result = avcodec_receive_frame(mAvContext, frame);
if (result == AVERROR_EOF)
break;
else if (result == AVERROR(EAGAIN)) {
result = 0;
break;
} else if (result < 0) {
av_log(NULL, AV_LOG_ERROR, "Error decoding frame\n");
av_frame_unref(frame);
break;
}
// 省略...
}
打开解码器
示例代码:
// 打开解码器
if (avcodec_open2(mAvContext, mVcodec, NULL) != 0){
LOGE("打开失败")
return;
}
分配和返回一个 SwsContext。其原型如下:
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* swsContext = sws_getContext(mAvContext->width,mAvContext->height,mAvContext->pix_fmt,
mAvContext->width,mAvContext->height,AV_PIX_FMT_RGBA,
SWS_BICUBIC,NULL,NULL,NULL);
处理图像数据。
其原型如下:
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 *c: 转换格式的上下文。
srcSlice[],:输入图像的每个颜色通道的数据指针。
srcStride[]:输入图像的每个颜色通道的跨度。.
srcSliceY:起始位置。
srcSliceH:处理多少行。
dst[]:输出图像的每个颜色通道数据指针。
dstStride[]:输出图像的每个颜色通道行字节数。
示例代码:
//转换为rgb格式
sws_scale(swsContext, (const uint8_t *const *) frame->data, frame->linesize, 0,
frame->height, rgb_frame->data,
rgb_frame->linesize);