v4l.c File Reference

#include "config.h"
#include "libavformat/avformat.h"
#include "libavcodec/dsputil.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <linux/videodev.h>
#include <time.h>

Go to the source code of this file.

Data Structures

struct  VideoData

Defines

#define _LINUX_TIME_H   1

Functions

static int grab_read_header (AVFormatContext *s1, AVFormatParameters *ap)
static int v4l_mm_read_picture (VideoData *s, uint8_t *buf)
static int grab_read_packet (AVFormatContext *s1, AVPacket *pkt)
static int grab_read_close (AVFormatContext *s1)

Variables

struct {
   int   palette
   int   depth
   enum PixelFormat   pix_fmt
video_formats []
AVInputFormat v4l_demuxer


Define Documentation

#define _LINUX_TIME_H   1

Definition at line 30 of file v4l.c.


Function Documentation

static int grab_read_close ( AVFormatContext s1  )  [static]

Definition at line 330 of file v4l.c.

References VideoData::audio_saved, VideoData::fd, VideoData::gb_buffers, s1, VideoData::use_mmap, and VideoData::video_buf.

00331 {
00332     VideoData *s = s1->priv_data;
00333 
00334     if (s->use_mmap)
00335         munmap(s->video_buf, s->gb_buffers.size);
00336 
00337     /* mute audio. we must force it because the BTTV driver does not
00338        return its state correctly */
00339     s->audio_saved.flags |= VIDEO_AUDIO_MUTE;
00340     ioctl(s->fd, VIDIOCSAUDIO, &s->audio_saved);
00341 
00342     close(s->fd);
00343     return 0;
00344 }

static int grab_read_header ( AVFormatContext s1,
AVFormatParameters ap 
) [static]

Definition at line 67 of file v4l.c.

References av_log(), AV_LOG_ERROR, av_new_stream(), av_set_pts_info(), AVERROR, AVRational::den, VideoData::frame_rate, frame_rate, VideoData::frame_rate_base, VideoData::height, AVFormatParameters::height, height, AVRational::num, AVFormatParameters::pix_fmt, s1, AVFormatParameters::time_base, VideoData::video_cap, video_formats, VideoData::width, AVFormatParameters::width, and width.

00068 {
00069     VideoData *s = s1->priv_data;
00070     AVStream *st;
00071     int width, height;
00072     int video_fd, frame_size;
00073     int ret, frame_rate, frame_rate_base;
00074     int desired_palette, desired_depth;
00075     struct video_tuner tuner;
00076     struct video_audio audio;
00077     struct video_picture pict;
00078     int j;
00079     int vformat_num = sizeof(video_formats) / sizeof(video_formats[0]);
00080 
00081     if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
00082         av_log(s1, AV_LOG_ERROR, "Bad capture size (%dx%d) or wrong time base (%d)\n",
00083             ap->width, ap->height, ap->time_base.den);
00084 
00085         return -1;
00086     }
00087 
00088     width = ap->width;
00089     height = ap->height;
00090     frame_rate      = ap->time_base.den;
00091     frame_rate_base = ap->time_base.num;
00092 
00093     if((unsigned)width > 32767 || (unsigned)height > 32767) {
00094         av_log(s1, AV_LOG_ERROR, "Capture size is out of range: %dx%d\n",
00095             width, height);
00096 
00097         return -1;
00098     }
00099 
00100     st = av_new_stream(s1, 0);
00101     if (!st)
00102         return AVERROR(ENOMEM);
00103     av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
00104 
00105     s->width = width;
00106     s->height = height;
00107     s->frame_rate      = frame_rate;
00108     s->frame_rate_base = frame_rate_base;
00109 
00110     video_fd = open(s1->filename, O_RDWR);
00111     if (video_fd < 0) {
00112         av_log(s1, AV_LOG_ERROR, "%s: %s\n", s1->filename, strerror(errno));
00113         goto fail;
00114     }
00115 
00116     if (ioctl(video_fd,VIDIOCGCAP, &s->video_cap) < 0) {
00117         av_log(s1, AV_LOG_ERROR, "VIDIOCGCAP: %s\n", strerror(errno));
00118         goto fail;
00119     }
00120 
00121     if (!(s->video_cap.type & VID_TYPE_CAPTURE)) {
00122         av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not handle capture\n");
00123         goto fail;
00124     }
00125 
00126     desired_palette = -1;
00127     desired_depth = -1;
00128     for (j = 0; j < vformat_num; j++) {
00129         if (ap->pix_fmt == video_formats[j].pix_fmt) {
00130             desired_palette = video_formats[j].palette;
00131             desired_depth = video_formats[j].depth;
00132             break;
00133         }
00134     }
00135 
00136     /* set tv standard */
00137     if (ap->standard && !ioctl(video_fd, VIDIOCGTUNER, &tuner)) {
00138         if (!strcasecmp(ap->standard, "pal"))
00139             tuner.mode = VIDEO_MODE_PAL;
00140         else if (!strcasecmp(ap->standard, "secam"))
00141             tuner.mode = VIDEO_MODE_SECAM;
00142         else
00143             tuner.mode = VIDEO_MODE_NTSC;
00144         ioctl(video_fd, VIDIOCSTUNER, &tuner);
00145     }
00146 
00147     /* unmute audio */
00148     audio.audio = 0;
00149     ioctl(video_fd, VIDIOCGAUDIO, &audio);
00150     memcpy(&s->audio_saved, &audio, sizeof(audio));
00151     audio.flags &= ~VIDEO_AUDIO_MUTE;
00152     ioctl(video_fd, VIDIOCSAUDIO, &audio);
00153 
00154     ioctl(video_fd, VIDIOCGPICT, &pict);
00155 #if 0
00156     printf("v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n",
00157            pict.colour,
00158            pict.hue,
00159            pict.brightness,
00160            pict.contrast,
00161            pict.whiteness);
00162 #endif
00163     /* try to choose a suitable video format */
00164     pict.palette = desired_palette;
00165     pict.depth= desired_depth;
00166     if (desired_palette == -1 || (ret = ioctl(video_fd, VIDIOCSPICT, &pict)) < 0) {
00167         for (j = 0; j < vformat_num; j++) {
00168             pict.palette = video_formats[j].palette;
00169             pict.depth = video_formats[j].depth;
00170             if (-1 != ioctl(video_fd, VIDIOCSPICT, &pict))
00171                 break;
00172         }
00173         if (j >= vformat_num)
00174             goto fail1;
00175     }
00176 
00177     ret = ioctl(video_fd,VIDIOCGMBUF,&s->gb_buffers);
00178     if (ret < 0) {
00179         /* try to use read based access */
00180         struct video_window win;
00181         int val;
00182 
00183         win.x = 0;
00184         win.y = 0;
00185         win.width = width;
00186         win.height = height;
00187         win.chromakey = -1;
00188         win.flags = 0;
00189 
00190         ioctl(video_fd, VIDIOCSWIN, &win);
00191 
00192         s->frame_format = pict.palette;
00193 
00194         val = 1;
00195         ioctl(video_fd, VIDIOCCAPTURE, &val);
00196 
00197         s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base;
00198         s->use_mmap = 0;
00199     } else {
00200         s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0);
00201         if ((unsigned char*)-1 == s->video_buf) {
00202             s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_PRIVATE,video_fd,0);
00203             if ((unsigned char*)-1 == s->video_buf) {
00204                 av_log(s1, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
00205                 goto fail;
00206             }
00207         }
00208         s->gb_frame = 0;
00209         s->time_frame = av_gettime() * s->frame_rate / s->frame_rate_base;
00210 
00211         /* start to grab the first frame */
00212         s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames;
00213         s->gb_buf.height = height;
00214         s->gb_buf.width = width;
00215         s->gb_buf.format = pict.palette;
00216 
00217         ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
00218         if (ret < 0) {
00219             if (errno != EAGAIN) {
00220             fail1:
00221                 av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not support suitable format\n");
00222             } else {
00223                 av_log(s1, AV_LOG_ERROR,"Fatal: grab device does not receive any video signal\n");
00224             }
00225             goto fail;
00226         }
00227         for (j = 1; j < s->gb_buffers.frames; j++) {
00228           s->gb_buf.frame = j;
00229           ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
00230         }
00231         s->frame_format = s->gb_buf.format;
00232         s->use_mmap = 1;
00233     }
00234 
00235     for (j = 0; j < vformat_num; j++) {
00236         if (s->frame_format == video_formats[j].palette) {
00237             frame_size = width * height * video_formats[j].depth / 8;
00238             st->codec->pix_fmt = video_formats[j].pix_fmt;
00239             break;
00240         }
00241     }
00242 
00243     if (j >= vformat_num)
00244         goto fail;
00245 
00246     s->fd = video_fd;
00247     s->frame_size = frame_size;
00248 
00249     st->codec->codec_type = CODEC_TYPE_VIDEO;
00250     st->codec->codec_id = CODEC_ID_RAWVIDEO;
00251     st->codec->width = width;
00252     st->codec->height = height;
00253     st->codec->time_base.den      = frame_rate;
00254     st->codec->time_base.num = frame_rate_base;
00255     st->codec->bit_rate = frame_size * 1/av_q2d(st->codec->time_base) * 8;
00256 
00257     return 0;
00258  fail:
00259     if (video_fd >= 0)
00260         close(video_fd);
00261     return AVERROR(EIO);
00262 }

