~ubuntu-branches/ubuntu/quantal/vdr-plugin-xine/quantal

« back to all changes in this revision

Viewing changes to xineDevice.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Schmidt
  • Date: 2008-04-06 21:34:14 UTC
  • Revision ID: james.westby@ubuntu.com-20080406213414-54lbe5pj1cbbquon
Tags: upstream-0.8.2
ImportĀ upstreamĀ versionĀ 0.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "xineCommon.h"
 
3
 
 
4
#include <vdr/remux.h>
 
5
#include <vdr/transfer.h>
 
6
 
 
7
#include "xineDevice.h"
 
8
#include "xineOsd.h"
 
9
#include "xineSettings.h"
 
10
 
 
11
 
 
12
//#define LOG_ME(x) x
 
13
#define LOG_ME(x)
 
14
 
 
15
 
 
16
namespace PluginXine
 
17
{
 
18
  void cXineSpuDecoder::ptsAdjust(uint32_t &pts)
 
19
  {
 
20
    if (0 == pts
 
21
        || -1 == (int32_t)pts)
 
22
    {
 
23
      return;
 
24
    }
 
25
    
 
26
    const int64_t ptsXine = m_xineDevice->GetSTC();
 
27
 
 
28
    if (-1 == ptsXine)
 
29
      return;
 
30
    
 
31
//    ::fprintf(stderr, "ptsAdjust: %ld, %lld, %lld\n", pts, ptsXine, pts - ptsXine);
 
32
 
 
33
    pts = (uint32_t)ptsXine;
 
34
  }
 
35
  
 
36
  int cXineSpuDecoder::setTime(uint32_t pts)
 
37
  {
 
38
    ptsAdjust(pts);
 
39
    
 
40
    return cDvbSpuDecoder::setTime(pts);
 
41
  }
 
42
 
 
43
  static cXineDevice *theXineDevice = 0;
 
44
 
 
45
  bool cXineDevice::HasDecoder(void) const
 
46
  {
 
47
    return true;
 
48
  }
 
49
 
 
50
  cSpuDecoder *cXineDevice::GetSpuDecoder(void)
 
51
  {
 
52
    if (!m_spuDecoder
 
53
        && IsPrimaryDevice())
 
54
    {
 
55
      m_spuDecoder = new cXineSpuDecoder(this);
 
56
    }
 
57
    
 
58
    return m_spuDecoder;
 
59
  }
 
60
 
 
61
  bool cXineDevice::CanReplay(void) const
 
62
  {
 
63
    return true;
 
64
  }
 
65
 
 
66
  static bool findVideo = false;
 
67
  static bool foundVideo = false;
 
68
  static int ts = 0;
 
69
  static bool f = false;
 
70
  static bool np = false;
 
71
  static bool muted = false;
 
72
  static int jumboPESsize = 0;
 
73
  static int jumboPEStail = 0;
 
74
  static ePlayMode pm = pmNone;
 
75
  static bool audioSeen = false;
 
76
 
 
77
  static int64_t ptsV = -1, ptsA = -1, ptsP = -1, ptsD = -1;
 
78
  
 
79
  static enum { sstNone = 0, sstNormal, sstNoMetronom } softStartTrigger = sstNone;
 
80
  static enum
 
81
  {
 
82
    sIdle
 
83
    , sInitiateSequence
 
84
    , sStartSequence
 
85
    , sContinueSequence
 
86
  }
 
87
  softStartState = sIdle;
 
88
 
 
89
  double tNow()
 
90
  {
 
91
    timeval tv;
 
92
    ::gettimeofday(&tv, 0);
 
93
    return tv.tv_sec + tv.tv_usec / 1.0e+6; 
 
94
  }
 
95
 
 
96
  static double ttt0 = tNow(), ttt1 = tNow(), ttt2 = 0, ttt3 = 0, ttt4 = 0, ttt5 = 0, ttt6 = 0;
 
97
 
 
98
//  static int streams[ 256 ];
 
99
  static bool doClear = false;
 
100
 
 
101
  bool cXineDevice::SetPlayMode(ePlayMode PlayMode)
 
102
  {
 
103
    if (pmNone == PlayMode) 
 
104
    {
 
105
      doClear = true;
 
106
      ttt0 = tNow();
 
107
    }
 
108
    else 
 
109
      ttt2 = tNow();
 
110
/*
 
111
    timeval tv0;
 
112
    ::gettimeofday(&tv0, 0);
 
113
*/
 
114
    if (0)
 
115
    {
 
116
      time_t t1 = time(0);
 
117
      static time_t t0 = t1;
 
118
 
 
119
      if (0 == PlayMode && (t1 - t0) > (30 * 60))
 
120
        *(char *)0 = 0;
 
121
      
 
122
      t0 = t1;
 
123
    }
 
124
 
 
125
    bool playModeSupported = false;
 
126
 
 
127
    switch (PlayMode)
 
128
    {
 
129
    case pmNone:
 
130
    case pmAudioVideo:
 
131
    case pmAudioOnlyBlack:
 
132
    case pmExtern_THIS_SHOULD_BE_AVOIDED:
 
133
      playModeSupported = true;
 
134
      break;
 
135
    case pmAudioOnly:
 
136
#if APIVERSNUM >= 10308
 
137
    case pmVideoOnly:
 
138
#endif
 
139
      break;
 
140
    }
 
141
 
 
142
    ptsV = ptsA = ptsP = ptsD = -1;
 
143
    
 
144
    ts = 0;
 
145
    np = 0;
 
146
    f  = 0;
 
147
    
 
148
    xfprintf(stderr, "SetPlayMode: %d\n", PlayMode);
 
149
 
 
150
    m_xineLib.pause(false);
 
151
    m_xineLib.execFuncTrickSpeedMode(false);
 
152
    m_xineLib.execFuncSetSpeed(100.0);
 
153
 
 
154
    if (muted)
 
155
    {
 
156
      muted = false;
 
157
      m_xineLib.execFuncMute(false);
 
158
    } 
 
159
 
 
160
    if (pmNone == PlayMode)
 
161
    {
 
162
      if (pmExtern_THIS_SHOULD_BE_AVOIDED == pm)
 
163
        m_xineLib.enableExternal(false);
 
164
    
 
165
      pm = PlayMode;
 
166
    
 
167
      jumboPESsize = 0;
 
168
      jumboPEStail = 0;
 
169
/*
 
170
      for (unsigned int i = 0; i < sizeof (streams) / sizeof (*streams); i++)
 
171
      {
 
172
        if (streams[ i ])
 
173
          fprintf(stderr, "stream: 0x%02x\n", i);
 
174
      }
 
175
*/
 
176
      
 
177
      m_xineLib.ignore();
 
178
//      m_xineLib.execFuncMute();
 
179
//      m_xineLib.execFuncSetPrebuffer(0);
 
180
      m_xineLib.execFuncClear(-2);
 
181
//      m_xineLib.execFuncStart();
 
182
//      m_xineLib.execFuncMetronom(0);
 
183
      m_xineLib.execFuncStillFrame();
 
184
      m_xineLib.execFuncWait();
 
185
 
 
186
//      for (int i = 0; i < 2; i++)
 
187
        m_xineLib.showNoSignal();
 
188
 
 
189
      PushOut();
 
190
      m_xineLib.execFuncFlush();
 
191
 
 
192
      softStartTrigger = sstNone;
 
193
      softStartState = sIdle;
 
194
 
 
195
      foundVideo = false;
 
196
      findVideo = false;
 
197
    }
 
198
    else
 
199
    {
 
200
      audioSeen = false;
 
201
      softStartTrigger = sstNone;
 
202
      softStartState = sIdle;
 
203
      
 
204
//      ::memset(&streams, 0, sizeof (streams));
 
205
      
 
206
      m_xineLib.freeze();
 
207
      m_xineLib.ignore(false);
 
208
 
 
209
      m_xineLib.freeze(false);
 
210
/*
 
211
      PushOut();
 
212
      m_xineLib.execFuncFlush();
 
213
      m_xineLib.execFuncWait();
 
214
*/      
 
215
//      m_xineLib.execFuncSetPrebuffer(m_settings.GetModeParams()->m_prebufferFrames);
 
216
//      m_xineLib.execFuncSetPrebuffer(0);
 
217
      m_xineLib.execFuncClear(-4);
 
218
//      m_xineLib.execFuncStart();
 
219
      m_xineLib.execFuncWait();
 
220
 
 
221
#if APIVERSNUM < 10342
 
222
      m_settings.SelectReplayPrebufferMode(0 == cTransferControl::ReceiverDevice());
 
223
#else
 
224
      m_settings.SelectReplayPrebufferMode(!Transferring());
 
225
#endif
 
226
      
 
227
      if (m_settings.LiveTV())
 
228
      {
 
229
//        ::fprintf(stderr, "LiveTV\n");
 
230
        softStartTrigger = sstNormal;
 
231
      }
 
232
      else
 
233
        np = true;
 
234
 
 
235
      foundVideo = false;
 
236
      findVideo = true;
 
237
 
 
238
      cMutexLock pmMutexLock(&m_pmMutex);
 
239
      pm = PlayMode;
 
240
      m_pmCondVar.Broadcast();
 
241
    }
 
242
    
 
243
    if (pmExtern_THIS_SHOULD_BE_AVOIDED == PlayMode)
 
244
      m_xineLib.enableExternal();
 
245
/*    
 
246
    timeval tv1;
 
247
    ::gettimeofday(&tv1, 0);
 
248
 
 
249
    fprintf(stderr, "spm: %.3lf ms\n", 1000 * ((tv1.tv_sec + tv1.tv_usec / 1.0e+6) - (tv0.tv_sec + tv0.tv_usec / 1.0e+6)));
 
250
*/
 
251
    if (pmNone == PlayMode) {
 
252
      ttt1 = tNow(); ttt4 = 0; ttt5 = 0; }
 
253
    else
 
254
      ttt3 = tNow();
 
255
    return playModeSupported;
 
256
  }
 
257
 
 
258
  static bool lastCmdWasClear = false;
 
259
 
 
260
  void cXineDevice::TrickSpeed(int Speed)
 
261
  {
 
262
    f = false;
 
263
    ts = Speed;
 
264
 
 
265
    xfprintf(stderr, "TrickSpeed: %d\n", Speed);
 
266
    m_xineLib.execFuncTrickSpeedMode(lastCmdWasClear);
 
267
    m_xineLib.execFuncSetSpeed(100.0 / Speed);
 
268
    m_xineLib.execFuncWait();
 
269
    m_xineLib.freeze(false);
 
270
    m_xineLib.pause(false);
 
271
  }
 
272
 
 
273
  void cXineDevice::Clear(void)
 
274
  {
 
275
    lastCmdWasClear = true;
 
276
 
 
277
    doClear = true;
 
278
    ptsV = ptsA = ptsP = ptsD = -1;
 
279
    
 
280
    static int cntClear = 0;
 
281
 
 
282
    xfprintf(stderr, "Clear(%d)", cntClear);
 
283
 
 
284
    m_xineLib.pause();
 
285
    
 
286
    jumboPESsize = 0;
 
287
    jumboPEStail = 0;
 
288
 
 
289
    if (f)
 
290
        m_xineLib.execFuncSetSpeed(100.0);
 
291
 
 
292
    m_xineLib.execFuncClear(cntClear++);
 
293
//    m_xineLib.execFuncStart();
 
294
    np = true;
 
295
    
 
296
    if (f)
 
297
        m_xineLib.execFuncSetSpeed(0.0);
 
298
    
 
299
    m_xineLib.execFuncWait();
 
300
    m_xineLib.pause(false);
 
301
  xfprintf(stderr, "!\n");
 
302
    if (m_settings.LiveTV())
 
303
      softStartTrigger = sstNoMetronom;
 
304
   
 
305
    cDevice::Clear();
 
306
  }
 
307
 
 
308
  void cXineDevice::Play(void)
 
309
  {
 
310
    lastCmdWasClear = false;
 
311
 
 
312
    f = false;
 
313
    ts = 0;
 
314
 
 
315
    xfprintf(stderr, "Play\n");
 
316
    m_xineLib.execFuncTrickSpeedMode(false);
 
317
    m_xineLib.execFuncSetSpeed(100.0);
 
318
 
 
319
    if (muted)
 
320
    {
 
321
      muted = false;
 
322
      m_xineLib.execFuncMute(false);
 
323
    }
 
324
    
 
325
    m_xineLib.execFuncWait();
 
326
    m_xineLib.freeze(false);
 
327
    m_xineLib.pause(false);
 
328
    LOG_ME(::fprintf(stderr, "----\n");)
 
329
  }
 
330
 
 
331
  void cXineDevice::Freeze(void)
 
332
  {
 
333
    lastCmdWasClear = false;
 
334
 
 
335
    f = true;
 
336
    
 
337
    xfprintf(stderr, "Freeze\n");  
 
338
    m_xineLib.freeze();
 
339
    m_xineLib.pause();
 
340
    m_xineLib.execFuncSetSpeed(0.0);
 
341
    m_xineLib.execFuncWait();
 
342
    LOG_ME(::fprintf(stderr, "------\n");)  
 
343
  }
 
344
 
 
345
  void cXineDevice::Mute(void)
 
346
  {
 
347
    xfprintf(stderr, "Mute\n");
 
348
    m_xineLib.execFuncMute(true);
 
349
 
 
350
    muted = true;
 
351
  }
 
352
 
 
353
  static void store_frame(const unsigned char *buf, int len, int line)
 
354
  {
 
355
    if (0)
 
356
    {
 
357
      static int cnt = 0;
 
358
      
 
359
      char name[ 100 ];
 
360
      ::sprintf(name, "/tmp/frame_%05d_%05d", line, cnt++);
 
361
      
 
362
      FILE *f = fopen(name, "wb");
 
363
      size_t r = fwrite(buf, 1, len, f);
 
364
      (void)r;
 
365
      fclose(f);
 
366
    }
 
367
  }
 
368
  
 
369
#define VERBOSE_NOP() do{ xfprintf(stderr, "FIXME: %s:%d\n", __FILE__, __LINE__); } while (0)
 
370
#define VERBOSE_NOP1() do{ store_frame(Data, Length, __LINE__); xfprintf(stderr, "FIXME: %s:%d\n", __FILE__, __LINE__); } while (0)
 
371
#define VERBOSE_RETURN0(x) do{ xfprintf(stderr, "FIXME: %s:%d\n", __FILE__, __LINE__); return x; } while (0)
 
372
#define VERBOSE_RETURN1(x) do{ store_frame(buf0, len0, __LINE__); xfprintf(stderr, "FIXME: %s:%d\n", __FILE__, __LINE__); return x; } while (0)
 
373
#define VERBOSE_RETURN2(x) do{ store_frame(buf, len, __LINE__); xfprintf(stderr, "FIXME: %s:%d\n", __FILE__, __LINE__); return x; } while (0)
 
374
#define VERBOSE_RETURN3(x) do{ store_frame(Data, Length, __LINE__); xfprintf(stderr, "FIXME: %s:%d\n", __FILE__, __LINE__); return x; } while (0)
 
375
  
 
376
#if APIVERSNUM < 10331
 
377
 
 
378
enum ePesHeader {
 
379
  phNeedMoreData = -1,
 
380
  phInvalid = 0,
 
381
  phMPEG1 = 1,
 
382
  phMPEG2 = 2
 
383
  };
 
384
 
 
385
static ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader = NULL)
 
386
{
 
387
  if (Count < 7)
 
388
     return phNeedMoreData; // too short
 
389
 
 
390
  if ((Data[6] & 0xC0) == 0x80) { // MPEG 2
 
391
     if (Count < 9)
 
392
        return phNeedMoreData; // too short
 
393
 
 
394
     PesPayloadOffset = 6 + 3 + Data[8];
 
395
     if (Count < PesPayloadOffset)
 
396
        return phNeedMoreData; // too short
 
397
 
 
398
     if (ContinuationHeader)
 
399
        *ContinuationHeader = ((Data[6] == 0x80) && !Data[7] && !Data[8]);
 
400
 
 
401
     return phMPEG2; // MPEG 2
 
402
     }
 
403
 
 
404
  // check for MPEG 1 ...
 
405
  PesPayloadOffset = 6;
 
406
 
 
407
  // skip up to 16 stuffing bytes
 
408
  for (int i = 0; i < 16; i++) {
 
409
      if (Data[PesPayloadOffset] != 0xFF)
 
410
         break;
 
411
 
 
412
      if (Count <= ++PesPayloadOffset)
 
413
         return phNeedMoreData; // too short
 
414
      }
 
415
 
 
416
  // skip STD_buffer_scale/size
 
417
  if ((Data[PesPayloadOffset] & 0xC0) == 0x40) {
 
418
     PesPayloadOffset += 2;
 
419
 
 
420
     if (Count <= PesPayloadOffset)
 
421
        return phNeedMoreData; // too short
 
422
     }
 
423
 
 
424
  if (ContinuationHeader)
 
425
     *ContinuationHeader = false;
 
426
 
 
427
  if ((Data[PesPayloadOffset] & 0xF0) == 0x20) {
 
428
     // skip PTS only
 
429
     PesPayloadOffset += 5;
 
430
     }
 
431
  else if ((Data[PesPayloadOffset] & 0xF0) == 0x30) {
 
432
     // skip PTS and DTS
 
433
     PesPayloadOffset += 10;
 
434
     }
 
435
  else if (Data[PesPayloadOffset] == 0x0F) {
 
436
     // continuation header
 
437
     PesPayloadOffset++;
 
438
 
 
439
     if (ContinuationHeader)
 
440
        *ContinuationHeader = true;
 
441
     }
 
442
  else
 
443
     return phInvalid; // unknown
 
444
 
 
445
  if (Count < PesPayloadOffset)
 
446
     return phNeedMoreData; // too short
 
447
 
 
448
  return phMPEG1; // MPEG 1
 
449
}
 
450
 
 
451
#endif 
 
452
 
 
453
//#if APIVERSNUM < 10345
 
454
 
 
455
  namespace cRemux
 
456
  {
 
457
// Start codes:
 
458
#define SC_SEQUENCE 0xB3  // "sequence header code"
 
459
#define SC_GROUP    0xB8  // "group start code"
 
460
#define SC_PICTURE  0x00  // "picture start code"
 
461
 
 
462
    int GetPacketLength(const uchar *Data, int Count, int Offset)
 
463
    {
 
464
      // Returns the length of the packet starting at Offset, or -1 if Count is
 
465
      // too small to contain the entire packet.
 
466
      int Length = (Offset + 5 < Count) ? (Data[Offset + 4] << 8) + Data[Offset + 5] + 6 : -1;
 
467
      if (Length > 0 && Offset + Length <= Count)
 
468
         return Length;
 
469
      return -1;
 
470
    }
 
471
 
 
472
bool IsFrameH264(const uchar *Data, int Length)
 
473
{
 
474
  int PesPayloadOffset;
 
475
  const uchar *limit = Data + Length;
 
476
  if (AnalyzePesHeader(Data, Length, PesPayloadOffset) <= phInvalid)
 
477
     return false; // neither MPEG1 nor MPEG2
 
478
 
 
479
  Data += PesPayloadOffset + 3; // move to video payload and skip 00 00 01
 
480
  if (Data < limit) {
 
481
     // cVideoRepacker ensures that in case of H264 we will see an access unit delimiter here
 
482
     if (0x01 == Data[-1] && 9 == Data[0] && 0x00 == Data[-2] && 0x00 == Data[-3])
 
483
        return true;
 
484
     }
 
485
 
 
486
  return false;
 
487
}
 
488
 
 
489
int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType)
 
