ffmpeg视频编码及封装

#include <stdio.h>
#include <libavcodec/avcodec.h>
//#include <libavutil/time.h>
#include <libavformat/avformat.h>


static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
                   AVFormatContext *oc)
{
    int ret;
    ret = avcodec_send_frame(enc_ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending a frame for encoding\n");
        exit(1);
    }
    while (ret >= 0) {
        ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during encoding\n");
            exit(1);
        }
        //printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
        //fwrite(pkt->data, 1, pkt->size, outfile)
        ;
        //将编码后的帧写入文件
		av_interleaved_write_frame(oc, pkt);
        av_packet_unref(pkt);
    }
}

int main(int argc, char* argv[])
{
    const char *ifile = "./test/clip.yuv";
    const char *ofile = "111.ts";
    int bitrate = 5000000;
    int width = 1280;
    int height = 720;
    int fps = 30;
    int ret = -1;
    unsigned int read_size;
    int64_t start_time;
    
    AVCodec* codec;
    AVFrame *frame;
    AVPacket *pkt;
    AVCodecContext *codec_ctx;
    ///
    AVFormatContext *oc = NULL;
    
    
    FILE *input_fp = fopen(ifile, "rb");
    if (input_fp == NULL)
    {
      fprintf(stderr, "Could not to open inputfile.\n");
      return -1;
    }
    
    // output_fp = fopen("./clip2.ts", "wb");
    // if (!output_fp )
    // {
    //   fprintf(stderr, "Could not open outputfile.\n");
    //   return -1;
    // }
    
    fseek(input_fp, 0, SEEK_END);
    unsigned int infile_size = ftell(input_fp);
    unsigned int frame_cnt = infile_size / (width*height*3/2);
    printf("frame_cnt frame_cnt %3d \n", frame_cnt);

    codec = avcodec_find_encoder_by_name("libxvid");
    if (!codec) {
        fprintf(stderr,"Codec not found\n");
        return -1;
    }

    codec_ctx = avcodec_alloc_context3(codec);
    if (!codec_ctx) {
        fprintf(stderr,"Could not allocate video codec context\n");
        return -1;
    }
    
    codec_ctx->bit_rate = bitrate;
    codec_ctx->width = width;
    codec_ctx->height = height;
    codec_ctx->time_base = (AVRational){1, fps};
    codec_ctx->framerate = (AVRational){fps, 1};
    //codec_ctx->gop_size = 4;
    codec_ctx->max_b_frames = 2;
    codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;

    
    //av_opt_set(codec_ctx->priv_data, "preset", "slow", 0);
        
    ret = avcodec_open2(codec_ctx, codec, NULL);
    if (ret < 0) {
        fprintf(stderr,"Could not open codec: %s\n", av_err2str(ret));
        return -1;
    }

    /
    //2 create out context
	avformat_alloc_output_context2(&oc, 0, 0, ofile);
 
	//3 add video stream
	AVStream *st = avformat_new_stream(oc, NULL);
	st->id = 0;
	st->codecpar->codec_tag = 0;
    avcodec_parameters_from_context(st->codecpar, codec_ctx);

    av_dump_format(oc, 0, ofile, 1);

    //5 write mp4 head
	ret = avio_open(&oc->pb, ofile, AVIO_FLAG_WRITE);
	if (ret < 0)
	{
		fprintf(stderr," avio_open  failed! \n");
		getchar();
		return -1;
	}
	ret = avformat_write_header(oc, NULL);
	if (ret < 0)
	{
		fprintf(stderr," avformat_write_header  failed! \n");
		getchar();
		return -1;
	}

    /

    frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr,"Could not allocate video frame\n");
        return -1;
    }
    frame->format = codec_ctx->pix_fmt;
    frame->width  = codec_ctx->width;
    frame->height = codec_ctx->height;
	
    ret = av_frame_get_buffer(frame, 32);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate the video frame data\n");
        return -1;
    }

    pkt = av_packet_alloc();
    if (!pkt) {
        return -1;
    }
    
    //start_time = av_gettime_relative();
    fseek(input_fp, 0, SEEK_SET);
    // Loop over all frames in inputfile
    int i, j;
    for (i = 0; i < frame_cnt; i++)
    {
        // Make sure the frame data is writable
        int rc = av_frame_make_writable(frame);
        if (rc < 0)
        {
          fprintf(stderr, "av_frame_make_writable() error.\n");
          return -1;
        }

        // Read data for Y into frame buffer
        for (j = 0; j < codec_ctx->height; j++)
        {
          read_size = fread(&frame->data[0][0] + j * frame->linesize[0], codec_ctx->width, 1, input_fp);
          if (read_size != 1) {
            fprintf(stderr, "Failed to read Y. read_size=%u.\n", read_size);
            return -1;
          }
        }
        // Read data for U into frame buffer
        for (j = 0; j < codec_ctx->height / 2; j++)
        {
          read_size = fread(&frame->data[1][0] + j * frame->linesize[1], codec_ctx->width / 2, 1, input_fp);
          if (read_size != 1) {
            fprintf(stderr, "Failed to read U. read_size=%u.\n", read_size);
            return -1;
          }
        }
        // Read data for V into frame buffer
        for (j = 0; j < codec_ctx->height / 2; j++)
        {
          read_size = fread(&frame->data[2][0] + j * frame->linesize[2], codec_ctx->width / 2, 1, input_fp);
          if (read_size != 1)
          {
            fprintf(stderr, "Failed to read V. read_size=%u.\n", read_size);
            return -1;
          }
        }

        frame->pts = i * 90000 / fps;
        
        // Encode frame
        encode(codec_ctx, frame, pkt, oc);
        //print_report(0, start_time, av_gettime_relative(), i);
    }
    
    //sleep(2);
    encode(codec_ctx, NULL, pkt, oc);
    //print_report(0, start_time, av_gettime_relative(), frame_cnt);

    //写文件尾
	av_write_trailer(oc);
 
	//关闭视频输出IO
	avio_close(oc->pb);
 
	//清理封装输出上下文
	avformat_free_context(oc);

    //fclose(output_fp);
    fclose(input_fp);
    //清理编码器上下文
    avcodec_free_context(&codec_ctx);
    av_frame_free(&frame);
    av_packet_free(&pkt);
    
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值