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/trunktags/v0.5
@@ -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 | |||
@@ -0,0 +1,197 @@ | |||
/* | |||
* 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; | |||
} |