From f02be79d61022f399bb08573fd42d068cdf75b7b Mon Sep 17 00:00:00 2001
From: Roman Shaposhnik <roman@shaposhnik.org>
Date: Fri, 22 Oct 2004 02:04:30 +0000
Subject: [PATCH]    * 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
---
 Makefile                 |   4 +
 configure                |  10 ++
 libavcodec/avcodec.h     |   1 +
 libavcodec/imgconvert.c  |  66 +++++++++++++
 libavcodec/utils.c       |   1 +
 libavformat/Makefile     |   4 +
 libavformat/allformats.c |   4 +
 libavformat/avformat.h   |   1 +
 libavformat/dc1394.c     | 197 +++++++++++++++++++++++++++++++++++++++
 9 files changed, 288 insertions(+)
 create mode 100644 libavformat/dc1394.c

diff --git a/Makefile b/Makefile
index 8aaa51b70f7..db8bcea5e4b 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/configure b/configure
index c76695b39f1..664825782fd 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 4919e977abd..88f83b9b273 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -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,
 };
 
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c
index 7bcb8ee23da..040b2c7939c 100644
--- a/libavcodec/imgconvert.c
+++ b/libavcodec/imgconvert.c
@@ -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 &&
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 2d2fc14c0eb..05e63ae7f2d 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -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;
diff --git a/libavformat/Makefile b/libavformat/Makefile
index f8d769f96a4..944a5dd1c29 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -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
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index aae3eb5a89a..d1fc72a9496 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -102,6 +102,10 @@ void av_register_all(void)
     dv1394_init();
 #endif
 
+#ifdef CONFIG_DC1394
+    dc1394_init();
+#endif
+
     nut_init();
     matroska_init();
     sol_init();
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index a17778ea51f..7d51ac425e5 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -616,6 +616,7 @@ int audio_init(void);
 
 /* DV1394 */
 int dv1394_init(void);
+int dc1394_init(void);
 
 #ifdef HAVE_AV_CONFIG_H
 
diff --git a/libavformat/dc1394.c b/libavformat/dc1394.c
new file mode 100644
index 00000000000..2aba671da13
--- /dev/null
+++ b/libavformat/dc1394.c
@@ -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;
+}
-- 
GitLab