490
{
 
491
  // Scans the video packet starting at Offset and returns its length.
 
492
  // If the return value is -1 the packet was not completely in the buffer.
 
493
  int Length = GetPacketLength(Data, Count, Offset);
 
494
  if (Length > 0) {
 
495
     const bool h264 = IsFrameH264(Data + Offset, Length);
 
496
     int PesPayloadOffset = 0;
 
497
     if (AnalyzePesHeader(Data + Offset, Length, PesPayloadOffset) >= phMPEG1) {
 
498
        const uchar *p = Data + Offset + PesPayloadOffset + 2;
 
499
        const uchar *pLimit = Data + Offset + Length - 3;
 
500
#if APIVERSNUM >= 10326
 
501
        // cVideoRepacker ensures that a new PES packet is started for a new sequence,
 
502
        // group or picture which allows us to easily skip scanning through a huge
 
503
        // amount of video data.
 
504
        if (p < pLimit) {
 
505
           if (p[-2] || p[-1] || p[0] != 0x01)
 
506
              pLimit = 0; // skip scanning: packet doesn't start with 0x000001
 
507
           else {
 
508
              if (h264) {
 
509
                 int nal_unit_type = p[1] & 0x1F;
 
510
                 switch (nal_unit_type) {
 
511
                   case 9: // access unit delimiter
 
512
                        // when the MSB in p[1] is set (which violates H.264) then this is a hint
 
513
                        // from cVideoRepacker::HandleNalUnit() that this bottom field shall not
 
514
                        // be reported as picture.
 
515
                        if (p[1] & 0x80)
 
516
                           ((uchar *)p)[1] &= ~0x80; // revert the hint and fall through
 
517
                        else
 
518
                           break;
 
519
                   default: // skip scanning: packet doesn't start a new picture
 
520
                        pLimit = 0;
 
521
                   }
 
522
                 }
 
523
              else {
 
524
                 switch (p[1]) {
 
525
                   case SC_SEQUENCE:
 
526
                   case SC_GROUP:
 
527
                   case SC_PICTURE:
 
528
                        break;
 
529
                   default: // skip scanning: packet doesn't start a new sequence, group or picture
 
530
                        pLimit = 0;
 
531
                   }
 
532
                 }
 
533
              }
 
534
           }
 
535
#endif
 
536
        while (p < pLimit && (p = (const uchar *)memchr(p, 0x01, pLimit - p))) {
 
537
              if (!p[-2] && !p[-1]) { // found 0x000001
 
538
                 if (h264) {
 
539
                    int nal_unit_type = p[1] & 0x1F;
 
540
                    switch (nal_unit_type) {
 
541
                      case 9: { // access unit delimiter
 
542
                              int primary_pic_type = p[2] >> 5;
 
543
                              switch (primary_pic_type) {
 
544
                                case 0: // I
 
545
                                case 3: // SI
 
546
                                case 5: // I, SI
 
547
                                     PictureType = I_FRAME;
 
548
                                     break;
 
549
                                case 1: // I, P
 
550
                                case 4: // SI, SP
 
551
                                case 6: // I, SI, P, SP
 
552
                                     PictureType = P_FRAME;
 
553
                                     break;
 
554
                                case 2: // I, P, B
 
555
                                case 7: // I, SI, P, SP, B
 
556
                                     PictureType = B_FRAME;
 
557
                                     break;
 
558
                                }
 
559
                              return Length;
 
560
                              }
 
561
                      }
 
562
                    }
 
563
                 else {
 
564
                    switch (p[1]) {
 
565
                      case SC_PICTURE: PictureType = (p[3] >> 3) & 0x07;
 
566
                                       return Length;
 
567
                      }
 
568
                    }
 
569
                 p += 4; // continue scanning after 0x01ssxxyy
 
570
                 }
 
571
              else
 
572
                 p += 3; // continue scanning after 0x01xxyy
 
573
              }
 
574
        }
 
575
     PictureType = NO_PICTURE;
 
576
     return Length;
 
577
     }
 
578
  return -1;
 
579
}
 
580
  }
 
581
 
 
582
//#endif
 
583
 
 
584
/*
 
585
  static bool IsNotVideoIorPframe(const uchar *buf, int len)
 
586
  {
 
587
    if (0xe0 != (0xf0 & buf[ 3 ]))     // not video
 
588
      return true;
 
589
 
 
590
    uchar pt = NO_PICTURE;
 
591
    cRemux::ScanVideoPacket(buf, len, 0, pt);
 
592
 
 
593
    return (I_FRAME == pt || P_FRAME == pt);
 
594
  }
 
595
*/
 
596
/*
 
597
  static char *getFrameType(const uchar *buf, int len)
 
598
  {
 
599
    if (0xe0 != (0xf0 & buf[ 3 ]))     // not video
 
600
      return "";
 
601
 
 
602
    static char *frameTypes[ 8 ] = 
 
603
    {
 
604
      "",
 
605
      "i",
 
606
      "p",
 
607
      "b",
 
608
      "4",
 
609
      "5",
 
610
      "6",
 
611
      "7"
 
612
    };
 
613
 
 
614
    uchar pt = NO_PICTURE;
 
615
    cRemux::ScanVideoPacket(buf, len, 0, pt);
 
616
 
 
617
    return frameTypes[ pt ];
 
618
  }
 
619
*/
 
620
  static bool getPTS(const unsigned char *buf0, int len0, int64_t &pts)
 
621
  {
 
622
    while (len0 > 0)
 
623
    {
 
624
      while (len0 > 3
 
625
             && 0x00 == buf0[ 0 ]
 
626
             && 0x00 == buf0[ 1 ]
 
627
             && 0x00 == buf0[ 2 ])
 
628
      {
 
629
        buf0++;
 
630
        len0--;
 
631
      }
 
632
      
 
633
      if (3 == len0
 
634
          && 0x00 == buf0[ 0 ]
 
635
          && 0x00 == buf0[ 1 ]
 
636
          && 0x00 == buf0[ 2 ])
 
637
      {
 
638
        break;
 
639
      }
 
640
      
 
641
      if (len0 < 6)
 
642
        VERBOSE_RETURN1(false);
 
643
      
 
644
      if (0x00 != buf0[ 0 ]
 
645
          || 0x00 != buf0[ 1 ]
 
646
          || 0x01 != buf0[ 2 ])
 
647
      {
 
648
        VERBOSE_RETURN1(false);
 
649
      }
 
650
      
 
651
      if (0xe0 != (0xf0 & buf0[ 3 ])      // video
 
652
          && 0xc0 != (0xe0 & buf0[ 3 ])   // audio
 
653
          && 0xbd != (0xff & buf0[ 3 ])   // dolby
 
654
          && 0xbe != (0xff & buf0[ 3 ]))  // padding (DVD)
 
655
      {
 
656
        VERBOSE_RETURN1(false);
 
657
      }
 
658
      
 
659
      int len = (6 + buf0[ 4 ] * 0x100 + buf0[ 5 ]);
 
660
      if (len > len0)
 
661
        VERBOSE_RETURN1(false);
 
662
      
 
663
      const unsigned char *buf = buf0;
 
664
      buf0 += len;
 
665
      len0 -= len;
 
666
 
 
667
//      if (len0 != 0)
 
668
//        VERBOSE_NOP();
 
669
      
 
670
      if (0xbe == (0xff & buf[ 3 ]))  // padding (DVD)
 
671
        continue;
 
672
      
 
673
      if (len < (6 + 3))
 
674
        VERBOSE_RETURN2(false);
 
675
      
 
676
      if (0x80 != (0xc0 & buf[ 6 ]))  // MPEG1
 
677
      {
 
678
        do // ... while (false);
 
679
        {
 
680
          int o = 0;
 
681
 
 
682
          for (int i = 0; i < 16; i++)
 
683
          {
 
684
             if (buf[ 6 + o ] != 0xff)
 
685
               break;
 
686
 
 
687
             if (len < (6 + ++o))
 
688
               VERBOSE_RETURN2(false);
 
689
          }
 
690
 
 
691
          if (0x40 == (0xc0 & buf[ 6 + o ]))
 
692
            o += 2;
 
693
        
 
694
          if (len < (6 + o))
 
695
            VERBOSE_RETURN2(false);
 
696
          
 
697
          if (0x31 == (0xf1 & buf[ 6 + o + 0 ]))
 
698
          {
 
699
            if (len < (6 + o + 5 + 5))
 
700
              VERBOSE_RETURN2(false);
 
701
          
 
702
            if (0x01 != (0x01 & buf[ 6 + o + 2 ]))
 
703
              VERBOSE_RETURN2(false);
 
704
            
 
705
            if (0x01 != (0x01 & buf[ 6 + o + 4 ]))
 
706
              VERBOSE_RETURN2(false);
 
707
            
 
708
            if (0x11 != (0xf1 & buf[ 6 + o + 5 + 0 ]))
 
709
              VERBOSE_RETURN2(false);
 
710
            
 
711
            if (0x01 != (0x01 & buf[ 6 + o + 5 + 2 ]))
 
712
              VERBOSE_RETURN2(false);
 
713
            
 
714
            if (0x01 != (0x01 & buf[ 6 + o + 5 + 4 ]))
 
715
              VERBOSE_RETURN2(false);
 
716
            
 
717
            int64_t _pts = ((int64_t)(0x0e & buf[ 6 + o + 0 ])) << 29
 
718
              |                      (0xff & buf[ 6 + o + 1 ])  << 22
 
719
              |                      (0xfe & buf[ 6 + o + 2 ])  << 14
 
720
              |                      (0xff & buf[ 6 + o + 3 ])  << 7
 
721
              |                      (0xfe & buf[ 6 + o + 4 ])  >> 1;
 
722
            
 
723
//            ::fprintf(stderr, "pts: %lld\n", _pts);
 
724
            
 
725
            if (0 == _pts)
 
726
              break;
 
727
            
 
728
//            if (!IsNotVideoIorPframe(buf, len)) // only PTS of I and P frames are progressive in time
 
729
//              break;
 
730
            
 
731
            pts = _pts;
 
732
            
 
733
            return true;
 
734
          }
 
735
          else if (0x21 == (0xf1 & buf[ 6 + o + 0 ]))
 
736
          {
 
737
            if (len < (6 + o + 5))
 
738
              VERBOSE_RETURN2(false);
 
739
          
 
740
            if (0x01 != (0x01 & buf[ 6 + o + 2 ]))
 
741
              VERBOSE_RETURN2(false);
 
742
            
 
743
            if (0x01 != (0x01 & buf[ 6 + o + 4 ]))
 
744
              VERBOSE_RETURN2(false);
 
745
            
 
746
            int64_t _pts = ((int64_t)(0x0e & buf[ 6 + o + 0 ])) << 29
 
747
              |                      (0xff & buf[ 6 + o + 1 ])  << 22
 
748
              |                      (0xfe & buf[ 6 + o + 2 ])  << 14
 
749
              |                      (0xff & buf[ 6 + o + 3 ])  << 7
 
750
              |                      (0xfe & buf[ 6 + o + 4 ])  >> 1;
 
751
            
 
752
//            ::fprintf(stderr, "pts: %lld\n", _pts);
 
753
            
 
754
            if (0 == _pts)
 
755
              break;
 
756
 
 
757
//            if (!IsNotVideoIorPframe(buf, len)) // only PTS of I and P frames are progressive in time
 
758
//              break;
 
759
            
 
760
            pts = _pts;
 
761
            
 
762
            return true;
 
763
          }
 
764
          else if (0x0f == (0xff & buf[ 6 + o + 0 ]))
 
765
          {
 
766
            break;
 
767
          }
 
768
          
 
769
          for (int i = 0; i < 30; i++)
 
770
            xfprintf(stderr, "%02x ", buf[ i ]);
 
771
          xfprintf(stderr, "\n");
 
772
          
 
773
          VERBOSE_RETURN2(false);
 
774
        }
 
775
        while (false);
 
776
 
 
777
        continue;
 
778
      }
 
779
      
 
780
      if (0x40 == (0xc0 & buf[ 7 ]))
 
781
        VERBOSE_RETURN2(false);
 
782
      
 
783
      if (0x00 == (0xc0 & buf[ 7 ]))
 
784
        continue;
 
785
 
 
786
// ignore      
 
787
//      if (0x00 != (0x3f & buf[ 7 ]))
 
788
//        VERBOSE_RETURN2(false);
 
789
      
 
790
      bool hasPTS = (0 != (0x80 & buf[ 7 ]));
 
791
      bool hasDTS = (0 != (0x40 & buf[ 7 ]));
 
792
      
 
793
      unsigned char hdl = buf[ 8 ];
 
794
      
 
795
      if (hdl < ((hasPTS + hasDTS) * 5))
 
796
        VERBOSE_RETURN2(false);
 
797
      
 
798
      if (len < (6 + 3 + hdl))
 
799
        VERBOSE_RETURN2(false);
 
800
      
 
801
      if ((0x20 * hasPTS + 0x10 * hasDTS + 0x01) != (0xf1 & buf[ 9 ]))
 
802
      {
 
803
        if ((0x20 * hasPTS + 0x00 * hasDTS + 0x01) != (0xf1 & buf[ 9 ]))
 
804
        {
 
805
          // accept streams, that start with '00X0' instead of '00X1'.
 
806
        }
 
807
        else if ((0x00 * hasPTS + 0x10 * hasDTS + 0x01) != (0xf1 & buf[ 9 ]))
 
808
        {
 
809
          // accept streams, that start with '000X' instead of '001X'.
 
810
        }
 
811
        else
 
812
        {
 
813
          VERBOSE_RETURN2(false);
 
814
        }
 
815
      }
 
816
      
 
817
      if (0x01 != (0x01 & buf[ 11 ]))
 
818
        VERBOSE_RETURN2(false);
 
819
      
 
820
      if (0x01 != (0x01 & buf[ 13 ]))
 
821
        VERBOSE_RETURN2(false);
 
822
      
 
823
      if (hasDTS)
 
824
      {
 
825
        if (0x11 != (0xf1 & buf[ 14 ]))
 
826
          VERBOSE_RETURN2(false);
 
827
                  
 
828
        if (0x01 != (0x01 & buf[ 16 ]))
 
829
          VERBOSE_RETURN2(false);
 
830
              
 
831
        if (0x01 != (0x01 & buf[ 18 ]))
 
832
          VERBOSE_RETURN2(false);
 
833
      }
 
834
/*
 
835
      fprintf(stderr, " %02x %02x %02x %02x %02x\n"
 
836
              , buf[  9 ]
 
837
              , buf[ 10 ]
 
838
              , buf[ 11 ]
 
839
              , buf[ 12 ]
 
840
              , buf[ 13 ]);
 
841
*/
 
842
      int64_t _pts = ((int64_t)(0x0e & buf[  9 ])) << 29
 
843
        |                      (0xff & buf[ 10 ])  << 22
 
844
        |                      (0xfe & buf[ 11 ])  << 14
 
845
        |                      (0xff & buf[ 12 ])  << 7
 
846
        |                      (0xfe & buf[ 13 ])  >> 1;
 
847
 
 
848
      if (0 == _pts)
 
849
        return false;
 
850
 
 
851
//      if (!IsNotVideoIorPframe(buf, len)) // only PTS of I and P frames are progressive in time
 
852
//        return false;
 
853
            
 
854
      pts = _pts;
 
855
      
 
856
      return true;
 
857
    }
 
858
 
 
859
//    VERBOSE_RETURN2(false);
 
860
    return false;
 
861
  }
 
862
 
 
863
  static bool stripPTSandDTS(unsigned char *buf0, int len0)
 
