~ubuntu-branches/ubuntu/feisty/avidemux/feisty

« back to all changes in this revision

Viewing changes to avidemux/ADM_video/ADM_vidVobsub.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2005-05-25 13:02:29 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050525130229-jw94cav0yhmg7vjw
Tags: 1:2.0.40-0.0
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// C++ Implementation:Spudecoder (subs for DVd like stream)
 
3
//
 
4
// Description:
 
5
//
 
6
//
 
7
// Author: Mean, fixounet@free.fr
 
8
//
 
9
// Copyright: See COPYING file that comes with this distribution
 
10
//
 
11
// see http://sam.zoy.org/writings/dvd/subtitles/
 
12
 
 
13
 
 
14
/***************************************************************************
 
15
 *                                                                         *
 
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.                                   *
 
20
 *                                                                         *
 
21
 ***************************************************************************/
 
22
 
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <math.h>
 
27
#include <ADM_assert.h>
 
28
 
 
29
#include "config.h"
 
30
#include "fourcc.h"
 
31
#include "avio.hxx"
 
32
#include "config.h"
 
33
#include "avi_vars.h"
 
34
 
 
35
 
 
36
 
 
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"
 
42
 
 
43
#include "ADM_mpeg2dec/ADM_mpegpacket.h"
 
44
#include "ADM_mpeg2dec/ADM_mpegpacket_PS.h"
 
45
 
 
46
#include "ADM_toolkit/filesel.h"
 
47
 
 
48
#include "ADM_colorspace/colorspace.h"
 
49
 
 
50
#include "ADM_vobsubinfo.h"
 
51
 
 
52
#define VOBSUB "/capture/sub/phone.sub"
 
53
 
 
54
#include "ADM_vidVobSub.h"
 
55
 
 
56
#include "ADM_toolkit/ADM_debugID.h"
 
57
#define MODULE_NAME MODULE_FILTER
 
58
#include "ADM_toolkit/ADM_debug.h"
 
59
 
 
60
 
 
61
extern uint8_t DIA_vobsub(vobSubParam *param);
 
62
 
 
63
static FILTER_PARAM vobsubParam={1,{"subname"}};
 
64
//*************************************************************
 
65
//
 
66
 
 
67
//*************************************************************
 
68
SCRIPT_CREATE(vobsub_script,ADMVideoVobSub,vobsubParam);
 
69
BUILD_CREATE(vobsub_create,ADMVideoVobSub);
 
70
//*************************************************************
 
71
uint8_t ADMVideoVobSub::configure(AVDMGenericVideoStream *in)
 
72
{
 
73
 
 
74
       
 
75
  if(DIA_vobsub(_param))
 
76
       {
 
77
                cleanup();
 
78
                setup();
 
79
                return 1;
 
80
       }
 
81
        
 
82
        return 0;        
 
83
}
 
84
 
 
85
//*************************************************************
 
86
char *ADMVideoVobSub::printConf( void )
 
87
{
 
88
        static char buf[50];
 
89
        
 
90
        sprintf((char *)buf," VobSub");
 
91
        return buf;
 
92
}
 
93
//*************************************************************
 
94
ADMVideoVobSub::ADMVideoVobSub(  AVDMGenericVideoStream *in,CONFcouple *couples)
 
95
{
 
96
 
 
97
        _in=in;         
 
98
        memcpy(&_info,_in->getInfo(),sizeof(_info));    
 
99
        _info.encoding=1;       
 
100
        _parser=NULL;  
 
101
        _resampled=NULL;
 
102
        _chromaResampled=NULL;
 
103
        _original=NULL;        
 
104
        
 
105
        _param=NEW(vobSubParam);
 
106
        
 
107
        if(couples)
 
108
        {                 
 
109
                GET(subname);
 
110
                GET(index);                               
 
111
                GET(subShift);  
 
112
        }
 
113
        else
 
114
        {
 
115
#ifdef KK_ADM_DEBUG
 
116
                _param->subname=ADM_strdup(VOBSUB);
 
117
#else                
 
118
                _param->subname =NULL;
 
119
#endif                
 
120
                _param->index = 0;   
 
121
                _param->subShift=0;             
 
122
        }
 
123
        
 
124
        setup();
 
125
}
 
