ffmpeg--编码延迟问题(编码后avcodec_encode_video2要延迟几帧才能got_packet)

ffmpeg 编码延迟问题(编码后avcodec_encode_video2要延迟几帧才能got_packet 但要求是要实时编码,即立刻得到pkt)

// 	gcc temp.c -o 2  -I/root/ffmpeg/include/ -L/root/ffmpeg/lib -lavcodec -lavformat -lavdevice -lavutil -lswscale  -lswresample	//没有包含x264库
// 	gcc temp.c -o 2  -I/home/aston/ffmpeg-all/ffmpeg/include/ -L/home/aston/ffmpeg-all/ffmpeg/lib -lavcodec -lavformat -lavdevice -lavutil -lswscale  -lswresample	
//	./2
/** 
 * @file 
 * libavcodec API use example. 
 * 
 * Note that libavcodec only handles codecs (mpeg, mpeg4, etc...), 
 * not file formats (avi, vob, mp4, mov, mkv, mxf, flv, mpegts, mpegps, etc...). See library 'libavformat' for the 
 * format handling 
 */  
  
#include <stdio.h>  
#include <math.h>  
  

#include <libavutil/opt.h>       
#include <libavcodec/avcodec.h>  
#include <libavutil/imgutils.h>  
 

static void video_encode_example(const char *filename, int codec_id)  
{  
    AVCodec *codec;  
    
    int i, ret, x, y, got_output;  
    FILE *f;  
    AVFrame *picture;  
    AVPacket pkt;  
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };  
  
    printf("Encode video file %s\n", filename);  
  
printf("codec_id=%d\n",codec_id);
	codec = avcodec_find_encoder(codec_id);  
    if (!codec) {  fprintf(stderr, "codec not found\n");   exit(1);  } 

  
	AVCodecContext *c = avcodec_alloc_context3(codec);  


    c->bit_rate = 400000;  

    c->width = 800;		//352;  
    c->height = 500;	//288;  
    c->time_base.den = 1;  
    c->time_base.num = 25;  
    c->gop_size = 10; // 一个序列GOP包含几帧
    c->max_b_frames=1;  
    c->pix_fmt = AV_PIX_FMT_YUV420P;

	
    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);  }  
  
    picture = av_frame_alloc();  
    if (!picture) {  fprintf(stderr, "Could not allocate video frame\n");   exit(1);  }  
	
    picture->format = c->pix_fmt;  
    picture->width  = c->width;  
    picture->height = c->height;  
  
    /* 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 */  
    ret = av_image_alloc(picture->data, picture->linesize, c->width, c->height,  c->pix_fmt, 32);  
    if (ret < 0) {  fprintf(stderr, "could not alloc raw picture buffer\n");   exit(1);  }  
  
    static int delayedFrame = 0;  
    /* encode 1 second of video */  
    for(i=0;i<25;i++) {  
        av_init_packet(&pkt);  
        pkt.data = NULL;    // packet data will be allocated by the encoder  
        pkt.size = 0;  
  
        fflush(stdout);  
        /* prepare a dummy image */  
        /* Y */  
        for(y=0;y<c->height;y++) {  
            for(x=0;x<c->width;x++) {  
                picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;  
            }  
        }  
  
        /* Cb and Cr */  
        for(y=0;y<c->height/2;y++) {  
            for(x=0;x<c->width/2;x++) {  
                picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;  
                picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;  
            }  
        }  
  
        picture->pts = i;  
  
        printf("encoding frame %3d----", i);  
        /* encode the image */  
        ret = avcodec_encode_video2(c, &pkt, picture, &got_output);  
        if (ret < 0) {  fprintf(stderr, "error encoding frame\n");   exit(1);  }  
  
        if (got_output) {  
            printf("output frame %3d (size=%5d)\n", i-delayedFrame, pkt.size);  
            fwrite(pkt.data, 1, pkt.size, f);  
            av_free_packet(&pkt);  
        }  
        else {  
            delayedFrame++;  
            printf("no output frame\n");  
        }  
    }  
  
    /* get the delayed frames */  
    for (got_output = 1; got_output; i++) {  
        fflush(stdout);  
  
        ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);  
        if (ret < 0) {  fprintf(stderr, "error encoding frame\n");   exit(1);  }  
  
        if (got_output) {  
            printf("output delayed frame %3d (size=%5d)\n", i-delayedFrame, pkt.size);  
            fwrite(pkt.data, 1, pkt.size, f);  
            av_free_packet(&pkt);  
        }  
    }  
  
    /* add sequence end code to have a real mpeg file */  
    fwrite(endcode, 1, sizeof(endcode), f);  
    fclose(f);  
  
    avcodec_close(c);  
    av_free(c);  
    av_freep(&picture->data[0]);  
    av_free(picture);  
    printf("\n");  
}  
  
int main(int argc, char **argv)  
{  
    /* register all the codecs */  
    avcodec_register_all(); 
	avdevice_register_all();
	av_register_all();
  
    video_encode_example("test.H264", AV_CODEC_ID_H264);  
  
    system("pause");  
  
    return 0;  
}
avcodec_register_all		注册ffmpeg提供的所有编解码器
注册x264编码器时,有个条件判断CONFIG_LIBX264_ENCODER,我们在ffmpeg工程中查找,发现在它Config.mak中,这个文件是在咱们编译ffmpeg工程时由./configure根据你的选项自动生成的,还记得我们编译时用了--enable-libx264选项吗(我们要使用X264编码器,当然要指定该选项)?所以有CONFIG_LIBX264_ENCODER=yes,因此这里可以成功注册x264编码器,如果当初没有指定该选项,编码器是不会注册进去的。

降延迟–改参数

// 新增语句,设置为编码延迟  
av_opt_set(c->priv_data, "preset", "superfast", 0);  

// 实时编码关键看这句,上面那条无所谓  
av_opt_set(c->priv_data, "tune", "zerolatency", 0);

发布了81 篇原创文章 · 获赞 1 · 访问量 2923

猜你喜欢

转载自blog.csdn.net/qq_42024067/article/details/103969575