/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * dv1394.cc * * Tue Apr 19 12:10:34 CEST 2005 * Copyright 2005 Bent Bisballe * deva@aasimon.org ****************************************************************************/ /* * This file is part of MIaV. * * MIaV is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MIaV 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MIaV; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include "dv1394.h" #ifdef USE_GUI #include "dv.h" #include #include #include #include #include #include #include /** * Callback function for the firewire interface. */ static raw1394_iso_disposition raw_reader(raw1394handle_t handle, unsigned char *data, unsigned int length, unsigned char channel, unsigned char tag, unsigned char sy, unsigned int cycle, unsigned int dropped) { static char *framedata = NULL; // Only process packets with reasonable length. if ( length > 16 ) { unsigned char * p = ( unsigned char* ) & data[ 8 ]; int section_type = p[ 0 ] >> 5; // section type is in bits 5 - 7 int dif_sequence = p[ 1 ] >> 4; // dif sequence number is in bits 4 - 7 int dif_block = p[ 2 ]; if ( section_type == 0 && dif_sequence == 0 ) { if ( framedata != NULL ) { raw1394_set_userdata(handle, (void *)framedata); framedata = NULL; } } if(!framedata) { framedata = (char *)malloc(DVPACKAGE_SIZE); // dvframe.h if(!framedata) { // We're fucked fprintf(stderr, "Framedata allocation error: %s.\n", strerror( errno ) ); fflush(stderr); exit(1); } } switch ( section_type ) { case 0: // 1 Header block // p[3] |= 0x80; // hack to force PAL data memcpy( framedata + dif_sequence * 150 * 80, p, 480 ); break; case 1: // 2 Subcode blocks memcpy( framedata + dif_sequence * 150 * 80 + ( 1 + dif_block ) * 80, p, 480 ); break; case 2: // 3 VAUX blocks memcpy( framedata + dif_sequence * 150 * 80 + ( 3 + dif_block ) * 80, p, 480 ); break; case 3: // 9 Audio blocks interleaved with video memcpy( framedata + dif_sequence * 150 * 80 + ( 6 + dif_block * 16 ) * 80, p, 480 ); break; case 4: // 135 Video blocks interleaved with audio memcpy( framedata + dif_sequence * 150 * 80 + ( 7 + ( dif_block / 15 ) + dif_block ) * 80, p, 480 ); break; default: // we can't handle any other data break; } } return RAW1394_ISO_OK; } dv1394::dv1394(Info *i, int p, int c) { info = i; port = p; channel = c; } dv1394::~dv1394() { // Close firewire connection. if(handle) { raw1394_iso_shutdown(handle); raw1394_destroy_handle(handle); } } bool dv1394::connect() { int n_ports; struct raw1394_portinfo pinf[ 16 ]; // Get handle to firewire channels handle = raw1394_new_handle(); if(!handle) { info->error("raw1394 - failed to get handle: %s.", strerror( errno ) ); return false; } // how many adapters are hooked in? if((n_ports = raw1394_get_port_info(handle, pinf, 16)) < 0 ) { info->error("raw1394 - failed to get port info: %s.", strerror( errno ) ); raw1394_destroy_handle(handle); handle = NULL; return false; } // Tell raw1394 which host adapter to use if(raw1394_set_port(handle, port) < 0 ) { info->error("raw1394 - failed to set port: %s.", strerror( errno ) ); raw1394_destroy_handle(handle); handle = NULL; return false; } int res = raw1394_iso_recv_init(handle, raw_reader, 488, 512, // Wonder what this size should actually be!? channel, RAW1394_DMA_PACKET_PER_BUFFER,//RAW1394_DMA_DEFAULT, -1); if(res == -1) { fprintf(stderr, "Error in raw1394_iso_recv_init: %s\n", strerror(errno)); // exit(1); } raw1394_set_userdata( handle, ( void* ) NULL); res = raw1394_iso_recv_start(handle, -1, -1, 0); if(res == -1) { fprintf(stderr, "Error in raw1394_iso_recv_start: %s\n", strerror(errno)); // exit(1); } return true; } unsigned char *dv1394::readFrame() { // Firewire port not correctly opened. if(!handle) return NULL; unsigned char *ptr; while(1) { raw1394_loop_iterate(handle); ptr = (unsigned char *)raw1394_get_userdata(handle); if(ptr) { raw1394_set_userdata(handle, NULL); break; } } return ptr; } #endif/*USE_GUI*/