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 | EXTRALIBS+=-lxvidcore | ||||
endif | endif | ||||
ifeq ($(CONFIG_DC1394),yes) | |||||
EXTRALIBS+=-ldc1394_control -lraw1394 | |||||
endif | |||||
ifeq ($(BUILD_VHOOK),yes) | ifeq ($(BUILD_VHOOK),yes) | ||||
VHOOK=videohook | VHOOK=videohook | ||||
INSTALLVHOOK=install-vhook | 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-amr_wb enable amr_wb float audio codec" | ||||
echo " --enable-sunmlib use Sun medialib [default=no]" | echo " --enable-sunmlib use Sun medialib [default=no]" | ||||
echo " --enable-pthreads use pthreads [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 " --enable-gpl allow use of gpl code, the resulting libav* and ffmpeg will be under gpl [default=no]" | ||||
echo "" | echo "" | ||||
echo "Advanced options (experts only):" | echo "Advanced options (experts only):" | ||||
@@ -145,6 +146,7 @@ v4l="yes" | |||||
audio_oss="yes" | audio_oss="yes" | ||||
audio_beos="no" | audio_beos="no" | ||||
dv1394="yes" | dv1394="yes" | ||||
dc1394="no" | |||||
network="yes" | network="yes" | ||||
zlib="yes" | zlib="yes" | ||||
mp3lame="no" | mp3lame="no" | ||||
@@ -418,6 +420,8 @@ for opt do | |||||
;; | ;; | ||||
--enable-xvid) xvid="yes" | --enable-xvid) xvid="yes" | ||||
;; | ;; | ||||
--enable-dc1394) dc1394="yes" | |||||
;; | |||||
--disable-vhook) vhook="no" | --disable-vhook) vhook="no" | ||||
;; | ;; | ||||
--disable-simple_idct) simpleidct="no" | --disable-simple_idct) simpleidct="no" | ||||
@@ -686,6 +690,7 @@ if test "$mingw32" = "yes" ; then | |||||
v4l="no" | v4l="no" | ||||
audio_oss="no" | audio_oss="no" | ||||
dv1394="no" | dv1394="no" | ||||
dc1394="no" | |||||
ffserver="no" | ffserver="no" | ||||
network="no" | network="no" | ||||
LIBPREF="" | LIBPREF="" | ||||
@@ -1261,6 +1266,11 @@ if test "$dv1394" = "yes" ; then | |||||
echo "CONFIG_DV1394=yes" >> config.mak | echo "CONFIG_DV1394=yes" >> config.mak | ||||
fi | fi | ||||
if test "$dc1394" = "yes" ; then | |||||
echo "#define CONFIG_DC1394 1" >> $TMPH | |||||
echo "CONFIG_DC1394=yes" >> config.mak | |||||
fi | |||||
if test "$dlopen" = "yes" ; then | if test "$dlopen" = "yes" ; then | ||||
echo "#define CONFIG_HAVE_DLOPEN 1" >> $TMPH | echo "#define CONFIG_HAVE_DLOPEN 1" >> $TMPH | ||||
fi | 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_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h) | ||||
PIX_FMT_XVMC_MPEG2_IDCT, | PIX_FMT_XVMC_MPEG2_IDCT, | ||||
PIX_FMT_UYVY422, ///< Packed pixel, Cb Y0 Cr Y1 | PIX_FMT_UYVY422, ///< Packed pixel, Cb Y0 Cr Y1 | ||||
PIX_FMT_UYVY411, ///< Packed pixel, Cb Y0 Y1 Cr Y2 Y3 | |||||
PIX_FMT_NB, | PIX_FMT_NB, | ||||
}; | }; | ||||
@@ -227,6 +227,14 @@ static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { | |||||
[PIX_FMT_XVMC_MPEG2_IDCT] = { | [PIX_FMT_XVMC_MPEG2_IDCT] = { | ||||
.name = "xvmcidct", | .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) | 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->data[2] = NULL; | ||||
picture->linesize[0] = width * 2; | picture->linesize[0] = width * 2; | ||||
return size * 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: | case PIX_FMT_GRAY8: | ||||
picture->data[0] = ptr; | picture->data[0] = ptr; | ||||
picture->data[1] = NULL; | 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_RGB565 || | ||||
pix_fmt == PIX_FMT_RGB555) | pix_fmt == PIX_FMT_RGB555) | ||||
w = width * 2; | w = width * 2; | ||||
else if (pix_fmt == PIX_FMT_UYVY411) | |||||
w = width + width/2; | |||||
else if (pix_fmt == PIX_FMT_PAL8) | else if (pix_fmt == PIX_FMT_PAL8) | ||||
w = width; | w = width; | ||||
else | else | ||||
@@ -466,6 +482,9 @@ static int avg_bits_per_pixel(int pix_fmt) | |||||
case PIX_FMT_RGB555: | case PIX_FMT_RGB555: | ||||
bits = 16; | bits = 16; | ||||
break; | break; | ||||
case PIX_FMT_UYVY411: | |||||
bits = 12; | |||||
break; | |||||
default: | default: | ||||
bits = pf->depth * pf->nb_channels; | bits = pf->depth * pf->nb_channels; | ||||
break; | break; | ||||
@@ -579,6 +598,9 @@ void img_copy(AVPicture *dst, const AVPicture *src, | |||||
case PIX_FMT_RGB555: | case PIX_FMT_RGB555: | ||||
bits = 16; | bits = 16; | ||||
break; | break; | ||||
case PIX_FMT_UYVY411: | |||||
bits = 12; | |||||
break; | |||||
default: | default: | ||||
bits = pf->depth * pf->nb_channels; | bits = pf->depth * pf->nb_channels; | ||||
break; | 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 | #define SCALEBITS 10 | ||||
@@ -1777,6 +1833,12 @@ static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = { | |||||
.convert = pal8_to_rgba32 | .convert = pal8_to_rgba32 | ||||
}, | }, | ||||
}, | }, | ||||
[PIX_FMT_UYVY411] = { | |||||
[PIX_FMT_YUV411P] = { | |||||
.convert = uyvy411_to_yuv411p, | |||||
}, | |||||
}, | |||||
}; | }; | ||||
int avpicture_alloc(AVPicture *picture, | int avpicture_alloc(AVPicture *picture, | ||||
@@ -2003,6 +2065,10 @@ int img_convert(AVPicture *dst, int dst_pix_fmt, | |||||
dst_pix_fmt == PIX_FMT_UYVY422) { | dst_pix_fmt == PIX_FMT_UYVY422) { | ||||
/* specific case: convert to YUV422P first */ | /* specific case: convert to YUV422P first */ | ||||
int_pix_fmt = PIX_FMT_YUV422P; | 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 && | } else if ((src_pix->color_type == FF_COLOR_GRAY && | ||||
src_pix_fmt != PIX_FMT_GRAY8) || | src_pix_fmt != PIX_FMT_GRAY8) || | ||||
(dst_pix->color_type == FF_COLOR_GRAY && | (dst_pix->color_type == FF_COLOR_GRAY && | ||||
@@ -159,6 +159,7 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ | |||||
h_align= 16; | h_align= 16; | ||||
break; | break; | ||||
case PIX_FMT_YUV411P: | case PIX_FMT_YUV411P: | ||||
case PIX_FMT_UYVY411: | |||||
w_align=32; | w_align=32; | ||||
h_align=8; | h_align=8; | ||||
break; | break; | ||||
@@ -47,6 +47,10 @@ ifeq ($(CONFIG_DV1394),yes) | |||||
OBJS+= dv1394.o | OBJS+= dv1394.o | ||||
endif | endif | ||||
ifeq ($(CONFIG_DC1394),yes) | |||||
OBJS+= dc1394.o | |||||
endif | |||||
ifeq ($(CONFIG_AUDIO_OSS),yes) | ifeq ($(CONFIG_AUDIO_OSS),yes) | ||||
OBJS+= audio.o | OBJS+= audio.o | ||||
endif | endif | ||||
@@ -102,6 +102,10 @@ void av_register_all(void) | |||||
dv1394_init(); | dv1394_init(); | ||||
#endif | #endif | ||||
#ifdef CONFIG_DC1394 | |||||
dc1394_init(); | |||||
#endif | |||||
nut_init(); | nut_init(); | ||||
matroska_init(); | matroska_init(); | ||||
sol_init(); | sol_init(); | ||||
@@ -616,6 +616,7 @@ int audio_init(void); | |||||
/* DV1394 */ | /* DV1394 */ | ||||
int dv1394_init(void); | int dv1394_init(void); | ||||
int dc1394_init(void); | |||||
#ifdef HAVE_AV_CONFIG_H | #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; | |||||
} |