[MPlayer-dev-eng] small patch to set FPS on v4l2 capture devices
Jaijeet Roychowdhury
jr at berkeley.edu
Sat Aug 20 09:02:26 EEST 2016
I have made a small patch (attached) that sets a v4l2 capture device's fps if -tv fps=xxx is specified by mplayer/mencoder.
Without this patch, the capture device's fps is not set, resulting in the device (a Magewell USB Capture HDMI device, the only such device I have) sending frames at its maximum fps (60, for the Magewell). This leads to frame drops and video buffer overflows (the latter if mplayer's -fps and -ofps are set to some other value).
With the patch, it seems to work properly with, eg, the following command (which produces video buffer overflow messages without the patch):
mencoder -fps 29.97 -ofps 29.97 -tv device=/dev/video0:width=640:height=480:norm=ntsc:alsa:adevice=front.CARD=XI100DUSBHDMI,DEV=0:immediatemode=0:forceaudio:buffersize=64:audiorate=48000:amode=1:fps=29.97 -ovc x264 -x264encopts preset=veryfast:crf=22:threads=2 -oac mp3lame -lameopts fast:preset=medium -o try.avi tv://
Please consider incorporating it into the main code base. I have not tested it exhaustively, but would be glad to test further with the Magewell device if needed.
Thanks,
Jaijeet
-------------- next part --------------
diff -Naur MPlayer-1.3.0/stream/tv.c MPlayer-1.3.0-JR-setfps-patched/stream/tv.c
--- MPlayer-1.3.0/stream/tv.c 2016-02-13 09:03:23.000000000 -0800
+++ MPlayer-1.3.0-JR-setfps-patched/stream/tv.c 2016-08-19 21:27:41.489480360 -0700
@@ -420,6 +420,7 @@
static int open_tv(tvi_handle_t *tvh)
{
int i;
+ double fps;
const tvi_functions_t *funcs = tvh->functions;
static const int tv_fmt_list[] = {
IMGFMT_YV12,
@@ -512,27 +513,28 @@
funcs->control(tvh->priv, TVI_CONTROL_VID_SET_WIDTH_HEIGHT, dim);
}
/* set width */
- if (tvh->tv_param->width != -1)
- {
- if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_WIDTH, &tvh->tv_param->width) == TVI_CONTROL_TRUE)
- funcs->control(tvh->priv, TVI_CONTROL_VID_SET_WIDTH, &tvh->tv_param->width);
- else
- {
- mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnableToSetWidth, tvh->tv_param->width);
- funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &tvh->tv_param->width);
- }
+ if (tvh->tv_param->width != -1) {
+ if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_WIDTH, &tvh->tv_param->width) == TVI_CONTROL_TRUE)
+ funcs->control(tvh->priv, TVI_CONTROL_VID_SET_WIDTH, &tvh->tv_param->width);
+ else {
+ mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnableToSetWidth, tvh->tv_param->width);
+ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &tvh->tv_param->width);
+ }
}
/* set height */
- if (tvh->tv_param->height != -1)
- {
- if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_HEIGHT, &tvh->tv_param->height) == TVI_CONTROL_TRUE)
- funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HEIGHT, &tvh->tv_param->height);
- else
- {
- mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnableToSetHeight, tvh->tv_param->height);
- funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &tvh->tv_param->height);
- }
+ if (tvh->tv_param->height != -1) {
+ if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_HEIGHT, &tvh->tv_param->height) == TVI_CONTROL_TRUE)
+ funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HEIGHT, &tvh->tv_param->height);
+ else {
+ mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnableToSetHeight, tvh->tv_param->height);
+ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &tvh->tv_param->height);
+ }
+ }
+
+ /* set parm (fps) */
+ if (tvh->tv_param->fps != -1) {
+ funcs->control(tvh->priv, TVI_CONTROL_VID_SET_FPS, 0); // arg unused; getfps() within gets the framerate
}
if (funcs->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE)
diff -Naur MPlayer-1.3.0/stream/tv.h MPlayer-1.3.0-JR-setfps-patched/stream/tv.h
--- MPlayer-1.3.0/stream/tv.h 2010-09-13 11:09:29.000000000 -0700
+++ MPlayer-1.3.0-JR-setfps-patched/stream/tv.h 2016-08-19 21:48:16.457997297 -0700
@@ -200,6 +200,7 @@
#define TVI_CONTROL_VID_SET_GAIN 0x11f
#define TVI_CONTROL_VID_GET_GAIN 0x120
#define TVI_CONTROL_VID_SET_WIDTH_HEIGHT 0x121
+#define TVI_CONTROL_VID_SET_FPS 0x122
/* TUNER controls */
#define TVI_CONTROL_TUN_GET_FREQ 0x201
diff -Naur MPlayer-1.3.0/stream/tvi_v4l2.c MPlayer-1.3.0-JR-setfps-patched/stream/tvi_v4l2.c
--- MPlayer-1.3.0/stream/tvi_v4l2.c 2014-06-10 09:39:04.000000000 -0700
+++ MPlayer-1.3.0-JR-setfps-patched/stream/tvi_v4l2.c 2016-08-19 21:50:06.480901539 -0700
@@ -753,6 +753,8 @@
{
struct v4l2_control control;
struct v4l2_frequency frequency;
+ struct v4l2_streamparm parm; /* get/set parm */
+ float fps;
switch(cmd) {
case TVI_CONTROL_IS_VIDEO:
@@ -768,8 +770,25 @@
return TVI_CONTROL_TRUE;
case TVI_CONTROL_VID_GET_FPS:
*(float *)arg = getfps(priv);
- mp_msg(MSGT_TV, MSGL_V, "%s: get fps: %f\n", info.short_name,
- *(float *)arg);
+ mp_msg(MSGT_TV, MSGL_V, "%s: get fps: %f\n", info.short_name, *(float *)arg);
+ return TVI_CONTROL_TRUE;
+ case TVI_CONTROL_VID_SET_FPS:
+ fps = getfps(priv);
+ memset(&parm, 0, sizeof(parm));
+ parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ parm.parm.capture.timeperframe.numerator = 1000;
+ parm.parm.capture.timeperframe.denominator = fps * parm.parm.capture.timeperframe.numerator;
+
+ if (ioctl(priv->video_fd, VIDIOC_S_PARM, &parm) < 0) {
+ mp_msg(MSGT_TV, MSGL_ERR,"control: ioctl set fps failed: %s\n", info.short_name, strerror(errno));
+ return TVI_CONTROL_FALSE;
+ } else { // should have returned == 0
+ struct v4l2_fract *tf = &parm.parm.capture.timeperframe;
+ if (!tf->denominator || !tf->numerator)
+ mp_msg(MSGT_TV,MSGL_WARN,"control: ioctl set fps: invalid frame rate\n");
+ else
+ mp_msg(MSGT_TV,MSGL_V,"control: ioctl set fps: frame rate set to %0.3fps\n", 1.0*tf->denominator / tf->numerator);
+ }
return TVI_CONTROL_TRUE;
case TVI_CONTROL_VID_GET_BITS:
if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
More information about the MPlayer-dev-eng
mailing list