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

📄 com.c

📁 基于linux的DVD播放器程序
💻 C
字号:
/* 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 <inttypes.h>#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <string.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/shm.h>#include <fcntl.h>#include <unistd.h>#include <sys/msg.h>#include <errno.h>#ifndef SHM_SHARE_MMU#define SHM_SHARE_MMU 0#endif#include <ogle/msgevents.h>#include "common.h"#include "queue.h"#include "timemath.h"//#include "sync.h"#include "debug_print.h"#include "vm.h"void handle_events(MsgEventQ_t *msgq, MsgEvent_t *ev);int wait_q(MsgEventQ_t *msgq, MsgEvent_t *ev);int get_q(MsgEventQ_t *msgq, unsigned char *buffer);void wait_for_init(MsgEventQ_t *msgq);int send_demux(MsgEventQ_t *msgq, MsgEvent_t *ev);int send_spu(MsgEventQ_t *msgq, MsgEvent_t *ev);static void change_file(char *new_filename);static int attach_ctrl_shm(int shmid);static int attach_stream_buffer(uint8_t stream_id, uint8_t subtype, int shmid);static char *mmap_base;static int ctrl_data_shmid;static ctrl_data_t *ctrl_data;static ctrl_time_t *ctrl_time;static int stream_shmid;static char *stream_shmaddr = NULL;static int data_buf_shmid;static unsigned char *data_buf_shmaddr;static MsgEventClient_t demux_client = 0;static MsgEventClient_t spu_client = 0;static char *dvdroot = NULL;//MsgEventClient_t ui_client;extern MsgEvent_t dvdroot_return_ev;extern MsgEventClient_t dvdroot_return_client;int send_demux(MsgEventQ_t *msgq, MsgEvent_t *ev) {  return MsgSendEvent(msgq, demux_client, ev, 0);}int send_spu(MsgEventQ_t *msgq, MsgEvent_t *ev) {  return MsgSendEvent(msgq, spu_client, ev, 0);}char *get_dvdroot(void) {  return dvdroot;}void free_dvdroot(void) {  if (dvdroot)    free(dvdroot);  dvdroot = NULL;}void handle_events(MsgEventQ_t *msgq, MsgEvent_t *ev){    switch(ev->type) {  case MsgEventQNotify:    //DPRINTF(1, "nav: got notification\n");    break;  case MsgEventQChangeFile:    change_file(ev->changefile.filename);    break;  case MsgEventQDecodeStreamBuf:    /*      DPRINTF(1, "video_decode: got stream %x, %x buffer \n",	    ev->decodestreambuf.stream_id,	    ev->decodestreambuf.subtype);    */    attach_stream_buffer(ev->decodestreambuf.stream_id,			 ev->decodestreambuf.subtype,			 ev->decodestreambuf.q_shmid);        break;  case MsgEventQCtrlData:    attach_ctrl_shm(ev->ctrldata.shmid);    break;  case MsgEventQGntCapability:    if((ev->gntcapability.capability & (DEMUX_MPEG2_PS | DEMUX_MPEG1))       == (DEMUX_MPEG2_PS | DEMUX_MPEG1))      demux_client = ev->gntcapability.capclient;    else if((ev->gntcapability.capability & DECODE_DVD_SPU) == DECODE_DVD_SPU)      spu_client = ev->gntcapability.capclient;    else      WARNING("capabilities not requested (%d)\n", 	      ev->gntcapability.capability);    break;  case MsgEventQDVDCtrl:    {      DVDLangID_t langid;      DVDCountryID_t country;      DVDParentalLevel_t level;      DVDPlayerRegion_t region;      switch(ev->dvdctrl.cmd.type) {      case DVDCtrlDefaultMenuLanguageSelect:	langid = ev->dvdctrl.cmd.defaultmenulanguageselect.langid;	set_sprm(0, langid);	break;      case DVDCtrlDefaultAudioLanguageSelect:	langid = ev->dvdctrl.cmd.defaultmenulanguageselect.langid;	set_sprm(16, langid);	break;      case DVDCtrlDefaultSubpictureLanguageSelect:	langid = ev->dvdctrl.cmd.defaultmenulanguageselect.langid;	set_sprm(18, langid);	break;      case DVDCtrlParentalCountrySelect:	country = ev->dvdctrl.cmd.parentalcountryselect.countryid;	set_sprm(12, country);	break;      case DVDCtrlParentalLevelSelect:	level = ev->dvdctrl.cmd.parentallevelselect.level;	set_sprm(13, level);	break;      case DVDCtrlPlayerRegionSelect:	region = ev->dvdctrl.cmd.playerregionselect.region;	set_sprm(20, region);	break;      case DVDCtrlGetCurrentDomain:      case DVDCtrlGetCurrentLocation:      case DVDCtrlGetDVDVolumeInfo:      case DVDCtrlGetTitles:      case DVDCtrlGetNumberOfPTTs:      case DVDCtrlGetCurrentAudio:      case DVDCtrlIsAudioStreamEnabled:      case DVDCtrlGetCurrentUOPS:      case DVDCtrlGetAudioAttributes:      case DVDCtrlGetCurrentSubpicture:      case DVDCtrlIsSubpictureStreamEnabled:      case DVDCtrlGetSubpictureAttributes:      case DVDCtrlGetCurrentAngle:      case DVDCtrlGetState:      case DVDCtrlGetDiscID:      case DVDCtrlGetVolIds:	{	  MsgEvent_t send_ev;	  	  send_ev.type = MsgEventQDVDCtrl;	  send_ev.dvdctrl.cmd.type = DVDCtrlRetVal;	  send_ev.dvdctrl.cmd.retval.serial =	    ev->dvdctrl.cmd.any.serial;	  send_ev.dvdctrl.cmd.retval.val = DVD_E_RootNotSet;	  MsgSendEvent(msgq, ev->any.client, &send_ev, 0);	}	break;      default:	DNOTE("unhandled dvdctrl event type (%d)\n", ev->dvdctrl.cmd.type);	break;      }    }    break;  case MsgEventQDVDCtrlLong:    switch(ev->dvdctrllong.cmd.type) {    case DVDCtrlLongSetDVDRoot:      if(dvdroot)	free(dvdroot);      dvdroot = strdup(ev->dvdctrllong.cmd.dvdroot.path);      dvdroot_return_ev.type = MsgEventQDVDCtrl;      dvdroot_return_ev.dvdctrl.cmd.type = DVDCtrlRetVal;      dvdroot_return_ev.dvdctrl.cmd.retval.serial =	ev->dvdctrllong.cmd.dvdroot.serial;      dvdroot_return_client = ev->any.client;            break;    }    break;  case MsgEventQFlushData:    /* Ignore for now */    break;  default:    DNOTE("unhandled event type (%d)\n", ev->type);    break;  }}void wait_for_init(MsgEventQ_t *msgq) {  while(!demux_client || !spu_client || !dvdroot) {    MsgEvent_t t_ev;    if(MsgNextEvent(msgq, &t_ev) != -1) {      handle_events(msgq, &t_ev);    }  }}static void change_file(char *new_filename){  int filefd;  static struct stat statbuf;  int rv;  static char *cur_filename = NULL;    // maybe close file when null ?  if(new_filename == NULL) {    return;  }  if(new_filename[0] == '\0') {    return;  }    // if same filename do nothing  if(cur_filename != NULL && strcmp(cur_filename, new_filename) == 0) {    return;  }  if(mmap_base != NULL) {    munmap(mmap_base, statbuf.st_size);  }  if(cur_filename != NULL) {    free(cur_filename);  }    filefd = open(new_filename, O_RDONLY);  if(filefd == -1) {    perror(new_filename);    exit(1);  }  cur_filename = strdup(new_filename);  rv = fstat(filefd, &statbuf);  if(rv == -1) {    perror("fstat");    exit(1);  }  mmap_base = (char *)mmap(NULL, statbuf.st_size, 			      PROT_READ, MAP_SHARED, filefd,0);  close(filefd);  if(mmap_base == MAP_FAILED) {    perror("mmap");    exit(1);  }#ifdef HAVE_MADVISE  rv = madvise(mmap_base, statbuf.st_size, MADV_SEQUENTIAL);  if(rv == -1) {    perror("madvise");    exit(1);  }#endif}static int attach_ctrl_shm(int shmid){  char *shmaddr;    if(shmid >= 0) {    if((shmaddr = shmat(shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {      perror("vmg: attach_ctrl_data(), 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_stream_buffer(uint8_t stream_id, uint8_t subtype, int shmid){  char *shmaddr;  q_head_t *q_head;  //DNOTE("shmid: %d\n", shmid);    if(shmid >= 0) {    if((shmaddr = shmat(shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {      perror("vmg: attach_decoder_buffer(), shmat()");      return -1;    }        stream_shmid = shmid;    stream_shmaddr = shmaddr;  }      q_head = (q_head_t *)stream_shmaddr;  shmid = q_head->data_buf_shmid;    if(shmid >= 0) {    if((shmaddr = shmat(shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {      perror("vmg: attach_data_buffer(), shmat()");      return -1;    }        data_buf_shmid = shmid;    data_buf_shmaddr = (unsigned char *)shmaddr;  }      return 0;}int wait_q(MsgEventQ_t *msgq, MsgEvent_t *ev) {  q_head_t *q_head;  q_elem_t *q_elems;  int elem;    if(stream_shmaddr == NULL) {    while(MsgNextEvent(msgq, ev) == -1);    return 0;  }    q_head = (q_head_t *)stream_shmaddr;  q_elems = (q_elem_t *)(stream_shmaddr+sizeof(q_head_t));  elem = q_head->read_nr;    if(!q_elems[elem].in_use) {    q_head->reader_requests_notification = 1;        while(!q_elems[elem].in_use) {      //DPRINTF(1, "vmg: waiting for notification\n");      if(MsgNextEvent(msgq, ev) != -1) {	if(ev->type == MsgEventQNotify) // Is this OK?	  continue;	return 0;      }    }  }    return 1;}int get_q(MsgEventQ_t *msgq, unsigned char *buffer){  q_head_t *q_head;  q_elem_t *q_elems;  data_buf_head_t *data_head;  data_elem_t *data_elems;  data_elem_t *data_elem;  int elem;    uint8_t *data_buffer;  //uint8_t PTS_DTS_flags;  //uint64_t PTS;  //uint64_t DTS;  uint64_t SCR_base;  uint16_t SCR_ext = 0;  uint8_t SCR_flags;  //int scr_nr;  int off;  int len;  //static int prev_scr_nr = 0;  //static int packnr = 0;  //static clocktime_t time_offset = { 0, 0 };  MsgEvent_t ev;    /* Should never hapen if you call wait_q first */  while(stream_shmaddr == NULL) {    MsgEvent_t t_ev;    if(MsgNextEvent(msgq, &t_ev) != -1) {      handle_events(msgq, &t_ev);    }  }    q_head = (q_head_t *)stream_shmaddr;  q_elems = (q_elem_t *)(stream_shmaddr+sizeof(q_head_t));  elem = q_head->read_nr;    /* Should never hapen if you call wait_q first */  if(!q_elems[elem].in_use) {    q_head->reader_requests_notification = 1;        while(!q_elems[elem].in_use) {      //DPRINTF(1, "vmg: waiting for notification\n");      if(MsgNextEvent(msgq, &ev) != -1) {	handle_events(msgq, &ev);      }    }  }  data_head = (data_buf_head_t *)data_buf_shmaddr;  data_elems = (data_elem_t *)(data_buf_shmaddr+sizeof(data_buf_head_t));  data_buffer = data_buf_shmaddr + data_head->buffer_start_offset;    data_elem = &data_elems[q_elems[elem].data_elem_index];  //PTS = q_elems[elem].PTS;  //DTS = q_elems[elem].DTS;  SCR_flags = data_elem->SCR_flags;  SCR_base = data_elem->SCR_base;  if(SCR_flags & 0x2) {    SCR_ext = data_elem->SCR_ext;  }  //scr_nr = q_elems[elem].scr_nr;    change_file(data_elem->filename);  off = data_elem->packet_data_offset;  len = data_elem->packet_data_len;    /*  if(SCR_flags & 0x1) {    fprintf(stderr, "vmg: SCR_base: %llx\n", SCR_base);  }  if(SCR_flags & 0x2) {    fprintf(stderr, "vmg: SCR_ext: %x\n", SCR_ext);  }  if(SCR_flags) {    fprintf(stderr, "vmg: SCR: %.9f\n",	    (double)(SCR_base*300+SCR_ext)/27000000.0);  } else {    fprintf(stderr, "vmg: SCR: no scr\n");  }  */  /*  //TODO release scr_nr when done  if(prev_scr_nr != scr_nr) {    ctrl_time[scr_nr].offset_valid = OFFSET_NOT_VALID;  }    if(ctrl_time[scr_nr].offset_valid == OFFSET_NOT_VALID) {    if(PTS_DTS_flags && 0x2) {      set_time_base(PTS, ctrl_time, scr_nr, time_offset);    }  }  if(PTS_DTS_flags && 0x2) {    time_offset = get_time_base_offset(PTS, ctrl_time, scr_nr);  }  prev_scr_nr = scr_nr;  */  /*  fprintf(stderr, "vmg: flags: %01x, pts: %llx, dts: %llx\noff: %d, len: %d\n",	  PTS_DTS_flags, PTS, DTS, off, len);  */    //  memcpy(buffer, mmap_base + off, len);  memcpy(buffer, data_buffer + off, len);      // release elem  data_elem->in_use = 0;  q_elems[elem].in_use = 0;  q_head->read_nr = (q_head->read_nr+1)%q_head->nr_of_qelems;  if(q_head->writer_requests_notification) {    q_head->writer_requests_notification = 0;    ev.type = MsgEventQNotify;    if(MsgSendEvent(msgq, q_head->writer, &ev, 0) == -1) {      WARNING("%s", "couldn't send notification\n");    }  }  return len;}

⌨️ 快捷键说明

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