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

📄 spudec.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        height = (end_row < start_row) ? 0 : end_row - start_row /* + 1 */;
        DPRINTF(_l("Coords  col: %d - %d  row: %d - %d  (%dx%d)"), 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);
        DPRINTF(_l("Graphic offset 1: %d  offset 2: %d"), current_nibble[0] / 2, current_nibble[1] / 2);
        off+=4;
        break;
      case 0xff:
        /* All done, bye-bye */
        DPRINTF(_l("Done!"));
        return;
//      break;
      default:
        DPRINTF(_l("spudec: Error determining control type 0x%02x.  Skipping %d bytes."), type, next_off - off);
        goto next_control;
      }
    }
  next_control:
    if (display) {
      packet_t *packet = (packet_t*)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 = (unsigned char*)malloc(this->packet_size);
      memcpy(packet->packet, this->packet, this->packet_size);
      spudec_queue_packet(packet);
    }
  }
}

void Tspudec::spudec_decode(unsigned int pts100)
{
    spudec_process_control( pts100);
}

int Tspudec::spudec_changed(void)
{
    return (spu_changed || now_pts > end_pts);
}

void Tspudec::spudec_assemble(const unsigned char *packet, unsigned int len, unsigned int pts100)
{
  if (len < 2) {
      DPRINTF(_l("SPUasm: packet too short"));
      return;
  }
  if ((this->packet_pts + 10000) < pts100) {
    // [cb] too long since last fragment: force new packet
    this->packet_offset = 0;
  }
  this->packet_pts = pts100;
  if (this->packet_offset == 0) {
    unsigned int len2 = get_be16(packet);
    // Start new fragment
    if (this->packet_reserve < len2) {
      if (this->packet != NULL)
              free(this->packet);
      this->packet = (unsigned char*)malloc(len2);
      this->packet_reserve = this->packet != NULL ? len2 : 0;
    }
    if (this->packet != NULL) {
      this->packet_size = len2;
      if (len > len2) {
               DPRINTF(_l("SPUasm: invalid frag len / len2: %d / %d "), len, len2);
               return;
      }
      memcpy(this->packet, packet, len);
      this->packet_offset = len;
      this->packet_pts = pts100;
    }
  } else {
    // Continue current fragment
    if (this->packet_size < this->packet_offset + len){
      DPRINTF(_l("SPUasm: invalid fragment"));
      this->packet_size = this->packet_offset = 0;
      return;
    } else {
      memcpy(this->packet + this->packet_offset, packet, len);
      this->packet_offset += len;
    }
  }
#if 1
  // check if we have a complete packet (unfortunately packet_size is bad
  // for some disks)
  // [cb] packet_size is padded to be even -> may be one byte too long
  if ((this->packet_offset == this->packet_size) ||
      ((this->packet_offset + 1) == this->packet_size)){
    unsigned int x=0,y;
    while(x+4<=this->packet_offset){
      y=get_be16(this->packet+x+2); // next control pointer
      DPRINTF(_l("SPUtest: x=%d y=%d off=%d size=%d"),x,y,this->packet_offset,this->packet_size);
      if(x>=4 && x==y){         // if it points to self - we're done!
        // we got it!
               DPRINTF(_l("SPUgot: off=%d  size=%d "),this->packet_offset,this->packet_size);
               spudec_decode(pts100);
               this->packet_offset = 0;
               break;
      }
      if(y<=x || y>=this->packet_size){ // invalid?
               DPRINTF(_l("SPUtest: broken packet!!!!! y=%d < x=%d"),y,x);
        this->packet_size = this->packet_offset = 0;
        break;
      }
      x=y;
    }
    // [cb] packet is done; start new packet
    this->packet_offset = 0;
  }
#else
  if (this->packet_offset == this->packet_size) {
    spudec_decode(pts100);
    this->packet_offset = 0;
  }
#endif
/*
 packet_t *p=queue_head;
 while (p)
  {
   DPRINTF("packet: %i %i",p->start_pts,p->end_pts);
   p=p->next;
  }*/
}

void Tspudec::spudec_reset(void)  // called after seek
{
  while (queue_head)
    spudec_free_packet(spudec_dequeue_packet());
  now_pts = 0;
  end_pts = 0;
  packet_size = packet_offset = 0;
}

