⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_output.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Ogle - A video player * Copyright (C) 2000, 2001 Bj鰎n Englund, H錵an Hjort * * This program 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. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <sys/shm.h>#include <time.h>#include <errno.h>#ifdef __bsdi__#include <sys/param.h>#include <sys/sysctl.h>#endif#ifndef HAVE_CLOCK_GETTIME#include <sys/time.h>#endif#include <X11/Xlib.h>#include <ogle/msgevents.h>#include "debug_print.h"#include "common.h"#include "video_types.h"#include "timemath.h"#include "sync.h"#include "spu_mixer.h"#include "video_output.h"#include "xscreensaver-comm.h"#include "screenshot.h"#ifndef SHM_SHARE_MMU#define SHM_SHARE_MMU 0#endifextern void display_init(int padded_width, int padded_height,		  int picture_buffer_shmid,		  char *picture_buffer_addr);extern void display_reset(void);extern void display(yuv_image_t *current_image);extern void display_poll(yuv_image_t *current_image);extern void display_exit(void);extern void display_reset_screensaver(void);extern void screenshot_mode(int mode);int register_event_handler(int(*eh)(MsgEventQ_t *, MsgEvent_t *));int event_handler(MsgEventQ_t *q, MsgEvent_t *ev);char *program_name;int dlevel;int video_scr_nr;int process_interrupted = 0;Bool talk_to_xscreensaver;static int end_of_wait;static long clk_tck;static long min_time_left;AspectModeSrc_t aspect_mode = AspectModeSrcVM;AspectModeSrc_t aspect_sender;uint16_t aspect_new_frac_n;uint16_t aspect_new_frac_d;ZoomMode_t zoom_mode = ZoomModeResizeAllowed;static int ctrl_data_shmid;ctrl_data_t *ctrl_data;ctrl_time_t *ctrl_time;int msgqid = -1;MsgEventQ_t *msgq;static int flush_to_scrid = -1;static int prev_scr_nr = 0;static data_q_t *data_q_head;data_q_t *cur_data_q;static MsgEventClient_t gui_client = 0;MsgEventClient_t input_client = 0;InputMask_t input_mask = INPUT_MASK_None;typedef struct _event_handler_t {  int(*eh)(MsgEventQ_t *, MsgEvent_t *);  struct _event_handler_t *next;} event_handler_t;static event_handler_t *eh_head = NULL;int register_event_handler(int(*eh)(MsgEventQ_t *, MsgEvent_t *)){  event_handler_t *eh_ptr;    eh_ptr = malloc(sizeof(event_handler_t));  eh_ptr->next = eh_head;  eh_ptr->eh = eh;  eh_head = eh_ptr;    return 0;}int event_handler(MsgEventQ_t *q, MsgEvent_t *ev){  event_handler_t *eh_ptr;    eh_ptr = eh_head;    while(eh_ptr != NULL) {    if(eh_ptr->eh(q, ev)) {      return 1;    }    eh_ptr = eh_ptr->next;  }  DNOTE("event_handler: unhandled event: %d\n", ev->type);  return 0;}void wait_for_q_attach(void){  MsgEvent_t ev;    //DNOTE("waiting for attachq\n");    while(ev.type != MsgEventQAttachQ) {    if(MsgNextEventInterruptible(msgq, &ev) == -1) {      switch(errno) {      case EINTR:	continue;	break;      default:	FATAL("%s", "waiting for attachq\n");	perror("MsgNextEvent");	exit(1);	break;      }    }    event_handler(msgq, &ev);  }  //DNOTE("got attachq\n");}static int attach_ctrl_shm(int shmid){  char *shmaddr;    if(ctrl_data_shmid) {    return 0;  }  if(shmid >= 0) {    if((shmaddr = shmat(shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {      ERROR("%s", "attach_ctrl_data()\n");      perror("shmat");      return -1;    }        ctrl_data_shmid = shmid;    ctrl_data = (ctrl_data_t*)shmaddr;    ctrl_time = (ctrl_time_t *)(shmaddr+sizeof(ctrl_data_t));  }        return 0;}static int attach_data_q(int q_shmid, data_q_t *data_q){  int n;  int data_shmid;  char *q_shmaddr;  char *data_shmaddr;  q_head_t *q_head;  q_elem_t *q_elems;  data_buf_head_t *data_head;  picture_data_elem_t *data_elems;  yuv_image_t *image_bufs;#ifdef HAVE_XV  yuv_image_t *reserv_image;#endif    //DNOTE("attach_data_q: q_shmid: %d\n", q_shmid);    if(q_shmid < 0) {    ERROR("%s", "attach_data_q(), q_shmid < 0\n");    return -1;  }  if((q_shmaddr = shmat(q_shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {    ERROR("%s", "attach_data_q()\n");    perror("shmat");    return -1;  }  q_head = (q_head_t *)q_shmaddr;  q_elems = (q_elem_t *)(q_shmaddr+sizeof(q_head_t));  data_shmid = q_head->data_buf_shmid;  //DNOTE("attach_data_q: data_shmid: %d\n", data_shmid);  if(data_shmid < 0) {    ERROR("%s", "attach_data_q(), data_shmid\n");    return -1;  }  if((data_shmaddr = shmat(data_shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {    ERROR("%s", "attach_data_q()");    perror("shmat");    return -1;  }      data_head = (data_buf_head_t *)data_shmaddr;    data_elems = (picture_data_elem_t *)(data_shmaddr + 				       sizeof(data_buf_head_t));    //TODO ugly hack#ifdef HAVE_XV  image_bufs =     malloc((data_head->nr_of_dataelems+1) *	   sizeof(yuv_image_t));  for(n = 0; n < (data_head->nr_of_dataelems+1); n++) {#else  image_bufs =     malloc(data_head->nr_of_dataelems * sizeof(yuv_image_t));  for(n = 0; n < data_head->nr_of_dataelems; n++) {#endif    image_bufs[n].y = data_shmaddr + data_elems[n].picture.y_offset;    image_bufs[n].u = data_shmaddr + data_elems[n].picture.u_offset;    image_bufs[n].v = data_shmaddr + data_elems[n].picture.v_offset;    image_bufs[n].info = &data_elems[n];  }  //TODO ugly hack#ifdef HAVE_XV  reserv_image = &image_bufs[n-1];#endif  if(data_head->info.type != DataBufferType_Video) {    ERROR("%s", "Didn't get type Video\n");    return -1;  }  data_q->in_use = 0;  data_q->eoq = 0;  data_q->q_head = q_head;  data_q->q_elems = q_elems;  data_q->data_head = data_head;  data_q->data_elems = data_elems;  data_q->image_bufs = image_bufs;#ifdef HAVE_XV  data_q->reserv_image = reserv_image;#endif  data_q->next = NULL;  return 0;}static int detach_data_q(int q_shmid, data_q_t **data_q_head){  MsgEvent_t ev;  MsgEventClient_t client;  data_q_t **data_q_p;  data_q_t *data_q_tmp;    //DNOTE("detach_data_q q_shmid: %d\n", q_shmid);    for(data_q_p=data_q_head;      *data_q_p != NULL && (*data_q_p)->q_head->qid != q_shmid;      data_q_p = &(*data_q_p)->next) {  }  if(*data_q_p == NULL) {    ERROR("%s", "detach_data_q q_shmid not found\n");    return -1;  }  client = (*data_q_p)->q_head->writer;  if(shmdt((char *)(*data_q_p)->data_head) == -1) {    ERROR("%s", "detach_data_q data_head");    perror("shmdt");  }    if(shmdt((char *)(*data_q_p)->q_head) == -1) {    ERROR("%s", "detach_data_q q_head");    perror("shmdt");  }  //TODO ugly hack  free((*data_q_p)->image_bufs);  data_q_tmp = *data_q_p;  *data_q_p = (*data_q_p)->next;  free(data_q_tmp);  ev.type = MsgEventQQDetached;  ev.detachq.q_shmid = q_shmid;    if(MsgSendEvent(msgq, client, &ev, 0) == -1) {    DPRINTF(1, "vo: qdetached\n");  }  return 0;}static int append_picture_q(int q_shmid, data_q_t **data_q){  data_q_t **data_q_p;  for(data_q_p = data_q; *data_q_p != NULL; data_q_p =&(*data_q_p)->next);      *data_q_p = malloc(sizeof(data_q_t));    if(attach_data_q(q_shmid, *data_q_p) == -1) {    free(*data_q_p);    *data_q_p = NULL;    return -1;  }    return 0;}static int attach_picture_buffer(int q_shmid){  append_picture_q(q_shmid, &data_q_head);  if(cur_data_q == NULL) {    cur_data_q = data_q_head;  }  return 0;}static int detach_picture_q(int shmid){    //DNOTE("detach_picture_q q_shmid: %d\n", shmid);    detach_data_q(shmid, &data_q_head);  display_reset();  return 0;}static yuv_image_t *last_image_buf = NULL;static int redraw_needed = 0;void redraw_request(void){  redraw_needed = 1;}void redraw_done(void){  redraw_needed = 0;}static void redraw_screen(void){  if(flush_to_scrid != -1) {    if(ctrl_time[video_scr_nr].scr_id < flush_to_scrid) {      redraw_done();      return;    } else {      flush_to_scrid = -1;    }  }  if(last_image_buf != NULL) {    display(last_image_buf);      }  redraw_done();}void screenshot_request(ScreenshotMode_t mode){  screenshot_mode(mode);  if(mode == 0) {    if(last_image_buf) {      if(last_image_buf->info->is_reference || (ctrl_data->speed < 1.0)) {	redraw_request();      }    }  } else {    redraw_request();  }}static int handle_events(MsgEventQ_t *q, MsgEvent_t *ev){  MsgEvent_t s_ev;    switch(ev->type) {  case MsgEventQNotify:    if((cur_data_q->q_head != NULL) &&       (ev->notify.qid == cur_data_q->q_head->qid)) {      ;    } else {      return 0;    }    break;  case MsgEventQFlushData:    DPRINTF(1, "vo: got flush\n");    flush_to_scrid = ev->flushdata.to_scrid;    flush_subpicture(flush_to_scrid);    break;  case MsgEventQAttachQ:    attach_picture_buffer(ev->attachq.q_shmid);    break;  case MsgEventQAppendQ:    append_picture_q(ev->attachq.q_shmid, &data_q_head);    break;  case MsgEventQDetachQ:    detach_picture_q(ev->detachq.q_shmid);        s_ev.type = MsgEventQQDetached;    s_ev.detachq.q_shmid = ev->detachq.q_shmid;        if(MsgSendEvent(msgq, ev->detachq.client, &s_ev, 0) == -1) {      DPRINTF(1, "vo: qdetached\n");    }        wait_for_q_attach();        break;  case MsgEventQCtrlData:    attach_ctrl_shm(ev->ctrldata.shmid);    break;  case MsgEventQGntCapability:    if((ev->gntcapability.capability & UI_DVD_GUI) == UI_DVD_GUI)      gui_client = ev->gntcapability.capclient;    else      ERROR("capabilities not requested (%d)\n",               ev->gntcapability.capability);    break;  case MsgEventQSetAspectModeSrc:    aspect_mode = ev->setaspectmodesrc.mode_src;    break;  case MsgEventQSetSrcAspect:    // hack, fix this to use an array of all aspectmodesrc's    aspect_sender = ev->setsrcaspect.mode_src;    aspect_new_frac_n = ev->setsrcaspect.aspect_frac_n;    aspect_new_frac_d = ev->setsrcaspect.aspect_frac_d;    break;  case MsgEventQSetZoomMode:    zoom_mode = ev->setzoommode.mode;    redraw_request();    break;  case MsgEventQReqInput:    input_mask = ev->reqinput.mask;    input_client = ev->reqinput.client;    break;  case MsgEventQSpeed:    if(ctrl_time[prev_scr_nr].sync_master <= SYNC_VIDEO) {      set_speed(&ctrl_time[prev_scr_nr].sync_point, ev->speed.speed);    }    break;  case MsgEventQSaveScreenshot:    if(ev->savescreenshot.formatstr[0]) {      screenshot_set_formatstr(ev->savescreenshot.formatstr);    }    screenshot_request(ev->savescreenshot.mode);    break;  default:    //DNOTE("unrecognized event type: %d\n", ev->type);    return 0;    break;  }  return 1;}void wait_until_handler(int sig) {  end_of_wait = 1;  return;}void alarm_handler(int sig) {  end_of_wait = 1;  if(last_image_buf)    display_poll(last_image_buf);}static clocktime_t wait_until(clocktime_t *scr, sync_point_t *sp){  struct itimerval timer;  clocktime_t time_left;  clocktime_t real_time;  struct sigaction act;  struct sigaction oact;  static clocktime_t last_ss_disable = {0,0};  timer.it_interval.tv_sec = 0;  timer.it_interval.tv_usec = 0;    while(1) {        end_of_wait = 0;        clocktime_get(&real_time);    if(TIME_S(real_time) - TIME_S(last_ss_disable) > 50) {      clocktime_t prof_time;      if(talk_to_xscreensaver) {	nudge_xscreensaver();	clocktime_get(&prof_time);	timesub(&prof_time, &prof_time, &real_time);	DNOTE("ss disable took %ld.%09ld s\n",	      TIME_S(prof_time), TIME_SS(prof_time));      }      display_reset_screensaver();      TIME_S(last_ss_disable) = TIME_S(real_time);    }        calc_realtime_left_to_scrtime(&time_left, &real_time,				  scr, sp);    /*    fprintf(stderr, "rt: %ld.%09ld, scr: %ld.%09ld, left: %ld.%09ld\n",	    real_time.tv_sec, real_time.tv_nsec,	    scr->tv_sec, scr->tv_nsec,	    time_left.tv_sec, time_left.tv_nsec);    */    if((TIME_S(time_left) > 0) || (TIME_SS(time_left) > (CT_FRACTION/10))) {      // more then 100 ms left, lets wait and check x events every 100ms      timer.it_value.tv_sec = 0;      timer.it_value.tv_usec = 100000;      act.sa_handler = alarm_handler;      act.sa_flags = 0;      sigaction(SIGALRM, &act, &oact);      setitimer(ITIMER_REAL, &timer, NULL);    } else if(TIME_SS(time_left) > min_time_left) {      // less than 100ms but more than clktck/2 left, lets wait      struct timespec sleeptime; #if 0      timer.it_value.tv_sec = 0;      timer.it_value.tv_usec = TIME_SS(time_left)/(CT_FRACTION/1000000);            act.sa_handler = wait_until_handler;      act.sa_flags = 0;            sigaction(SIGALRM, &act, &oact);      setitimer(ITIMER_REAL, &timer, NULL);#endif      sleeptime.tv_sec = TIME_S(time_left);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -