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
tags/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; | |||||
| } | |||||