FFMPEG yuv编码H264

雷霄骅-CSDN博客 讲FFMpeg感觉很详细

代码是在雷霄骅的基础上稍加修改

Ubuntu FFMpeg与x264安装


x264安装:
git clone https://code.videolan.org/videolan/x264.git
cd x264/
./configure --prefix=/usr/local/x264 --disable-asm
make &&sudo make install
sudo vim /etc/profile
export PATH="/usr/local/x264/bin:$PATH"


ffmpeg安装
wget http://ffmpeg.org/releases/ffmpeg-4.2.tar.bz2
tar xvjf ffmpeg-4.2.tar.bz2
cd ffmpeg-4.2/
./configure --enable-shared --disable-x86asm --enable-libx264  --enable-gpl  --prefix=/usr/local/ffmpeg
make && sudo make install
sudo ldconfig

将yuv视频文件编码成H264文件存储



extern "C"
{
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    #include <libavdevice/avdevice.h>
    #include <libavformat/version.h>
    #include <libavutil/time.h>
    #include <libavutil/mathematics.h>
    #include <libavfilter/buffersink.h>
    #include <libavfilter/buffersrc.h>
    #include <libavutil/avutil.h>
    #include <libavutil/imgutils.h>
    #include <libavutil/pixfmt.h>
    #include <libswresample/swresample.h>
    #include <libavutil/opt.h>
}

#include <stdio.h>

int main()
{
    int i = 0, ret, got_output;
    AVPacket pkt;
    int framecnt=0;

    char filename_in[]="/mnt/hgfs/shareVM/welcom_to_beijing.yuv";
    char filename_out[]="/mnt/hgfs/shareVM/welcom_to_beijing.h264";
    int in_w=720,in_h=480;

    avcodec_register_all();
    AVCodecID codec_id=AV_CODEC_ID_H264;
    AVCodec *pCodec = avcodec_find_encoder(codec_id);
    if (!pCodec) {
        printf("Codec not found\n");
        return -1;
    }
    AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
    if (!pCodecCtx) {
        printf("Could not allocate video codec context\n");
        return -1;
    }
    pCodecCtx->codec_id = pCodec->id;           // 编解码器的id 根据他可以找到对应的编解码器
    pCodecCtx->bit_rate = 400000;               // 平均比特率
    pCodecCtx->width = in_w;                    // 编码宽度
    pCodecCtx->height = in_h;                   // 编码高度
    pCodecCtx->time_base = {1, 30};             //根据该参数,可以把PTS转化为实际的时间(单位为秒s)
    pCodecCtx->framerate = {30, 1};             // 帧率
    pCodecCtx->gop_size = 10;                   //每10帧插入1个I帧 编码时设置,解码时不使用
    pCodecCtx->max_b_frames = 1;                //两个非B帧之间允许出现多少个B帧数,设置0表示不使用B帧,b 帧越多,图片越小
    pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;    // 像素传输格式

    if (codec_id == AV_CODEC_ID_H264) {
        // 预设值 速度慢 编码质量高
        // 可选: ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo
        av_opt_set(pCodecCtx->priv_data, "preset", "fast", 0);
        // 在上一个选项基础上进一步优化输入。如果定义了一个tune值,它将在preset之后,其它选项之前生效
        // 可选: film、animation、grain、stillimage、psnr、ssim、fastdecode、zerolatency
        av_opt_set(pCodecCtx->priv_data, "tune", "zerolatency", 0);
        // 限制输出文件的profile。这个参数将覆盖其它所有值,此选项能保证输出profile兼容的视频流。如果使用了这个选项,将不能进行无损压缩
        // 可选: baseline, extended, main, high
        // 默认: baseline
        av_opt_set(pCodecCtx->priv_data, "profile", "baseline", 0); //
    }

    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        printf("Could not open codec\n");
        return -1;
    }

    AVFrame *pFrame = av_frame_alloc();
    if (!pFrame) {
        printf("Could not allocate video frame\n");
        return -1;
    }
    pFrame->format = pCodecCtx->pix_fmt;
    pFrame->width  = pCodecCtx->width;
    pFrame->height = pCodecCtx->height;

    ret = av_image_alloc(pFrame->data, pFrame->linesize, pCodecCtx->width, pCodecCtx->height,
                         pCodecCtx->pix_fmt, 16);
    if (ret < 0) {
        printf("Could not allocate raw picture buffer\n");
        return -1;
    }
    //Input raw data
    FILE *fp_in = fopen(filename_in, "rb");
    if (!fp_in) {
        printf("Could not open %s\n", filename_in);
        return -1;
    }
    //Output bitstream
    FILE *fp_out = fopen(filename_out, "wb");
    if (!fp_out) {
        printf("Could not open %s\n", filename_out);
        return -1;
    }

    int y_size = pCodecCtx->width * pCodecCtx->height;
    //Encode
    while (true) {
        //Read raw YUV data
        if (fread(pFrame->data[0],1,y_size,fp_in)<= 0||        // Y
            fread(pFrame->data[1],1,y_size/4,fp_in)<= 0||    // U
            fread(pFrame->data[2],1,y_size/4,fp_in)<= 0){    // V
            return -1;
        }else if(feof(fp_in)){
            break;
        }

        /* encode the image */
        av_init_packet(&pkt);
        pkt.data = NULL;    // packet data will be allocated by the encoder
        pkt.size = 0;
        ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_output);
        pFrame->pts++;
        if (ret < 0) {
            printf("Error encoding frame\n");
            return -1;
        }
        if (got_output) {
            printf("Succeed to encode frame: %5d\tsize:%5d\tgot_output:%5d\n",framecnt,pkt.size,got_output);
            framecnt++;
            fwrite(pkt.data, 1, pkt.size, fp_out);
            av_free_packet(&pkt);
        }
    }
    //Flush Encoder  编码器中剩余的视频帧输出
    for (got_output = 1; got_output; i++) {
        ret = avcodec_encode_video2(pCodecCtx, &pkt, NULL, &got_output);
        if (ret < 0) {
            printf("Error encoding frame\n");
            return -1;
        }
        if (got_output) {
            printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",pkt.size);
            fwrite(pkt.data, 1, pkt.size, fp_out);
            av_free_packet(&pkt);
        }
    }

    fclose(fp_out);
    avcodec_close(pCodecCtx);
    av_free(pCodecCtx);
    av_freep(&pFrame->data[0]);
    av_frame_free(&pFrame);

    return 0;

}

编译:


g++ main.cpp -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswresample -lswscale

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值