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

📄 tsubtitledvd.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}

void TsubtitleDVD::createImage(const TspuPlane src[3],const CRect &rcclip,CRect rectReal,const TrenderedSubtitleLines::TprintPrefs &prefs) const
{
 lines.clear();
 rectReal.bottom++;rectReal.right++;
#ifdef __SSE2__
 if (Tconfig::cpu_flags&FF_CPU_SSE2)
  image=new TspuImageSimd<Tsse2>(src,rcclip,rectReal,parent->rectOrig,prefs);
 else
#endif
  image=new TspuImageSimd<Tmmx>(src,rcclip,rectReal,parent->rectOrig,prefs);
 lines.add(new TrenderedSubtitleLine(image),NULL);
}
void TsubtitleDVD::linesprint(const TrenderedSubtitleLines::TprintPrefs &prefs) const
{
 if (prefs.dvd || !prefs.vobchangeposition)
  image->ownprint(prefs);
 else
  lines.print(prefs);
}

void TsubtitleDVD::print(REFERENCE_TIME time,bool wasseek,Tfont &f,bool forceChange,const TrenderedSubtitleLines::TprintPrefs &prefs) const
{
 if (this->offset[0]==DWORD(-1))
  return;

 if (lines.empty() || changed)
  {
   changed=false;

   const BYTE *p=&*data.begin();
   DWORD offset[2]={this->offset[0],this->offset[1]};

   AM_PROPERTY_SPHLI sphli=this->sphli;
   CPoint pt(sphli.StartX, sphli.StartY);
   CRect rc(pt, CPoint(sphli.StopX, sphli.StopY));

   if (parent->rectOrig.dx==0)
    parent->rectOrig=CRect(0,0,prefs.dx,prefs.dy);
   CRect rcclip=parent->rectOrig;
   rcclip&=rc;

   if (psphli)
    {
     rcclip&=CRect(psphli->StartX,psphli->StartY,psphli->StopX,psphli->StopY);
     sphli=*psphli;
    }

   TspuPlane *planes=parent->allocPlanes(rcclip);
   DPRINTF(_l("rect: [%i,%i] - [%i,%i]"),rcclip.left,rcclip.top,rcclip.Width(),rcclip.Height());

   AM_DVD_YUV pal[4];
   pal[0]=parent->sppal[parent->fsppal?sphli.ColCon.backcol :0];pal[0].Reserved=sphli.ColCon.backcon;
   pal[1]=parent->sppal[parent->fsppal?sphli.ColCon.patcol  :1];pal[1].Reserved=sphli.ColCon.patcon;
   pal[2]=parent->sppal[parent->fsppal?sphli.ColCon.emph1col:2];pal[2].Reserved=sphli.ColCon.emph1con;
   pal[3]=parent->sppal[parent->fsppal?sphli.ColCon.emph2col:3];pal[3].Reserved=sphli.ColCon.emph2con;

   int nField=0;
   int fAligned=1;

   DWORD end[2]={offset[1],(p[2]<<8)|p[3]};

   CRect rectReal(INT_MAX/2,INT_MAX/2,INT_MIN/2,INT_MIN/2);
   while ((nField==0 && offset[0]<end[0]) || (nField==1 && offset[1]<end[1]))
    {
     DWORD code;
     if ((code=getNibble(p,offset,nField,fAligned))>=0x4 ||
         (code=(code<<4) | getNibble(p,offset,nField,fAligned))>=0x10 ||
         (code=(code<<4) | getNibble(p,offset,nField,fAligned))>=0x40 ||
         (code=(code<<4) | getNibble(p,offset,nField,fAligned))>=0x100)
      {
       drawPixels(pt,code>>2,pal[code&3],rcclip,rectReal,planes);
       if ((pt.x+=code>>2)<rc.right)
        continue;
      }

     drawPixels(pt,rc.right-pt.x,pal[code&3],rcclip,rectReal,planes);

     if (!fAligned) getNibble(p,offset,nField,fAligned); // align to byte

     pt.x=rc.left;
     pt.y++;
     nField=1-nField;
    }
   DPRINTF(_l("rectReal: [%i,%i] - [%i,%i]"),rectReal.left,rectReal.top,rectReal.Width(),rectReal.Height());
   createImage(planes,rcclip,rectReal,prefs);
  }
 linesprint(prefs);
}

void TsubtitleDVD::append(const unsigned char *Idata,unsigned int Idatalen)
{
 data.append(Idata,Idatalen);
 parse();
}

