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

📄 programstream.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 <string.h>#include <signal.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>#include <ogle/msgevents.h>#include <dvdread/dvd_reader.h>#include "debug_print.h"#include "ogle_endian.h"#include "programstream.h"#include "common.h"#include "queue.h"#include "mpeg.h"#ifndef SHM_SHARE_MMU#define SHM_SHARE_MMU 0#endiftypedef enum {  STREAM_NOT_REGISTERED = 0,  STREAM_DISCARD = 1,  STREAM_DECODE = 2,  STREAM_MUTED = 3} stream_state_t;  typedef struct {  int infile;  FILE *file;  int shmid;  char *shmaddr;  stream_state_t state; // not_registerd, in_use, muted, ...} buf_data_t;buf_data_t id_reg[256];buf_data_t id_reg_ps1[256];int register_id(uint8_t id, int subtype);int id_registered(uint8_t id, uint8_t subtype);int init_id_reg(stream_state_t default_state);//int wait_for_msg(mq_cmdtype_t cmdtype);//int eval_msg(mq_cmd_t *cmd);int get_buffer(int size);int attach_decoder_buffer(uint8_t stream_id, uint8_t subtype, int shmid);int id_stat(uint8_t id, uint8_t subtype);char *id_qaddr(uint8_t id, uint8_t subtype);FILE *id_file(uint8_t id, uint8_t subtype);void id_add(uint8_t stream_id, uint8_t subtype, stream_state_t state, int shmid, char *shmaddr, FILE *file);int put_in_q(char *q_addr, int off, int len, uint8_t PTS_DTS_flags,	     uint64_t PTS, uint64_t DTS, int is_new_file, int extra_cmd,	     PacketType_t packet_type, uint32_t packet_offset);int attach_buffer(int shmid, int size);//int chk_for_msg(void);void loadinputfile(char *infilename);void add_to_demux_q(MsgEvent_t *ev);static void handle_events(MsgEvent_t *ev);int id_infile(uint8_t id, uint8_t subtype);void id_setinfile(uint8_t id, uint8_t subtype, int newfile);uint8_t type_registered(uint8_t id, uint8_t subtype);int switch_to_stream(uint8_t id, uint8_t subtype);int switch_from_to_stream(uint8_t oldid, uint8_t oldsubtype,			  uint8_t newid, uint8_t newsubtype);int id_has_output(uint8_t stream_id, uint8_t subtype);int id_get_output(uint8_t id, int subtype);typedef struct {  uint8_t *buf_start;  int len;  int in_use;} q_elem;static int msgqid = -1;static MsgEventQ_t *msgq;int scr_discontinuity = 0;uint64_t SCR_base;uint16_t SCR_ext;uint8_t SCR_flags;int packnr = 0;#define MPEG1 0x0#define MPEG2 0x1uint8_t    *disk_buf;int shmid;char *shmaddr;int shmsize;static int ctrl_data_shmid;static ctrl_data_t *ctrl_data;static ctrl_time_t *ctrl_time;char *data_buf_addr;int off_from;int off_to;int demux_cmd;extern char *optarg;extern int   optind, opterr, optopt;/* Variables for getbits */unsigned int bits_left = 64;uint64_t     cur_word = 0;unsigned int nextbits(unsigned int nr_of_bits);int synced = 0;int audio       = 0;int debug       = 0;char *program_name;int dlevel;FILE *video_file;FILE *audio_file;FILE *subtitle_file;FILE *ps1_file;int video_stream = -1;int   infilefd;void* infileaddr;long  infilelen;uint32_t offs;char cur_filename[PATH_MAX+1];int new_file;// #define DEBUG#ifdef STATS    static uint32_t stat_video_unaligned_packet_offset = 0;    static uint32_t stat_video_unaligned_packet_end    = 0;    static uint32_t stat_video_n_packets               = 0;    static uint32_t stat_audio_n_packets               = 0;    static uint32_t stat_subpicture_n_packets          = 0;    static uint32_t stat_n_packets                     = 0;#endif //STATSvoid usage(void){  fprintf(stderr, "Usage: %s [-v <video file>] [-a <audio file>] [-s <subtitle file> -i <subtitle_id>] [-p subid=<substreambaseid>,nr=<streamnr>,file=<outputfile>] [-d <debug level>] <input file>\n", 	  program_name);}/* 2.3 Definition of bytealigned() function */int bytealigned(void){  return !(bits_left%8);}#ifdef DEBUG#define GETBITS(a,b) getbits(a,b)#else#define GETBITS(a,b) getbits(a)#endif#ifdef DEBUGuint32_t getbits(unsigned int nr, char *func)#elsestatic inline uint32_t getbits(unsigned int nr)#endif{  uint32_t result;    result = (cur_word << (64-bits_left)) >> 32;  result = result >> (32-nr);  bits_left -=nr;  if(bits_left <= 32) {    uint32_t new_word = FROM_BE_32(*(uint32_t *)(&disk_buf[offs]));    offs+=4;    cur_word = (cur_word << 32) | new_word;    bits_left = bits_left+32;  }    DPRINTF(5, "%s getbits(%u): %0*i, 0x%0*x, ",              func, nr, (nr-1)/3+1, result, (nr-1)/4+1, result);  DPRINTBITS(6, nr, result);  DPRINTF(5, "\n");    return result;}static inline void drop_bytes(int len){    uint rest;  uint todo;  // This is always byte-aligned. Trust us.  len  -= bits_left/8;  rest  = len % 4;  offs += (len - rest);  todo  = bits_left+rest*8;  while(todo > 32) {    GETBITS(32, "skip");    todo -= 32;  }  GETBITS(todo, "skip");  return;}#if 1static dvd_reader_t *dvdroot;static dvd_file_t *dvdfile;int dvd_open_root(char *path){    if((dvdroot = DVDOpen(path)) == NULL) {    FATAL("%s", "Couldn't open dvd\n");    exit(1);  }    return 0;} int dvd_close_root(void) {  DVDClose(dvdroot);    return 0;}static int dvd_file_num = -1;static dvd_read_domain_t dvd_file_dom = -1;int dvd_change_file(int titlenum, dvd_read_domain_t domain){  // If same as current do nothing  if(titlenum == dvd_file_num && domain == dvd_file_dom) {    return 0;  }  if(dvdfile != NULL && dvdroot != NULL) {    //fprintf(stderr, "demux: closing open file when opening new\n");    DVDCloseFile(dvdfile);  }  if((dvdfile = DVDOpenFile(dvdroot, titlenum, domain)) == NULL) {    FATAL("%s", "Couldn't open dvdfile\n");    exit(1);  }  dvd_file_num = titlenum;  dvd_file_dom = domain;  return 0;}void dvd_close_file(void){  DVDCloseFile(dvdfile);  dvd_file_num = -1;  dvd_file_dom = -1;  }int dvd_read_block(char *buf, int boffset, int nblocks){  int blocks_read;  int tries = 0;  do {    blocks_read = DVDReadBlocks(dvdfile, boffset, nblocks, buf);        switch(blocks_read) {    case -1:      FATAL("%s", "dvdreadblocks failed\n");      exit(1);    case 0:      WARNING("%s", "dvdreadblocks returned 0\n");      if(tries > 3) {	fprintf(stderr, "\n\n" "Ogle can't read any data.\n""Make sure that the CSS authentication works correctly.\n""See also the FAQ at http://www.dtek.chalmers.se/~dvd/faq.shtml\n""Three common problems are:\n""no write permission on you DVD drives device node.\n""you are trying to play a DVD from a region other than the one \n""of the DVD drive.\n""or you have never set the region on the drive.\n\n""For setting the region; a program called regionset will do this.\n""Search for dvd_disc or dvdkit on freshmeat.net\n""Beware that you can only sset the region 5 times!\n\n");	exit(1);      }      tries++;      break;    default:      break;    }    if(blocks_read != nblocks) {      WARNING("dvdreadblocks only got %d, wanted %d\n",	      blocks_read, nblocks);    }    buf += blocks_read * 2048;    nblocks -= blocks_read;    boffset += blocks_read;  } while(nblocks > 0);  return 0;}int fill_buffer(int title, dvd_read_domain_t domain, int boffset, int nblocks){  int next_write_pos;  static int free_block_offs = 0;  data_buf_head_t *data_buf_head;  data_elem_t *data_elems;  int data_elem_nr;  int buf_empty = 0;  int first_data_elem_nr;  int off;  int blocks_in_buf;  int size;  //fprintf(stderr, "demux: fill_buffer: title: %d, domain: %d, off: %d, blocks: %d\n", title, domain, boffset, nblocks);    //  get_next_demux_range(&title, &domain, &boffset, &blocks);    data_buf_head = (data_buf_head_t *)data_buf_addr;  if(data_buf_head == NULL) {    fprintf(stderr, "*demux: fill_buffer, no buffer\n");    exit(1);  }  blocks_in_buf = data_buf_head->buffer_size/2048;  //fprintf(stderr, "blocks_in_buf: %d\n", blocks_in_buf);  data_elems = (data_elem_t *)(data_buf_addr+sizeof(data_buf_head_t));  data_elem_nr = data_buf_head->write_nr;    first_data_elem_nr = data_elem_nr;  //fprintf(stderr, "first_data_elem_nr: %d\n", first_data_elem_nr);  while(1) {    if(data_elems[data_elem_nr].in_use || buf_empty) {      /* this block is in use, check if we have enough free space */            /* offset in buffer of the used block we found */      if(buf_empty) {	off = blocks_in_buf;	free_block_offs = 0;      } else {	off = data_elems[data_elem_nr].packet_offset / 2048;      }            if(off < free_block_offs) {		/* if the block in use is before the first free block	 * we can either use the blocks 	 * between the first free block and the end of the buffer	 * or	 * use the blocks	 * between the beginning of the buffer and the used block in use	 */		/* nr of blocks from first free block to end of buffer */		size = blocks_in_buf - free_block_offs;	next_write_pos = free_block_offs;		if(size < nblocks) {	  /* nr of blocks from start of buffer to the block in use */ 	  size = off;	  next_write_pos = 0;	}	      } else {		/* the block in use is after the first free block in the buffer */	/* nr of blocks from first free block to the block in use */	size = off - free_block_offs;	next_write_pos = free_block_offs;	      }            if(size < nblocks) {	/* the nr of contigously available blocks is too small, 	 * wait for more free blocks */	fprintf(stderr, "*demux: SEND A BUG REPORT: need more free space, not implemented\n");      } else {	/* we have enough free blocks */	break;      }    }        /* this block is not in use, check next one */        data_elem_nr =       (data_elem_nr+1) % data_buf_head->nr_of_dataelems;        /* check if we have looped through all data_elems */    if(!buf_empty) {      if(data_elem_nr == first_data_elem_nr) {	buf_empty = 1;      }    }  }    dvd_change_file(title, domain);  dvd_read_block(&disk_buf[next_write_pos*2048], boffset, nblocks);  //fprintf(stderr, "next_write_pos: %d\n", next_write_pos);  //fprintf(stderr, "dvd_read_block: dst: %u, offset: %d, blocks: %d\n", next_write_pos*2048, boffset, nblocks);  free_block_offs = next_write_pos + nblocks;  //fprintf(stderr, "free_block_offs: %d\n", free_block_offs);  off_from = next_write_pos * 2048;  off_to = free_block_offs * 2048;    //fprintf(stderr, "off_from: %d, off_to: %d\n", off_from, off_to);  return 0;}#endifunsigned int nextbits(unsigned int nr_of_bits){  uint32_t result = (cur_word << (64-bits_left)) >> 32;  DPRINTF(4, "nextbits %08x\n",(result >> (32-nr_of_bits )));  return result >> (32-nr_of_bits);}static inline void marker_bit(void)                                                           {  if(!GETBITS(1, "markerbit")) {    WARNING("%s", "Incorrect marker_bit in stream\n");    //exit(1);  }} /* 2.3 Definition of next_start_code() function */void next_start_code(void){   while(!bytealigned()) {    GETBITS(1, "next_start_code");  }   while(nextbits(24) != 0x000001) {    GETBITS(8, "next_start_code");  } }/* Table 2-24 -- Stream_id table */void dprintf_stream_id (int debuglevel, int stream_id){#ifdef DEBUG  DPRINTF(debuglevel, "0x%02x ", stream_id);  if ((stream_id & 0xf0) == 0xb0) // 1011 xxxx    switch (stream_id & 0x0f) {       case 0x8:        DPRINTF(debuglevel, "[all audio streams]\n");        return;      case 0x9:        DPRINTF(debuglevel, "[all video streams]\n");        return;      case 0xc:        DPRINTF(debuglevel, "[program stream map]\n");        return;      case 0xd:        DPRINTF(debuglevel, "[private_stream_1]\n");        return;      case 0xe:        DPRINTF(debuglevel, "[padding stream]\n");        return;      case 0xf:        DPRINTF(debuglevel, "[private_stream_2]\n");        return;    }  else if ((stream_id & 0xe0) == 0xc0) { // 110x xxxx    DPRINTF(debuglevel, "[audio stream number %i]\n", stream_id & 0x1f);    return;  } else if ((stream_id & 0xf0) == 0xe0) {    DPRINTF(debuglevel, "[video stream number %i]\n", stream_id & 0x1f);    return;  } else if ((stream_id & 0xf0) == 0xf0) {    switch (stream_id & 0x0f) {      case 0x0:        DPRINTF(debuglevel, "[ECM]\n");        return;      case 0x1:        DPRINTF(debuglevel, "[EMM]\n");        return;      case 0x2:        DPRINTF(debuglevel, "[DSM CC]\n");        return;      case 0x3:        DPRINTF(debuglevel, "[ISO/IEC 13522 stream]\n");        return;      case 0xf:        DPRINTF(debuglevel, "[program stream directory]\n");        return;      default:        DPRINTF(debuglevel, "[reserved data stream - number %i]\n",                stream_id & 0x0f);

⌨️ 快捷键说明

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