864
  {
 
865
    while (len0 > 0)
 
866
    {
 
867
      while (len0 > 3
 
868
             && 0x00 == buf0[ 0 ]
 
869
             && 0x00 == buf0[ 1 ]
 
870
             && 0x00 == buf0[ 2 ])
 
871
      {
 
872
        buf0++;
 
873
        len0--;
 
874
      }
 
875
      
 
876
      if (3 == len0
 
877
          && 0x00 == buf0[ 0 ]
 
878
          && 0x00 == buf0[ 1 ]
 
879
          && 0x00 == buf0[ 2 ])
 
880
      {
 
881
        break;
 
882
      }
 
883
      
 
884
      if (len0 < 6)
 
885
        VERBOSE_RETURN1(false);
 
886
      
 
887
      if (0x00 != buf0[ 0 ]
 
888
          || 0x00 != buf0[ 1 ]
 
889
          || 0x01 != buf0[ 2 ])
 
890
      {
 
891
        VERBOSE_RETURN1(false);
 
892
      }
 
893
      
 
894
      if (0xe0 != (0xf0 & buf0[ 3 ])      // video
 
895
          && 0xc0 != (0xe0 & buf0[ 3 ])   // audio
 
896
          && 0xbd != (0xff & buf0[ 3 ])   // dolby
 
897
          && 0xbe != (0xff & buf0[ 3 ])   // padding (DVD)
 
898
          && 0xba != (0xff & buf0[ 3 ])   // system layer: pack header
 
899
          && 0xbb != (0xff & buf0[ 3 ])   // system layer: system header
 
900
          && 0xb9 != (0xff & buf0[ 3 ]))  // system layer: stream end
 
901
      {
 
902
//fprintf(stderr, "buf0[ 3 ]: %02x\n", buf0[ 3 ]);
 
903
        VERBOSE_RETURN1(false);
 
904
      }
 
905
 
 
906
      int len = (6 + buf0[ 4 ] * 0x100 + buf0[ 5 ]);
 
907
      if (0xba == buf0[ 3 ]) // pack header has fixed length
 
908
      {
 
909
        if (0x00 == (0xc0 & buf0[ 4 ])) // MPEG 1
 
910
          len = 12;
 
911
        else // MPEG 2
 
912
          len = 14 + (buf0[ 13 ] & 0x07);
 
913
      }
 
914
      else if (0xb9 == buf0[ 3 ]) // stream end has fixed length
 
915
      {
 
916
        len = 4;
 
917
      }
 
918
 
 
919
      if (len > len0)
 
920
        VERBOSE_RETURN1(false);
 
921
      
 
922
      unsigned char *buf = buf0;
 
923
      buf0 += len;
 
924
      len0 -= len;
 
925
 
 
926
//      if (len0 != 0)
 
927
//        VERBOSE_NOP();
 
928
      
 
929
      if (0xbe == (0xff & buf[ 3 ])    // padding (DVD)
 
930
        || 0xba == (0xff & buf[ 3 ])   // system layer: pack header
 
931
        || 0xbb == (0xff & buf[ 3 ])   // system layer: system header
 
932
        || 0xb9 == (0xff & buf[ 3 ]))  // system layer: stream end
 
933
      {
 
934
        continue;
 
935
      }
 
936
      
 
937
      if (len < (6 + 3))
 
938
        VERBOSE_RETURN2(false);
 
939
      
 
940
      if (0x80 != (0xc0 & buf[ 6 ]))  // MPEG1
 
941
      {
 
942
        bool ok = false;
 
943
        
 
944
        do // ... while (false);
 
945
        {
 
946
          int o = 0;
 
947
 
 
948
          for (int i = 0; i < 16; i++)
 
949
          {
 
950
             if (buf[ 6 + o ] != 0xff)
 
951
               break;
 
952
 
 
953
             if (len < (6 + ++o))
 
954
               VERBOSE_RETURN2(false);
 
955
          }
 
956
 
 
957
          if (0x40 == (0xc0 & buf[ 6 + o ]))
 
958
            o += 2;
 
959
        
 
960
          if (len < (6 + o))
 
961
            VERBOSE_RETURN2(false);
 
962
          
 
963
          if (0x31 == (0xf1 & buf[ 6 + o + 0 ]))
 
964
          {
 
965
            if (0x01 != (0x01 & buf[ 6 + o + 2 ]))
 
966
              VERBOSE_RETURN2(false);
 
967
            
 
968
            if (0x01 != (0x01 & buf[ 6 + o + 4 ]))
 
969
              VERBOSE_RETURN2(false);
 
970
            
 
971
            if (0x11 != (0xf1 & buf[ 6 + o + 5 + 0 ]))
 
972
              VERBOSE_RETURN2(false);
 
973
            
 
974
            if (0x01 != (0x01 & buf[ 6 + o + 5 + 2 ]))
 
975
              VERBOSE_RETURN2(false);
 
976
            
 
977
            if (0x01 != (0x01 & buf[ 6 + o + 5 + 4 ]))
 
978
              VERBOSE_RETURN2(false);
 
979
            
 
980
            buf[ 6 + o + 0 ] = 0xff;
 
981
            buf[ 6 + o + 1 ] = 0xff;
 
982
            buf[ 6 + o + 2 ] = 0xff;
 
983
            buf[ 6 + o + 3 ] = 0xff;
 
984
            buf[ 6 + o + 4 ] = 0xff;
 
985
            
 
986
            buf[ 6 + o + 5 + 0 ] = 0xff;
 
987
            buf[ 6 + o + 5 + 1 ] = 0xff;
 
988
            buf[ 6 + o + 5 + 2 ] = 0xff;
 
989
            buf[ 6 + o + 5 + 3 ] = 0xff;
 
990
            buf[ 6 + o + 5 + 4 ] = 0x0f;
 
991
            
 
992
            ok = true;
 
993
          }
 
994
          else if (0x21 == (0xf1 & buf[ 6 + o + 0 ]))
 
995
          {
 
996
            if (0x01 != (0x01 & buf[ 6 + o + 2 ]))
 
997
              VERBOSE_RETURN2(false);
 
998
            
 
999
            if (0x01 != (0x01 & buf[ 6 + o + 4 ]))
 
1000
              VERBOSE_RETURN2(false);
 
1001
            
 
1002
            buf[ 6 + o + 0 ] = 0xff;
 
1003
            buf[ 6 + o + 1 ] = 0xff;
 
1004
            buf[ 6 + o + 2 ] = 0xff;
 
1005
            buf[ 6 + o + 3 ] = 0xff;
 
1006
            buf[ 6 + o + 4 ] = 0x0f;
 
1007
            
 
1008
            ok = true;
 
1009
          }
 
1010
          else if (0x0f == (0xff & buf[ 6 + o + 0 ]))
 
1011
          {
 
1012
            ok = true;
 
1013
          }
 
1014
 
 
1015
          if (ok)
 
1016
            break;
 
1017
            
 
1018
          for (int i = 0; i < 30; i++)
 
1019
            xfprintf(stderr, "%02x ", buf[ i ]);
 
1020
          xfprintf(stderr, "\n");
 
1021
          
 
1022
          VERBOSE_RETURN2(false);
 
1023
        }
 
1024
        while (false);
 
1025
 
 
1026
        if (ok)
 
1027
          continue;
 
1028
      }
 
1029
      
 
1030
      if (0x40 == (0xc0 & buf[ 7 ]))
 
1031
        VERBOSE_RETURN2(false);
 
1032
      
 
1033
      if (0x00 == (0xc0 & buf[ 7 ]))
 
1034
        continue;
 
1035
 
 
1036
// ignore      
 
1037
//      if (0x00 != (0x3f & buf[ 7 ]))
 
1038
//        VERBOSE_RETURN2(false);
 
1039
      
 
1040
      bool hasPTS = (0 != (0x80 & buf[ 7 ]));
 
1041
      bool hasDTS = (0 != (0x40 & buf[ 7 ]));
 
1042
      
 
1043
      unsigned char hdl = buf[ 8 ];
 
1044
      
 
1045
      if (hdl < ((hasPTS + hasDTS) * 5))
 
1046
        VERBOSE_RETURN2(false);
 
1047
      
 
1048
      if (len < (6 + 3 + hdl))
 
1049
        VERBOSE_RETURN2(false);
 
1050
      
 
1051
      if ((0x20 * hasPTS + 0x10 * hasDTS + 0x01) != (0xf1 & buf[ 9 ]))
 
1052
      {
 
1053
        if ((0x20 * hasPTS + 0x00 * hasDTS + 0x01) != (0xf1 & buf[ 9 ]))
 
1054
        {
 
1055
          // accept streams, that start with '00X0' instead of '00X1'.
 
1056
        }
 
1057
        else if ((0x00 * hasPTS + 0x10 * hasDTS + 0x01) != (0xf1 & buf[ 9 ]))
 
1058
        {
 
1059
          // accept streams, that start with '000X' instead of '001X'.
 
1060
        }
 
1061
        else
 
1062
        {
 
1063
          VERBOSE_RETURN2(false);
 
1064
        }
 
1065
      }
 
1066
      
 
1067
      if (0x01 != (0x01 & buf[ 11 ]))
 
1068
        VERBOSE_RETURN2(false);
 
1069
      
 
1070
      if (0x01 != (0x01 & buf[ 13 ]))
 
1071
        VERBOSE_RETURN2(false);
 
1072
      
 
1073
      if (hasDTS)
 
1074
      {
 
1075
        if (0x11 != (0xf1 & buf[ 14 ]))
 
1076
          VERBOSE_RETURN2(false);
 
1077
        
 
1078
        if (0x01 != (0x01 & buf[ 16 ]))
 
1079
          VERBOSE_RETURN2(false);
 
1080
                  
 
1081
        if (0x01 != (0x01 & buf[ 18 ]))
 
1082
          VERBOSE_RETURN2(false);
 
1083
      }
 
1084
      
 
1085
      buf[ 7 ] &= 0x3f;
 
1086
      
 
1087
      for (int i = 9; i < (9 + ((hasPTS + hasDTS) * 5)); i++)
 
1088
        buf[ i ] = 0xff;
 
1089
    }
 
1090
    
 
1091
    return true;
 
1092
  }
 
1093
 
 
1094
  static uchar padding[ 6 + 0xffff ] =
 
1095
  {
 
1096
    0x00
 
1097
    , 0x00
 
1098
    , 0x01
 
1099
    , 0xbe
 
1100
    , 0xff
 
1101
    , 0xff
 
1102
  };
 
1103
 
 
1104
  int cXineDevice::PushOut()
 
1105
  {
 
1106
    uchar *Data = padding;
 
1107
    int Length = sizeof (padding);
 
1108
    
 
1109
    return PlayCommon3(Data, Length, -1);
 
1110
  }
 
1111
  
 
1112
//static bool blahblah = false;
 
1113
 
 
1114
  void cXineDevice::StillPicture(const uchar *Data, int Length)
 
1115
  {
 
1116
    xfprintf(stderr, "StillPicture: %p, %d\n", Data, Length);
 
1117
 
 
1118
    if (0)
 
1119
    {
 
1120
      for (int i = 0; i < Length - 3; i++)
 
1121
      {
 
1122
        if (i != 0
 
1123
            && Data[ i + 0 ] == 0x00
 
1124
            && Data[ i + 1 ] == 0x00
 
1125
            && Data[ i + 2 ] == 0x01)
 
1126
        {
 
1127
          xfprintf(stderr, "\n");
 
1128
        }
 
1129
        
 
1130
        xfprintf(stderr, "%02x ", Data[ i ]);
 
1131
      }
 
1132
      
 
1133
      for (int i = Length - 3; i < Length; i++)
 
1134
      {
 
1135
        xfprintf(stderr, "%02x ", Data[ i ]);
 
1136
      }
 
1137
      
 
1138
      xfprintf(stderr, "\n");
 
1139
    }
 
1140
    
 
1141
    const int maxPackets = 3;
 
1142
    uchar pes[ maxPackets * (6 + 0xffff) ];
 
1143
    static const uchar header[ 6 + 3 ] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
 
1144
    
 
1145
    do // ... while (false);
 
1146
    {
 
1147
      if (Length < 6)
 
1148
      {
 
1149
        VERBOSE_NOP();
 
1150
        break;
 
1151
      }
 
1152
      
 
1153
      if (0x00 != Data[ 0 ]
 
1154
          || 0x00 != Data[ 1 ]
 
1155
          || 0x01 != Data[ 2 ])
 
1156
      {
 
1157
        VERBOSE_NOP();
 
1158
        break;
 
1159
      }
 
1160
      
 
1161
      if (0xe0 != (0xf0 & Data[ 3 ])      // video
 
1162
          && 0xc0 != (0xe0 & Data[ 3 ])   // audio
 
1163
          && 0xbd != (0xff & Data[ 3 ])   // dolby
 
1164
          && 0xbe != (0xff & Data[ 3 ]))  // padding (DVD)
 
1165
      {
 
1166
        if (Length > maxPackets * (0xffff - 3))
 
1167
        {
 
1168
          VERBOSE_NOP();
 
1169
          break;
 
1170
        }
 
1171
      
 
1172
        int todo = Length;
 
1173
        const uchar *src = Data;
 
1174
        uchar *dst = pes;
 
1175
 
 
1176
        while (todo > 0)
 
1177
        {
 
1178
          ::memcpy(dst, header, sizeof (header));
 
1179
          
 
1180
          int bite = todo;
 
1181
 
 
1182
          if (bite > 0xffff - 3)
 
1183
            bite = 0xffff - 3;
 
1184
 
 
1185
          todo -= bite;
 
1186
          
 
1187
          dst[ 4 ] = 0xff & ((bite + 3) >> 8);
 
1188
          dst[ 5 ] = 0xff & (bite + 3);
 
1189
 
 
1190
          ::memcpy(dst + sizeof (header), src, bite);
 
1191
 
 
1192
          Length += sizeof (header);
 
1193
          dst += sizeof (header) + bite;
 
1194
          src += bite;
 
1195
        }
 
1196
        
 
1197
        Data = pes;
 
1198
      }
 
1199
    }
 
1200
    while (false);
 
1201
    
 
1202
    stripPTSandDTS((uchar *)Data, Length);
 
1203
    
 
1204
    ts = 0;
 
1205
 
 
1206
    m_xineLib.execFuncTrickSpeedMode(false);
 
1207
    m_xineLib.execFuncSetSpeed(100.0);
 
1208
    m_xineLib.execFuncStillFrame();
 
1209
    m_xineLib.execFuncWait();
 
1210
 
 
1211
    f = 0;
 
1212
    
 
1213
    m_xineLib.pause(false);
 
1214
 
 
1215
//    PushOut();
 
1216
 
 
1217
//blahblah = true;
 
1218
 
 
1219
    for (int i = 0; i < 1 /* 4 */; i++)
 
1220
    {
 
1221
//fprintf(stderr, " (%d) ", i);
 
1222
      int r = PlayVideo1(Data, Length, true);      
 
1223
      if (r < 0)
 
1224
        return;
 
1225
    }
 
1226
 
 
1227
    PushOut();
 
1228
//    m_xineLib.execFuncFlush(0);
 
1229
    m_xineLib.execFuncFlush();
 
1230
 
 
1231
//    ::fprintf(stderr, "------------\n");      
 
1232
    LOG_ME(::fprintf(stderr, "------------\n");)
 
1233
  }
 
1234
 
 
1235
  static bool softStartPoll(cXineLib &xineLib, cPoller &poller, const int timeout, const bool result);
 
1236
 
 
1237
  bool cXineDevice::Poll(cPoller &Poller, int TimeoutMs /* = 0 */)
 
1238
  {
 
1239
    if (softStartState != sIdle)
 
1240
      return true;
 
1241
 
 
1242
    if (m_xineLib.Poll(Poller, TimeoutMs))
 
1243
      return softStartPoll(m_xineLib, Poller, TimeoutMs, true);
 
1244
 
 
1245
    return softStartPoll(m_xineLib, Poller, TimeoutMs, false);
 
1246
  }
 
1247
 
 
1248
  static bool jw = false;
 
1249
 
 
1250
  bool cXineDevice::Flush(int TimeoutMs /* = 0 */)
 
1251
  {
 
1252
    const bool jw0 = jw;
 
1253
    
 
1254
    m_xineLib.pause(false);
 
1255
 
 
1256
    if (!jw0)
 
1257
    {
 
1258
      int r = PushOut();
 
1259
      if (r < 0)
 
1260
        return true;
 
1261
    }
 
1262
 
 
1263
    bool retVal = m_xineLib.execFuncFlush(TimeoutMs, jw0);
 
1264
 
 
1265
    if (!retVal)
 
1266
      xfprintf(stderr, jw0 ? "f" : "F");
 
1267
    
 
1268
    jw = true;
 
1269
    
 
1270
    return retVal;
 
1271
  }
 
1272
  
 
1273
  static bool dumpAudio(const char *proc, const uchar *Data, int Length)
 
1274
  {
 
1275
    return false;
 
1276
    
 
1277
  nextPacket:
 
1278
    if (Length == 0)
 
1279
      return true;
 
1280
/*    
 
1281
    fprintf(stderr
 
1282
            , "%s: "
 
1283
            , proc);
 
1284
*/  
 
1285
    if (Length < 6)
 
1286
      VERBOSE_RETURN0(false);
 
1287
        
 
1288
    if (0x00 != Data[ 0 ]
 
1289
        || 0x00 != Data[ 1 ]
 
1290
        || 0x01 != Data[ 2 ])
 
1291
    {
 
1292
      VERBOSE_RETURN3(false);
 
1293
    }
 
1294
 
 
1295
    int l = Data[ 4 ] * 0x0100 + Data[ 5 ];
 
1296
    if (Length < (6 + l))
 
1297
      VERBOSE_RETURN0(false);
 
1298
    
 
1299
    if (0xe0 == (Data[ 3 ] & 0xf0)     //video
 
1300
        || 0xc0 == (Data[ 3 ] & 0xe0)  //audio
 
1301
        || 0xbe == Data[ 3 ])          //padding
 
1302
    {
 
1303
      Data += (6 + l);
 
1304
      Length -= (6 + l);
 
1305
      goto nextPacket;
 
1306
    }
 
1307
    
 
1308
  //  if (0xbd != Data[ 3 ])             //private (dolby, pcm)
 
1309
  //    VERBOSE_RETURN0(false);
 
1310
 
 
1311
//    fprintf(stderr, "private ");
 
1312
    
 
1313
    if (l < (3 + 0 + 2))
 
1314
      VERBOSE_RETURN0(false);
 
1315
    
 
1316
    int h = Data[ 8 ];
 
1317
    if (l < (3 + h + 2))
 
1318
      VERBOSE_RETURN0(false);
 
1319
 
 
1320
    xfprintf(stderr
 
1321
            , "%s: "
 
1322
            , proc);
 
1323
 
 
1324
    xfprintf(stderr
 
1325
            , "0x%02x 0x%02x\n"
 
1326
            , Data[ 6 + 3 + h + 0 ]
 
1327
            , Data[ 6 + 3 + h + 1 ]);
 
1328
 
 
1329
    Data += (6 + l);
 
1330
    Length -= (6 + l);
 
1331
    goto nextPacket;
 
1332
  }
 
1333
  
 
1334
  static bool IsVideo(const uchar *Data, int Length)
 
1335
  {
 
1336
    return (Length >= 4
 
1337
            && 0x00 == Data[ 0 ]
 
1338
            && 0x00 == Data[ 1 ]
 
1339
            && 0x01 == Data[ 2 ]
 
1340
            && 0xe0 == (0xf0 & Data[ 3 ]));
 
1341
  }
 
1342
 
 
1343
  int cXineDevice::PlayVideo(const uchar *Data, int Length)
 
1344
  {
 
1345
    if (ttt4 == 0) ttt4 = tNow();
 
1346
//    static FILE *f = fopen("/tmp/egon1", "wb");
 
1347
//    fwrite(Data, Length, 1, f);
 
1348
 
 
1349
    return PlayVideo1(Data, Length, false);
 
1350
  }
 
1351
  
 
1352
  int cXineDevice::PlayVideo1(const uchar *Data, int Length, const bool stillImageData)
 
1353
  {
 
1354
    LOG_ME(::fprintf(stderr, "V");)
 
1355
 
 
1356
    if (f)
 
1357
    {      
 
1358
      LOG_ME(::fprintf(stderr, "<");)
 
1359
      return 0;
 
1360
    }
 
1361
 
 
1362
    if (pmNone == pm)
 
1363
    {
 
1364
      cMutexLock pmMutexLock(&m_pmMutex);
 
1365
 
 
1366
      if (pmNone == pm)
 
1367
        m_pmCondVar.Wait(m_pmMutex);
 
1368
    }
 
1369
    
 
1370
    int retVal = PlayVideo2(Data, Length, stillImageData);
 
1371
 
 
1372
    LOG_ME(::fprintf(stderr, "v");)
 
1373
 
 
1374
    return retVal;
 
1375
  }
 
1376
 
 
1377
  int cXineDevice::PlayCommon2(const uchar *Data, int Length, int64_t ptsForce)
 
1378
  {
 
1379
/*
 
1380
if (blahblah)
 
1381
{
 
1382
  fprintf(stderr, "blahblah C2");
 
1383
  for (int i = 0; i < 50 && i < Length; i++)
 
1384
    fprintf(stderr, " %02x", Data[ i ]);
 
1385
  fprintf(stderr, "\n");
 
1386
}
 
1387
*/
 
1388
    do // ... while (false);
 
1389
    {
 
1390
      if (Length < 6)
 
1391
      {
 
1392
        VERBOSE_NOP();
 
1393
        break;
 
1394
      }
 
1395
      
 
1396
      if (0x00 != Data[ 0 ]
 
1397
          || 0x00 != Data[ 1 ]
 
1398
          || 0x01 != Data[ 2 ])
 
1399
      {
 
1400
        VERBOSE_NOP();
 
1401
        break;
 
1402
      }
 
1403
      
 
1404
      int l = 6 + Data[ 4 ] * 0x0100 + Data[ 5 ];
 
1405
      if (Length < l)
 
1406
      {
 
1407
        VERBOSE_NOP();
 
1408
        break;
 
1409
      }
 
1410
      
 
1411
      if (0xe0 != (Data[ 3 ] & 0xf0)     //video
 
1412
          && 0xc0 != (Data[ 3 ] & 0xe0)  //audio
 
1413
          && 0xbd != Data[ 3 ])          //private (dolby, pcm)
 
1414
      {
 
1415
        VERBOSE_NOP();
 
1416
        break;
 
1417
      }
 
1418
 
 
1419
      int payloadOffset = 0;
 
1420
      if (AnalyzePesHeader(Data, Length, payloadOffset) <= phInvalid)
 
1421
      {
 
1422
        VERBOSE_NOP();
 
1423
        break;
 
1424
      }
 
1425
 
 
1426
      if (l <= payloadOffset)
 
1427
      {
 
1428
        // drop short frames
 
1429
//        ::fprintf(stderr, "i");
 
1430
        return Length;
 
1431
      }
 
1432
 
 
1433
//      if (0xc0 == (Data[ 3 ] & 0xe0))  //audio
 
1434
//        return Length;
 
1435
    }
 
1436
    while (false);
 
1437
 
 
1438
    return PlayCommon3(Data, Length, ptsForce);
 
1439
  }
 
1440
 
 
1441
typedef long long int lld_t;
 
1442
 
 
1443
static int xzabc = 0;
 
1444
 
 
1445
  int cXineDevice::PlayCommon3(const uchar *Data, int Length, int64_t ptsForce)
 
