📄 v4l.c
字号:
} else { i_len = strlen( psz_parser ); } p_sys->psz_adev = strndup( psz_parser, i_len ); psz_parser += i_len; } else if( !strncmp( psz_parser, "samplerate=", strlen( "samplerate=" ) ) ) { p_sys->i_sample_rate = strtol( psz_parser + strlen( "samplerate=" ), &psz_parser, 0 ); } else if( !strncmp( psz_parser, "stereo", strlen( "stereo" ) ) ) { psz_parser += strlen( "stereo" ); p_sys->b_stereo = true; } else if( !strncmp( psz_parser, "mono", strlen( "mono" ) ) ) { psz_parser += strlen( "mono" ); p_sys->b_stereo = false; } else if( !strncmp( psz_parser, "mjpeg", strlen( "mjpeg" ) ) ) { psz_parser += strlen( "mjpeg" ); p_sys->b_mjpeg = true; } else if( !strncmp( psz_parser, "decimation=", strlen( "decimation=" ) ) ) { p_sys->i_decimation = strtol( psz_parser + strlen( "decimation=" ), &psz_parser, 0 ); } else if( !strncmp( psz_parser, "quality=", strlen( "quality=" ) ) ) { p_sys->i_quality = strtol( psz_parser + strlen( "quality=" ), &psz_parser, 0 ); } else if( !strncmp( psz_parser, "fps=", strlen( "fps=" ) ) ) { p_sys->f_fps = strtof( psz_parser + strlen( "fps=" ), &psz_parser ); } else { msg_Warn( p_demux, "unknown option" ); } while( *psz_parser && *psz_parser != ':' ) { psz_parser++; } if( *psz_parser == '\0' ) { break; } } } if( *psz_dup ) { p_sys->psz_device = strdup( psz_dup ); } free( psz_dup );}/***************************************************************************** * OpenVideoDev: *****************************************************************************/static int OpenVideoDev( demux_t *p_demux, char *psz_device ){ demux_sys_t *p_sys = p_demux->p_sys; int i_fd; struct video_channel vid_channel; struct mjpeg_params mjpeg; int i; if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 ) { msg_Err( p_demux, "cannot open device (%m)" ); goto vdev_failed; } if( ioctl( i_fd, VIDIOCGCAP, &p_sys->vid_cap ) < 0 ) { msg_Err( p_demux, "cannot get capabilities (%m)" ); goto vdev_failed; } msg_Dbg( p_demux, "V4L device %s %d channels %d audios %d < w < %d %d < h < %d", p_sys->vid_cap.name, p_sys->vid_cap.channels, p_sys->vid_cap.audios, p_sys->vid_cap.minwidth, p_sys->vid_cap.maxwidth, p_sys->vid_cap.minheight, p_sys->vid_cap.maxheight ); if( p_sys->i_channel < 0 || p_sys->i_channel >= p_sys->vid_cap.channels ) { msg_Dbg( p_demux, "invalid channel, falling back on channel 0" ); p_sys->i_channel = 0; } if( p_sys->vid_cap.audios && p_sys->i_audio >= p_sys->vid_cap.audios ) { msg_Dbg( p_demux, "invalid audio, falling back with no audio" ); p_sys->i_audio = -1; } if( p_sys->i_width < p_sys->vid_cap.minwidth || p_sys->i_width > p_sys->vid_cap.maxwidth ) { msg_Dbg( p_demux, "invalid width %i", p_sys->i_width ); p_sys->i_width = 0; } if( p_sys->i_height < p_sys->vid_cap.minheight || p_sys->i_height > p_sys->vid_cap.maxheight ) { msg_Dbg( p_demux, "invalid height %i", p_sys->i_height ); p_sys->i_height = 0; } if( !( p_sys->vid_cap.type & VID_TYPE_CAPTURE ) ) { msg_Err( p_demux, "cannot grab" ); goto vdev_failed; } vid_channel.channel = p_sys->i_channel; if( ioctl( i_fd, VIDIOCGCHAN, &vid_channel ) < 0 ) { msg_Err( p_demux, "cannot get channel infos (%m)" ); goto vdev_failed; } msg_Dbg( p_demux, "setting channel %s(%d) %d tuners flags=0x%x type=0x%x norm=0x%x", vid_channel.name, vid_channel.channel, vid_channel.tuners, vid_channel.flags, vid_channel.type, vid_channel.norm ); if( p_sys->i_tuner >= vid_channel.tuners ) { msg_Dbg( p_demux, "invalid tuner, falling back on tuner 0" ); p_sys->i_tuner = 0; } vid_channel.norm = p_sys->i_norm; if( ioctl( i_fd, VIDIOCSCHAN, &vid_channel ) < 0 ) { msg_Err( p_demux, "cannot set channel (%m)" ); goto vdev_failed; } if( vid_channel.flags & VIDEO_VC_TUNER ) { /* set tuner */#if 0 struct video_tuner vid_tuner; if( p_sys->i_tuner >= 0 ) { vid_tuner.tuner = p_sys->i_tuner; if( ioctl( i_fd, VIDIOCGTUNER, &vid_tuner ) < 0 ) { msg_Err( p_demux, "cannot get tuner (%m)" ); goto vdev_failed; } msg_Dbg( p_demux, "tuner %s low=%d high=%d, flags=0x%x " "mode=0x%x signal=0x%x", vid_tuner.name, vid_tuner.rangelow, vid_tuner.rangehigh, vid_tuner.flags, vid_tuner.mode, vid_tuner.signal ); msg_Dbg( p_demux, "setting tuner %s (%d)", vid_tuner.name, vid_tuner.tuner ); /* FIXME FIXME to be checked FIXME FIXME */ //vid_tuner.mode = p_sys->i_norm; if( ioctl( i_fd, VIDIOCSTUNER, &vid_tuner ) < 0 ) { msg_Err( p_demux, "cannot set tuner (%m)" ); goto vdev_failed; } }#endif /* Show a warning if frequency is < than 30000. * User is certainly usint old syntax. */ /* set frequency */ if( p_sys->i_frequency >= 0 ) { int driver_frequency = p_sys->i_frequency * 16 /1000; if( ioctl( i_fd, VIDIOCSFREQ, &driver_frequency ) < 0 ) { msg_Err( p_demux, "cannot set frequency (%m)" ); goto vdev_failed; } msg_Dbg( p_demux, "frequency %d (%d)", p_sys->i_frequency, driver_frequency ); } } /* set audio */ if( vid_channel.flags & VIDEO_VC_AUDIO ) { struct video_audio vid_audio; /* XXX TODO volume, balance, ... */ if( p_sys->i_audio >= 0 ) { vid_audio.audio = p_sys->i_audio; if( ioctl( i_fd, VIDIOCGAUDIO, &vid_audio ) < 0 ) { msg_Err( p_demux, "cannot get audio (%m)" ); goto vdev_failed; } /* unmute audio */ vid_audio.flags &= ~VIDEO_AUDIO_MUTE; if( ioctl( i_fd, VIDIOCSAUDIO, &vid_audio ) < 0 ) { msg_Err( p_demux, "cannot set audio (%m)" ); goto vdev_failed; } } } /* establish basic params with input and norm before feeling width * or height */ if( p_sys->b_mjpeg ) { struct quicktime_mjpeg_app1 *p_app1; int32_t i_offset; if( ioctl( i_fd, MJPIOC_G_PARAMS, &mjpeg ) < 0 ) { msg_Err( p_demux, "cannot get mjpeg params (%m)" ); goto vdev_failed; } mjpeg.input = p_sys->i_channel; mjpeg.norm = p_sys->i_norm; mjpeg.decimation = p_sys->i_decimation; if( p_sys->i_width ) mjpeg.img_width = p_sys->i_width / p_sys->i_decimation; if( p_sys->i_height ) mjpeg.img_height = p_sys->i_height / p_sys->i_decimation; /* establish Quicktime APP1 marker while we are here */ mjpeg.APPn = 1; mjpeg.APP_len = 40; /* aligned */ p_app1 = (struct quicktime_mjpeg_app1 *)mjpeg.APP_data; p_app1->i_reserved = 0; p_app1->i_tag = VLC_FOURCC( 'm','j','p','g' ); p_app1->i_field_size = 0; p_app1->i_padded_field_size = 0; p_app1->i_next_field = 0; /* XXX WARNING XXX */ /* these's nothing magic about these values. We are dangerously * assuming the encoder card is encoding mjpeg-a and is not throwing * in marker tags we aren't expecting. It's bad enough we have to * search through the jpeg output for every frame we grab just to * find the first field's end marker, so we take this risk to boost * performance. * This is really something the driver could do for us because this * does conform to standards outside of Apple Quicktime. */ i_offset = 0x2e; p_app1->i_DQT_offset = hton32( i_offset ); i_offset = 0xb4; p_app1->i_DHT_offset = hton32( i_offset ); i_offset = 0x258; p_app1->i_SOF_offset = hton32( i_offset ); i_offset = 0x26b; p_app1->i_SOS_offset = hton32( i_offset ); i_offset = 0x279; p_app1->i_data_offset = hton32( i_offset ); /* SOF and SOS aren't specified by the mjpeg API because they aren't * optional. They will be present in the output. */ mjpeg.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT; if( ioctl( i_fd, MJPIOC_S_PARAMS, &mjpeg ) < 0 ) { msg_Err( p_demux, "cannot set mjpeg params (%m)" ); goto vdev_failed; } p_sys->i_width = mjpeg.img_width * mjpeg.HorDcm; p_sys->i_height = mjpeg.img_height * mjpeg.VerDcm * mjpeg.field_per_buff; } /* fix width/height */ if( !p_sys->b_mjpeg && ( p_sys->i_width == 0 || p_sys->i_height == 0 ) ) { struct video_window vid_win; if( ioctl( i_fd, VIDIOCGWIN, &vid_win ) < 0 ) { msg_Err( p_demux, "cannot get win (%m)" ); goto vdev_failed; } p_sys->i_width = vid_win.width; p_sys->i_height = vid_win.height; if( !p_sys->i_width || !p_sys->i_height ) { p_sys->i_width = p_sys->vid_cap.maxwidth; p_sys->i_height = p_sys->vid_cap.maxheight; } if( !p_sys->i_width || !p_sys->i_height ) { msg_Err( p_demux, "invalid video size (%ix%i)", p_sys->i_width, p_sys->i_height ); goto vdev_failed; } msg_Dbg( p_demux, "will use %dx%d", p_sys->i_width, p_sys->i_height ); } if( !p_sys->b_mjpeg ) { /* set hue/color/.. */ if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 ) { struct video_picture vid_picture = p_sys->vid_picture; if( p_sys->i_brightness >= 0 && p_sys->i_brightness < 65536 ) { vid_picture.brightness = p_sys->i_brightness; } if( p_sys->i_colour >= 0 && p_sys->i_colour < 65536 ) { vid_picture.colour = p_sys->i_colour; } if( p_sys->i_hue >= 0 && p_sys->i_hue < 65536 ) { vid_picture.hue = p_sys->i_hue; } if( p_sys->i_contrast >= 0 && p_sys->i_contrast < 65536 ) { vid_picture.contrast = p_sys->i_contrast; } if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 ) { msg_Dbg( p_demux, "v4l device uses brightness: %d", vid_picture.brightness ); msg_Dbg( p_demux, "v4l device uses colour: %d", vid_picture.colour ); msg_Dbg( p_demux, "v4l device uses hue: %d", vid_picture.hue ); msg_Dbg( p_demux, "v4l device uses contrast: %d", vid_picture.contrast ); p_sys->vid_picture = vid_picture; } } /* Find out video format used by device */ if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 ) { struct video_picture vid_picture = p_sys->vid_picture; char *psz; int i; p_sys->i_fourcc = 0; psz = var_CreateGetString( p_demux, "v4l-chroma" ); if( strlen( psz ) >= 4 ) { vid_picture.palette = 0; int i_chroma = VLC_FOURCC( psz[0], psz[1], psz[2], psz[3] ); /* Find out v4l chroma code */ for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ ) { if( v4lchroma_to_fourcc[i].i_fourcc == i_chroma ) { vid_picture.palette = v4lchroma_to_fourcc[i].i_v4l; break; } } } free( psz ); if( vid_picture.palette && !ioctl( i_fd, VIDIOCSPICT, &vid_picture ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -