我们在FFmpeg简单总结对FFmpeg 组成模块,编码进行了简单介绍。
FFmpeg组成部分:
libavcodec: 提供了音视频编解码器的库。
libavformat: 处理多媒体容器格式的库,包括封装和解封装。
libavutil: 包含一些公共的实用工具函数。
libswscale: 提供图像缩放和颜色转换功能的库。
libavfilter: 实现音视频过滤器的库,用于进行各种音视频处理操作。
ffmpeg: 命令行工具,用于进行音视频处理和转码。
ffprobe: 用于检测多媒体文件信息的命令行工具。
ffplay: 简单的播放器,支持音视频播放。
libswscale(Software Scaling and Conversion Library)是FFmpeg中的一个库,用于执行图像缩放、颜色空间转换以及图像格式转换等操作。它主要提供了一些函数和工具,使得在视频处理过程中可以方便地进行图像大小和颜色空间的调整。
sws_getContext: 创建并返回一个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);
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[]);
sws_freeContext: 释放SwsContext对象占用的资源。
void sws_freeContext(struct SwsContext *swsContext);
下面给出一个例子,使用FFmpeg对图像进行处理,该程序解码视频流,选取视频流中的输入图片,进行灰度化处理,然后保存为新的图片
#include
#include
#include
#include
#include
#include
void process_image(const char *input_filename, const char *output_filename) {
AVFormatContext *input_format_context = NULL;
AVCodecContext *codec_context = NULL;
AVCodec *codec = NULL;
AVFrame *frame = NULL;
AVFrame *gray_frame = NULL;
AVPacket packet;
struct SwsContext *sws_context = NULL;
// Register FFmpeg components
av_register_all();
// Open input file
if (avformat_open_input(&input_format_context, input_filename, NULL, NULL) != 0) {
fprintf(stderr, "Error opening input file\n");
exit(EXIT_FAILURE);
}
// Retrieve stream information
if (avformat_find_stream_info(input_format_context, NULL) < 0) {
fprintf(stderr, "Error finding stream information\n");
exit(EXIT_FAILURE);
}
// Find the first video stream
int video_stream_index = -1;
for (int i = 0; i < input_format_context->nb_streams; i++) {
if (input_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
break;
}
}
if (video_stream_index == -1) {
fprintf(stderr, "Error: No video stream found\n");
exit(EXIT_FAILURE);
}
// Find the decoder for the video stream
codec = avcodec_find_decoder(input_format_context->streams[video_stream_index]->codecpar->codec_id);
if (!codec) {
fprintf(stderr, "Error: No decoder found\n");
exit(EXIT_FAILURE);
}
// Allocate a codec context for the decoder
codec_context = avcodec_alloc_context3(codec);
if (!codec_context) {
fprintf(stderr, "Error allocating codec context\n");
exit(EXIT_FAILURE);
}
// Copy codec parameters from input stream to codec context
if (avcodec_parameters_to_context(codec_context, input_format_context->streams[video_stream_index]->codecpar) < 0) {
fprintf(stderr, "Error setting codec parameters\n");
exit(EXIT_FAILURE);
}
// Open codec
if (avcodec_open2(codec_context, codec, NULL) < 0) {
fprintf(stderr, "Error opening codec\n");
exit(EXIT_FAILURE);
}
// Allocate video frames
frame = av_frame_alloc();
gray_frame = av_frame_alloc();
if (!frame || !gray_frame) {
fprintf(stderr, "Error allocating frames\n");
exit(EXIT_FAILURE);
}
// Determine required buffer size and allocate buffer
int num_bytes = av_image_get_buffer_size(AV_PIX_FMT_GRAY8, codec_context->width, codec_context->height, 1);
uint8_t *buffer = (uint8_t *)av_malloc(num_bytes * sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in gray_frame
av_image_fill_arrays(gray_frame->data, gray_frame->linesize, buffer, AV_PIX_FMT_GRAY8, codec_context->width, codec_context->height, 1);
// Initialize SwsContext for converting between color spaces
sws_context = sws_getContext(
codec_context->width, codec_context->height, codec_context->pix_fmt,
codec_context->width, codec_context->height, AV_PIX_FMT_GRAY8,
SWS_BILINEAR, NULL, NULL, NULL);
// Open output file
FILE *output_file = fopen(output_filename, "wb");
if (!output_file) {
fprintf(stderr, "Error opening output file\n");
exit(EXIT_FAILURE);
}
// Read frames from the input file, convert to grayscale, and write to the output file
while (av_read_frame(input_format_context, &packet) == 0) {
if (packet.stream_index == video_stream_index) {
// Decode video frame
if (avcodec_receive_frame(codec_context, frame) == 0) {
// Convert frame to grayscale
sws_scale(sws_context, frame->data, frame->linesize, 0, frame->height, gray_frame->data, gray_frame->linesize);
// Write grayscale frame to output file
fwrite(gray_frame->data[0], 1, num_bytes, output_file);
}
}
av_packet_unref(&packet);
}
// Cleanup
fclose(output_file);
av_frame_free(&frame);
av_frame_free(&gray_frame);
av_free(buffer);
sws_freeContext(sws_context);
avcodec_close(codec_context);
avformat_close_input(&input_format_context);
}
int main() {
const char *input_filename = "input.jpg";
const char *output_filename = "output.gray";
process_image(input_filename, output_filename);
return 0;
}
也可以直接用接口函数,对image操作
#include
#include
#include
#include
int main() {
// Input image parameters
int src_width = 1920;
int src_height = 1080;
enum AVPixelFormat src_format = AV_PIX_FMT_RGB24;
// Output image parameters
int dst_width = 640;
int dst_height = 360;
enum AVPixelFormat dst_format = AV_PIX_FMT_YUV420P;
// Allocate source and destination buffers
uint8_t *src_data[4];
int src_linesize[4];
uint8_t *dst_data[4];
int dst_linesize[4];
// Initialize SwsContext
struct SwsContext *sws_context = sws_getContext(src_width, src_height, src_format,
dst_width, dst_height, dst_format,
SWS_BILINEAR, NULL, NULL, NULL);
// Perform scaling and color space conversion
sws_scale(sws_context, src_data, src_linesize, 0, src_height,
dst_data, dst_linesize);
// Free resources
sws_freeContext(sws_context);
return 0;
}