1446
  {
 
1447
//    if (!m_settings.LiveTV())
 
1448
//    {
 
1449
//      VERBOSE_NOP1();
 
1450
//      return Length;
 
1451
//    }
 
1452
 
 
1453
//    if (xzabc)
 
1454
    if (0)
 
1455
    {
 
1456
      if (0xe0 == (Data[ 3 ] & 0xf0))      //video
 
1457
      {
 
1458
        uchar pt = NO_PICTURE;
 
1459
        cRemux::ScanVideoPacket(Data, Length, 0, pt);
 
1460
 
 
1461
        if (pt != NO_PICTURE)
 
1462
        {
 
1463
          static int64_t last = -1;
 
1464
          int64_t pts = -1;
 
1465
          getPTS(Data, Length, pts);
 
1466
          fprintf(stderr, "** %c ** %lld ** %lld ** %lld **\n", "0IPB4567"[pt], (lld_t)ptsForce, (lld_t)(ptsForce - last), (lld_t)pts);
 
1467
          last = ptsForce;
 
1468
        }
 
1469
      }
 
1470
      if (0xc0 == (Data[ 3 ] & 0xe0))      //audio
 
1471
      {
 
1472
        {
 
1473
          static int64_t last = -1;
 
1474
          int64_t pts = -1;
 
1475
          getPTS(Data, Length, pts);
 
1476
          fprintf(stderr, "\t\t\t\t\t\t\t** %c ** %lld ** %lld ** %lld **\n", 'A', (lld_t)ptsForce, (lld_t)(ptsForce - last), (lld_t)pts);
 
1477
          last = ptsForce;
 
1478
        }
 
1479
      }
 
1480
    }
 
1481
    if (0)
 
1482
    {
 
1483
      int64_t pts = ptsForce;
 
1484
      if (ptsForce > -1
 
1485
        || getPTS(Data, Length, pts))
 
1486
      {
 
1487
        xzabc = 0;
 
1488
        int64_t *pPTS = 0;
 
1489
        
 
1490
        if (0xe0 == (Data[ 3 ] & 0xf0))      //video
 
1491
        {
 
1492
          pPTS = &ptsV;
 
1493
        }
 
1494
        else if (0xc0 == (Data[ 3 ] & 0xe0)) //audio
 
1495
        {
 
1496
          pPTS = &ptsA;
 
1497
        }
 
1498
        else if (0xbd == Data[ 3 ])          //private (dolby, pcm)
 
1499
        {
 
1500
          int h = Data[ 6 + 2 ];
 
1501
          
 
1502
          if (0xa0 == (0xf0 & Data[ 6 + 3 + h + 0 ]))  // pcm?
 
1503
            pPTS = &ptsP;
 
1504
          else
 
1505
            pPTS = &ptsD;
 
1506
        }
 
1507
        else
 
1508
        {
 
1509
          xfprintf(stderr, "0x%02x\t", Data[ 3 ]);
 
1510
          VERBOSE_NOP();        
 
1511
        }
 
1512
        
 
1513
        if (pPTS
 
1514
            && *pPTS != pts)
 
1515
        {
 
1516
          *pPTS = pts;
 
1517
          
 
1518
          int64_t ptsX = -1;
 
1519
          m_xineLib.execFuncGetPTS(ptsX);
 
1520
 
 
1521
          int64_t dV = (ptsV != -1 && ptsX != -1) ? ptsV - ptsX : 0;
 
1522
          int64_t dA = (ptsA != -1 && ptsX != -1) ? ptsA - ptsX : 0;
 
1523
          int64_t dP = (ptsP != -1 && ptsX != -1) ? ptsP - ptsX : 0;
 
1524
          int64_t dD = (ptsD != -1 && ptsX != -1) ? ptsD - ptsX : 0;
 
1525
 
 
1526
          int64_t dVA = (ptsV != -1 && ptsA != -1) ? ptsA - ptsV : 0; 
 
1527
          int64_t dVD = (ptsV != -1 && ptsD != -1) ? ptsD - ptsV : 0; 
 
1528
 
 
1529
          fprintf(stderr, "ptsVideo: %lld, ptsAudio: %lld, ptsPCM: %lld, ptsDolby: %lld, ptsXine: %lld, dVA: %lld, dVD: %lld, dV: %lld, dA: %lld, dP: %lld, dD: %lld\n", (lld_t)ptsV, (lld_t)ptsA, (lld_t)ptsP, (lld_t)ptsD, (lld_t)ptsX, (lld_t)dVA, (lld_t)dVD, (lld_t)dV, (lld_t)dA, (lld_t)dP, (lld_t)dD);
 
1530
        }
 
1531
      }
 
1532
    }
 
1533
    
 
1534
/*
 
1535
if (blahblah)
 
1536
{
 
1537
  blahblah = false;
 
1538
  fprintf(stderr, "blahblah C3");
 
1539
  for (int i = 0; i < 50 && i < Length; i++)
 
1540
    fprintf(stderr, " %02x", Data[ i ]);
 
1541
  fprintf(stderr, "\n");
 
1542
}
 
1543
*/
 
1544
 
 
1545
    int done = 0;
 
1546
 
 
1547
    while (done < Length)
 
1548
    {
 
1549
      int r = m_xineLib.execFuncStream1(Data + done, Length - done);
 
1550
      if (r < 0)
 
1551
        return r;
 
1552
      
 
1553
      done += r;
 
1554
    }
 
1555
 
 
1556
    return done;
 
1557
  }
 
1558
  
 
1559
  int cXineDevice::PlayVideo2(const uchar *Data, int Length, const bool stillImageData)
 
1560
  {
 
1561
//    fprintf(stderr, "D");
 
1562
    
 
1563
    int done = 0;
 
1564
 
 
1565
    while (done < Length)
 
1566
    {
 
1567
      char ch = 'X';
 
1568
      
 
1569
      int todo = Length - done;
 
1570
      
 
1571
      if (todo >= 6)
 
1572
      {
 
1573
        if (0x00 == Data[ done + 0 ]
 
1574
            && 0x00 == Data[ done + 1 ]
 
1575
            && 0x01 == Data[ done + 2 ])
 
1576
        {
 
1577
          int id  = Data[ done + 3 ];
 
1578
          int len = 6 + Data[ done + 4 ] * 0x0100 + Data[ done + 5 ];
 
1579
 
 
1580
          if (0xba == id) // pack header has fixed length
 
1581
          {
 
1582
            if (0x00 == (0xc0 & Data[ done + 4 ])) // MPEG 1
 
1583
              len = 12;
 
1584
            else // MPEG 2
 
1585
              len = 14 + (Data[ done + 13 ] & 0x07);
 
1586
          }
 
1587
          else if (0xb9 == id) // stream end has fixed length
 
1588
          {
 
1589
            len = 4;
 
1590
          }
 
1591
 
 
1592
          if (todo >= len)
 
1593
          {
 
1594
            todo = len;
 
1595
 
 
1596
            if (0xbe == id   // padding
 
1597
              || 0xba == id  // system layer: pack header
 
1598
              || 0xbb == id  // system layer: system header
 
1599
              || 0xb9 == id) // system layer: stream end
 
1600
            {
 
1601
              done += todo;
 
1602
 
 
1603
//              fprintf(stderr, "x");
 
1604
              continue;
 
1605
            }
 
1606
 
 
1607
            ch = '.';            
 
1608
          }
 
1609
          else        
 
1610
          {
 
1611
//            ::fprintf(stderr, "todo: %d, len: %d\t", todo, len);
 
1612
            VERBOSE_NOP();
 
1613
            ch = '3';
 
1614
 
 
1615
//            break;
 
1616
          }
 
1617
        }
 
1618
        else        
 
1619
        {
 
1620
          VERBOSE_NOP();
 
1621
          ch = '2';
 
1622
        }
 
1623
      }
 
1624
      else        
 
1625
      {
 
1626
        VERBOSE_NOP();
 
1627
        ch = '1';
 
1628
      }
 
1629
      
 
1630
//      fprintf(stderr, "%c", ch);
 
1631
      
 
1632
      int r = PlayVideo3(Data + done, todo, stillImageData);
 
1633
      if (r < 0)
 
1634
        return r;
 
1635
 
 
1636
      done += r;
 
1637
    }
 
1638
    
 
1639
    return done;
 
1640
  }
 
1641
 
 
1642
  static void resetScramblingControl(const uchar *Data, int Length)
 
1643
  {
 
1644
    if (Length < 6)
 
1645
    {
 
1646
      VERBOSE_NOP();
 
1647
      return;
 
1648
    }
 
1649
      
 
1650
    if (0x00 != Data[ 0 ]
 
1651
        || 0x00 != Data[ 1 ]
 
1652
        || 0x01 != Data[ 2 ])
 
1653
    {
 
1654
      VERBOSE_NOP1();
 
1655
      return;
 
1656
    }
 
1657
      
 
1658
    if (0xe0 != (0xf0 & Data[ 3 ])      // video
 
1659
        && 0xc0 != (0xe0 & Data[ 3 ])   // audio
 
1660
        && 0xbd != (0xff & Data[ 3 ])   // dolby
 
1661
        && 0xbe != (0xff & Data[ 3 ])   // padding (DVD)
 
1662
        && 0xba != (0xff & Data[ 3 ])   // system layer: pack header
 
1663
        && 0xbb != (0xff & Data[ 3 ])   // system layer: system header
 
1664
        && 0xb9 != (0xff & Data[ 3 ]))  // system layer: stream end
 
1665
    {
 
1666
      VERBOSE_NOP();
 
1667
      return;
 
1668
    }
 
1669
        
 
1670
    if (0xbe == (0xff & Data[ 3 ])    // padding (DVD)
 
1671
      || 0xba == (0xff & Data[ 3 ])   // system layer: pack header
 
1672
      || 0xbb == (0xff & Data[ 3 ])   // system layer: system header
 
1673
      || 0xb9 == (0xff & Data[ 3 ]))  // system layer: stream end
 
1674
    {
 
1675
      return;
 
1676
    }
 
1677
 
 
1678
    int len = (6 + Data[ 4 ] * 0x100 + Data[ 5 ]);
 
1679
    if (len < 6 + 1
 
1680
        || Length < 6 + 1)
 
1681
    {
 
1682
      VERBOSE_NOP();
 
1683
      return;
 
1684
    }
 
1685
 
 
1686
    if (0x00 != (0x30 & Data[ 6 ]))
 
1687
    {
 
1688
      if (0x80 == (0xc0 & Data[ 6 ]))  // only touch MPEG2
 
1689
      {
 
1690
        xfprintf(stderr, "reseting PES_scrambling_control: 0x%02x\n", Data[ 6 ]);
 
1691
 
 
1692
        ((uchar *)Data)[ 6 ] &= ~0x30;
 
1693
      }
 
1694
    }
 
1695
  }
 
1696
  
 
1697
  int cXineDevice::PlayVideo3(const uchar *Data, int Length, const bool stillImageData)
 
1698
  {
 
1699
/*
 
1700
if (blahblah)
 
1701
{
 
1702
  fprintf(stderr, "blahblah V3");
 
1703
  for (int i = 0; i < 50 && i < Length; i++)
 
1704
    fprintf(stderr, " %02x", Data[ i ]);
 
1705
  fprintf(stderr, "\n");
 
1706
}
 
1707
*/
 
1708
    resetScramblingControl(Data, Length);
 
1709
    
 
1710
    dumpAudio("Video", Data, Length);
 
1711
 
 
1712
    return PlayCommon(Data, Length, stillImageData);
 
1713
  }
 
1714
  
 
1715
  static double videoFrameDuration(const uchar *Data, int Length)
 
1716
  {
 
1717
    int PesPayloadOffset = 0;
 
1718
    ePesHeader ph = AnalyzePesHeader(Data, Length, PesPayloadOffset);
 
1719
    if (ph < phMPEG1)
 
1720
      return -1;
 
1721
 
 
1722
    if ((Data[ 3 ] & 0xf0) != 0xe0)
 
1723
      return -1;
 
1724
 
 
1725
    if (Length < PesPayloadOffset + 8)
 
1726
      return -1;
 
1727
 
 
1728
    const uchar *p = Data + PesPayloadOffset;
 
1729
 
 
1730
    if (*p++ != 0x00)
 
1731
      return -1;
 
1732
 
 
1733
    if (*p++ != 0x00)
 
1734
      return -1;
 
1735
 
 
1736
    if (*p++ != 0x01)
 
1737
      return -1;
 
1738
 
 
1739
    if (*p++ != 0xb3)
 
1740
      return -1;
 
1741
 
 
1742
    p += 3;
 
1743
 
 
1744
    static const double frameRates[ 16 ] =
 
1745
    {
 
1746
      -1,
 
1747
      24000/1001.0,
 
1748
      24,
 
1749
      25,
 
1750
      30000/1001.0,
 
1751
      30,
 
1752
      50,
 
1753
      60000/1001.0,
 
1754
      60,
 
1755
      -1,
 
1756
      -1,
 
1757
      -1,
 
1758
      -1,
 
1759
      -1,
 
1760
      -1,
 
1761
      -1,
 
1762
    };
 
1763
 
 
1764
    int frameRateIndex = *p & 0x0f;
 
1765
 
 
1766
    if (frameRates[ frameRateIndex ] < 0)
 
1767
      return -1;
 
1768
 
 
1769
    long n = 0, d = 0;
 
1770
 
 
1771
    if (ph == phMPEG2)
 
1772
    {
 
1773
      const uchar *const limit = Data + Length - 10 + 3;
 
1774
      while (p < limit)
 
1775
      {
 
1776
        if (p[ 0 ] != 0x01 || p[ -1 ] != 0x00 || p[ -2 ] != 0x00)
 
1777
        {
 
1778
          p++;
 
1779
          continue;
 
1780
        }
 
1781
 
 
1782
        if (p[ 1 ] != 0xb5) // extension start code
 
1783
          break;
 
1784
 
 
1785
        if ((p[ 2 ] & 0xf0) != 0x10) // sequence extension
 
1786
          break;
 
1787
 
 
1788
        p += 7;
 
1789
 
 
1790
        n = (*p & 0x60) >> 5;
 
1791
        d = (*p & 0x1f);
 
1792
        break;
 
1793
      }
 
1794
    }
 
1795
 
 
1796
    return 90000 / (frameRates[ frameRateIndex ] * (n + 1) / (d + 1));
 
1797
  }
 
1798
 
 
1799
  static int frameSizes[ 256 ];
 
1800
  
 
1801
  static double audioFrameDuration(const uchar *Data, int Length)
 
1802
  {
 
1803
    int PesPayloadOffset = 0;
 
1804
    ePesHeader ph = AnalyzePesHeader(Data, Length, PesPayloadOffset);
 
1805
    if (ph < phMPEG1)
 
1806
      return -1;
 
1807
 
 
1808
    if ((Data[ 3 ] & 0xff) == 0xbd)
 
1809
    {
 
1810
      static int samplingFrequencies[ 4 ] = // all values are specified in Hz
 
1811
      {
 
1812
        48000, 44100, 32000, -1
 
1813
      };
 
1814
 
 
1815
      if (PesPayloadOffset + 5 <= Length
 
1816
        && Data[ PesPayloadOffset + 0 ] == 0x0b
 
1817
        && Data[ PesPayloadOffset + 1 ] == 0x77
 
1818
        && frameSizes[ Data[ PesPayloadOffset + 4 ] ] > 0)
 
1819
      {
 
1820
        if (samplingFrequencies[ Data[ PesPayloadOffset + 4 ] >> 6 ] < 0)
 
1821
          return -1;
 
1822
 
 
1823
        return 90000.0 * 1536 / samplingFrequencies[ Data[ PesPayloadOffset + 4 ] >> 6 ];
 
1824
      }
 
1825
      else if (PesPayloadOffset + 4 + 5 <= Length
 
1826
        && Data[ PesPayloadOffset + 4 + 0 ] == 0x0b
 
1827
        && Data[ PesPayloadOffset + 4 + 1 ] == 0x77
 
1828
        && frameSizes[ Data[ PesPayloadOffset + 4 + 4 ] ] > 0)
 
1829
      {
 
1830
        if (samplingFrequencies[ Data[ PesPayloadOffset + 4 + 4 ] >> 6 ] < 0)
 
1831
          return -1;
 
1832
 
 
1833
        return 90000.0 * 1536 / samplingFrequencies[ Data[ PesPayloadOffset + 4 + 4 ] >> 6 ];
 
1834
      }
 
1835
      else 
 
1836
        return -1;
 
1837
    }
 
1838
 
 
1839
    if ((Data[ 3 ] & 0xe0) != 0xc0)
 
1840
      return -1;
 
1841
 
 
1842
    if (Length < PesPayloadOffset + 4)
 
1843
      return -1;
 
1844
 
 
1845
    ulong Header = 0;
 
1846
    Header |= Data[ PesPayloadOffset + 0 ];
 
1847
    Header <<= 8;
 
1848
    Header |= Data[ PesPayloadOffset + 1 ];
 
1849
    Header <<= 8;
 
1850
    Header |= Data[ PesPayloadOffset + 2 ];
 
1851
    Header <<= 8;
 
1852
    Header |= Data[ PesPayloadOffset + 3 ];
 
1853
 
 
1854
    bool Mpeg2 = (ph == phMPEG2);
 
1855
    
 
1856
    int syncword           = (Header & 0xFFF00000) >> 20;
 
1857
    int id                 = (Header & 0x00080000) >> 19;
 
1858
    int layer              = (Header & 0x00060000) >> 17;
 
1859
//  int protection_bit     = (Header & 0x00010000) >> 16;
 
1860
    int bitrate_index      = (Header & 0x0000F000) >> 12;
 
1861
    int sampling_frequency = (Header & 0x00000C00) >> 10;
 
1862
//  int padding_bit        = (Header & 0x00000200) >>  9;
 
1863
//  int private_bit        = (Header & 0x00000100) >>  8;
 
1864
//  int mode               = (Header & 0x000000C0) >>  6;
 
1865
//  int mode_extension     = (Header & 0x00000030) >>  4;
 
1866
//  int copyright          = (Header & 0x00000008) >>  3;
 
1867
//  int orignal_copy       = (Header & 0x00000004) >>  2;
 
1868
    int emphasis           = (Header & 0x00000003);
 
1869
 
 
1870
    if (syncword != 0xFFF)
 
1871
      return -1;
 
1872
 
 
1873
    if (id == 0 && !Mpeg2) // reserved in MPEG 1
 
1874
      return -1;
 
1875
 
 
1876
    if (layer == 0) // reserved
 
1877
      return -1;
 
1878
 
 
1879
    if (bitrate_index == 0xF) // forbidden
 
1880
      return -1;
 
1881
 
 
1882
    if (sampling_frequency == 3) // reserved
 
1883
      return -1;
 
1884
 
 
1885
    if (emphasis == 2) // reserved
 
1886
      return -1;
 
1887
 
 
1888
    static int samplingFrequencies[ 2 ][ 4 ] = // all values are specified in Hz
 
1889
    {
 
1890
      { 44100, 48000, 32000, -1 }, // MPEG 1
 
1891
      { 22050, 24000, 16000, -1 }  // MPEG 2
 
1892
    };
 
1893
 
 
1894
    static int slots_per_frame[ 2 ][ 3 ] =
 
1895
    {
 
1896
      { 12, 144, 144 }, // MPEG 1, Layer I, II, III
 
1897
      { 12, 144,  72 }  // MPEG 2, Layer I, II, III
 
1898
    };
 
1899
 
 
1900
    int mpegIndex  = 1 - id;
 
1901
    int layerIndex = 3 - layer;
 
1902
 
 
1903
    // Layer I (i. e., layerIndex == 0) has a larger slot size
 
1904
    int slotSize = (layerIndex == 0) ? 4 : 1; // bytes
 
1905
 
 
1906
    int sf = samplingFrequencies[ mpegIndex ][ sampling_frequency ];
 
1907
 
 
1908
//fprintf(stderr, "afd: %.3f ms, PES-Length: %d\n", 1000.0 * 8 * slotSize * slots_per_frame[ mpegIndex ][ layerIndex ] / sf, Length);
 
1909
 
 
1910
    return 90000.0 * 8 * slotSize * slots_per_frame[ mpegIndex ][ layerIndex ] / sf;
 
1911
  }
 
1912
 
 
1913
  static double softStartTime = 0;
 
1914
  static const double softStartSpeedStart = 0.75;
 
1915
  static const double softStartSpeedMin = 0.15;
 
1916
  static double softStartDuration = 31 / 25.0;
 
1917
  static const int softStartMaxSpeedChanges = 20;
 
1918
  static double softStartLastSpeed = -1;
 
1919
  static double softStartSpeedChangeTime = -1;
 
1920
  static int64_t softStartPtsVdr = -1;
 
1921
  static const int64_t softStartLogPtsDelta = 4 * 90000;
 
1922
  static int softStartHitPoll = 0;
 
1923
  static bool softStartNoMetronom = false;
 
