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

📄 spu_mixer.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 <assert.h>#include <stdlib.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 <string.h>#include "debug_print.h"#include "common.h"#include "queue.h"#include "timemath.h"#include "sync.h"#include "spu_mixer.h"#ifndef SHM_SHARE_MMU#define SHM_SHARE_MMU 0#endif#ifdef DEBUG#define GETBYTES(a,b) getbytes(a,b)#else#define GETBYTES(a,b) getbytes(a)#endiftypedef struct {  int spu_size;  uint16_t DCSQT_offset;  int next_DCSQ_offset;  int last_DCSQ;    uint16_t fieldoffset[2];  unsigned char *buffer;  unsigned char *next_buffer;  int scr_nr;  uint64_t base_time;  uint64_t next_time;    int start_time;  int width;  int height;  int x_start;  int x_end;  int y_start;  int y_end;  int display_start;  int has_highlight;  uint8_t color[4];  uint8_t contrast[4];} spu_handle_t;typedef struct {  uint8_t color[4];  uint8_t contrast[4];  int x_start;  int y_start;  int x_end;  int y_end;} highlight_t;extern ctrl_data_t *ctrl_data;extern 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 aligned;static uint16_t fieldoffset[2];static uint16_t field = 0;static spu_handle_t spu_info = { 0 };static int initialized = 0;static uint32_t palette_yuv[16];static uint32_t palette_rgb[16];static uint32_t *palette;static void (*mix_function)(uint32_t color, uint32_t contrast, 			    unsigned int len, uint8_t* pixel,			    int, uint8_t*, uint8_t*) = NULL;static highlight_t highlight = {{0,1,2,3}, {0xf, 0xa, 0x6,0x2}, 2,2,718, 450};extern int video_scr_nr;extern int msgqid;extern MsgEventQ_t *msgq;static int flush_to_scrid = -1;static int rgbmode,pixelstride;#define MAX_BUF_SIZE 65536#define MODE_RGB  0x1#define MODE_BGR  0x2#define MODE_RGB_ALIEN 0x5#define MODE_BGR_ALIEN 0x6#define MODE_ALIEN_MASK 0x4extern void redraw_request(void);extern int register_event_handler(int(*eh)(MsgEventQ_t *, MsgEvent_t *));static uint32_t yuv2rgb(uint32_t yuv_color){  int Y,Cb,Cr;  int Ey, Epb, Epr;  int Eg, Eb, Er;  uint32_t result;    Y  = (yuv_color >> 16) & 0xff;  Cb = (yuv_color      ) & 0xff;  Cr = (yuv_color >> 8 ) & 0xff;   Ey  = (Y-16);  Epb = (Cb-128);  Epr = (Cr-128);  /* ITU-R 709  Eg = (298*Ey - 55*Epb - 137*Epr)/256;  Eb = (298*Ey + 543*Epb)/256;  Er = (298*Ey + 460*Epr)/256;  */  /* FCC ~= mediaLib */  Eg = (298*Ey - 100*Epb - 208*Epr)/256;  Eb = (298*Ey + 516*Epb)/256;  Er = (298*Ey + 408*Epr)/256;    if(Eg > 255)    Eg = 255;  if(Eg < 0)    Eg = 0;  if(Eb > 255)    Eb = 255;  if(Eb < 0)    Eb = 0;  if(Er > 255)    Er = 255;  if(Er < 0)    Er = 0;  if( rgbmode == MODE_BGR || rgbmode == MODE_RGB_ALIEN) {    result = (Eb << 16) | (Eg << 8) | Er;  } else {    result = (Er << 16) | (Eg << 8) | Eb;    }  return result;}static int attach_stream_buffer(uint8_t stream_id, uint8_t subtype, int shmid){  char *shmaddr;  q_head_t *q_head;    //DNOTE("spu_mixer: shmid: %d\n", shmid);    if(shmid >= 0) {    if((shmaddr = shmat(shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) {      ERROR("%s", "spu_mixer: attach_decoder_buffer()");      perror("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) {      ERROR("%s", "spu: attach_data_buffer()");      perror("shmat");      return -1;    }        data_buf_shmid = shmid;    data_buf_shmaddr = shmaddr;  }        initialized = 1;  return 0;}static int handle_events(MsgEventQ_t *q, MsgEvent_t *ev){  switch(ev->type) {  case MsgEventQNotify:    if((stream_shmaddr != NULL) &&       (ev->notify.qid == ((q_head_t *)stream_shmaddr)->qid)) {      DPRINTF(1, "spu_mixer: got notification\n");      redraw_request();    } else {      return 0;    }    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 MsgEventQSPUPalette:    {      int n;      /* Should have PTS or SCR I think */      for(n = 0; n < 16; n++) {	palette_yuv[n] = ev->spupalette.colors[n];	palette_rgb[n] = yuv2rgb(palette_yuv[n]);      }      redraw_request();    }    break;  case MsgEventQSPUHighlight:    {      int n;            /* Enable the highlight, should have PTS or scr I think */      spu_info.has_highlight = 1;            highlight.x_start = ev->spuhighlight.x_start;      highlight.y_start = ev->spuhighlight.y_start;      highlight.x_end = ev->spuhighlight.x_end;      highlight.y_end = ev->spuhighlight.y_end;      for(n = 0; n < 4; n++) {	highlight.color[n] = ev->spuhighlight.color[n];      }      for(n = 0; n < 4; n++) {	highlight.contrast[n] = ev->spuhighlight.contrast[n];      }      redraw_request();    }    break;  default:    /* DNOTE("spu_mixer: ignoring event type (%d)\n", ev->type); */    return 0;    break;  }  return 1;}static int get_q(char *dst, int readlen, uint64_t *display_base_time, 		 int *new_scr_nr){  MsgEvent_t ev;  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 int read_offset = 0;  //  clocktime_t pts_time;  int cpy_len;  q_head = (q_head_t *)stream_shmaddr;  q_elems = (q_elem_t *)(stream_shmaddr+sizeof(q_head_t));  elem = q_head->read_nr;    if(!read_offset) {        if(!q_elems[elem].in_use) {      q_head->reader_requests_notification = 1;            if(!q_elems[elem].in_use) {	return 0;      }    }    //DNOTE("spu_mixer: get element\n");  }  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];  off = data_elem->packet_data_offset+1;  len = data_elem->packet_data_len-1;      PTS_DTS_flags = data_elem->PTS_DTS_flags;  if(PTS_DTS_flags & 0x2) {    PTS = data_elem->PTS;    scr_nr = data_elem->scr_nr;    *display_base_time = PTS;      /*    PTS_TO_CLOCKTIME(pts_time, PTS);    calc_realtime_from_scrtime(display_base_time, &pts_time, 			       &ctrl_time[scr_nr].sync_point);      */    *new_scr_nr = scr_nr;  }  if(PTS_DTS_flags & 0x1) {    DTS = data_elem->DTS;  }    //DNOTE("spu_mixer: len: %d\n", len);  //DNOTE("spu_mixer: readlen: %d\n", readlen);  //DNOTE("spu_mixer: read_offset: %d\n", read_offset);    if((readlen + read_offset) < len) {    if((PTS_DTS_flags & 0x2) && (readlen != 2)) {      read_offset = 0;      DNOTE("%s", "Invalid SPU packet?\n");      return -1;    }  }  if((readlen + read_offset) > len) {    cpy_len = len-read_offset;    //DNOTE("spu_mixer: bigger than available\n");  } else {    cpy_len = readlen;  }  //DNOTE("spu_mixer: cpy_len: %d\n", cpy_len);  memcpy(dst, data_buffer + off + read_offset, cpy_len);    if(cpy_len + read_offset == len) {    read_offset = 0;  } else {    read_offset += cpy_len;  }    if(read_offset) {    return cpy_len;  }    // release elem  //DNOTE("spu_mixer: release element\n");    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) {      FATAL("%s", "spu_mixer: couldn't send notification\n");      exit(1);    }  }    q_head->read_nr = (q_head->read_nr+1)%q_head->nr_of_qelems;  return cpy_len;}int init_spu(void){  //DNOTE("spu_mixer: init\n");  spu_info.buffer = malloc(MAX_BUF_SIZE);  spu_info.next_buffer = malloc(MAX_BUF_SIZE);  if(spu_info.buffer == NULL || spu_info.next_buffer == NULL) {    ERROR("%s", "init_spu\n");    perror("malloc");  }  register_event_handler(handle_events);  return 0;}static int get_data(uint8_t *databuf, int bufsize, 		    uint64_t *dtime, int *scr_nr){  int r;  static int bytes_to_read = 0;  static int state = 0;  static int spu_size;  /* Make sure to have a buffer bigger than this */  /*  if(bufsize < 2) {    // databuf not big enough    ERROR("buffer too small\n");    return -1;  }  */  if(bytes_to_read == 0) {    // get first 2 bytes of spu (size of spu)    bytes_to_read = 2;  }  if(state == 0) {    while(bytes_to_read > 0) {      r = get_q(&databuf[2-bytes_to_read], bytes_to_read, dtime, scr_nr);            if(r > 0) {	bytes_to_read -= r;      } else if(r < 0) {	perror("read");	state = 0;	bytes_to_read = 0;	return -1;      } else if(r == 0) {	/* no more elements in q at this moment */	//DNOTE("q empty, %d bytes read\n", 2-bytes_to_read);	return 0;      }    }    

⌨️ 快捷键说明

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