Commit 358f59e8 authored by gpoirier's avatar gpoirier

implement new grabbing interface, as described here:

ttp://thread.gmane.org/gmane.comp.video.ffmpeg.devel/42920
patch by Ramiro Polla % ramiro A lisha P ufsc P br %
Original thread:
Date: Jan 31, 2007 8:56 PM
Subject: [Ffmpeg-devel] [PATCH] New grabbing interface


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@7983 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 39e1ffda
......@@ -26,11 +26,11 @@ video on the fly with a high quality polyphase filter.
@c man begin EXAMPLES
@section Video and Audio grabbing
FFmpeg can use a video4linux compatible video source and any Open Sound
System audio source:
FFmpeg can grab video and audio from devices given that you specify the input
format and device.
@example
ffmpeg /tmp/out.mpg
ffmpeg -f audio_device -i /dev/dsp -f video4linux2 -i /dev/video0 /tmp/out.mpg
@end example
Note that you must activate the right video source and channel before
......@@ -44,14 +44,14 @@ standard mixer.
FFmpeg can grab the X11 display.
@example
ffmpeg -f x11grab -vd x11:0.0 /tmp/out.mpg
ffmpeg -f x11grab -i :0.0 /tmp/out.mpg
@end example
0.0 is display.screen number of your X11 server, same as
the DISPLAY environment variable.
@example
ffmpeg -f x11grab -vd x11:0.0+10,20 /tmp/out.mpg
ffmpeg -f x11grab -i :0.0+10,20 /tmp/out.mpg
@end example
0.0 is display.screen number of your X11 server, same as the DISPLAY environment
......@@ -154,8 +154,6 @@ ffmpeg [[infile options][@option{-i} @var{infile}]]... @{[outfile options] @var{
@c man end
@end example
@c man begin DESCRIPTION
If no input file is given, audio/video grabbing is done.
As a general rule, options are applied to the next specified
file. Therefore, order is important, and you can have the same
option on the command line multiple times. Each occurrence is
......@@ -609,20 +607,12 @@ Set the ISO 639 language code (3 letters) of the current subtitle stream.
@section Audio/Video grab options
@table @option
@item -vd device
sEt video grab device (e.g. @file{/dev/video0}).
@item -vc channel
Set video grab channel (DV1394 only).
@item -tvstd standard
Set television standard (NTSC, PAL (SECAM)).
@item -dv1394
Set DV1394 grab.
@item -ad device
Set audio device (e.g. @file{/dev/dsp}).
@item -grab format
Request grabbing using.
@item -gd device
Set grab device.
@item -isync
Synchronize read on input.
@end table
@section Advanced options
......
......@@ -181,22 +181,9 @@ static int video_global_header = 0;
static int rate_emu = 0;
#ifdef CONFIG_BKTR
static const char *video_grab_format = "bktr";
#else
#ifdef CONFIG_VIDEO4LINUX2
static const char *video_grab_format = "video4linux2";
#else
static const char *video_grab_format = "video4linux";
#endif
#endif
static char *video_device = NULL;
static char *grab_device = NULL;
static int video_channel = 0;
static char *video_standard = "ntsc";
static const char *audio_grab_format = "audio_device";
static char *audio_device = NULL;
static int audio_volume = 256;
static int using_stdin = 0;
......@@ -2357,16 +2344,6 @@ static void opt_audio_channels(const char *arg)
audio_channels = atoi(arg);
}
static void opt_video_device(const char *arg)
{
video_device = av_strdup(arg);
}
static void opt_grab_device(const char *arg)
{
grab_device = av_strdup(arg);
}
static void opt_video_channel(const char *arg)
{
video_channel = strtol(arg, NULL, 0);
......@@ -2377,11 +2354,6 @@ static void opt_video_standard(const char *arg)
video_standard = av_strdup(arg);
}
static void opt_audio_device(const char *arg)
{
audio_device = av_strdup(arg);
}
static void opt_codec(int *pstream_copy, int *pcodec_id,
int codec_type, const char *arg)
{
......@@ -2573,7 +2545,6 @@ static void opt_input_file(const char *filename)
ap->width = frame_width + frame_padleft + frame_padright;
ap->height = frame_height + frame_padtop + frame_padbottom;
ap->pix_fmt = frame_pix_fmt;
ap->device = grab_device;
ap->channel = video_channel;
ap->standard = video_standard;
ap->video_codec_id = video_codec_id;
......@@ -2699,18 +2670,11 @@ static void opt_input_file(const char *filename)
file_iformat = NULL;
file_oformat = NULL;
grab_device = NULL;
video_channel = 0;
rate_emu = 0;
}
static void opt_grab(const char *arg)
{
file_iformat = av_find_input_format(arg);
opt_input_file("");
}
static void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr)
{
int has_video, has_audio, i, j;
......@@ -3179,107 +3143,6 @@ static void opt_output_file(const char *filename)
file_iformat = NULL;
}
/* prepare dummy protocols for grab */
static void prepare_grab(void)
{
int has_video, has_audio, i, j;
AVFormatContext *oc;
AVFormatContext *ic;
AVFormatParameters vp1, *vp = &vp1;
AVFormatParameters ap1, *ap = &ap1;
/* see if audio/video inputs are needed */
has_video = 0;
has_audio = 0;
memset(ap, 0, sizeof(*ap));
memset(vp, 0, sizeof(*vp));
vp->time_base.num= 1;
for(j=0;j<nb_output_files;j++) {
oc = output_files[j];
for(i=0;i<oc->nb_streams;i++) {
AVCodecContext *enc = oc->streams[i]->codec;
switch(enc->codec_type) {
case CODEC_TYPE_AUDIO:
if (enc->sample_rate > ap->sample_rate)
ap->sample_rate = enc->sample_rate;
if (enc->channels > ap->channels)
ap->channels = enc->channels;
has_audio = 1;
break;
case CODEC_TYPE_VIDEO:
if (enc->width > vp->width)
vp->width = enc->width;
if (enc->height > vp->height)
vp->height = enc->height;
if (vp->time_base.num*(int64_t)enc->time_base.den > enc->time_base.num*(int64_t)vp->time_base.den){
vp->time_base = enc->time_base;
vp->width += frame_leftBand + frame_rightBand;
vp->width -= (frame_padleft + frame_padright);
vp->height += frame_topBand + frame_bottomBand;
vp->height -= (frame_padtop + frame_padbottom);
}
has_video = 1;
break;
default:
av_abort();
}
}
}
if (has_video == 0 && has_audio == 0) {
fprintf(stderr, "Output file must have at least one audio or video stream\n");
exit(1);
}
if (has_video) {
AVInputFormat *fmt1;
#warning FIXME: find a better interface
if(video_device&&!strncmp(video_device,"x11:",4)) {
video_grab_format="x11grab";
}
fmt1 = av_find_input_format(video_grab_format);
vp->device = video_device;
vp->channel = video_channel;
vp->standard = video_standard;
vp->pix_fmt = frame_pix_fmt;
if (av_open_input_file(&ic, "", fmt1, 0, vp) < 0) {
fprintf(stderr, "Could not find video grab device\n");
exit(1);
}
/* If not enough info to get the stream parameters, we decode the
first frames to get it. */
if ((ic->ctx_flags & AVFMTCTX_NOHEADER) && av_find_stream_info(ic) < 0) {
fprintf(stderr, "Could not find video grab parameters\n");
exit(1);
}
/* by now video grab has one stream */
ic->streams[0]->r_frame_rate.num = vp->time_base.den;
ic->streams[0]->r_frame_rate.den = vp->time_base.num;
input_files[nb_input_files] = ic;
if (verbose >= 0)
dump_format(ic, nb_input_files, "", 0);
nb_input_files++;
}
if (has_audio && audio_grab_format) {
AVInputFormat *fmt1;
fmt1 = av_find_input_format(audio_grab_format);
ap->device = audio_device;
if (av_open_input_file(&ic, "", fmt1, 0, ap) < 0) {
fprintf(stderr, "Could not find audio grab device\n");
exit(1);
}
input_files[nb_input_files] = ic;
if (verbose >= 0)
dump_format(ic, nb_input_files, "", 0);
nb_input_files++;
}
}
/* same option as mencoder */
static void opt_pass(const char *pass_str)
{
......@@ -3789,14 +3652,9 @@ const OptionDef options[] = {
{ "slang", HAS_ARG | OPT_STRING | OPT_SUBTITLE, {(void *)&subtitle_language}, "set the ISO 639 language code (3 letters) of the current subtitle stream" , "code" },
/* grab options */
{ "vd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_device}, "set video grab device", "device" },
{ "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" },
{ "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "set television standard (NTSC, PAL (SECAM))", "standard" },
{ "ad", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_GRAB, {(void*)opt_audio_device}, "set audio device", "device" },
/* G.2 grab options */
{ "grab", HAS_ARG | OPT_EXPERT | OPT_GRAB, {(void*)opt_grab}, "request grabbing using", "format" },
{ "gd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_grab_device}, "set grab device", "device" },
{ "isync", OPT_BOOL | OPT_EXPERT | OPT_GRAB, {(void*)&input_sync}, "sync read on input", "" },
/* muxer options */
{ "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_max_delay}, "set the maximum demux-decode delay", "seconds" },
......@@ -3928,8 +3786,8 @@ int main(int argc, char **argv)
}
if (nb_input_files == 0) {
input_sync = 1;
prepare_grab();
fprintf(stderr, "Must supply at least one input file\n");
exit(1);
}
ti = getutime();
......
......@@ -53,14 +53,6 @@ static int audio_open(AudioData *s, int is_output, const char *audio_device)
int tmp, err;
char *flip = getenv("AUDIO_FLIP_LEFT");
/* open linux audio device */
if (!audio_device)
#ifdef __OpenBSD__
audio_device = "/dev/sound";
#else
audio_device = "/dev/dsp";
#endif
if (is_output)
audio_fd = open(audio_device, O_WRONLY);
else
......@@ -229,7 +221,7 @@ static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
s->sample_rate = ap->sample_rate;
s->channels = ap->channels;
ret = audio_open(s, 0, ap->device);
ret = audio_open(s, 0, s1->filename);
if (ret < 0) {
av_free(st);
return AVERROR_IO;
......
......@@ -117,7 +117,9 @@ typedef struct AVFormatParameters {
int height;
enum PixelFormat pix_fmt;
int channel; /* used to select dv channel */
#if LIBAVFORMAT_VERSION_INT < (52<<16)
const char *device; /* video, audio or DV device */
#endif
const char *standard; /* tv standard, NTSC, PAL, SECAM */
int mpeg2ts_raw:1; /* force raw MPEG2 transport stream output, if possible */
int mpeg2ts_compute_pcr:1; /* compute exact PCR for each transport
......
......@@ -361,7 +361,7 @@ static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
s->sample_rate = ap->sample_rate;
s->channels = ap->channels;
ret = audio_open(s, 0, ap->device);
ret = audio_open(s, 0, s1->filename);
if (ret < 0) {
av_free(st);
return AVERROR(EIO);
......
......@@ -118,7 +118,7 @@ static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap)
fmt->frame_size_id,
SPEED_400,
fps->frame_rate_id, 8, 1,
ap->device,
c->filename,
&dc1394->camera);
dc1394_free_camera_nodes(camera_nodes);
if (res != DC1394_SUCCESS) {
......
......@@ -83,7 +83,6 @@ static int dv1394_start(struct dv1394_data *dv)
static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap)
{
struct dv1394_data *dv = context->priv_data;
const char *video_device;
dv->dv_demux = dv_init_demux(context);
if (!dv->dv_demux)
......@@ -100,10 +99,7 @@ static int dv1394_read_header(AVFormatContext * context, AVFormatParameters * ap
dv->channel = DV1394_DEFAULT_CHANNEL;
/* Open and initialize DV1394 device */
video_device = ap->device;
if (!video_device)
video_device = "/dev/dv1394/0";
dv->fd = open(video_device, O_RDONLY);
dv->fd = open(context->filename, O_RDONLY);
if (dv->fd < 0) {
perror("Failed to open DV interface");
goto failed;
......
......@@ -68,7 +68,6 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
struct video_tuner tuner;
struct video_audio audio;
struct video_picture pict;
const char *video_device;
int j;
if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
......@@ -100,12 +99,9 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
s->frame_rate = frame_rate;
s->frame_rate_base = frame_rate_base;
video_device = ap->device;
if (!video_device)
video_device = "/dev/video";
video_fd = open(video_device, O_RDWR);
video_fd = open(s1->filename, O_RDWR);
if (video_fd < 0) {
perror(video_device);
perror(s1->filename);
goto fail;
}
......
......@@ -243,7 +243,6 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
int frame_rate;
int frame_rate_base;
int format = -1;
const char *video_device;
if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0)
return -1;
......@@ -253,10 +252,6 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
frame_rate = ap->time_base.den;
frame_rate_base = ap->time_base.num;
video_device = ap->device;
if (!video_device)
video_device = "/dev/bktr0";
st = av_new_stream(s1, 0);
if (!st)
return AVERROR(ENOMEM);
......@@ -285,7 +280,7 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
format = NTSC;
}
if (bktr_init(video_device, width, height, format,
if (bktr_init(s1->filename, width, height, format,
&(s->video_fd), &(s->tuner_fd), -1, 0.0) < 0)
return AVERROR(EIO);
......
......@@ -114,16 +114,16 @@ static struct fmt_map fmt_conversion_table[] = {
},
};
static int device_open(AVFormatContext *ctx, const char *devname, uint32_t *capabilities)
static int device_open(AVFormatContext *ctx, uint32_t *capabilities)
{
struct v4l2_capability cap;
int fd;
int res;
fd = open(devname, O_RDWR /*| O_NONBLOCK*/, 0);
fd = open(ctx->filename, O_RDWR /*| O_NONBLOCK*/, 0);
if (fd < 0) {
av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n",
devname, strerror(errno));
ctx->filename, strerror(errno));
return -1;
}
......@@ -429,7 +429,6 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
int width, height;
int res, frame_rate, frame_rate_base;
uint32_t desired_format, capabilities;
const char *video_device;
if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) {
av_log(s1, AV_LOG_ERROR, "Missing/Wrong parameters\n");
......@@ -459,12 +458,8 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap)
s->frame_rate = frame_rate;
s->frame_rate_base = frame_rate_base;
video_device = ap->device;
if (!video_device) {
video_device = "/dev/video";
}
capabilities = 0;
s->fd = device_open(s1, video_device, &capabilities);
s->fd = device_open(s1, &capabilities);
if (s->fd < 0) {
av_free(st);
......
......@@ -97,25 +97,14 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
int use_shm;
char *param, *offset;
if (!ap->device) {
av_log(s1, AV_LOG_ERROR, "AVParameters don't specify any device. Use -vd.\n");
return AVERROR_IO;
}
param = strchr(ap->device, ':');
if (!param) {
av_free(st);
return AVERROR_IO;
}
param = av_strdup(param);
param = av_strdup(s1->filename);
offset = strchr(param, '+');
if (offset) {
sscanf(offset, "%d,%d", &x_off, &y_off);
*offset= 0;
}
av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", ap->device, param, x_off, y_off, ap->width, ap->height);
av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", s1->filename, param, x_off, y_off, ap->width, ap->height);
dpy = XOpenDisplay(param);
if(!dpy) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment