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

📄 ac3dec_wrap.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 <sys/types.h>#include <sys/stat.h>#include <sys/shm.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#ifndef SHM_SHARE_MMU#define SHM_SHARE_MMU 0#endif#include <ogle/msgevents.h>#include "debug_print.h"#include "common.h"#include "queue.h"#include "timemath.h"#include "sync.h"static int get_q();static int attach_ctrl_shm(int shmid);static int attach_stream_buffer(uint8_t stream_id, uint8_t subtype, int shmid);static void handle_events(MsgEventQ_t *q, MsgEvent_t *ev);static char *program_name;static FILE *outfile;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;static int data_buf_shmid;static char *data_buf_shmaddr;static int msgqid = -1;static MsgEventQ_t *msgq;static int flush_to_scrid = -1;static int prev_scr_nr = 0;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];    /* 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;    }  }  // test  outfile = fopen("/tmp/ac3", "w");    if(msgqid != -1) {    if((msgq = MsgOpen(msgqid)) == NULL) {      fprintf(stderr, "ac3wrap: couldn't get message q\n");      exit(-1);    }        ev.type = MsgEventQRegister;    ev.registercaps.capabilities = DECODE_AC3_AUDIO;    if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) {      DPRINTF(1, "ac3wrap: register capabilities\n");    }        while(ev.type != MsgEventQDecodeStreamBuf) {      if(MsgNextEvent(msgq, &ev) != -1) {	handle_events(msgq, &ev);      }    }  } else {    fprintf(stderr, "what?\n");  }  while(1) {    get_q();  }  return 0;}static void handle_events(MsgEventQ_t *q, MsgEvent_t *ev){    switch(ev->type) {  case MsgEventQNotify:    DPRINTF(1, "ac3wrap: got notify\n");    break;  case MsgEventQFlushData:    DPRINTF(1, "ac3wrap: got flush\n");    flush_to_scrid = ev->flushdata.to_scrid;    break;  case MsgEventQDecodeStreamBuf:    DPRINTF(1, "ac3wrap: 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 MsgEventQSpeed:    if(ev->speed.speed == 1.0) {      set_speed(&(ctrl_time[prev_scr_nr].sync_point), ev->speed.speed);    } else {      if(ctrl_time[prev_scr_nr].sync_point.speed == 1.0) {	set_speed(&(ctrl_time[prev_scr_nr].sync_point), ev->speed.speed);	if((ctrl_time[prev_scr_nr].sync_master == SYNC_AUDIO)) {	  ctrl_time[prev_scr_nr].sync_master = SYNC_NONE;	}      }    }    break;  default:    fprintf(stderr, "ac3wrap: unrecognized event type: %d\n", ev->type);    break;  }}int attach_ctrl_shm(int shmid){  char *shmaddr;    if(shmid >= 0) {    if((shmaddr = shmat(shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {      perror("ac3wrap: 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;}int attach_stream_buffer(uint8_t stream_id, uint8_t subtype, int shmid){  char *shmaddr;  q_head_t *q_head;  fprintf(stderr, "ac3: shmid: %d\n", shmid);    if(shmid >= 0) {    if((shmaddr = shmat(shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {      perror("ac3: 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("ac3: attach_data_buffer(), shmat()");      return -1;    }        data_buf_shmid = shmid;    data_buf_shmaddr = shmaddr;  }      return 0;}int get_q(){  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;  int scr_nr;  int off;  int len;  static clocktime_t time_offset = { 0, 0 };  static clocktime_t last_rt = { -1, 0 };  MsgEvent_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;  while(MsgCheckEvent(msgq, &ev) != -1) {    handle_events(msgq, &ev);  }    if(!q_elems[elem].in_use) {    q_head->reader_requests_notification = 1;        while(!q_elems[elem].in_use) {      DPRINTF(1, "ac3wrap: waiting for notification1\n");      if(MsgNextEvent(msgq, &ev) != -1) {	handle_events(msgq, &ev);      }    }  }  data_head = (data_buf_head_t *)data_buf_shmaddr;  data_buffer = data_buf_shmaddr + data_head->buffer_start_offset;  data_elems = (data_elem_t *)(data_buf_shmaddr+sizeof(data_buf_head_t));    data_elem = &data_elems[q_elems[elem].data_elem_index];    PTS_DTS_flags = data_elem->PTS_DTS_flags;  PTS = data_elem->PTS;  DTS = data_elem->DTS;  scr_nr = data_elem->scr_nr;  /*    p[0] is the number of frames of audio which have a sync code in this pack    p[1]<<8 | p[2] is the starting index of the frame which       the PTS value belong to  */  off = data_elem->packet_data_offset + 4;  len = data_elem->packet_data_len - 4;  if(flush_to_scrid != -1) {    if(ctrl_time[scr_nr].scr_id < flush_to_scrid) {      q_head->read_nr = (q_head->read_nr+1)%q_head->nr_of_qelems;            // release elem      data_elem->in_use = 0;      q_elems[elem].in_use = 0;            if(q_head->writer_requests_notification) {	q_head->writer_requests_notification = 0;	ev.type = MsgEventQNotify;	if(MsgSendEvent(msgq, q_head->writer, &ev, 0) == -1) {	  fprintf(stderr, "ac3wrap: couldn't send notification\n");	}      }      return 0;    } else {      flush_to_scrid = -1;    }  }     if(ctrl_data->speed == 1.0) {    clocktime_t real_time, scr_time;        clocktime_get(&real_time);    if(PTS_DTS_flags & 0x2) {      PTS_TO_CLOCKTIME(scr_time, PTS);    }    if(ctrl_time[scr_nr].sync_master <= SYNC_AUDIO) {      ctrl_time[scr_nr].sync_master = SYNC_AUDIO;            if(ctrl_time[scr_nr].offset_valid == OFFSET_NOT_VALID) {	if(PTS_DTS_flags & 0x2) {	  clocktime_t tmptime;	  	  // time_offset is our guess to how much is in the output q	  if(TIME_S(last_rt) != -1) {	    tmptime = last_rt;	  } else {	    tmptime = real_time;	  }	  	  {	    clocktime_t corr = { 0, 100000000 };	    timeadd(&tmptime, &tmptime, &corr);	    	  }	        	  set_sync_point(&ctrl_time[scr_nr],			 &tmptime,			 &scr_time,			 ctrl_data->speed);	}	      }            if(PTS_DTS_flags & 0x2) {	calc_realtime_left_to_scrtime(&time_offset, &real_time,				      &scr_time,				      &(ctrl_time[scr_nr].sync_point));      }      /*       * primitive resync in case output buffer is emptied        */            if(TIME_SS(time_offset) < 0 || TIME_S(time_offset) < 0) {	TIME_S(time_offset) = 0;	TIME_SS(time_offset) = 0;	fprintf(stderr, "ac3wrap: resetting offset\n");	set_sync_point(&ctrl_time[scr_nr],		       &real_time,		       &scr_time,		       ctrl_data->speed);      }          }    if(PTS_DTS_flags & 0x2) {      calc_realtime_from_scrtime(&last_rt,				 &scr_time,				 &(ctrl_time[scr_nr].sync_point));      calc_realtime_left_to_scrtime(&time_offset, &real_time,				    &scr_time,				    &(ctrl_time[scr_nr].sync_point));      if(TIME_S(time_offset) > 10) {	TIME_S(time_offset) = 0;	TIME_SS(time_offset) = 0;	fprintf(stderr, "more than 10 secs in audio output buffer, somethings wrong?\n");      }    }            if(ctrl_data->speed == 1.0) {      clocktime_t real_time, scr_time;            PTS_TO_CLOCKTIME(scr_time, PTS);      clocktime_get(&real_time);            /** TODO this is just so we don't buffer alot in the pipe **/            {#ifndef HAVE_CLOCK_GETTIME	struct timespec bepa;	clocktime_t apa = {0, 100000};	timesub(&apa, &time_offset, &apa);	bepa.tv_sec = apa.tv_sec;	bepa.tv_nsec = apa.tv_usec*1000;		if(bepa.tv_nsec > 10000 || bepa.tv_sec > 0) {	  nanosleep(&bepa, NULL);	}#else		clocktime_t apa = {0, 100000000};	timesub(&apa, &time_offset, &apa);		if(TIME_SS(apa) > 10000000 || TIME_S(apa) > 0) {	  nanosleep(&apa, NULL);	}	#endif       }    }  }  prev_scr_nr = scr_nr;    q_head->read_nr = (q_head->read_nr+1)%q_head->nr_of_qelems;      if(ctrl_data->speed == 1.0) {    fwrite(data_buffer+off, len, 1, outfile);  } else {    //    fprintf(stderr, "*ac3: speed: %f\n", ctrl_data->speed);  }  // release elem  data_elem->in_use = 0;  q_elems[elem].in_use = 0;    if(q_head->writer_requests_notification) {    q_head->writer_requests_notification = 0;    ev.type = MsgEventQNotify;    if(MsgSendEvent(msgq, q_head->writer, &ev, 0) == -1) {      fprintf(stderr, "ac3wrap: couldn't send notification\n");    }  }    return 0;}

⌨️ 快捷键说明

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