Project

General

Profile

Bug #6155 » tsfix.c

Diogo Sena, 2022-03-31 23:58

 
1
/**
2
 *  Timestamp fixup
3
 *  Copyright (C) 2010 Andreas Öman
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation, either version 3 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

    
19
#include "tvheadend.h"
20
#include "streaming.h"
21
#include "tsfix.h"
22

    
23
#define REF_OK       0
24
#define REF_ERROR    1
25
#define REF_DROP     2
26

    
27
LIST_HEAD(tfstream_list, tfstream);
28

    
29
/**
30
 *
31
 */
32
typedef struct tfstream {
33

    
34
  LIST_ENTRY(tfstream) tfs_link;
35

    
36
  int tfs_index;
37

    
38
  streaming_component_type_t tfs_type;
39
  uint8_t tfs_video;
40
  uint8_t tfs_audio;
41
  uint8_t tfs_subtitle;
42

    
43
  int tfs_bad_dts;
44
  int64_t tfs_local_ref;
45
  int64_t tfs_last_dts_norm;
46
  int64_t tfs_dts_epoch;
47

    
48
  int64_t tfs_last_dts_in;
49

    
50
  int tfs_seen;
51

    
52
  struct tfstream *tfs_parent;
53

    
54
} tfstream_t;
55

    
56

    
57
/**
58
 *
59
 */
60
typedef struct tsfix {
61
  streaming_target_t tf_input;
62

    
63
  streaming_target_t *tf_output;
64

    
65
  struct tfstream_list tf_streams;
66
  int tf_hasvideo;
67
  int tf_wait_for_video;
68
  int64_t tf_tsref;
69
  int64_t tf_start_time;
70
  int64_t dts_offset;
71
  int dts_offset_apply;
72

    
73
  struct th_pktref_queue tf_ptsq;
74
  struct th_pktref_queue tf_backlog;
75

    
76
} tsfix_t;
77

    
78

    
79
/**
80
 * Compute the timestamp deltas
81
 */
82
static int64_t
83
tsfix_ts_diff(int64_t ts1, int64_t ts2)
84
{
85
  int64_t r;
86
  ts1 &= PTS_MASK;
87
  ts2 &= PTS_MASK;
88

    
89
  r = llabs(ts1 - ts2);
90
  if (r > (PTS_MASK / 2)) {
91
    /* try to wrap the lowest value */
92
    if (ts1 < ts2)
93
      ts1 += PTS_MASK + 1;
94
    else
95
      ts2 += PTS_MASK + 1;
96
    return llabs(ts1 - ts2);
97
  }
98
  return r;
99
}
100

    
101
/**
102
 *
103
 */
104
static void
105
tsfix_destroy_streams(tsfix_t *tf)
106
{
107
  tfstream_t *tfs;
108
  pktref_clear_queue(&tf->tf_ptsq);
109
  pktref_clear_queue(&tf->tf_backlog);
110
  while((tfs = LIST_FIRST(&tf->tf_streams)) != NULL) {
111
    LIST_REMOVE(tfs, tfs_link);
112
    free(tfs);
113
  }
114
}
115

    
116

    
117
static tfstream_t *
118
tfs_find(tsfix_t *tf, th_pkt_t *pkt)
119
{
120
  tfstream_t *tfs;
121
  LIST_FOREACH(tfs, &tf->tf_streams, tfs_link)
122
    if(pkt->pkt_componentindex == tfs->tfs_index)
123
      break;
124
  return tfs;
125
}
126

    
127
/**
128
 *
129
 */
130
static tfstream_t *
131
tsfix_add_stream(tsfix_t *tf, int index, streaming_component_type_t type)
132
{
133
  tfstream_t *tfs = calloc(1, sizeof(tfstream_t));
134

    
135
  tfs->tfs_type = type;
136
  if (SCT_ISVIDEO(type))
137
    tfs->tfs_video = 1;
138
  else if (SCT_ISAUDIO(type))
139
    tfs->tfs_audio = 1;
140
  else if (SCT_ISSUBTITLE(type))
141
    tfs->tfs_subtitle = 1;
142

    
143
  tfs->tfs_index = index;
144
  tfs->tfs_local_ref = PTS_UNSET;
145
  tfs->tfs_last_dts_norm = PTS_UNSET;
146
  tfs->tfs_last_dts_in = PTS_UNSET;
147
  tfs->tfs_dts_epoch = 0;
148
  tfs->tfs_seen = 0;
149

    
150
  LIST_INSERT_HEAD(&tf->tf_streams, tfs, tfs_link);
151
  return tfs;
152
}
153

    
154

    
155
/**
156
 *
157
 */