126
/*
 
127
    Alternate constructor for use by OCR
 
128
*/
 
129
ADMVideoVobSub::ADMVideoVobSub(  char *fileidx,uint32_t idx)
 
130
{
 
131
 
 
132
        _in=NULL;         
 
133
        memset(&_info,0,sizeof(_info));    
 
134
        _info.encoding=1;       
 
135
        _parser=NULL;  
 
136
        _resampled=NULL;
 
137
        _chromaResampled=NULL;
 
138
        _original=NULL;        
 
139
        
 
140
        _param=NEW(vobSubParam);
 
141
        
 
142
        
 
143
        _param->subname=ADM_strdup(fileidx);
 
144
        _param->index = idx;   
 
145
        _param->subShift=0;                    
 
146
        
 
147
        setup();
 
148
}
 
149
/*
 
150
    Returns bitmap & info for the Nth subs
 
151
*/
 
152
 
 
153
vobSubBitmap *ADMVideoVobSub::getBitmap(uint32_t nb,uint32_t *start, uint32_t *end,uint32_t *first,uint32_t *last)
 
154
{
 
155
uint32_t top=0,bottom=0;
 
156
    ADM_assert(_vobSubInfo);
 
157
    ADM_assert(nb<_vobSubInfo->nbLines);
 
158
    
 
159
    // Seek & decode
 
160
    _parser->_asyncJump2(0,_vobSubInfo->lines[nb].fileOffset);
 
161
    if(!handleSub(nb))
 
162
        {
 
163
                printf("Error reading getBimap\n");
 
164
                *first=*last=0;
 
165
                return _original; // might be null (?)
 
166
        }
 
167
    *first=*last=0;
 
168
    if(_original)
 
169
    {
 
170
    uint32_t ox,oy;
 
171
        _original->buildYUV(_YUVPalette);
 
172
        ox=_original->_width;        
 
173
        oy=_original->_height;
 
174
        printf("Original :%lu x %lu\n",ox,oy);
 
175
        ADM_assert(oy<=_vobSubInfo->height);
 
176
        
 
177
        // Search the 1st/last non null line
 
178
//#define DONTCLIP
 
179
#ifdef DONTCLIP     
 
180
         *first=0;
 
181
         *last=oy-1;   
 
182
#else
 
183
        while(top<oy && !_original->isDirty(top)) top++;
 
184
        
 
185
        if(top==oy)
 
186
        {
 
187
                top=bottom=0;   // Empty bitmap ?
 
188
                *first=top;
 
189
                *last=bottom;
 
190
                return NULL; 
 
191
        }
 
192
        bottom=oy-1;
 
193
        while(bottom>top && !_original->isDirty(bottom)) bottom--;
 
194
        
 
195
        // If true it means we have 2 subs, one on top, one on bottom
 
196
        //
 
197
#if 0
 
198
        if(bottom>(oy>>1) && top<(oy>>1) && (bottom-top>(oy>>1)))
 
199
        {
 
200
          // in that case, take only the lower one
 
201
          top=oy>>1;
 
202
          while(top<oy && !_original->isDirty(top)) top++;                    
 
203
        }
 
204
        printf("> clipped: %lu / %lu=%lu\n",top,bottom,bottom-top+1);
 
205
#endif
 
206
        *first=top;
 
207
        *last=bottom;
 
208
#endif
 
209
    }
 
210
    *start=_vobSubInfo->lines[nb].startTime;
 
211
    *end=_vobSubInfo->lines[nb].stopTime;
 
212
    return _original;
 
213
}
 
214
/*
 
215
    Returns the nb of lines found in the sub
 
216
*/
 
217
uint32_t     ADMVideoVobSub::getNbImage( void)
 
218
{
 
219
    if(!_parser) return 0;
 
220
    if(!_param) return 0;
 
221
    if(!_vobSubInfo) return 0;
 
222
    return _vobSubInfo->nbLines;
 
223
 
 
224
}
 