1924
  static const double pi = 4 * ::atan(1);
 
1925
 
 
1926
 
 
1927
  static double softStartCalcSpeed0(const double /* t */)
 
1928
  {
 
1929
    return 0;
 
1930
  }
 
1931
  
 
1932
  static double softStartCalcSpeed1(const double t)
 
1933
  {
 
1934
    const double p = (1 + ::cos(2 * pi * t)) / 2;    
 
1935
          
 
1936
    return softStartSpeedMin + p * ((softStartSpeedStart * (1 - t) + 1.0 * t) - softStartSpeedMin);
 
1937
  }
 
1938
  
 
1939
  static double softStartCalcSpeed2(const double t)
 
1940
  {
 
1941
    double p = 2 * t - 1;
 
1942
    if (p < 0)
 
1943
      p = -p;
 
1944
 
 
1945
//    p = p * p * p;
 
1946
    p = p * p;
 
1947
          
 
1948
    return softStartSpeedMin + p * ((softStartSpeedStart * (1 - t) + 1.0 * t) - softStartSpeedMin);
 
1949
  }
 
1950
  
 
1951
  static double softStartCalcSpeed3(const double t)
 
1952
  {
 
1953
    if (t < 0.25)
 
1954
      return softStartSpeedStart;
 
1955
 
 
1956
    if (t < 0.50)
 
1957
      return softStartSpeedMin + (1 - softStartSpeedMin) * 0 / 3;
 
1958
 
 
1959
    if (t < 0.75)
 
1960
      return softStartSpeedMin + (1 - softStartSpeedMin) * 1 / 3;
 
1961
 
 
1962
    return   softStartSpeedMin + (1 - softStartSpeedMin) * 2 / 3;
 
1963
  }
 
1964
  
 
1965
  static double softStartCalcSpeed4(const double t)
 
1966
  {
 
1967
    const double p = (1 + ::cos(pi * (1 + t))) / 2;    
 
1968
          
 
1969
    return softStartSpeedMin + (1 - softStartSpeedMin) * p;
 
1970
  }
 
1971
 
 
1972
  static double softStartCalcSpeed(const double t)
 
1973
  {
 
1974
    if (t >= 1)
 
1975
      return 1;
 
1976
 
 
1977
    return softStartCalcSpeed0(t);  // choose a method
 
1978
 
 
1979
    (void)softStartCalcSpeed0;
 
1980
    (void)softStartCalcSpeed1;
 
1981
    (void)softStartCalcSpeed2;
 
1982
    (void)softStartCalcSpeed3;
 
1983
    (void)softStartCalcSpeed4;
 
1984
  }
 
1985
 
 
1986
  bool softStartPoll(cXineLib &xineLib, cPoller &poller, const int timeout, bool result)
 
1987
  {
 
1988
    if (softStartState > sIdle)
 
1989
    {
 
1990
      if (result)
 
1991
      {
 
1992
        softStartHitPoll = 0;
 
1993
      }
 
1994
      else if (++softStartHitPoll >= 2)
 
1995
      {
 
1996
        do
 
1997
        {
 
1998
          softStartState = sIdle;
 
1999
          
 
2000
          xineLib.execFuncFirstFrame();
 
2001
          xineLib.execFuncSetSpeed(100.0);
 
2002
          xineLib.execFuncWait();
 
2003
        }
 
2004
        while (!xineLib.Poll(poller, timeout, true));
 
2005
 
 
2006
        softStartHitPoll = 0;
 
2007
        result = true;
 
2008
      }
 
2009
 
 
2010
//      ::fprintf(stderr, "softStartHitPoll: %d, %d\n", result, softStartHitPoll);      
 
2011
    }
 
2012
 
 
2013
    return result;
 
2014
  }
 
2015
 
 
2016
  static int64_t vpts, apts, extra0, extra;
 
2017
  static bool useApts;
 
2018
  static bool seenAudio = false;
 
2019
  static bool seenVideo = false;
 
2020
  static bool seenApts = false;
 
2021
  static bool seenVpts = false;
 
2022
  
 
2023
  static const int64_t extra_max = 50 * 90000 / 25;
 
2024
 
 
2025
  static bool oldMode = false;
 
2026
 
 
2027
  static inline double softStartCalcQ0(int64_t vdr, int64_t xine, int64_t hyst)
 
2028
  {
 
2029
    if (vdr < 0 || xine < 0)
 
2030
      return 0;
 
2031
 
 
2032
    double delta = (vdr - xine) / 90000.0;
 
2033
    if (delta <= 0)
 
2034
      return 0;
 
2035
 
 
2036
    if (delta >= softStartLogPtsDelta / 90000.0)
 
2037
      return 0;
 
2038
 
 
2039
    if (delta >= (softStartDuration + hyst / 90000.0))
 
2040
      return 1;
 
2041
 
 
2042
    return delta / (softStartDuration + hyst / 90000.0);
 
2043
  }
 
2044
 
 
2045
  static bool gotQ1 = false;
 
2046
  static int64_t hystQ = 0;
 
2047
  static int64_t hystQ1 = 0;
 
2048
  static bool vdrTime100reload = false;
 
2049
 
 
2050
  static inline double softStartCalcQ(int64_t vdr, int64_t xine)
 
2051
  {
 
2052
    double q = softStartCalcQ0(vdr, xine, hystQ);
 
2053
 
 
2054
    bool gQ1 = (q >= 1);
 
2055
    if (gQ1 != gotQ1)
 
2056
    {
 
2057
      gotQ1 = gQ1;
 
2058
 
 
2059
      if (gotQ1)
 
2060
      {
 
2061
        hystQ = 0;
 
2062
      }
 
2063
      else
 
2064
      {
 
2065
        vdrTime100reload = true;
 
2066
        hystQ = (hystQ1 += 90000 / 25);
 
2067
      }
 
2068
    }
 
2069
 
 
2070
//fprintf(stderr, "q: %.3lf, gq1: %d, hystQ: %lld, hystQ1: %lld, vdr: %lld, xine: %lld, d: %lld\n", q, gotQ1, hystQ, hystQ1, vdr, xine, vdr - xine);
 
2071
    return q;
 
2072
  }
 
2073
 
 
2074
  static int64_t vdrPTSLast = -2;
 
2075
  static int64_t vdrAptsLast = -1;
 
2076
  static int64_t vdrVptsLast = -1;
 
2077
 
 
2078
  static double vdrVptsCalced = -1;
 
2079
  static double vdrAptsCalced = -1;
 
2080
  static double vdrVduration = -1;
 
2081
  static double vdrAduration = -1;
 
2082
 
 
2083
  static double vdrVptsBuffered[ 2 ] = { -1, -1 };
 
2084
 
 
2085
  static bool getPTS(const uchar *Data, int Length, int64_t &pts, bool isVideo, bool isAudio, double &vptsCalced, double &aptsCalced, double &vDuration, double &aDuration, double vptsBuffered[2])
 
2086
  {
 
2087
    uchar pt = NO_PICTURE;
 
2088
 
 
2089
    if (isVideo)
 
2090
    {
 
2091
      cRemux::ScanVideoPacket(Data, Length, 0, pt);
 
2092
 
 
2093
      if (pt != NO_PICTURE && vDuration > 0 && vptsBuffered[ 1 ] > 0)
 
2094
        vptsBuffered[ 1 ] += vDuration;
 
2095
    }
 
2096
 
 
2097
    bool retVal = false;
 
2098
 
 
2099
    if (getPTS(Data, Length, pts))
 
2100
    {
 
2101
      if (isAudio)
 
2102
      {
 
2103
        aptsCalced = pts;
 
2104
 
 
2105
        double duration = audioFrameDuration(Data, Length);
 
2106
        if (duration >= 0)
 
2107
          aDuration = duration;
 
2108
      }
 
2109
 
 
2110
      if (isVideo)
 
2111
      {
 
2112
        if (pt == B_FRAME)
 
2113
          vptsCalced = pts;
 
2114
        else if (pt != NO_PICTURE)
 
2115
          vptsBuffered[ 1 ] = pts;
 
2116
 
 
2117
        double duration = videoFrameDuration(Data, Length);
 
2118
        if (duration >= 0)
 
2119
          vDuration = duration;
 
2120
 
 
2121
        if (pt != B_FRAME)
 
2122
          goto other;
 
2123
      }
 
2124
 
 
2125
      return true;
 
2126
    }
 
2127
    else
 
2128
    {
 
2129
      if (isAudio)
 
2130
      {
 
2131
        double duration = audioFrameDuration(Data, Length);
 
2132
 
 
2133
        bool frameStart = (duration > -1);
 
2134
 
 
2135
        if (aptsCalced > -1 && aDuration > -1 && frameStart)
 
2136
        {
 
2137
          aptsCalced += aDuration;
 
2138
          while (aptsCalced >= 0x200000000ull)
 
2139
            aptsCalced -= 0x200000000ull;
 
2140
 
 
2141
          pts = (int64_t)aptsCalced;
 
2142
 
 
2143
          retVal = true;
 
2144
        }
 
2145
 
 
2146
        if (duration >= 0)
 
2147
          aDuration = duration;
 
2148
      }
 
2149
 
 
2150
      if (isVideo)
 
2151
      {
 
2152
other:
 
2153
        double dur = vDuration;
 
2154
 
 
2155
        if (pt != B_FRAME && pt != NO_PICTURE)
 
2156
        {
 
2157
          vptsCalced = vptsBuffered[ 0 ];
 
2158
          vptsBuffered[ 0 ] = vptsBuffered[ 1 ];
 
2159
          dur = 0;
 
2160
        }
 
2161
          
 
2162
        bool frameStart = (pt != NO_PICTURE);
 
2163
 
 
2164
        if (vptsCalced > -1 && dur > -1 && frameStart)
 
2165
        {
 
2166
          vptsCalced += dur;
 
2167
          while (vptsCalced >= 0x200000000ull)
 
2168
            vptsCalced -= 0x200000000ull;
 
2169
 
 
2170
          pts = (int64_t)vptsCalced;
 
2171
 
 
2172
          retVal = true;
 
2173
        }
 
2174
 
 
2175
        double duration = videoFrameDuration(Data, Length);
 
2176
        if (duration >= 0)
 
2177
          vDuration = duration;
 
2178
      }
 
2179
 
 
2180
      return retVal;
 
2181
    }
 
2182
  }
 
2183
 
 
2184
  static double vdrTime100 = -1;
 
2185
 
 
2186
  int cXineDevice::PlayCommon(const uchar *Data, int Length, const bool stillImageData)
 
2187
  {
 
2188
    const bool isAudio = !IsVideo(Data, Length);
 
2189
    const bool isVideo = !isAudio && !stillImageData;
 
2190
 
 
2191
    if (stillImageData
 
2192
      && isAudio)
 
2193
    {
 
2194
//      ::fprintf(stderr, "x");
 
2195
      return Length;
 
2196
    }
 
2197
/*    
 
2198
    if (stillImageData)
 
2199
      fprintf(stderr, "writing: %d\n", Length - 6);
 
2200
*/
 
2201
    if (findVideo && (isVideo || isAudio))
 
2202
    {
 
2203
      findVideo = false;
 
2204
      foundVideo = isVideo;
 
2205
//xfprintf(stderr, "foundVideo: %d\n", foundVideo);
 
2206
    }
 
2207
 
 
2208
if (0 && isAudio) {
 
2209
static int64_t opts = -1;
 
2210
static int64_t xpts = -1;
 
2211
getPTS(Data, Length, xpts, isVideo, isAudio, vdrVptsCalced, vdrAptsCalced, vdrVduration, vdrAduration, vdrVptsBuffered);
 
2212
//fprintf(stderr, "audio: %.3lf, %d, %lld, %lld\n", audioFrameDuration(Data, Length), Length, xpts, xpts - opts);
 
2213
opts = xpts;
 
2214
}
 
2215
if (0 && isVideo) {
 
2216
static int64_t opts = -1;
 
2217
static int64_t xpts = -1;
 
2218
getPTS(Data, Length, xpts, isVideo, isAudio, vdrVptsCalced, vdrAptsCalced, vdrVduration, vdrAduration, vdrVptsBuffered);
 
2219
//fprintf(stderr, "video: %.3lf, %d, %lld, %lld\n", videoFrameDuration(Data, Length), Length, xpts, xpts - opts);
 
2220
opts = xpts;
 
2221
}
 
2222
 
 
2223
    int64_t ptsForce = -1;
 
2224
 
 
2225
    if (softStartTrigger
 
2226
      && !stillImageData)
 
2227
    {
 
2228
      softStartNoMetronom = (sstNoMetronom == softStartTrigger);
 
2229
      softStartTrigger = sstNone;
 
2230
 
 
2231
      softStartState = sInitiateSequence;
 
2232
//fprintf(stderr, "/////////////////////////////\n");
 
2233
//      ::fprintf(stderr, "#(%d,%d)", ::getpid(), pthread_self());
 
2234
    }
 
2235
 
 
2236
    if (stillImageData)
 
2237
    {
 
2238
      softStartLastSpeed = -1;
 
2239
    }
 
2240
    else if (softStartState > sIdle)
 
2241
    {
 
2242
      timeval tv;
 
2243
      ::gettimeofday(&tv, 0);
 
2244
 
 
2245
      const double now = (tv.tv_sec + tv.tv_usec / 1.0e+6);
 
2246
 
 
2247
      if (softStartState == sInitiateSequence)
 
2248
      {
 
2249
        xfprintf(stderr, "[");
 
2250
      
 
2251
        softStartDuration = m_settings.GetModeParams()->m_prebufferFrames / 25.0;
 
2252
        
 
2253
        softStartTime = now;        
 
2254
        
 
2255
        softStartSpeedChangeTime = -1;
 
2256
        softStartLastSpeed = -1;
 
2257
        softStartPtsVdr = -1;
 
2258
        softStartHitPoll = 0;
 
2259
 
 
2260
        softStartState = sStartSequence;
 
2261
 
 
2262
        vpts = -1;
 
2263
        apts = -1;
 
2264
        extra0 = 0;
 
2265
        extra = 0;
 
2266
 
 
2267
        useApts = 1;
 
2268
        
 
2269
        seenAudio = false;
 
2270
        seenVideo = false;
 
2271
        seenApts = false;
 
2272
        seenVpts = false;
 
2273
 
 
2274
        vdrPTSLast = -2;
 
2275
        vdrAptsLast = -1;
 
2276
        vdrVptsLast = -1;
 
2277
        
 
2278
        vdrAptsCalced = -1;
 
2279
        vdrVptsCalced = -1;
 
2280
        vdrAduration = -1;
 
2281
        vdrVduration = -1;
 
2282
 
 
2283
        vdrVptsBuffered[ 0 ] = -1;
 
2284
        vdrVptsBuffered[ 1 ] = -1;
 
2285
 
 
2286
        vdrTime100 = -1;
 
2287
        vdrTime100reload = false;
 
2288
 
 
2289
        gotQ1 = false;
 
2290
        hystQ = hystQ1 = 90000 * m_settings.GetModeParams()->m_prebufferHysteresis / 25;
 
2291
      }
 
2292
 
 
2293
      {
 
2294
        char packetType = 0;
 
2295
        char packetTypeOnce = 0;
 
2296
 
 
2297
        if (isVideo)
 
2298
        {
 
2299
          if (!seenVideo)
 
2300
          {
 
2301
            seenVideo = true;
 
2302
//            ::fprintf(stderr, "seen video\n");
 
2303
//            xfprintf(stderr, "v");
 
2304
            packetTypeOnce = 'v';
 
2305
          }
 
2306
 
 
2307
          packetType = 'v';
 
2308
        }
 
2309
        else if (isAudio)
 
2310
        {
 
2311
          if (!seenAudio)
 
2312
          {
 
2313
            audioSeen = true;
 
2314
            seenAudio = true;
 
2315
//            ::fprintf(stderr, "seen audio\n");
 
2316
//            xfprintf(stderr, "a");
 
2317
            packetTypeOnce = 'a';
 
2318
          }
 
2319
 
 
2320
          packetType = 'a';
 
2321
        }
 
2322
        
 
2323
        int64_t pts = 0;
 
2324
        if (getPTS(Data, Length, pts, isVideo, isAudio, vdrVptsCalced, vdrAptsCalced, vdrVduration, vdrAduration, vdrVptsBuffered))
 
2325
        {
 
2326
          ptsForce = pts;
 
2327
 
 
2328
          if (isVideo)
 
2329
          {
 
2330
            if (!seenVpts)
 
2331
            {
 
2332
              seenVpts = true;
 
2333
//              ::fprintf(stderr, "seen video pts\n");
 
2334
//              xfprintf(stderr, "V");
 
2335
              packetTypeOnce = 'V';
 
2336
            }
 
2337
 
 
2338
            packetType = 'V';
 
2339
            
 
2340
            vpts = pts;
 
2341
 
 
2342
            if (apts > -1)
 
2343
            {
 
2344
              int64_t delta = vpts - apts;
 
2345
              if (delta < 0)
 
2346
                delta = - delta;
 
2347
 
 
2348
              if (extra0 < delta)
 
2349
              {
 
2350
                extra0 = delta;
 
2351
 
 
2352
//                ::fprintf(stderr, "max. A/V delta: %lld pts => total extra buffering: %d frames", extra0, (int)(extra0 * 25 / 90000));
 
2353
 
 
2354
                extra = extra0;
 
2355
                
 
2356
                if (extra > extra_max)
 
2357
                {
 
2358
                  extra = extra_max;
 
2359
 
 
2360
//                  ::fprintf(stderr, ", limited to %d frames", (int)(extra * 25 / 90000));
 
2361
                }       
 
2362
 
 
2363
//              ::fprintf(stderr, "\n");
 
2364
                if (oldMode)
 
2365
                  xfprintf(stderr, "+%d", (int)(extra * 25 / 90000));
 
2366
              }
 
2367
            }
 
2368
 
 
2369
//            ::fprintf(stderr, "video: v: %lld, a: %lld, d: %lld, e: %lld\n", vpts, apts, vpts - apts, extra);
 
2370
          }
 
2371
          else if (isAudio)
 
2372
          {
 
2373
            if (!seenApts)
 
2374
            {
 
2375
              seenApts = true;
 
2376
//              ::fprintf(stderr, "seen audio pts\n");
 
2377
//              xfprintf(stderr, "A");
 
2378
              packetTypeOnce = 'A';
 
2379
            }
 
2380
            
 
2381
            packetType = 'A';
 
2382
 
 
2383
            apts = pts;
 
2384
            
 
2385
            if (vpts > -1)
 
2386
            {
 
2387
              int64_t delta = vpts - apts;
 
2388
              if (delta < 0)
 
2389
                delta = - delta;
 
2390
 
 
2391
              if (extra0 < delta)
 
2392
              {
 
2393
                extra0 = delta;
 
2394
                
 
2395
//                ::fprintf(stderr, "max. A/V delta: %lld pts => total extra buffering: %d frames", extra0, (int)(extra0 * 25 / 90000));
 
2396
 
 
2397
                extra = extra0;
 
2398
                
 
2399
                if (extra > extra_max)
 
2400
                {
 
2401
                  extra = extra_max;
 
2402
 
 
2403
//                  ::fprintf(stderr, ", limited to %d frames", (int)(extra * 25 / 90000));
 
2404
                }       
 
2405
 
 
2406
//              ::fprintf(stderr, "\n");
 
2407
                if (oldMode)
 
2408
                  xfprintf(stderr, "+%d", (int)(extra * 25 / 90000));
 
2409
              }
 
2410
            }
 
2411
 
 
2412
//            ::fprintf(stderr, "audio: v: %lld, a: %lld, d: %lld, e: %lld\n", vpts, apts, vpts - apts, extra);
 
2413
          }
 
2414
        }
 
2415
 
 
2416
//xfprintf(stderr, "%s%c", getFrameType(Data, Length), packetType); packetTypeOnce = 0; //ZZZ
 
2417
//
 
2418
        if (packetTypeOnce)
 
2419
          xfprintf(stderr, "%c", packetTypeOnce);
 
2420
      }
 
2421
 
 
2422
      if (seenVideo && !seenVpts
 
2423
          || seenAudio && !seenApts)
 
2424
      {
 
2425
        softStartTime = now;
 
2426
      }
 
2427
      
 
2428
      if (softStartState >= sStartSequence)
 
2429
      {
 
2430
        if (isVideo)
 
2431
          useApts = false;
 
2432
        
 
2433
        if (useApts
 
2434
            || isVideo)
 
2435
        {
 
2436
          softStartPtsVdr = ptsForce;
 
2437
//          getPTS(Data, Length, softStartPtsVdr);
 
2438
 
 
2439
          if (softStartPtsVdr != -1)
 
2440
          {
 
2441
            int64_t ptsXine = -1;
 
2442
            m_xineLib.execFuncGetPTS(ptsXine);
 
2443
            
 
2444
            const int64_t delta = (ptsXine != -1) ? (softStartPtsVdr - ptsXine) : 0;
 
2445
            if (softStartState == sStartSequence
 
2446
                || delta < -softStartLogPtsDelta
 
2447
                || delta > +softStartLogPtsDelta)
 
2448
            {
 
2449
//              if (softStartState != sStartSequence)
 
2450
//                ::fprintf(stderr, "SoftStart: ptsVdr: %lld, ptsXine: %lld, delta: %lld\n", softStartPtsVdr, ptsXine, delta);
 
2451
 
 
2452
//AAA              m_xineLib.execFuncStart();
 
2453
//AAA              m_xineLib.execFuncWait();
 
2454
 
 
2455
              if (!softStartNoMetronom)
 
2456
              {
 
2457
                xfprintf(stderr, "M");
 
2458
                
 
2459
//ZZZ                m_xineLib.execFuncMetronom(softStartPtsVdr);
 
2460
//ZZZ                m_xineLib.execFuncWait();
 
2461
              }
 
2462
              
 
2463
              softStartTime = now;
 
2464
              
 
2465
              softStartState = sContinueSequence;
 
2466
            }
 
2467
          }
 
2468
        }
 
2469
      }
 
2470
        
 
2471
//      if (softStartState <= sStartSequence)
 
2472
//        stripPTSandDTS((uchar *)Data, Length);
 
2473
 
 
2474
      m_xineLib.execFuncFirstFrame();
 
2475
 
 
2476
      int64_t vdrPTS = -1;
 
2477
 
 
2478
      if (seenVideo && vpts <= -1
 
2479
        || seenAudio && apts <= -1)
 
2480
      {
 
2481
      }
 
2482
      else if (vpts > -1)
 
2483
      {
 
2484
        if (apts > -1 && vpts > apts)
 
2485
          vdrPTS = apts;
 
2486
        else
 
2487
          vdrPTS = vpts;
 
2488
      }
 
2489
      else if (apts > -1)
 
2490
        vdrPTS = apts;
 
2491
 
 
2492
      int64_t xinePTS = -1;
 
2493
 
 
2494
      m_xineLib.execFuncGetPTS(xinePTS);
 
2495
 
 
2496
      const double totalDuration = (softStartDuration + extra / 90000.0);
 
2497
      const double q = oldMode ? ((now - softStartTime) / totalDuration) : softStartCalcQ(vdrPTS, xinePTS); 
 
2498
      double p = softStartCalcSpeed(q);
 
2499
     
 
2500
      if (!oldMode)
 
2501
      {
 
2502
        if (vdrPTSLast == vdrPTS || vdrVptsLast > vpts || vdrAptsLast > apts)
 
2503
          p = softStartLastSpeed / 100;
 
2504
        else
 
2505
          vdrPTSLast = vdrPTS;
 
2506
 
 
2507
        if (apts != vdrAptsLast || vpts != vdrVptsLast)
 
2508
        {
 
2509
//          xfprintf(stderr, "p: %.3lf, DA: %lld, DV: %lld, DC: %lld\n", p, (apts > -1) ? (apts - xinePTS) : -1, (vpts > -1) ? (vpts - xinePTS) : -1, (vdrPTS > - 1) ? (vdrPTS - xinePTS) : -1);
 
2510
//          xfprintf(stderr, "(%.1lf|%.1lf)", 25 * ((apts > -1) ? ((apts - xinePTS) / 90000.0) : 0.0), 25 * ((vpts > -1) ? ((vpts - xinePTS) / 90000.0) : 0.0));
 
2511
        }
 
2512
 
 
2513
        vdrVptsLast = vpts;
 
2514
        vdrAptsLast = apts;
 
2515
      }
 
2516
 
 
2517
      double speed = (p > 0) ? (100.0 * p) : 12.5;
 
2518
         
 
2519
      if (speed >= 100.0 || xinePTS == -1)
 
2520
      { 
 
2521
        bool newlineRequired = false;
 
2522
           
 
2523
        if (vdrTime100 < 0)
 
2524
        {
 
2525
ttt6 = tNow();
 
2526
/*
 
2527
fprintf(stderr, "+++++ %.3lf ms, %.3lf ms, %.3lf ms, (%.3lf ms, %.3lf ms, %.3lf ms) +++++\n"
 
2528
, (ttt1 - ttt0) * 1000.0
 
2529
, (ttt2 - ttt1) * 1000.0
 
2530
, (ttt3 - ttt2) * 1000.0
 
2531
, (ttt4 - ttt3) * 1000.0
 
2532
, (ttt5 - ttt3) * 1000.0
 
2533
, (ttt6 - ttt3) * 1000.0
 
2534
);
 
2535
*/
 
2536
          vdrTime100 = now;
 
2537
 
 
2538
          xfprintf(stderr, "]");
 
2539
          newlineRequired = true;
 
2540
        }
 
2541
        
 
2542
        speed = 100.0;
 
2543
 
 
2544
        if (vdrTime100reload)
 
2545
        {
 
2546
          vdrTime100reload = false;
 
2547
 
 
2548
          vdrTime100 = now;
 
2549
        }
 
2550
      
 
2551
        if (xinePTS < 0)
 
2552
          softStartState = sIdle;
 
2553
        else if ((now - vdrTime100) >= m_settings.GetModeParams()->m_monitoringDuration)
 
2554
        {
 
2555
          if (m_settings.GetModeParams()->MonitoringContinuous())
 
2556
            hystQ1 = 90000 * (m_settings.GetModeParams()->m_prebufferHysteresis - 1) / 25;
 
2557
          else
 
2558
            softStartState = sIdle;
 
2559
        }
 
2560
 
 
2561
        if ((softStartState == sIdle || speed != softStartLastSpeed) && vdrPTS > -1 && xinePTS > -1)
 
2562
        {
 
2563
          xfprintf(stderr, "buffered %.1lf frames (v:%.1lf, a:%.1lf)", (vdrPTS - xinePTS) / 90000.0 * 25, (vpts > -1) ? ((vpts - xinePTS) / 90000.0 * 25) : 0.0, (apts > -1) ? ((apts - xinePTS) / 90000.0 * 25) : 0.0);
 
2564
          if (softStartState == sIdle)
 
2565
            xfprintf(stderr, " <<<<<");
 
2566
          newlineRequired = true;
 
2567
        }
 
2568
        
 
2569
        if (newlineRequired)
 
2570
          xfprintf(stderr, "\n");
 
2571
      }
 
2572
          
 
2573
      if (100.0 == speed
 
2574
          || (speed != softStartLastSpeed
 
2575
              && (!oldMode || (now - softStartSpeedChangeTime) > (totalDuration / softStartMaxSpeedChanges))))
 
2576
      {
 
2577
        softStartSpeedChangeTime = now;
 
2578
        
 
2579
//        fprintf(stderr, "slowstart: %lg, %lg\n", speed, p);
 
2580
 
 
2581
        m_xineLib.execFuncSetSpeed(speed);
 
2582
        m_xineLib.execFuncWait();
 
2583
 
 
2584
//        if (100.0 == speed)
 
2585
//          m_xineLib.execFuncSetPrebuffer(m_settings.GetModeParams()->m_prebufferFrames);
 
2586
        
 
2587
        softStartLastSpeed = speed;
 
2588
      }
 
2589
    }
 
2590
    
 
2591
    jw = false;
 
2592
    
 
2593
//    fprintf(stderr, "v");
 
2594
    
 
2595
    if (ts)
 
2596
    {
 
2597
      stripPTSandDTS((uchar *)Data, Length);
 
2598
    }
 
2599
    else if (0) //ZZZ
 
2600
    {
 
2601
      int64_t pts = 0;
 
2602
      
 
2603
      if (np && getPTS(Data, Length, pts))
 
2604
      {
 
2605
        np = false;
 
2606
        
 
2607
//        fprintf(stderr, "M %lld %llx\n", pts);
 
2608
        m_xineLib.execFuncMetronom(pts);
 
2609
        m_xineLib.execFuncWait();
 
2610
      }
 
2611
    }
 
2612
        
 
2613
    int r = PlayCommon1(Data, Length, ptsForce);
 
2614
 
 
2615
//    fprintf(stderr, "V");
 
2616
 
 
2617
    return r;
 
2618
  }
 
