调整视频的分辨率

main.cpp

cpp 复制代码
extern "C" {
    #include <libavformat/avformat.h>
    #include <libavcodec/avcodec.h>
    #include <libavutil/avutil.h>
    #include <libavutil/imgutils.h>
    #include <libswscale/swscale.h>
}

#include <iostream>
#include <string>

int resize_video(const std::string &input_filename, const std::string &output_filename, int width, int height) {
    av_register_all();

    AVFormatContext *input_format_context = nullptr;
    if (avformat_open_input(&input_format_context, input_filename.c_str(), nullptr, nullptr) < 0) {
        std::cerr << "Could not open input file." << std::endl;
        return -1;
    }

    if (avformat_find_stream_info(input_format_context, nullptr) < 0) {
        std::cerr << "Could not find stream information." << std::endl;
        return -1;
    }

    AVCodec *decoder = nullptr;
    int video_stream_index = av_find_best_stream(input_format_context, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
    if (video_stream_index < 0) {
        std::cerr << "Could not find video stream in the input file." << std::endl;
        return -1;
    }

    AVCodecContext *decoder_context = avcodec_alloc_context3(decoder);
    if (!decoder_context) {
        std::cerr << "Could not allocate decoder context." << std::endl;
        return -1;
    }

    if (avcodec_parameters_to_context(decoder_context, input_format_context->streams[video_stream_index]->codecpar) < 0) {
        std::cerr << "Could not copy decoder parameters to decoder context." << std::endl;
        return -1;
    }

    if (avcodec_open2(decoder_context, decoder, nullptr) < 0) {
        std::cerr << "Could not open decoder." << std::endl;
        return -1;
    }

    AVFormatContext *output_format_context = nullptr;
    if (avformat_alloc_output_context2(&output_format_context, nullptr, nullptr, output_filename.c_str()) < 0) {
        std::cerr << "Could not create output context." << std::endl;
        return -1;
    }

    AVStream *output_stream = avformat_new_stream(output_format_context, nullptr);
    if (!output_stream) {
        std::cerr << "Failed to allocate output stream." << std::endl;
        return -1;
    }

    AVCodec *encoder = avcodec_find_encoder(decoder_context->codec_id);
    if (!encoder) {
        std::cerr << "Necessary encoder not found." << std::endl;
        return -1;
    }

    AVCodecContext *encoder_context = avcodec_alloc_context3(encoder);
    if (!encoder_context) {
        std::cerr << "Could not allocate encoder context." << std::endl;
        return -1;
    }

    encoder_context->height = height;
    encoder_context->width = width;
    encoder_context->sample_aspect_ratio = decoder_context->sample_aspect_ratio;
    encoder_context->pix_fmt = encoder->pix_fmts[0];
    encoder_context->time_base = av_inv_q(decoder_context->framerate);

    if (output_format_context->oformat->flags & AVFMT_GLOBALHEADER) {
        encoder_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    }

    if (avcodec_open2(encoder_context, encoder, nullptr) < 0) {
        std::cerr << "Could not open encoder." << std::endl;
        return -1;
    }

    if (avcodec_parameters_from_context(output_stream->codecpar, encoder_context) < 0) {
        std::cerr << "Could not copy encoder parameters to output stream." << std::endl;
        return -1;
    }

    output_stream->time_base = encoder_context->time_base;

    if (!(output_format_context->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&output_format_context->pb, output_filename.c_str(), AVIO_FLAG_WRITE) < 0) {
            std::cerr << "Could not open output file." << std::endl;
            return -1;
        }
    }

    if (avformat_write_header(output_format_context, nullptr) < 0) {
        std::cerr << "Error occurred when opening output file." << std::endl;
        return -1;
    }

    AVFrame *frame = av_frame_alloc();
    AVFrame *sws_frame = av_frame_alloc();
    if (!frame || !sws_frame) {
        std::cerr << "Could not allocate frame." << std::endl;
        return -1;
    }

    sws_frame->format = encoder_context->pix_fmt;
    sws_frame->width = encoder_context->width;
    sws_frame->height = encoder_context->height;

    if (av_image_alloc(sws_frame->data, sws_frame->linesize, width, height, encoder_context->pix_fmt, 32) < 0) {
        std::cerr << "Could not allocate destination image." << std::endl;
        return -1;
    }

    SwsContext *sws_context = sws_getContext(
        decoder_context->width, decoder_context->height, decoder_context->pix_fmt,
        width, height, encoder_context->pix_fmt,
        SWS_BILINEAR, nullptr, nullptr, nullptr
    );

    AVPacket packet;
    av_init_packet(&packet);
    packet.data = nullptr;
    packet.size = 0;

    while (av_read_frame(input_format_context, &packet) >= 0) {
        if (packet.stream_index == video_stream_index) {
            if (avcodec_send_packet(decoder_context, &packet) == 0) {
                while (avcodec_receive_frame(decoder_context, frame) == 0) {
                    sws_scale(sws_context, frame->data, frame->linesize, 0, frame->height, sws_frame->data, sws_frame->linesize);
                    sws_frame->pts = frame->pts;
                    if (avcodec_send_frame(encoder_context, sws_frame) == 0) {
                        AVPacket encoded_packet;
                        av_init_packet(&encoded_packet);
                        encoded_packet.data = nullptr;
                        encoded_packet.size = 0;
                        while (avcodec_receive_packet(encoder_context, &encoded_packet) == 0) {
                            av_interleaved_write_frame(output_format_context, &encoded_packet);
                            av_packet_unref(&encoded_packet);
                        }
                    }
                }
            }
        }
        av_packet_unref(&packet);
    }

    av_write_trailer(output_format_context);

    avcodec_close(decoder_context);
    avcodec_close(encoder_context);
    avformat_close_input(&input_format_context);
    if (output_format_context && !(output_format_context->oformat->flags & AVFMT_NOFILE)) {
        avio_closep(&output_format_context->pb);
    }
    avformat_free_context(output_format_context);
    av_frame_free(&frame);
    av_frame_free(&sws_frame);
    sws_freeContext(sws_context);

    return 0;
}