static int grab_read_packet ( AVFormatContext s1,
AVPacket pkt 
) [static]

Definition at line 290 of file v4l.c.

References av_gettime(), VideoData::frame_rate, VideoData::frame_rate_base, NULL, s1, and VideoData::time_frame.

00291 {
00292     VideoData *s = s1->priv_data;
00293     int64_t curtime, delay;
00294     struct timespec ts;
00295 
00296     /* Calculate the time of the next frame */
00297     s->time_frame += INT64_C(1000000);
00298 
00299     /* wait based on the frame rate */
00300     for(;;) {
00301         curtime = av_gettime();
00302         delay = s->time_frame  * s->frame_rate_base / s->frame_rate - curtime;
00303         if (delay <= 0) {
00304             if (delay < INT64_C(-1000000) * s->frame_rate_base / s->frame_rate) {
00305                 /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */
00306                 s->time_frame += INT64_C(1000000);
00307             }
00308             break;
00309         }
00310         ts.tv_sec = delay / 1000000;
00311         ts.tv_nsec = (delay % 1000000) * 1000;
00312         nanosleep(&ts, NULL);
00313     }
00314 
00315     if (av_new_packet(pkt, s->frame_size) < 0)
00316         return AVERROR(EIO);
00317 
00318     pkt->pts = curtime;
00319 
00320     /* read one frame */
00321     if (s->use_mmap) {
00322         return v4l_mm_read_picture(s, pkt->data);
00323     } else {
00324         if (read(s->fd, pkt->data, pkt->size) != pkt->size)
00325             return AVERROR(EIO);
00326         return s->frame_size;
00327     }
00328 }

