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

📄 ctrl.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <fcntl.h>#include <unistd.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/msg.h>#include <limits.h>#include <string.h>#include <errno.h>#include <signal.h>#include <ogle/msgevents.h>#include "mpeg.h"#include "common.h"#include "queue.h"#include "timemath.h"#include "debug_print.h"#ifndef SHM_SHARE_MMU#define SHM_SHARE_MMU 0#endif/* SA_SIGINFO isn't implemented yet on for example NetBSD */#if !defined(SA_SIGINFO)#define siginfo_t void#endifint create_msgq(void);int init_decoder(char *msgqid_str, char *decoderstr);int get_buffer(int size, shm_bufinfo_t *bufinfo);int create_q(int nr_of_elems, int buf_shmid, 	     MsgEventClient_t writer, MsgEventClient_t reader);int create_ctrl_data(void);int register_stream(uint8_t stream_id, uint8_t subtype);static void handle_events(MsgEventQ_t *q, MsgEvent_t *ev);void int_handler(int sig);void sigchld_handler(int sig, siginfo_t *info, void* context);void remove_q_shm(void);void add_q_shmid(int shmid);void remove_q_shmid(int shmid);void destroy_msgq(void);void add_to_pidlist(pid_t pid, char *name);int remove_from_pidlist(pid_t pid);void cleanup_and_exit(void);void slay_children(void);int msgqid;int ctrl_data_shmid;ctrl_data_t *ctrl_data;char *program_name;int dlevel;char msgqid_str[9];char *input_file;char *framerate = NULL;char *output_bufs = NULL;char *file_offset = NULL;char *videodecode_debug = NULL;char *demux_debug = NULL;int ac3_audio_stream = -1;int dts_audio_stream = -1;int mpeg_audio_stream = -1;int lpcm_audio_stream = -1;int mpeg_video_stream = -1;int subpicture_stream = -1;int nav_stream = -1;char *ui = NULL;static int child_killed = 0;void usage(void){  fprintf(stderr, "Usage: %s [-h] [-u cli|gui] [<path>]\n", program_name);  //"[-a <ac3_stream#>] [-m <mpeg_audio_stream#>] [-p <pcm_audio_stream#>] [-v <mpeg_video_stream#>] [-s <subpicture_stream#>] [-n] [-f <fps>] [-r <#ouput_bufs>] [-o <file_offset>] [-d <videodebug_level>] [-D <demuxdebug_level>] <input file>\n", program_name);}int next_client_id = CLIENT_UNINITIALIZED+1;int demux_registered = 0;MsgEventClient_t demux_client;typedef enum {  CAP_started = 1,  CAP_running = 2} cap_state_t;/*  * a client can offer several different capabilities. * a client can offer several instances of the same capability. * several instances of the same client can exist. * an instance of a client can be identified by its MsgEventClient_t * a client ca be in two states, Started: it has been exec'd but * haven't registered itself. * Running: the client has registered itself and is ready. */typedef struct _capability_t {  struct _capability_t *next;  int capability;  int nr_of_instances;  int instances_in_use;} capability_t;typedef struct {  MsgEventClient_t client;          // client id  int capabilities;                 // mask of all capabilities the client has  capability_t *used_capabilities;  // list of the capabilities in use  cap_state_t state;                // started, running  pid_t pid;                        // pid of client  char *exec_name;                  // file name of executable} process_info_t;typedef struct {  MsgEventClient_t client;  int caps;  cap_state_t state;  char *executable_file;} caps_t;static caps_t *caps_array = NULL;static int nr_caps = 0;int register_capabilities(MsgEventClient_t client, int caps, cap_state_t state){  if(nr_caps >= 20) {    WARNING("%s", "more than 20 capabilities registered\n");  }  nr_caps++;  caps_array = realloc(caps_array, sizeof(caps_t)*nr_caps);  caps_array[nr_caps-1].client = client;  caps_array[nr_caps-1].caps = caps;  caps_array[nr_caps-1].state = state;  return 0;}int search_capabilities(int caps, MsgEventClient_t *client, int *ret_caps,			cap_state_t *ret_state){  int n;  int nr = 0;  if(client != NULL) {    *client = CLIENT_NONE;  }#if DEBUG  DNOTE("searching cap: %d\n", caps);#endif    for(n = 0; n < nr_caps; n++) {    if((caps_array[n].caps & caps) == caps) {      nr++;      if(client != NULL) {	*client = caps_array[n].client;#if DEBUG        DNOTE("found capclient: %ld\n", *client);#endif      }      if(ret_caps != NULL) {	*ret_caps = caps_array[n].caps;#if DEBUG	DNOTE("found cap: %x\n", *ret_caps);#endif      }#if DEBUG      DNOTE("state cap: %d\n", caps_array[n].state);#endif      if(ret_state != NULL) {	*ret_state = caps_array[n].state;      }    }  }    return nr;}static int streamid_to_capability(uint8_t stream_id, uint8_t subtype){  int cap = 0;  if(stream_id == MPEG2_PRIVATE_STREAM_1) {    if((subtype >= 0x80) && (subtype < 0x88)) {      cap = DECODE_AC3_AUDIO;    } else if((subtype >= 0x88) && (subtype < 0x90)) {      cap = DECODE_DTS_AUDIO;          } else if((subtype >= 0xA0) && (subtype < 0xA8)) {      cap = DECODE_LPCM_AUDIO;          } else if((subtype >= 0x20) && (subtype < 0x40)) {      cap = DECODE_DVD_SPU;    }      } else if((stream_id >= 0xc0) && (stream_id < 0xe0)) {    cap = DECODE_MPEG1_AUDIO | DECODE_MPEG2_AUDIO;      } else if((stream_id >= 0xe0) && (stream_id < 0xf0)) {    cap = DECODE_MPEG1_VIDEO | DECODE_MPEG2_VIDEO;      } else if(stream_id == MPEG2_PRIVATE_STREAM_2) {    cap = DECODE_DVD_NAV;  }    return cap;}static char *streamid_to_decoderstr(uint8_t stream_id, uint8_t subtype){  char *name = NULL;  if(stream_id == MPEG2_PRIVATE_STREAM_1) {    if((subtype >= 0x80) && (subtype < 0x88)) {      name = getenv("DVDP_AC3");          } else if((subtype >= 0x88) && (subtype < 0x90)) {      name = getenv("DVDP_DTS");    } else if((subtype >= 0xA0) && (subtype < 0xA8)) {      name = getenv("DVDP_LPCM");    } else if((subtype >= 0x20) && (subtype < 0x40)) {      name = getenv("DVDP_SPU");    }      } else if((stream_id >= 0xc0) && (stream_id < 0xe0)) {    name = getenv("DVDP_MPEGAUDIO");      } else if((stream_id >= 0xe0) && (stream_id < 0xf0)) {    name = getenv("DVDP_VIDEO");      } else if(stream_id == MPEG2_PRIVATE_STREAM_2) {    name = getenv("DVDP_VMG");  }    return name;}static char *capability_to_decoderstr(int capability, int *ret_capability){  char *name = NULL;      if((capability & DECODE_AC3_AUDIO) == capability) {    name = getenv("DVDP_AC3");    *ret_capability = DECODE_AC3_AUDIO;  } else if((capability & DECODE_DTS_AUDIO) == capability) {    name = getenv("DVDP_DTS");    *ret_capability = DECODE_DTS_AUDIO;  } else if((capability & (DECODE_MPEG1_AUDIO | DECODE_MPEG2_AUDIO))	    == capability) {    name = getenv("DVDP_MPEGAUDIO");    *ret_capability = DECODE_MPEG1_AUDIO | DECODE_MPEG2_AUDIO;  } else if((capability & DECODE_DVD_SPU) == capability) {    name = getenv("DVDP_SPU");    *ret_capability = (DECODE_DVD_SPU | VIDEO_OUTPUT);  } else if((capability & (DECODE_MPEG1_VIDEO | DECODE_MPEG2_VIDEO))	    == capability) {    name = getenv("DVDP_VIDEO");    *ret_capability = DECODE_MPEG1_VIDEO | DECODE_MPEG2_VIDEO;  } else if((capability & (DEMUX_MPEG1 | DEMUX_MPEG2_PS))	    == capability) {    name = getenv("DVDP_DEMUX");    *ret_capability = DEMUX_MPEG1 | DEMUX_MPEG2_PS;  } else if((capability & (UI_DVD_CLI))	    == capability) {    name = getenv("DVDP_CLI_UI");    *ret_capability = UI_DVD_CLI;  } else if((capability & (DECODE_DVD_NAV))	    == capability) {    name = getenv("DVDP_VMG");    *ret_capability = DECODE_DVD_NAV;  } else if((capability & (UI_DVD_GUI))	    == capability) {    name = getenv("DVDP_UI");    *ret_capability = UI_DVD_GUI;  } else if((capability & VIDEO_OUTPUT) == capability) {    name = getenv("DVDP_VIDEO_OUT");    *ret_capability = (DECODE_DVD_SPU | VIDEO_OUTPUT);  }  return name;}static void cleanup(void){  //DNOTE("waiting for children to really die\n");     while(sleep(2)); // Continue sleeping if interupted   slay_children();  cleanup_and_exit();}int request_capability(MsgEventQ_t *q, int cap,		       MsgEventClient_t *capclient, int *retcaps){  MsgEvent_t r_ev;  char *decodername;  cap_state_t state = 0;#if DEBUG  DNOTE("_MsgEventQReqCapability\n");#endif    if(!search_capabilities(cap, capclient, retcaps, &state)) {    int fullcap;        decodername = capability_to_decoderstr(cap, &fullcap);	    if(decodername != NULL) {      register_capabilities(0,			    fullcap,			    CAP_started);          //DNOTE("starting decoder %d %s\n", fullcap, decodername);      init_decoder(msgqid_str, decodername);    }      }    while(search_capabilities(cap, capclient, retcaps, &state) &&	(state != CAP_running)) {    if(child_killed) {      cleanup();    }    if(MsgNextEventInterruptible(q, &r_ev) == -1) {      switch(errno) {      case EINTR:	continue;	break;      }    }    handle_events(q, &r_ev);  }    if(state == CAP_running) {#if DEBUG    DNOTE("sending ctrldata\n");#endif    r_ev.type = MsgEventQCtrlData;    r_ev.ctrldata.shmid = ctrl_data_shmid;        MsgSendEvent(q, *capclient, &r_ev, 0);        return 1;  } else {    ERROR("%s", "didn't find capability\n");    return 0;  }}static void handle_events(MsgEventQ_t *q, MsgEvent_t *ev){  MsgEvent_t s_ev;  MsgEvent_t r_ev;  MsgEventClient_t rcpt;  char *decodername;  int capability;    switch(ev->type) {  case MsgEventQInitReq:#if DEBUG    DNOTE("_MsgEventQInitReq, new_id: %d\n", next_client_id);#endif    ev->type = MsgEventQInitGnt;    ev->initgnt.newclientid = next_client_id++;    MsgSendEvent(q, CLIENT_UNINITIALIZED, ev, 0);    break;  case MsgEventQRegister:#if DEBUG    DNOTE("_MsgEventQRegister\n");#endif    register_capabilities(ev->registercaps.client,			  ev->registercaps.capabilities,			  CAP_running);    break;  case MsgEventQReqCapability:    {      MsgEvent_t retev;      retev.type = MsgEventQGntCapability;            if(request_capability(q, ev->reqcapability.capability,			    &retev.gntcapability.capclient,			    &retev.gntcapability.capability)) {	MsgSendEvent(q, ev->reqcapability.client, &retev, 0);      } else {	retev.gntcapability.client = CLIENT_NONE;	MsgSendEvent(q, ev->reqcapability.client, &retev, 0);      }    }    break;  case MsgEventQReqBuf:    {      shm_bufinfo_t bufinfo;      #if DEBUG      DNOTE("_got request for buffer size %d\n",	      ev->reqbuf.size);#endif      if(get_buffer(ev->reqbuf.size, &bufinfo) == -1) {	bufinfo.shmid = -1;      }            s_ev.type = MsgEventQGntBuf;      s_ev.gntbuf.shmid = bufinfo.shmid;      s_ev.gntbuf.size = bufinfo.size;      MsgSendEvent(q, ev->reqbuf.client, &s_ev, 0);    }    break;  case MsgEventQDestroyBuf:    {      //DNOTE("_got destroy buffer shmid %d\n", ev->destroybuf.shmid);      remove_q_shmid(ev->destroybuf.shmid);    }    break;  case MsgEventQDestroyQ:    {      //DNOTE("_got destroy Q shmid %d\n", ev->detachq.q_shmid);      remove_q_shmid(ev->detachq.q_shmid);    }    break;  case MsgEventQReqStreamBuf:    {      int shmid;      cap_state_t state = 0;            DNOTE("_new stream %x, %x\n",	    ev->reqstreambuf.stream_id,	    ev->reqstreambuf.subtype);            if(register_stream(ev->reqstreambuf.stream_id,			 ev->reqstreambuf.subtype)) {	// this stream is wanted			// check if we have a decoder		//TODO check which decoder handles the stream and start it	//if there isn't already one running that is free to use	// TODO clean up logic/functions		capability = streamid_to_capability(ev->reqstreambuf.stream_id,					    ev->reqstreambuf.subtype);	// check if there is a decoder running or started	if(!search_capabilities(capability, &rcpt, NULL, NULL)) {	  	  decodername = streamid_to_decoderstr(ev->reqstreambuf.stream_id,					       ev->reqstreambuf.subtype);	  	  if((capability & VIDEO_OUTPUT) || (capability & DECODE_DVD_SPU)) {	    DNOTE("%s", "registered VO or SPU started\n");	  }	  if(capability == DECODE_DVD_SPU) {	    register_capabilities(0,				  DECODE_DVD_SPU | VIDEO_OUTPUT,				  CAP_started);	  } else {	    	    register_capabilities(0,				  capability,				  CAP_started);	  } // DNOTE("starting decoder %d %s\n", capability, decodername);	  init_decoder(msgqid_str, decodername); // DNOTE("started decoder %d\n", capability);	}		while(!search_capabilities(capability, &rcpt, NULL, &state) ||	      (state != CAP_running)) {

⌨️ 快捷键说明

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