ffmpeg h64编码

#include <fstream>
#include <iostream>

extern "C"
{
#include <libavcodec/avcodec.h>
}


#define print(x) std::cout << x << std::endl

void print_av_err(int ret)
{
    char buf[1024] = {0};
    av_strerror(ret, buf, sizeof(buf) - 1);
    std::cerr << buf << std::endl;
}

#define H264

int main(int argc, char **argv)
{
    // 一定要注册,不然会找不到编码器!!!!!!!!!!!!!!!!!
    avcodec_register_all();
    AVCodecID codec_id = AV_CODEC_ID_H264;
    std::string filename = "400_300_25.h264";
   

    // std::ifstream ifs;
    // ifs.open("/workspace/ffmpeg_tutorials/tutorials/ch02/resource/400_300_25.yuv", std::ios::binary);
    // if (!ifs)
    // {
    //     std::cerr << "file1 open failed!" << std::endl;
    //     return -1;
    // }

    std::ofstream ofs;
    ofs.open(filename, std::ios::binary);
    if (!ofs)
    {
        std::cerr << "file2 open failed!" << std::endl;
        return -1;
    }

    // 1.查找编码器
    AVCodec *codec = avcodec_find_encoder(codec_id);
    if (!codec)
    {
        std::cerr << "codec not found!" << std::endl;
        return -1;
    }

    // 2.编码上下文
    AVCodecContext *ctx = avcodec_alloc_context3(codec);
    if (!ctx)
    {
        std::cerr << "context alloc failed!" << std::endl;
        return -1;
    }

    // 3.设定上下文参数
    ctx->width = 400;
    ctx->height = 300;
    ctx->pix_fmt = AV_PIX_FMT_YUV420P;
    ctx->time_base = {1, 25}; //帧时间戳单位,pts帧id,每帧时间=pts*1/25
    ctx->thread_count = 8;    //编码线程数,可以用过调用系统接口获得cpu核心数量

    // 4.打开编码上下文
    auto ret = avcodec_open2(ctx, codec, NULL);
    if (ret)
    {
        char buf[1024] = {0};
        av_strerror(ret, buf, sizeof(buf) - 1);
        std::cerr << "avcodec_open2 failed!" << buf << std::endl;
        return -1;
    }

    std::cout << "codec context 创建成功!" << std::endl;

    // 创建AVFrame
    AVFrame *frame = av_frame_alloc();
    frame->width = ctx->width;
    frame->height = ctx->height;
    frame->format = ctx->pix_fmt;
    // frame->linesize[0] = ctx->width;
    // frame->linesize[1] = ctx->width / 2;
    // frame->linesize[2] = ctx->width / 2;

    ret = av_frame_get_buffer(frame, 0);
    if (ret)
    {
        char buf[1024] = {0};
        av_strerror(ret, buf, sizeof(buf) - 1);
        std::cerr << "frame create failed!" << buf << std::endl;
        return -1;
    }

    // 创建AVPacket
    AVPacket *packet = av_packet_alloc();

    // 开始生成视频文件  10s 25fps

    for (int i = 0; i < 250; ++i)
    {
        // Y
        for (int y = 0; y < ctx->height; ++y)
        {
            for (int x = 0; x < ctx->width; ++x)
            {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }
        // UV
        for (int y = 0; y < ctx->height / 2; ++y)
        {
            for (int x = 0; x < ctx->width / 2; ++x)
            {
                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }
        frame->pts = i; //帧序列id

        //开始压缩
        ret = avcodec_send_frame(ctx, frame);
        if (ret)
        {
            std::cerr << "avcodec_send_frame failed!" << std::endl;
            break;
        }

        // 等待接收压缩完的数据
        // 一般情况下,前几次会返回null,编码未完成
        // 编码实在独立的线程中执行的,每次调用会重新分配packet中的空间
        while (1)
        {
            ret = avcodec_receive_packet(ctx, packet);
            // 如果读完当前帧, 则退出循环
            if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
            {
                std::cerr << "avcodec_receive_packet failed!" << std::endl;
                break;
            }
            if (ret)
            {
                char buf[1024] = {0};
                av_strerror(ret, buf, sizeof(buf) - 1);
                // std::cerr << "avcodec_receive_packet failed!" << buf << std::endl;
                // break;
                continue;
            }
            std::cout << "压缩之后数据大小为:" << packet->size << std::endl;
            ofs.write((char *)packet->data, packet->size);

            // 每次释放packet资源并重新分配
            av_packet_unref(packet);
        }
    }

    av_packet_free(&packet);
    av_frame_free(&frame);

    //释放编码器上下文
    avcodec_free_context(&ctx);

    // ifs.close();
    ofs.close();

    return 0;
}
cmake_minimum_required(VERSION 3.4.1)
SET(CMAKE_CXX_STANDARD 11)

project(main)

add_executable(main main.cpp)
target_link_libraries(main avcodec avutil )
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,介绍一下C++中使用FFmpeg进行H.265硬编码的方法。 在C++中使用FFmpeg进行H.265硬编码,可以通过以下步骤实现[^1]: 1. 初始化FFmpeg库和相关的编码器。 2. 创建输入和输出的AVFormatContext。 3. 打开输入文件并读取视频流的信息。 4. 创建输出文件并设置编码器的参数。 5. 打开输出文件并写入文件头。 6. 循环读取输入文件中的视频帧。 7. 将视频帧送入编码器进行编码。 8. 将编码后的数据写入输出文件。 9. 释放资源并关闭文件。 下面是一个示例代码,演示了如何使用FFmpeg进行H.265硬编码: ```cpp extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/opt.h> } int main() { // 初始化FFmpeg库 av_register_all(); avcodec_register_all(); // 创建输入和输出的AVFormatContext AVFormatContext* inputFormatContext = avformat_alloc_context(); AVFormatContext* outputFormatContext = avformat_alloc_context(); // 打开输入文件并读取视频流的信息 avformat_open_input(&inputFormatContext, "input.mp4", nullptr, nullptr); avformat_find_stream_info(inputFormatContext, nullptr); // 创建输出文件并设置编码器的参数 avformat_alloc_output_context2(&outputFormatContext, nullptr, nullptr, "output.mp4"); AVStream* outputStream = avformat_new_stream(outputFormatContext, nullptr); AVCodec* codec = avcodec_find_encoder_by_name("libx265"); AVCodecContext* codecContext = avcodec_alloc_context3(codec); codecContext->width = inputFormatContext->streams->codecpar->width; codecContext->height = inputFormatContext->streams->codecpar->height; codecContext->pix_fmt = AV_PIX_FMT_YUV420P; avcodec_open2(codecContext, codec, nullptr); // 打开输出文件并写入文件头 avio_open(&outputFormatContext->pb, "output.mp4", AVIO_FLAG_WRITE); avformat_write_header(outputFormatContext, nullptr); // 循环读取输入文件中的视频帧 AVPacket packet; while (av_read_frame(inputFormatContext, &packet) >= 0) { if (packet.stream_index == 0) { // 将视频帧送入编码器进行编码 avcodec_send_packet(codecContext, &packet); while (avcodec_receive_packet(codecContext, &packet) == 0) { // 将编码后的数据写入输出文件 av_interleaved_write_frame(outputFormatContext, &packet); av_packet_unref(&packet); } } av_packet_unref(&packet); } // 释放资源并关闭文件 av_write_trailer(outputFormatContext); avcodec_free_context(&codecContext); avformat_close_input(&inputFormatContext); avformat_free_context(inputFormatContext); avio_close(outputFormatContext->pb); avformat_free_context(outputFormatContext); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值