void Tspudec::spudec_heartbeat(unsigned int pts100)
{
  now_pts = pts100;

  while (queue_head != NULL && pts100 >= queue_head->start_pts) {
    packet_t *packet = spudec_dequeue_packet();
    start_pts = packet->start_pts;
    end_pts = packet->end_pts;
    if (auto_palette)
      compute_palette( packet);
    spudec_process_data( packet);
    spudec_free_packet(packet);
    spu_changed = 1;
  }
}

int Tspudec::spudec_visible(void){
    int ret=(start_pts <= now_pts &&
             now_pts < end_pts &&
             height > 0);
//    printf("spu visible: %d  ",ret);
    return ret;
}

void Tspudec::spudec_set_forced_subs_only( const unsigned int flag)
{
      forced_subs_only=flag;
      DPRINTF(_l("SPU: Display only forced subs now %s"), flag ? _l("enabled"): _l("disabled"));
}
/*
void Tspudec::spudec_draw( void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride,const void *self),const void *self)
{
    if (start_pts <= now_pts && now_pts < end_pts && image)
    {
        draw_alpha(start_col, start_row, width, height,
                   image, aimage, stride,self);
        spu_changed = 0;
    }
}
*/
/* calc the bbox for spudec subs */
void Tspudec::spudec_calc_bbox( unsigned int dxs, unsigned int dys, unsigned int* bbox)
{
  int y1;
  if (orig_frame_width == 0 || orig_frame_height == 0
  || (orig_frame_width == dxs && orig_frame_height == dys)) {
    bbox[0] = start_col;
    bbox[1] = start_col + width;
    bbox[2] = start_row;
    bbox[3] = start_row + height;
  }
  else if (scaled_frame_width != dxs || scaled_frame_height != dys) {
    unsigned int scalex = 0x100 * dxs / orig_frame_width;
    unsigned int scaley = 0x100 * dys / orig_frame_height;
    bbox[0] = start_col * scalex / 0x100;
    bbox[1] = start_col * scalex / 0x100 + width * scalex / 0x100;
    switch (spu_alignment) {
    case 0:
      bbox[3] = dys*sub_pos/100 + height * scaley / 0x100;
      if (bbox[3] > dys) bbox[3] = dys;
      bbox[2] = bbox[3] - height * scaley / 0x100;
      break;
    case 1:
      if (sub_pos < 50) {
	 y1 = dys*sub_pos/100 - height * scaley / 0x200;
	 if (y1 < 0) bbox[2] = 0; else bbox[2] = y1;
        bbox[3] = bbox[2] + height;
      } else {
        bbox[3] = dys*sub_pos/100 + height * scaley / 0x200;
        if (bbox[3] > dys) bbox[3] = dys;
        bbox[2] = bbox[3] - height * scaley / 0x100;
      }
      break;
    case 2:
      y1 = dys*sub_pos/100 - height * scaley / 0x100;
      if (y1 < 0) bbox[2] = 0; else bbox[2] = y1;
      bbox[3] = bbox[2] + height;
      break;
    default: /* -1 */
      bbox[2] = start_row * scaley / 0x100;
      bbox[3] = start_row * scaley / 0x100 + height * scaley / 0x100;
      break;
    }
  }
}
/* transform mplayer's alpha value into an opacity value that is linear */
int Tspudec::canon_alpha(int alpha)
{
 return alpha ? 256 - alpha : 0;
}