158
static void
159
tsfix_start(tsfix_t *tf, streaming_start_t *ss)
160
{
161
  int i, hasvideo = 0, vwait = 0;
162
  tfstream_t *tfs;
163

    
164
  for(i = 0; i < ss->ss_num_components; i++) {
165
    const streaming_start_component_t *ssc = &ss->ss_components[i];
166
    tfs = tsfix_add_stream(tf, ssc->es_index, ssc->es_type);
167
    if (tfs->tfs_video) {
168
      if (ssc->es_width == 0 || ssc->es_height == 0)
169
        /* only first video stream may be valid */
170
        vwait = !hasvideo ? 1 : 0;
171
      hasvideo = 1;
172
    }
173
  }
174

    
175
  TAILQ_INIT(&tf->tf_ptsq);
176
  TAILQ_INIT(&tf->tf_backlog);
177

    
178
  tf->tf_tsref = PTS_UNSET;
179
  tf->tf_hasvideo = hasvideo;
180
  tf->tf_wait_for_video = vwait;
181
}
182

    
183

    
184
/**
185
 *
186
 */
187
static void
188
tsfix_stop(tsfix_t *tf)
189
{
190
  tsfix_destroy_streams(tf);
191
}
192

    
193

    
194
/**
195
 *
196
 */
197
static void
198
tsfix_packet_drop(tfstream_t *tfs, th_pkt_t *pkt, const char *reason)
199
{
200
  if (tvhtrace_enabled()) {
201
    char buf[64];
202
    snprintf(buf, sizeof(buf), "drop %s", reason);
203
    pkt_trace(LS_TSFIX, pkt, buf);
204
  }
205
  pkt_ref_dec(pkt);
206
}
207

    
208
/**
209
 *
210
 */
