00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
#ifdef HAVE_CONFIG_H
00034
#include <config.h>
00035
#endif
00036
00037
#include <stdio.h>
00038
#include <string.h>
00039
#include <stdlib.h>
00040
#include <unistd.h>
00041
#include <sys/time.h>
00042
#include <signal.h>
00043
#include <sys/socket.h>
00044
#include <sys/shm.h>
00045
#include <assert.h>
00046
00047
#include <sys/types.h>
00048
#include <sys/stat.h>
00049
#include <fcntl.h>
00050
#include <unistd.h>
00051
00052
#include <pthread.h>
00053
00054
#ifdef LINUX
00055
#include <getopt.h>
00056
#endif
00057
00058
#include <libdv/dv.h>
00059
00060
#include <xdvshow-info.h>
00061
00062
#if (HAVE_SDL || HAVE_SDL11)
00063
#include <xdvshow-sdl.h>
00064
#endif
00065
00066
#include <xdvshow-x11.h>
00067
00068
#include "xdvshow-shm.h"
00069
#include "xdvshow-rtp.h"
00070
#include "xdvshow-file.h"
00071
#include "xdvshow-ieee1394.h"
00072
#include "xdvshow-audio.h"
00073
#include "xdvshow-flags.h"
00074
#include "xdvshow-const.h"
00075
#include "xdvshow-defs.h"
00076
00077 int flags_stereo = 0;
00078 int flags_fulscreen = 0;
00079
#if (HAVE_SDL || HAVE_SDL11)
00080
int flags_sdl = 1;
00081
int flags_x11 = 0;
00082
#else
00083 int flags_sdl = 0;
00084 int flags_x11 = 1;
00085
#endif
00086 int fags_sdlnooverlay = 0;
00087 int flags_file = 0;
00088 int flags_zoom = 0;
00089 int flags_scale = 0;
00090 int flags_dump = 0;
00091 int flags_deinterlace = 0;
00092 int flags_reflector = 0;
00093 int flags_use_audio = 0;
00094
00095 int flags_format_wide = 0;
00096 int flags_format_normal = 0;
00097
00098 u_int32_t
flags = 0x0;
00099 u_int32_t
dv_format_type = e_dv_system_625_50;
00100 int (*input_func) __P((u_char **));
00101
int (*input_unlock_func) __P(());
00102
00103
int (*audio_input_func) __P((u_char **));
00104
int (*audio_unlock_func) __P(());
00105
00106 char *prog_name = XDVSHOW_PROGNAME;
00107
00108
void *video_thread_func __P((
void *));
00109
void *audio_thread_func __P((
void *));
00110
00111 u_char *videodata;
00112
00113 u_char *audioframe;
00114 int16_t *audio_buffers[4];
00115
00116
00117 struct
xdvshow_rtp_param rtp_param;
00118
00119 int dump_fd;
00120 char *reflector_address;
00121
00122 struct timeval currtime;
00123 long frametime_usec;
00124 long frametimeadd_usec = 27000;
00125 long framedelay_usec;
00126
00127 dv_decoder_t *dv_dec;
00128
00129 pthread_t read_thread;
00130 pthread_t ping_thread;
00131 pthread_t video_thread;
00132
00142 static
void
00143 sigint_signal(
int signo) {
00144
00145
void *thread_result;
00146
int ret;
00147
00148 assert(signo == SIGINT);
00149
00150
DPRINT_BARE(
"\n");
00151
DPRINT(
"Entering SIGINT handling.\n");
00152
00153
if (
flags_reflector) {
00154
DPRINT(
"Waiting for ping thread to finish.\n");
00155 ret = pthread_join(
ping_thread, &thread_result);
00156
if (ret < 0) {
00157 perror(
"ping_thread join failed");
00158 }
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
DPRINT(
"Waiting for video thread to finish.\n");
00176
00177
00178
00179
if (
video_thread) {
00180
#ifndef FREEBSD_5
00181
pthread_cancel(
video_thread);
00182
#endif
00183 ret = pthread_join(
video_thread, &thread_result);
00184
if (ret < 0) {
00185 perror(
"video_thread join failed");
00186 }
00187 }
else {
00188
DPRINT(
"No video thread initialized.\n");
00189 }
00190
00191
00192
DPRINT(
"Waiting for read thread to finish.\n");
00193
00194
00195
00196
#ifdef LINUX26
00197
pthread_cancel(
read_thread);
00198
#endif
00199 pthread_kill(
read_thread, SIGTERM);
00200 ret = pthread_join(
read_thread, &thread_result);
00201
if (ret < 0) {
00202 perror(
"read_thread join failed");
00203 }
00204
00205
if (
flags_dump) {
00206
DPRINT(
"Closing dump file.\n");
00207 close(
dump_fd);
00208 }
00209
00210
#if (HAVE_SDL || HAVE_SDL11)
00211
if (
flags_sdl != 0) {
00212
DPRINT(
"Closing SDL.\n");
00213
xdvshow_close_window();
00214 }
00215
#endif
00216
if (
flags_x11 != 0) {
00217
DPRINT(
"Closing X11.\n");
00218
xdvshow_x11_close_window();
00219 }
00220
00221
DPRINT(
"Freeing memory.\n");
00222 dv_decoder_free(
dv_dec);
00223
00224
if(shmdt(
_xdvshow_shm.
shm_buf) != 0) {
00225 perror(
"shmdt on _xdvshow_shm.shm_buf");
00226 }
00227
if (shmctl(
_xdvshow_shm.
shmid, IPC_RMID, NULL) != 0) {
00228 perror(
"shmctl on _xdvshow_shm.shmid");
00229 }
00230
00231 printf(
"Exit\n");
00232 exit (EXIT_SUCCESS);
00233 }
00234
00243
int
00244 main(
int argc,
char *argv[])
00245 {
00246
int ret;
00247
00248 u_char *dvframe;
00249
00250 pthread_attr_t bigstack;
00251
00252
int i;
00253
00254
char *audio_dev = NULL;
00255
00256
extern char *optarg;
00257
int op;
00258
00259
void *open_option = NULL;
00260
00261
void * (*input_open)
__P((
void *));
00262
00263 void (*input_close)
__P((
void));
00264
00265 memset(&
rtp_param, 0,
sizeof(
rtp_param));
00266
00267
dv_dec = dv_decoder_new(FALSE, FALSE, FALSE);
00268
if (
dv_dec == NULL) {
00269 fprintf(stderr,
"ERROR : dv_decoder_new\n");
00270
return(EXIT_FAILURE);
00271 }
00272
00273
dv_dec->quality = DV_QUALITY_BEST;
00274
00275 input_open =
xdvshow_prepare_rtp;
00276 input_func =
xdvshow_read_shm;
00277 input_unlock_func =
xdvshow_read_unlock;
00278 audio_input_func =
xdvshow_read_audio_shm;
00279 audio_unlock_func =
xdvshow_read_audio_unlock;
00280 input_close =
xdvshow_close_shm;
00281 open_option = &
rtp_param;
00282
00283
rtp_param.
s_addr.ss_family = (sa_family_t) AF_INET;
00284
rtp_param.
port = 12000;
00285
00286
while ((op = getopt(argc, argv,
"A:vhf:46P:j:r:odDFzZSixs")) > 0) {
00287
switch (op) {
00288
case 'v':
00289
show_version();
00290 exit(EXIT_SUCCESS);
00291
00292
case 'f':
00293 input_open =
xdvshow_prepare_file;
00294 input_func =
xdvshow_read_shm;
00295 audio_input_func =
xdvshow_read_audio_shm;
00296 input_close =
xdvshow_close_file;
00297 open_option = optarg;
00298
flags_file = 1;
00299
break;
00300
00301
case '4':
00302
rtp_param.
s_addr.ss_family = (sa_family_t) AF_INET;
00303
break;
00304
00305
#ifdef ENABLE_INET6
00306
case '6':
00307
rtp_param.
s_addr.ss_family = (sa_family_t) AF_INET6;
00308
break;
00309
#endif
00310
00311
case 'P':
00312
rtp_param.
port = atoi(optarg);
00313 printf(
"Port: %d\n",
rtp_param.
port);
00314
if (
rtp_param.
port < 1) {
00315 printf(
"Invalid port number : %d\n",
rtp_param.
port);
00316
return(EXIT_FAILURE);
00317 }
00318
break;
00319
00320
case 'j':
00321
rtp_param.
multi_addr_str = optarg;
00322
break;
00323
00324
case 'A':
00325
flags_use_audio = 1;
00326 audio_dev = optarg;
00327
break;
00328
00329
case 'r':
00330
flags_reflector = 1;
00331
reflector_address = optarg;
00332
break;
00333
00334
case 'z':
00335
if (
flags_stereo == 0) {
00336
flags_zoom = 1;
00337 }
else {
00338 printf(
"Zoom not enabled with stereo flag.\n");
00339 }
00340
break;
00341
00342
case 'Z':
00343
flags_scale = 1;
00344
break;
00345
00346
case 'S':
00347
flags_stereo = 1;
00348
if (
flags_zoom != 0) {
00349
flags_zoom = 0;
00350 printf(
"Zoom not enabled with stereo flag.\n");
00351 }
00352
break;
00353
00354
case 'F':
00355
flags_fullscreen = 1;
00356
break;
00357
00358
#if (LINUX && HAVE_LIBRAW1394) || FREEBSD_5
00359
case 'i':
00360 input_open =
xdvshow_capture_raw;
00361 input_func =
xdvshow_read_shm;
00362 audio_input_func =
xdvshow_read_audio_shm;
00363 input_close = NULL;
00364 open_option = NULL;
00365
break;
00366
#endif
00367
00368
#if (HAVE_SDL || HAVE_SDL11)
00369
case 's':
00370
flags_sdl = 1;
00371
flags_x11 = 0;
00372
break;
00373
00374
case 'o':
00375
flags_sdlnooverlay = 1;
00376
break;
00377
#endif
00378
00379
case 'x':
00380
flags_x11 = 1;
00381
flags_sdl = 0;
00382
flags_fullscreen = 0;
00383
break;
00384
00385
case 'd':
00386
flags_dump = 1;
00387
#ifdef __USE_LARGEFILES64
00388
dump_fd = open(
"dump.dv", O_RDWR | O_CREAT | O_LARGEFILE, 00644);
00389
#else
00390
dump_fd = open(
"dump.dv", O_RDWR | O_CREAT, 00644);
00391
#endif
00392
00393
if (
dump_fd < 0) {
00394 perror(
"open dump.dv");
00395
flags_dump = 0;
00396 }
00397
break;
00398
00399
case 'D':
00400
flags_deinterlace = 1;
00401
break;
00402
00403
case 'h':
00404
default:
00405
show_usage(argv[0]);
00406
return(EXIT_FAILURE);
00407
break;
00408
00409 }
00410 }
00411
00412
if (signal(SIGINT,
sigint_signal) == SIG_ERR) {
00413 fprintf(stderr,
"Cannot install signal handler.\n");
00414 }
00415
00416
#ifdef DEBUG
00417
if (
flags_file) {
00418 gettimeofday(&
currtime, NULL);
00419
DPRINT(
"Start: %ld : %ld\n",
currtime.tv_sec,
currtime.tv_usec);
00420 }
00421
#endif
00422
00423
if (
flags_file){
00424 gettimeofday(&
currtime, NULL);
00425
frametime_usec =
currtime.tv_usec +
frametimeadd_usec;
00426 }
00427
00428
if (
flags_reflector) {
00429 memset(&
ping_thread, 0,
sizeof(
ping_thread));
00430
if((ret = pthread_create(&
ping_thread, NULL,
xdvshow_ping_reflector, (
void *)
reflector_address))) {
00431 perror(
"ping thread creation");
00432 assert(ret==0);
00433 }
00434 }
00435
00436 pthread_attr_init(&bigstack);
00437 pthread_attr_setstacksize(&bigstack, (size_t)
THREAD_STACKSIZE);
00438
00439
00440
if(
xdvshow_semaphore_init() != 0) {
00441 perror(
"Failed to initialize semaphores!");
00442 dv_decoder_free(
dv_dec);
00443
00444 exit(EXIT_FAILURE);
00445 }
00446
00447 memset(&
read_thread, 0,
sizeof(
read_thread));
00448
if (input_open ==
xdvshow_prepare_rtp) {
00449
if ((ret = pthread_create(&
read_thread, &bigstack,
xdvshow_prepare_rtp, (
void *)open_option))) {
00450 perror(
"xdvshow_prepare_rtp thread creation");
00451 assert(ret==0);
00452 }
00453 }
00454 pthread_attr_destroy(&bigstack);
00455
if (input_open ==
xdvshow_prepare_file) {
00456
if((ret = pthread_create(&
read_thread, NULL,
xdvshow_prepare_file, (
void *)open_option))) {
00457 perror(
"xdvshow_prepare_file thread creation");
00458 assert(ret==0);
00459 }
00460 }
00461
if (input_open ==
xdvshow_capture_raw) {
00462
if((ret = pthread_create(&
read_thread, NULL,
xdvshow_capture_raw, (
void *)open_option))) {
00463 perror(
"xdvshow_capture_raw thread creation");
00464 assert(ret==0);
00465 }
00466 }
00467
00468
DPRINT(
"Read thread started\n");
00469
00470
while ((
flags_format_normal == 0) && (
flags_format_wide == 0)) {
00471
00472
DPRINT(
"Reading DV frames for 16:9/4:3 detection.\n");
00473 ret = (*input_func)(&dvframe);
00474
if (ret < 0) {
00475 kill(getpid(), SIGINT);
00476
return(EXIT_FAILURE);
00477 }
00478
00479
DPRINT(
"Detecting 16:9/4:3 formats.\n");
00480
00481 dv_parse_header(
dv_dec, dvframe);
00482
00483
if (dv_format_wide(
dv_dec)) {
00484
flags_format_normal = 1;
00485 fprintf (stderr,
"Detected 16:9 format\n");
00486 }
00487
if (dv_format_normal(
dv_dec)) {
00488
flags_format_wide = 1;
00489 fprintf (stderr,
"Detected 4:3 format\n");
00490 }
00491
00492 fprintf(stderr,
"Audio is %.1f kHz, %d bits quantization, %d channels, emphasis %s\n",
00493 (
float)
dv_dec->audio->frequency / 1000.0,
00494
dv_dec->audio->quantization,
00495
dv_dec->audio->num_channels,
00496 (
dv_dec->audio->emphasis ?
"on" :
"off"));
00497
00498
if ((
flags_format_normal != 0) && (
flags_format_wide != 0)) {
00499 fprintf (stderr,
"Error detecting 16:9/4:3 video format. Trying again...\n");
00500
flags_format_normal = 0;
00501
flags_format_wide = 0;
00502 }
00503
00504
if (input_unlock_func) {
00505 (*input_unlock_func)();
00506 }
00507 }
00508
00509
dv_format_type =
dv_dec->system;
00510
switch (
dv_format_type) {
00511
case e_dv_system_525_60:
00512 fprintf (stderr,
"Detected NTSC format\n");
00513
break;
00514
case e_dv_system_625_50:
00515 fprintf (stderr,
"Detected PAL format\n");
00516
break;
00517
default:
00518 fprintf (stderr,
"Error detecting NTSC/PAL format...\n");
00519 }
00520
00521
00522
if (
flags_use_audio) {
00523
00524 ret =
xdvshow_init_audio(audio_dev,
dv_dec->audio);
00525
if (ret < 0) {
00526 fprintf(stderr,
"Audio init failed. Audio disabled.\n");
00527
flags_use_audio = 0;
00528
00529
goto audio_init_failed;
00530 }
00531
00532
for (i = 0; i < 4; i++) {
00533
audio_buffers[i] = malloc(DV_AUDIO_MAX_SAMPLES *
sizeof(u_int16_t));
00534
00535
if (
audio_buffers[i] == NULL) {
00536 fprintf(stderr,
"Failed to init audio.\n");
00537
flags_use_audio = 0;
00538 }
00539
else if (memset (
audio_buffers[i], 0, DV_AUDIO_MAX_SAMPLES *
sizeof(u_int16_t)) == NULL) {
00540 perror(
"memset of audio_buffers[i] failed");
00541 assert(0);
00542 }
00543 }
00544 }
00545
00546 audio_init_failed:
00547
00548
if(memset(&
video_thread, 0,
sizeof(
video_thread)) == NULL) {
00549 perror(
"memset of video_thread failed");
00550 assert(0);
00551 }
00552 ret = pthread_create(&
video_thread, NULL,
video_thread_func, (
void *)
dv_dec);
00553
if(ret != 0) {
00554 perror(
"video_thread creation failed");
00555 }
00556
00557
audio_thread_func((
void *)
dv_dec);
00558
00559 kill(getpid(), SIGINT);
00560
00561
return(EXIT_SUCCESS);
00562 }
00573
void *
00574 video_thread_func(
void *data)
00575 {
00576
int ret = 0;
00577
00578 dv_decoder_t *
dv_dec = NULL;
00579
00580
struct x_params param;
00581
00582 memset(¶m, 0,
sizeof(param));
00583
00584
dv_dec = (dv_decoder_t *)data;
00585
00586 param.dv_format_type =
dv_format_type;
00587
00588
#if (HAVE_SDL || HAVE_SDL11)
00589
if (
flags_sdl) {
00590 ret =
xdvshow_open_window(
prog_name, ¶m);
00591 }
00592
#endif
00593
if (
flags_x11) {
00594 ret =
xdvshow_x11_open_window(
prog_name, ¶m);
00595 }
00596
if (ret < 0) {
00597 printf(
"failed to open window\n");
00598 kill(getpid(), SIGINT);
00599
return(NULL);
00600 }
00601
00602
while (1) {
00603
#if (HAVE_SDL || HAVE_SDL11)
00604
xdvshow_SDL_handle_events();
00605
#endif
00606
00607 (*input_func)(&
videodata);
00608
00609
if (
flags_dump) {
00610 ret = write(
dump_fd,
videodata, 144000);
00611
DPRINT(
"Videodata written: %d\n", ret);
00612
if(ret == -1) {
00613 perror(
"writing videodata failed");
00614 }
00615 }
00616
00617 pthread_testcancel();
00618 dv_decode_full_frame(
dv_dec,
00619
videodata,
00620 param.decode_format,
00621 param.pixels,
00622 param.pitches);
00623
00624 pthread_testcancel();
00625
#if (HAVE_SDL || HAVE_SDL11)
00626
if (
flags_sdl) {
00627
xdvshow_render();
00628 }
00629
#endif
00630
if (
flags_x11) {
00631
xdvshow_x11_render();
00632 }
00633
DPRINT(
"DISPLAYED\n");
00634 pthread_testcancel();
00635
00636
if (input_unlock_func) {
00637 (*input_unlock_func)();
00638 }
00639 pthread_testcancel();
00640
00641
if (
flags_file){
00642 gettimeofday(&
currtime, NULL);
00643
framedelay_usec =
frametime_usec -
currtime.tv_usec;
00644
if (framedelay_usec < 0 || framedelay_usec > 40000){
00645
DPRINT(
"Machine too slow or timing is queer somehow :(\n");
00646
DPRINT(
"currtime_usec: %ld, frametime_usec: %ld, framedelay_usec: %ld\n",
00647
currtime.tv_usec,
frametime_usec,
framedelay_usec);
00648 }
else {
00649 usleep(
framedelay_usec);
00650
DPRINT(
"currtime_sec: %ld\n",
currtime.tv_sec);
00651
DPRINT(
"currtime_usec: %ld, frametime_usec: %ld, framedelay_usec: %ld\n",
00652
currtime.tv_usec,
frametime_usec,
framedelay_usec);
00653 }
00654 gettimeofday(&
currtime, NULL);
00655
frametime_usec =
currtime.tv_usec +
frametimeadd_usec;
00656
if (
frametime_usec > 1000000){
00657
frametime_usec =
frametime_usec - 1000000;
00658 }
00659 }
00660 }
00661
00662
return(NULL);
00663 }
00664
00676
void *
00677 audio_thread_func(
void *data)
00678 {
00679
int ret = 0;
00680
00681
if (
flags_use_audio) {
00682
while(1) {
00683 (*audio_input_func)(&
audioframe);
00684
00685 dv_decode_full_audio(
dv_dec,
audioframe,
audio_buffers);
00686 ret =
xdvshow_play_audio(
dv_dec->audio,
audio_buffers);
00687
if (ret < 0) {
00688
break;
00689 }
00690
00691
if (audio_unlock_func) {
00692 (*audio_unlock_func)();
00693 }
00694 }
00695 }
else {
00696
while (1) {
00697 sleep(30);
00698 }
00699 }
00700
00701
return(NULL);
00702 }
00703