2619
 
 
2620
  int cXineDevice::PlayCommon1(const uchar *Data, int Length, int64_t ptsForce)
 
2621
  {
 
2622
/*
 
2623
if (blahblah)
 
2624
{
 
2625
  fprintf(stderr, "blahblah C1");
 
2626
  for (int i = 0; i < 50 && i < Length; i++)
 
2627
    fprintf(stderr, " %02x", Data[ i ]);
 
2628
  fprintf(stderr, "\n");
 
2629
}
 
2630
*/
 
2631
    if (oldMode)
 
2632
      return PlayCommon2(Data, Length, ptsForce);
 
2633
 
 
2634
    struct sBuffer
 
2635
    {
 
2636
      sBuffer *next;
 
2637
      int length;
 
2638
      int64_t ptsForce;
 
2639
      uchar data[1];
 
2640
    };
 
2641
 
 
2642
    static sBuffer *pHead = 0;
 
2643
    static sBuffer *pTail = 0;
 
2644
    static int bufCount = 0;
 
2645
 
 
2646
    while (!doClear && pHead)
 
2647
    {
 
2648
      if (sIdle != softStartState)
 
2649
      {
 
2650
        cPoller p;
 
2651
        if (!m_xineLib.Poll(p, -1))
 
2652
          break;
 
2653
      }
 
2654
 
 
2655
      int r = PlayCommon2(pHead->data, pHead->length, pHead->ptsForce);
 
2656
      if (r > 0)
 
2657
      {
 
2658
        sBuffer *p = pHead;
 
2659
        pHead = pHead->next;
 
2660
        ::free(p);
 
2661
//fprintf(stderr, "bufCount: %d\n", --bufCount);
 
2662
      }
 
2663
      else if (r < 0)
 
2664
      {
 
2665
        while (pHead)
 
2666
        {
 
2667
          sBuffer *p = pHead;
 
2668
          pHead = pHead->next;
 
2669
          ::free(p);
 
2670
        }
 
2671
 
 
2672
        bufCount = 0;
 
2673
        pTail = 0;
 
2674
//fprintf(stderr, "--- bufCount: %d\n", bufCount);
 
2675
        return r;
 
2676
      }
 
2677
      else
 
2678
        break;
 
2679
    }
 
2680
    
 
2681
    if (doClear)
 
2682
    {
 
2683
      while (pHead)
 
2684
      {
 
2685
        sBuffer *p = pHead;
 
2686
        pHead = pHead->next;
 
2687
        ::free(p);
 
2688
      }
 
2689
 
 
2690
      bufCount = 0;
 
2691
      pTail = 0;
 
2692
      doClear = false;
 
2693
//fprintf(stderr, "=== bufCount: %d\n", bufCount);
 
2694
 
 
2695
//      return Length;
 
2696
    }
 
2697
 
 
2698
    if (!pHead)
 
2699
    {
 
2700
      pTail = 0;
 
2701
      
 
2702
      do // ... while (false);
 
2703
      {
 
2704
        if (sIdle != softStartState)
 
2705
        {
 
2706
          cPoller p;
 
2707
          if (!m_xineLib.Poll(p, -1))
 
2708
            break;
 
2709
//fprintf(stderr, "### bufCount: %d\n", bufCount);
 
2710
        }
 
2711
 
 
2712
        return PlayCommon2(Data, Length, ptsForce);
 
2713
      }
 
2714
      while (false);
 
2715
    }
 
2716
 
 
2717
    sBuffer *p = (sBuffer *)::malloc(sizeof (sBuffer) - sizeof (p->data) + Length);
 
2718
    if (!p)
 
2719
      return 0;
 
2720
 
 
2721
    p->next = 0;
 
2722
    p->length = Length;
 
2723
    p->ptsForce = ptsForce;
 
2724
    memcpy(&p->data, Data, Length);
 
2725
 
 
2726
    if (!pTail)
 
2727
      pHead = pTail = p;
 
2728
    else
 
2729
    {
 
2730
      pTail->next = p;
 
2731
      pTail = p;
 
2732
    }
 
2733
 
 
2734
//fprintf(stderr, "*** bufCount: %d\n", ++bufCount);
 
2735
    return Length;
 
2736
  }
 
2737
 
 
2738
  static uchar jumboPESdata[ 6 + 0xffff ];
 
2739
  static uchar *jumboPEStailData = 0;
 
2740
  
 
2741
  static bool mkJumboPES(const uchar *Data, int Length)
 
2742
  {
 
2743
    int origJumboPESsize = jumboPESsize;
 
2744
    jumboPESsize = 0;
 
2745
    
 
2746
    if (Length < 9)
 
2747
      VERBOSE_RETURN0(false);
 
2748
 
 
2749
    if (0x00 != Data[ 0 ])
 
2750
      VERBOSE_RETURN0(false);
 
2751
    
 
2752
    if (0x00 != Data[ 1 ])
 
2753
      VERBOSE_RETURN0(false);
 
2754
    
 
2755
    if (0x01 != Data[ 2 ])
 
2756
      VERBOSE_RETURN0(false);
 
2757
    
 
2758
    if (0xbd != Data[ 3 ])
 
2759
      VERBOSE_RETURN0(false);
 
2760
 
 
2761
    int l = Data[ 4 ] * 256 + Data[ 5 ];    
 
2762
    if ((6 + l) != Length)
 
2763
    {
 
2764
      const uchar *data = Data + (6 + l);
 
2765
      int length = Length - (6 + l);
 
2766
      
 
2767
      if (length < 6)
 
2768
        VERBOSE_RETURN3(false);
 
2769
      
 
2770
      if (0x00 != data[ 0 ])
 
2771
        VERBOSE_RETURN3(false);
 
2772
      
 
2773
      if (0x00 != data[ 1 ])
 
2774
        VERBOSE_RETURN3(false);
 
2775
      
 
2776
      if (0x01 != data[ 2 ])
 
2777
        VERBOSE_RETURN3(false);
 
2778
      
 
2779
      if (0xbe != data[ 3 ])
 
2780
        VERBOSE_RETURN3(false);
 
2781
 
 
2782
      int L = data[ 4 ] * 256 + data[ 5 ];    
 
2783
      if ((6 + L) != length)
 
2784
        VERBOSE_RETURN3(false);
 
2785
 
 
2786
      // ignore padding
 
2787
      Length -= length;
 
2788
    }
 
2789
/*
 
2790
    for (int i = 0; i < 20; i++)
 
2791
      fprintf(stderr, "%02x ", Data[ i ]);
 
2792
    fprintf(stderr, "\n");
 
2793
*/    
 
2794
    bool cont = (0x80 == Data[ 6 ]
 
2795
                 && 0x00 == Data[ 7 ]
 
2796
                 && 0x00 == Data[ 8 ]);
 
2797
 
 
2798
    if (cont
 
2799
        && Length >= 6 + 3 + 5
 
2800
        && Data[  9 ] == 0x0b
 
2801
        && Data[ 10 ] == 0x77
 
2802
        && frameSizes[ Data[ 13 ] ] > 0)
 
2803
    {
 
2804
      cont = false;
 
2805
    }
 
2806
    
 
2807
    if (!cont
 
2808
      || 0 == origJumboPESsize)
 
2809
    {
 
2810
      if (0 != origJumboPESsize)
 
2811
        VERBOSE_RETURN0(false);
 
2812
 
 
2813
      if ((origJumboPESsize + Length - 0) > (6 + 0xffff))
 
2814
        VERBOSE_RETURN0(false);
 
2815
 
 
2816
      if (jumboPEStail > 0)
 
2817
      {
 
2818
        int headerSize = 6 + 3 + Data[ 8 ];
 
2819
        ::memcpy(&jumboPESdata[ origJumboPESsize ], &Data[ 0 ], headerSize);
 
2820
 
 
2821
        ::memmove(&jumboPESdata[ origJumboPESsize + headerSize ], jumboPEStailData, jumboPEStail);
 
2822
        
 
2823
        ::memcpy(&jumboPESdata[ origJumboPESsize + headerSize + jumboPEStail ], &Data[ headerSize ], Length - headerSize);
 
2824
        
 
2825
        origJumboPESsize += headerSize + jumboPEStail + Length - headerSize;
 
2826
 
 
2827
        jumboPEStail = 0;
 
2828
        jumboPEStailData = 0;
 
2829
 
 
2830
        //FIXME: PTS should be adjusted to take care of jumboPEStail's duration.
 
2831
        //       Otherwise there is a certain jitter on audio duration <=> PTS.
 
2832
      }
 
2833
      else
 
2834
      {
 
2835
        ::memcpy(&jumboPESdata[ origJumboPESsize ], &Data[ 0 ], Length - 0);
 
2836
        origJumboPESsize += Length - 0;
 
2837
      }
 
2838
    }
 
2839
    else
 
2840
    {
 
2841
      if (0 == origJumboPESsize)
 
2842
        VERBOSE_RETURN0(false);
 
2843
      
 
2844
      if ((origJumboPESsize + Length - 9) > (6 + 0xffff))
 
2845
        VERBOSE_RETURN0(false);
 
2846
        
 
2847
      ::memcpy(&jumboPESdata[ origJumboPESsize ], &Data[ 9 ], Length - 9);
 
2848
      origJumboPESsize += Length - 9;
 
2849
    }
 
2850
 
 
2851
    if (0 == origJumboPESsize)
 
2852
      VERBOSE_RETURN0(false);
 
2853
 
 
2854
    jumboPESsize = origJumboPESsize;
 
2855
 
 
2856
    if (2048 == Length)
 
2857
    {
 
2858
//      fprintf(stderr, " b %d", jumboPESsize);
 
2859
      return false;
 
2860
    }
 
2861
    
 
2862
    jumboPESdata[ 4 ] = (jumboPESsize - 6) >> 8;
 
2863
    jumboPESdata[ 5 ] = (jumboPESsize - 6) & 0xff;
 
2864
    
 
2865
//    fprintf(stderr, " B %d", jumboPESsize);
 
2866
    return true;
 
2867
  }
 
2868
 
 
2869
  static int initFrameSizes()
 
2870
  {
 
2871
    ::memset(frameSizes, 0, sizeof (frameSizes));
 
2872
 
 
2873
    // fs = 48 kHz
 
2874
    frameSizes[ 0x00 ] =   64;
 
2875
    frameSizes[ 0x01 ] =   64;
 
2876
    frameSizes[ 0x02 ] =   80;
 
2877
    frameSizes[ 0x03 ] =   80;
 
2878
    frameSizes[ 0x04 ] =   96;
 
2879
    frameSizes[ 0x05 ] =   96;
 
2880
    frameSizes[ 0x06 ] =  112;
 
2881
    frameSizes[ 0x07 ] =  112;
 
2882
    frameSizes[ 0x08 ] =  128;
 
2883
    frameSizes[ 0x09 ] =  128;
 
2884
    frameSizes[ 0x0a ] =  160;
 
2885
    frameSizes[ 0x0b ] =  160;
 
2886
    frameSizes[ 0x0c ] =  192;
 
2887
    frameSizes[ 0x0d ] =  192;
 
2888
    frameSizes[ 0x0e ] =  224;
 
2889
    frameSizes[ 0x0f ] =  224;
 
2890
    frameSizes[ 0x10 ] =  256;
 
2891
    frameSizes[ 0x11 ] =  256;
 
2892
    frameSizes[ 0x12 ] =  320;
 
2893
    frameSizes[ 0x13 ] =  320;
 
2894
    frameSizes[ 0x14 ] =  384;
 
2895
    frameSizes[ 0x15 ] =  384;
 
2896
    frameSizes[ 0x16 ] =  448;
 
2897
    frameSizes[ 0x17 ] =  448;
 
2898
    frameSizes[ 0x18 ] =  512;
 
2899
    frameSizes[ 0x19 ] =  512;
 
2900
    frameSizes[ 0x1a ] =  640;
 
2901
    frameSizes[ 0x1b ] =  640;
 
2902
    frameSizes[ 0x1c ] =  768;
 
2903
    frameSizes[ 0x1d ] =  768;
 
2904
    frameSizes[ 0x1e ] =  896;
 
2905
    frameSizes[ 0x1f ] =  896;
 
2906
    frameSizes[ 0x20 ] = 1024;
 
2907
    frameSizes[ 0x21 ] = 1024;
 
2908
    frameSizes[ 0x22 ] = 1152;
 
2909
    frameSizes[ 0x23 ] = 1152;
 
2910
    frameSizes[ 0x24 ] = 1280;
 
2911
    frameSizes[ 0x25 ] = 1280;
 
2912
    
 
2913
    // fs = 44.1 kHz
 
2914
    frameSizes[ 0x40 ] =   69;
 
2915
    frameSizes[ 0x41 ] =   70;
 
2916
    frameSizes[ 0x42 ] =   87;
 
2917
    frameSizes[ 0x43 ] =   88;
 
2918
    frameSizes[ 0x44 ] =  104;
 
2919
    frameSizes[ 0x45 ] =  105;
 
2920
    frameSizes[ 0x46 ] =  121;
 
2921
    frameSizes[ 0x47 ] =  122;
 
2922
    frameSizes[ 0x48 ] =  139;
 
2923
    frameSizes[ 0x49 ] =  140;
 
2924
    frameSizes[ 0x4a ] =  174;
 
2925
    frameSizes[ 0x4b ] =  175;
 
2926
    frameSizes[ 0x4c ] =  208;
 
2927
    frameSizes[ 0x4d ] =  209;
 
2928
    frameSizes[ 0x4e ] =  243;
 
2929
    frameSizes[ 0x4f ] =  244;
 
2930
    frameSizes[ 0x50 ] =  278;
 
2931
    frameSizes[ 0x51 ] =  279;
 
2932
    frameSizes[ 0x52 ] =  348;
 
2933
    frameSizes[ 0x53 ] =  349;
 
2934
    frameSizes[ 0x54 ] =  417;
 
2935
    frameSizes[ 0x55 ] =  418;
 
2936
    frameSizes[ 0x56 ] =  487;
 
2937
    frameSizes[ 0x57 ] =  488;
 
2938
    frameSizes[ 0x58 ] =  557;
 
2939
    frameSizes[ 0x59 ] =  558;
 
2940
    frameSizes[ 0x5a ] =  696;
 
2941
    frameSizes[ 0x5b ] =  697;
 
2942
    frameSizes[ 0x5c ] =  835;
 
2943
    frameSizes[ 0x5d ] =  836;
 
2944
    frameSizes[ 0x5e ] =  975;
 
2945
    frameSizes[ 0x5f ] =  976;
 
2946
    frameSizes[ 0x60 ] = 1114;
 
2947
    frameSizes[ 0x61 ] = 1115;
 
2948
    frameSizes[ 0x62 ] = 1253;
 
2949
    frameSizes[ 0x63 ] = 1254;
 
2950
    frameSizes[ 0x64 ] = 1393;
 
2951
    frameSizes[ 0x65 ] = 1394;
 
2952
    
 
2953
    // fs = 32 kHz
 
2954
    frameSizes[ 0x80 ] =   96;
 
2955
    frameSizes[ 0x81 ] =   96;
 
2956
    frameSizes[ 0x82 ] =  120;
 
2957
    frameSizes[ 0x83 ] =  120;
 
2958
    frameSizes[ 0x84 ] =  144;
 
2959
    frameSizes[ 0x85 ] =  144;
 
2960
    frameSizes[ 0x86 ] =  168;
 
2961
    frameSizes[ 0x87 ] =  168;
 
2962
    frameSizes[ 0x88 ] =  192;
 
2963
    frameSizes[ 0x89 ] =  192;
 
2964
    frameSizes[ 0x8a ] =  240;
 
2965
    frameSizes[ 0x8b ] =  240;
 
2966
    frameSizes[ 0x8c ] =  288;
 
2967
    frameSizes[ 0x8d ] =  288;
 
2968
    frameSizes[ 0x8e ] =  336;
 
2969
    frameSizes[ 0x8f ] =  336;
 
2970
    frameSizes[ 0x90 ] =  384;
 
2971
    frameSizes[ 0x91 ] =  384;
 
2972
    frameSizes[ 0x92 ] =  480;
 
2973
    frameSizes[ 0x93 ] =  480;
 
2974
    frameSizes[ 0x94 ] =  576;
 
2975
    frameSizes[ 0x95 ] =  576;
 
2976
    frameSizes[ 0x96 ] =  672;
 
2977
    frameSizes[ 0x97 ] =  672;
 
2978
    frameSizes[ 0x98 ] =  768;
 
2979
    frameSizes[ 0x99 ] =  768;
 
2980
    frameSizes[ 0x9a ] =  960;
 
2981
    frameSizes[ 0x9b ] =  960;
 
2982
    frameSizes[ 0x9c ] = 1152;
 
2983
    frameSizes[ 0x9d ] = 1152;
 
2984
    frameSizes[ 0x9e ] = 1344;
 
2985
    frameSizes[ 0x9f ] = 1344;
 
2986
    frameSizes[ 0xa0 ] = 1536;
 
2987
    frameSizes[ 0xa1 ] = 1536;
 
2988
    frameSizes[ 0xa2 ] = 1728;
 
2989
    frameSizes[ 0xa3 ] = 1728;
 
2990
    frameSizes[ 0xa4 ] = 1920;
 
2991
    frameSizes[ 0xa5 ] = 1920;
 
2992
    
 
2993
    return 0;
 
2994
  };
 
2995
  
 
2996
#if APIVERSNUM < 10318
 
2997
 
 
2998
  void cXineDevice::PlayAudio(const uchar *Data, int Length)
 
2999
  {
 
3000
    cDevice::PlayAudio(Data, Length);
 
3001
 
 
3002
    PlayAudioCommon(Data, Length);
 
3003
  }
 
3004
 
 
3005
#else
 
3006
 
 
3007
  int cXineDevice::GetAudioChannelDevice(void)
 
3008
  {
 
3009
    return m_audioChannel;
 
3010
  }
 
3011
 
 
3012
  void cXineDevice::SetAudioChannelDevice(int AudioChannel)
 
3013
  {
 
3014
    xfprintf(stderr, "SetAudioChannelDevice: %d\n", AudioChannel);
 
3015
 
 
3016
    m_audioChannel = AudioChannel;
 
3017
 
 
3018
    m_xineLib.execFuncSelectAudio(m_audioChannel);
 
3019
  }
 
3020
 
 
3021
  void cXineDevice::SetDigitalAudioDevice(bool On)
 
3022
  {
 
3023
    xfprintf(stderr, "SetDigitalAudioDevice: %d\n", On);
 
3024
 
 
3025
    m_xineLib.execFuncSelectAudio(On ? -1 : m_audioChannel);
 
3026
 
 
3027
    if (pmNone == pm)
 
3028
      return;
 
3029
 
 
3030
    if (m_settings.LiveTV()
 
3031
      && !audioSeen)
 
3032
    {
 
3033
      if (softStartState == sIdle)
 
3034
        softStartTrigger = sstNoMetronom;
 
3035
      
 
3036
      return;
 
3037
    }
 
3038
    
 
3039
    m_xineLib.pause();
 
3040
//xzabc = 1;    
 
3041
    jumboPESsize = 0;
 
3042
    jumboPEStail = 0;
 
3043
 
 
3044
    if (f)
 
3045
        m_xineLib.execFuncSetSpeed(100.0);
 
3046
//double t0 = tNow();
 
3047
    if (m_settings.LiveTV()
 
3048
      || !foundVideo) // radio recording: audio channels are not related
 
3049
    {
 
3050
      ptsV = ptsA = ptsP = ptsD = -1;
 
3051
    
 
3052
      m_xineLib.execFuncClear(-3);
 
3053
 
 
3054
//      if (!foundVideo)
 
3055
//        m_xineLib.execFuncStart();
 
3056
//      np = true;
 
3057
    }
 
3058
    
 
3059
    m_xineLib.execFuncResetAudio();
 
3060
 
 
3061
    if (f)
 
3062
        m_xineLib.execFuncSetSpeed(0.0);
 
3063
    
 
3064
    m_xineLib.execFuncWait();
 
3065
//xzabc = 2;
 
3066
    m_xineLib.pause(false);
 
3067
//double t1 = tNow(); fprintf(stderr, "!!!!!!! %.3lf ms\n", (t1 - t0) * 1000);
 
3068
    if (m_settings.LiveTV())
 
3069
      softStartTrigger = sstNoMetronom;
 
3070
    
 
3071
//fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");    
 
3072
  }
 
3073
 
 
3074
#if APIVERSNUM < 10342  
 
3075
 
 
3076
  int cXineDevice::PlayAudio(const uchar *Data, int Length)
 
3077
  {
 
3078
//    fprintf(stderr, " 0x%02x ", Data[ 3 ]);
 
3079
    return PlayAudioCommon(Data, Length);
 
3080
  }
 
3081
 
 
3082
#else
 
3083
  
 
3084
  int cXineDevice::PlayAudio(const uchar *Data, int Length, uchar /* Id */)
 
3085
  {
 
3086
//    fprintf(stderr, " 0x%02x ", Data[ 3 ]);
 
3087
    return PlayAudioCommon(Data, Length);
 
3088
  }
 
3089
 
 
3090
#endif
 
3091
#endif
 
3092
  
 
3093
  int cXineDevice::PlayAudioCommon(const uchar *Data, int Length)
 
3094
  {
 
3095
    if (ttt5 == 0) ttt5 = tNow();
 
3096
//    fprintf(stderr, " 0x%02x: %d ", Data[ 3 ], Data[4] * 256 + Data[5]);
 
3097
/*
 
3098
if (Data[ 3 ] == 0xd0) {
 
3099
  FILE *f = fopen("/tmp/d0", "ab");
 
3100
  fwrite(Data, Length, 1, f);
 
3101
  fclose(f);
 
3102
}
 
3103
*/
 
3104
    {
 
3105
      static int i = initFrameSizes();
 
3106
      (void)i;
 
3107
    }
 
3108
    
 
3109
store_frame(Data, Length, __LINE__);
 
3110
 
 
3111
    LOG_ME(::fprintf(stderr, "A");)
 
3112
    
 
3113
    if (f)
 
3114
    {      
 
3115
      LOG_ME(::fprintf(stderr, "<");)
 
3116
      return Length;
 
3117
    }
 
3118
    
 
3119
    if (pmNone == pm)
 
3120
    {
 
3121
      cMutexLock pmMutexLock(&m_pmMutex);
 
3122
 
 
3123
      if (pmNone == pm)
 
3124
        m_pmCondVar.Wait(m_pmMutex);
 
3125
    }
 
3126
 
 
3127
    int retVal = PlayAudio2(Data, Length);
 
3128
    
 
3129
    LOG_ME(::fprintf(stderr, "a"));
 
3130
 
 
3131
    return retVal;
 
3132
  }
 
3133
  
 
3134
  int cXineDevice::PlayAudio2(const uchar *Data, int Length)
 
3135
  {
 
3136
//    fprintf(stderr, "D");
 
3137
    
 
3138
    int done = 0;
 
3139
 
 
3140
    while (done < Length)
 
3141
    {
 
3142
      char ch = 'X';
 
3143
 
 
3144
      int id = 0x00;
 
3145
      
 
3146
      int todo = Length - done;
 
3147
      if (todo >= 6)
 
3148
      {
 
3149
        if (0x00 == Data[ done + 0 ]
 
3150
            && 0x00 == Data[ done + 1 ]
 
3151
            && 0x01 == Data[ done + 2 ])
 
3152
        {
 
3153
          id  = Data[ done + 3 ];
 
3154
          int len = Data[ done + 4 ] * 0x0100 + Data[ done + 5 ];
 
3155
 
 
3156
          if (todo >= (6 + len))
 
3157
          {
 
3158
            todo = (6 + len);
 
3159
 
 
3160
            if (0xbe == id)
 
3161
            {
 
3162
              done += todo;
 
3163
 
 
3164
//              ::fprintf(stderr, "x");
 
3165
              continue;
 
3166
            }
 
3167
 
 
3168
            ch = '.';            
 
3169
          }
 
3170
          else        
 
3171
          {
 
3172
            VERBOSE_NOP();
 
3173
            ch = '3';
 
3174
          }
 
3175
        }
 
3176
        else        
 
3177
        {
 
3178
          VERBOSE_NOP();
 
3179
          ch = '2';
 
3180
        }
 
3181
      }
 
3182
      else        
 
3183
      {
 
3184
        VERBOSE_NOP();
 
3185
        ch = '1';
 
3186
      }
 
3187
      
 
3188
//      ::fprintf(stderr, "%c", ch);
 
3189
 
 
3190
      int r;
 
3191
      
 
3192
      if (0xbd == id)
 
3193
        r = PlayAudio3(Data + done, todo);
 
3194
      else
 
3195
        r = PlayVideo3(Data + done, todo, false);
 
3196
        
 
3197
      if (r < 0)
 
3198
        return r;
 
3199
      
 
3200
      if (r != todo)
 
3201
        VERBOSE_NOP();
 
3202
                
 
3203
      done += r;
 
3204
    }
 
3205
    
 
3206
    return done;
 
3207
  }
 
3208
  
 
3209
  int cXineDevice::PlayAudio3(const uchar *Data, int Length)
 
3210
  {
 
3211
    resetScramblingControl(Data, Length);
 
3212
    
 
3213
store_frame(Data, Length, __LINE__);    
 
3214
/*    
 
3215
    ::fprintf(stderr, "l: %d\t", Length);
 
3216
    for (int i = 0; i < 20; i++)
 
3217
      ::fprintf(stderr, "%02x ", Data[ i ]);
 
3218
    ::fprintf(stderr, "\n");
 
3219
*/ 
 
3220
//    fprintf(stderr, "A");
 
3221
    
 
3222
    if (mkJumboPES(Data, Length))
 
3223
    {
 
3224
      int todo = jumboPESsize;
 
3225
      jumboPESsize = 0;
 
3226
 
 
3227
      dumpAudio("Audio", jumboPESdata, todo);
 
3228
 
 
3229
      bool dolby = false;
 
3230
      bool pcm = false;
 
3231
      
 
3232
      do
 
3233
      {
 
3234
        if (todo < (6 + 3 + 0 + 2))
 
3235
          break;
 
3236
        
 
3237
        if (0x00 != jumboPESdata[ 0 ]
 
3238
            || 0x00 != jumboPESdata[ 1 ]
 
3239
            || 0x01 != jumboPESdata[ 2 ]
 
3240
            || 0xbd != jumboPESdata[ 3 ])
 
3241
        {
 
3242
          break;
 
3243
        }
 
3244
 
 
3245
        int l = jumboPESdata[ 4 ] * 0x0100 + jumboPESdata[ 5 ];
 
3246
        if (l < (3 + 0 + 2))
 
3247
          break;
 
3248
 
 
3249
        if (todo < (6 + l))
 
3250
          break;
 
3251
 
 
3252
        int h = jumboPESdata[ 8 ];
 
3253
        if (l < (3 + h + 2))
 
3254
          break;
 
3255
 
 
3256
        if (0x0b == jumboPESdata[ 6 + 3 + h + 0 ]
 
3257
            && 0x77 == jumboPESdata[ 6 + 3 + h + 1 ])
 
3258
        {
 
3259
          if (l < (3 + h + 2 + 2 + 1))
 
3260
          {
 
3261
            VERBOSE_NOP();            
 
3262
            break;
 
3263
          }
 
3264
          
 
3265
          int frameStart = 6 + 3 + h;
 
3266
          bool failed = false;
 
3267
          
 
3268
          while (true)
 
3269
          {
 
3270
            int frameSize = 2 * frameSizes[ jumboPESdata[ frameStart + 4 ] ];
 
3271
            if (frameSize <= 0)
 
3272
            {
 
3273
              failed = true;
 
3274
              
 
3275
              xfprintf(stderr, "frame_size_code: 0x%02x\n", jumboPESdata[ frameStart + 4 ]);
 
3276
              VERBOSE_NOP();              
 
3277
              break;
 
3278
            }
 
3279
 
 
3280
            if (frameStart + frameSize > todo)
 
3281
              break;
 
3282
 
 
3283
            frameStart += frameSize;
 
3284
            
 
3285
            if (frameStart + 2 + 2 + 1 > todo)
 
3286
              break;
 
3287
 
 
3288
            if (0x0b != jumboPESdata[ frameStart + 0 ]
 
3289
                || 0x77 != jumboPESdata[ frameStart + 1 ])
 
3290
            {
 
3291
              failed = true;
 
3292
              
 
3293
              VERBOSE_NOP();
 
3294
              break;
 
3295
            }
 
3296
          }
 
3297
          
 
3298
          if (failed)
 
3299
            break;
 
3300
          
 
3301
          jumboPEStail = todo - frameStart;
 
3302
          jumboPEStailData = jumboPESdata + frameStart;
 
3303
 
 
3304
          todo = frameStart;
 
3305
 
 
3306
          jumboPESdata[ 4 + 0 ] = (todo - 6) >> 8;
 
3307
          jumboPESdata[ 4 + 1 ] = (todo - 6) & 0xff;
 
3308
          
 
3309
          dolby = true;
 
3310
store_frame(jumboPESdata, todo, __LINE__);    
 
3311
          break;
 
3312
        }
 
3313
 
 
3314
        if (0x80 == (0xf0 & jumboPESdata[ 6 + 3 + h + 0 ]))
 
3315
        {
 
3316
          dolby = true;
 
3317
          break;
 
3318
        }
 
3319
        
 
3320
        if (0xa0 == (0xf0 & jumboPESdata[ 6 + 3 + h + 0 ]))
 
3321
        {
 
3322
          pcm = true;
 
3323
          break;
 
3324
        }
 
3325
 
 
3326
        for (int i = 6 + 3 + h; i < todo - 2 - 2 - 1; i++)
 
3327
        {
 
3328
          if (0x0b == jumboPESdata[ i + 0 ]
 
3329
              && 0x77 == jumboPESdata[ i + 1 ]
 
3330
              && 0 != frameSizes[ jumboPESdata[ i + 4 ] ])
 
3331
          {
 
3332
            jumboPEStail = todo - i;
 
3333
            jumboPEStailData = jumboPESdata + i;
 
3334
          }
 
3335
        }
 
3336
      }
 
3337
      while (false);
 
3338
 
 
3339
      if (pcm
 
3340
          || (dolby && m_settings.AudioDolbyOn()))
 
3341
      {
 
3342
        int done = 0;
 
3343
        
 
3344
        while (done < todo)
 
3345
        {
 
3346
          int r = PlayCommon(jumboPESdata + done, todo - done, false);
 
3347
          if (r < 0)
 
3348
            return r;
 
3349
          
 
3350
//          fprintf(stderr, ".");
 
3351
          
 
3352
          done += r;
 
3353
        }
 
3354
 
 
3355
// Don't return done here as the remaining bytes were buffered elsewhere!
 
3356
//        return done;
 
3357
      }
 
3358
    }
 
3359
    else if (jumboPESsize == Length)
 
3360
    {
 
3361
      int todo = jumboPESsize;
 
3362
 
 
3363
      bool dolby = false;
 
3364
      bool pcm = false;
 
3365
      
 
3366
      do
 
3367
      {
 
3368
        if (todo < (6 + 3 + 0 + 2))
 
3369
          break;
 
3370
        
 
3371
        if (0x00 != jumboPESdata[ 0 ]
 
3372
            || 0x00 != jumboPESdata[ 1 ]
 
3373
            || 0x01 != jumboPESdata[ 2 ]
 
3374
            || 0xbd != jumboPESdata[ 3 ])
 
3375
        {
 
3376
          break;
 
3377
        }
 
3378
 
 
3379
        int l = jumboPESdata[ 4 ] * 0x0100 + jumboPESdata[ 5 ];
 
3380
        if (l < (3 + 0 + 2))
 
3381
          break;
 
3382
 
 
3383
        if (todo < (6 + l))
 
3384
          break;
 
3385
 
 
3386
        int h = jumboPESdata[ 8 ];
 
3387
        if (l < (3 + h + 2))
 
3388
          break;
 
3389
 
 
3390
        if (0x80 == (0xf0 & jumboPESdata[ 6 + 3 + h + 0 ]))
 
3391
        {
 
3392
          dolby = true;
 
3393
          break;
 
3394
        }
 
3395
        
 
3396
        if (0xa0 == (0xf0 & jumboPESdata[ 6 + 3 + h + 0 ]))
 
3397
        {
 
3398
          pcm = true;
 
3399
          break;
 
3400
        }
 
3401
      }
 
3402
      while (false);
 
3403
 
 
3404
      if (dolby || pcm)
 
3405
      {
 
3406
        dumpAudio("Audio", jumboPESdata, todo);
 
3407
 
 
3408
        jumboPESsize = 0;
 
3409
      }
 
3410
 
 
3411
      if (pcm
 
3412
          || (dolby && m_settings.AudioDolbyOn()))
 
3413
      {
 
3414
        int done = 0;
 
3415
        
 
3416
        while (done < todo)
 
3417
        {
 
3418
          int r = PlayCommon(jumboPESdata + done, todo - done, false);
 
3419
          if (r < 0)
 
3420
            return r;
 
3421
          
 
3422
//          fprintf(stderr, ".");
 
3423
          
 
3424
          done += r;
 
3425
        }
 
3426
 
 
3427
// Don't return done here as the remaining bytes were buffered elsewhere!
 
3428
//        return done;
 
3429
      }
 
3430
    }
 
3431
 
 
3432
//    fprintf(stderr, "\n");
 
3433
 
 
3434
    return Length;
 
3435
  }
 
