FFmpeg———encode

慈云数据 2024-05-11 技术支持 43 0

目录

  • 前言
  • 源码
  • 函数
  • 最终效果

    前言

    encode_video:实现了对图片使用指定编码进行编码,生成可播放的视频流,编译时出现了一些错误,做了一些调整。

    基本流程

    1、获取指定的编码器

    2、编码器内存申请

    3、编码器上下文内容参数设置

    4、打开编码器

    5、申请数据帧内存

    6、模拟图片

    7、编码

    源码

    测试代码,做了部分修改

    #include 
    using namespace std;
    #include 
    #include 
    #include 
    extern"C"
    {
    #include "libavcodec/avcodec.h"
    #include "libavutil/opt.h"
    #include "libavutil/imgutils.h"
    #include "libavutil/error.h"
    }
    static void encode(AVCodecContext* enc_ctx, AVFrame* frame, AVPacket* pkt,
        FILE* outfile)
    {
        int ret;
        /* send the frame to the encoder */
        if (frame)
            printf("Send frame %lld\n", frame->pts);  //修改 lld 替换 PRId64
        /*avcodec_send_frame 与 avcodec_receive_packet 配合使用*/
        ret = avcodec_send_frame(enc_ctx, frame);
        if (ret = 0) {
            ret = avcodec_receive_packet(enc_ctx, pkt);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                return;
            else if (ret pts, pkt->size); //修改 lld 替换 PRId64
            fwrite(pkt->data, 1, pkt->size, outfile);
            av_packet_unref(pkt); //清空数据压缩包
        }
    }
    int main()
    {
        const char* filename;
        const AVCodec* codec;
        AVCodecContext* c = NULL;  // 编码器上下文
        int i, ret, x, y;
        FILE* f;
        AVFrame* frame;  // 音视频数据帧结构体
        AVPacket* pkt;
        uint8_t endcode[] = { 0, 0, 1, 0xb7 };
        filename = "text_264";
        /* find the mpeg1video encoder */
        codec = avcodec_find_encoder(AV_CODEC_ID_H264);
        if (!codec) {
            fprintf(stderr, "Codec not found\n");
            exit(1);
        }
       // 为编码器申请空间并设置初始值
        c = avcodec_alloc_context3(codec);
        if (!c) {
            fprintf(stderr, "Could not allocate video codec context\n");
            exit(1);
        }
        pkt = av_packet_alloc();
        if (!pkt)
            exit(1);
        /* put sample parameters */
        c->bit_rate = 400000;
        /* 分辨率 为2的倍数 */
        c->width = 352;
        c->height = 288;
        /* frames per second */
        c->time_base.num = 1;
        c->time_base.den = 25;
        //帧率
        c->framerate.num = 25;
        c->framerate.den = 1;
        /* emit one intra frame every ten frames
         * check frame pict_type before passing frame
         * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
         * then gop_size is ignored and the output of encoder
         * will always be I frame irrespective to gop_size
         */
        c->gop_size = 10;
        c->max_b_frames = 1;  //非B帧之间的最大的B帧数
        c->pix_fmt = AV_PIX_FMT_YUV420P;   //像素格式
        if (codec->id == AV_CODEC_ID_H264)
            av_opt_set(c->priv_data, "preset", "slow", 0);   //设置属性
        /* open it */
        ret = avcodec_open2(c, codec, NULL);
        if (ret format = c->pix_fmt;
        frame->width = c->width;
        frame->height = c->height;
        ret = av_frame_get_buffer(frame, 0);  //申请数据帧缓冲区
        if (ret height; y++) {
                for (x = 0; x width; x++) {
                    frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
                }
            }
            /* Cb and Cr */
            for (y = 0; y height / 2; y++) {
                for (x = 0; x 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;
            /* encode the image */
            encode(c, frame, pkt, f);
        }
        /* flush the encoder */
        encode(c, NULL, pkt, f);
        /* Add sequence end code to have a real MPEG file.
           It makes only sense because this tiny examples writes packets
           directly. This is called "elementary stream" and only works for some
           codecs. To create a valid file, you usually need to write packets
           into a proper file format or protocol; see mux.c.
         */
        if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO)
            fwrite(endcode, 1, sizeof(endcode), f);
        fclose(f);
        avcodec_free_context(&c);
        av_frame_free(&frame);
        av_packet_free(&pkt);
        return 0;
    }
    

    函数

    1、int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);

    向编码器发送音频或视频的数据包与

    int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);配合使用

    成功返回0

    2、av_err2str(errnum)

    编译会报错

    修改:

    char av_error[AV_ERROR_MAX_STRING_SIZE] = { 0 };
    #define av_err2str(errnum) \
        av_make_error_string(av_error, AV_ERROR_MAX_STRING_SIZE, errnum)
    

    最终效果

    在这里插入图片描述

微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon