FFmpeg 中的 libpostproc
库是一个后处理库,主要用于视频解码后的图像处理。它的主要功能包括:
ffmpeg 中的 postproc 库
主要用途
- 去块效应(Deblocking)
- 处理压缩视频(如H.264/MPEG)解码后可能出现的块状伪影。
- 去环效应(Deringing)
- 减少高频噪声引起的振铃效应。
- 亮度/色度平滑(Brightness/Chroma Smoothing)
- 对图像进行降噪或平滑处理。
- 自动裁剪(Auto-crop)
- 检测并移除黑边。
是否可以去掉?
可以去掉,但需注意以下情况:
- 无后处理需求
- 如果处理的视频无需上述后处理(如原始视频质量已很高,或解码器自带去块功能),可以禁用。
- 性能考量
- 禁用后可能轻微提升性能(节省后处理计算),但对现代硬件影响通常很小。
- 编译时排除
- 通过FFmpeg编译配置
--disable-postproc
移除该库依赖。
- 通过FFmpeg编译配置
注意事项
- 兼容性:某些解码流(如低质量H.264)可能需要后处理来改善视觉效果。
- 替代方案:部分解码器(如libavcodec)内置了去块滤波,可能无需额外后处理。
操作建议
若确定不需要,重新编译FFmpeg时添加 --disable-postproc
即可。对于已编译的二进制文件,只要不调用相关功能(如 pp
滤镜),该库不会被加载。
libpostproc
库提供了一些后处理功能,主要用于视频解码后的图像处理(如去块效应、去环效应等)。虽然 FFmpeg 官方推荐使用 libavfilter
进行更灵活的滤镜处理,但 libpostproc
仍然可以直接调用。
主要函数
libpostproc
的核心函数和结构体定义在 <libpostproc/postprocess.h>
中,主要包括:
pp_postprocess()
– 执行后处理的主要函数。pp_get_mode_by_name_and_quality()
– 根据名称和质量获取后处理模式。pp_get_context()
/pp_free_context()
– 分配和释放后处理上下文。
使用示例
示例 1:基本后处理(去块 + 去环)
#include<libavcodec/avcodec.h>
#include<libpostproc/postprocess.h>
voidapply_postprocess(AVFrame *frame,int width,int height){
// 后处理模式(去块 + 去环)
int mode = PP_CPU_CAPS_MMX;// CPU 加速标志
int qp =5;// 量化参数(影响滤波强度)
// 获取后处理模式
pp_mode *ppmode =pp_get_mode_by_name_and_quality("deblock", qp);
if(!ppmode){
fprintf(stderr,"Failed to get postprocessing mode\n");
return;
}
// 创建后处理上下文
pp_context *ppctx =pp_get_context(width, height, mode);
if(!ppctx){
fprintf(stderr,"Failed to create postprocessing context\n");
pp_free_mode(ppmode);
return;
}
// 执行后处理(YUV420P 格式)
uint8_t*src[3]={ frame->data[0], frame->data[1], frame->data[2]};
int src_stride[3]={ frame->linesize[0], frame->linesize[1], frame->linesize[2]};
uint8_t*dst[3]={ frame->data[0], frame->data[1], frame->data[2]};
int dst_stride[3]={ frame->linesize[0], frame->linesize[1], frame->linesize[2]};
pp_postprocess(src, src_stride, dst, dst_stride, width, height,NULL,0, ppmode, ppctx);
// 释放资源
pp_free_mode(ppmode);
pp_free_context(ppctx);
}
示例 2:结合 FFmpeg 解码 + 后处理
#include<libavcodec/avcodec.h>
#include<libavformat/avformat.h>
#include<libpostproc/postprocess.h>
voiddecode_and_postprocess(constchar*filename){
AVFormatContext *fmt_ctx =NULL;
AVCodecContext *codec_ctx =NULL;
AVCodec *codec =NULL;
AVPacket pkt;
AVFrame *frame =av_frame_alloc();
// 打开输入文件
if(avformat_open_input(&fmt_ctx, filename,NULL,NULL)<0){
fprintf(stderr,"Could not open file\n");
return;
}
// 查找视频流
if(avformat_find_stream_info(fmt_ctx,NULL)<0){
fprintf(stderr,"Could not find stream info\n");
return;
}
int video_stream_idx =av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO,-1,-1,&codec,0);
if(video_stream_idx <0){
fprintf(stderr,"No video stream found\n");
return;
}
// 初始化解码器
codec_ctx =avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[video_stream_idx]->codecpar);
if(avcodec_open2(codec_ctx, codec,NULL)<0){
fprintf(stderr,"Could not open codec\n");
return;
}
// 初始化后处理
pp_mode *ppmode =pp_get_mode_by_name_and_quality("deblock",5);
pp_context *ppctx =pp_get_context(codec_ctx->width, codec_ctx->height, PP_CPU_CAPS_MMX);
// 读取并解码帧
while(av_read_frame(fmt_ctx,&pkt)>=0){
if(pkt.stream_index == video_stream_idx){
if(avcodec_send_packet(codec_ctx,&pkt)<0){
fprintf(stderr,"Error sending packet\n");
break;
}
while(avcodec_receive_frame(codec_ctx, frame)>=0){
// 应用后处理
uint8_t*src[3]={ frame->data[0], frame->data[1], frame->data[2]};
int src_stride[3]={ frame->linesize[0], frame->linesize[1], frame->linesize[2]};
pp_postprocess(src, src_stride, src, src_stride, codec_ctx->width, codec_ctx->height,NULL,0, ppmode, ppctx);
// 处理后的帧(可以保存或显示)
// ...
}
}
av_packet_unref(&pkt);
}
// 清理
pp_free_mode(ppmode);
pp_free_context(ppctx);
av_frame_free(&frame);
avcodec_free_context(&codec_ctx);
avformat_close_input(&fmt_ctx);
}
示例 2:结合 FFmpeg 解码 + 后处理
#include<libavcodec/avcodec.h>
#include<libavformat/avformat.h>
#include<libpostproc/postprocess.h>
voiddecode_and_postprocess(constchar*filename){
AVFormatContext *fmt_ctx =NULL;
AVCodecContext *codec_ctx =NULL;
AVCodec *codec =NULL;
AVPacket pkt;
AVFrame *frame =av_frame_alloc();
// 打开输入文件
if(avformat_open_input(&fmt_ctx, filename,NULL,NULL)<0){
fprintf(stderr,"Could not open file\n");
return;
}
// 查找视频流
if(avformat_find_stream_info(fmt_ctx,NULL)<0){
fprintf(stderr,"Could not find stream info\n");
return;
}
int video_stream_idx =av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO,-1,-1,&codec,0);
if(video_stream_idx <0){
fprintf(stderr,"No video stream found\n");
return;
}
// 初始化解码器
codec_ctx =avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[video_stream_idx]->codecpar);
if(avcodec_open2(codec_ctx, codec,NULL)<0){
fprintf(stderr,"Could not open codec\n");
return;
}
// 初始化后处理
pp_mode *ppmode =pp_get_mode_by_name_and_quality("deblock",5);
pp_context *ppctx =pp_get_context(codec_ctx->width, codec_ctx->height, PP_CPU_CAPS_MMX);
// 读取并解码帧
while(av_read_frame(fmt_ctx,&pkt)>=0){
if(pkt.stream_index == video_stream_idx){
if(avcodec_send_packet(codec_ctx,&pkt)<0){
fprintf(stderr,"Error sending packet\n");
break;
}
while(avcodec_receive_frame(codec_ctx, frame)>=0){
// 应用后处理
uint8_t*src[3]={ frame->data[0], frame->data[1], frame->data[2]};
int src_stride[3]={ frame->linesize[0], frame->linesize[1], frame->linesize[2]};
pp_postprocess(src, src_stride, src, src_stride, codec_ctx->width, codec_ctx->height,NULL,0, ppmode, ppctx);
// 处理后的帧(可以保存或显示)
// ...
}
}
av_packet_unref(&pkt);
}
// 清理
pp_free_mode(ppmode);
pp_free_context(ppctx);
av_frame_free(&frame);
avcodec_free_context(&codec_ctx);
avformat_close_input(&fmt_ctx);
}
可用的后处理模式
pp_get_mode_by_name_and_quality()
支持的常见模式:
名称 | 作用 |
---|---|
"deblock" | 去块效应(默认) |
"dering" | 去环效应 |
"autolevels" | 自动调整亮度/对比度 |
"denoise" | 降噪 |
"deinterlace" | 去隔行(简单模式) |
现代替代方案(推荐)
libpostproc
已经逐渐被 libavfilter
取代,推荐使用 FFmpeg 滤镜(如 -vf pp=...
或 -vf deband
)进行后处理:
ffmpeg -i input.mp4 -vf"pp=deblock" output.mp4
总结
libpostproc
提供简单的后处理功能,适用于去块、去环等操作。- 现代 FFmpeg 更推荐使用
libavfilter
(如-vf pp
或自定义滤镜链)。 - 如果不需要后处理,可以在编译 FFmpeg 时禁用
--disable-postproc
。
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。