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
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>
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
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
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
00069 #define NEMPTY 10
00070
00071 #define RBUFSIZE (PSIZE * NPACKET_R)
00072 #define MAXBLOCKS (300)
00073 #define CYCLE_FRAC 0xc00
00074 #endif
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
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
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
00152 raw1394_set_bus_reset_handler(handle, my_reset_handler);
00153
00154
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
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 , 300 };
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
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 )) > 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
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
00312
00313 ciph = (struct ciphdr *)(ptr + 1);
00314 if (ciph->fmt != CIP_FMT_DVCR)
00315 errx(1, "unknown format 0x%x", ciph->fmt);
00316 ptr = (u_int32_t *) (ciph + 1);
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
00323
00324 if (pkt->mode.stream.len <= sizeof(struct ciphdr)) {
00325
00326
00327
00328
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
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
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
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
00383 k++;
00384 if (k % frame_rate[system] == 0) {
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