225
//************************************
 
226
uint8_t ADMVideoVobSub::setup(void)
 
227
{
 
228
  char *dup;
 
229
  int l;
 
230
  
 
231
   _vobSubInfo=NULL;
 
232
   if(_param->subname && strlen(_param->subname)>5)
 
233
        {
 
234
                printf("Opening %s\n",_param->subname);
 
235
                dup=ADM_strdup(_param->subname);
 
236
                l=strlen(dup);
 
237
                if(l>5)
 
238
                  if(dup[l-4]=='.')
 
239
                {
 
240
                  dup[l-3]='s';
 
241
                  dup[l-2]='u';
 
242
                  dup[l-1]='b';
 
243
                          
 
244
                }
 
245
                if(vobSubRead(_param->subname,_param->index,&_vobSubInfo))
 
246
                {
 
247
                        printf("Opening index \n");
 
248
                       
 
249
                        
 
250
                        _parser=new ADM_mpegDemuxerProgramStream(_param->index+0x20,0xe0);
 
251
                        
 
252
                        if(!_parser->open(dup))
 
253
                        {
 
254
                                printf("Mpeg Parser : opening %s failed\n",_param->subname);
 
255
                                delete _parser;
 
256
                                _parser=NULL;
 
257
                
 
258
                         }
 
259
                         
 
260
                }
 
261
                ADM_dealloc(dup);
 
262
        }
 
263
        
 
264
        
 
265
        if(!_parser)
 
266
        {
 
267
                printf("opening of vobsub file failed\n");
 
268
        }
 
269
         else
 
270
        {       // Recompute sub duration
 
271
                uint32_t end;
 
272
                vobSubLine *cur,*next;
 
273
                // Assuming max displat time = MAX_DISPLAY_TIME
 
274
                for(uint32_t i=0;i<_vobSubInfo->nbLines-1;i++)
 
275
                {
 
276
                        if(i && !_vobSubInfo->lines[i].startTime)
 
277
                        {
 
278
                                _vobSubInfo->lines[i].startTime=0xf0000000;
 
279
                                _vobSubInfo->lines[i].stopTime=0xf0000001;
 
280
                                
 
281
                        }
 
282
                        else
 
283
                        {
 
284
                                cur=&_vobSubInfo->lines[i];
 
285
                                next=&_vobSubInfo->lines[i+1];
 
286
                        
 
287
                                end=cur->startTime+MAX_DISPLAY_TIME;
 
288
                                if(end>=next->startTime) end=next->startTime-1;
 
289
                                cur->stopTime=end;                                
 
290
                        }
 
291
                }
 
292
                _vobSubInfo->lines[_vobSubInfo->nbLines-1].stopTime=
 
293
                        MAX_DISPLAY_TIME+_vobSubInfo->lines[_vobSubInfo->nbLines-1].startTime;
 
294
                // Convert all the palette from RGB to YUV
 
295
                paletteYUV();
 
296
        }
 
297
      
 
298
        _x1=_y1=_x2=_y2=0;
 
299
        _data=new uint8_t [VS_MAXPACKET];
 
300
        _subSize=0;
 
301
        _subW=_subH=0;
 
302
        
 
303
        memset(&_original,0,sizeof(_original));
 
304
        _currentSub=NOSUB;
 
305
        _initialPts=0;
 
306
                
 
307
 
 
308
}
 
309
//*************************************************************
 
310
uint8_t ADMVideoVobSub::cleanup(void)
 
311
{
 
312
 
 
313
        if(_parser) delete _parser;
 
314
        _parser=NULL;
 
315
        
 
316
        if(_original)
 
317
          delete _original;
 
318
        _original=NULL;        
 
319
        
 
320
        if(_resampled)
 
321
          delete _resampled;
 
322
        _resampled=NULL;
 
323
        
 
324
        if(_chromaResampled)
 
325
          delete _chromaResampled;
 
326
        _chromaResampled=NULL;
 
327
        
 
328
        
 
329
        if(_data) delete [] _data;
 
330
        _data=NULL;
 
331
        
 
332
        if(_vobSubInfo) destroySubInfo( _vobSubInfo);
 
333
        _vobSubInfo=NULL;
 
334
        
 
335
 
 
336
}
 
