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

📄 spudec.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 3 页
字号:
	this->palette[0] = this->packet[off] >> 4;	this->palette[1] = this->packet[off] & 0xf;	this->palette[2] = this->packet[off + 1] >> 4;	this->palette[3] = this->packet[off + 1] & 0xf;	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Palette %d, %d, %d, %d\n",	       this->palette[0], this->palette[1], this->palette[2], this->palette[3]);	off+=2;	break;      case 0x04:	/* Alpha */	this->alpha[0] = this->packet[off] >> 4;	this->alpha[1] = this->packet[off] & 0xf;	this->alpha[2] = this->packet[off + 1] >> 4;	this->alpha[3] = this->packet[off + 1] & 0xf;	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Alpha %d, %d, %d, %d\n",	       this->alpha[0], this->alpha[1], this->alpha[2], this->alpha[3]);	off+=2;	break;      case 0x05:	/* Co-ords */	a = get_be24(this->packet + off);	b = get_be24(this->packet + off + 3);	start_col = a >> 12;	end_col = a & 0xfff;	width = (end_col < start_col) ? 0 : end_col - start_col + 1;	stride = (width + 7) & ~7; /* Kludge: draw_alpha needs width multiple of 8 */	start_row = b >> 12;	end_row = b & 0xfff;	height = (end_row < start_row) ? 0 : end_row - start_row /* + 1 */;	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Coords  col: %d - %d  row: %d - %d  (%dx%d)\n",	       start_col, end_col, start_row, end_row,	       width, height);	off+=6;	break;      case 0x06:	/* Graphic lines */	current_nibble[0] = 2 * get_be16(this->packet + off);	current_nibble[1] = 2 * get_be16(this->packet + off + 2);	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Graphic offset 1: %d  offset 2: %d\n",	       current_nibble[0] / 2, current_nibble[1] / 2);	off+=4;	break;      case 0xff:	/* All done, bye-bye */	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"Done!\n");	return;//	break;      default:	mp_msg(MSGT_SPUDEC,MSGL_WARN,"spudec: Error determining control type 0x%02x.  Skipping %d bytes.\n",	       type, next_off - off);	goto next_control;      }    }  next_control:    if (display) {      packet_t *packet = calloc(1, sizeof(packet_t));      int i;      packet->start_pts = start_pts;      if (end_pts == UINT_MAX && start_off != next_off) {	start_pts = pts100 + get_be16(this->packet + next_off) * 1024;        packet->end_pts = start_pts - 1;      } else packet->end_pts = end_pts;      packet->current_nibble[0] = current_nibble[0];      packet->current_nibble[1] = current_nibble[1];      packet->start_row = start_row;      packet->end_row = end_row;      packet->start_col = start_col;      packet->end_col = end_col;      packet->width = width;      packet->height = height;      packet->stride = stride;      packet->control_start = control_start;      for (i=0; i<4; i++) {	packet->alpha[i] = this->alpha[i];	packet->palette[i] = this->palette[i];      }      packet->packet = malloc(this->packet_size);      memcpy(packet->packet, this->packet, this->packet_size);      spudec_queue_packet(this, packet);    }  }}static void spudec_decode(spudec_handle_t *this, unsigned int pts100){  if(this->hw_spu) {    static vo_mpegpes_t packet = { NULL, 0, 0x20, 0 };    static vo_mpegpes_t *pkg=&packet;    packet.data = this->packet;    packet.size = this->packet_size;    packet.timestamp = pts100;    this->hw_spu->draw_frame((uint8_t**)&pkg);  } else    spudec_process_control(this, pts100);}int spudec_changed(void * this){    spudec_handle_t * spu = (spudec_handle_t*)this;    return (spu->spu_changed || spu->now_pts > spu->end_pts);}void spudec_assemble(void *this, unsigned char *packet, unsigned int len, unsigned int pts100){  spudec_handle_t *spu = (spudec_handle_t*)this;//  spudec_heartbeat(this, pts100);  if (len < 2) {      mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUasm: packet too short\n");      return;  }  if ((spu->packet_pts + 10000) < pts100) {    // [cb] too long since last fragment: force new packet    spu->packet_offset = 0;  }  spu->packet_pts = pts100;  if (spu->packet_offset == 0) {    unsigned int len2 = get_be16(packet);    // Start new fragment    if (spu->packet_reserve < len2) {      if (spu->packet != NULL)	free(spu->packet);      spu->packet = malloc(len2);      spu->packet_reserve = spu->packet != NULL ? len2 : 0;    }    if (spu->packet != NULL) {      spu->packet_size = len2;      if (len > len2) {	mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUasm: invalid frag len / len2: %d / %d \n", len, len2);	return;      }      memcpy(spu->packet, packet, len);      spu->packet_offset = len;      spu->packet_pts = pts100;    }  } else {    // Continue current fragment    if (spu->packet_size < spu->packet_offset + len){      mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUasm: invalid fragment\n");      spu->packet_size = spu->packet_offset = 0;      return;    } else {      memcpy(spu->packet + spu->packet_offset, packet, len);      spu->packet_offset += len;    }  }#if 1  // check if we have a complete packet (unfortunatelly packet_size is bad  // for some disks)  // [cb] packet_size is padded to be even -> may be one byte too long  if ((spu->packet_offset == spu->packet_size) ||      ((spu->packet_offset + 1) == spu->packet_size)){    unsigned int x=0,y;    while(x+4<=spu->packet_offset){      y=get_be16(spu->packet+x+2); // next control pointer      mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPUtest: x=%d y=%d off=%d size=%d\n",x,y,spu->packet_offset,spu->packet_size);      if(x>=4 && x==y){		// if it points to self - we're done!        // we got it!	mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPUgot: off=%d  size=%d \n",spu->packet_offset,spu->packet_size);	spudec_decode(spu, pts100);	spu->packet_offset = 0;	break;      }      if(y<=x || y>=spu->packet_size){ // invalid?	mp_msg(MSGT_SPUDEC,MSGL_WARN,"SPUtest: broken packet!!!!! y=%d < x=%d\n",y,x);        spu->packet_size = spu->packet_offset = 0;        break;      }      x=y;    }    // [cb] packet is done; start new packet    spu->packet_offset = 0;  }#else  if (spu->packet_offset == spu->packet_size) {    spudec_decode(spu, pts100);    spu->packet_offset = 0;  }#endif}void spudec_reset(void *this)	// called after seek{  spudec_handle_t *spu = (spudec_handle_t*)this;  while (spu->queue_head)    spudec_free_packet(spudec_dequeue_packet(spu));  spu->now_pts = 0;  spu->end_pts = 0;  spu->packet_size = spu->packet_offset = 0;}void spudec_heartbeat(void *this, unsigned int pts100){   spudec_handle_t *spu = (spudec_handle_t*) this;  spu->now_pts = pts100;  while (spu->queue_head != NULL && pts100 >= spu->queue_head->start_pts) {    packet_t *packet = spudec_dequeue_packet(spu);    spu->start_pts = packet->start_pts;    spu->end_pts = packet->end_pts;    if (spu->auto_palette)      compute_palette(spu, packet);    spudec_process_data(spu, packet);    spudec_free_packet(packet);    spu->spu_changed = 1;  }}int spudec_visible(void *this){    spudec_handle_t *spu = (spudec_handle_t *)this;    int ret=(spu->start_pts <= spu->now_pts &&	     spu->now_pts < spu->end_pts &&	     spu->height > 0);//    printf("spu visible: %d  \n",ret);    return ret;}void spudec_set_forced_subs_only(void * const this, const unsigned int flag){  if(this){      ((spudec_handle_t *)this)->forced_subs_only=flag;      mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPU: Display only forced subs now %s\n", flag ? "enabled": "disabled");  }}void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){    spudec_handle_t *spu = (spudec_handle_t *)this;    if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image)    {	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,		   spu->image, spu->aimage, spu->stride);	spu->spu_changed = 0;    }}/* calc the bbox for spudec subs */void spudec_calc_bbox(void *me, unsigned int dxs, unsigned int dys, unsigned int* bbox){  spudec_handle_t *spu;  spu = (spudec_handle_t *)me;  if (spu->orig_frame_width == 0 || spu->orig_frame_height == 0  || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys)) {    bbox[0] = spu->start_col;    bbox[1] = spu->start_col + spu->width;    bbox[2] = spu->start_row;    bbox[3] = spu->start_row + spu->height;  }  else if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {    unsigned int scalex = 0x100 * dxs / spu->orig_frame_width;    unsigned int scaley = 0x100 * dys / spu->orig_frame_height;    bbox[0] = spu->start_col * scalex / 0x100;    bbox[1] = spu->start_col * scalex / 0x100 + spu->width * scalex / 0x100;    switch (spu_alignment) {    case 0:      bbox[3] = dys*sub_pos/100 + spu->height * scaley / 0x100;      if (bbox[3] > dys) bbox[3] = dys;      bbox[2] = bbox[3] - spu->height * scaley / 0x100;      break;    case 1:      if (sub_pos < 50) {        bbox[2] = dys*sub_pos/100 - spu->height * scaley / 0x200;        if (bbox[2] < 0) bbox[2] = 0;        bbox[3] = bbox[2] + spu->height;      } else {        bbox[3] = dys*sub_pos/100 + spu->height * scaley / 0x200;        if (bbox[3] > dys) bbox[3] = dys;        bbox[2] = bbox[3] - spu->height * scaley / 0x100;      }      break;    case 2:      bbox[2] = dys*sub_pos/100 - spu->height * scaley / 0x100;      if (bbox[2] < 0) bbox[2] = 0;      bbox[3] = bbox[2] + spu->height;      break;    default: /* -1 */      bbox[2] = spu->start_row * scaley / 0x100;      bbox[3] = spu->start_row * scaley / 0x100 + spu->height * scaley / 0x100;      break;    }  }}/* transform mplayer's alpha value into an opacity value that is linear */static inline int canon_alpha(int alpha){  return alpha ? 256 - alpha : 0;}typedef struct {  unsigned position;  unsigned left_up;  unsigned right_down;}scale_pixel;static void scale_table(unsigned int start_src, unsigned int start_tar, unsigned int end_src, unsigned int end_tar, scale_pixel * table){  unsigned int t;  unsigned int delta_src = end_src - start_src;  unsigned int delta_tar = end_tar - start_tar;  int src = 0;  int src_step;  if (delta_src == 0 || delta_tar == 0) {    return;  }  src_step = (delta_src << 16) / delta_tar >>1;  for (t = 0; t<=delta_tar; src += (src_step << 1), t++){    table[t].position= MIN(src >> 16, end_src - 1);    table[t].right_down = src & 0xffff;    table[t].left_up = 0x10000 - table[t].right_down;  }}/* bilinear scale, similar to vobsub's code */static void scale_image(int x, int y, scale_pixel* table_x, scale_pixel* table_y, spudec_handle_t * spu){  int alpha[4];  int color[4];  unsigned int scale[4];  int base = table_y[y].position * spu->stride + table_x[x].position;  int scaled = y * spu->scaled_stride + x;  alpha[0] = canon_alpha(spu->aimage[base]);  alpha[1] = canon_alpha(spu->aimage[base + 1]);  alpha[2] = canon_alpha(spu->aimage[base + spu->stride]);  alpha[3] = canon_alpha(spu->aimage[base + spu->stride + 1]);  color[0] = spu->image[base];  color[1] = spu->image[base + 1];  color[2] = spu->image[base + spu->stride];  color[3] = spu->image[base + spu->stride + 1];  scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0];  scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1];  scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2];  scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3];  spu->scaled_image[scaled] = (color[0] * scale[0] + color[1] * scale[1] + color[2] * scale[2] + color[3] * scale[3])>>24;  spu->scaled_aimage[scaled] = (scale[0] + scale[1] + scale[2] + scale[3]) >> 16;  if (spu->scaled_aimage[scaled]){    spu->scaled_aimage[scaled] = 256 - spu->scaled_aimage[scaled];    if(spu->scaled_aimage[scaled] + spu->scaled_image[scaled] > 255)      spu->scaled_image[scaled] = 256 - spu->scaled_aimage[scaled];  }}void sws_spu_image(unsigned char *d1, unsigned char *d2, int dw, int dh, int ds,	unsigned char *s1, unsigned char *s2, int sw, int sh, int ss){/*	struct SwsContext *ctx;	static SwsFilter filter;	static int firsttime = 1;	static float oldvar;	int i;	if (!firsttime && oldvar != spu_gaussvar) sws_freeVec(filter.lumH);	if (firsttime) {		filter.lumH = filter.lumV =			filter.chrH = filter.chrV = sws_getGaussianVec(spu_gaussvar, 3.0);		sws_normalizeVec(filter.lumH, 1.0);		firsttime = 0;		oldvar = spu_gaussvar;	}		ctx=sws_getContext(sw, sh, IMGFMT_Y800, dw, dh, IMGFMT_Y800, SWS_GAUSS, &filter, NULL, NULL);	sws_scale(ctx,&s1,&ss,0,sh,&d1,&ds);	for (i=ss*sh-1; i>=0; i--) if (!s2[i]) s2[i] = 255; //else s2[i] = 1;	sws_scale(ctx,&s2,&ss,0,sh,&d2,&ds);	for (i=ds*dh-1; i>=0; i--) if (d2[i]==0) d2[i] = 1; else if (d2[i]==255) d2[i] = 0;	sws_freeContext(ctx);*/}void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){  spudec_handle_t *spu = (spudec_handle_t *)me;  scale_pixel *table_x;  scale_pixel *table_y;  if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) {    // check if only forced subtitles are requested     if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ 	return;    }    if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0	|| (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) {      if (spu->image)      {	draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,		   spu->image, spu->aimage, spu->stride);	spu->spu_changed = 0;      }    }    else {      if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) {	/* Resizing is needed */	/* scaled_x = scalex * x / 0x100	   scaled_y = scaley * y / 0x100	   order of operations is important because of rounding. */	unsigned int scalex = 0x100 * dxs / spu->orig_frame_width;

⌨️ 快捷键说明

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