void Tspudec::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= std::min((unsigned int)(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 */
void Tspudec::scale_image(int x, int y, scale_pixel* table_x, scale_pixel* table_y)
{
  int alpha[4];
  int color[4];
  unsigned int scale[4];
  int base = table_y[y].position * stride + table_x[x].position;
  int scaled = y * scaled_strideY + x;
  alpha[0] = canon_alpha(aimage[base]);
  alpha[1] = canon_alpha(aimage[base + 1]);
  alpha[2] = canon_alpha(aimage[base + stride]);
  alpha[3] = canon_alpha(aimage[base + stride + 1]);
  color[0] = image[base];
  color[1] = image[base + 1];
  color[2] = image[base + stride];
  color[3] = image[base + 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];
  scaled_imageY[scaled] = (unsigned char)((color[0] * scale[0] + color[1] * scale[1] + color[2] * scale[2] + color[3] * scale[3])>>24);
  scaled_aimageY[scaled] = (unsigned char)((scale[0] + scale[1] + scale[2] + scale[3]) >> 16);
/*
  if (scaled_aimage[scaled]){
    scaled_aimage[scaled] = (unsigned char)(256 - scaled_aimage[scaled]);
    if(scaled_aimage[scaled] + scaled_image[scaled] > 255)
      scaled_image[scaled] = (unsigned char)(256 - scaled_aimage[scaled]);
  }*/
}

void Tspudec::sws_spu_image(unsigned char *d1, unsigned char *d2, int dw, int dh, stride_t ds,
        unsigned char *s1, unsigned char *s2, int sw, int sh, stride_t ss,const TrenderedSubtitleLines::TprintPrefs &prefs)
{
 if (!filter.lumH || oldgauss != prefs.vobaagauss)
  {
   if (filter.lumH) libmplayer->sws_freeVec(filter.lumH);
   filter.lumH = filter.lumV = filter.chrH = filter.chrV = libmplayer->sws_getGaussianVec(prefs.vobaagauss/1000.0, 3.0);
   libmplayer->sws_normalizeVec(filter.lumH, 1.0);
   oldgauss = prefs.vobaagauss;
  }

 SwsParams params;Tlibmplayer::swsInitParams(&params,SWS_GAUSS);
 SwsContext *ctx=libmplayer->sws_getContext(sw, sh, IMGFMT_Y800, dw, dh, IMGFMT_Y800, &params, &filter, NULL);
 libmplayer->sws_scale_ordered(ctx,(const uint8_t**)&s1,&ss,0,sh,&d1,&ds);
 for (stride_t i=ss*sh-1; i>=0; i--) s2[i]=(unsigned char)canon_alpha(s2[i]);
 libmplayer->sws_scale_ordered(ctx,(const uint8_t**)&s2,&ss,0,sh,&d2,&ds);
 libmplayer->sws_freeContext(ctx);
}

void Tspudec::spudec_draw_scaled(unsigned int dxs, unsigned int dys, TdrawAlpha draw_alpha,const TrenderedSubtitleLines::TprintPrefs &prefs)
{
  scale_pixel *table_x;
  scale_pixel *table_y;
  int y1;

  if (start_pts <= now_pts && now_pts < end_pts) {

    // check if only forced subtitles are requested
    if( (forced_subs_only) && !(is_forced_sub) ){
        return;
    }
/*
    if (!(spu_aamode&16) && (orig_frame_width == 0 || orig_frame_height == 0
        || (orig_frame_width == dxs && orig_frame_height == dys))) {
      if (image)
      {
        draw_alpha(start_col, start_row, width, height,
                   imageY, aimageY, strideY, imageUV, aimageUV,strideUV self);
        spu_changed = 0;
      }
    }
    else*/ {
      if (/*oldscale!=prefs.vobscale || */scaled_frame_width != dxs || scaled_frame_height != dys || spu_aamode!=prefs.vobaamode) {  /* Resizing is needed */
        spu_aamode=prefs.vobaamode;
        oldscale=prefs.vobscale;
        /* scaled_x = scalex * x / 0x100
           scaled_y = scaley * y / 0x100
           order of operations is important because of rounding. */
        unsigned int scalex = prefs.vobscale * dxs / orig_frame_width;
        unsigned int scaley = prefs.vobscale * dys / orig_frame_height;
        scaled_start_col = start_col * scalex / 0x100;
        scaled_start_row = start_row * scaley / 0x100;
         scaled_width = width * scalex / 0x100;
        scaled_height = height * scaley / 0x100;
        /* Kludge: draw_alpha needs width multiple of 8 */
        scaled_strideY = (scaled_width + 7) & ~7;
        scaled_strideUV = ((scaled_width/2) + 7) & ~7;
        if (scaled_image_size < scaled_strideY * scaled_height) {
          if (scaled_imageY) {
            free(scaled_imageY);
            scaled_image_size = 0;
          }
          if (scaled_imageUV)
            free(scaled_imageUV);
          scaled_imageY = (unsigned char*) malloc(2 * scaled_strideY * scaled_height);
          scaled_imageUV= (unsigned char*) malloc(2 * scaled_strideUV* ((scaled_height+1)/2));
          if (scaled_imageY) {
            scaled_image_size = scaled_strideY * scaled_height;
            scaled_aimageY = scaled_imageY + scaled_image_size;
            scaled_aimageUV= scaled_imageUV+ scaled_strideUV * ((scaled_height+1)/2);
          }
        }
        if (scaled_imageY) {
          //unsigned int x, y;
          /* Kludge: draw_alpha needs width multiple of 8. */
          if (scaled_width < scaled_strideY)
           for (unsigned int y = 0; y < scaled_height; ++y)
            {

⌨️ 快捷键说明

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