Main Page | Data Structures | File List | Data Fields | Globals

ieee1394io.c

Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 
00009 #include <unistd.h>
00010 #include <fcntl.h>
00011 
00012 #ifdef LINUX
00013 #include <assert.h>
00014 #include <signal.h>
00015 #include <pthread.h>
00016 
00017 #include <libraw1394/raw1394.h>
00018 #include <libraw1394/csr.h>
00019 #endif /* LINUX */
00020 
00021 #ifdef FREEBSD_5
00022 #include <err.h>
00023 #include <sys/types.h>
00024 #include <sys/socket.h>
00025 #include <netinet/in.h>
00026 #include <errno.h>
00027 #include <sys/time.h>  /* struct timeval, gettimeofday() */
00028 #include <netdb.h>
00029 #include <unistd.h>
00030 
00031 #include <sys/param.h>
00032 #include <sys/ioctl.h>
00033 #include <sys/types.h>
00034 #include <sys/uio.h>
00035 
00036 #if __FreeBSD_version >= 500000
00037 #include <arpa/inet.h>
00038 #endif
00039 
00040 #include <dev/firewire/firewire.h>
00041 #include "iec68113.h"
00042 #endif /* FREEBSD_5 */
00043 
00044 #include "dvsend.h"
00045 
00046 #include "rtp_api.h"
00047 #include "rtp_highlevel.h"
00048   
00049 #define RAW_BUF_SIZE    (10240)
00050 
00051 /* global variables shared with the main thread */
00052 
00053 #ifdef FREEBSD_5
00054 #define DEBUG           0
00055 #define FIX_FRAME       1
00056 
00057 #define PSIZE 512
00058 #define DSIZE 480
00059 #define NCHUNK 8
00060 
00061 #define NPACKET_R 256
00062 #define NPACKET_T 255
00063 
00064 #define NPKT 50
00065 #define NVEC 50
00066 #define BLOCKSIZE 80
00067 
00068 #define TNBUF 100       /* XXX too large value causes block noise */
00069 #define NEMPTY 10       /* depends on TNBUF */
00070 
00071 #define RBUFSIZE (PSIZE * NPACKET_R)
00072 #define MAXBLOCKS (300)
00073 #define CYCLE_FRAC 0xc00
00074 #endif /* FREEBSD_5 */
00075 
00076 #ifdef LINUX
00077 
00078 extern volatile int     g_reader_active;
00079 extern int      g_buffer_underrun;
00080 extern int      g_card;
00081 extern int      g_channel;
00082 extern int      g_testmode;
00083 extern pthread_mutex_t  g_mutex;
00084 
00085 #endif /* LINUX */
00086 
00087 #ifdef FREEBSD_5
00088 char *system_name[] = {"NTSC", "PAL"};
00089 int frame_rate[] = {30, 25};
00090 
00091 unsigned long int SentPackets = 0;
00092 unsigned long int dvdata = 0;
00093 #endif /* FREEBSD_5 */
00094 
00095 int     g_testdata;
00096 unsigned char *g_frame;
00097 
00098 extern char *g_dst_file_name;
00099 extern int g_frame_count;
00100 extern volatile int     g_alldone;
00101 
00102 extern context cid;
00103 extern rtperror status;
00104 
00105 #ifdef LINUX
00106 int raw_iso_handler(raw1394handle_t handle, int channel, size_t length,
00107                     quadlet_t *data)
00108 {
00109         if (length < RAW_BUF_SIZE) {
00110                 *(int*)g_frame = length;
00111                 memcpy(g_frame + 4, data, length);
00112         }
00113         return 0;
00114 }
00115 
00116 
00117 int my_reset_handler(raw1394handle_t handle, unsigned int generation)
00118 {
00119         static int i = 0;
00120 
00121         printf("reset %d\n", i++);
00122         if (i == 100)
00123                 g_reader_active = 0;
00124         return 0;
00125 }
00126 
00127 raw1394handle_t open_1394_driver(int channel, iso_handler_t handler)
00128 {
00129         int numcards;
00130         struct raw1394_portinfo g_pinf[16];
00131         iso_handler_t   g_oldhandler;
00132         raw1394handle_t handle;
00133 
00134         if (!(handle = raw1394_new_handle())) {
00135                 perror("raw1394 - couldn't get handle");
00136                 printf("This error usually means that the ieee1394 driver is not loaded or that /dev/raw1394 does not exist.\n");
00137                 exit( -1);
00138         }
00139 
00140         if ((numcards = raw1394_get_port_info(handle, g_pinf, 16)) < 0) {
00141                 perror("raw1394 - couldn't get card info");
00142                 exit( -1);
00143         }
00144 
00145         if (raw1394_set_port(handle, g_card) < 0) {
00146                 perror("raw1394 - couldn't set port");
00147                 exit( -1);
00148         }
00149 
00150         g_oldhandler = raw1394_set_iso_handler(handle, g_channel, handler);
00151         /*      raw1394_set_tag_handler(handle, my_tag_handler);              */
00152         raw1394_set_bus_reset_handler(handle, my_reset_handler);
00153 
00154         /* Starting iso receive */
00155 
00156         if (raw1394_start_iso_rcv(handle, channel) < 0) {
00157                 perror("raw1394 - couldn't start iso receive");
00158                 exit( -1);
00159         }
00160         return handle;
00161 }
00162 
00163 
00164 void close_1394_driver(int channel, raw1394handle_t handle)
00165 {
00166         raw1394_stop_iso_rcv(handle, channel);
00167         raw1394_destroy_handle(handle);
00168 }
00169 
00170 int capture_raw_linux()
00171 {
00172   int frames_read;
00173   int length;
00174   raw1394handle_t handle;
00175   int found_first_frame;
00176   int skipped = 0;
00177 
00178   g_frame = (unsigned char*)malloc(RAW_BUF_SIZE);
00179 
00180   handle = open_1394_driver(g_channel, raw_iso_handler);
00181 
00182   frames_read = 0;
00183   found_first_frame = 0;
00184 
00185   while (!g_alldone) {
00186     raw1394_loop_iterate(handle);
00187     length = *(int*)g_frame;
00188     if (length >= 492) {
00189       if (!found_first_frame) {
00190         if (g_frame[16] == 0x1f && g_frame[17] == 0x07)
00191           found_first_frame = 1;
00192         else skipped++;
00193       }
00194       if (skipped > 500) {
00195         printf("skipped too many without finding frame\n");
00196         break;
00197       }
00198       if (found_first_frame) {
00199           if (g_frame[16] == 0x1f && g_frame[17] == 0x07)
00200             frames_read++;
00201           if (frames_read > g_frame_count)
00202             break;
00203           if (flags_dump) {
00204           write(dump_fd, (g_frame + 16), 480);
00205           }
00206           status = RTPSend(cid, 3600, 0, 111, (int8*)(g_frame + 16), 480);
00207           if (status != RTP_OK){
00208             fprintf(stderr, "RTPSend: %s\n", RTPStrError(status));
00209           }
00210       }
00211     }
00212   }
00213   close_1394_driver(g_channel, handle);
00214   free(g_frame);
00215 
00216   return 0;
00217 }
00218 #endif /* LINUX */
00219 
00220 
00221 #ifdef FREEBSD_5
00222 int capture_raw_freebsd(int d, char ich)
00223 {
00224         struct fw_isochreq isoreq;
00225         struct fw_isobufreq bufreq;
00226         struct dvdbc *dv;
00227         struct ciphdr *ciph;
00228         struct fw_pkt *pkt;
00229         char *pad, *buf;
00230         u_int32_t *ptr;
00231         int len, tlen, npad, k, m, vec, nb, system = -1 ;
00232         int nblocks[] = {250 /* NTSC */, 300 /* PAL */};
00233         struct iovec wbuf[NPACKET_R];
00234 
00235         int pad_iter, iovec_iter;
00236 
00237 #if 0
00238         int mode;
00239 #endif
00240 
00241         buf = (char *)malloc(RBUFSIZE);
00242         pad = (char *)malloc(DSIZE*MAXBLOCKS);
00243         
00244         /*bzero(pad, BLOCKSIZE*MAXBLOCKS);*/
00245         memset(pad, 0xff, DSIZE*MAXBLOCKS);
00246         bzero(wbuf, sizeof(wbuf));
00247         
00248 #if 0   
00249         if (ioctl(d, FW_SSTDV, &mode) < 0)
00250                 err(1, "ioctl");
00251 #else
00252         bufreq.rx.nchunk = NCHUNK;
00253         bufreq.rx.npacket = NPACKET_R;
00254         bufreq.rx.psize = PSIZE;
00255         bufreq.tx.nchunk = 0;
00256         bufreq.tx.npacket = 0;
00257         bufreq.tx.psize = 0;
00258         if (ioctl(d, FW_SSTBUF, &bufreq) < 0) {
00259                 err(1, "%s", "ioctl");
00260         }
00261 #endif
00262 
00263         isoreq.ch = ich & 0x3f;
00264         isoreq.tag = (ich >> 6) & 3;
00265 
00266         if( ioctl(d, FW_SRSTREAM, &isoreq) < 0)
00267                 err(1, "%s", "ioctl");
00268 
00269         k = m = 0;
00270         while (!g_alldone) {
00271 #if 0
00272                 tlen = 0;
00273                 while ((len = read(d, buf + tlen, PSIZE
00274                                                 /* RBUFSIZE - tlen */)) > 0) {
00275                         if (len < 0) {
00276                                 if (errno == EAGAIN) {
00277                                         fprintf(stderr, "(EAGAIN)\n");
00278                                         fflush(stderr);
00279                                         if (len <= 0)
00280                                                 continue;
00281                                 } else
00282                                         err(1, "read failed");
00283                         }
00284                         tlen += len;
00285                         if ((RBUFSIZE - tlen) < PSIZE)
00286                                 break;
00287                 };
00288 #else
00289                 tlen = len = read(d, buf, RBUFSIZE);
00290                 if (len < 0) {
00291                         if (errno == EAGAIN) {
00292                                 fprintf(stderr, "(EAGAIN)\n");
00293                                 fflush(stderr);
00294                                 if (len <= 0)
00295                                         continue;
00296                         } else
00297                                 err(1, "read failed");
00298                 }
00299 #endif
00300         
00301                 vec = 0;
00302                 /*wbuf[0].iov_len = 0;*/
00303                 ptr = (u_int32_t *) buf;
00304 again:
00305                 pkt = (struct fw_pkt *) ptr;
00306 
00307 #if DEBUG
00308                 printf("%08x %08x %08x %08x\n",
00309                         htonl(ptr[0]), htonl(ptr[1]),
00310                         htonl(ptr[2]), htonl(ptr[3]));
00311 #endif /* DEBUG */
00312 
00313                 ciph = (struct ciphdr *)(ptr + 1);      /* skip iso header */
00314                 if (ciph->fmt != CIP_FMT_DVCR)
00315                         errx(1, "unknown format 0x%x", ciph->fmt);
00316                 ptr = (u_int32_t *) (ciph + 1);         /* skip cip header */
00317 
00318 #if DEBUG
00319                 if (ciph->fdf.dv.cyc != 0xffff && k == 0) { 
00320                         fprintf(stderr, "0x%04x\n", ntohs(ciph->fdf.dv.cyc));
00321                 }
00322 #endif /* DEBUG */
00323 
00324                 if (pkt->mode.stream.len <= sizeof(struct ciphdr)) {
00325                         /* no payload */
00326                         /*
00327                           ptr ++;        
00328                           ptr += ntohs(pkt->mode.stream.len)/sizeof(u_int32_t);
00329                         */
00330                         goto next;
00331                 }
00332                 
00333                 for (dv = (struct dvdbc *)ptr;
00334                                 (char *)dv < (char *)(ptr + ciph->len);
00335                                 dv+=6) {
00336 
00337 #if DEBUG
00338                         printf("(%d,%d) ", dv->sct, dv->dseq);
00339 #endif /* DEBUG */
00340                         if  (dv->sct == DV_SCT_HEADER && dv->dseq == 0) {
00341                                 if (system < 0) {
00342                                         system = ciph->fdf.dv.fs;
00343                                         printf("%s\n", system_name[system]);
00344                                 }
00345 
00346                                 /* Fix DSF bit */
00347                                 if (system == 1 &&
00348                                         (dv->payload[0] & DV_DSF_12) == 0)
00349                                         dv->payload[0] |= DV_DSF_12;
00350                                 nb = nblocks[system];
00351                                 fprintf(stderr, "%d", k%10);
00352 
00353 #if FIX_FRAME
00354                                 if (m > 0 && m != nb) {
00355                                         /* padding bad frame */
00356                                         npad = ((nb - m) % nb);
00357                                         if (npad < 0)
00358                                                 npad += nb;
00359                                         printf("(%d blocks padded)", npad);
00360                                         npad *= DSIZE;
00361                                         wbuf[vec].iov_base = pad;
00362                                         wbuf[vec++].iov_len = npad;
00363 
00364                                         if (flags_dump) {
00365                                           write(dump_fd, pad, npad);
00366                                         }
00367                                         if (vec >= NPACKET_R) {
00368 
00369                                                 printf("Packet length: %d\n", npad*BLOCKSIZE);
00370                                                 for(pad_iter=0; pad_iter < npad; pad_iter++){
00371                                                   status = RTPSend(cid, 3600, 0, 111, pad, BLOCKSIZE);
00372                                                   if (status != RTP_OK){
00373                                                     printf("Padding: RTPSend: %s\n", RTPStrError(status));
00374                                                   }else{
00375                                                     SentPackets++;
00376                                                   }
00377                                                 }
00378                                                 
00379                                                 vec = 0;
00380                                         }
00381                                 }
00382 #endif /* FIX_FRAME */
00383                                 k++;
00384                                 if (k % frame_rate[system] == 0) { /* every second */
00385                                         printf("\n");
00386                                         fflush(stdout);
00387                                 }
00388                                 m = 0;
00389                         }
00390                         
00391                         m++;
00392                         wbuf[vec].iov_base = (char *) dv;
00393                         wbuf[vec++].iov_len = DSIZE;
00394 
00395                         if (vec >= NPACKET_R) {
00396                                 if (flags_dump) {
00397                                   writev(dump_fd, wbuf, vec);
00398                                 }
00399                                 for(iovec_iter=0; iovec_iter < vec; iovec_iter++){
00400                                         status = RTPSend(cid, 3600, 0, 111, wbuf[iovec_iter].iov_base, wbuf[iovec_iter].iov_len);
00401                                         if (status != RTP_OK){
00402                                           printf("RTPSend: %s\t", RTPStrError(status));
00403                                           printf("Packet length: %d\n", wbuf[iovec_iter].iov_len);
00404                                          }else{
00405                                            SentPackets++;
00406                                            dvdata += wbuf[iovec_iter].iov_len;
00407                                          }
00408                                 }
00409 
00410                                 vec = 0;
00411                         }
00412 
00413                 }
00414                 ptr = (u_int32_t *)dv;
00415 next:
00416                 if ((char *)ptr < buf + tlen) {
00417                         goto again;
00418                 }
00419 
00420                 if (vec > 0) {
00421                         if (flags_dump) {
00422                           writev(dump_fd, wbuf, vec+1);
00423                         }
00424                         for(iovec_iter=0; iovec_iter < vec+1; iovec_iter++){
00425                                 status = RTPSend(cid, 3600, 0, 111, wbuf[iovec_iter].iov_base, wbuf[iovec_iter].iov_len);
00426                                 if (status != RTP_OK){
00427                                   printf("RTPSend: %s\t", RTPStrError(status));
00428                                   printf("Packet length: %d\n", wbuf[iovec_iter].iov_len);
00429                                 }else{
00430                                   SentPackets++;
00431                                   dvdata += wbuf[iovec_iter].iov_len;
00432                                 }
00433                         }
00434 
00435                 }
00436         }
00437         printf("\n");
00438         return 0;
00439 }
00440 #endif /* FREEBSD_5 */

Generated on Mon Apr 5 16:35:08 2004 for dvsend by doxygen 1.3.5