📄 tsubreadermplayer.cpp
字号:
if (!fd.fgets (line, this->LINE_LEN))
return previous=store(current);
next = line;//,i=1;
while ((next =sub_readtext (next,current))!=NULL)
;
if (current.at(0)[0]=='\0' && current.at(1)[0]=='\0') {
// void subtitle -> end of previous marked and exit
previous = NULL;
return NULL;
}
return previous=store(current);
}
template<class tchar> Tsubtitle* TsubtitleParserSubrip09<tchar>::parse(Tstream &fd,int flags) {
tchar line[this->LINE_LEN+1];
int a1,a2,a3;
const tchar * next=NULL;
int i;
while (1) {
// try to locate next subtitle
if (!fd.fgets (line, this->LINE_LEN))
return NULL;
if (!(tchar_traits<tchar>::sscanf() (line, _L("[%d:%d:%d]"),&a1,&a2,&a3) < 3))
break;
}
TsubtitleTextBase<tchar> current(this->format);
current.start = this->hmsToTime(a1,a2,a3);
if (previous != NULL)
previous->stop = current.start-1;
if (!fd.fgets (line, this->LINE_LEN))
return NULL;
next = line;i=0;
//(*current)[0]=""; // just to be sure that string is clear
while ((next =sub_readtext (next, current))!=NULL)
i++;
if (current.size()==0 || (current.at(0)[0]=='\0') && (i==0)) {
// void subtitle -> end of previous marked and exit
previous = NULL;
return NULL;
}
return previous=store(current);
}
template<class tchar> Tsubtitle* TsubtitleParserMPL2<tchar>::parse(Tstream &fd,int flags) {
tchar line[this->LINE_LEN+1];
tchar line2[this->LINE_LEN+1];
const tchar *p,*next;
int start=0,end=0;
do {
if (!fd.fgets (line, this->LINE_LEN)) return NULL;
} while ((tchar_traits<tchar>::sscanf() (line,
_L("[%ld][%ld]%[^\r\n]"),
&start, &end, line2) < 3));
TsubtitleTextBase<tchar> current(this->format);
current.start = this->frameToTime(start);
current.stop = this->frameToTime(end);
p=line2;
next=p;
while ((next =sub_readtext (next, current))!=NULL)
;
return store(current);
}
template<class tchar> TsubtitleParserBase* TsubtitleParserBase::getParser0(int format,double fps,const TsubtitlesSettings *cfg,const Tconfig *ffcfg,Tsubreader *subreader,bool isEmbedded)
{
switch (format&Tsubreader::SUB_FORMATMASK)
{
case Tsubreader::SUB_MICRODVD :return new TsubtitleParserMicrodvd<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_SUBRIP :return new TsubtitleParserSubrip<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_SUBVIEWER :return new TsubtitleParserSubviewer<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_SAMI :return new TsubtitleParserSami<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_VPLAYER :return new TsubtitleParserVplayer<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_RT :return new TsubtitleParserRt<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_SSA :return new TsubtitleParserSSA<tchar>(format,fps,cfg,ffcfg,subreader,isEmbedded);
case Tsubreader::SUB_DUNNOWHAT :return new TsubtitleParserDunnowhat<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_MPSUB :return new TsubtitleParserMPsub<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_AQTITLE :return new TsubtitleParserAqt<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_SUBVIEWER2:return new TsubtitleParserSubviewer2<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_SUBRIP09 :return new TsubtitleParserSubrip09<tchar>(format,fps,cfg,ffcfg,subreader);
case Tsubreader::SUB_MPL2 :return new TsubtitleParserMPL2<tchar>(format,fps,cfg,ffcfg,subreader);
default:return NULL;
}
}
TsubtitleParserBase* TsubtitleParserBase::getParser(int format,double fps,const TsubtitlesSettings *cfg,const Tconfig *ffcfg,Tsubreader *subreader,bool utf8,bool isEmbedded)
{
if (ffcfg->unicodeOS && (utf8 || Tsubreader::getSubEnc(format)&Tstream::ENC_UNICODE))
return getParser0<wchar_t>(format,fps,cfg,ffcfg,subreader,isEmbedded);
else
return getParser0<char>(format,fps,cfg,ffcfg,subreader,isEmbedded);
}
//======================================= TsubreaderMplayer =======================================
TsubreaderMplayer::TsubreaderMplayer(Tstream &fd,int sub_format,double fps,const TsubtitlesSettings *cfg,const Tconfig *ffcfg,bool isEmbedded)
{
TsubtitleParserBase *parser=TsubtitleParserBase::getParser(sub_format,fps,cfg,ffcfg,this,false,isEmbedded);
if (!parser) return;
fd.rewind();
while (parser->parse(fd))
;
delete parser;
processDuration(cfg);
if (cfg->timeoverlap && !empty())
{
for (iterator s=begin();s!=end()-1;s++)
if ((*s)->stop<(*s)->start)
(*s)->stop=(*(s+1))->start-1;
processOverlap(sub_format);
}
}
void Tsubreader::processOverlap(int sub_format)
{
int sub_format1=sub_format&Tsubreader::SUB_FORMATMASK;
if (!(sub_format1==Tsubreader::SUB_MICRODVD
|| sub_format1==Tsubreader::SUB_SUBRIP
|| sub_format1==Tsubreader::SUB_SAMI
|| sub_format1==Tsubreader::SUB_VPLAYER
|| sub_format1==Tsubreader::SUB_RT
|| sub_format1==Tsubreader::SUB_SSA
|| sub_format1==Tsubreader::SUB_DUNNOWHAT
|| sub_format1==Tsubreader::SUB_MPSUB
|| sub_format1==Tsubreader::SUB_AQTITLE
|| sub_format1==Tsubreader::SUB_SUBVIEWER2
|| sub_format1==Tsubreader::SUB_SUBRIP09
|| sub_format1==Tsubreader::SUB_MPL2))
return;
static const int SUB_MAX_TEXT=INT_MAX/2;
int sub_orig = size();
int n_first = size();
int sub_num =0;
std::vector<Tsubtitle*> newsubs;
for (int sub_first = 0; sub_first < n_first; ++sub_first)
{
REFERENCE_TIME global_start = at(sub_first)->start,global_end = at(sub_first)->stop, local_start, local_end;
int lines_to_add = at(sub_first)->numlines(), sub_to_add = 0;
int **placeholder = NULL, higher_line = 0, counter, start_block_sub = sub_num;
char real_block = 1;
// here we find the number of subtitles inside the 'block'
// and its span interval. this works well only with sorted
// subtitles
while ((sub_first + sub_to_add + 1 < n_first) && (at(sub_first + sub_to_add + 1)->start < global_end))
{
++sub_to_add;
lines_to_add += at(sub_first + sub_to_add)->numlines();
if (at(sub_first + sub_to_add)->start < global_start)
global_start = at(sub_first + sub_to_add)->start;
if (at(sub_first + sub_to_add)->stop > global_end)
global_end = at(sub_first + sub_to_add)->stop;
}
// we need a structure to keep trace of the screen lines
// used by the subs, a 'placeholder'
counter = 2 * sub_to_add + 1; // the maximum number of subs derived rom a block of sub_to_add+1 subs
placeholder = (int **) malloc(sizeof(int *) * counter);
for (int i = 0; i < counter; ++i)
{
placeholder[i] = (int *) malloc(sizeof(int) * lines_to_add);
for (int j = 0; j < lines_to_add; ++j)
placeholder[i][j] = -1;
}
counter = 0;
local_end = global_start - 1;
do
{
// here we find the beginning and the end of a new subtitle in the block
local_start = local_end + 1;
local_end = global_end;
for (int j = 0; j <= sub_to_add; ++j)
if ((at(sub_first + j)->start - 1 > local_start) && (at(sub_first + j)->start - 1 < local_end))
local_end = at(sub_first + j)->start - 1;
else if ((at(sub_first + j)->stop > local_start) && (at(sub_first + j)->stop< local_end))
local_end = at(sub_first + j)->stop;
// here we allocate the screen lines to subs we must
// display in current local_start-local_end interval.
// if the subs were yet presents in the previous interval
// they keep the same lines, otherwise they get unused lines
for (int j = 0; j <= sub_to_add; ++j)
{
if ((at(sub_first + j)->start <= local_end) && (at(sub_first + j)->stop > local_start))
{
unsigned long sub_lines=at(sub_first + j)->numlines(), fragment_length = lines_to_add + 1,tmp=0;
char boolean = 0;
int fragment_position = -1;
// if this is not the first new sub of the block
// we find if this sub was present in the previous
// new sub
if (counter)
for (int i = 0; i < lines_to_add; ++i)
if (placeholder[counter - 1][i] == sub_first + j)
{
placeholder[counter][i] = sub_first + j;
boolean = 1;
}
if (boolean)
continue;
// we are looking for the shortest among all groups of
// sequential blank lines whose length is greater than or
// equal to sub_lines. we store in fragment_position the
// position of the shortest group, in fragment_length its
// length, and in tmp the length of the group currently
// examined
int i;
for (i = 0; i < lines_to_add; ++i)
{
if (placeholder[counter][i] == -1)
++tmp; // placeholder[counter][i] is part of the current group of blank lines
else
{
if (tmp == sub_lines)
{
// current group's size fits exactly the one we
// need, so we stop looking
fragment_position = i - tmp;
tmp = 0;
break;
}
if ((tmp) && (tmp > sub_lines) && (tmp < fragment_length))
{
// current group is the best we found till here,
// but is still bigger than the one we are looking
// for, so we keep on looking
fragment_length = tmp;
fragment_position = i - tmp;
tmp = 0;
}
else
tmp = 0; // current group doesn't fit at all, so we forget it
}
}
if (tmp)
if ((tmp >= sub_lines) && (tmp < fragment_length)) // last screen line is blank, a group ends with it
fragment_position = i - tmp;
if (fragment_position == -1)
{
// it was not possible to find free screen line(s) for a subtitle,
// usually this means a bug in the code; however we do not overlap
//mp_msg(MSGT_SUBREADER, MSGL_WARN, "SUB: we could not find a suitable position for an overlapping subtitle\n");
higher_line = SUB_MAX_TEXT + 1;
break;
}
else
for (tmp = 0; tmp < sub_lines; ++tmp)
placeholder[counter][fragment_position + tmp] = sub_first + j;
}
}
for (int j = higher_line + 1; j < lines_to_add; ++j)
if (placeholder[counter][j] != -1)
higher_line = j;
else
break;
// we read the placeholder structure and create the new subs.
Tsubtitle *second=at(0)->create();
second->start = local_start;
second->stop = local_end;
for (int i = 0, j = 0; j < lines_to_add ; ++j)
if (placeholder[counter][j] != -1)
{
at(placeholder[counter][j])->copyProps(second);
int lines = at(placeholder[counter][j])->numlines();
for (int ls = 0; ls < lines; ++ls)
//second[sub_num].text[i++] = strdup(first[placeholder[counter][j]].text[ls]);
//second->push_back((*(TsubtitleTextBase<char>*)at(placeholder[counter][j]))[ls]);
at(placeholder[counter][j])->copyLine(second,ls);
j+=lines-1;
}
else
second->addEmpty();
newsubs.push_back(second);
++sub_num;
++counter;
} while (local_end < global_end);
counter = 2 * sub_to_add + 1;
for (int i = 0; i < counter; ++i)
free(placeholder[i]);
free(placeholder);
sub_first += sub_to_add;
}
clear();
for (std::vector<Tsubtitle*>::const_iterator s=newsubs.begin();s!=newsubs.end();s++)
push_back(*s);
IsProcessOverlapDone=true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -