lqtplay.c
来自「这个库实现了录象功能」· C语言 代码 · 共 1,866 行 · 第 1/4 页
C
1,866 行
snd_pcm_prepare(pcm_handle); fprintf(stderr, _("Warning: buffer underrun\n")); } else if (ret < 0) { fprintf(stderr, _("Warning: %s\n"), snd_strerror(ret)); } else if (ret >= 0) done = 1; } if (ret > 0 ) { qt_audio_samples_in_buffer -=ret; qt_audio_ptr += ret * qt_channels; } if (qt_audio_eof && 0 == qt_audio_samples_in_buffer) { snd_pcm_drain(pcm_handle); return -1; }#endif return 0;}static int qt_oss_audio_write(void){ int rc; if(!qt_audio_samples_in_buffer) decode_audio(AUDIO_BLOCK_SIZE); rc = write(oss_fd,qt_audio_ptr,qt_audio_samples_in_buffer * qt_channels * sizeof(*qt_audio)); switch (rc) { case -1: perror("write dsp"); close(oss_fd); oss_fd = -1; qt_hasaudio = 0; break; case 0: fprintf(stderr,_("write dsp: Huh? no data written?\n")); close(oss_fd); oss_fd = -1; qt_hasaudio = 0; break; default: qt_audio_samples_in_buffer -= rc / (qt_channels * sizeof(*qt_audio)); qt_audio_ptr += rc / sizeof(*qt_audio); break; } if (qt_audio_eof && 0 == qt_audio_samples_in_buffer) { return -1; } return 0;}/* ------------------------------------------------------------------------ *//* main */struct ARGS { int xv; int gl; int alsa;} args;XtResource args_desc[] = { /* name, class, type, size, offset, default_type, default_addr */ { /* Integer */ "xv", XtCValue, XtRInt, sizeof(int), XtOffset(struct ARGS*,xv), XtRString, "1" },{ "gl", XtCValue, XtRInt, sizeof(int), XtOffset(struct ARGS*,gl), XtRString, "1" },{ "alsa", XtCValue, XtRInt, sizeof(int), XtOffset(struct ARGS*,alsa), XtRString, "1" }};const int args_count = XtNumber(args_desc);XrmOptionDescRec opt_desc[] = { { "-noxv", "xv", XrmoptionNoArg, "0" }, { "-nogl", "gl", XrmoptionNoArg, "0" }, { "-noalsa", "alsa", XrmoptionNoArg, "0" },};const int opt_count = (sizeof(opt_desc)/sizeof(XrmOptionDescRec));static void usage(FILE *fp, char *prog){ char *p; p = strrchr(prog,'/'); if (p) prog = p+1; fprintf(fp, _("\n" "Very simple quicktime movie player for X11. Just playes\n" "the movie and nothing else. No fancy gui, no controls.\n" "\n" "You can quit with 'Q' and 'ESC' keys.\n" "\n" "usage: %s [ options ] <file>\n" "options:\n" " -noxv don't use the Xvideo extention\n" " -nogl don't use OpenGL\n" " -noalsa don't use Alsa\n" "\n"), prog);}static void decode_qtvr(){ XEvent event; int startpos; startpos = quicktime_video_position(qt, 0); XFlush(dpy); if (qt_hasvideo) { if (qt_frame_decode() || qt_frame_blit()) exit(0); } for (;;) { struct timespec time; // printf("loop pos :%ld\n",quicktime_video_position(qt,0)); if (quicktime_video_position(qt,0) >= startpos + lqt_qtvr_get_loop_frames(qt)) quicktime_set_video_position(qt, startpos, 0); if (True == XCheckMaskEvent(dpy, ~0, &event)) { XtDispatchEvent(&event); } else { // printf("loop pos before decode :%ld\n",quicktime_video_position(qt,0)); XFlush(dpy); XtAppProcessEvent(app_context, KeyPressMask||KeyReleaseMask); time.tv_nsec = 10000000; time.tv_sec = 0; nanosleep(&time, NULL); } }}static void quit_ac(Widget widget, XEvent *event, String *params, Cardinal *num_params){ exit(0);}static void resize_ev(Widget widget, XtPointer client_data, XEvent *event, Boolean *d){ switch(event->type) { case MapNotify: case ConfigureNotify: XtVaGetValues(widget,XtNheight,&sheight,XtNwidth,&swidth,NULL); fprintf(stderr,_("INFO: window size is %dx%d\n"),swidth,sheight);#ifdef HAVE_GL if (use_gl) gl_resize(widget,swidth,sheight);#endif if (qt_isqtvr != 0) decode_qtvr(); break; case UnmapNotify: case DestroyNotify: exit(0); break; }}/* event handlers */static void left_ac(Widget widget, XEvent *event, String *params, Cardinal *num_params){ if (qt_isqtvr == QTVR_PAN) { if (xpos - 10 >= 0 ) xpos -= 10; if (xpos - 10 < 0) { xpos = xpos-10 + lqt_qtvr_get_width(qt); } } else if (qt_isqtvr == QTVR_OBJ) { int vpos = quicktime_video_position(qt, 0); int lfxcolumns = lqt_qtvr_get_loop_frames(qt) * lqt_qtvr_get_columns(qt); if (vpos % lfxcolumns == lfxcolumns - lqt_qtvr_get_loop_frames(qt) && vpos != 0) { quicktime_set_video_position(qt, vpos - (lqt_qtvr_get_columns(qt)-1), 0); } else { quicktime_set_video_position(qt, vpos + lqt_qtvr_get_loop_frames(qt), 0); } } else return;// printf("pos %ld\n",quicktime_video_position(qt,0)); decode_qtvr();}static void right_ac(Widget widget, XEvent *event, String *params, Cardinal *num_params){ if (qt_isqtvr == QTVR_PAN) { if (xpos + 10 <= lqt_qtvr_get_width(qt)+oh_width - qtvr_dwidth) xpos += 10; if (xpos + 10 > lqt_qtvr_get_width(qt)) { xpos = xpos+10 - lqt_qtvr_get_width(qt); } } else if (qt_isqtvr == QTVR_OBJ) { int vpos = quicktime_video_position(qt, 0); int lfxcolumns = lqt_qtvr_get_loop_frames(qt) * lqt_qtvr_get_columns(qt); if (vpos % lfxcolumns == 0) { quicktime_set_video_position(qt, vpos + (lqt_qtvr_get_loop_frames(qt) * lqt_qtvr_get_columns(qt)-1), 0); } else { quicktime_set_video_position(qt, vpos - lqt_qtvr_get_loop_frames(qt), 0); } } else return;// printf("pos %ld\n",quicktime_video_position(qt,0)); decode_qtvr();}static void up_ac(Widget widget, XEvent *event, String *params, Cardinal *num_params){ if (qt_isqtvr == QTVR_PAN) { if (ypos - 10 >= 0 ) ypos -= 10; } else if (qt_isqtvr == QTVR_OBJ) { int vpos = quicktime_video_position(qt, 0); if (vpos + lqt_qtvr_get_columns(qt) < lqt_qtvr_get_loop_frames(qt) * lqt_qtvr_get_rows(qt) * lqt_qtvr_get_columns(qt)) { quicktime_set_video_position(qt ,vpos + lqt_qtvr_get_columns(qt), 0); }// printf("pos %ld\n",quicktime_video_position(qt,0)); } else return; decode_qtvr();}static void down_ac(Widget widget, XEvent *event, String *params, Cardinal *num_params){ if (qt_isqtvr == QTVR_PAN) { if (ypos + 10 < lqt_qtvr_get_height(qt) - lqt_qtvr_get_display_height(qt)) ypos += 10; } else if (qt_isqtvr == QTVR_OBJ) { if (quicktime_video_position(qt, 0) - lqt_qtvr_get_columns(qt) >= 0) { quicktime_set_video_position(qt ,quicktime_video_position(qt, 0) - lqt_qtvr_get_columns(qt), 0); } } else return;// printf("pos %ld\n",quicktime_video_position(qt,0)); decode_qtvr();}static void expose_ev(Widget widget, XtPointer client_data, XEvent *event, Boolean *d){ if (event->type == Expose) decode_qtvr();}static XtActionsRec action_table[] = { { "Quit", quit_ac }, { "Right", right_ac }, { "Left", left_ac }, { "Up", up_ac }, { "Down", down_ac },};static String res[] = { "lqtplay.playback.translations: #override \\n" " <Key>Q: Quit() \\n" " <Key>Escape: Quit() \\n" " <Key>Right: Right() \\n" " <Key>Left: Left() \\n" " <Key>Up: Up() \\n" " <Key>Down: Down()", "lqtplay.playback.background: black", NULL};int main(int argc, char *argv[]){ int has_frame = 0, blit_frame = 0; struct timeval start,wait; // int audio_frames; setlocale(LC_MESSAGES, ""); setlocale(LC_CTYPE, ""); bindtextdomain(PACKAGE, LOCALE_DIR); app_shell = XtVaAppInitialize(&app_context, "lqtplay", opt_desc, opt_count, &argc, argv, res, NULL); XtGetApplicationResources(app_shell,&args, args_desc,args_count, NULL,0); /* don't use alsa*/ if (!args.alsa) use_alsa=0; /* open file */ if (argc < 2) { usage(stderr,argv[0]); exit(1); } qt_init(stdout,argv[1]); /* init x11 stuff */ dpy = XtDisplay(app_shell); XtAppAddActions(app_context,action_table, sizeof(action_table)/sizeof(XtActionsRec)); XtVaSetValues(app_shell, XtNtitle,argv[1],NULL); if (qt_isqtvr) { simple = XtVaCreateManagedWidget("playback",simpleWidgetClass,app_shell, XtNwidth, qtvr_dwidth, XtNheight, qtvr_dheight, NULL); XtAddEventHandler(simple,ExposureMask, True, expose_ev, NULL); } else simple = XtVaCreateManagedWidget("playback",simpleWidgetClass,app_shell, XtNwidth, qt_width, XtNheight, qt_height, NULL); XtAddEventHandler(simple,StructureNotifyMask, True, resize_ev, NULL); x11_init(); if (args.xv && qt_hasvideo) xv_init(); if(qt_hasvideo) { if (qt_isqtvr == QTVR_PAN) { /* cmodel hardcoded for panos */ lqt_set_cmodel(qt, 0, BC_RGB888); } else { /* Decide about the colormodel */ fprintf(stderr, _("Stream colormodel %s, "), lqt_colormodel_to_string(lqt_get_cmodel(qt, 0))); qt_cmodel = lqt_get_best_colormodel(qt, 0, qt_cmodels); fprintf(stderr, _("using %s\n"), lqt_colormodel_to_string(qt_cmodel)); /* Set decoding colormodel */ lqt_set_cmodel(qt, 0, qt_cmodel); } } /* use OpenGL? */ XtRealizeWidget(app_shell);#ifdef HAVE_GL if (BC_RGB888 == qt_cmodel && args.gl && qt_hasvideo) { if (qt_isqtvr == QTVR_PAN) { gl_init(simple,qtvr_dwidth,qtvr_dheight); } else gl_init(simple,qt_width,qt_height); }#endif /* frames per chunk for alsa */#if 0 if(qt_hasvideo) audio_frames = ((oss_sr / quicktime_frame_rate(qt,0)) / 2 + 0.5); else audio_frames = oss_sr + 1024;#endif /* Initialize video */ if(qt_hasvideo) qt_init_video(); if (qt_isqtvr) { decode_qtvr(); } else { /* enter main loop */ gettimeofday(&start,NULL); for (;;) { int rc,max; fd_set rd,wr; XEvent event; if (True == XCheckMaskEvent(dpy, ~0, &event)) { XtDispatchEvent(&event); } else { XFlush(dpy); FD_ZERO(&rd); FD_ZERO(&wr); FD_SET(ConnectionNumber(dpy),&rd); max = ConnectionNumber(dpy); if (qt_hasaudio) { if (use_alsa == 0) { FD_SET(oss_fd,&wr); if (oss_fd > max) max = oss_fd; } } if (qt_hasvideo) { if(!has_frame) { if(0 != qt_frame_decode()) { qt_hasvideo = 0; wait.tv_sec = 0; wait.tv_usec = 1000; } else { has_frame = 1; } } qt_frame_delay(&start,&wait); /* "wait" is the time, we would have to wait. If it's longer, than 2 ms, we'll continue feeding the soundcard. This prevents audio underruns for frames with a VERY long duration */ if(wait.tv_sec || (wait.tv_usec > 2000)) { wait.tv_sec = 0; wait.tv_usec = 2000; blit_frame = 0; } else blit_frame = 1; } else { wait.tv_sec = 0; wait.tv_usec = 1000; } rc = select(max+1,&rd,&wr,NULL,&wait); if (qt_hasaudio) { if (use_alsa == 1) { if (0 != qt_alsa_audio_write()) qt_hasaudio = 0; } else if (FD_ISSET(oss_fd,&wr)) { if (0 != qt_oss_audio_write()) qt_hasaudio = 0; } } if (qt_hasvideo && 0 == rc && blit_frame) { qt_frame_blit(); has_frame = 0; } } if(!qt_hasvideo && !qt_hasaudio) break; } } qt_cleanup(); fprintf(stderr, _("Decoded %lld samples\n"), (long long)total_samples_decoded); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?