Hi All,<div><br></div><div>I'm new to FFmpeg programming and I'm having a strange issue with H264 file framerates.</div><div><br></div><div>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).</div>
<div><br></div><div>I'm using Win7/64 with FFmpeg compiled with MinGW64. I've tried the pre-built binaries from zeranoe with the same results.</div><div><br></div><div>Here's the code:</div><div><br></div><div>
<div>#include <mil.h></div><div>#include <iostream></div><div>extern "C"</div><div>{</div><div> #include <libavformat/avformat.h></div><div> #include <libswscale/swscale.h></div><div> #include <libavutil/imgutils.h></div>
<div>}</div><div><br></div><div>using namespace std;</div><div><br></div><div>const unsigned long RGB_BUFFER_SIZE = 640 * 480 * 3;</div><div><br></div><div>MIL_ID mil_buffers[10];</div><div>unsigned char *p_raw_buffer;</div>
<div>SwsContext *p_sws_context;</div><div>AVFrame *p_out_frame;</div><div>AVFormatContext *p_format_context;</div><div>AVStream *p_output_stream;</div><div><br></div><div>static MIL_INT MFTYPE hook_handler(MIL_INT hook_type, MIL_ID event_id, void MPTYPE *p_user_data)</div>
<div>{</div><div> static unsigned long count = 0;</div><div><br></div><div> AVPicture picture_in;</div><div> AVPacket pkt;</div><div> int got_packet_ptr;</div><div><br></div><div> // get frame into BGR buffer</div>
<div> MIL_ID current_buf;</div><div> MdigGetHookInfo(event_id, M_MODIFIED_BUFFER+M_BUFFER_ID, ¤t_buf);</div><div> MbufGetColor(current_buf, M_PACKED+M_BGR24, M_ALL_BANDS, p_raw_buffer);</div><div><br></div><div>
// fill the input picture with the BGR data and convert it to YUV420P</div><div> avpicture_fill(&picture_in, p_raw_buffer, PIX_FMT_BGR24, 640, 480);</div><div> sws_scale(p_sws_context, picture_in.data, picture_in.linesize, 0, 480, p_out_frame->data, p_out_frame->linesize);</div>
<div><br></div><div> av_init_packet(&pkt);</div><div> AVCodecContext *p_codec_context = p_output_stream->codec;</div><div> pkt.data = NULL;</div><div> pkt.size = 0;</div><div> p_out_frame->pts = count;</div>
<div> int result = avcodec_encode_video2(p_codec_context, &pkt, p_out_frame, &got_packet_ptr);</div><div> if (result < 0)</div><div> {</div><div> cout << "Error encoding frame." << endl;</div>
<div> }</div><div> if (got_packet_ptr)</div><div> {</div><div> av_interleaved_write_frame(p_format_context, &pkt);</div><div> }</div><div><br></div><div> ++count;</div><div><br></div><div> return M_NULL;</div>
<div>} // hook_handler</div><div><br></div><div>int</div><div>main(int argc, char *argv[])</div><div>{</div><div> // MIL setup</div><div> MIL_ID mil_app = MappAlloc(M_DEFAULT, M_NULL);</div><div> MIL_ID mil_sys = MsysAlloc(M_SYSTEM_MORPHIS, M_DEFAULT, M_DEFAULT, M_NULL);</div>
<div> MIL_ID mil_dig = MdigAlloc(mil_sys, M_DEFAULT, MIL_TEXT("M_NTSC"), M_DEFAULT, M_NULL);</div><div> for (int x = 0; x < 10; ++x)</div><div> {</div><div> MbufAllocColor(mil_sys, 3, 640, 480, M_UNSIGNED+8, M_IMAGE+M_GRAB, &mil_buffers[x]);</div>
<div> }</div><div> p_raw_buffer = new unsigned char[RGB_BUFFER_SIZE];</div><div> MdigChannel(mil_dig, M_CH4);</div><div><br></div><div> // FFmpeg setup</div><div> av_register_all();</div><div><br></div><div> // get the scaling context to transform input image to YUV420P</div>
<div> p_sws_context = sws_getContext(640, 480, PIX_FMT_BGR24, 640, 480, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);</div><div><br></div><div> // allocate the output frame</div><div> p_out_frame = avcodec_alloc_frame();</div>
<div> p_out_frame->format = PIX_FMT_YUV420P;</div><div> p_out_frame->width = 640;</div><div> p_out_frame->height = 480;</div><div> av_image_alloc(p_out_frame->data, p_out_frame->linesize, 640, 480, PIX_FMT_YUV420P, 1);</div>
<div> p_out_frame->pts = 0;</div><div> </div><div> // allocate the output format context</div><div> avformat_alloc_output_context2(&p_format_context, NULL, NULL, "test.mp4");</div><div> </div><div> AVOutputFormat *p_output_format = p_format_context->oformat;</div>
<div><br></div><div> AVCodec *p_codec = avcodec_find_encoder(CODEC_ID_H264);</div><div><br></div><div> // format the output video stream</div><div> p_output_stream = avformat_new_stream(p_format_context, p_codec);</div>
<div><br></div><div> AVCodecContext *p_codec_context = p_output_stream->codec;</div><div><br></div><div> // set up the codec context</div><div> avcodec_get_context_defaults3(p_codec_context, p_codec);</div><div> p_codec_context->codec_id = CODEC_ID_H264;</div>
<div> p_codec_context->bit_rate = 400000;</div><div> p_codec_context->width = 640;</div><div> p_codec_context->height = 480;</div><div> p_codec_context->qmin = 10;</div><div> p_codec_context->qmax = 42;</div>
<div> p_codec_context->time_base.den = 30;</div><div> p_codec_context->time_base.num = 1;</div><div> p_codec_context->gop_size = 10;</div><div> p_codec_context->pix_fmt = PIX_FMT_YUV420P;</div><div> p_codec_context->ticks_per_frame = 2;</div>
<div> p_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;</div><div><br></div><div> // open the codec context</div><div> avcodec_open2(p_codec_context, p_codec, NULL);</div><div><br></div><div> // open the io context</div>
<div> avio_open2(&p_format_context->pb, "test.mp4", AVIO_FLAG_WRITE, NULL, NULL);</div><div><br></div><div> av_dump_format(p_format_context, 0, "test.mp4", 1);</div><div><br></div><div> // write the file header</div>
<div> avformat_write_header(p_format_context, NULL);</div><div><br></div><div> // process 300 frames (10 seconds of video)</div><div> cout << "Starting processing..." << endl << endl; </div>
<div> MdigProcess(mil_dig, mil_buffers, 9, M_SEQUENCE+M_COUNT(300), M_DEFAULT, hook_handler, M_NULL);</div><div> cout << endl << "Processing done." << endl << "Press any key to continue...";</div>
<div><br></div><div> // flush the (possibly) buffered frames to the output file</div><div> int got_packet_ptr;</div><div> do</div><div> {</div><div> AVPacket pkt;</div><div> pkt.data = NULL;</div><div> pkt.size = 0;</div>
<div> int result = avcodec_encode_video2(p_codec_context, &pkt, NULL, &got_packet_ptr);</div><div> if (result < 0)</div><div> {</div><div> cout << "Error encoding frame." << endl;</div>
<div> }</div><div> if (got_packet_ptr)</div><div> {</div><div> av_interleaved_write_frame(p_format_context, &pkt);</div><div> av_free_packet(&pkt);</div><div> }</div><div> } while (got_packet_ptr);</div>
<div><br></div><div> // write the file trailer</div><div> av_write_trailer(p_format_context);</div><div><br></div><div> // clean up</div><div> avformat_free_context(p_format_context);</div><div> av_freep(&p_out_frame->data[0]);</div>
<div> av_free(p_out_frame);</div><div> sws_freeContext(p_sws_context);</div><div><br></div><div> delete [] p_raw_buffer;</div><div> for (int x = 0; x < 10; ++x)</div><div> {</div><div> MbufFree(mil_buffers[x]);</div>
<div> }</div><div> MdigFree(mil_dig);</div><div> MsysFree(mil_sys);</div><div> MappFree(mil_app);</div><div><br></div><div> getchar();</div><div> return 0;</div><div>} // main</div></div><div><br></div><div>Any help would be greatly appreciated.</div>
<div><br></div><div>Thanks,</div><div>Noah</div><div><br></div>