Re: V4l2 :: Debugging an issue with cx8800 card. | |
| [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] | |
On Thu, 2008-09-04 at 15:14 -0700, B. Bogart wrote: > Hello all, > > This issue has been lagging for years and I wanted to get some expert > advice on debugging it. It seems I'm the only one with a cx8800 card > that is having problems so I hope to take the challenge up and propose a > solution to the maintainer. > > So the software I'm using is GEM. It has v4l2 support, and works fine > with my bt848 card. Problem is I can't get things working properly with > my cx8800 cards. > > First HW info: > > lspci reports my tuner as: > > 00:0d.0 Multimedia video controller: Conexant CX23880/1/2/3 PCI Video > and Audio Decoder (rev 05) > > The card is branded as a Leadtek Winfast 2000XP Expert. > > I'm sure the problem is with the v4l2 implementation in Gem as running > the following command gives me perfect video on this card at 640x480: > > mplayer tv:// -tv driver=v4l2:device=/dev/video0:input=1:norm=NTSC-M > > (the output follows this message). > > So the card is capable of 640x480. > > If I run Gem on this card as 320x240 all works fine. (pictured in > attachment 320x240.png) > > As soon as I change the resolution to 640x480 I get the following errors > repeated: > > VIDIOCMCAPTURE1: Invalid argument > VIDIOCMCAPTURE2: Invalid argument > > And the image appears as in attachment 640x480.png > > What should my steps for debugging be? > > Is there dead-simple v4l2 example source (including output so I can > confirm its working) I can test with and compare with Gem sources? I am not a V4L2 app programmer. However, I have attached a program I wrote a while ago to exercise the cx18 driver and HVR-1600 as MythTV would opening an ivtv/cx18 based card. The cx88 probably won't support the MPEG ioctls but I think the program is a pretty simple example of how to set up a v4l2 device and capture data. You might want to look at the set_picture_size() call. The V4L2 API document can be found at linuxtv.org, if you need further documentation on the ioctl()s. Regards, Andy > Any advice appreciated. > > B. Bogart > > > -- > Here is the mplayer output: > > MPlayer dev-SVN-r26940 > CPU: AMD Athlon(tm) 64 Processor 3200+ (Family: 15, Model: 47, Stepping: 0) > CPUflags: MMX: 1 MMX2: 1 3DNow: 1 3DNow2: 1 SSE: 1 SSE2: 1 > Compiled with runtime CPU detection. > Can't open joystick device /dev/input/js0: No such file or directory > Can't init input joystick > mplayer: could not connect to socket > mplayer: No such file or directory > Failed to open LIRC support. You will not be able to use your remote > control. > > Playing tv://. > TV file format detected. > Selected driver: v4l2 > name: Video 4 Linux 2 input > author: Martin Olschewski <olschewski@xxxxxxxxxxxxxxxx> > comment: first try, more to come ;-) > Selected device: Leadtek Winfast 2000XP Expert > Tuner cap: > Tuner rxs: > Capabilites: video capture VBI capture device tuner read/write > streaming > supported norms: 0 = PAL-BG; 1 = PAL-DK; 2 = PAL-I; 3 = PAL-M; 4 = > PAL-N; 5 = PAL-Nc; 6 = PAL-60; 7 = NTSC-M; 8 = NTSC-M-JP; 9 = NTSC-443; > 10 = SECAM-DK; 11 = SECAM-L; > inputs: 0 = Television; 1 = Composite1; 2 = S-Video; > Current input: 1 > Current format: BGR24 > v4l2: current audio mode is : MONO > v4l2: ioctl set format failed: Invalid argument > v4l2: ioctl set format failed: Invalid argument > open: No such file or directory > [MGA] Couldn't open: /dev/mga_vid > open: No such file or directory > [MGA] Couldn't open: /dev/mga_vid > [VO_TDFXFB] Can't open /dev/fb0: No such file or directory. > s3fb: can't open /dev/fb0: No such file or directory > ========================================================================== > Opening video decoder: [raw] RAW Uncompressed Video > VDec: vo config request - 640 x 480 (preferred colorspace: Packed UYVY) > VDec: using Packed UYVY as output csp (no 0) > Movie-Aspect is undefined - no prescaling applied. > VO: [xv] 640x480 => 640x480 Packed UYVY > Selected video codec: [rawuyvy] vfm: raw (RAW UYVY) > ========================================================================== > Audio: no sound > Starting playback... > v4l2: 40 frames successfully processed, -39 frames dropped. > > Exiting... (Quit) > > -- > video4linux-list mailing list > Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe > https://www.redhat.com/mailman/listinfo/video4linux-list
/*
* pollcx18 - exercise the cx18 driver in a manner similar to MythTV
* Copyright (C) 2008 Andy Walls
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Andy Walls <cwalls@xxxxxxxxx>
*
* Compile: gcc -Wall -O2 -o pollcx18 pollcx18.c
*
* Invoke: ./pollcx18 -d /dev/video1 -o foo.mpg
*
* To see the cx23418 encoder stall out for a while and a select() timeout,
* cx18_v4l2_enc_poll() should be modified not to check q_io, and you should
* tune to and away from a weak, snowy TV station (but not one that's all snow)
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/select.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
struct parsed_args
{
char *devpath;
char *outfile;
};
static int quit = 0;
void sig_handler (int signum, siginfo_t *info, void *ucontext)
{
quit = 1;
}
int parse_args (int argc, char **argv, struct parsed_args *args)
{
int c, retval;
args->devpath = "/dev/video";
args->outfile = NULL;
retval = 0;
while ((c = getopt(argc, argv, "d:o:")) != -1)
{
switch (c)
{
case 'd':
args->devpath = optarg;
break;
case 'o':
args->outfile = optarg;
break;
default:
fprintf (stderr, "Usage:\npollcx18 [-d videodev] [-o outfile]\n");
retval = -1;
break;
}
}
return retval;
}
void mainloop (int *readfd, int outfd, int *quit, char *devpath)
{
const int bufsize = 4 * 1024; /* 4 kB is what MythTV uses */
char buffer[bufsize];
int bytesused, n;
/* Set retry limit to > 0 to try a few times before closing and
* reopening the fd on a select() timeout */
const int retry_limit = 0;
int retries;
int got_data;
int nfds;
struct timeval timeout;
fd_set rfds;
retries = 0;
got_data = 0;
bytesused = 0;
while (!(*quit))
{
/*
* Attempt to reopen the capture device like MythTV, since
* we may close it later in this loop on timeout, like MythTV
*
* We reopen it without O_NONBLOCK, as does MythTV,
* but that's really a MythTV bug. We should really reopen with
* O_NONBLOCK set.
*
*/
if (*readfd < 0)
{
if ((*readfd =
open(devpath, O_RDWR /*|O_NONBLOCK*/)) < 0)
{
perror("open");
fprintf(stderr,
"Unable to re-open video capture device: %s\n",
devpath);
*quit = 1;
break;
}
else
{
got_data = 0;
retries = 0;
}
}
FD_ZERO(&rfds);
FD_SET(*readfd, &rfds);
timeout.tv_sec = 5; /* MythTV uses 5 seconds */
timeout.tv_usec = 0;
nfds = *readfd + 1;
nfds = select (nfds, &rfds, NULL, NULL, &timeout);
switch (nfds)
{
case -1:
if (errno == EINTR)
continue;
perror("select");
fprintf(stderr, "select failed on video "
"capture device: %s\n",
devpath);
*quit = 1;
retries++; /* this doesn't matter for now */
continue;
case 0:
fprintf(stderr, "select timeout on video "
"capture device: %s\n",
devpath);
/*
* MythTV tries to fix things by closing and
* reopening the readfd
*
* Well do few retries before doing so.
*/
retries++;
if (retries >= retry_limit)
{
close(*readfd);
*readfd = -1;
retries = 0;
got_data = 0;
}
continue;
default:
break;
}
retries = 0;
n = read(*readfd, &(buffer[bytesused]), bufsize-bytesused);
if (n == -1 && errno != EAGAIN && errno != EINTR)
{
perror("read");
fprintf(stderr,
"read failed on video capture device: %s\n",
devpath);
*quit = 1;
}
if (n > 0)
{
bytesused += n;
if (got_data == 0)
{
fprintf(stderr,
"received data on video capture device: %s\n",
devpath);
got_data = 1;
}
}
if (bytesused >= bufsize)
{
if (outfd > -1)
write(outfd, buffer, bufsize);
bytesused = 0;
}
}
/* write out the final partially filled buffer */
if (bytesused > 0 && outfd > -1)
write(outfd, buffer, bytesused);
return;
}
int set_picture_size (int chanfd, int width, int height, char *devpath)
{
struct v4l2_format f;
memset (&f, 0, sizeof (f));
f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(chanfd, VIDIOC_G_FMT, &f) < 0)
{
perror ("ioctl");
fprintf (stderr, "couldn't get video format for device %s\n",
devpath);
return -1;
}
f.fmt.pix.width = width;
f.fmt.pix.height = height;
if (ioctl(chanfd, VIDIOC_S_FMT, &f) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't get video format for device %s\n",
devpath);
return -1;
}
return 0;
}
int set_volume (int chanfd, int level, char *devpath)
{
struct v4l2_control c;
c.id = V4L2_CID_AUDIO_VOLUME;
c.value = (65536*level)/100;
if (ioctl(chanfd, VIDIOC_S_CTRL, &c) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't set audio volume for device %s\n",
devpath);
return -1;
}
return 0;
}
int set_audio_fs (int chanfd, int rate, char *devpath)
{
struct v4l2_ext_controls e;
struct v4l2_ext_control c;
memset(&e, 0, sizeof(e));
memset(&c, 0, sizeof(c));
e.ctrl_class = V4L2_CTRL_CLASS_MPEG;
e.count = 1;
e.controls = &c;
c.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
switch (rate)
{
case 32000:
c.value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
break;
case 44100:
c.value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
break;
case 48000:
default:
c.value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
break;
}
if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &e) < 0)
{
perror("ioctl");
fprintf(stderr,
"couldn't set audio sample rate for device %s\n",
devpath);
return -1;
}
return 0;
}
int set_aspect_ratio (int chanfd, enum v4l2_mpeg_video_aspect aspect,
char *devpath)
{
struct v4l2_ext_controls e;
struct v4l2_ext_control c;
memset(&e, 0, sizeof(e));
memset(&c, 0, sizeof(c));
e.ctrl_class = V4L2_CTRL_CLASS_MPEG;
e.count = 1;
e.controls = &c;
c.id = V4L2_CID_MPEG_VIDEO_ASPECT;
c.value = aspect;
if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &e) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't set aspect ratio for device %s\n",
devpath);
return -1;
}
return 0;
}
int set_audio_encoding (int chanfd, enum v4l2_mpeg_audio_encoding encoding,
char *devpath)
{
struct v4l2_ext_controls e;
struct v4l2_ext_control c;
memset(&e, 0, sizeof(e));
memset(&c, 0, sizeof(c));
e.ctrl_class = V4L2_CTRL_CLASS_MPEG;
e.count = 1;
e.controls = &c;
c.id = V4L2_CID_MPEG_AUDIO_ENCODING;
c.value = encoding;
if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &e) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't set audio encoding for device %s\n",
devpath);
return -1;
}
return 0;
}
int set_audio_bitrate (int chanfd, enum v4l2_mpeg_audio_l2_bitrate rate,
char *devpath)
{
struct v4l2_ext_controls e;
struct v4l2_ext_control c;
memset(&e, 0, sizeof(e));
memset(&c, 0, sizeof(c));
e.ctrl_class = V4L2_CTRL_CLASS_MPEG;
e.count = 1;
e.controls = &c;
c.id = V4L2_CID_MPEG_AUDIO_L2_BITRATE;
c.value = rate;
if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &e) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't set audio encoding for device %s\n",
devpath);
return -1;
}
return 0;
}
int set_video_bitrates (int chanfd, int peak, int nominal, char *devpath)
{
struct v4l2_ext_controls e;
struct v4l2_ext_control c[2];
memset(&e, 0, sizeof(e));
memset(&c, 0, sizeof(struct v4l2_ext_control)*2);
e.ctrl_class = V4L2_CTRL_CLASS_MPEG;
e.count = 2;
e.controls = c;
c[0].id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
c[0].value = peak;
c[1].id = V4L2_CID_MPEG_VIDEO_BITRATE;
c[1].value = nominal;
if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &e) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't set video bitrates for device %s\n",
devpath);
return -1;
}
return 0;
}
int set_streamtype (int chanfd, enum v4l2_mpeg_stream_type type, char *devpath)
{
struct v4l2_ext_controls e;
struct v4l2_ext_control c;
memset(&e, 0, sizeof(e));
memset(&c, 0, sizeof(c));
e.ctrl_class = V4L2_CTRL_CLASS_MPEG;
e.count = 1;
e.controls = &c;
c.id = V4L2_CID_MPEG_STREAM_TYPE;
c.value = type;
if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &e) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't set stream type for device %s\n",
devpath);
return -1;
}
return 0;
}
int setup_vbi (int chanfd, int vbitype, char *devpath)
{
struct v4l2_format f;
struct v4l2_ext_controls e;
struct v4l2_ext_control c;
memset (&f, 0, sizeof (f));
f.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
f.fmt.sliced.service_set = vbitype;
if (ioctl(chanfd, VIDIOC_S_FMT, &f) < 0)
{
perror("ioctl");
fprintf(stderr, "couldn't enable vbi for device %s\n",
devpath);
return -1;
}
memset(&e, 0, sizeof(e));
memset(&c, 0, sizeof(c));
e.ctrl_class = V4L2_CTRL_CLASS_MPEG;
e.count = 1;
e.controls = &c;
c.id = V4L2_CID_MPEG_STREAM_VBI_FMT;
c.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV;
if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &e) < 0)
{
perror("ioctl");
fprintf(stderr,
"couldn't set vbi stream format for device %s\n",
devpath);
return -1;
}
return 0;
}
int main (int argc, char **argv)
{
int chanfd, readfd, outfd;
struct parsed_args args;
struct sigaction sigact;
if (parse_args(argc, argv, &args) < 0)
exit(1);
outfd = -1;
if (args.outfile != NULL &&
(outfd = open(args.outfile, O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0)
{
perror("open");
fprintf(stderr, "Unable to open output file: %s\n",
args.outfile);
}
/* MythTV would use this fd for controlling the capture device */
if ((chanfd = open(args.devpath, O_RDWR)) < 0)
{
perror("open");
fprintf(stderr, "Unable to open video control device: %s\n",
args.devpath);
exit(2);
}
/* Setup like MythTV does on my NTSC-M system */
set_picture_size (chanfd, 704, 480, args.devpath);
set_volume (chanfd, 90, args.devpath);
set_audio_fs (chanfd, 48000, args.devpath);
set_aspect_ratio (chanfd, V4L2_MPEG_VIDEO_ASPECT_4x3, args.devpath);
set_audio_encoding (chanfd, V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
args.devpath);
set_audio_bitrate (chanfd, V4L2_MPEG_AUDIO_L2_BITRATE_384K,
args.devpath);
set_video_bitrates (chanfd, 6000000, 4500000, args.devpath);
set_streamtype (chanfd, V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
args.devpath);
/*
* This vbi setup makes the difference between the encoder permanently
* stalling or not
*/
setup_vbi (chanfd, V4L2_SLICED_VBI_525, args.devpath);
/* MythTV would use this fd for video capture */
if ((readfd = open(args.devpath, O_RDWR|O_NONBLOCK)) < 0)
{
perror("open");
fprintf(stderr, "Unable to open video capture device: %s\n",
args.devpath);
exit(3);
}
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = sig_handler;
sigemptyset(&(sigact.sa_mask));
sigaction(SIGINT, &sigact, NULL); /* handle ^C to do a graceful exit */
quit = 0;
mainloop(&readfd, outfd, &quit, args.devpath);
close(readfd);
close(chanfd);
close(outfd);
exit(0);
}
-- video4linux-list mailing list Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe https://www.redhat.com/mailman/listinfo/video4linux-list
[Home] [Older V4L] [Linux DVB] [Video Disk Recorder] [Video Technology] [Asterisk] [Photo] [DCCP] [Netdev] [Plasma TVs] [Video Projectors] [PDAs] [Xorg] [Util Linux NG] [Xfree86] [Devices] [Big List of Linux Books] [Free Photo Albums] [LCD TVs] [Fedora Users] [Webcams] [Fedora Women] [HDTV] [ALSA Users] [ALSA Devel] [Stuff] [SSH] [DVB Maintainers] [Linux USB]
![]() |
![]() |