211
static void
212
normalize_ts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt, int backlog)
213
{
214
  int64_t ref, dts, odts, opts, d;
215

    
216
  if(tf->tf_tsref == PTS_UNSET) {
217
    if (backlog) {
218
      if (pkt->pkt_dts != PTS_UNSET)
219
        tfs->tfs_seen = 1;
220
      pktref_enqueue(&tf->tf_backlog, pkt);
221
    } else
222
      pkt_ref_dec(pkt);
223
    return;
224
  }
225

    
226
  ref = tfs->tfs_local_ref != PTS_UNSET ? tfs->tfs_local_ref : tf->tf_tsref;
227
  odts = pkt->pkt_dts;
228
  opts = pkt->pkt_pts;
229

    
230
  if (pkt->pkt_dts == PTS_UNSET) {
231
    if (pkt->pkt_pts != PTS_UNSET)
232
      pkt->pkt_dts = pkt->pkt_pts;
233
    else
234
      goto deliver;
235
  }
236

    
237
  pkt->pkt_dts &= PTS_MASK;
238

    
239
  /* Subtract the transport wide start offset */
240
  if (tf->dts_offset_apply)
241
    dts = pts_diff(ref, pkt->pkt_dts + tf->dts_offset);
242
  else
243
    dts = pts_diff(ref, pkt->pkt_dts);
244

    
245
  if (tfs->tfs_last_dts_norm == PTS_UNSET) {
246
    if (dts < 0 || pkt->pkt_err) {
247
      /* Early packet with negative time stamp, drop those */
248
      tsfix_packet_drop(tfs, pkt, "negative/error");
249
      return;
250
    }
251
  } else {
252
    const int64_t nlimit =      -1; /* allow negative values - rounding errors? */
253
    int64_t low          =   90000; /* one second */
254
    int64_t upper        = 2*90000; /* two seconds */
255
    d = dts + tfs->tfs_dts_epoch - tfs->tfs_last_dts_norm;
256

    
257
    if (tfs->tfs_subtitle) {
258
      /*
259
       * special conditions for subtitles, because they may be broadcasted
260
       * with large time gaps
261
       */
262
      low   = PTS_MASK / 2; /* more than 13 hours */
263
      upper = low - 1;
264
    }
265

    
266
    if (d < nlimit || d > low) {
267
      if (d < -PTS_MASK || d > -PTS_MASK + upper) {
268
        if (pkt->pkt_err) {
269
          tsfix_packet_drop(tfs, pkt, "possible wrong discontinuity");
270
          return;
271
        }
272
	tfs->tfs_bad_dts++;
273
        if (tfs->tfs_bad_dts < 5) {
274
	  tvhwarn(LS_TSFIX,
275
		   "transport stream %s, DTS discontinuity. "
276
		   "DTS = %" PRId64 ", last = %" PRId64,
277
		   streaming_component_type2txt(tfs->tfs_type),
278
		   dts, tfs->tfs_last_dts_norm);
279
	}
280
      } else {
281
	/* DTS wrapped, increase upper bits */
282
	tfs->tfs_dts_epoch += PTS_MASK + 1;
283
	tfs->tfs_bad_dts = 0;
284
      }
285
    } else {
286
      tfs->tfs_bad_dts = 0;
287
    }
288
  }
289

    
290
  dts += tfs->tfs_dts_epoch;
291
  tfs->tfs_last_dts_norm = dts;
292

    
293
  if(pkt->pkt_pts != PTS_UNSET) {
294
    /* Compute delta between PTS and DTS (and watch out for 33 bit wrap) */
295
    d = ((pkt->pkt_pts & PTS_MASK) - pkt->pkt_dts) & PTS_MASK;
296
    pkt->pkt_pts = dts + d;
297
  }
298
  if(pkt->pkt_pcr != PTS_UNSET) {
299
    /* Compute delta between PCR and DTS (and watch out for 33 bit wrap) */
300
    d = ((pkt->pkt_pcr & PTS_MASK) - pkt->pkt_dts) & PTS_MASK;
301
    if (d > PTS_MASK / 2)
302
      d = -(PTS_MASK - d);
303
    pkt->pkt_pcr = dts + d;
304
  }
305

    
306
  pkt->pkt_dts = dts;
307

    
308
  if (pkt->pkt_pts < 0 || pkt->pkt_dts < 0 || pkt->pkt_pcr < 0) {
309
    tsfix_packet_drop(tfs, pkt, "negative2/error");
310
    return;
311
  }
312

    
313
deliver:
314
  if (tvhtrace_enabled()) {
315
    char _odts[22], _opts[22];
316
    pkt_trace(LS_TSFIX, pkt,
317
              "deliver odts %s opts %s ref %"PRId64" epoch %"PRId64,
318
              pts_to_string(odts, _odts), pts_to_string(opts, _opts),
319
              ref, tfs->tfs_dts_epoch);
320
  }
321

    
322
  streaming_message_t *sm = streaming_msg_create_pkt(pkt);
323
  streaming_target_deliver2(tf->tf_output, sm);
324
  pkt_ref_dec(pkt);
325
}
326

    
327
/**
328
 *
329
 */