337
//*************************************************************
 
338
ADMVideoVobSub::~ADMVideoVobSub()
 
339
{
 
340
        cleanup();
 
341
         if(_param)
 
342
        {
 
343
                if(_param->subname)  ADM_dealloc(_param->subname);
 
344
                DELETE(_param);
 
345
        }
 
346
        _param=NULL;
 
347
}
 
348
 
 
349
//*************************************************************
 
350
uint8_t ADMVideoVobSub::getCoupledConf( CONFcouple **couples)
 
351
{
 
352
                        ADM_assert(_param);
 
353
                        *couples=new CONFcouple(3);
 
354
 
 
355
#define CSET(x)  (*couples)->setCouple((char *)#x,(_param->x))
 
356
                        if(_param->subname)
 
357
                                CSET(subname);
 
358
                        else
 
359
                          (*couples)->setCouple("subname","none") ;
 
360
                        CSET(index);
 
361
                        CSET(subShift);
 
362
                        
 
363
 
 
364
                        return 1;
 
365
}
 
366
//*************************************************************
 
367
uint8_t ADMVideoVobSub::getFrameNumberNoAlloc(uint32_t frame,
 
368
                                uint32_t *len,
 
369
                                ADMImage *data,
 
370
                                uint32_t *flags)
 
371
{
 
372
 
 
373
uint64_t time;
 
374
uint32_t sub;
 
375
 
 
376
        ADM_assert(frame<_info.nb_frames);
 
377
        // read uncompressed frame
 
378
        if(!_in->getFrameNumberNoAlloc(frame, len,data,flags)) return 0;
 
379
 
 
380
        if(!_parser)        
 
381
        {
 
382
                //
 
383
                printf("No valid vobsub to process\n");
 
384
                
 
385
                return 1;
 
386
        
 
387
        }
 
388
        
 
389
        time=(frame+_info.orgFrame);
 
390
        time=(time*1000*1000)/_info.fps1000;
 
391
        
 
392
        sub=lookupSub(time);  
 
393
        // Should we re-use the current one ? 
 
394
        if(sub==NOSUB)
 
395
        {
 
396
                aprintf("No matching sub for time %llu frame%lu\n",time,frame);
 
397
                return 1;
 
398
        }
 
399
        // If it is a new sub, decode it...
 
400
        if(sub!=_currentSub )
 
401
        {                
 
402
                 _parser->_asyncJump2(0,_vobSubInfo->lines[sub].fileOffset);
 
403
                 _initialPts=_parser->getPTS();
 
404
                 handleSub(sub);
 
405
                _currentSub=sub;
 
406
                Palettte2Display(); // Create the bitmap
 
407
                // Time to resize the bitmap
 
408
                // First try : Do it bluntly
 
409
                
 
410
        }                
 
411
        
 
412
        // and if there is something to display, display it
 
413
        //
 
414
        vobSubBitmap *src;
 
415
        //src=_original;
 
416
        src=_resampled;
 
417
        
 
418
        if(src)          
 
419
        {
 
420
               
 
421
          aprintf("We have %lu %lu to merge\n",src->_width,src->_height);
 
422
                // Merge
 
423
                
 
424
                uint32_t stridein,strideout,len;
 
425
                uint8_t *in,*out,*mask,*in2;
 
426
                uint16_t old,nw,alp;
 
427
                uint32_t xx,yy;
 
428
                
 
429
                stridein=src->_width;
 
430
                strideout=_info.width;
 
431
                
 
432
                if(strideout>stridein)
 
433
                {
 
434
                        len=stridein;
 
435
                        xx=src->_width;
 
436
                }
 
437
                else
 
438
                {
 
439
                        xx=_info.width;
 
440
                        len=strideout;
 
441
                }
 
442
                if(src->_height>_info.height) yy=_info.height;
 
443
                        else                 yy=src->_height;           
 
444
                in=src->_bitmap;
 
445
                mask=src->_alphaMask;
 
446
               
 
447
                out=data->data+_info.width*src->placeTop;
 
448
                // auto center
 
449
                uint32_t center=_info.width-src->_width;
 
450
                out+=(center>>2)*2;
 
451
                
 
452
                for(uint32_t y=0;y<yy;y++)
 
453
                {
 
454
                  for(uint32_t x=0;x<xx;x++)
 
455
                        {
 
456
                               old=out[x];
 
457
                               nw=in[x];
 
458
                               alp=mask[x];
 
459
 
 
460
                                if(alp) 
 
461
                                {
 
462
                                  if(alp>7)  nw=old*(16-alp-1)+(alp+1)*nw;
 
463
                                        else nw=old*(16-alp)+(alp)*nw;
 
464
                                  out[x]=nw>>4;                                         
 
465
                                }
 
466
 
 
467
                               //out[x]=nw;
 
468
                        }
 
469
                        //memcpy(out,in,len);
 
470
                        out+=strideout;
 
471
                        in+=stridein;
 
472
                        mask+=stridein;
 
473
                }
 
474
                
 
475
                // Now do chroma u & chroma V
 
476
#define DOCHROMA                
 
477
#if defined(DOCHROMA)                
 
478
                uint32_t crosspage=(_info.width*_info.height)>>2;
 
479
                
 
480
                strideout=_info.width>>1;
 
481
                stridein=_chromaResampled->_width;
 
482
                
 
483
                out=data->data+_info.width*_info.height;
 
484
                out+=(src->placeTop>>1)*(_info.width>>1);
 
485
                mask=_chromaResampled->_alphaMask;
 
486
                // Center
 
487
                out+=(center>>2)*1;
 
488
                if(strideout>stridein) xx=stridein;
 
489
                else            xx=strideout;
 
490
                
 
491
                int16_t left=(_info.height>>1)-(_chromaResampled->_height+(_original->placeTop>>1));
 
492
                
 
493
                if(left<_chromaResampled->_height) yy=left;
 
494
                else yy=_chromaResampled->_height;
 
495
                
 
496
                for(uint32_t y=0;y<yy;y++)
 
497
                {
 
498
                   for(uint32_t x=0;x<xx;x++)
 
499
                   {
 
500
                        if(mask[x]>10)         
 
501
                        {
 
502
                          int16_t val;
 
503
                          val=out[x];
 
504
                          val-=128;
 
505
                         
 
506
                          
 
507
                          
 
508
                          nw=val*(16-alp);
 
509
                          
 
510
                          val/=4;
 
511
                          val=val+128;
 
512
                                
 
513
                          out[x]=val; 
 
514
                          out[crosspage+x]=val;
 
515
                        }                                                 
 
516
                   }
 
517
                   out+=strideout;
 
518
                   mask+=stridein;
 
519
                }
 
520
#endif                
 
521
        }
 
522
        return 1;
 
523
}
 
