/[tivodecode]/t2sami/trunk/PS.cpp
ViewVC logotype

Contents of /t2sami/trunk/PS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 255 - (show annotations) (download)
Mon Apr 25 03:37:29 2011 UTC (11 years, 3 months ago) by jeremyd2019
File size: 6392 byte(s)
fix a crash during caption extraction.  Added some asserts to help track down that crash.
1 // PS.cpp : implementation file
2 //
3 //********************************************************************
4 //
5
6 #ifdef HAVE_CONFIG_H
7 # include "config.h"
8 #endif
9
10 #include <fcntl.h>
11 #include <errno.h>
12
13 #ifdef HAVE_STRING_H
14 # include <string.h>
15 #endif
16
17 #ifdef WIN32
18 # include <winsock2.h>
19 #endif
20 #ifdef HAVE_NETINET_IN_H
21 # include <netinet/in.h>
22 #endif
23
24 #include "TScan.h"
25 #include "Utility.h"
26
27 #ifndef O_BINARY
28 # define O_BINARY 0
29 #endif
30
31 #if defined(HAVE_STRCASECMP)
32 # define ICASE_STR_COMPARE(a, b) strcasecmp(a, b)
33 #elif defined(HAVE__STRICMP)
34 # define ICASE_STR_COMPARE(a, b) _stricmp(a, b)
35 #elif defined(HAVE_STRICMP)
36 # define ICASE_STR_COMPARE(a, b) stricmp(a, b)
37 #else
38 # error No known case-insensitive string compare function for this platform
39 #endif
40
41 CPs::CPs()
42 {
43
44 m_nFile = NULL;
45 buf = NULL;
46 buf_len = 0;
47 pos = 0;
48 m_dwFileLength = 0;
49 m_dwBufferBase = 0;
50 m_pParent = NULL;
51
52 }
53
54 CPs::~CPs()
55 {
56
57 CleanUp();
58
59 }
60
61 bool CPs::CleanUp(void)
62 {
63
64 if( m_nFile != NULL ) {
65 hclose( m_nFile );
66 m_nFile = NULL;
67 }
68
69 if( buf != NULL ) {
70 free( buf );
71 buf = NULL;
72 }
73
74 return true;
75
76 }
77
78 bool CPs::Initialize( std::string szInputFile )
79 {
80
81 CleanUp();
82
83 if( buf == NULL )
84 buf = (byte *)malloc(PS_BUFFER_LENGTH);
85
86 memset( buf, 0, PS_BUFFER_LENGTH);
87
88 buf_len=0;
89 pos=0;
90
91 if(szInputFile == "-")
92 m_nFile = hattach(stdin);
93 else
94 m_nFile = hopen( szInputFile.c_str(), "rb");
95 if( m_nFile == NULL ) {
96 TRACE("File could not be opened %0x\n", errno );
97 return false;
98 } else {
99 if (szInputFile != "-")
100 {
101 hseek(m_nFile, 0L, SEEK_END);
102 m_dwFileLength = htell( m_nFile );
103 hseek( m_nFile, 0, SEEK_SET );
104
105 std::string csExt = GetFileExtFromPath(szInputFile.c_str());
106 if( ICASE_STR_COMPARE(csExt.c_str(), ".tivo") != 0)
107 return false;
108 }
109
110 char fingerprint[5];
111 memset( fingerprint, 0, 5 );
112 hread( fingerprint, 4, m_nFile );
113
114 if( ICASE_STR_COMPARE( fingerprint, "tivo" ) )
115 {
116 /* rewind. This should be OK because happyfile is
117 * careful to buffer
118 */
119 hseek(m_nFile, 0, SEEK_SET);
120 return false;
121 }
122
123 hseek( m_nFile, 0x0A, SEEK_SET );
124 boost::uint32_t offset = 0;
125 hread( &offset, 4, m_nFile );
126 m_dwBufferBase = ntohl(offset);
127
128 hseek( m_nFile, m_dwBufferBase, SEEK_SET ); // Skip xml notice and file fingerprint information
129
130 return true;
131
132 }
133 }
134
135 int CPs::PercentDone()
136 {
137 if( m_dwFileLength == 0 )
138 return 0;
139 else
140 return (int)(( 100 * (m_dwBufferBase + pos ))/m_dwFileLength);
141 }
142
143 void CPs::fill_buffer(size_t st)
144 {
145 buf_len = hread( buf+st, PS_BUFFER_LENGTH-st, m_nFile) + st;
146 m_dwBufferBase = htell( m_nFile ) - buf_len; // File location for start of buffer
147 pos=0;
148 }
149
150 bool CPs::check_buffer( size_t need )
151 {
152 size_t i;
153 #ifdef _DEBUG
154 byte *pj = &buf[pos]; // Gives me a convenient place for a break point...
155 #endif
156
157 if( (buf_len - pos) < need ) {
158 if( buf_len==PS_BUFFER_LENGTH ) {
159 for(i=pos;i<buf_len;i++)
160 buf[i-pos]=buf[i];
161 fill_buffer(buf_len-pos);
162 } else
163 return false;
164 }
165
166 return true;
167
168 }
169
170 int CPs::next_code(bool *valid )
171 {
172
173 if( !check_buffer(4) ) {
174 // premature file EOF : Synthesize MPEG end
175 *valid = true;
176 return 185;
177 }
178
179 if (b.ret_value(buf,(int)pos,(int)pos+2)!=1) // Invalid sync - not code sequence
180 *valid = false;
181 else
182 *valid = true;
183
184 int code = (int)b.ret_value(buf,(int)pos+3,(int)pos+3);
185 return code;
186
187 }
188
189 bool CPs::read_code(int *code )
190 {
191
192 bool rtcode;
193 *code = next_code( &rtcode );
194 pos += 4;
195 return rtcode;
196
197 }
198
199 size_t CPs::skip2code()
200 {
201
202 size_t dif = 0;
203 bool valid;
204
205 for(;;) {
206
207 if( buf_len-pos > 4 )
208 if( buf[pos] != 0 ) {
209
210 byte *p = (byte *)memchr( &buf[pos], 0, buf_len-pos );
211 if( p != NULL ) {
212
213 ptrdiff_t nch = p - &buf[pos];
214 assert(nch >= 0);
215 pos += nch;
216 dif += nch;
217
218 if( (buf_len-pos > 4) && (buf[pos+1] != '\0') ) {
219 pos++;
220 dif++;
221 continue;
222 }
223
224 }
225
226 }
227
228 next_code(&valid);
229 if( !valid ) {
230 skip_info(1);
231 dif += 1;
232 } else
233 break;
234
235 }
236
237 return dif;
238
239 }
240
241 bool CPs::end_mb( int st_bit )
242 {
243
244 check_buffer(4);
245
246 size_t p = pos;
247 for( int i=0; i<23; i++ ) {
248
249 if( b.ret_bit( buf[p], st_bit ) )
250 return false;
251
252 st_bit++;
253 if( st_bit > 0 ) {
254 st_bit = 0;
255 p++;
256 }
257
258 }
259
260 return true;
261
262 }
263
264 void CPs::skip_info(int n_bytes)
265 {
266 assert(n_bytes >= 0);
267 check_buffer(n_bytes);
268 pos=pos+n_bytes;
269 }
270
271 int CPs::ret_value(int n_bytes)
272 {
273 int val;
274 assert(n_bytes >= 0);
275 check_buffer(n_bytes);
276 val = b.ret_value(buf,(int)pos,(int)pos+n_bytes-1);
277 pos=pos+n_bytes;
278 return val;
279 }
280
281 int CPs::ret_bit_value(int st_bit,int end_bit,bool act)
282 {
283 int val;
284 check_buffer(1);
285 val=b.ret_bit_value(buf[pos],st_bit,end_bit);
286 if(act) pos++;
287 return val;
288 }
289
290 int CPs::get_bit_value( int *st_bit, int *dif, int nbits )
291 {
292
293 int val = 0;
294 int nb;
295 while( *st_bit + nbits > 7 ) {
296
297 nb = 8 - *st_bit;
298 val = (val << nb) + b.ret_bit_value( buf[pos], *st_bit, 7 );
299
300 *st_bit = 0;
301 pos++;
302 (*dif)++;
303 nbits -= nb;
304
305 } // while
306
307 if( nbits > 0 ) {
308 val = (val << nbits) + b.ret_bit_value( buf[pos], *st_bit, *st_bit + nbits - 1 );
309 *st_bit += nbits;
310 }
311
312 return val;
313
314 }
315
316 void CPs::end_PS()
317 {
318 CleanUp();
319 }
320
321 bool CPs::zero()
322 {
323 check_buffer(1);
324 if (buf[pos]==0) return true;
325 return false;
326 }
327
328 void CPs::go_back(int step)
329 {
330 assert(-step <= pos);
331 pos=pos-step;
332 }
333
334 double CPs::get_SCR()
335 {
336 int SCR;
337 double scr_val;
338
339 SCR=ret_bit_value(2,4,false); // SCR(32..30)
340 scr_val=(SCR>3)?4294967296.0:0.0; // caz pt. SCR[32]=1 -> overflow
341 SCR=SCR<<30;
342 SCR|=ret_bit_value(6,7,true)<<28; // SCR(29,28)
343 SCR|=ret_value(1)<<20; // SCR(27..20)
344 SCR|=ret_bit_value(0,4,false)<<15; // SCR(19..15)
345 SCR|=ret_bit_value(6,7,true)<<13; // SCR(14,13)
346 SCR|=ret_value(1)<<5; // SCR(12..5)
347 SCR|=ret_bit_value(0,4,false); // SCR(4..0)
348 scr_val+=SCR;
349 scr_val*=300.0;
350 SCR=ret_bit_value(6,7,true)<<7; // SCR_ext(8,7)
351 SCR|=ret_bit_value(0,6,true); // SCR_ext(6..0)
352 scr_val+=SCR;
353 return scr_val/27000.0; // 27Mhz clock
354
355 }
356
357 double CPs::get_PES_stamp()
358 {
359
360 int stamp;
361 double val;
362
363 stamp=ret_bit_value(4,6,true); // PTS(32..30)
364 val=(stamp>3)?4294967296.0:0.0; // caz de overflow (PTS[32]=1)
365 stamp=stamp<<30;
366 stamp|=ret_value(1)<<22; // PTS(29..22)
367 stamp|=ret_bit_value(0,6,true)<<15; // PTS(21..15)
368 stamp|=ret_value(1)<<7; // PTS(14..7)
369 stamp|=ret_bit_value(0,6,true); // PTS(6..0)
370 val+=stamp;
371 return val/90.0; // 90Khz clock
372
373 }
374
375 bool CPs::ret_bit(int pz)
376 {
377 return b.ret_bit(buf[pos],pz);
378 }

cvs@jdrake.com
ViewVC Help
Powered by ViewVC 1.1.13