1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * IIDC1394 grab interface (uses libdc1394 and libraw1394) 3cabdff1aSopenharmony_ci * Copyright (c) 2004 Roman Shaposhnik 4cabdff1aSopenharmony_ci * Copyright (c) 2008 Alessandro Sappia 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <dc1394/dc1394.h> 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 26cabdff1aSopenharmony_ci#include "libavutil/internal.h" 27cabdff1aSopenharmony_ci#include "libavutil/log.h" 28cabdff1aSopenharmony_ci#include "libavutil/mathematics.h" 29cabdff1aSopenharmony_ci#include "libavutil/opt.h" 30cabdff1aSopenharmony_ci#include "libavutil/parseutils.h" 31cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci#include "libavformat/avformat.h" 34cabdff1aSopenharmony_ci#include "libavformat/internal.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_citypedef struct dc1394_data { 37cabdff1aSopenharmony_ci AVClass *class; 38cabdff1aSopenharmony_ci dc1394_t *d; 39cabdff1aSopenharmony_ci dc1394camera_t *camera; 40cabdff1aSopenharmony_ci dc1394video_frame_t *frame; 41cabdff1aSopenharmony_ci int current_frame; 42cabdff1aSopenharmony_ci int frame_rate; /**< frames per 1000 seconds (fps * 1000) */ 43cabdff1aSopenharmony_ci char *video_size; /**< String describing video size, set by a private option. */ 44cabdff1aSopenharmony_ci char *pixel_format; /**< Set by a private option. */ 45cabdff1aSopenharmony_ci char *framerate; /**< Set by a private option. */ 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci int size; 48cabdff1aSopenharmony_ci int stream_index; 49cabdff1aSopenharmony_ci} dc1394_data; 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_cistatic const struct dc1394_frame_format { 52cabdff1aSopenharmony_ci int width; 53cabdff1aSopenharmony_ci int height; 54cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt; 55cabdff1aSopenharmony_ci int frame_size_id; 56cabdff1aSopenharmony_ci} dc1394_frame_formats[] = { 57cabdff1aSopenharmony_ci { 320, 240, AV_PIX_FMT_UYVY422, DC1394_VIDEO_MODE_320x240_YUV422 }, 58cabdff1aSopenharmony_ci { 640, 480, AV_PIX_FMT_GRAY8, DC1394_VIDEO_MODE_640x480_MONO8 }, 59cabdff1aSopenharmony_ci { 640, 480, AV_PIX_FMT_UYYVYY411, DC1394_VIDEO_MODE_640x480_YUV411 }, 60cabdff1aSopenharmony_ci { 640, 480, AV_PIX_FMT_UYVY422, DC1394_VIDEO_MODE_640x480_YUV422 }, 61cabdff1aSopenharmony_ci { 0, 0, 0, 0 } /* gotta be the last one */ 62cabdff1aSopenharmony_ci}; 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_cistatic const struct dc1394_frame_rate { 65cabdff1aSopenharmony_ci int frame_rate; 66cabdff1aSopenharmony_ci int frame_rate_id; 67cabdff1aSopenharmony_ci} dc1394_frame_rates[] = { 68cabdff1aSopenharmony_ci { 1875, DC1394_FRAMERATE_1_875 }, 69cabdff1aSopenharmony_ci { 3750, DC1394_FRAMERATE_3_75 }, 70cabdff1aSopenharmony_ci { 7500, DC1394_FRAMERATE_7_5 }, 71cabdff1aSopenharmony_ci { 15000, DC1394_FRAMERATE_15 }, 72cabdff1aSopenharmony_ci { 30000, DC1394_FRAMERATE_30 }, 73cabdff1aSopenharmony_ci { 60000, DC1394_FRAMERATE_60 }, 74cabdff1aSopenharmony_ci {120000, DC1394_FRAMERATE_120 }, 75cabdff1aSopenharmony_ci {240000, DC1394_FRAMERATE_240 }, 76cabdff1aSopenharmony_ci { 0, 0 } /* gotta be the last one */ 77cabdff1aSopenharmony_ci}; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(dc1394_data, x) 80cabdff1aSopenharmony_ci#define DEC AV_OPT_FLAG_DECODING_PARAM 81cabdff1aSopenharmony_cistatic const AVOption options[] = { 82cabdff1aSopenharmony_ci { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = "qvga"}, 0, 0, DEC }, 83cabdff1aSopenharmony_ci { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = "uyvy422"}, 0, 0, DEC }, 84cabdff1aSopenharmony_ci { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc"}, 0, 0, DEC }, 85cabdff1aSopenharmony_ci { NULL }, 86cabdff1aSopenharmony_ci}; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_cistatic const AVClass libdc1394_class = { 89cabdff1aSopenharmony_ci .class_name = "libdc1394 indev", 90cabdff1aSopenharmony_ci .item_name = av_default_item_name, 91cabdff1aSopenharmony_ci .option = options, 92cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 93cabdff1aSopenharmony_ci .category = AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, 94cabdff1aSopenharmony_ci}; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_cistatic inline int dc1394_read_common(AVFormatContext *c, 98cabdff1aSopenharmony_ci const struct dc1394_frame_format **select_fmt, const struct dc1394_frame_rate **select_fps) 99cabdff1aSopenharmony_ci{ 100cabdff1aSopenharmony_ci dc1394_data* dc1394 = c->priv_data; 101cabdff1aSopenharmony_ci AVStream* vst; 102cabdff1aSopenharmony_ci const struct dc1394_frame_format *fmt; 103cabdff1aSopenharmony_ci const struct dc1394_frame_rate *fps; 104cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt; 105cabdff1aSopenharmony_ci int width, height; 106cabdff1aSopenharmony_ci AVRational framerate; 107cabdff1aSopenharmony_ci int ret = 0; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci if ((pix_fmt = av_get_pix_fmt(dc1394->pixel_format)) == AV_PIX_FMT_NONE) { 110cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "No such pixel format: %s.\n", dc1394->pixel_format); 111cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 112cabdff1aSopenharmony_ci goto out; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci if ((ret = av_parse_video_size(&width, &height, dc1394->video_size)) < 0) { 116cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Could not parse video size '%s'.\n", dc1394->video_size); 117cabdff1aSopenharmony_ci goto out; 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci if ((ret = av_parse_video_rate(&framerate, dc1394->framerate)) < 0) { 120cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", dc1394->framerate); 121cabdff1aSopenharmony_ci goto out; 122cabdff1aSopenharmony_ci } 123cabdff1aSopenharmony_ci dc1394->frame_rate = av_rescale(1000, framerate.num, framerate.den); 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci for (fmt = dc1394_frame_formats; fmt->width; fmt++) 126cabdff1aSopenharmony_ci if (fmt->pix_fmt == pix_fmt && fmt->width == width && fmt->height == height) 127cabdff1aSopenharmony_ci break; 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci for (fps = dc1394_frame_rates; fps->frame_rate; fps++) 130cabdff1aSopenharmony_ci if (fps->frame_rate == dc1394->frame_rate) 131cabdff1aSopenharmony_ci break; 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_ci if (!fps->frame_rate || !fmt->width) { 134cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Can't find matching camera format for %s, %dx%d@%d:1000fps\n", av_get_pix_fmt_name(pix_fmt), 135cabdff1aSopenharmony_ci width, height, dc1394->frame_rate); 136cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 137cabdff1aSopenharmony_ci goto out; 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci /* create a video stream */ 141cabdff1aSopenharmony_ci vst = avformat_new_stream(c, NULL); 142cabdff1aSopenharmony_ci if (!vst) { 143cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 144cabdff1aSopenharmony_ci goto out; 145cabdff1aSopenharmony_ci } 146cabdff1aSopenharmony_ci avpriv_set_pts_info(vst, 64, 1, 1000); 147cabdff1aSopenharmony_ci vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 148cabdff1aSopenharmony_ci vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; 149cabdff1aSopenharmony_ci vst->codecpar->width = fmt->width; 150cabdff1aSopenharmony_ci vst->codecpar->height = fmt->height; 151cabdff1aSopenharmony_ci vst->codecpar->format = fmt->pix_fmt; 152cabdff1aSopenharmony_ci vst->avg_frame_rate = framerate; 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci dc1394->current_frame = 0; 155cabdff1aSopenharmony_ci dc1394->stream_index = vst->index; 156cabdff1aSopenharmony_ci dc1394->size = av_image_get_buffer_size(fmt->pix_fmt, 157cabdff1aSopenharmony_ci fmt->width, fmt->height, 1); 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci vst->codecpar->bit_rate = av_rescale(dc1394->size * 8, 160cabdff1aSopenharmony_ci fps->frame_rate, 1000); 161cabdff1aSopenharmony_ci *select_fps = fps; 162cabdff1aSopenharmony_ci *select_fmt = fmt; 163cabdff1aSopenharmony_ciout: 164cabdff1aSopenharmony_ci return ret; 165cabdff1aSopenharmony_ci} 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_cistatic int dc1394_read_header(AVFormatContext *c) 168cabdff1aSopenharmony_ci{ 169cabdff1aSopenharmony_ci dc1394_data* dc1394 = c->priv_data; 170cabdff1aSopenharmony_ci dc1394camera_list_t *list; 171cabdff1aSopenharmony_ci int res, i; 172cabdff1aSopenharmony_ci const struct dc1394_frame_format *fmt = NULL; 173cabdff1aSopenharmony_ci const struct dc1394_frame_rate *fps = NULL; 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci if (dc1394_read_common(c, &fmt, &fps) != 0) 176cabdff1aSopenharmony_ci return -1; 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci /* Now let us prep the hardware. */ 179cabdff1aSopenharmony_ci dc1394->d = dc1394_new(); 180cabdff1aSopenharmony_ci if (dc1394_camera_enumerate(dc1394->d, &list) != DC1394_SUCCESS || !list) { 181cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Unable to look for an IIDC camera.\n"); 182cabdff1aSopenharmony_ci goto out; 183cabdff1aSopenharmony_ci } 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci if (list->num == 0) { 186cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "No cameras found.\n"); 187cabdff1aSopenharmony_ci dc1394_camera_free_list(list); 188cabdff1aSopenharmony_ci goto out; 189cabdff1aSopenharmony_ci } 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci /* FIXME: To select a specific camera I need to search in list its guid */ 192cabdff1aSopenharmony_ci dc1394->camera = dc1394_camera_new (dc1394->d, list->ids[0].guid); 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci if (!dc1394->camera) { 195cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Unable to open camera with guid 0x%"PRIx64"\n", 196cabdff1aSopenharmony_ci list->ids[0].guid); 197cabdff1aSopenharmony_ci dc1394_camera_free_list(list); 198cabdff1aSopenharmony_ci goto out; 199cabdff1aSopenharmony_ci } 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_ci if (list->num > 1) { 202cabdff1aSopenharmony_ci av_log(c, AV_LOG_INFO, "Working with the first camera found\n"); 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci 205cabdff1aSopenharmony_ci /* Freeing list of cameras */ 206cabdff1aSopenharmony_ci dc1394_camera_free_list (list); 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci /* Select MAX Speed possible from the cam */ 209cabdff1aSopenharmony_ci if (dc1394->camera->bmode_capable>0) { 210cabdff1aSopenharmony_ci dc1394_video_set_operation_mode(dc1394->camera, DC1394_OPERATION_MODE_1394B); 211cabdff1aSopenharmony_ci i = DC1394_ISO_SPEED_800; 212cabdff1aSopenharmony_ci } else { 213cabdff1aSopenharmony_ci i = DC1394_ISO_SPEED_400; 214cabdff1aSopenharmony_ci } 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci for (res = DC1394_FAILURE; i >= DC1394_ISO_SPEED_MIN && res != DC1394_SUCCESS; i--) { 217cabdff1aSopenharmony_ci res=dc1394_video_set_iso_speed(dc1394->camera, i); 218cabdff1aSopenharmony_ci } 219cabdff1aSopenharmony_ci if (res != DC1394_SUCCESS) { 220cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Couldn't set ISO Speed\n"); 221cabdff1aSopenharmony_ci goto out_camera; 222cabdff1aSopenharmony_ci } 223cabdff1aSopenharmony_ci 224cabdff1aSopenharmony_ci if (dc1394_video_set_mode(dc1394->camera, fmt->frame_size_id) != DC1394_SUCCESS) { 225cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Couldn't set video format\n"); 226cabdff1aSopenharmony_ci goto out_camera; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci if (dc1394_video_set_framerate(dc1394->camera,fps->frame_rate_id) != DC1394_SUCCESS) { 230cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Couldn't set framerate %d \n",fps->frame_rate); 231cabdff1aSopenharmony_ci goto out_camera; 232cabdff1aSopenharmony_ci } 233cabdff1aSopenharmony_ci if (dc1394_capture_setup(dc1394->camera, 10, DC1394_CAPTURE_FLAGS_DEFAULT)!=DC1394_SUCCESS) { 234cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Cannot setup camera \n"); 235cabdff1aSopenharmony_ci goto out_camera; 236cabdff1aSopenharmony_ci } 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci if (dc1394_video_set_transmission(dc1394->camera, DC1394_ON) !=DC1394_SUCCESS) { 239cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "Cannot start capture\n"); 240cabdff1aSopenharmony_ci goto out_camera; 241cabdff1aSopenharmony_ci } 242cabdff1aSopenharmony_ci return 0; 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ciout_camera: 245cabdff1aSopenharmony_ci dc1394_capture_stop(dc1394->camera); 246cabdff1aSopenharmony_ci dc1394_video_set_transmission(dc1394->camera, DC1394_OFF); 247cabdff1aSopenharmony_ci dc1394_camera_free (dc1394->camera); 248cabdff1aSopenharmony_ciout: 249cabdff1aSopenharmony_ci dc1394_free(dc1394->d); 250cabdff1aSopenharmony_ci return -1; 251cabdff1aSopenharmony_ci} 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_cistatic int dc1394_read_packet(AVFormatContext *c, AVPacket *pkt) 254cabdff1aSopenharmony_ci{ 255cabdff1aSopenharmony_ci struct dc1394_data *dc1394 = c->priv_data; 256cabdff1aSopenharmony_ci int res; 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci /* discard stale frame */ 259cabdff1aSopenharmony_ci if (dc1394->current_frame++) { 260cabdff1aSopenharmony_ci if (dc1394_capture_enqueue(dc1394->camera, dc1394->frame) != DC1394_SUCCESS) 261cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "failed to release %d frame\n", dc1394->current_frame); 262cabdff1aSopenharmony_ci } 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci res = dc1394_capture_dequeue(dc1394->camera, DC1394_CAPTURE_POLICY_WAIT, &dc1394->frame); 265cabdff1aSopenharmony_ci if (res == DC1394_SUCCESS) { 266cabdff1aSopenharmony_ci pkt->data = (uint8_t *)dc1394->frame->image; 267cabdff1aSopenharmony_ci pkt->size = dc1394->frame->image_bytes; 268cabdff1aSopenharmony_ci pkt->pts = dc1394->current_frame * 1000000 / dc1394->frame_rate; 269cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 270cabdff1aSopenharmony_ci pkt->stream_index = dc1394->stream_index; 271cabdff1aSopenharmony_ci } else { 272cabdff1aSopenharmony_ci av_log(c, AV_LOG_ERROR, "DMA capture failed\n"); 273cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 274cabdff1aSopenharmony_ci } 275cabdff1aSopenharmony_ci 276cabdff1aSopenharmony_ci return pkt->size; 277cabdff1aSopenharmony_ci} 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_cistatic int dc1394_close(AVFormatContext * context) 280cabdff1aSopenharmony_ci{ 281cabdff1aSopenharmony_ci struct dc1394_data *dc1394 = context->priv_data; 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci dc1394_video_set_transmission(dc1394->camera, DC1394_OFF); 284cabdff1aSopenharmony_ci dc1394_capture_stop(dc1394->camera); 285cabdff1aSopenharmony_ci dc1394_camera_free(dc1394->camera); 286cabdff1aSopenharmony_ci dc1394_free(dc1394->d); 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci return 0; 289cabdff1aSopenharmony_ci} 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ciconst AVInputFormat ff_libdc1394_demuxer = { 292cabdff1aSopenharmony_ci .name = "libdc1394", 293cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("dc1394 v.2 A/V grab"), 294cabdff1aSopenharmony_ci .priv_data_size = sizeof(struct dc1394_data), 295cabdff1aSopenharmony_ci .read_header = dc1394_read_header, 296cabdff1aSopenharmony_ci .read_packet = dc1394_read_packet, 297cabdff1aSopenharmony_ci .read_close = dc1394_close, 298cabdff1aSopenharmony_ci .flags = AVFMT_NOFILE, 299cabdff1aSopenharmony_ci .priv_class = &libdc1394_class, 300cabdff1aSopenharmony_ci}; 301