bool TsubtitleDVD::parse(void)
{
 BYTE *p=&*data.begin();

 WORD packetsize=short((p[0]<<8)|p[1]);
 WORD datasize=short((p[2]<<8)|p[3]);

 if (packetsize>data.size() || datasize>packetsize)
  return false;

 int i,next=datasize;

 do
  {
   i=next;
   int pts=(p[i]<<8)|p[i+1];i+=2;
   next=(p[i]<<8)|p[i+1];i+=2;

   if (next>packetsize || next<datasize)
    return false;

   for (bool fBreak=false;!fBreak;)
    {
     int len;
     switch(p[i])
      {
       case 0x00:len=0;break;
       case 0x01:len=0;break;
       case 0x02:len=0;break;
       case 0x03:len=2;break;
       case 0x04:len=2;break;
       case 0x05:len=6;break;
       case 0x06:len=4;break;
       default  :len=0;break;
      }
     if (i+len>=packetsize)
      {
       DPRINTF(_l("Warning: Wrong subpicture parameter block ending"));
       break;
      }

     switch (p[i++])
      {
       case 0x00: // forced start displaying
        forced=true;
        break;
       case 0x01: // normal start displaying
        forced=false;
        break;
       case 0x02: // stop displaying
        stop=start+1024*pts2rt(pts);
        break;
       case 0x03:
        sphli.ColCon.emph2col=p[i]>>4;
        sphli.ColCon.emph1col=p[i]&0xf;
        sphli.ColCon.patcol =p[i+1]>>4;
        sphli.ColCon.backcol=p[i+1]&0xf;
        i += 2;
        break;
       case 0x04:
        sphli.ColCon.emph2con=p[i]>>4;
        sphli.ColCon.emph1con=p[i]&0xf;
        sphli.ColCon.patcon =p[i+1]>>4;
        sphli.ColCon.backcon=p[i+1]&0xf;
        i += 2;
        break;
       case 0x05:
        sphli.StartX=USHORT((p[i]<<4) + (p[i+1]>>4));
        sphli.StopX =USHORT(((p[i+1]&0x0f)<<8) + p[i+2]+1);
        sphli.StartY=USHORT((p[i+3]<<4) + (p[i+4]>>4));
        sphli.StopY =USHORT(((p[i+4]&0x0f)<<8) + p[i+5]+1);
        i += 6;
        break;
       case 0x06:
        offset[0]=(p[i]<<8)|p[i+1];i+=2;
        offset[1]=(p[i]<<8)|p[i+1];i+=2;
        break;
       case 0xff: // end of ctrlblk
        fBreak=true;
        continue;
       default: // skip this ctrlblk
        fBreak=true;
        break;
      }
    }
  } while (i<=next && i<packetsize);
 return true;
}

//===================================== TsubtitleSVCD =====================================
bool TsubtitleSVCD::parse(void)
{
 BYTE *p=&*data.begin(),*p0=p;
 if (data.size()<2)
  return false;

 WORD packetsize=WORD((p[0]<<8)|p[1]);p += 2;

 if (packetsize>data.size())
  return false;

 bool duration=!!(*p++&0x04);

 *p++; // unknown

 if(duration)
  {
   stop=start+10000LL*((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3])/90;
   p+=4;
  }
 sphli.StartX=sphli.StopX=USHORT((p[0]<<8)|p[1]);p+=2;
 sphli.StartY=sphli.StopY=USHORT((p[0]<<8)|p[1]);p+=2;
 sphli.StopX=USHORT(sphli.StopX+(p[0]<<8)|p[1]);p+=2;
 sphli.StopY=USHORT(sphli.StopY+(p[0]<<8)|p[1]);p+=2;

 for (int i=0;i<4;i++)
  {
   sppal[i].Y=*p++;
   sppal[i].U=*p++;
   sppal[i].V=*p++;
   sppal[i].Reserved=UCHAR(*p++>>4);
  }

 if (*p++&0xc0)
  p+=4; // duration of the shift operation should be here, but it is untested

 offset[1]=(p[0]<<8)|p[1];p+=2;

 offset[0]=DWORD(p-p0);
 offset[1]+=offset[0];

 return true;
}
void TsubtitleSVCD::print(REFERENCE_TIME time,bool wasseek,Tfont &f,bool forceChange,const TrenderedSubtitleLines::TprintPrefs &prefs) const
{
 if (lines.empty() || changed)
  {
   changed=false;

   const BYTE *p=&*data.begin();
   DWORD offset[2]={this->offset[0],this->offset[1]};

   CRect rcclip(0,0,prefs.dx,prefs.dy);

   /* FIXME: startx/y looks to be wrong in the sample I tested (yes, this one too!)
   CPoint pt(m_sphli.StartX, m_sphli.StartY);
   CRect rc(pt, CPoint(m_sphli.StopX, m_sphli.StopY));
   */

   CSize size(sphli.StopX - sphli.StartX, sphli.StopY - sphli.StartY);
   CPoint pt((rcclip.Width() - size.cx) / 2, (rcclip.Height()*3 - size.cy*1) / 4);
   CRect rc(pt, size);

   int nField=0;
   int n=3;

   DWORD end[2]={offset[1],(p[2]<<8)|p[3]};

   CRect rectReal(INT_MAX/2,INT_MAX/2,INT_MIN/2,INT_MIN/2);
   TspuPlane *planes=parent->allocPlanes(rcclip);
   while ((nField==0 && offset[0]<end[0]) || (nField==1 && offset[1]<end[1]))
    {
     BYTE code=getHalfNibble(p,offset,nField,n);
     BYTE repeat=BYTE(1+(code==0?getHalfNibble(p,offset,nField,n):0));

     drawPixels(pt,repeat,sppal[code&3],rcclip,rectReal,planes);
     if ((pt.x+=repeat)<rc.right) continue;
     while(n!=3)
      getHalfNibble(p,offset,nField,n); // align to byte
     pt.x=rc.left;
     pt.y++;
     nField=1-nField;
    }
   createImage(planes,rcclip,rectReal,prefs);
  }
 linesprint(prefs);
}

