#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 |
| 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 }
| 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 |
Initial value:
{
"video4linux",
NULL_IF_CONFIG_SMALL("video grab"),
sizeof(VideoData),
NULL,
grab_read_header,
grab_read_packet,
grab_read_close,
.flags = AVFMT_NOFILE,
}
struct { ... } video_formats[] [static] |
Referenced by grab_read_header().
1.5.1