[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, &current_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