我正在使用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");`
答案 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。