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

📄 nav.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Ogle - A video player * Copyright (C) 2000, 2001 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 <inttypes.h>#include <string.h>#include <assert.h>#include <time.h>#include <ogle/msgevents.h>#include <ogle/dvdevents.h>#include "debug_print.h"#include <dvdread/nav_types.h>#include <dvdread/nav_read.h>#include <dvdread/nav_print.h>#include "vm.h"#include "interpret_config.h"extern int wait_q(MsgEventQ_t *msgq, MsgEvent_t *ev); // com.cextern int get_q(MsgEventQ_t *msgq, unsigned char *buffer);extern void wait_for_init(MsgEventQ_t *msgq);extern void handle_events(MsgEventQ_t *msgq, MsgEvent_t *ev);extern int send_demux(MsgEventQ_t *msgq, MsgEvent_t *ev);extern int send_spu(MsgEventQ_t *msgq, MsgEvent_t *ev);extern char *get_dvdroot(void);extern void free_dvdroot(void);extern dvd_state_t state;extern unsigned char discid[16];MsgEvent_t dvdroot_return_ev;MsgEventClient_t dvdroot_return_client;static void do_run(void);static int process_user_data(MsgEvent_t ev, pci_t *pci, dsi_t *dsi,			     cell_playback_t *cell, 			     int block, int *still_time);static void time_convert(DVDTimecode_t *dest, dvd_time_t *source){  dest->Hours   = bcd2int(source->hour);  dest->Minutes = bcd2int(source->minute);  dest->Seconds = bcd2int(source->second);  dest->Frames  = bcd2int(source->frame_u & 0x3f);}MsgEventQ_t *msgq;char *program_name;int dlevel;void usage(void){  fprintf(stderr, "Usage: %s  -m <msgqid>\n",           program_name);}int main(int argc, char *argv[]){  int msgqid = -1;  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();      exit(1);    }  }    if(msgqid == -1) {    fprintf(stderr, "what?\n");    exit(1);  }  srand(getpid());  {    MsgEvent_t ev;        if((msgq = MsgOpen(msgqid)) == NULL) {      FATAL("%s", "couldn't get message q\n");      exit(1);    }        ev.type = MsgEventQRegister;    ev.registercaps.capabilities = DECODE_DVD_NAV;    if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) {      FATAL("%s", "registering capabilities\n");      exit(1);    }        ev.type = MsgEventQReqCapability;    ev.reqcapability.capability = DEMUX_MPEG2_PS | DEMUX_MPEG1;    if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) {      FATAL("%s", "didn't get demux cap\n");      exit(1);    }        ev.type = MsgEventQReqCapability;    ev.reqcapability.capability = DECODE_DVD_SPU;    if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) {      FATAL("%s", "didn't get spu cap\n");      exit(1);    }        vm_reset();    interpret_config();    while(1) {      wait_for_init(msgq);          /*  Call start here */      // hack placed here because it calls DVDOpen...      DNOTE("Opening DVD at \"%s\"\n", get_dvdroot());      if(vm_init(get_dvdroot()) == -1) {	// Failure, don't quit... just let the app know we didn't succeed	dvdroot_return_ev.dvdctrl.cmd.retval.val = DVD_E_RootNotSet;	MsgSendEvent(msgq, dvdroot_return_client, &dvdroot_return_ev, 0);	free_dvdroot();      } else {	// Success, send ok and breakout of loop	dvdroot_return_ev.dvdctrl.cmd.retval.val = DVD_E_Ok;	MsgSendEvent(msgq, dvdroot_return_client, &dvdroot_return_ev, 0);	break;      }    }        ev.type = MsgEventQDemuxDVDRoot;    strncpy(ev.demuxdvdroot.path, get_dvdroot(), sizeof(ev.demuxdvdroot.path));    ev.demuxdvdroot.path[sizeof(ev.demuxdvdroot.path)-1] = '\0';    if(send_demux(msgq, &ev) == -1) {      FATAL("%s", "failed sending dvdroot to demuxer\n");      exit(1);    }        ev.type = MsgEventQDemuxStream;    ev.demuxstream.stream_id = 0xe0; // Mpeg1/2 Video     ev.demuxstream.subtype = 0;        if(send_demux(msgq, &ev) == -1) {      FATAL("%s", "failed setting demux video stream id\n");      exit(1);    }        ev.type = MsgEventQDemuxStream;    ev.demuxstream.stream_id = 0xbd; // AC3 1    ev.demuxstream.subtype = 0x80;        if(send_demux(msgq, &ev) == -1) {      FATAL("%s", "failed setting demux AC3 stream id\n");      exit(1);    }        ev.type = MsgEventQDemuxStream;    ev.demuxstream.stream_id = 0xbd; // SPU 1    ev.demuxstream.subtype = 0x20;        if(send_demux(msgq, &ev) == -1) {      FATAL("%s", "failed setting demux subpicture stream id\n");      exit(1);    }        ev.type = MsgEventQDemuxStream;    ev.demuxstream.stream_id = 0xbf; // NAV    ev.demuxstream.subtype = 0;        if(send_demux(msgq, &ev) == -1) {      FATAL("%s", "failed setting demux NAV stream id\n");      exit(1);    }  }    //vm_reset(get_dvdroot());  do_run();    return 0;}/** * Update any info the demuxer needs, and then tell the demuxer * what range of sectors to process. */static void send_demux_sectors(int start_sector, int nr_sectors, 			       FlowCtrl_t flush) {  static int video_aspect = -1;  //  static int audio_stream_id = -1;  static int subp_stream_id = -1;  MsgEvent_t ev;    /* Tell video out what aspect ratio this pice has */   {    video_attr_t attr = vm_get_video_attr();    if(attr.display_aspect_ratio != video_aspect) {      video_aspect = attr.display_aspect_ratio;            //DNOTE("sending aspect %s\n", video_aspect ? "16:9" : "4:3");            ev.type = MsgEventQSetSrcAspect;      ev.setsrcaspect.mode_src = AspectModeSrcVM;      if(video_aspect) {	ev.setsrcaspect.aspect_frac_n = 16;	ev.setsrcaspect.aspect_frac_d = 9;      } else {	ev.setsrcaspect.aspect_frac_n = 4;	ev.setsrcaspect.aspect_frac_d = 3;      }      /* !!! FIXME should be sent to video out not spu */      if(send_spu(msgq, &ev) == -1) {	ERROR("%s", "failed to send aspect info\n");      }    }       }  /* Tell the demuxer which audio stream to demux */   {    int sN = vm_get_audio_stream(state.AST_REG);    if(sN < 0 || sN > 7) sN = 7; // XXX == -1 for _no audio_    {      static uint8_t old_id = 0xbd;      static uint8_t old_subtype = 0x80;      uint8_t new_id;      uint8_t new_subtype;      audio_attr_t attr;      int audio_stream_id = sN;            new_id = 0;      new_subtype = 0;            attr = vm_get_audio_attr(sN);            switch(attr.audio_format) {      case 0:	//af = DVD_AUDIO_FORMAT_AC3;	new_id = 0xbd; //private stream 1	new_subtype = 0x80 + audio_stream_id; // AC-3	break;      case 2:	//af = DVD_AUDIO_FORMAT_MPEG1;	new_id = 0xC0 + audio_stream_id; //mpeg audio      case 3:	//af = DVD_AUDIO_FORMAT_MPEG2;	new_id = 0xC0 + audio_stream_id; //mpeg audio	break;      case 4:	//af = DVD_AUDIO_FORMAT_LPCM;	new_id = 0xbd; //private stream 1	new_subtype = 0xA0 + audio_stream_id; // lpcm	break;      case 6:	//af = DVD_AUDIO_FORMAT_DTS;	new_id = 0xbd; //private stream 1	new_subtype = 0x88 + audio_stream_id; // dts	break;      default:	NOTE("%s", "please send a bug report, unknown Audio format!");	break;      }            if(old_id != new_id || old_subtype != new_subtype) {	DNOTE("sending audio demuxstream %d\n", sN);	DNOTE("oid: %02x, ost: %02x, nid: %02x, nst: %02x\n",	      old_id, old_subtype, new_id, new_subtype);	ev.type = MsgEventQDemuxStreamChange2;	ev.demuxstreamchange2.old_stream_id = old_id;	ev.demuxstreamchange2.old_subtype = old_subtype;	ev.demuxstreamchange2.new_stream_id = new_id;	ev.demuxstreamchange2.new_subtype = new_subtype;	if(send_demux(msgq, &ev) == -1) {	  ERROR("%s", "failed to send audio demuxstream\n");	}      }      old_id = new_id;      old_subtype = new_subtype;    }  }  /* Tell the demuxer which subpicture stream to demux */   {    int sN = vm_get_subp_active_stream();    if(sN < 0 || sN > 31) sN = 31; // XXX == -1 for _no audio_    if(sN != subp_stream_id) {      subp_stream_id = sN;            DNOTE("sending subp demuxstream %d\n", sN);          ev.type = MsgEventQDemuxStreamChange;      ev.demuxstreamchange.stream_id = 0xbd; // SPU      ev.demuxstreamchange.subtype = 0x20 | subp_stream_id;      if(send_demux(msgq, &ev) == -1) {	ERROR("%s", "failed to send Subpicture demuxstream\n");      }    }  }  /* Tell the demuxer what file and which sectors to demux. */  ev.type = MsgEventQDemuxDVD;  if(state.domain == VMGM_DOMAIN || state.domain == FP_DOMAIN)    ev.demuxdvd.titlenum = 0;  else    ev.demuxdvd.titlenum = state.vtsN;  if(state.domain == VTS_DOMAIN)    ev.demuxdvd.domain = DVD_READ_TITLE_VOBS;  else    ev.demuxdvd.domain = DVD_READ_MENU_VOBS;  ev.demuxdvd.block_offset = start_sector;  ev.demuxdvd.block_count = nr_sectors;  ev.demuxdvd.flowcmd = flush;  if(send_demux(msgq, &ev) == -1) {    FATAL("%s", "failed to send demux dvd block range\n");    exit(1);  }  //DNOTE("sent demux dvd block range (%d,%d)\n", start_sector, nr_sectors);}static void send_spu_palette(uint32_t palette[16]) {  MsgEvent_t ev;  int i;    ev.type = MsgEventQSPUPalette;  for(i = 0; i < 16; i++) {    ev.spupalette.colors[i] = palette[i];  }    //DNOTE("sending subpicture palette\n");    if(send_spu(msgq, &ev) == -1) {    ERROR("%s", "failed sending subpicture palette\n");  }}static void send_highlight(int x_start, int y_start, int x_end, int y_end, 			   uint32_t btn_coli) {  MsgEvent_t ev;  int i;    ev.type = MsgEventQSPUHighlight;  ev.spuhighlight.x_start = x_start;  ev.spuhighlight.y_start = y_start;  ev.spuhighlight.x_end = x_end;  ev.spuhighlight.y_end = y_end;  for(i = 0; i < 4; i++)    ev.spuhighlight.color[i] = 0xf & (btn_coli >> (16 + 4*i));  for(i = 0; i < 4; i++)    ev.spuhighlight.contrast[i] = 0xf & (btn_coli >> (4*i));  if(send_spu(msgq, &ev) == -1) {    ERROR("%s", "faild sending highlight info\n");  }}/**  * Check if mouse coords are over any highlighted area. *  * @return The button number if the the coordinate is enclosed in the area. * Zero otherwise. */int mouse_over_hl(pci_t *pci, unsigned int x, unsigned int y) {  int button = 1;  while(button <= pci->hli.hl_gi.btn_ns) {    if( (x >= pci->hli.btnit[button-1].x_start)	&& (x <= pci->hli.btnit[button-1].x_end) 	&& (y >= pci->hli.btnit[button-1].y_start) 	&& (y <= pci->hli.btnit[button-1].y_end ))       return button;    button++;  }  return 0;}/**  * Update the highligted button in response to an input event. * Also send highlight information to the spu_mixer. * * @return One if the (possibly updated) button is activated. * Zero otherwise. */static int process_button(DVDCtrlEvent_t *ce, pci_t *pci, uint16_t *btn_reg) {  /* Keep the button register value in a local variable. */  uint16_t button_nr = (*btn_reg) >> 10;  int tmp, is_action = 0;  /* MORE CODE HERE :) */    /* Paranoia.. */    // No highlight/button pci info to use or no buttons  if((pci->hli.hl_gi.hli_ss & 0x03) == 0 || pci->hli.hl_gi.btn_ns == 0)    return 0;    // Selected button > than max button? then cap it  if(button_nr > pci->hli.hl_gi.btn_ns)    button_nr = pci->hli.hl_gi.btn_ns;    // Selected button should never be 0.  if(button_nr == 0) {    //FATAL("%s", "send bug report, button number is 0, this is invalid.");    button_nr = 1;    *btn_reg = button_nr << 10;  }       switch(ce->type) {  case DVDCtrlUpperButtonSelect:    button_nr = pci->hli.btnit[button_nr - 1].up;    break;  case DVDCtrlLowerButtonSelect:    button_nr = pci->hli.btnit[button_nr - 1].down;    break;  case DVDCtrlLeftButtonSelect:    button_nr = pci->hli.btnit[button_nr - 1].left;    break;  case DVDCtrlRightButtonSelect:    button_nr = pci->hli.btnit[button_nr - 1].right;    break;  case DVDCtrlButtonActivate:    is_action = 1;    break;  case DVDCtrlButtonSelectAndActivate:    is_action = 1;    /* Fall through */  case DVDCtrlButtonSelect:    tmp = ce->button.nr - pci->hli.hl_gi.btn_ofn;    if(tmp > 0 && tmp <= pci->hli.hl_gi.nsl_btn_ns)      button_nr = tmp;    else /* not a valid button */      is_action = 0;    break;  case DVDCtrlMouseActivate:    is_action = 1;    /* Fall through */  case DVDCtrlMouseSelect:

⌨️ 快捷键说明

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