int main(int argc, char *argv[]) {
    if (argc < 5) {
        std::cerr << "Usage: " << argv[0] << " <input file> <output file> <width> <height>" << std::endl;
        return -1;
    }

    std::string input_filename = argv[1];
    std::string output_filename = argv[2];
    int width = std::stoi(argv[3]);
    int height = std::stoi(argv[4]);

    if (resize_video(input_filename, output_filename, width, height) == 0) {
        std::cout << "Video resized successfully." << std::endl;
    } else {
        std::cout << "Failed to resize video." << std::endl;
    }

    return 0;
}

代码解释

  1. 初始化 FFmpeg :使用 av_register_all() 初始化 FFmpeg 库。
  2. 打开输入文件 :使用 avformat_open_input() 打开输入文件,并获取输入文件的格式上下文。
  3. 查找视频流 :使用 av_find_best_stream() 查找输入文件中的视频流,并获取其解码器和解码器上下文。
  4. 打开解码器 :使用 avcodec_open2() 打开解码器。
  5. 创建输出文件上下文 :使用 avformat_alloc_output_context2() 创建输出文件的格式上下文。
  6. 创建输出流并初始化编码器:为输出文件创建一个新的流,并为其分配编码器上下文。设置编码器上下文的宽度、高度、像素格式和时间基准。
  7. 打开编码器 :使用 avcodec_open2() 打开编码器。
  8. 写入文件头 :使用 avformat_write_header() 将文件头写入输出文件。
  9. 初始化 SWS 上下文 :使用 sws_getContext() 初始化 SWS 上下文,用于缩放图像。
  10. 读取和处理帧:循环读取输入文件中的每个帧,缩放帧,并将其发送到编码器,然后将编码后的帧写入输出文件。
  11. 写入文件尾 :使用 av_write_trailer() 写入输出文件的文件尾。
  12. 清理资源:关闭解码器和编码器,关闭输入和输出文件,并释放所有分配的资源。
相关推荐
老歌老听老掉牙5 分钟前
粒子群优化算法实现与多维函数优化应用
c++·pso·粒子群算法
myloveasuka30 分钟前
信号操作集函数
linux·运维·服务器·c语言·c++·vscode
山野万里__44 分钟前
C++与Java内存共享技术:跨平台与跨语言实现指南
android·java·c++·笔记
Mr_Xuhhh1 小时前
网络基础(1)
c语言·开发语言·网络·c++·qt·算法
音视频牛哥2 小时前
计算机视觉的新浪潮:扩散模型(Diffusion Models)技术剖析与应用前景
人工智能·计算机视觉·ai·音视频·实时音视频·扩散模型
醇醛酸醚酮酯2 小时前
std::promise和std::future的使用示例——单线程多链接、多线程单链接
网络·c++·算法
背影疾风2 小时前
C++之路:类基础、构造析构、拷贝构造函数
linux·开发语言·c++
电子科技圈3 小时前
SmartDV推出先进的H.264和H.265视频编码器和解码器IP
音视频·h.265·h.264
程序员弘羽3 小时前
C++ 第四阶段 内存管理 - 第二节:避免内存泄漏的技巧
java·jvm·c++
DolphinDB4 小时前
如何在C++交易系统中集成高性能回测与模拟撮合
c++