[Libav-user] Frame Rate Oddities
Noah Zigas
noahzig at gmail.com
Wed Nov 28 15:09:54 CET 2012
Hi All,
I'm new to FFmpeg programming and I'm having a strange issue with H264 file
framerates.
I'm simply trying to capture video from an NTSC camera using a Matrox
capture card. I wrote a simple application to capture 10 seconds of video
to an MP4 file. The program works, sort of. I get an MP4 file but it
plays very quickly. If I look at the details of the file the framerate is
somewhere in the thousands (it changes based on the number of frames I
capture, which is also strange).
I'm using Win7/64 with FFmpeg compiled with MinGW64. I've tried the
pre-built binaries from zeranoe with the same results.
Here's the code:
#include <mil.h>
#include <iostream>
extern "C"
{
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
using namespace std;
const unsigned long RGB_BUFFER_SIZE = 640 * 480 * 3;
MIL_ID mil_buffers[10];
unsigned char *p_raw_buffer;
SwsContext *p_sws_context;
AVFrame *p_out_frame;
AVFormatContext *p_format_context;
AVStream *p_output_stream;
static MIL_INT MFTYPE hook_handler(MIL_INT hook_type, MIL_ID event_id, void
MPTYPE *p_user_data)
{
static unsigned long count = 0;
AVPicture picture_in;
AVPacket pkt;
int got_packet_ptr;
// get frame into BGR buffer
MIL_ID current_buf;
MdigGetHookInfo(event_id, M_MODIFIED_BUFFER+M_BUFFER_ID, ¤t_buf);
MbufGetColor(current_buf, M_PACKED+M_BGR24, M_ALL_BANDS, p_raw_buffer);
// fill the input picture with the BGR data and convert it to YUV420P
avpicture_fill(&picture_in, p_raw_buffer, PIX_FMT_BGR24, 640, 480);
sws_scale(p_sws_context, picture_in.data, picture_in.linesize, 0, 480,
p_out_frame->data, p_out_frame->linesize);
av_init_packet(&pkt);
AVCodecContext *p_codec_context = p_output_stream->codec;
pkt.data = NULL;
pkt.size = 0;
p_out_frame->pts = count;
int result = avcodec_encode_video2(p_codec_context, &pkt, p_out_frame,
&got_packet_ptr);
if (result < 0)
{
cout << "Error encoding frame." << endl;
}
if (got_packet_ptr)
{
av_interleaved_write_frame(p_format_context, &pkt);
}
++count;
return M_NULL;
} // hook_handler
int
main(int argc, char *argv[])
{
// MIL setup
MIL_ID mil_app = MappAlloc(M_DEFAULT, M_NULL);
MIL_ID mil_sys = MsysAlloc(M_SYSTEM_MORPHIS, M_DEFAULT, M_DEFAULT,
M_NULL);
MIL_ID mil_dig = MdigAlloc(mil_sys, M_DEFAULT, MIL_TEXT("M_NTSC"),
M_DEFAULT, M_NULL);
for (int x = 0; x < 10; ++x)
{
MbufAllocColor(mil_sys, 3, 640, 480, M_UNSIGNED+8, M_IMAGE+M_GRAB,
&mil_buffers[x]);
}
p_raw_buffer = new unsigned char[RGB_BUFFER_SIZE];
MdigChannel(mil_dig, M_CH4);
// FFmpeg setup
av_register_all();
// get the scaling context to transform input image to YUV420P
p_sws_context = sws_getContext(640, 480, PIX_FMT_BGR24, 640, 480,
PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
// allocate the output frame
p_out_frame = avcodec_alloc_frame();
p_out_frame->format = PIX_FMT_YUV420P;
p_out_frame->width = 640;
p_out_frame->height = 480;
av_image_alloc(p_out_frame->data, p_out_frame->linesize, 640, 480,
PIX_FMT_YUV420P, 1);
p_out_frame->pts = 0;
// allocate the output format context
avformat_alloc_output_context2(&p_format_context, NULL, NULL, "test.mp4");
AVOutputFormat *p_output_format = p_format_context->oformat;
AVCodec *p_codec = avcodec_find_encoder(CODEC_ID_H264);
// format the output video stream
p_output_stream = avformat_new_stream(p_format_context, p_codec);
AVCodecContext *p_codec_context = p_output_stream->codec;
// set up the codec context
avcodec_get_context_defaults3(p_codec_context, p_codec);
p_codec_context->codec_id = CODEC_ID_H264;
p_codec_context->bit_rate = 400000;
p_codec_context->width = 640;
p_codec_context->height = 480;
p_codec_context->qmin = 10;
p_codec_context->qmax = 42;
p_codec_context->time_base.den = 30;
p_codec_context->time_base.num = 1;
p_codec_context->gop_size = 10;
p_codec_context->pix_fmt = PIX_FMT_YUV420P;
p_codec_context->ticks_per_frame = 2;
p_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
// open the codec context
avcodec_open2(p_codec_context, p_codec, NULL);
// open the io context
avio_open2(&p_format_context->pb, "test.mp4", AVIO_FLAG_WRITE, NULL,
NULL);
av_dump_format(p_format_context, 0, "test.mp4", 1);
// write the file header
avformat_write_header(p_format_context, NULL);
// process 300 frames (10 seconds of video)
cout << "Starting processing..." << endl << endl;
MdigProcess(mil_dig, mil_buffers, 9, M_SEQUENCE+M_COUNT(300), M_DEFAULT,
hook_handler, M_NULL);
cout << endl << "Processing done." << endl << "Press any key to
continue...";
// flush the (possibly) buffered frames to the output file
int got_packet_ptr;
do
{
AVPacket pkt;
pkt.data = NULL;
pkt.size = 0;
int result = avcodec_encode_video2(p_codec_context, &pkt, NULL,
&got_packet_ptr);
if (result < 0)
{
cout << "Error encoding frame." << endl;
}
if (got_packet_ptr)
{
av_interleaved_write_frame(p_format_context, &pkt);
av_free_packet(&pkt);
}
} while (got_packet_ptr);
// write the file trailer
av_write_trailer(p_format_context);
// clean up
avformat_free_context(p_format_context);
av_freep(&p_out_frame->data[0]);
av_free(p_out_frame);
sws_freeContext(p_sws_context);
delete [] p_raw_buffer;
for (int x = 0; x < 10; ++x)
{
MbufFree(mil_buffers[x]);
}
MdigFree(mil_dig);
MsysFree(mil_sys);
MappFree(mil_app);
getchar();
return 0;
} // main
Any help would be greatly appreciated.
Thanks,
Noah
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20121128/2b83aec5/attachment.html>
More information about the Libav-user
mailing list