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

📄 video_output.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 2 页
字号:
      sleeptime.tv_nsec = TIME_SS(time_left)*(1000000000/CT_FRACTION);      nanosleep(&sleeptime, NULL);      clocktime_get(&real_time);      calc_realtime_left_to_scrtime(&time_left, &real_time,				    scr, sp);      return time_left;    } else {      // less than clktck/2 left or negative time left, we cant sleep      // a shorter period than clktck so we return      return time_left;    }      while(!end_of_wait) {      MsgEvent_t ev;            // check any events that arrives       if(MsgNextEventInterruptible(msgq, &ev) == -1) {	switch(errno) {	case EINTR:	  end_of_wait = 1;	  break;	default:	  FATAL("%s", "waiting for notification");	  perror("MsgNextEvent");	  // might never have had dispay_init called	  display_exit(); //clean up and exit	  break;	}      } else {	timer.it_value.tv_sec = 0; // disable timer	timer.it_value.tv_usec = 0; // disable timer	setitimer(ITIMER_REAL, &timer, NULL);	event_handler(msgq, &ev);	if(redraw_needed) {	  redraw_screen();	}	break;      }    }    timer.it_value.tv_sec = 0; // disable timer    timer.it_value.tv_usec = 0; // disable timer    setitimer(ITIMER_REAL, &timer, NULL);        sigaction(SIGALRM, &oact, NULL);  }  }static int get_next_picture_q_elem_id(data_q_t *data_q){  int elem;  MsgEvent_t ev;  struct itimerval timer;  timer.it_interval.tv_sec = 0;  timer.it_interval.tv_usec = 0;  timer.it_value.tv_sec = 0;  timer.it_value.tv_usec = 0;    elem = data_q->q_head->read_nr;  //DNOTE("get_next_picture_q_elem_id: elem: %d\n", elem);  data_q->q_head->read_nr =    (data_q->q_head->read_nr+1)%data_q->q_head->nr_of_qelems;  if(!data_q->q_elems[elem].in_use) {    data_q->q_head->reader_requests_notification = 1;    //DNOTE("elem not in use, setting notification req\n");    while(!data_q->q_elems[elem].in_use) {      if(process_interrupted) {	// might never have had dispay_init called	display_exit();      }      timer.it_value.tv_usec = 100000; //0.1 sec      setitimer(ITIMER_REAL, &timer, NULL);      //DNOTE("waiting for notification\n");      if(MsgNextEventInterruptible(msgq, &ev) == -1) {	switch(errno) {	case EINTR:	  continue;	  break;	default:	  FATAL("%s", "waiting for notification");	  perror("MsgNextEvent");	  // might never have had dispay_init called?	  display_exit(); //clean up and exit	  break;	}      }      timer.it_value.tv_usec = 0; // disable timer      setitimer(ITIMER_REAL, &timer, NULL);      event_handler(msgq, &ev);      if(redraw_needed) {	redraw_screen();      }    }  }  if((data_q->q_elems[elem].data_elem_index) == -1) {    // end of q    data_q->eoq = 1;    return -1;  }  data_q->in_use++;  return elem;}static void release_picture(int q_elem_id, data_q_t *data_q){  MsgEvent_t ev;  int msg_sent = 0;  int id;    id = data_q->q_elems[q_elem_id].data_elem_index;  /*  DNOTE("release_picture: elem: %d, buf: %d\n",	  q_elem_id, id);  */  data_q->data_elems[id].displayed = 1;  data_q->q_elems[q_elem_id].in_use = 0;  if(data_q->q_head->writer_requests_notification) {    data_q->q_head->writer_requests_notification = 0;    ev.type = MsgEventQNotify;    do {      if(process_interrupted) {	display_exit();      }      if(MsgSendEvent(msgq, data_q->q_head->writer, &ev, IPC_NOWAIT) == -1) {	MsgEvent_t c_ev;	switch(errno) {	case EAGAIN:	  WARNING("%s", "msgq full, checking incoming messages and trying again\n");	  while(MsgCheckEvent(msgq, &c_ev) != -1) {	    event_handler(msgq, &c_ev);	  }	  break;#ifdef EIDRM	case EIDRM:#endif	case EINVAL:	  FATAL("%s", "couldn't send notification no msgq\n");	  display_exit(); //TODO clean up and exit	  break;	default:	  FATAL("%s", "couldn't send notification\n");	  display_exit(); //TODO clean up and exit	  break;	}      } else {	msg_sent = 1;      }    } while(!msg_sent);  }  data_q->in_use--;}data_q_t *get_next_data_q(data_q_t **head, data_q_t *cur_q){  data_q_t **data_q;  data_q_t *tmp_q;    for(data_q = head;      *data_q != NULL && *data_q != cur_q;      data_q = &(*data_q)->next);    if(*data_q == NULL) {    ERROR("%s", "get_next_data_q(), couldn't find cur_q\n");    return NULL;  }  tmp_q = (*data_q)->next; //pointer to the next q    if(!(*data_q)->in_use) {    display_reset();    detach_data_q((*data_q)->q_head->qid, head);  }  if(tmp_q == NULL) {    // no next q, lets wait for it    DNOTE("%s", "get_next_data_q: no next q\n");    wait_for_q_attach();    if(*data_q != cur_q) {      //cur has been detached      tmp_q = *data_q;    } else {      tmp_q = (*data_q)->next;    }  }    return tmp_q;}/* Erhum test... */clocktime_t first_time;int frame_nr = 0;static void int_handler(int sig){  process_interrupted = 1;}static void display_process(){  clocktime_t real_time, prefered_time, frame_interval;  clocktime_t avg_time, oavg_time;#ifndef HAVE_CLOCK_GETTIME  clocktime_t waittmp;#endif  clocktime_t wait_time;  struct sigaction sig;  int q_elem_id = -1;  int prev_q_elem_id = -1;    int buf_id = -1;  int prev_buf_id = -1;  int old_q_id = -1;  int drop = 0;  int avg_nr = 23;  picture_data_elem_t *pinfos;  data_q_t *old_data_q = NULL;    TIME_S(prefered_time) = 0;    sig.sa_handler = int_handler;  sig.sa_flags = 0;  sigaction(SIGINT, &sig, NULL);  sig.sa_handler = alarm_handler;  sig.sa_flags = 0;  sigaction(SIGALRM, &sig, NULL);  talk_to_xscreensaver = look_for_good_xscreensaver();  while(1) {    //DNOTE("old_q_id: %d\n", old_q_id);    old_data_q = cur_data_q;    do {      q_elem_id = get_next_picture_q_elem_id(cur_data_q);      /*      DNOTE("get_next_picture_q_elem_id: %d, buf:%d\n",	      q_elem_id, cur_data_q->q_elems[q_elem_id].data_elem_index);      */      if(cur_data_q->eoq) {	//end of q	/*	  last pic in the current q,	  switch to new q, and detach the old	  if there is no new q, wait for an attachq or appendq	  get first pic in the new q	*/        if(!cur_data_q->in_use) {          last_image_buf = NULL;	  old_data_q = NULL;        }		cur_data_q = get_next_data_q(&data_q_head, cur_data_q);      }    } while(q_elem_id == -1);    pinfos = cur_data_q->data_elems;    buf_id = cur_data_q->q_elems[q_elem_id].data_elem_index;    //DNOTE("last_image_buf: %d\n", last_image_buf);    video_scr_nr = pinfos[buf_id].scr_nr;        // Consume all messages for us and spu_mixer    if(msgqid != -1) {      MsgEvent_t ev;      while(MsgCheckEvent(msgq, &ev) != -1) {	event_handler(msgq, &ev);      }    }    if(ctrl_time[pinfos[buf_id].scr_nr].sync_master <= SYNC_VIDEO) {      ctrl_time[pinfos[buf_id].scr_nr].sync_master = SYNC_VIDEO;            //TODO release scr_nr when done            if(ctrl_time[pinfos[buf_id].scr_nr].offset_valid == OFFSET_NOT_VALID) {	if(pinfos[buf_id].PTS_DTS_flags & 0x2) {	  clocktime_t scr_time;	  DNOTE("%s", "set_sync_point()\n");	  PTS_TO_CLOCKTIME(scr_time, pinfos[buf_id].PTS);	  clocktime_get(&real_time);	  set_sync_point(&ctrl_time[pinfos[buf_id].scr_nr],			 &real_time,			 &scr_time,			 ctrl_data->speed);	}      }      /*      if(pinfos[buf_id].PTS_DTS_flags & 0x2) {	time_offset = get_time_base_offset(pinfos[buf_id].PTS,					   ctrl_time, pinfos[buf_id].scr_nr);      }      */      prev_scr_nr = pinfos[buf_id].scr_nr;    }        PTS_TO_CLOCKTIME(frame_interval, pinfos[buf_id].frame_interval);    clocktime_get(&real_time);    TIME_S(wait_time) = 0;    TIME_SS(wait_time) = 0;    if(flush_to_scrid != -1) {      if(ctrl_time[video_scr_nr].scr_id >= flush_to_scrid) {	flush_to_scrid = -1;      }    }        if(flush_to_scrid == -1) {      if(TIME_S(prefered_time) == 0 || TIME_SS(frame_interval) == 1) {	prefered_time = real_time;      } else if(ctrl_time[pinfos[buf_id].scr_nr].offset_valid == OFFSET_NOT_VALID) {	prefered_time = real_time;      } else /* if(TIME_S(pinfos[buf_id].pts_time) != -1) */ { 	clocktime_t pts_time;	PTS_TO_CLOCKTIME(pts_time, pinfos[buf_id].PTS);		/*	calc_realtime_from_scrtime(&prefered_time, &pts_time,				   &ctrl_time[pinfos[buf_id].scr_nr].sync_point);	*/	wait_time =	  wait_until(&pts_time, &ctrl_time[pinfos[buf_id].scr_nr].sync_point);	      }    }    /**     * We have waited and now it's time to show a new picture     */    last_image_buf = &cur_data_q->image_bufs[buf_id];        // release the old picture, if it's not done already    if(prev_buf_id != -1) {      if(old_q_id != cur_data_q->q_head->qid) {	//DNOTE("old_q_id != current\n");      }      if((old_data_q != NULL) && (old_data_q != cur_data_q)) {       //DNOTE("release old_q buf_id: %d\n", prev_buf_id);	release_picture(prev_q_elem_id, old_data_q);      } else {	//DNOTE("release buf_id: %d\n", prev_buf_id);	release_picture(prev_q_elem_id, cur_data_q);      }    } else if(prev_q_elem_id != -1) {      //DNOTE("release2 buf_id: %d\n", prev_buf_id);      release_picture(prev_q_elem_id, cur_data_q);    }          //detach old q if any    if(old_q_id != cur_data_q->q_head->qid) {      if(old_q_id != -1) {	detach_data_q(old_q_id, &data_q_head);      }      /*      DNOTE("display_init: width: %d, height:%d\n",	      cur_data_q->data_head->info.video.width,	      cur_data_q->data_head->info.video.height);      */      display_init(cur_data_q->data_head->info.video.width,		   cur_data_q->data_head->info.video.height,		   cur_data_q->data_head->shmid,		   (char *)cur_data_q->data_head);    }        prev_q_elem_id = q_elem_id;    prev_buf_id = buf_id;    old_q_id = cur_data_q->q_head->qid;    /*    fprintf(stderr, "*vo: waittime: %ld.%+010ld\n",	    wait_time.tv_sec, wait_time.tv_nsec);    */    if(TIME_SS(wait_time) < -60*(CT_FRACTION/1000)) {      // more than 60 ms late, drop decoded pictures      drop = 1;    }        if(!drop) {      frame_nr++;      avg_nr++;    }    if(avg_nr == 200) {      avg_nr = 0;      oavg_time = avg_time;      clocktime_get(&avg_time);            fprintf(stderr, "display: frame rate: %.3f fps\n",	      200.0/(((double)TIME_S(avg_time)+		      (double)TIME_SS(avg_time)/CT_FRACTION)-		     ((double)TIME_S(oavg_time)+		      (double)TIME_SS(oavg_time)/CT_FRACTION))	      );    }    /*    clocktime_get(&real_time2);    timesub(&diff, &prefered_time, &real_time2);        fprintf(stderr, "diff: %d.%+010ld\n",	    TIME_S(diff), TIME_SS(diff));    */    /*    fprintf(stderr, "rt: %d.%09ld, pt: %d.%09ld, diff: %d.%+09ld\n",	    TIME_S(real_time2), TIME_SS(real_time2),	    TIME_S(prefered_time), TIME_SS(prefered_time),	    TIME_S(diff), TIME_SS(diff));    */    if(!drop) {      if(flush_to_scrid != -1) {	if(ctrl_time[video_scr_nr].scr_id < flush_to_scrid) {	  redraw_done();	} else {	  flush_to_scrid = -1;	  display(&cur_data_q->image_bufs[buf_id]);	  redraw_done();	}      } else {	display(&cur_data_q->image_bufs[buf_id]);	redraw_done();      }    } else {      fprintf(stderr, "#");      drop = 0;    }  }}void display_process_exit(void) {  exit(0);}#ifdef __bsdi__static int bsdi_getticks(void){  int mib[2];  size_t olen = sizeof (struct clockinfo);  struct clockinfo ci;    mib[0] = CTL_KERN;  mib[1] = KERN_CLOCKRATE;  if (sysctl(mib, 2, &ci, &olen, NULL, 0) < 0) {    perror("sysctl kern.clockrate");    return(100);  }  return ci.hz;}#endifstatic void usage(){  fprintf(stderr, "Usage: %s  [-m <msgid>]\n", 	  program_name);}int main(int argc, char **argv){  MsgEvent_t ev;  int c;   program_name = argv[0];  GET_DLEVEL();  /* Parse command line options */  while ((c = getopt(argc, argv, "m:h?")) != EOF) {    switch (c) {    case 'm':      msgqid = atoi(optarg);      break;    case 'h':    case '?':      usage();      return 1;    }  }  if(msgqid == -1) {    if(argc - optind != 1){      usage();      return 1;    }  }    errno = 0;#ifdef __bsdi__  clk_tck = bsdi_getticks();#else  clk_tck = sysconf(_SC_CLK_TCK);#endif    if(clk_tck <= 0) {    // linux returns 0 as error also    if(errno != 0 && clk_tck == -1) {      perror("sysconf(_SC_CLK_TCK)");    } else {      fprintf(stderr, "sysconf(_SC_CLK_TCK), not supported\n");    }    //guessed default value    clk_tck = 100;  }  min_time_left = (CT_FRACTION/clk_tck)/2;  DNOTE("CLK_TCK: %ld\n", clk_tck);  if(msgqid != -1) {        if((msgq = MsgOpen(msgqid)) == NULL) {      FATAL("%s", "couldn't get message q\n");      exit(1);    }        register_event_handler(handle_events);    init_spu();    ev.type = MsgEventQRegister;    ev.registercaps.capabilities = VIDEO_OUTPUT | DECODE_DVD_SPU;        if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) {      DPRINTF(1, "vo: register capabilities\n");      exit(1); //TODO clean up and exit    }        //DNOTE("sent caps\n");        ev.type = MsgEventQReqCapability;    ev.reqcapability.capability = UI_DVD_GUI;    if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) {      FATAL("%s", "didn't get dvd_gui cap\n");      exit(1); //TODO clean up and exit    }        //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");	  perror("MsgNextEvent");	  exit(1);	  break;	}      }      event_handler(msgq, &ev);    }    //DNOTE("got attachq\n");    display_process();      } else {    fprintf(stderr, "what?\n");  }    exit(0);}

⌨️ 快捷键说明

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