* Green/purple video from 950Q + security cam
@ 2013-07-28 22:00 Michael Conrad
2013-07-29 13:19 ` Devin Heitmueller
0 siblings, 1 reply; 2+ messages in thread
From: Michael Conrad @ 2013-07-28 22:00 UTC (permalink / raw)
To: linux-media
[-- Attachment #1: Type: text/plain, Size: 5601 bytes --]
Hi,
I have a WinTV-HVR-950Q which I am using to capture composite video. I
have two cameras: a rear-view cam for a car, and a security camera.
When I plug either of these cameras into the video plug on a plain old
TV, they work great. When I plug either camera into the 950Q on Windows
using the supplied WinTV software, they work great. When I plug the
rear-view camera into the 950Q on Linux, it works great. But when I
plug the security camera into 950Q on Linux, it mostly works and then
the picture starts randomly jumping sideways (like it is having trouble
keeping a horizontal sync on the signal) and then will suddenly flip to
a green-grayscale image with all bright areas as purple-grayscale. Once
turned green/purple, it remains like this until I reset the camera, but
the video is full framerate, low latency, and looks flawless aside from
the bizarre colors.
For the tests under Linux, I am using the v4l2 API directly in a simple
demo C program I wrote. It is attached. I tried both the "read" API,
and the mmap API. Both produce identical results.
My other attempts on Linux had been to use v4l2-ctl to select the
composite channel, and then play the device with VLC or Cheese. Neither
were successful (no video at all) but I need to do this from C in the
long run, anyway.
Anyone seen anything like this before?
Thanks in advance.
-Mike
------------
Some details:
Linux Mint 12, 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:56:25 UTC
2011 x86_64 x86_64 x86_64 GNU/Linux
Bus 001 Device 007: ID 2040:7200 Hauppauge
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x2040 Hauppauge
idProduct 0x7200
bcdDevice 0.05
iManufacturer 1
iProduct 2
iSerial 10
bNumConfigurations 1
Relevant loaded modules:
tuner 27428 1
au8522 27916 2
au0828 48363 0
dvb_core 110616 1 au0828
videobuf_vmalloc 13589 1 au0828
videobuf_core 26390 2 au0828,videobuf_vmalloc
tveeprom 21249 1 au0828
v4l2_common 16454 3 tuner,au8522,au0828
videodev 93004 4 tuner,au8522,au0828,v4l2_common
v4l2_compat_ioctl32 17083 1 videodev
Relevant kernel messages (only from bootup, nothing new shows while playing)
[ 10.467852] Linux video capture interface: v2.00
[ 10.677764] au0828 driver loaded
[ 11.036080] au0828: i2c bus registered
[ 11.294654] tveeprom 0-0050: Hauppauge model 72001, rev B4F0, serial#
8455749
[ 11.294658] tveeprom 0-0050: MAC address is 00:0d:fe:81:06:45
[ 11.294661] tveeprom 0-0050: tuner model is Xceive XC5000 (idx 150,
type 76)
[ 11.294664] tveeprom 0-0050: TV standards NTSC(M) ATSC/DVB Digital
(eeprom 0x88)
[ 11.294666] tveeprom 0-0050: audio processor is AU8522 (idx 44)
[ 11.294669] tveeprom 0-0050: decoder processor is AU8522 (idx 42)
[ 11.294672] tveeprom 0-0050: has no radio, has IR receiver, has no IR
transmitter
[ 11.294674] hauppauge_eeprom: hauppauge eeprom: model=72001
[ 11.321442] nvidia: module license 'NVIDIA' taints kernel.
[ 11.321446] Disabling lock debugging due to kernel taint
[ 12.006495] nvidia 0000:01:00.0: PCI INT A -> GSI 16 (level, low) ->
IRQ 16
[ 12.006503] nvidia 0000:01:00.0: setting latency timer to 64
[ 12.006508] vgaarb: device changed decodes:
PCI:0000:01:00.0,olddecodes=io+mem,decodes=none:owns=io+mem
[ 12.006583] NVRM: loading NVIDIA UNIX x86_64 Kernel Module 280.13
Wed Jul 27 16:53:56 PDT 2011
[ 12.020865] au8522 0-0047: creating new instance
[ 12.020867] au8522_decoder creating new instance...
[ 12.061240] i2c-core: driver [tuner] using legacy suspend method
[ 12.061242] i2c-core: driver [tuner] using legacy resume method
[ 12.061662] tuner 0-0061: Tuner -1 found with type(s) Radio TV.
[ 12.089530] xc5000 0-0061: creating new instance
[ 12.094274] xc5000: Successfully identified at address 0x61
[ 12.094277] xc5000: Firmware has not been loaded previously
[ 12.094536] au8522 0-0047: attaching existing instance
[ 12.101901] xc5000 0-0061: attaching existing instance
[ 12.112396] xc5000: Successfully identified at address 0x61
[ 12.112398] xc5000: Firmware has not been loaded previously
[ 12.112400] DVB: registering new adapter (au0828)
[ 12.112402] DVB: registering adapter 0 frontend 0 (Auvitek AU8522
QAM/8VSB Frontend)...
[ 12.112699] Registered device AU0828 [Hauppauge HVR950Q]
[ 12.631925] usbcore: registered new interface driver snd-usb-audio
[ 12.632064] usbcore: registered new interface driver au0828
Output from my program:
Driver : au0828
Card : Hauppauge HVR950Q
Bus : au0828 1-5.1.2:1.0
Version: 0.0.1
Caps : V4L2_CAP_VIDEO_CAPTURE V4L2_CAP_VBI_CAPTURE V4L2_CAP_TUNER
V4L2_CAP_AUDIO V4L2_CAP_READWRITE V4L2_CAP_STREAMING
Control 9963776: Brightness (0-255) slider
Control 9963777: Contrast (0-255) slider
Control 9963778: Saturation (0-255) slider
Control 9963779: Hue (-32768-32768) slider
4 controls
Input Television: tuner 0 status:
Input Composite: camera status:
Input S-Video: camera status:
3 inputs.
Set input to 1 (new val = 1)
Current video standard: NTSC-M
Image Format: 720 x 480 UYVY field=4 pitch=1440 size=691200 colorspace=1
End of formats
Received 691200 bytes
... (repeated for each frame)
[-- Attachment #2: v4ltest.cpp --]
[-- Type: text/x-c++src, Size: 12112 bytes --]
//#include "config.h"
#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/videodev2.h>
typedef long long unsigned UINT64_C;
extern "C" {
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
}
#include <fcntl.h>
#include <sys/ioctl.h>
void showcaps(int fd);
void showcontrols(int fd);
void show_inputs(int fd);
void set_input(int fd, int idx);
void query_standard(int fd);
void query_imgfmt(int fd, v4l2_pix_format *fmt);
void query_formats(int fd);
bool show_frame(uint8_t *frame, PixelFormat fmt, int stride, int w, int h);
void init_mmap(int fd);
void* acquire_mmap_frame(int fd, struct v4l2_buffer *buffer);
void release_mmap_frame(int fd, struct v4l2_buffer *buffer);
void finalize_mmap(int fd);
uint8_t *framebuf;
uint8_t *rgbbuf;
struct mmap_buffer_item {
void *start;
size_t length;
bool locked;
} *mmap_buffers= NULL;
int mmap_buffer_count= 0;
int main() {
v4l2_pix_format fmt;
struct v4l2_buffer buffer;
//int lines;
int got= 0;
int fd= open("/dev/video0", O_RDWR);
if (fd < 0) { perror("open(/dev/video0)"); exit(2); }
showcaps(fd);
showcontrols(fd);
show_inputs(fd);
set_input(fd, 1);
query_standard(fd);
query_imgfmt(fd, &fmt);
query_formats(fd);
printf("End of formats\n");
int framesize= fmt.sizeimage;
int imglines= fmt.height; // account for interlace
//framebuf= (uint8_t*) malloc(framesize);
//if (!framebuf) { perror("malloc"); return 1; }
rgbbuf= (uint8_t*) malloc(fmt.width * imglines * 3);
if (!rgbbuf) { perror("malloc"); return 1; }
init_mmap(fd);
while (1) {
#if 0
got= read(fd, framebuf, framesize);
if (got < 0) { perror("read"); return 2; }
#else
framebuf= (uint8_t*) acquire_mmap_frame(fd, &buffer);
got= framesize= buffer.bytesused;
#endif
printf("Received %d bytes\n", got);
if (got != framesize) {
printf("didn't get frame size\n");
} else if (imglines * (int)fmt.bytesperline > framesize) {
printf("frame not large enough for image\n");
} else if (!show_frame(framebuf, PIX_FMT_UYVY422, fmt.bytesperline, fmt.width, imglines)) {
abort();
}
release_mmap_frame(fd, &buffer);
}
//unlink("frame");
//int out= open("frame", O_RDWR|O_CREAT, 777);
//if (out < 0) { perror("open(frame)"); exit(2); }
//write(out, framebuf, got);
//close(out);
close(fd);
return 0;
}
struct SwsContext *convparam= NULL;
SDL_Surface *window= NULL;
SDL_Event event;
bool show_frame(uint8_t *frame, PixelFormat fmt, int stride, int w, int h) {
if (!window) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
return false;
}
atexit(SDL_Quit);
window = SDL_SetVideoMode(w, h, 24, SDL_SWSURFACE);
if (!window) {
fprintf(stderr, "Couldn't set create window: %s\n", SDL_GetError());
return false;
}
}
convparam= sws_getCachedContext(convparam, w, h, fmt, w, h, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
if (!convparam) {
printf("Unable to convert image format\n");
return false;
}
//void* pixels;
//int pitch;
if (SDL_LockSurface(window) < 0) {
fprintf(stderr, "Couldn't lock texture: %s\n", SDL_GetError());
return false;
}
uint8_t* s_data[4]= { frame, NULL, NULL, NULL };
int s_linesize[4]= { stride, 0, 0, 0 };
uint8_t* d_data[4]= { (uint8_t*)window->pixels, NULL, NULL, NULL };
int d_linesize[4]= { window->pitch, 0, 0, 0 };
sws_scale(convparam, s_data, s_linesize, 0, h, d_data, d_linesize);
SDL_UnlockSurface(window);
SDL_UpdateRect(window, 0, 0, w, h);
bool done= false;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) {
done= true;
}
break;
case SDL_QUIT:
done= true;
break;
}
}
if (done) {
SDL_Quit();
window= NULL;
}
return true;
}
typedef struct {
long long code;
const char* name;
} const_entry_t;
/*const char * find_constant(struct const_entry_t *array, int array_len, int code) {
for (int i=0; i<array_len; i++) {
if (array[i].code == code)
return array[i].name;
}
return "??";
}*/
#define ARRAY_LENGTH(array) ((int)(sizeof(array)/sizeof(*array)))
#define F(x) { x, #x }
static const_entry_t
v4l_cap_decode[]= {
F(V4L2_CAP_VIDEO_CAPTURE),
F(V4L2_CAP_VIDEO_OUTPUT),
F(V4L2_CAP_VIDEO_OVERLAY),
F(V4L2_CAP_VBI_CAPTURE),
F(V4L2_CAP_VBI_OUTPUT),
F(V4L2_CAP_SLICED_VBI_CAPTURE),
F(V4L2_CAP_SLICED_VBI_OUTPUT),
F(V4L2_CAP_RDS_CAPTURE),
F(V4L2_CAP_VIDEO_OUTPUT_OVERLAY),
F(V4L2_CAP_TUNER),
F(V4L2_CAP_AUDIO),
F(V4L2_CAP_RADIO),
F(V4L2_CAP_READWRITE),
F(V4L2_CAP_ASYNCIO),
F(V4L2_CAP_STREAMING)
},
v4l_input_status[]= {
F(V4L2_IN_ST_NO_POWER),
F(V4L2_IN_ST_NO_SIGNAL),
F(V4L2_IN_ST_NO_COLOR),
F(V4L2_IN_ST_NO_H_LOCK),
F(V4L2_IN_ST_COLOR_KILL),
F(V4L2_IN_ST_NO_SYNC),
F(V4L2_IN_ST_NO_EQU),
F(V4L2_IN_ST_NO_CARRIER),
F(V4L2_IN_ST_MACROVISION),
F(V4L2_IN_ST_NO_ACCESS),
F(V4L2_IN_ST_VTR),
},
v4l_vid_std[]= {
F(V4L2_STD_PAL_B),
F(V4L2_STD_PAL_B1),
F(V4L2_STD_PAL_G),
F(V4L2_STD_PAL_H),
F(V4L2_STD_PAL_I),
F(V4L2_STD_PAL_D),
F(V4L2_STD_PAL_D1),
F(V4L2_STD_PAL_K),
F(V4L2_STD_PAL_M),
F(V4L2_STD_PAL_N),
F(V4L2_STD_PAL_Nc),
F(V4L2_STD_PAL_60),
F(V4L2_STD_NTSC_M),
F(V4L2_STD_NTSC_M_JP),
F(V4L2_STD_NTSC_443),
F(V4L2_STD_NTSC_M_KR),
F(V4L2_STD_SECAM_B),
F(V4L2_STD_SECAM_D),
F(V4L2_STD_SECAM_G),
F(V4L2_STD_SECAM_H),
F(V4L2_STD_SECAM_K),
F(V4L2_STD_SECAM_K1),
F(V4L2_STD_SECAM_L),
F(V4L2_STD_SECAM_LC),
F(V4L2_STD_ATSC_8_VSB),
F(V4L2_STD_ATSC_16_VSB)
};
#undef F
void showcaps(int fd) {
struct v4l2_capability caps;
int ret= ioctl(fd, VIDIOC_QUERYCAP, &caps);
if (ret < 0) { perror("ioctl(QUERYCAP)"); exit(2); }
printf("Driver : %s\nCard : %s\nBus : %s\nVersion: %u.%u.%u\nCaps :",
caps.driver,
caps.card,
caps.bus_info,
(caps.version>>16)&0xFF, (caps.version>>8)&0xFF, caps.version&0xFF);
for (int i=0; i < ARRAY_LENGTH(v4l_cap_decode); i++) {
if (caps.capabilities & v4l_cap_decode[i].code)
printf(" %s", v4l_cap_decode[i].name);
}
printf("\n");
}
void showcontrols(int fd) {
struct v4l2_queryctrl ctrl;
int cnt= 0;
for (int i=V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++) {
memset(&ctrl, 0, sizeof(ctrl));
ctrl.id= i;
int ret= ioctl(fd, VIDIOC_QUERYCTRL, &ctrl);
if (ret < 0) {
if (errno == EINVAL) continue;
perror("ioctl(QUERYCTRL)"); exit(2);
}
cnt++;
printf("Control %3d: %-20s (%d-%d)%s%s%s%s%s%s\n", i, ctrl.name, ctrl.minimum, ctrl.maximum,
(ctrl.flags&V4L2_CTRL_FLAG_DISABLED)? " disabled":"",
(ctrl.flags&V4L2_CTRL_FLAG_GRABBED)? " grabbed":"",
(ctrl.flags&V4L2_CTRL_FLAG_READ_ONLY)? " r/o":"",
(ctrl.flags&V4L2_CTRL_FLAG_UPDATE)? " update":"",
(ctrl.flags&V4L2_CTRL_FLAG_INACTIVE)? " inact":"",
(ctrl.flags&V4L2_CTRL_FLAG_SLIDER)? " slider":""
);
}
printf("%d controls\n", cnt);
}
void show_inputs(int fd) {
struct v4l2_input inp;
int i= 0;
while (1) {
memset(&inp, 0, sizeof(inp));
inp.index= i;
int ret= ioctl(fd, VIDIOC_ENUMINPUT, &inp);
if (ret < 0) {
if (errno == EINVAL) break;
perror("ioctl(ENUMINPUT)");
exit(2);
}
i++;
if (inp.type == V4L2_INPUT_TYPE_TUNER) {
printf("Input %s: tuner %d status:", inp.name, inp.tuner);
} else if (inp.type == V4L2_INPUT_TYPE_CAMERA) {
printf("Input %s: camera status:", inp.name);
} else {
printf("Input %s: (unknown) status:", inp.name);
}
for (int f= 0; f < ARRAY_LENGTH(v4l_input_status); f++) {
if (inp.status & v4l_input_status[f].code)
printf(" %s", v4l_input_status[i].name);
}
printf("\n");
}
printf("%d inputs.\n", i);
}
void set_input(int fd, int idx) {
if (-1 == ioctl(fd, VIDIOC_S_INPUT, &idx)) {
perror("VIDEOC_S_INPUT");
exit(2);
}
int newVal= -1;
if (-1 == ioctl(fd, VIDIOC_G_INPUT, &newVal)) {
perror("VIDEOC_G_INPUT");
exit(2);
}
printf("Set input to %d (new val = %d)\n", idx, newVal);
}
void query_standard(int fd) {
v4l2_std_id std_id;
struct v4l2_standard standard;
if (-1 == ioctl (fd, VIDIOC_G_STD, &std_id)) {
/* Note when VIDIOC_ENUMSTD always returns EINVAL this
is no video device or it falls under the USB exception,
and VIDIOC_G_STD returning EINVAL is no error. */
perror ("VIDIOC_G_STD");
exit (2);
}
memset (&standard, 0, sizeof (standard));
standard.index = 0;
while (0 == ioctl (fd, VIDIOC_ENUMSTD, &standard)) {
if (standard.id & std_id) {
printf ("Current video standard: %s\n", standard.name);
return;
}
standard.index++;
}
printf("Unknown standard\n");
}
void query_formats(int fd) {
v4l2_fmtdesc fmtd;
int i=0;
do {
memset(&fmtd, 0, sizeof(fmtd));
fmtd.index= i++;
int ret= ioctl(fd, VIDIOC_ENUM_FMT, &fmtd);
if (ret < 0) {
if (errno == EINVAL) return;
perror("ioctl(ENUM_FMT)");
}
printf("Pixel Format %s: type=%d flags=%d pixelformat=%d (%4.4s)\n", fmtd.description, fmtd.type, fmtd.flags, fmtd.pixelformat, (char*)&fmtd.pixelformat);
} while (1);
}
void query_imgfmt(int fd, v4l2_pix_format *fmt) {
v4l2_format vfmt;
v4l2_pix_format *pix= &vfmt.fmt.pix;
memset(&vfmt, 0, sizeof(vfmt));
vfmt.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_G_FMT, &vfmt) < 0) {
perror("ioctl(G_FMT)");
exit(1);
}
printf("Image Format: %d x %d %4.4s field=%d pitch=%d size=%d colorspace=%d\n",
pix->width, pix->height, (char*)&pix->pixelformat, pix->field, pix->bytesperline, pix->sizeimage, pix->colorspace);
if (fmt) memcpy(fmt, pix, sizeof(*fmt));
}
void init_mmap(int fd) {
struct v4l2_requestbuffers reqbuf;
struct v4l2_buffer buffer;
unsigned int i;
memset(&reqbuf, 0, sizeof(reqbuf));
reqbuf.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory= V4L2_MEMORY_MMAP;
reqbuf.count= 8;
if (-1 == ioctl(fd, VIDIOC_REQBUFS, &reqbuf)) {
if (errno == EINVAL)
printf("Video capturing or mmap-streaming is not supported\n");
else
perror("VIDIOC_REQBUFS");
exit(2);
}
/* We want at least five buffers. */
mmap_buffer_count= reqbuf.count;
if (mmap_buffer_count < 5) {
/* You may need to free the buffers here. */
printf("Not enough buffer memory\n");
exit(2);
}
mmap_buffers= (struct mmap_buffer_item*) realloc(mmap_buffers, mmap_buffer_count * sizeof(*mmap_buffers));
assert(mmap_buffers != NULL);
memset(mmap_buffers, 0, mmap_buffer_count * sizeof(*mmap_buffers));
for (i = 0; i < mmap_buffer_count; i++) {
memset(&buffer, 0, sizeof(buffer));
buffer.type= reqbuf.type;
buffer.memory= V4L2_MEMORY_MMAP;
buffer.index= i;
if (-1 == ioctl(fd, VIDIOC_QUERYBUF, &buffer)) {
perror("VIDIOC_QUERYBUF");
exit(2);
}
mmap_buffers[i].length= buffer.length; /* remember for munmap() */
mmap_buffers[i].start= mmap(NULL, buffer.length,
PROT_READ | PROT_WRITE, /* recommended */
MAP_SHARED, /* recommended */
fd, buffer.m.offset);
if (MAP_FAILED == mmap_buffers[i].start) {
/* If you do not exit here you should unmap() and free()
the buffers mapped so far. */
perror("mmap");
exit(2);
}
if (-1 == ioctl(fd, VIDIOC_QBUF, &buffer)) {
perror("VIDIOC_QBUF");
exit(2);
}
}
}
void* acquire_mmap_frame(int fd, struct v4l2_buffer *buffer) {
int i;
memset(buffer, 0, sizeof(*buffer));
buffer->type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer->memory= V4L2_MEMORY_MMAP;
buffer->index= i;
if (-1 == ioctl(fd, VIDIOC_DQBUF, buffer)) {
perror("VIDIOC_DQBUF");
exit(2);
}
if (buffer->index < 0 || buffer->index >= mmap_buffer_count) {
printf("Buffer index out of bounds! %d\n", buffer->index);
exit(2);
}
return mmap_buffers[buffer->index].start;
}
void release_mmap_frame(int fd, struct v4l2_buffer *buffer) {
if (-1 == ioctl(fd, VIDIOC_QBUF, buffer)) {
perror("VIDIOC_QBUF");
exit(2);
}
}
void finalize_mmap(int fd) {
int i;
for (i = 0; i < mmap_buffer_count; i++)
munmap(mmap_buffers[i].start, mmap_buffers[i].length);
free(mmap_buffers);
mmap_buffers= NULL;
}
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: Green/purple video from 950Q + security cam
2013-07-28 22:00 Green/purple video from 950Q + security cam Michael Conrad
@ 2013-07-29 13:19 ` Devin Heitmueller
0 siblings, 0 replies; 2+ messages in thread
From: Devin Heitmueller @ 2013-07-29 13:19 UTC (permalink / raw)
To: Michael Conrad; +Cc: linux-media
Hi Michael,
On Sun, Jul 28, 2013 at 6:00 PM, Michael Conrad <mike@nrdvana.net> wrote:
> When I plug either of these cameras into the video plug on a plain old TV,
> they work great. When I plug either camera into the 950Q on Windows using
> the supplied WinTV software, they work great. When I plug the rear-view
> camera into the 950Q on Linux, it works great. But when I plug the security
> camera into 950Q on Linux, it mostly works and then the picture starts
> randomly jumping sideways (like it is having trouble keeping a horizontal
> sync on the signal) and then will suddenly flip to a green-grayscale image
> with all bright areas as purple-grayscale. Once turned green/purple, it
> remains like this until I reset the camera, but the video is full framerate,
> low latency, and looks flawless aside from the bizarre colors.
Yeah, there have been some issues with frame alignment on that
particular chip, which primarily manifest themselves when using highly
unstable video sources. This might sound like a cop-out, but you
would be better suited with *any* $29 capture device from NewEgg than
with the 950q.
I've got workarounds in the driver code which cover most of the edge
cases, but they aren't foolproof.
> For the tests under Linux, I am using the v4l2 API directly in a simple demo
> C program I wrote. It is attached. I tried both the "read" API, and the
> mmap API. Both produce identical results.
Won't make a difference whether using mmap or read in this case.
> My other attempts on Linux had been to use v4l2-ctl to select the composite
> channel, and then play the device with VLC or Cheese. Neither were
> successful (no video at all) but I need to do this from C in the long run,
> anyway.
Cheese typically doesn't work with anything other than webcams since
they typically don't support all the colorspaces (and the 950q in
particular uses one that is unusual for raw video). VLC should work
though if you get the correct magic incantation of command line
arguments (I use it regularly with the 950q).
> Anyone seen anything like this before?
Yes, I have. :-)
It can certainly be made to work via hacking at the driver (but I
don't have a video source which readily reproduces the issue). But
with Kworld 2800d units being available for $29 on Ebay, that is
probably by far the easier approach.
Devin
--
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-07-29 13:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-28 22:00 Green/purple video from 950Q + security cam Michael Conrad
2013-07-29 13:19 ` Devin Heitmueller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox