增加视频FFMPEG C ++的持续时间

时间:2015-04-09 09:48:54

标签: c ffmpeg video-encoding

我正在使用FFmpeg样本中的代码,该代码将图片编码为视频。我想做的就是给它一系列图片,它给了我一个视频,每张图片花了一秒钟。下面的代码只是从我的文件系统中取出一张图片&从中创建视频

AVCodec *codec;
AVCodecContext *c = NULL;
int i, ret, x, y, got_output;
FILE *f;

AVPacket pkt;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };

printf("Encode video file %s\n", filename);

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

c = avcodec_alloc_context3(codec);
if (!c)
{
    fprintf(stderr, "Could not allocate video codec context\n");
    exit(1);
}

/* put sample parameters */
c->bit_rate = 400000;
/* resolution must be a multiple of two */
c->width = 200;
c->height = 200;
/* frames per second */
AVRational rational;
rational.num = 1;
rational.den = 25;
c->time_base = rational;
/* emit one intra frame every ten frames
* check frame pict_type before passing frame
* to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
* then gop_size is ignored and the output of encoder
* will always be I frame irrespective to gop_size
*/
c->gop_size = 10;
c->max_b_frames = 1;
c->pix_fmt = AV_PIX_FMT_YUV420P;

if (codec_id == AV_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);
}

fopen_s(&f, filename, "wb");
if (!f)
{
    fprintf(stderr, "Could not open %s\n", filename);
    exit(1);
}
AVFrame *frame = OpenImage("..\\..\\..\\..\\..\\..\\1.jpg");
//frame = av_frame_alloc();
if (!frame)
{
    fprintf(stderr, "Could not allocate video frame\n");
    exit(1);
}

frame->format = c->pix_fmt;
frame->width = c->width;
frame->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 */

int screenHeight = 200;
int screenWidth = 200;
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);



    frame->pts = i;

    /* encode the image */
    ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
    if (ret < 0)
    {
        fprintf(stderr, "Error encoding frame\n");
        exit(1);
    }

    if (got_output)
    {
        printf("Write frame %3d (size=%5d)\n", i, pkt.size);
        fwrite(pkt.data, 1, pkt.size, f);
        av_free_packet(&pkt);
    }
}

/* 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("Write frame %3d (size=%5d)\n", i, 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(&frame->data[0]);
av_frame_free(&frame);
printf("\n");`

2 个答案:

答案 0 :(得分:1)

您正在尝试对h264视频进行编码,然后将编码数据按原样写入文件。我想你要做的是写一个annexb h264文件。寻找使用libavformat编写文件,并选择一个名为“h264”的文件(基本上是一个annexb编写器)。有关多路复用的更多文档,请参阅此link

好的,现在你的问题:1 fps。我不确定它是附件中的有效值,但无论如何。请参阅ffmpeg的libavcodec / libx264.c中的以下代码:

x4->params.i_fps_num = avctx->time_base.den;
x4->params.i_fps_den = avctx->time_base.num * avctx->ticks_per_frame;

由于annexb只是按原样获取编解码器参数,在这种特殊情况下,更改AVCodecContext.time_base将足以指示您所需的帧速率。但是,通常,容器将指定时间戳和帧速率,并且您希望在使用libavformat编写的AVPacket的pts / dts字段中设置适当的时间戳。换句话说,AVCodecContext.time_base仅适用于附件b,AVPacket。pts / dts AV_TIME_BASE单位是容器格式,如mp4或mkv。

答案 1 :(得分:0)

在代码的这一部分

/* frames per second */
AVRational rational;
rational.num = 1;
rational.den = 25;
c->time_base = rational;

您将时基设置为25FPS(每秒帧数),您只需将其更改为所需的FPS。

更多信息:AVCodecContext::time_base