//===================================== TsubtitleCVD ======================================
bool TsubtitleCVD::parse(void)
{
 const BYTE *p=&*data.begin();
 WORD packetsize=WORD((p[0]<<8)|p[1]);
 WORD datasize=WORD((p[2]<<8)|p[3]);

 if (packetsize>data.size() || datasize>packetsize)
  return false;

 p=&*data.begin()+datasize;

 for (int i=datasize,j=packetsize-4;i<=j;i+=4,p+=4)
  switch(p[0])
   {
    case 0x0c:
     break;
    case 0x04:
     stop=start+10000LL*((p[1]<<16)|(p[2]<<8)|p[3])/90;
     break;
    case 0x17:
     sphli.StartX=USHORT(((p[1]&0x0f)<<6) + (p[2]>>2));
     sphli.StartY=USHORT(((p[2]&0x03)<<8) + p[3]);
     break;
    case 0x1f:
     sphli.StopX=USHORT(((p[1]&0x0f)<<6) + (p[2]>>2));
     sphli.StopY=USHORT(((p[2]&0x03)<<8) + p[3]);
     break;
    case 0x24:
    case 0x25:
    case 0x26:
    case 0x27:
     sppal[0][p[0]-0x24].Y=p[1];
     sppal[0][p[0]-0x24].U=p[2];
     sppal[0][p[0]-0x24].V=p[3];
     break;
    case 0x2c:
    case 0x2d:
    case 0x2e:
    case 0x2f:
     sppal[1][p[0]-0x2c].Y=p[1];
     sppal[1][p[0]-0x2c].U=p[2];
     sppal[1][p[0]-0x2c].V=p[3];
     break;
    case 0x37:
     sppal[0][3].Reserved=UCHAR(p[2]>>4);
     sppal[0][2].Reserved=UCHAR(p[2]&0xf);
     sppal[0][1].Reserved=UCHAR(p[3]>>4);
     sppal[0][0].Reserved=UCHAR(p[3]&0xf);
     break;
    case 0x3f:
     sppal[1][3].Reserved=UCHAR(p[2]>>4);
     sppal[1][2].Reserved=UCHAR(p[2]&0xf);
     sppal[1][1].Reserved=UCHAR(p[3]>>4);
     sppal[1][0].Reserved=UCHAR(p[3]&0xf);
     break;
    case 0x47:
     offset[0] = (p[2]<<8)|p[3];
     break;
    case 0x4f:
     offset[1] = (p[2]<<8)|p[3];
     break;
    default:
     break;
   }
 return true;
}
void TsubtitleCVD::print(REFERENCE_TIME time,bool wasseek,Tfont &f,bool forceChange,const TrenderedSubtitleLines::TprintPrefs &prefs) const
{
 if (lines.empty() || changed)
  {
   changed=false;

   const BYTE *p=&*data.begin();
   DWORD offset[2]={this->offset[0],this->offset[1]};

   CRect rcclip(0,0,prefs.dx,prefs.dy);

   /* FIXME: startx/y looks to be wrong in the sample I tested
   CPoint pt(m_sphli.StartX, m_sphli.StartY);
   CRect rc(pt, CPoint(m_sphli.StopX, m_sphli.StopY));
   */

   CSize size(sphli.StopX-sphli.StartX,sphli.StopY-sphli.StartY);
   CPoint pt((rcclip.Width() - size.cx) / 2, (rcclip.Height()*3 - size.cy*1) / 4);
   CRect rc(pt,size);

   int nField=0;
   int fAligned=1;

   DWORD end[2]={offset[1],(p[2]<<8)|p[3]};

   CRect rectReal(INT_MAX/2,INT_MAX/2,INT_MIN/2,INT_MIN/2);
   TspuPlane *planes=parent->allocPlanes(rcclip);
   while ((nField==0 && offset[0]<end[0]) || (nField==1 && offset[1]<end[1]))
    {
     BYTE code;

     if ((code=getNibble(p,offset,nField,fAligned))>=0x4)
      {
       drawPixels(pt,code>>2,sppal[0][code&3],rcclip,rectReal,planes);
       pt.x+=code>>2;
       continue;
      }

     code=getNibble(p,offset,nField,fAligned);
     drawPixels(pt,rc.right-pt.x,sppal[0][code&3],rcclip,rectReal,planes);

     if (!fAligned)
      getNibble(p,offset,nField,fAligned); // align to byte

     pt.x=rc.left;
     pt.y++;
     nField=1-nField;
    }
   createImage(planes,rcclip,rectReal,prefs);
  }
 linesprint(prefs);
}

⌨️ 快捷键说明

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