Video plays too fast

For the developers that use FFmpeg in their software.
Post Reply
PavelRem
Posts: 1
Joined: Mon Jul 01, 2019 7:17 pm

Video plays too fast

Post by PavelRem » Mon Jul 01, 2019 7:31 pm

Hi, I need advice.
I use gdigrab to capture frames of the desktop screen, then I encode them using the "mpeg1video" codec. And then I write the encoded frames to a file. Everything works fine, but the created video plays too fast. I can not understand why this is happening and how to fix it.
Help me please.

Code: Select all

#include "windows.h"
#include <math.h>
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"


static AVFormatContext		*pFormatCtx;
static AVCodec				*pCodec, *codec;
static AVDictionary			*options = NULL;
static AVInputFormat		*ifmt;
static AVFrame				*pFrame, *frameYUV;
static AVPacket				*packet, packet_w;
static struct SwsContext	*img_convert_ctx;
static FILE					*file;
static uint8_t endcode[] =	{ 0, 0, 1, 0xb7 };
static AVCodecContext		*pCodecCtx, *codec_context = NULL;
static int					i, got_output = 1, got_picture, x, y, counter;


static void innit(char* file_name, int fps, int bitate, int width, int height) {
	av_register_all();
	avformat_network_init();
	avdevice_register_all();
	avcodec_register_all();

	// gdigrab innit
	ifmt = av_find_input_format("gdigrab");
	avformat_open_input(&pFormatCtx, "desktop", ifmt, &options);
	avformat_find_stream_info(pFormatCtx, NULL);
	pCodecCtx = pFormatCtx->streams[0]->codec;
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	avcodec_open2(pCodecCtx, pCodec, NULL);		
	pFrame = av_frame_alloc();
	packet = (AVPacket *)av_malloc(sizeof(AVPacket));
	img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
		pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

	//mpeg1 codec innit
	codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO);
	codec_context = avcodec_alloc_context3(codec);
	codec_context->bit_rate = bitate;
	codec_context->width = width;
	codec_context->height = height;
	codec_context->time_base = { 1, 25 };
	codec_context->gop_size = 0;
	codec_context->max_b_frames = 1;
	codec_context->pix_fmt = AV_PIX_FMT_YUV420P;
	avcodec_open2(codec_context, codec, NULL);
	file = fopen(file_name, "wb");
	frameYUV = av_frame_alloc(); 
	frameYUV->format = codec_context->pix_fmt;
	frameYUV->width = codec_context->width;
	frameYUV->height = codec_context->height;
	av_image_alloc(frameYUV->data, frameYUV->linesize, codec_context->width, codec_context->height,
		codec_context->pix_fmt, 32);
	counter = 0;
}
static AVFrame* get_frame() {

	av_read_frame(pFormatCtx, packet);
	avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);

	sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data,
		pFrame->linesize, 0, pCodecCtx->height, frameYUV->data, frameYUV->linesize);

	frameYUV->pts = counter++;
	return frameYUV;
}
static void encode_frame(AVFrame* frame) {
	av_init_packet(&packet_w);
	packet_w.data = NULL;
	packet_w.size = 0;

	avcodec_encode_video2(codec_context, &packet_w, frame, &got_output);

	if (got_output) {
		fwrite(packet_w.data, 1, packet_w.size, file);
		av_free_packet(&packet_w);
	}
}
static void complete_encode() {
	for (got_output = 1; got_output;) {
		avcodec_encode_video2(codec_context, &packet_w, NULL, &got_output);
		if (got_output) {
			fwrite(packet_w.data, 1, packet_w.size, file);
			av_free_packet(&packet_w);
		}
	}

	fwrite(endcode, 1, sizeof(endcode), file);
	fclose(file);
	avcodec_close(codec_context);
	av_free(codec_context);
	av_freep(&frameYUV->data[0]);
	av_frame_free(&frameYUV);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);
}


int main()
{
	innit("E:/test.mpg", 25, 90000000, 1366, 768);
	for (size_t i = 0; i < 480; i++)
		encode_frame(get_frame());
	complete_encode();
}

Post Reply
'