static int v4l_mm_read_picture ( VideoData s,
uint8_t *  buf 
) [static]

Definition at line 264 of file v4l.c.

References av_log(), AV_LOG_ERROR, AVERROR, VideoData::fd, VideoData::frame_size, VideoData::gb_buf, VideoData::gb_buffers, VideoData::gb_frame, NULL, and VideoData::video_buf.

00265 {
00266     uint8_t *ptr;
00267 
00268     while (ioctl(s->fd, VIDIOCSYNC, &s->gb_frame) < 0 &&
00269            (errno == EAGAIN || errno == EINTR));
00270 
00271     ptr = s->video_buf + s->gb_buffers.offsets[s->gb_frame];
00272     memcpy(buf, ptr, s->frame_size);
00273 
00274     /* Setup to capture the next frame */
00275     s->gb_buf.frame = s->gb_frame;
00276     if (ioctl(s->fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) {
00277         if (errno == EAGAIN)
00278             av_log(NULL, AV_LOG_ERROR, "Cannot Sync\n");
00279         else
00280             av_log(NULL, AV_LOG_ERROR, "VIDIOCMCAPTURE: %s\n", strerror(errno));
00281         return AVERROR(EIO);
00282     }
00283 
00284     /* This is now the grabbing frame */
00285     s->gb_frame = (s->gb_frame + 1) % s->gb_buffers.frames;
00286 
00287     return s->frame_size;
00288 }


Variable Documentation

int depth

Definition at line 53 of file v4l.c.

Referenced by bmp_decode_frame(), decode_frame(), decode_macroblock(), dvbsub_parse_clut_segment(), encode_frame(), ff_pnm_decode_header(), flic_decode_init(), guess_mv(), pam_encode_frame(), sunrast_decode_frame(), targa_decode_rle(), tta_decode_frame(), and txd_decode_frame().

int palette

Definition at line 52 of file v4l.c.

Referenced by avs_read_packet(), decode_frame(), encode_frame(), get_alpha_info_pal8(), gif_read_image(), pcx_decode_frame(), seqvideo_decode(), set_palette(), and txd_decode_frame().

enum PixelFormat pix_fmt

Definition at line 54 of file v4l.c.

Referenced by dc1394_read_common(), and yuv4_read_header().

AVInputFormat v4l_demuxer

Initial value:

 {
    "video4linux",
    NULL_IF_CONFIG_SMALL("video grab"),
    sizeof(VideoData),
    NULL,
    grab_read_header,
    grab_read_packet,
    grab_read_close,
    .flags = AVFMT_NOFILE,
}

Definition at line 346 of file v4l.c.

struct { ... } video_formats[] [static]

Referenced by grab_read_header().


Generated on Thu Dec 4 09:46:29 2008 for libextractor by  doxygen 1.5.1