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

📄 spudec.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* SPUdec.c   Skeleton of function spudec_process_controll() is from xine sources.   Further works:   LGB,... (yeah, try to improve it and insert your name here! ;-)   Kim Minh Kaplan   implement fragments reassembly, RLE decoding.   read brightness from the IFO.   For information on SPU format see <URL:http://sam.zoy.org/doc/dvd/subtitles/>   and <URL:http://members.aol.com/mpucoder/DVD/spu.html> */#include "config.h"#include "mp_msg.h"#include <errno.h>#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <math.h>#include "libvo/video_out.h"#include "spudec.h"//#include "postproc/swscale.h"#define MIN(a, b)	((a)<(b)?(a):(b))/* Valid values for spu_aamode:   0: none (fastest, most ugly)   1: approximate   2: full (slowest)   3: bilinear (similiar to vobsub, fast and not too bad)   4: uses swscaler gaussian (this is the only one that looks good) */int spu_aamode = 3;int spu_alignment = -1;float spu_gaussvar = 1.0;extern int sub_pos;typedef struct packet_t packet_t;struct packet_t {  unsigned char *packet;  unsigned int palette[4];  unsigned int alpha[4];  unsigned int control_start;	/* index of start of control data */  unsigned int current_nibble[2]; /* next data nibble (4 bits) to be                                     processed (for RLE decoding) for                                     even and odd lines */  int deinterlace_oddness;	/* 0 or 1, index into current_nibble */  unsigned int start_col, end_col;  unsigned int start_row, end_row;  unsigned int width, height, stride;  unsigned int start_pts, end_pts;  packet_t *next;};typedef struct {  packet_t *queue_head;  packet_t *queue_tail;  unsigned int global_palette[16];  unsigned int orig_frame_width, orig_frame_height;  unsigned char* packet;  size_t packet_reserve;	/* size of the memory pointed to by packet */  unsigned int packet_offset;	/* end of the currently assembled fragment */  unsigned int packet_size;	/* size of the packet once all fragments are assembled */  unsigned int packet_pts;	/* PTS for this packet */  unsigned int palette[4];  unsigned int alpha[4];  unsigned int cuspal[4];  unsigned int custom;  unsigned int now_pts;  unsigned int start_pts, end_pts;  unsigned int start_col, end_col;  unsigned int start_row, end_row;  unsigned int width, height, stride;  size_t image_size;		/* Size of the image buffer */  unsigned char *image;		/* Grayscale value */  unsigned char *aimage;	/* Alpha value */  unsigned int scaled_frame_width, scaled_frame_height;  unsigned int scaled_start_col, scaled_start_row;  unsigned int scaled_width, scaled_height, scaled_stride;  size_t scaled_image_size;  unsigned char *scaled_image;  unsigned char *scaled_aimage;  int auto_palette; /* 1 if we lack a palette and must use an heuristic. */  int font_start_level;  /* Darkest value used for the computed font */  vo_functions_t *hw_spu;  int spu_changed;  unsigned int forced_subs_only;     /* flag: 0=display all subtitle, !0 display only forced subtitles */  unsigned int is_forced_sub;         /* true if current subtitle is a forced subtitle */} spudec_handle_t;static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet){  if (this->queue_head == NULL)    this->queue_head = packet;  else    this->queue_tail->next = packet;  this->queue_tail = packet;}static packet_t *spudec_dequeue_packet(spudec_handle_t *this){  packet_t *retval = this->queue_head;  this->queue_head = retval->next;  if (this->queue_head == NULL)    this->queue_tail = NULL;  return retval;}static void spudec_free_packet(packet_t *packet){  if (packet->packet != NULL)    free(packet->packet);  free(packet);}static inline unsigned int get_be16(const unsigned char *p){  return (p[0] << 8) + p[1];}static inline unsigned int get_be24(const unsigned char *p){  return (get_be16(p) << 8) + p[2];}static void next_line(packet_t *packet){  if (packet->current_nibble[packet->deinterlace_oddness] % 2)    packet->current_nibble[packet->deinterlace_oddness]++;  packet->deinterlace_oddness = (packet->deinterlace_oddness + 1) % 2;}static inline unsigned char get_nibble(packet_t *packet){  unsigned char nib;  unsigned int *nibblep = packet->current_nibble + packet->deinterlace_oddness;  if (*nibblep / 2 >= packet->control_start) {    mp_msg(MSGT_SPUDEC,MSGL_WARN, "SPUdec: ERROR: get_nibble past end of packet\n");    return 0;  }  nib = packet->packet[*nibblep / 2];  if (*nibblep % 2)    nib &= 0xf;  else    nib >>= 4;  ++*nibblep;  return nib;}static inline int mkalpha(int i){  /* In mplayer's alpha planes, 0 is transparent, then 1 is nearly     opaque upto 255 which is transparent */  switch (i) {  case 0xf:    return 1;  case 0:    return 0;  default:    return (0xf - i) << 4;  }}/* Cut the sub to visible part */static inline void spudec_cut_image(spudec_handle_t *this){  unsigned int fy, ly;  unsigned int first_y, last_y;  unsigned char *image;  unsigned char *aimage;  if (this->stride == 0 || this->height == 0) {    return;  }  for (fy = 0; fy < this->image_size && !this->aimage[fy]; fy++);  for (ly = this->stride * this->height-1; ly && !this->aimage[ly]; ly--);  first_y = fy / this->stride;  last_y = ly / this->stride;  //printf("first_y: %d, last_y: %d\n", first_y, last_y);  this->start_row += first_y;  // Some subtitles trigger this condition  if (last_y + 1 > first_y ) {	  this->height = last_y - first_y +1;  } else {	  this->height = 0;	  this->image_size = 0;	  return;  }  //  printf("new h %d new start %d (sz %d st %d)---\n\n", this->height, this->start_row, this->image_size, this->stride);  image = malloc(2 * this->stride * this->height);  if(image){    this->image_size = this->stride * this->height;    aimage = image + this->image_size;    memcpy(image, this->image + this->stride * first_y, this->image_size);    memcpy(aimage, this->aimage + this->stride * first_y, this->image_size);    free(this->image);    this->image = image;    this->aimage = aimage;  } else {    mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: update_spu: malloc requested %d bytes\n", 2 * this->stride * this->height);  }}static void spudec_process_data(spudec_handle_t *this, packet_t *packet){  unsigned int cmap[4], alpha[4];  unsigned int i, x, y;  this->scaled_frame_width = 0;  this->scaled_frame_height = 0;  this->start_col = packet->start_col;  this->end_col = packet->end_col;  this->start_row = packet->start_row;  this->end_row = packet->end_row;  this->height = packet->height;  this->width = packet->width;  this->stride = packet->stride;  for (i = 0; i < 4; ++i) {    alpha[i] = mkalpha(packet->alpha[i]);    if (alpha[i] == 0)      cmap[i] = 0;    else if (this->custom){      cmap[i] = ((this->cuspal[i] >> 16) & 0xff);      if (cmap[i] + alpha[i] > 255)	cmap[i] = 256 - alpha[i];    }    else {      cmap[i] = ((this->global_palette[packet->palette[i]] >> 16) & 0xff);      if (cmap[i] + alpha[i] > 255)	cmap[i] = 256 - alpha[i];    }  }  if (this->image_size < this->stride * this->height) {    if (this->image != NULL) {      free(this->image);      this->image_size = 0;    }    this->image = malloc(2 * this->stride * this->height);    if (this->image) {      this->image_size = this->stride * this->height;      this->aimage = this->image + this->image_size;    }  }  if (this->image == NULL)    return;  /* Kludge: draw_alpha needs width multiple of 8. */  if (this->width < this->stride)    for (y = 0; y < this->height; ++y) {      memset(this->aimage + y * this->stride + this->width, 0, this->stride - this->width);      /* FIXME: Why is this one needed? */      memset(this->image + y * this->stride + this->width, 0, this->stride - this->width);    }  i = packet->current_nibble[1];  x = 0;  y = 0;  while (packet->current_nibble[0] < i	 && packet->current_nibble[1] / 2 < packet->control_start	 && y < this->height) {    unsigned int len, color;    unsigned int rle = 0;    rle = get_nibble(packet);    if (rle < 0x04) {      rle = (rle << 4) | get_nibble(packet);      if (rle < 0x10) {	rle = (rle << 4) | get_nibble(packet);	if (rle < 0x040) {	  rle = (rle << 4) | get_nibble(packet);	  if (rle < 0x0004)	    rle |= ((this->width - x) << 2);	}      }    }    color = 3 - (rle & 0x3);    len = rle >> 2;    if (len > this->width - x || len == 0)      len = this->width - x;    /* FIXME have to use palette and alpha map*/    memset(this->image + y * this->stride + x, cmap[color], len);    memset(this->aimage + y * this->stride + x, alpha[color], len);    x += len;    if (x >= this->width) {      next_line(packet);      x = 0;      ++y;    }  }  spudec_cut_image(this);}/*  This function tries to create a usable palette.  It determines how many non-transparent colors are used, and assigns differentgray scale values to each color.  I tested it with four streams and even got something readable. Half of thetimes I got black characters with white around and half the reverse.*/static void compute_palette(spudec_handle_t *this, packet_t *packet){  int used[16],i,cused,start,step,color;  memset(used, 0, sizeof(used));  for (i=0; i<4; i++)    if (packet->alpha[i]) /* !Transparent? */       used[packet->palette[i]] = 1;  for (cused=0, i=0; i<16; i++)    if (used[i]) cused++;  if (!cused) return;  if (cused == 1) {    start = 0x80;    step = 0;  } else {    start = this->font_start_level;    step = (0xF0-this->font_start_level)/(cused-1);  }  memset(used, 0, sizeof(used));  for (i=0; i<4; i++) {    color = packet->palette[i];    if (packet->alpha[i] && !used[color]) { /* not assigned? */       used[color] = 1;       this->global_palette[color] = start<<16;       start += step;    }  }}static void spudec_process_control(spudec_handle_t *this, unsigned int pts100){  int a,b; /* Temporary vars */  unsigned int date, type;  unsigned int off;  unsigned int start_off = 0;  unsigned int next_off;  unsigned int start_pts;  unsigned int end_pts;  unsigned int current_nibble[2];  unsigned int control_start;  unsigned int display = 0;  unsigned int start_col = 0;  unsigned int end_col = 0;  unsigned int start_row = 0;  unsigned int end_row = 0;  unsigned int width = 0;  unsigned int height = 0;  unsigned int stride = 0;  control_start = get_be16(this->packet + 2);  next_off = control_start;  while (start_off != next_off) {    start_off = next_off;    date = get_be16(this->packet + start_off) * 1024;    next_off = get_be16(this->packet + start_off + 2);    mp_msg(MSGT_SPUDEC,MSGL_DBG2, "date=%d\n", date);    off = start_off + 4;    for (type = this->packet[off++]; type != 0xff; type = this->packet[off++]) {      mp_msg(MSGT_SPUDEC,MSGL_DBG2, "cmd=%d  ",type);      switch(type) {      case 0x00:	/* Menu ID, 1 byte */	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Menu ID\n");        /* shouldn't a Menu ID type force display start? */	start_pts = pts100 + date;	end_pts = UINT_MAX;	display = 1;	this->is_forced_sub=~0; // current subtitle is forced	break;      case 0x01:	/* Start display */	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Start display!\n");	start_pts = pts100 + date;	end_pts = UINT_MAX;	display = 1;	this->is_forced_sub=0;	break;      case 0x02:	/* Stop display */	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Stop display!\n");	end_pts = pts100 + date;	break;      case 0x03:	/* Palette */

⌨️ 快捷键说明

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