Commit f02be79d authored by Roman Shaposhnik's avatar Roman Shaposhnik

* Introducing IIDC1394 grabbing interface.

     Use it with -grab dc1394

   * Introducing yet another packed pix_fmt in order to support some of
     the IIDC1394 modes: uyvy411 (Cb Y0 Y1 Cr Y2 Y3).

Originally committed as revision 3621 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 5ba7c3d7
......@@ -63,6 +63,10 @@ ifeq ($(CONFIG_XVID),yes)
EXTRALIBS+=-lxvidcore
endif
ifeq ($(CONFIG_DC1394),yes)
EXTRALIBS+=-ldc1394_control -lraw1394
endif
ifeq ($(BUILD_VHOOK),yes)
VHOOK=videohook
INSTALLVHOOK=install-vhook
......
......@@ -32,6 +32,7 @@ echo " --enable-amr_nb-fixed use fixed point for amr-nb codec"
echo " --enable-amr_wb enable amr_wb float audio codec"
echo " --enable-sunmlib use Sun medialib [default=no]"
echo " --enable-pthreads use pthreads [default=no]"
echo " --enable-dc1394 enable IIDC-1394 grabbing using libdc1394 and libraw1394 [default=no]"
echo " --enable-gpl allow use of gpl code, the resulting libav* and ffmpeg will be under gpl [default=no]"
echo ""
echo "Advanced options (experts only):"
......@@ -145,6 +146,7 @@ v4l="yes"
audio_oss="yes"
audio_beos="no"
dv1394="yes"
dc1394="no"
network="yes"
zlib="yes"
mp3lame="no"
......@@ -418,6 +420,8 @@ for opt do
;;
--enable-xvid) xvid="yes"
;;
--enable-dc1394) dc1394="yes"
;;
--disable-vhook) vhook="no"
;;
--disable-simple_idct) simpleidct="no"
......@@ -686,6 +690,7 @@ if test "$mingw32" = "yes" ; then
v4l="no"
audio_oss="no"
dv1394="no"
dc1394="no"
ffserver="no"
network="no"
LIBPREF=""
......@@ -1261,6 +1266,11 @@ if test "$dv1394" = "yes" ; then
echo "CONFIG_DV1394=yes" >> config.mak
fi
if test "$dc1394" = "yes" ; then
echo "#define CONFIG_DC1394 1" >> $TMPH
echo "CONFIG_DC1394=yes" >> config.mak
fi
if test "$dlopen" = "yes" ; then
echo "#define CONFIG_HAVE_DLOPEN 1" >> $TMPH
fi
......
......@@ -203,6 +203,7 @@ enum PixelFormat {
PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
PIX_FMT_XVMC_MPEG2_IDCT,
PIX_FMT_UYVY422, ///< Packed pixel, Cb Y0 Cr Y1
PIX_FMT_UYVY411, ///< Packed pixel, Cb Y0 Y1 Cr Y2 Y3
PIX_FMT_NB,
};
......
......@@ -227,6 +227,14 @@ static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
[PIX_FMT_XVMC_MPEG2_IDCT] = {
.name = "xvmcidct",
},
[PIX_FMT_UYVY411] = {
.name = "uyvy411",
.nb_channels = 1,
.color_type = FF_COLOR_YUV,
.pixel_type = FF_PIXEL_PACKED,
.depth = 8,
.x_chroma_shift = 2, .y_chroma_shift = 0,
},
};
void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
......@@ -308,6 +316,12 @@ int avpicture_fill(AVPicture *picture, uint8_t *ptr,
picture->data[2] = NULL;
picture->linesize[0] = width * 2;
return size * 2;
case PIX_FMT_UYVY411:
picture->data[0] = ptr;
picture->data[1] = NULL;
picture->data[2] = NULL;
picture->linesize[0] = width + width/2;
return size + size/2;
case PIX_FMT_GRAY8:
picture->data[0] = ptr;
picture->data[1] = NULL;
......@@ -355,6 +369,8 @@ int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height,
pix_fmt == PIX_FMT_RGB565 ||
pix_fmt == PIX_FMT_RGB555)
w = width * 2;
else if (pix_fmt == PIX_FMT_UYVY411)
w = width + width/2;
else if (pix_fmt == PIX_FMT_PAL8)
w = width;
else
......@@ -466,6 +482,9 @@ static int avg_bits_per_pixel(int pix_fmt)
case PIX_FMT_RGB555:
bits = 16;
break;
case PIX_FMT_UYVY411:
bits = 12;
break;
default:
bits = pf->depth * pf->nb_channels;
break;
......@@ -579,6 +598,9 @@ void img_copy(AVPicture *dst, const AVPicture *src,
case PIX_FMT_RGB555:
bits = 16;
break;
case PIX_FMT_UYVY411:
bits = 12;
break;
default:
bits = pf->depth * pf->nb_channels;
break;
......@@ -864,6 +886,40 @@ static void yuv422p_to_uyvy422(AVPicture *dst, const AVPicture *src,
}
}
static void uyvy411_to_yuv411p(AVPicture *dst, const AVPicture *src,
int width, int height)
{
const uint8_t *p, *p1;
uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
int w;
p1 = src->data[0];
lum1 = dst->data[0];
cb1 = dst->data[1];
cr1 = dst->data[2];
for(;height > 0; height--) {
p = p1;
lum = lum1;
cb = cb1;
cr = cr1;
for(w = width; w >= 4; w -= 4) {
cb[0] = p[0];
lum[0] = p[1];
lum[1] = p[2];
cr[0] = p[3];
lum[2] = p[4];
lum[3] = p[5];
p += 6;
lum += 4;
cb++;
cr++;
}
p1 += src->linesize[0];
lum1 += dst->linesize[0];
cb1 += dst->linesize[1];
cr1 += dst->linesize[2];
}
}
#define SCALEBITS 10
......@@ -1777,6 +1833,12 @@ static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
.convert = pal8_to_rgba32
},
},
[PIX_FMT_UYVY411] = {
[PIX_FMT_YUV411P] = {
.convert = uyvy411_to_yuv411p,
},
},
};
int avpicture_alloc(AVPicture *picture,
......@@ -2003,6 +2065,10 @@ int img_convert(AVPicture *dst, int dst_pix_fmt,
dst_pix_fmt == PIX_FMT_UYVY422) {
/* specific case: convert to YUV422P first */
int_pix_fmt = PIX_FMT_YUV422P;
} else if (src_pix_fmt == PIX_FMT_UYVY411 ||
dst_pix_fmt == PIX_FMT_UYVY411) {
/* specific case: convert to YUV411P first */
int_pix_fmt = PIX_FMT_YUV411P;
} else if ((src_pix->color_type == FF_COLOR_GRAY &&
src_pix_fmt != PIX_FMT_GRAY8) ||
(dst_pix->color_type == FF_COLOR_GRAY &&
......
......@@ -159,6 +159,7 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){
h_align= 16;
break;
case PIX_FMT_YUV411P:
case PIX_FMT_UYVY411:
w_align=32;
h_align=8;
break;
......
......@@ -47,6 +47,10 @@ ifeq ($(CONFIG_DV1394),yes)
OBJS+= dv1394.o
endif
ifeq ($(CONFIG_DC1394),yes)
OBJS+= dc1394.o
endif
ifeq ($(CONFIG_AUDIO_OSS),yes)
OBJS+= audio.o
endif
......
......@@ -102,6 +102,10 @@ void av_register_all(void)
dv1394_init();
#endif
#ifdef CONFIG_DC1394
dc1394_init();
#endif
nut_init();
matroska_init();
sol_init();
......
......@@ -616,6 +616,7 @@ int audio_init(void);
/* DV1394 */
int dv1394_init(void);
int dc1394_init(void);
#ifdef HAVE_AV_CONFIG_H
......
/*
* IIDC1394 grab interface (uses libdc1394 and libraw1394)
* Copyright (c) 2004 Roman Shaposhnik
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "avformat.h"
#include <libraw1394/raw1394.h>
#include <libdc1394/dc1394_control.h>
#undef free
typedef struct dc1394_data {
raw1394handle_t handle;
dc1394_cameracapture camera;
int current_frame;
int fps;
AVPacket packet;
} dc1394_data;
struct dc1394_frame_format {
int width;
int height;
enum PixelFormat pix_fmt;
int frame_size_id;
} dc1394_frame_formats[] = {
{ 320, 240, PIX_FMT_UYVY422, MODE_320x240_YUV422 },
{ 640, 480, PIX_FMT_UYVY411, MODE_640x480_YUV411 },
{ 640, 480, PIX_FMT_UYVY422, MODE_640x480_YUV422 },
{ 0, 0, 0, MODE_320x240_YUV422 } /* default -- gotta be the last one */
};
struct dc1394_frame_rate {
int frame_rate;
int frame_rate_id;
} dc1394_frame_rates[] = {
{ 1875, FRAMERATE_1_875 },
{ 3750, FRAMERATE_3_75 },
{ 7500, FRAMERATE_7_5 },
{ 15000, FRAMERATE_15 },
{ 30000, FRAMERATE_30 },
{ 60000, FRAMERATE_60 },
{ 0, FRAMERATE_30 } /* default -- gotta be the last one */
};
static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap)
{
dc1394_data* dc1394 = c->priv_data;
AVStream* vst;
nodeid_t* camera_nodes;
int res;
struct dc1394_frame_format *fmt;
struct dc1394_frame_rate *fps;
for (fmt = dc1394_frame_formats; fmt->width; fmt++)
if (fmt->pix_fmt == ap->pix_fmt && fmt->width == ap->width && fmt->height == ap->height)
break;
for (fps = dc1394_frame_rates; fps->frame_rate; fps++)
if (fps->frame_rate == av_rescale(1000, ap->frame_rate, ap->frame_rate_base))
break;
/* create a video stream */
vst = av_new_stream(c, 0);
if (!vst)
return -1;
av_set_pts_info(vst, 64, 1, 1000);
vst->codec.codec_type = CODEC_TYPE_VIDEO;
vst->codec.codec_id = CODEC_ID_RAWVIDEO;
vst->codec.frame_rate = fps->frame_rate;
vst->codec.frame_rate_base = 1000;
vst->codec.width = fmt->width;
vst->codec.height = fmt->height;
vst->codec.pix_fmt = fmt->pix_fmt;
/* packet init */
av_init_packet(&dc1394->packet);
dc1394->packet.size = avpicture_get_size(fmt->pix_fmt, fmt->width, fmt->height);
dc1394->packet.stream_index = vst->index;
dc1394->packet.flags |= PKT_FLAG_KEY;
dc1394->current_frame = 0;
dc1394->fps = fps->frame_rate;
vst->codec.bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000);
/* Now lets prep the hardware */
dc1394->handle = dc1394_create_handle(0); /* FIXME: gotta have ap->port */
if (!dc1394->handle) {
av_log(c, AV_LOG_ERROR, "Can't aquire dc1394 handle on port %d\n", 0 /* ap->port */);
goto out;
}
camera_nodes = dc1394_get_camera_nodes(dc1394->handle, &res, 1);
if (!camera_nodes || camera_nodes[ap->channel] == DC1394_NO_CAMERA) {
av_log(c, AV_LOG_ERROR, "There's no IIDC camera on the channel %d\n", ap->channel);
goto out_handle;
}
res = dc1394_dma_setup_capture(dc1394->handle, camera_nodes[ap->channel],
0,
FORMAT_VGA_NONCOMPRESSED,
fmt->frame_size_id,
SPEED_400,
fps->frame_rate_id, 8, 1,
ap->device,
&dc1394->camera);
dc1394_free_camera_nodes(camera_nodes);
if (res != DC1394_SUCCESS) {
av_log(c, AV_LOG_ERROR, "Can't prepare camera for the DMA capture\n");
goto out_handle;
}
res = dc1394_start_iso_transmission(dc1394->handle, dc1394->camera.node);
if (res != DC1394_SUCCESS) {
av_log(c, AV_LOG_ERROR, "Can't start isochronous transmission\n");
goto out_handle_dma;
}
return 0;
out_handle_dma:
dc1394_dma_unlisten(dc1394->handle, &dc1394->camera);
dc1394_dma_release_camera(dc1394->handle, &dc1394->camera);
out_handle:
dc1394_destroy_handle(dc1394->handle);
out:
return -1;
}
static int dc1394_read_packet(AVFormatContext *c, AVPacket *pkt)
{
struct dc1394_data *dc1394 = c->priv_data;
int res;
/* discard stale frame */
if (dc1394->current_frame++) {
if (dc1394_dma_done_with_buffer(&dc1394->camera) != DC1394_SUCCESS)
av_log(c, AV_LOG_ERROR, "failed to release %d frame\n", dc1394->current_frame);
}
res = dc1394_dma_single_capture(&dc1394->camera);
if (res == DC1394_SUCCESS) {
dc1394->packet.data = (uint8_t *)(dc1394->camera.capture_buffer);
dc1394->packet.pts = (dc1394->current_frame * 1000000) / dc1394->fps;
res = dc1394->packet.size;
} else {
av_log(c, AV_LOG_ERROR, "DMA capture failed\n");
dc1394->packet.data = NULL;
res = -1;
}
*pkt = dc1394->packet;
return res;
}
static int dc1394_close(AVFormatContext * context)
{
struct dc1394_data *dc1394 = context->priv_data;
dc1394_stop_iso_transmission(dc1394->handle, dc1394->camera.node);
dc1394_dma_unlisten(dc1394->handle, &dc1394->camera);
dc1394_dma_release_camera(dc1394->handle, &dc1394->camera);
dc1394_destroy_handle(dc1394->handle);
return 0;
}
static AVInputFormat dc1394_format = {
.name = "dc1394",
.long_name = "dc1394 A/V grab",
.priv_data_size = sizeof(struct dc1394_data),
.read_header = dc1394_read_header,
.read_packet = dc1394_read_packet,
.read_close = dc1394_close,
.flags = AVFMT_NOFILE
};
int dc1394_init(void)
{
av_register_input_format(&dc1394_format);
return 0;
}
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