330
static inline int
331
txfix_need_to_update_ref(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
332
{
333
  return tfs->tfs_local_ref == PTS_UNSET &&
334
         tf->tf_tsref != PTS_UNSET &&
335
         pkt->pkt_dts != PTS_UNSET;
336
}
337

    
338
/**
339
 *
340
 */
341
static int
342
tsfix_update_ref(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
343
{
344
  tfstream_t *tfs2;
345
  int64_t diff;
346

    
347
  if (pkt->pkt_err)
348
    return REF_ERROR;
349

    
350
  if (tfs->tfs_audio) {
351
    diff = tsfix_ts_diff(tf->tf_tsref, pkt->pkt_dts);
352
    if (diff > 3 * 90000) {
353
      tvhwarn(LS_TSFIX, "The timediff for %s is big (%"PRId64"), using current dts",
354
              streaming_component_type2txt(tfs->tfs_type), diff);
355
      tfs->tfs_local_ref = pkt->pkt_dts;
356
    } else {
357
      tfs->tfs_local_ref = tf->tf_tsref;
358
    }
359
  } else if (tfs->tfs_type == SCT_DVBSUB || tfs->tfs_type == SCT_TEXTSUB) {
360
    /* find first valid audio stream and check the dts timediffs */
361
    LIST_FOREACH(tfs2, &tf->tf_streams, tfs_link)
362
      if (tfs2->tfs_audio && tfs2->tfs_last_dts_in != PTS_UNSET) {
363
        diff = tsfix_ts_diff(tfs2->tfs_last_dts_in, pkt->pkt_dts);
364
        /*if (diff > 6 * 90000) {
365
          tvhwarn(LS_TSFIX, "The timediff for %s is big (%"PRId64"), using audio dts",
366
                  streaming_component_type2txt(tfs->tfs_type), diff);
367
          tfs->tfs_parent = tfs2;
368
          tfs->tfs_local_ref = tfs2->tfs_local_ref;
369
        } else {
370
          tfs->tfs_local_ref = tf->tf_tsref;
371
        }*/
372
		tfs->tfs_local_ref = tf->tf_tsref;
373
        break;
374
      }
375
    if (tfs2 == NULL)
376
      return REF_DROP;
377
  } else if (tfs->tfs_type == SCT_TELETEXT) {
378
    diff = tsfix_ts_diff(tf->tf_tsref, pkt->pkt_dts);
379
    if (diff > 2 * 90000) {
380
      tvhwarn(LS_TSFIX, "The timediff for TELETEXT is big (%"PRId64"), using current dts", diff);
381
      tfs->tfs_local_ref = pkt->pkt_dts;
382
    } else {
383
      tfs->tfs_local_ref = tf->tf_tsref;
384
    }
385
  }
386
  return REF_OK;
387
}
388

    
389
/**
390
 *
391
 */
392
static void
393
tsfix_backlog(tsfix_t *tf)
394
{
395
  th_pkt_t *pkt;
396
  tfstream_t *tfs;
397
  int r;
398

    
399
  while((pkt = pktref_get_first(&tf->tf_backlog)) != NULL) {
400
    tfs = tfs_find(tf, pkt);
401
    if (txfix_need_to_update_ref(tf, tfs, pkt)) {
402
      r = tsfix_update_ref(tf, tfs, pkt);
403
      if (r != REF_OK) {
404
        tsfix_packet_drop(tfs, pkt, r == REF_ERROR ? "bckle" : "bckld");
405
        continue;
406
      }
407
    }
408
    normalize_ts(tf, tfs, pkt, 0);
409
  }
410
}
411

    
412

    
413
/**
414
 *
415
 */
416
static int64_t
417
tsfix_backlog_diff(tsfix_t *tf)
418
{
419
  th_pkt_t *pkt;
420
  th_pktref_t *pr;
421
  tfstream_t *tfs;
422
  int64_t res = 0;
423

    
424
  PKTREF_FOREACH(pr, &tf->tf_backlog) {
425
    pkt = pr->pr_pkt;
426
    if (pkt->pkt_dts == PTS_UNSET) continue;
427
    if (pkt->pkt_dts >= tf->tf_tsref) continue;
428
    if (tf->tf_tsref > (PTS_MASK * 3) / 4 &&
429
        pkt->pkt_dts < PTS_MASK / 4) continue;
430
    tfs = tfs_find(tf, pkt);
431
    if (!tfs->tfs_audio && !tfs->tfs_video) continue;
432
    res = MAX(tsfix_ts_diff(pkt->pkt_dts, tf->tf_tsref), res);
433
  }
434
  return res;
435
}
436

    
437

    
438
/**
439
 *
440
 * Recover unset PTS.
441
 *
442
 * MPEG2 DTS/PTS example (rpts = result pts):
443
 * 01: I dts 4922701936 pts 4922712736 rpts 4922712736
444
 * 02: B dts 4922705536 pts <unset>    rpts 4922705536
445
 * 03: B dts 4922709136 pts <unset>    rpts 4922709136
446
 * 04: P dts 4922712736 pts <unset>    rpts 4922723536
447
 * 05: B dts 4922716336 pts <unset>    rpts 4922716336
448
 * 06: B dts 4922719936 pts <unset>    rpts 4922719936
449
 * 07: P dts 4922723536 pts <unset>    rpts 4922734336
450
 * 08: B dts 4922727136 pts <unset>    rpts 4922727136
451
 * 09: B dts 4922730736 pts <unset>    rpts 4922730736
452
 * 10: P dts 4922734336 pts <unset>    rpts 4922745136
453
 * 11: B dts 4922737936 pts <unset>    rpts 4922737936
454
 * 12: B dts 4922741536 pts <unset>    rpts 4922741536
455
 * 13: I dts 4922745136 pts 4922755936 rpts 4922755936
456
 */
457
static void
458
recover_pts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
459
{
460
  th_pktref_t *srch;
461
  int total;
462

    
463
  pktref_enqueue(&tf->tf_ptsq, pkt);
464
  while((pkt = pktref_get_first(&tf->tf_ptsq)) != NULL) {
465
    tfs = tfs_find(tf, pkt);
466

    
467
    switch(tfs->tfs_type) {
468

    
469
    case SCT_MPEG2VIDEO:
470

    
471
      switch(pkt->v.pkt_frametype) {
472
      case PKT_B_FRAME:
473
        if (pkt->pkt_pts == PTS_UNSET) {
474
	  /* B-frames have same PTS as DTS, pass them on */
475
	  tvhtrace(LS_TSFIX, "%-12s PTS b-frame set to %"PRId64" (old %"PRId64")",
476
		   streaming_component_type2txt(tfs->tfs_type),
477
		   pkt->pkt_dts, pkt->pkt_pts);
478
	  pkt->pkt_pts = pkt->pkt_dts;
479
        }
480
	break;
481
      
482
      case PKT_I_FRAME:
483
      case PKT_P_FRAME:
484
        if (pkt->pkt_pts == PTS_UNSET) {
485
	  /* Presentation occures at DTS of next I or P frame,
486
	     try to find it */
487
          total = 0;
488
          PKTREF_FOREACH(srch, &tf->tf_ptsq) {
489
            if (pkt->pkt_componentindex != tfs->tfs_index)
490
              continue;
491
            total++;
492
            if (srch->pr_pkt->v.pkt_frametype <= PKT_P_FRAME &&
493
                pts_is_greater_or_equal(pkt->pkt_dts, srch->pr_pkt->pkt_dts) > 0 &&
494
                pts_diff(pkt->pkt_dts, srch->pr_pkt->pkt_dts) < 10 * 90000) {
495
              tvhtrace(LS_TSFIX, "%-12s PTS *-frame set to %"PRId64" (old %"PRId64"), DTS %"PRId64,
496
                          streaming_component_type2txt(tfs->tfs_type),
497
                          srch->pr_pkt->pkt_dts, pkt->pkt_pts, pkt->pkt_dts);
498
              pkt->pkt_pts = srch->pr_pkt->pkt_dts;
499
              break;
500
            }	  
501
          }
502
          if (srch == NULL) {
503
            if (total < 50) {
504
              /* return packet back to tf_ptsq */
505
              pktref_insert_head(&tf->tf_ptsq, pkt);
506
            } else {
507
              tsfix_packet_drop(tfs, pkt, "mpeg2video overflow");
508
            }
509
            return; /* not arrived yet or invalid, wait */
510
          }
511
        }
512
      }
513
      break;
514

    
515
    default:
516
      break;
517
    }
518

    
519
    normalize_ts(tf, tfs, pkt, 1);
520
  }
521
}
522

    
523

    
524
/**
525
 * Compute PTS (if not known)
526
 */
527
static void
528
compute_pts(tsfix_t *tf, tfstream_t *tfs, th_pkt_t *pkt)
529
{
530
  // If PTS is missing, set it to DTS if not video
531
  if(pkt->pkt_pts == PTS_UNSET && !tfs->tfs_video) {
532
    pkt->pkt_pts = pkt->pkt_dts;
533
    tvhtrace(LS_TSFIX, "%-12s PTS set to %"PRId64,
534
		streaming_component_type2txt(tfs->tfs_type),
535
		pkt->pkt_pts);
536
  }
537

    
538
  /* PTS known and no other packets in queue, deliver at once */
539
  if(pkt->pkt_pts != PTS_UNSET && TAILQ_FIRST(&tf->tf_ptsq) == NULL)
540
    normalize_ts(tf, tfs, pkt, 1);
541
  else
542
    recover_pts(tf, tfs, pkt);
543
}
544

    
545

    
546
/**
547
 *
548
 */
549
static void
550
tsfix_input_packet(tsfix_t *tf, streaming_message_t *sm)
551
{
552
  th_pkt_t *pkt;
553
  tfstream_t *tfs, *tfs2;
554
  int64_t diff, diff2, threshold;
555
  int r;
556

    
557
  pkt = pkt_copy_shallow(sm->sm_data);
558
  tfs = tfs_find(tf, pkt);
559
  streaming_msg_free(sm);
560

    
561
  if (tfs == NULL || mclk() < tf->tf_start_time) {
562
    tsfix_packet_drop(tfs, pkt, "start time");
563
    return;
564
  }
565

    
566
  if (tf->tf_tsref == PTS_UNSET && pkt->pkt_dts != PTS_UNSET &&
567
      ((!tf->tf_hasvideo && tfs->tfs_audio) ||
568
       (tfs->tfs_video && pkt->v.pkt_frametype == PKT_I_FRAME))) {
569
    if (pkt->pkt_err) {
570
      tsfix_packet_drop(tfs, pkt, "ref1");
571
      return;
572
    }
573
    threshold = 22500;
574
    LIST_FOREACH(tfs2, &tf->tf_streams, tfs_link)
575
      if (tfs != tfs2 && (tfs2->tfs_audio || tfs2->tfs_video) && !tfs2->tfs_seen) {
576
        threshold = 90000;
577
        break;
578
      }
579
    tf->tf_tsref = pkt->pkt_dts & PTS_MASK;
580
    if (pts_is_greater_or_equal(pkt->pkt_pcr, pkt->pkt_dts) > 0)
581
      tf->tf_tsref = pkt->pkt_pcr & PTS_MASK;
582
    diff = diff2 = tsfix_backlog_diff(tf);
583
    if (diff > threshold) {
584
      if (diff > 160000)
585
        diff = 160000;
586
      tf->tf_tsref = (tf->tf_tsref - diff) % PTS_MASK;
587
      tvhtrace(LS_TSFIX, "reference clock set to %"PRId64" (dts %"PRId64" pcr %"PRId64" backlog %"PRId64")", tf->tf_tsref, pkt->pkt_dts, pkt->pkt_pcr, diff2);
588
      tsfix_backlog(tf);
589
    } else {
590
      tvhtrace(LS_TSFIX, "reference clock set to %"PRId64" (dts %"PRId64" pcr %"PRId64" backlog %"PRId64")", tf->tf_tsref, pkt->pkt_dts, pkt->pkt_pcr, diff2);
591
    }
592
  } else if (txfix_need_to_update_ref(tf, tfs, pkt)) {
593
    r = tsfix_update_ref(tf, tfs, pkt);
594
    if (r != REF_OK) {
595
      tsfix_packet_drop(tfs, pkt, r == REF_ERROR ? "refe" : "refd");
596
      return;
597
    }
598
  }
599

    
600
  int pdur = pkt->pkt_duration >> pkt->v.pkt_field;
601

    
602
  if (pkt->pkt_dts == PTS_UNSET) {
603
    if (tfs->tfs_last_dts_in == PTS_UNSET) {
604
      if (tfs->tfs_type == SCT_TELETEXT) {
605
        sm = streaming_msg_create_pkt(pkt);
606
        streaming_target_deliver2(tf->tf_output, sm);
607
      }
608
      pkt_ref_dec(pkt);
609
      return;
610
    }
611

    
612
    if (pkt->pkt_payload != NULL || pkt->pkt_pts != PTS_UNSET) {
613
      pkt->pkt_dts = (tfs->tfs_last_dts_in + pdur) & PTS_MASK;
614
      tvhtrace(LS_TSFIX, "%-12s DTS set to last %"PRId64" +%d == %"PRId64", PTS = %"PRId64,
615
		streaming_component_type2txt(tfs->tfs_type),
616
		tfs->tfs_last_dts_in, pdur, pkt->pkt_dts, pkt->pkt_pts);
617
    }
618
  }
619

    
620
  if (tfs->tfs_parent)
621
    pkt->pkt_dts = pkt->pkt_pts = tfs->tfs_parent->tfs_last_dts_in;
622

    
623
  tfs->tfs_last_dts_in = pkt->pkt_dts;
624

    
625
  compute_pts(tf, tfs, pkt);
626
}
627

    
628

    
629
/**
630
 *
631
 */
632
static void
633
tsfix_input(void *opaque, streaming_message_t *sm)
634
{
635
  tsfix_t *tf = opaque;
636

    
637
  switch(sm->sm_type) {
638
  case SMT_PACKET:
639
    if (tf->tf_wait_for_video) {
640
      streaming_msg_free(sm);
641
      return;
642
    }
643
    tsfix_input_packet(tf, sm);
644
    return;
645
  case SMT_START:
646
    tsfix_stop(tf);
647
    tsfix_start(tf, sm->sm_data);
648
    if (tf->tf_wait_for_video) {
649
      streaming_msg_free(sm);
650
      return;
651
    }
652
    break;
653
  case SMT_STOP:
654
    tsfix_stop(tf);
655
    break;
656
  case SMT_TIMESHIFT_STATUS:
657
    if(tf->dts_offset == PTS_UNSET) {
658
      timeshift_status_t *status;
659
      status = sm->sm_data;
660
      tf->dts_offset = status->shift;
661
    }
662
    streaming_msg_free(sm);
663
    return;
664
  case SMT_SKIP:
665
    if(tf->dts_offset != PTS_UNSET) {
666
      tf->dts_offset_apply = 1;
667
    }
668
    break;
669
  case SMT_GRACE:
670
  case SMT_EXIT:
671
  case SMT_SERVICE_STATUS:
672
  case SMT_SIGNAL_STATUS:
673
  case SMT_DESCRAMBLE_INFO:
674
  case SMT_NOSTART:
675
  case SMT_NOSTART_WARN:
676
  case SMT_MPEGTS:
677
  case SMT_SPEED:
678
    break;
679
  }
680

    
681
  streaming_target_deliver2(tf->tf_output, sm);
682
}
683

    
684
static htsmsg_t *
685
tsfix_input_info(void *opaque, htsmsg_t *list)
686
{
687
  tsfix_t *tf = opaque;
688
  streaming_target_t *st = tf->tf_output;
689
  htsmsg_add_str(list, NULL, "tsfix input");
690
  return st->st_ops.st_info(st->st_opaque, list);
691
}
692

    
693
static streaming_ops_t tsfix_input_ops = {
694
  .st_cb   = tsfix_input,
695
  .st_info = tsfix_input_info
696
};
697

    
698

    
699
/**
700
 *
701
 */
702
streaming_target_t *
703
tsfix_create(streaming_target_t *output)
704
{
705
  tsfix_t *tf = calloc(1, sizeof(tsfix_t));
706

    
707
  TAILQ_INIT(&tf->tf_ptsq);
708

    
709
  tf->tf_output = output;
710
  tf->tf_start_time = mclk();
711
  tf->dts_offset = PTS_UNSET;
712
  streaming_target_init(&tf->tf_input, &tsfix_input_ops, tf, 0);
713
  return &tf->tf_input;
714
}
715

    
716
/**
717
 *
718
 */
719
void
720
tsfix_destroy(streaming_target_t *pad)
721
{
722
  tsfix_t *tf = (tsfix_t *)pad;
723

    
724
  tsfix_destroy_streams(tf);
725
  free(tf);
726
}
(3-3/3)