3436
  
 
3437
#if APIVERSNUM >= 10338
 
3438
  uchar *cXineDevice::GrabImage(int &Size, bool Jpeg /* = true */, int Quality /* = -1 */, int SizeX /* = -1 */, int SizeY /* = -1 */)
 
3439
  {
 
3440
    const char *const FileName = 0;
 
3441
#else
 
3442
  bool cXineDevice::GrabImage(const char *FileName, bool Jpeg /* = true */, int Quality /* = -1 */, int SizeX /* = -1 */, int SizeY /* = -1 */)
 
3443
  {
 
3444
    int Size = 0;
 
3445
#endif
 
3446
    xfprintf(stderr, "GrabImage ...\n\n");
 
3447
 
 
3448
    if (-1 == Quality)
 
3449
      Quality = 100;
 
3450
 
 
3451
    if (-1 == SizeX)
 
3452
      SizeX = m_settings.DefaultGrabSizeX();
 
3453
 
 
3454
    if (-1 == SizeY)
 
3455
      SizeY = m_settings.DefaultGrabSizeY();
 
3456
 
 
3457
    uchar *result = m_xineLib.execFuncGrabImage(FileName, Size, Jpeg, Quality, SizeX, SizeY);
 
3458
 
 
3459
    xfprintf(stderr, result ? "\nGrabImage succeeded.\n" : "\nGrabImage failed.\n");    
 
3460
    return result;
 
3461
  }
 
3462
 
 
3463
  int64_t cXineDevice::GetSTC(void)
 
3464
  {
 
3465
//    ::fprintf(stderr, "GetSTC: ");
 
3466
    
 
3467
    int64_t pts = -1;
 
3468
 
 
3469
    if (!m_xineLib.execFuncGetPTS(pts) || pts < 0)
 
3470
      pts = cDevice::GetSTC();
 
3471
 
 
3472
//    ::fprintf(stderr, "%lld\n", pts);
 
3473
    
 
3474
    return pts;
 
3475
  }
 
3476
  
 
3477
  void cXineDevice::SetVideoFormat(bool VideoFormat16_9)
 
3478
  {
 
3479
    xfprintf(stderr, "SetVideoFormat: %d\n", VideoFormat16_9);
 
3480
    cDevice::SetVideoFormat(VideoFormat16_9); 
 
3481
  }
 
3482
 
 
3483
  static bool firstCallToSetVolume = true;
 
3484
  static void switchSkin(const bool restore);
 
3485
  
 
3486
  void cXineDevice::SetVolumeDevice(int Volume)
 
3487
  {
 
3488
    if (firstCallToSetVolume)
 
3489
    {
 
3490
      firstCallToSetVolume = false;
 
3491
 
 
3492
      if (m_settings.ShallSwitchSkin())
 
3493
        switchSkin(false);
 
3494
    }
 
3495
    
 
3496
    xfprintf(stderr, "SetVolumeDevice: %d\n", Volume);
 
3497
    m_xineLib.execFuncSetVolume(Volume);
 
3498
  }
 
3499
  
 
3500
#if APIVERSNUM < 10307
 
3501
  cOsdBase *cXineDevice::NewOsd(int x, int y)
 
3502
#elif APIVERSNUM < 10509    
 
3503
  cOsd *cXineDevice::NewOsd(int x, int y)
 
3504
#else
 
3505
  cOsd *cXineDevice::NewOsd(int x, int y, uint Level)
 
3506
#endif    
 
3507
  {
 
3508
//    ::fprintf(stderr, "NewOsd ---: %s\n", ::ctime(&(const time_t &)::time(0)));
 
3509
    cMutexLock osdLock(&m_osdMutex);
 
3510
//    ::fprintf(stderr, "NesOsd +++: %s\n", ::ctime(&(const time_t &)::time(0)));
 
3511
#if APIVERSNUM < 10509    
 
3512
    if (m_currentOsd)
 
3513
    {
 
3514
      esyslog("vdr-xine: new OSD(%d, %d) requested while another OSD is active", x, y);
 
3515
      xfprintf(stderr, "vdr-xine: new OSD(%d, %d) requested while another OSD is active", x, y);
 
3516
      return 0;
 
3517
    }
 
3518
#endif    
 
3519
    if (x < 0 || y < 0)
 
3520
    {
 
3521
      esyslog("vdr-xine: new OSD(%d, %d) requested with coordinates out of range", x, y);
 
3522
      xfprintf(stderr, "vdr-xine: new OSD(%d, %d) requested with coordinates out of range", x, y);
 
3523
    }
 
3524
 
 
3525
#if APIVERSNUM < 10509    
 
3526
    m_currentOsd = new cXineOsd(*this, x, y);
 
3527
#else
 
3528
    return new cXineOsd(*this, x, y, Level);
 
3529
#endif    
 
3530
 
 
3531
    return m_currentOsd;
 
3532
  }
 
3533
 
 
3534
#if APIVERSNUM < 10307
 
3535
  void cXineDevice::OnFreeOsd(cOsdBase *const osd)
 
3536
#else    
 
3537
  void cXineDevice::OnFreeOsd(cOsd *const osd)
 
3538
#endif    
 
3539
  {
 
3540
#if APIVERSNUM < 10509    
 
3541
    cMutexLock osdLock(&m_osdMutex);
 
3542
    
 
3543
    assert(osd == m_currentOsd);
 
3544
 
 
3545
    m_currentOsd = 0;
 
3546
#endif    
 
3547
  }
 
3548
 
 
3549
  bool cXineDevice::ChangeCurrentOsd(cXineOsd *const osd, bool on)
 
3550
  {
 
3551
    cMutexLock osdLock(&m_osdMutex);
 
3552
 
 
3553
    if (m_currentOsd)
 
3554
    {
 
3555
      if (on)
 
3556
      {
 
3557
        esyslog("vdr-xine: OSD activation requested while another OSD is active -- ignoring request");
 
3558
        xfprintf(stderr, "vdr-xine: OSD activation requested while another OSD is active -- ignoring request");
 
3559
        return false;
 
3560
      }
 
3561
      else if (m_currentOsd != osd)
 
3562
      {
 
3563
        esyslog("vdr-xine: OSD deactivation requested for an OSD which is not active -- ignoring request");
 
3564
        xfprintf(stderr, "vdr-xine: OSD deactivation requested for an OSD which is not active -- ignoring request");
 
3565
        return false;
 
3566
      }
 
3567
      else
 
3568
      {
 
3569
        m_currentOsd = 0;
 
3570
      }
 
3571
    }
 
3572
    else
 
3573
    {
 
3574
      if (!on)
 
3575
      {
 
3576
        esyslog("vdr-xine: OSD deactivation requested while no OSD is active -- ignoring request");
 
3577
        xfprintf(stderr, "vdr-xine: OSD deactivation requested while no OSD is active -- ignoring request");
 
3578
        return false;
 
3579
      }
 
3580
      else
 
3581
      {
 
3582
        m_currentOsd = osd;
 
3583
      }
 
3584
    }
 
3585
 
 
3586
    return true;
 
3587
  }
 
3588
 
 
3589
 
 
3590
  
 
3591
  static cDevice *originalPrimaryDevice = 0;
 
3592
  
 
3593
#if APIVERSNUM >= 10307
 
3594
  
 
3595
  void cXineDevice::MakePrimaryDevice(bool On)
 
3596
  {
 
3597
    xfprintf(stderr, "-------------------------\n");
 
3598
    xfprintf(stderr, "MakePrimaryDevice: %d\n", On);
 
3599
    xfprintf(stderr, "=========================\n");
 
3600
 
 
3601
    if (On)
 
3602
      new cXineOsdProvider(*this);
 
3603
    else
 
3604
      cOsdProvider::Shutdown();
 
3605
    
 
3606
    originalPrimaryDevice = 0;
 
3607
  }
 
3608
  
 
3609
#endif    
 
3610
 
 
3611
 
 
3612
 
 
3613
#if APIVERSNUM >= 10320
 
3614
  static cSkin *origSkin = 0;
 
3615
#endif
 
3616
  
 
3617
  static void switchSkin(const bool restore)
 
3618
  {
 
3619
#if APIVERSNUM >= 10320
 
3620
    if (restore)
 
3621
    {
 
3622
      Skins.SetCurrent(origSkin->Name());
 
3623
      cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme());
 
3624
    }
 
3625
    else
 
3626
    {
 
3627
      origSkin = Skins.Current();
 
3628
      Skins.SetCurrent("curses");
 
3629
      cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme());
 
3630
    }
 
3631
#else
 
3632
#warning vdr-xine: switching skins is only available for VDR versions >= 1.3.20
 
3633
    isyslog("vdr-xine: switching skins is only available for VDR versions >= 1.3.20");
 
3634
#endif
 
3635
  }
 
3636
  
 
3637
  void cXineDevice::reshowCurrentOsd(const bool dontOptimize /* = true */, const int frameLeft /* = -1 */, const int frameTop /* = -1 */, const int frameWidth /* = -1 */, const int frameHeight /* = -1 */, const int frameZoomX /* = -1 */, const int frameZoomY /* = -1 */)
 
3638
  {
 
3639
    cMutexLock osdLock(&m_osdMutex);
 
3640
    
 
3641
    if (m_currentOsd)
 
3642
      m_currentOsd->ReshowCurrentOsd(dontOptimize, frameLeft, frameTop, frameWidth, frameHeight, frameZoomX, frameZoomY);
 
3643
  }
 
3644
 
 
3645
  void cXineDevice::mainMenuTrampoline()
 
3646
  {
 
3647
#if APIVERSNUM >= 10332
 
3648
    cMutexLock switchPrimaryDeviceLock(&m_switchPrimaryDeviceMutex);
 
3649
    if (m_switchPrimaryDeviceDeviceNo < 0)
 
3650
      return;
 
3651
 
 
3652
    cControl::Shutdown();
 
3653
 
 
3654
    if (m_switchPrimaryDeviceDeviceNo == (1 + DeviceNumber()))
 
3655
    {  
 
3656
      char *msg = 0;
 
3657
      ::asprintf(&msg, tr("Switching primary DVB to %s..."), m_plugin->Name());
 
3658
 
 
3659
      Skins.Message(mtInfo, msg);
 
3660
      ::free(msg);
 
3661
    }
 
3662
 
 
3663
    SetPrimaryDevice(m_switchPrimaryDeviceDeviceNo);
 
3664
 
 
3665
    if (m_switchPrimaryDeviceDeviceNo != (1 + DeviceNumber()))
 
3666
    {
 
3667
      char *msg = 0;
 
3668
      ::asprintf(&msg, tr("Switched primary DVB back from %s"), m_plugin->Name());
 
3669
 
 
3670
      Skins.Message(mtInfo, msg);
 
3671
      ::free(msg);
 
3672
    }
 
3673
 
 
3674
    m_switchPrimaryDeviceDeviceNo = -1;
 
3675
 
 
3676
    m_switchPrimaryDeviceCond.Broadcast();
 
3677
#endif
 
3678
  }
 
3679
 
 
3680
  void cXineDevice::switchPrimaryDevice(const int deviceNo, const bool waitForExecution)
 
3681
  {
 
3682
#if APIVERSNUM >= 10332
 
3683
#if APIVERSNUM < 10347
 
3684
    while (cRemote::HasKeys())
 
3685
      cCondWait::SleepMs(10);
 
3686
#endif
 
3687
 
 
3688
    cMutexLock switchPrimaryDeviceLock(&m_switchPrimaryDeviceMutex);
 
3689
    m_switchPrimaryDeviceDeviceNo = deviceNo;
 
3690
 
 
3691
#if APIVERSNUM < 10347
 
3692
    cRemote::CallPlugin(m_plugin->Name());
 
3693
#endif
 
3694
 
 
3695
    if (waitForExecution)
 
3696
      m_switchPrimaryDeviceCond.Wait(m_switchPrimaryDeviceMutex);
 
3697
#else
 
3698
#warning vdr-xine: switching primary device is no longer supported for VDR versions < 1.3.32 
 
3699
    isyslog("vdr-xine: switching primary device is no longer supported for VDR versions < 1.3.32");
 
3700
#endif
 
3701
  }
 
3702
 
 
3703
  void cXineDevice::OnClientConnect()
 
3704
  {
 
3705
    reshowCurrentOsd();
 
3706
 
 
3707
    if (m_settings.LiveTV())
 
3708
      softStartTrigger = sstNormal;
 
3709
 
 
3710
    if (m_settings.AutoPrimaryDevice())
 
3711
    {
 
3712
      cDevice *primaryDevice = cDevice::PrimaryDevice();
 
3713
      if (this != primaryDevice)
 
3714
        switchPrimaryDevice(1 + DeviceNumber(), true);
 
3715
 
 
3716
      originalPrimaryDevice = primaryDevice;
 
3717
    }
 
3718
 
 
3719
    if (m_settings.ShallSwitchSkin())
 
3720
      switchSkin(true);
 
3721
  }
 
3722
 
 
3723
  void cXineDevice::OnClientDisconnect()
 
3724
  {
 
3725
    if (m_settings.ShallSwitchSkin())
 
3726
      switchSkin(false);
 
3727
 
 
3728
    if (m_settings.AutoPrimaryDevice()
 
3729
      && originalPrimaryDevice)
 
3730
    {
 
3731
      if (this != originalPrimaryDevice)
 
3732
        switchPrimaryDevice(1 + originalPrimaryDevice->DeviceNumber(), false);
 
3733
    }
 
3734
  }
 
3735
  
 
3736
  void cXineDevice::ReshowCurrentOSD(const int frameLeft, const int frameTop, const int frameWidth, const int frameHeight, const int frameZoomX, const int frameZoomY)
 
3737
  {
 
3738
//    ::fprintf(stderr, ">>> cXineDevice::ReshowCurrentOSD()\n");
 
3739
    reshowCurrentOsd(false, frameLeft, frameTop, frameWidth, frameHeight, frameZoomX, frameZoomY);
 
3740
//    ::fprintf(stderr, "<<< cXineDevice::ReshowCurrentOSD()\n");
 
3741
  }
 
3742
 
 
3743
  bool cXineDevice::DeviceReplayingOrTransferring()
 
3744
  {
 
3745
    return Replaying() || Transferring();
 
3746
  }
 
3747
 
 
3748
  bool cXineDevice::open()
 
3749
  {
 
3750
    if (!m_xineLib.Open())
 
3751
      return false;
 
3752
 
 
3753
    if (m_settings.ShallSwitchSkin())
 
3754
    {
 
3755
#if APIVERSNUM >= 10320
 
3756
      Skins.SetCurrent(Setup.OSDSkin);
 
3757
      cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme());
 
3758
#endif
 
3759
      switchSkin(false);
 
3760
    }
 
3761
    
 
3762
    return true;
 
3763
  }
 
3764
 
 
3765
  void cXineDevice::close()
 
3766
  {
 
3767
    m_xineLib.Close();
 
3768
 
 
3769
    if (m_settings.ShallSwitchSkin())
 
3770
      switchSkin(true);
 
3771
  }
 
3772
 
 
3773
  void cXineDevice::Stop()
 
3774
  {
 
3775
    if (!theXineDevice)
 
3776
      return;
 
3777
 
 
3778
    theXineDevice->close();
 
3779
  }
 
3780
 
 
3781
  cXineDevice::cXineDevice(cPlugin *const plugin, cXineSettings &settings, cXineRemote *remote)
 
3782
    : cDevice()
 
3783
    , m_settings(settings)
 
3784
    , m_currentOsd(0)
 
3785
    , m_spuDecoder(0)
 
3786
    , m_audioChannel(0)
 
3787
    , m_plugin(plugin)
 
3788
    , m_switchPrimaryDeviceDeviceNo(-1)
 
3789
    , m_xineLib(plugin, settings, m_osdMutex, remote)
 
3790
  {
 
3791
    m_xineLib.SetEventSink(this);
 
3792
  }
 
3793
  
 
3794
  cXineDevice::~cXineDevice()
 
3795
  {
 
3796
#if APIVERSNUM < 10320
 
3797
    close();
 
3798
#endif
 
3799
    if (m_spuDecoder)
 
3800
      delete m_spuDecoder;
 
3801
  }
 
3802
  
 
3803
  bool cXineDevice::Create(cPlugin *const plugin, cXineSettings &settings, cXineRemote *remote)
 
3804
  {
 
3805
    if (theXineDevice)
 
3806
      return false;
 
3807
 
 
3808
    theXineDevice = new cXineDevice(plugin, settings, remote);
 
3809
    
 
3810
    return 0 != theXineDevice
 
3811
      && theXineDevice->hasNoSignalStream();
 
3812
  }
 
3813
 
 
3814
  bool cXineDevice::Open()
 
3815
  {
 
3816
    if (!theXineDevice)
 
3817
      return false;
 
3818
 
 
3819
    return theXineDevice->open();
 
3820
  }
 
3821
 
 
3822
  cXineDevice *cXineDevice::GetDevice()
 
3823
  {
 
3824
    return theXineDevice;
 
3825
  }
 
3826
 
 
3827
};