FFmpeg 编解码

编码涉及结构体API

1.添加头文件

    ///AVCodec 编码器结构体

    ///AVCodecContext 编码器上下文

    ///AVFrame  解码后的帧

    ///结构体的分配与释放

    //av_frame_alloc()

    //av_frame_free(AVFrame **frame)

    //    avcodec_alloc_context3(<#const AVCodec *codec#>)

    //    avcodec_free_context(<#AVCodecContext **avctx#>)

编码步骤

    //1.输入参数

    //2.查找编码器

    //3.创建编码器上下文

    //4.设置编码器参数

    //5.编码器与编码器上下文绑定到一起

    //6.创建输出文件

    //7.创建AVFRAME

    //8.创建

    //9.生成视频内容

    //10.编码

int encode_action(AVCodecContext *codec_context,AVFrame *frame,AVPacket *packet, FILE *file) {
    int ret = -1;
    ret = avcodec_send_frame(codec_context, frame);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_send_frame error = %s\n",av_err2str(ret));
        goto __ERROR;
    }
    
    while (ret >= 0) {
        ret = avcodec_receive_packet(codec_context, packet);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return 0;
        } else if (ret < 0) {
            return -1;
        }
        fwrite(packet->data, 1, packet->size, file);
        av_packet_unref(packet);
    }
__ERROR:
    
    return 0;
}
void media_codec() {
    ///AVCodec 编码器结构体
    ///AVCodecContext 编码器上下文
    ///AVFrame  解码后的帧
    ///结构体的分配与释放
    //av_frame_alloc()
    //av_frame_free(AVFrame **frame)
    //    avcodec_alloc_context3(<#const AVCodec *codec#>)
    //    avcodec_free_context(<#AVCodecContext **avctx#>)
    
    //解码步骤
    //    1.查找解码器
    //    avcodec_find_decoder(<#enum AVCodecID id#>)
//    2.打开解码器
//   avcodec_open2(<#AVCodecContext *avctx#>, <#const AVCodec *codec#>, <#AVDictionary **options#>)
    //3.解码
   // avcodec_decode_subtitle2(<#AVCodecContext *avctx#>, <#AVSubtitle *sub#>, <#int *got_sub_ptr#>, <#const AVPacket *avpkt#>)
    
    av_log_set_level(AV_LOG_DEBUG);
    //1.输入参数
    //2.查找编码器
    //3.创建编码器上下文
    //4.设置编码器参数
    //5.编码器与编码器上下文绑定到一起
    //6.创建输出文件
    //7.创建AVFRAME
    //8.创建AVPacket
    //9.生成视频内容
    //10.编码
    
    //1.输入参数
    char *dst = "/Users/king/Desktop/ffmpeg/audio/codec_video.h264";
    char *codecname = "libx264";
    //2.查找编码器
//    avcodec_find_encoder(<#enum AVCodecID id#>)
//   c
    const AVCodec *codec = NULL;
    codec = avcodec_find_encoder(AV_CODEC_ID_H264);
//    codec = avcodec_find_encoder_by_name(codecname);
    if (codec == NULL) {
        av_log(NULL, AV_LOG_ERROR, "cant find codec\n");
        goto __ERROR;
    }
    //3.创建编码器上下文
    AVCodecContext *codec_context = NULL;
    codec_context = avcodec_alloc_context3(codec);
    if (codec_context == NULL) {
        av_log(NULL, AV_LOG_ERROR, "cant find codec_context\n");
        goto __ERROR;
    }
    codec_context->width = 640;
    codec_context->height = 480;
    codec_context->bit_rate = 500000;
    codec_context->time_base = (AVRational){1,25};//时间帧
    codec_context->framerate = (AVRational){25,1};//帧率
    codec_context->gop_size = 10;// 一组帧大小
    codec_context->max_b_frames = 1;//B帧数量 B帧数量一般不超过三帧 B帧过多会影响执行效率 直播议案不会要B帧
    codec_context->pix_fmt = AV_PIX_FMT_YUV420P; //视频格式
    if (codec->id == AV_CODEC_ID_H264) {
        av_opt_set(codec_context->priv_data, "preset", "slow", 0);
    }
    //5.编码器与编码器上下文绑定到一起
    int ret = -1;
    ret = avcodec_open2(codec_context, codec, NULL);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_open2 error = %s\n",av_err2str(ret));
        goto __ERROR;
    }
    //6.创建输出文件
    FILE *file = NULL;
    file = fopen(dst, "wb");
    if(!file) {
        av_log(NULL, AV_LOG_ERROR, "file  error\n");
        goto __ERROR;
    }
    //7.创建AVFRAME
    AVFrame *frame = av_frame_alloc();
    if(!frame) {
        av_log(NULL, AV_LOG_ERROR, "frame  error\n");
        goto __ERROR;
    }
    frame->width = codec_context->width;
    frame->height = codec_context->height;
    frame->format = codec_context->pix_fmt;
    ret = av_frame_get_buffer(frame, 0);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "av_frame_get_buffer error = %s\n",av_err2str(ret));
        goto __ERROR;
    }

    //8.创建AVPacket
    AVPacket *packet = NULL;
    packet = av_packet_alloc();
    if(!packet) {
        av_log(NULL, AV_LOG_ERROR, "packet  error\n");
        goto __ERROR;
    }
    //9.生成视频内容
    for (int i = 0; i < 25 * 10; i++) {
        /// 确保frame中的data'有效
       ret = av_frame_make_writable(frame);
        if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR, "av_frame_make_writable  error\n");
            goto __ERROR;
        }
        /// Y分量
        for (int y = 0; y < codec_context->height; y++) {
            for (int k = 0; k < codec_context->width; k++) {
                frame->data[0][y *frame->linesize[0] + k] = k + y + i * 3;
            }
        }
        /// UV分量
        for (int y = 0; y < codec_context->height/2; y++) {
            for (int k = 0; k < codec_context->width/2; k++) {
                frame->data[1][y * frame->linesize[1] + k] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + k] = 64 + y + i * 5;
            }
        }
        frame->pts = i;
        //10.编码
        ret = encode_action(codec_context, frame, packet,file);
        if (ret == -1) {
            goto __ERROR;
        }
    }
    ret = encode_action(codec_context, frame, packet,file);
__ERROR:
    if (codec_context) {
        avcodec_close(codec_context);
        avcodec_free_context(&codec_context);
    }
    if(frame) {
        av_frame_free(&frame);
    }
    if (packet) {
        av_packet_free(&packet);
    }
    if(file) {
        fclose(file);
    }
}

你可能感兴趣的:(ffmpeg)