使用FFMpeg中的sws_scale函数进行RGB24转YUV数据编码

//功能:将一张BMP位图作为数据源,利用FFMpeg编码出一个MPG的视频文件


#include
extern "C"
{
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libswscale/swscale.h"
}


#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096


/*
 * Video encoding example
 */
static void video_encode_example(const char *filename, int codec_id)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int i = 0;
    int out_size = 0;
int outbuf_size = 0;
int inbuf_size = 0;


    FILE *f, *InputFileHead;
    AVFrame *picture;
    uint8_t *outbuf, *inbuf;
    int had_output=0;


int index = 0;


    printf("Video encoding\n");


    /* find the mpeg1 video encoder */
    codec = avcodec_find_encoder((CodecID)codec_id);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }


    c = avcodec_alloc_context3(codec);
    picture= avcodec_alloc_frame(); //这里分配了帧



    /* put sample parameters */
    c->bit_rate = 400000*2;
    /* resolution must be a multiple of two */
    c->width = 640;//1920;//352;
    c->height = 480;//1080;//288;
    /* frames per second */
    c->time_base.num =1; //= (AVRational){1,25};
c->time_base.den = 24;
    c->gop_size = 10; /* emit one intra frame every ten frames */
    c->max_b_frames=1;
    c->pix_fmt = PIX_FMT_YUV420P;


//下面的参数影响着编码出视频的质量,没有这两个参数视频会有些模糊的马赛克,加入这两个参数值就没有了
//Q值最小值
c->qmin=1;
//Q值最大值.
c->qmax=5;


    if(codec_id == CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);


    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }


    f = fopen(filename, "wb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }


//编码一张位图图像
InputFileHead = fopen("C:\\a.bmp","r"); //注意:这里的位图文件路径设置成你的文件,同时注意位图文件的宽高也作同样的修改

    /* alloc image and output buffer */
    outbuf_size = 100000 + 12 * c->width * c->height;
    outbuf = (uint8_t *)malloc(outbuf_size);


//分配内存大小
inbuf_size = c->width * c->height * 3;
inbuf = (uint8_t *)malloc(inbuf_size);


    /* the image can be allocated by any means and av_image_alloc() is
     * just the most convenient way if av_malloc() is to be used */
    av_image_alloc(picture->data, picture->linesize,
                   c->width, c->height, c->pix_fmt, 1);


//----------------------------------------------------------------------------------------------
//这里用来加载一张图片来进行编码
fseek(InputFileHead, 54, SEEK_SET);
fread(inbuf, 1, inbuf_size, InputFileHead);

struct SwsContext *sws;
//下面的位图转完是倒立的
uint8_t *rgb_src[3]= {inbuf, NULL, NULL};
int rgb_stride[3]={3*c->width, 0, 0};

sws= sws_getContext(c->width, c->height, PIX_FMT_RGB24, c->width, c->height, PIX_FMT_YUV420P, 2, NULL, NULL, NULL);
sws_scale(sws, rgb_src, rgb_stride, 0, c->height, picture->data, picture->linesize);


//----------------------------------------------------------------------------------------------


    /* encode 1 second of video */

while(i<350/*feof(InputFile)*/)
{
        fflush(stdout);
  

        /* encode the image */
        out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
        had_output |= out_size;
        printf("encoding frame %3d (size=%5d)\n", i++, out_size);
        fwrite(outbuf, 1, out_size, f);
    }



    /* get the delayed frames */
    for(; out_size || !had_output; i++) {
        fflush(stdout);


        out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
        had_output |= out_size;
        printf("write frame %3d (size=%5d)\n", i, out_size);
        fwrite(outbuf, 1, out_size, f);
    }


    /* add sequence end code to have a real mpeg file */
    outbuf[0] = 0x00;
    outbuf[1] = 0x00;
    outbuf[2] = 0x01;
    outbuf[3] = 0xb7;
    fwrite(outbuf, 1, 4, f);
    fclose(f);
    free(outbuf);


    avcodec_close(c);
    av_free(c);
    //av_free(picture->data[0]);
    av_free(picture);
    printf("\n");
}


int main(int argc, char **argv)
{
    /* register all the codecs */
    avcodec_register_all();
  
    video_encode_example("D:\\tmp.mpg", CODEC_ID_MPEG1VIDEO);

    return 0;

}


要源码的留下邮箱

你可能感兴趣的:(FFMpeg学习)