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

📄 tsubtitledvd.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2004-2006 Milan Cutka
 * based of CSubpicInputPin by Gabest
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "stdafx.h"
#include "TsubtitleDVD.h"
#include "TsubtitlesTextpinDVD.h"
#include "ffdebug.h"
#include "TspuImage.h"
#include "Tstream.h"
#include "Tconfig.h"
#include "simd.h"

//=================================== TsubtitleDVDparent ==================================
TsubtitleDVDparent::TsubtitleDVDparent(void)
{
 psphli=NULL;
 fsppal=false;spon=true;
 sppal[0].Y=0x00;sppal[0].U=sppal[0].V=0x80;
 sppal[1].Y=0xe0;sppal[1].U=sppal[1].V=0x80;
 sppal[2].Y=0x80;sppal[2].U=sppal[2].V=0x80;
 sppal[3].Y=0x20;sppal[3].U=sppal[3].V=0x80;
 delay=0;forced_subs=false;
 custom_colors=false;tridx=0;
}

TspuPlane* TsubtitleDVDparent::allocPlanes(const CRect &r)
{
 planes[0].alloc(r.Size(),1);
 planes[1].alloc(r.Size(),1);
 planes[2].alloc(r.Size(),2);
 return planes;
}

const char* TsubtitleDVDparent::parseTimestamp(const char* &line,int &ms)
{
 while (isspace(*line))
  ++line;
 int forward=1;
 if (line[0]=='+')
  {
   forward = 1;
   line++;
  }
 else if (line[0]=='-')
  {
   forward = -1;
   line++;
  }
 const char *p = line;
 while (isdigit(*p))
  ++p;
 if (p - line == 0)
  return NULL;
 int h = atoi(line);
 if (*p != ':')
  return NULL;
 line = ++p;
 while (isdigit(*p))
  ++p;
 if (p - line == 0)
  return NULL;
 int m = atoi(line);
 if (*p != ':')
  return NULL;
 line = ++p;
 while (isdigit(*p))
  ++p;
 if (p - line == 0)
  return NULL;
 int s = atoi(line);
 if (*p != ':')
  return NULL;
 line = ++p;
 while (isdigit(*p))
  ++p;
 if (p - line == 0)
  return NULL;
 ms = (atoi(line) + 1000 * (s + 60 * (m + 60 * h)))*forward;
 return p;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_delay(const char *line)
{
 return parseTimestamp(line,delay)?PARSE_OK:PARSE_ERROR;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_size(const char *line)
{
 // size: WWWxHHH
 char *p;
 while (isspace(*line))
  ++line;
 if (!isdigit(*line))
  return PARSE_ERROR;
 rectOrig.dx=strtoul(line, &p, 10);
 if (*p != 'x')
  return PARSE_ERROR;
 ++p;
 rectOrig.dy=strtoul(p, NULL, 10);
 return PARSE_OK;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_origin(const char *line)
{
 // org: X,Y
 char *p;
 while (isspace(*line))
  ++line;
 if (!isdigit(*line))
  return PARSE_ERROR;
 rectOrig.x = strtoul(line, &p, 10);
 if (*p != ',')
  return PARSE_ERROR;
 ++p;
 rectOrig.y = strtoul(p, NULL, 10);
 return PARSE_OK;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_forced_subs(const char *line)
{
 const char *p;

 p  = line;
 while (isspace(*p))
  ++p;

 if (_strnicmp("on",p,2) == 0)
  {
   forced_subs=true;
   return PARSE_OK;
  }
 else if (_strnicmp("off",p,3) == 0)
  {
   forced_subs=false;
   return PARSE_OK;
  }
 else
  return PARSE_ERROR;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_palette(const char *line)
{
 // palette: XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX
 unsigned int n=0;
 PARSE_RES res=PARSE_OK;;
 while (1)
  {
   const char *p;
   int r, g, b, tmp;
   while (isspace(*line))
    ++line;
   p = line;
   while (isxdigit(*p))
    ++p;
   if (p - line != 6)
    {
     res=PARSE_ERROR;
     break;
    }
   tmp = strtoul(line, NULL, 16);
   r = tmp >> 16 & 0xff;
   g = tmp >> 8 & 0xff;
   b = tmp & 0xff;
   YUVcolor yuv(RGB(r,g,b),true);
   sppal[n].Y=yuv.Y;
   sppal[n].U=yuv.U;
   sppal[n].V=yuv.V;
   n++;
   if (n == 16)
    break;
   if (*p == ',')
    ++p;
   line = p;
  }
 if (n>0) fsppal=true;
 return res;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_custom(const char *line)
{
 //custom colors: OFF/ON(0/1)
 if ((strncmp("ON", line + 15, 2) == 0)||strncmp("1", line + 15, 1) == 0)
  {
   custom_colors=1;
   return PARSE_OK;
  }
 else if ((strncmp("OFF", line + 15, 3) == 0)||strncmp("0", line + 15, 1) == 0)
  {
   custom_colors=0;
   return PARSE_OK;
  }
 else
  return PARSE_ERROR;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_tridx(const char *line)
{
 //tridx: XXXX
 tridx = strtoul((line + 26), NULL, 16);
 tridx = ((tridx&0x1000)>>12) | ((tridx&0x100)>>7) | ((tridx&0x10)>>2) | ((tridx&1)<<3);
 return PARSE_OK;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_cuspal(const char *line)
{
 //colors: XXXXXX, XXXXXX, XXXXXX, XXXXXX
 unsigned int n;
 n = 0;
 line += 40;
 while(1)
  {
   const char *p;
   while (isspace(*line))
    ++line;
   p=line;
   while (isxdigit(*p))
    ++p;
   if (p - line !=6)
    return PARSE_ERROR;
   unsigned int tmp = strtoul(line, NULL, 16);
   int r = tmp >> 16 & 0xff;
   int g = tmp >> 8 & 0xff;
   int b = tmp & 0xff;
   YUVcolor yuv(RGB(r,g,b));
   cuspal[n].Y=yuv.Y;
   cuspal[n].U=yuv.U;
   cuspal[n].V=yuv.V;
   n++;
   if (n==4)
    break;
   if(*p == ',')
    ++p;
   line = p;
  }
 return PARSE_OK;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse_one_line(const char *line)
{
 if (strncmp("delay:", line, 6) == 0)
  return idx_parse_delay( line + 6);
 else if (strncmp("size:", line, 5) == 0)
  return idx_parse_size( line + 5);
 else if (strncmp("org:", line, 4) == 0)
  return idx_parse_origin( line + 4);
 else if (strncmp("palette:", line, 8) == 0)
  return idx_parse_palette( line + 8);
 else if (strncmp("custom colors:", line, 14) == 0) //custom colors: ON/OFF, tridx: XXXX, colors: XXXXXX, XXXXXX, XXXXXX,XXXXXX
  if (idx_parse_custom(line)==PARSE_OK &&
      idx_parse_tridx(line)==PARSE_OK &&
      idx_parse_cuspal(line)==PARSE_OK)
   return PARSE_OK;
  else
   return PARSE_ERROR;
 else if (strncmp("forced subs:", line, 12) == 0)
  return idx_parse_forced_subs( line + 12);
 else
  return PARSE_IGNORE;
}

TsubtitleDVDparent::PARSE_RES TsubtitleDVDparent::idx_parse(Tstream &fs)
{
 while (1)
  {
   char line[4096];
   if (!fs.fgets(line,4096))
    return PARSE_OK;
   if (*line == 0 || *line == '\r' || *line == '\n' || *line == '#')
    continue;
   PARSE_RES res=idx_parse_one_line(line);
   if (res==PARSE_IGNORE)
    {
     DPRINTF(_l("idx: ignoring %s"), line);
     continue;
    }
   else if (res==PARSE_ERROR)
    {
     DPRINTF(_l("idx: ERROR in %s"), line);
     return PARSE_ERROR;
    }
  }
}

//===================================== TsubtitleDVD ======================================
TsubtitleDVD::TsubtitleDVD(REFERENCE_TIME Istart,const unsigned char *Idata,unsigned int Idatalen,TsubtitleDVDparent *Iparent):parent(Iparent)
{
 start=Istart;
 stop=_I64_MAX;
 memset(&sphli,0,sizeof(sphli));
 forced=false;
 data.append(Idata,Idatalen);
 if (parent->psphli && start==pts2rt(parent->psphli->StartPTM))
  psphli=new AM_PROPERTY_SPHLI(*parent->psphli);
 else
  psphli=NULL;
 offset[0]=DWORD(-1);
 parse();
 changed=true;
 image=NULL;
}
TsubtitleDVD::~TsubtitleDVD()
{
 lines.clear();
}

BYTE TsubtitleDVD::getNibble(const BYTE *p,DWORD *offset,int &nField,int &fAligned)
{
 BYTE ret=BYTE((p[offset[nField]]>>(fAligned<<2))&0x0f);
 offset[nField]+=1-fAligned;
 fAligned=!fAligned;
 return ret;
}
BYTE TsubtitleDVD::getHalfNibble(const BYTE *p,DWORD *offset,int &nField,int &n)
{
 BYTE ret=BYTE((p[offset[nField]]>>(n<<1))&0x03);
 if (!n) offset[nField]++;
 n=(n-1+4)&3;
 return ret;
}

void TsubtitleDVD::drawPixel(const CPoint &pt,const AM_DVD_YUV &c,CRect &rectReal,TspuPlane plane[3]) const
{
/*
 if (c.Reserved==0) return;

 BYTE *p=&prefs.dst[0][pt.y*prefs.stride[0]+pt.x];
 *p-=(*p-c.Y)*c.Reserved>>4;

 // U/V is exchanged? weird but looks true when comparing the outputted colors from other decoders
 p=&prefs.dst[1][(pt.y/2)*prefs.stride[1]+(pt.x+1)/2];
 *p-=(*p-c.V)*c.Reserved>>4;
 p=&prefs.dst[2][(pt.y/2)*prefs.stride[2]+(pt.x+1)/2];
 *p-=(*p-c.U)*c.Reserved>>4;
*/
 int ptx=pt.x,pty=pt.y;
 if (c.Reserved!=0)
  {
   if (ptx<rectReal.left) rectReal.left=ptx;
   if (ptx>rectReal.right) rectReal.right=ptx;
  }
 plane[0].c[pty*plane[0].stride+ptx]=c.Y;
 plane[0].r[pty*plane[0].stride+ptx]=c.Reserved;

 if (pty&1) return;

 ptx=(ptx+1)/2;pty/=2;
 plane[1].c[pty*plane[1].stride+ptx]=c.V;
 plane[1].r[pty*plane[1].stride+ptx]=c.Reserved;

 plane[2].c[pty*plane[2].stride+ptx]=c.U;
 plane[2].r[pty*plane[2].stride+ptx]=c.Reserved;
}

void TsubtitleDVD::drawPixels(CPoint pt,int len,const AM_DVD_YUV &c,const CRect &rc,CRect &rectReal,TspuPlane plane[3]) const
{
 if (pt.y < rc.top || pt.y >= rc.bottom) return;
 if (pt.x < rc.left) {len -= rc.left - pt.x; pt.x = rc.left;}
 if (pt.x + len > rc.right) len = rc.right - pt.x;
 if (len <= 0 || pt.x >= rc.right) return;

 if (c.Reserved==0)
  {
   if (IsRectEmpty(&rc))
    return;

   if (pt.y < rc.top || pt.y >= rc.bottom  || pt.x+len < rc.left || pt.x >= rc.right)
    return;
  }

 int y=pt.y-rc.top;
 if (c.Reserved!=0)
  {
   if (y<rectReal.top) rectReal.top=y;
   if (y>rectReal.bottom) rectReal.bottom=y;
  }
 while (len-->0)
  {
   drawPixel(CPoint(pt.x-rc.left,y),c,rectReal,plane);
   pt.x++;
  }

⌨️ 快捷键说明

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