2
// C++ Implementation:Spudecoder (subs for DVd like stream)
7
// Author: Mean, fixounet@free.fr
9
// Copyright: See COPYING file that comes with this distribution
11
// see http://sam.zoy.org/writings/dvd/subtitles/
14
/***************************************************************************
16
* This program is free software; you can redistribute it and/or modify *
17
* it under the terms of the GNU General Public License as published by *
18
* the Free Software Foundation; either version 2 of the License, or *
19
* (at your option) any later version. *
21
***************************************************************************/
27
#include <ADM_assert.h>
37
#include "ADM_toolkit/toolkit.hxx"
38
#include "ADM_editor/ADM_edit.hxx"
39
#include "ADM_video/ADM_genvideo.hxx"
40
#include "ADM_video/ADM_vidFlipV.h"
41
#include "ADM_filter/video_filters.h"
44
#include "ADM_toolkit/filesel.h"
46
#include "ADM_colorspace/colorspace.h"
48
#include "ADM_vobsubinfo.h"
50
#define VOBSUB "/capture/sub/phone.sub"
52
#include "ADM_vidVobSub.h"
54
#include "ADM_toolkit/ADM_debugID.h"
55
#define MODULE_NAME MODULE_FILTER
56
#include "ADM_toolkit/ADM_debug.h"
59
extern uint8_t DIA_vobsub(vobSubParam *param);
61
static FILTER_PARAM vobsubParam={3,{"subname","index","subShift"}};
62
//*************************************************************
65
//*************************************************************
66
SCRIPT_CREATE(vobsub_script,ADMVideoVobSub,vobsubParam);
67
BUILD_CREATE(vobsub_create,ADMVideoVobSub);
68
//*************************************************************
69
uint8_t ADMVideoVobSub::configure(AVDMGenericVideoStream *in)
73
if(DIA_vobsub(_param))
83
//*************************************************************
84
char *ADMVideoVobSub::printConf( void )
88
sprintf((char *)buf," VobSub");
91
//*************************************************************
92
ADMVideoVobSub::ADMVideoVobSub( AVDMGenericVideoStream *in,CONFcouple *couples)
96
memcpy(&_info,_in->getInfo(),sizeof(_info));
100
_chromaResampled=NULL;
103
_param=NEW(vobSubParam);
114
_param->subname=ADM_strdup(VOBSUB);
116
_param->subname =NULL;
125
Alternate constructor for use by OCR
127
ADMVideoVobSub::ADMVideoVobSub( char *fileidx,uint32_t idx)
131
memset(&_info,0,sizeof(_info));
135
_chromaResampled=NULL;
138
_param=NEW(vobSubParam);
141
_param->subname=ADM_strdup(fileidx);
148
Returns bitmap & info for the Nth subs
151
vobSubBitmap *ADMVideoVobSub::getBitmap(uint32_t nb,uint32_t *start, uint32_t *end,uint32_t *first,uint32_t *last)
153
uint32_t top=0,bottom=0;
154
ADM_assert(_vobSubInfo);
155
ADM_assert(nb<_vobSubInfo->nbLines);
158
//_parser->_asyncJump2(0,_vobSubInfo->lines[nb].fileOffset);
159
_parser->setPos(_vobSubInfo->lines[nb].fileOffset,0);
162
printf("Error reading getBimap\n");
164
return _original; // might be null (?)
170
_original->buildYUV(_YUVPalette);
171
ox=_original->_width;
172
oy=_original->_height;
173
printf("Original :%lu x %lu (original %d)\n",ox,oy,_vobSubInfo->height);
174
ADM_assert(oy<=_vobSubInfo->height);
176
// Search the 1st/last non null line
182
if(oy>_original->_height) oy=_original->_height-1;
184
while(top<oy && !_original->isDirty(top) ) top++;
188
top=bottom=0; // Empty bitmap ?
191
printf("Empry bitmap\n");
195
while(bottom>top && !_original->isDirty(bottom)) bottom--;
197
// If true it means we have 2 subs, one on top, one on bottom
200
if(bottom>(oy>>1) && top<(oy>>1) && (bottom-top>(oy>>1)))
202
// in that case, take only the lower one
204
while(top<oy && !_original->isDirty(top)) top++;
206
printf("> clipped: %lu / %lu=%lu\n",top,bottom,bottom-top+1);
212
*start=_vobSubInfo->lines[nb].startTime;
213
*end=_vobSubInfo->lines[nb].stopTime;
217
Returns the nb of lines found in the sub
219
uint32_t ADMVideoVobSub::getNbImage( void)
221
if(!_parser) return 0;
222
if(!_param) return 0;
223
if(!_vobSubInfo) return 0;
224
return _vobSubInfo->nbLines;
227
//************************************
228
uint8_t ADMVideoVobSub::setup(void)
234
if(_param->subname && strlen(_param->subname)>5)
236
printf("Opening %s\n",_param->subname);
237
dup=ADM_strdup(_param->subname);
247
if(vobSubRead(_param->subname,_param->index,&_vobSubInfo))
249
printf("Opening index \n");
252
memset(&track,0,sizeof(track));
253
track.pes=_param->index+0x20;
255
// _parser=new ADM_mpegDemuxerProgramStream(_param->index+0x20,0xe0);
256
_parser=new dmx_demuxerPS(1,&track,0);
257
if(!_parser->open(dup))
259
printf("Mpeg Parser : opening %s failed\n",_param->subname);
272
printf("opening of vobsub file failed\n");
275
{ // Recompute sub duration
277
vobSubLine *cur,*next;
278
// Assuming max displat time = MAX_DISPLAY_TIME
279
for(uint32_t i=0;i<_vobSubInfo->nbLines-1;i++)
281
if(i && !_vobSubInfo->lines[i].startTime)
283
_vobSubInfo->lines[i].startTime=0xf0000000;
284
_vobSubInfo->lines[i].stopTime=0xf0000001;
289
cur=&_vobSubInfo->lines[i];
290
next=&_vobSubInfo->lines[i+1];
292
end=cur->startTime+MAX_DISPLAY_TIME;
293
if(end>=next->startTime) end=next->startTime-1;
297
_vobSubInfo->lines[_vobSubInfo->nbLines-1].stopTime=
298
MAX_DISPLAY_TIME+_vobSubInfo->lines[_vobSubInfo->nbLines-1].startTime;
299
// Convert all the palette from RGB to YUV
304
_data=new uint8_t [VS_MAXPACKET];
308
memset(&_original,0,sizeof(_original));
314
//*************************************************************
315
uint8_t ADMVideoVobSub::cleanup(void)
318
if(_parser) delete _parser;
330
delete _chromaResampled;
331
_chromaResampled=NULL;
334
if(_data) delete [] _data;
337
if(_vobSubInfo) destroySubInfo( _vobSubInfo);
342
//*************************************************************
343
ADMVideoVobSub::~ADMVideoVobSub()
348
if(_param->subname) ADM_dealloc(_param->subname);
354
//*************************************************************
355
uint8_t ADMVideoVobSub::getCoupledConf( CONFcouple **couples)
358
*couples=new CONFcouple(3);
360
#define CSET(x) (*couples)->setCouple((char *)#x,(_param->x))
364
(*couples)->setCouple("subname","none") ;
371
//*************************************************************
372
uint8_t ADMVideoVobSub::getFrameNumberNoAlloc(uint32_t frame,
381
ADM_assert(frame<_info.nb_frames);
382
// read uncompressed frame
383
if(!_in->getFrameNumberNoAlloc(frame, len,data,flags)) return 0;
388
printf("No valid vobsub to process\n");
394
time=(frame+_info.orgFrame);
395
time=(time*1000*1000)/_info.fps1000;
398
// Should we re-use the current one ?
401
aprintf("No matching sub for time %llu frame%lu\n",time,frame);
404
// If it is a new sub, decode it...
405
if(sub!=_currentSub )
407
// _parser->_asyncJump2(0,_vobSubInfo->lines[sub].fileOffset);
408
_parser->setPos(_vobSubInfo->lines[sub].fileOffset,0);
409
//_initialPts=_parser->getPTS();
412
Palettte2Display(); // Create the bitmap
413
// Time to resize the bitmap
414
// First try : Do it bluntly
418
// and if there is something to display, display it
427
aprintf("We have %lu %lu to merge\n",src->_width,src->_height);
430
uint32_t stridein,strideout,len;
431
uint8_t *in,*out,*mask,*in2;
435
stridein=src->_width;
436
strideout=_info.width;
438
if(strideout>stridein)
448
if(src->_height>_info.height) yy=_info.height;
449
else yy=src->_height;
451
mask=src->_alphaMask;
453
out=data->data+_info.width*src->placeTop;
455
uint32_t center=_info.width-src->_width;
458
for(uint32_t y=0;y<yy;y++)
460
for(uint32_t x=0;x<xx;x++)
468
if(alp>7) nw=old*(16-alp-1)+(alp+1)*nw;
469
else nw=old*(16-alp)+(alp)*nw;
475
//memcpy(out,in,len);
481
// Now do chroma u & chroma V
483
#if defined(DOCHROMA)
484
uint32_t crosspage=(_info.width*_info.height)>>2;
486
strideout=_info.width>>1;
487
stridein=_chromaResampled->_width;
489
out=data->data+_info.width*_info.height;
490
out+=(src->placeTop>>1)*(_info.width>>1);
491
mask=_chromaResampled->_alphaMask;
494
if(strideout>stridein) xx=stridein;
497
int16_t left=(_info.height>>1)-(_chromaResampled->_height+(_original->placeTop>>1));
499
if(left<_chromaResampled->_height) yy=left;
500
else yy=_chromaResampled->_height;
502
for(uint32_t y=0;y<yy;y++)
504
for(uint32_t x=0;x<xx;x++)
520
out[crosspage+x]=val;
530
//*************************************************************************
532
// Convert the original bitmap to a rescaled & repositionned one
533
// that will be blended into the current picutr
535
//*************************************************************************
536
uint8_t ADMVideoVobSub::Palettte2Display( void )
539
ADM_assert(_vobSubInfo);
541
// Then Process the RLE Datas
542
// To get the _bitmap yuv data
543
ADM_assert(_original);
546
_original->buildYUV(_YUVPalette);
548
// rebuild the scaled one
549
// Compute the target size
554
Fx, fy : Final size of the image (i.e size of the current picture)
555
ox,oy : Original size of the image where the sub is coming from
556
sx,sy : Size of the sub
558
And we want the final size of the sub
559
+ coordinates but that we will do later
566
ox=_vobSubInfo->width;
567
oy=_vobSubInfo->height;
572
// Search the 1st/last non null line
573
uint32_t top=0,bottom=0;
575
if(oy>_original->_height) oy=_original->_height-1;
577
while(top<oy && !_original->isDirty(top)) top++;
579
bottom=_original->_height-1;
582
printf("Empty sub ?");
586
while(bottom && !_original->isDirty(bottom)) bottom--;
588
// If true it means we have 2 subs, one on top, one on bottom
590
if(bottom>(oy>>1) && top<(oy>>1) && (bottom-top>(oy>>1)))
592
// in that case, take only the lower one
594
while(top<oy && !_original->isDirty(top)) top++;
597
// The useful part is between top & bottom lines
601
// The shrink factor is the one used to shrink from the original video
602
// to the resize video
607
printf("top %lu : bottom :%lu Scale :%f ox:%lu oy:%lu fx:%lu \n",top,bottom,scale,ox,oy,fx);
609
// We rescale the sub by the same factor
610
// Only the visible / useful part
613
sx=(uint32_t )floor(l);
618
sy=(uint32_t )floor(l);
621
// And we resize that useful part of sub
622
// to our final bitmap (resampled)
624
_original->subResize(&_resampled,sx,sy,top, bottom-top);
628
// Set the position of the sub so that it is ok
638
_resampled->placeTop=tail;
640
_resampled->subResize(&_chromaResampled,sx>>1,sy>>1,0,sy);
645
// Return the index in the sub table of the sub matching the time
647
uint32_t ADMVideoVobSub::lookupSub(uint64_t time)
649
int64_t head,tail, cur;
653
while(i<_vobSubInfo->nbLines-1)
655
head=(int64_t)_vobSubInfo->lines[i].startTime;
656
tail=(int64_t) _vobSubInfo->lines[i].stopTime;
657
head+=_param->subShift;
658
tail+=_param->subShift;
659
if(head<=cur &&tail>cur)
661
aprintf("Matching for time %llu : sub %lu starting at :%lu (shift %lu)\n",
662
time,i,_vobSubInfo->lines[i].startTime,_param->subShift);
665
if(head>cur) return NOSUB;