524
//*************************************************************************
 
525
//
 
526
//      Convert the original bitmap to a rescaled & repositionned one
 
527
//      that will be blended into the current picutr
 
528
//
 
529
//*************************************************************************
 
530
uint8_t ADMVideoVobSub::Palettte2Display( void )
 
531
{
 
532
        ADM_assert(_parser);
 
533
        ADM_assert(_vobSubInfo);
 
534
     
 
535
        // Then Process the RLE Datas
 
536
        // To get the _bitmap yuv data
 
537
        ADM_assert(_original);
 
538
        
 
539
        // Set correct color
 
540
        _original->buildYUV(_YUVPalette);
 
541
        
 
542
        // rebuild the scaled one
 
543
        // Compute the target size
 
544
        uint32_t fx,fy;
 
545
        uint32_t ox,oy;
 
546
        uint32_t sx,sy;
 
547
        /*
 
548
                Fx, fy : Final size of the image (i.e size of the current picture)
 
549
                ox,oy  : Original size of the image where the sub is coming from
 
550
                sx,sy  : Size of the  sub
 
551
        
 
552
                And we want the final size of the sub
 
553
                        + coordinates but that we will do later
 
554
        
 
555
        */
 
556
        
 
557
        fx=_info.width;
 
558
        fy=_info.height;
 
559
        
 
560
        ox=_vobSubInfo->width;
 
561
        oy=_vobSubInfo->height;
 
562
        
 
563
        sx=_subW;
 
564
        sy=_subH;
 
565
        
 
566
        // Search the 1st/last non null line
 
567
        uint32_t top=0,bottom=0;
 
568
        while(top<oy && !_original->isDirty(top)) top++;
 
569
        
 
570
        bottom=_original->_height-1;
 
571
        while(bottom && !_original->isDirty(bottom)) bottom--;
 
572
        
 
573
        // If true it means we have 2 subs, one on top, one on bottom
 
574
        //
 
575
        if(bottom>(oy>>1) && top<(oy>>1) && (bottom-top>(oy>>1)))
 
576
        {
 
577
          // in that case, take only the lower one
 
578
          top=oy>>1;
 
579
          while(top<oy && !_original->isDirty(top)) top++;                    
 
580
        }
 
581
        //
 
582
        //  The useful part is between top & bottom lines
 
583
        //
 
584
        
 
585
        // Shrink factor
 
586
        // The shrink factor is the one used to shrink from the original video
 
587
        // to the resize video
 
588
        
 
589
        double scale,l;
 
590
        scale=fx;
 
591
        scale/=ox;
 
592
        printf("top %lu : bottom :%lu Scale :%f ox:%lu oy:%lu fx:%lu \n",top,bottom,scale,ox,oy,fx);
 
593
        
 
594
        // We rescale the sub by the same factor
 
595
        // Only the visible / useful part
 
596
        l=scale;
 
597
        l=l*sx;
 
598
        sx=(uint32_t )floor(l);
 
599
        
 
600
       
 
601
        l=scale;
 
602
        l=l*(bottom-top);
 
603
        sy=(uint32_t )floor(l);
 
604
        
 
605
 
 
606
        // And we resize that useful part of sub
 
607
        // to our final bitmap (resampled)
 
608
                
 
609
        _original->subResize(&_resampled,sx,sy,top, bottom-top);
 
610
                
 
611
        uint32_t tail;
 
612
        
 
613
        // Set the position of the sub so that it is ok
 
614
        
 
615
        tail=16+sy;
 
616
        
 
617
        if(tail>fy) tail=0;
 
618
        else
 
619
        {
 
620
            tail=fy-tail;           
 
621
        }
 
622
        
 
623
        _resampled->placeTop=tail;
 
624
        
 
625
        _resampled->subResize(&_chromaResampled,sx>>1,sy>>1,0,sy);
 
626
        return 1;
 
627
}
 
628
 
 
629
//
 
630
//      Return the index in the sub table of the sub matching the time
 
631
//
 
632
uint32_t ADMVideoVobSub::lookupSub(uint64_t time)
 
633
{
 
634
int64_t head,tail, cur;
 
635
int32_t i;
 
636
        cur=(int64_t)time;
 
637
        i=0;
 
638
        while(i<_vobSubInfo->nbLines-1)
 
639
        {
 
640
                head=(int64_t)_vobSubInfo->lines[i].startTime;
 
641
                tail=(int64_t) _vobSubInfo->lines[i].stopTime;
 
642
                head+=_param->subShift;
 
643
                tail+=_param->subShift;
 
644
                if(head<=cur &&tail>cur)
 
645
                {
 
646
                  aprintf("Matching for time %llu : sub %lu starting at :%lu (shift %lu)\n",
 
647
                                        time,i,_vobSubInfo->lines[i].startTime,_param->subShift);
 
648
                        return i; 
 
649
                }   
 
650
                if(head>cur) return NOSUB;                   
 
651
                i++;       
 
652
        }
 
653
        return NOSUB;
 
654
 
 
655
 
 
656
}
 
657
//EOF
 
658