Project

General

Profile

Bug #900 » 0001-Fix-missing-PAT-PMT-packets-in-MPEG-TS.patch

Zdeněk Kopřivík, 2012-05-29 18:40

View differences:

src/dvr/dvr_rec.c
421 421
  dvr_entry_t *de = aux;
422 422
  streaming_queue_t *sq = &de->de_sq;
423 423
  streaming_message_t *sm;
424
  dvr_config_t *cfg = dvr_config_find_by_name_default(de->de_config_name);
425
  streaming_tsbuf_t pat_pmt_tsbuf;
426
  struct mk_ts_pat_pmt pat_pmt_buf;
427
  int ts_packets_cnt = 1000;
424 428
  int run = 1;
425 429

  
426 430
  pthread_mutex_lock(&sq->sq_mutex);
427

  
428 431
  while(run) {
429 432
    sm = TAILQ_FIRST(&sq->sq_queue);
430 433
    if(sm == NULL) {
431 434
      pthread_cond_wait(&sq->sq_cond, &sq->sq_mutex);
432 435
      continue;
433 436
    }
434
    
437

  
435 438
    TAILQ_REMOVE(&sq->sq_queue, sm, sm_link);
436 439

  
437 440
    pthread_mutex_unlock(&sq->sq_mutex);
438 441

  
439 442
    switch(sm->sm_type) {
443

  
440 444
    case SMT_PACKET:
441 445
      if(dispatch_clock > de->de_start - (60 * de->de_start_extra)) {
442
	dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
443
	if(de->de_mkmux != NULL) {
444
	  mk_mux_write_pkt(de->de_mkmux, sm->sm_data);
445
	  sm->sm_data = NULL;
446
	}
446
      dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
447
        if(de->de_mkmux != NULL) {
448
          mk_mux_write_pkt(de->de_mkmux, sm->sm_data);
449
          sm->sm_data = NULL;
450
        }
447 451
      }
448 452
      break;
449 453

  
......
452 456
      dvr_rec_set_state(de, DVR_RS_WAIT_PROGRAM_START, 0);
453 457
      dvr_rec_start(de, sm->sm_data);
454 458
      pthread_mutex_unlock(&global_lock);
459

  
460
      if (strcmp(cfg->dvr_format, "mpegts") == 0) {
461
        struct streaming_start *ss = sm->sm_data;
462
        run = mk_ts_build_pat_pmt(&pat_pmt_buf, ss, de->de_s->ths_service->s_pmt_pid, de->de_s->ths_service->s_pcr_pid);
463

  
464
        pat_pmt_tsbuf.ts_data = (uint8_t *)&pat_pmt_buf;
465
        pat_pmt_tsbuf.ts_cnt = 2;
466
      }
467

  
455 468
      break;
456 469

  
457 470
    case SMT_STOP:
......
523 536

  
524 537
    case SMT_MPEGTS:
525 538
      if(dispatch_clock > de->de_start - (60 * de->de_start_extra)) {
526
    	dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
527
    	if(de->de_mkts != NULL)
528
    	  mk_ts_write(de->de_mkts, (streaming_tsbuf_t *)sm->sm_data);
539
        dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
540

  
541
        if(de->de_mkts != NULL) {
542
          streaming_tsbuf_t *tsbuf = sm->sm_data;
543

  
544
          ts_packets_cnt += tsbuf->ts_cnt;
545
          if(ts_packets_cnt >= 1000) {
546
            ts_packets_cnt = 0;
547
            mk_ts_write(de->de_mkts, &pat_pmt_tsbuf);
548
          }
549

  
550
          mk_ts_write(de->de_mkts, tsbuf);
551
        }
529 552
      }
530 553
      break;
531 554

  
src/dvr/mkts.c
42 42
 */
43 43
mk_ts_t *
44 44
mk_ts_create(const char *filename,
45
		  const struct streaming_start *ss,
46
	      const struct dvr_entry *de)
45
             const struct streaming_start *ss,
46
             const struct dvr_entry *de)
47 47
{
48 48
  mk_ts_t *mkr;
49 49
  int fd;
50
  dvr_config_t *cfg = dvr_config_find_by_name_default(de->de_config_name);
51 50

  
52 51
  fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0777);
53 52
  if(fd == -1)
......
58 57
  mkr->fd = fd;
59 58
  mkr->title = strdup(de->de_title);
60 59

  
61
  // XXX Code from webui.c, it doesn't work with HD stream (H264+EAC3) and XBMC
62
  if (strcmp(cfg->dvr_format, "mpegts") == 0) {
63
        streaming_tsbuf_t tsbuf;
64
        struct {
65
          uint8_t pat_ts[188];
66
          uint8_t pmt_ts[188];
67
        } s;
68
	int pcrpid = ss->ss_pcr_pid;
69
	int pmtpid = 0x0fff;
70

  
71
	tsbuf.ts_cnt = 2;
72
	tsbuf.ts_data = (uint8_t *)&s;
73

  
74
	//Build PAT
75
	memset(s.pat_ts, 0xff, 188);
76
	psi_build_pat(NULL, s.pat_ts+5, 183, pmtpid);
77
	s.pat_ts[0] = 0x47;
78
	s.pat_ts[1] = 0x40;
79
	s.pat_ts[2] = 0x00;
80
	s.pat_ts[3] = 0x10;
81
	s.pat_ts[4] = 0x00;
82

  
83
	//Build PMT
84
	memset(s.pmt_ts, 0xff, 188);
85
	psi_build_pmt(ss, s.pmt_ts+5, 183, pcrpid);
86
	s.pmt_ts[0] = 0x47;
87
	s.pmt_ts[1] = 0x40 | (pmtpid >> 8);
88
	s.pmt_ts[2] = pmtpid;
89
	s.pmt_ts[3] = 0x10;
90
	s.pmt_ts[4] = 0x00;
91

  
92
	//Write PAT+PMT
93
	mk_ts_write(mkr, &tsbuf);
94
	if(mkr->error)
95
	  return NULL;
96
  }
97

  
98 60
  return mkr;
99 61
}
100 62

  
63
int mk_ts_build_pat_pmt(struct mk_ts_pat_pmt* buffer, const struct streaming_start* ss, int pmt_pid, int pcr_pid)
64
{
65
  int pmtpid = 0x0fff; //pmt_pid
66
  int pcrpid = pcr_pid;
67
  
68
  //Build PAT
69
  memset(buffer->pat_ts, 0xff, 188);
70
  psi_build_pat(NULL, buffer->pat_ts+5, 183, pmtpid);
71
  buffer->pat_ts[0] = 0x47;
72
  buffer->pat_ts[1] = 0x40;
73
  buffer->pat_ts[2] = 0x00;
74
  buffer->pat_ts[3] = 0x10;
75
  buffer->pat_ts[4] = 0x00;
76
  
77
  //Build PMT
78
  memset(buffer->pmt_ts, 0xff, 188);
79
  psi_build_pmt(ss, buffer->pmt_ts+5, 183, pcrpid);
80
  buffer->pmt_ts[0] = 0x47;
81
  buffer->pmt_ts[1] = 0x40 | (pmtpid >> 8);
82
  buffer->pmt_ts[2] = pmtpid;
83
  buffer->pmt_ts[3] = 0x10;
84
  buffer->pmt_ts[4] = 0x00;
85
  
86
  return 1;
87
}
88

  
101 89
/**
102 90
 *
103 91
 */
src/dvr/mkts.h
18 18

  
19 19
typedef struct mk_ts mk_ts_t;
20 20

  
21
struct mk_ts_pat_pmt {
22
  uint8_t pat_ts[188];
23
  uint8_t pmt_ts[188];
24
};
25

  
21 26
struct streaming_start;
22 27
struct dvr_entry;
23 28

  
24 29
mk_ts_t *mk_ts_create(const char *filename,
25
			const struct streaming_start *ss,
26
			const struct dvr_entry *de);
30
                      const struct streaming_start *ss,
31
                      const struct dvr_entry *de);
32

  
33
int mk_ts_build_pat_pmt(struct mk_ts_pat_pmt* buffer, const struct streaming_start* ss, int pmt_pid, int pcr_pid);
27 34

  
28 35
void mk_ts_write(mk_ts_t *mkr, const streaming_tsbuf_t *tsbuf);
29 36

  
src/rawtsinput.c
257 257
	  struct timespec slp;
258 258
	  int64_t delta = pcr - t->s_pcr_last;
259 259

  
260
	  
261

  
262 260
	  if(delta > 90000)
263 261
	    delta = 90000;
264 262
	  delta *= 11;
src/webui/webui.c
34 34
#include "http.h"
35 35
#include "webui.h"
36 36
#include "dvr/dvr.h"
37
#include "dvr/mkts.h"
37 38
#include "dvr/mkmux.h"
38 39
#include "filebundle.h"
39 40
#include "psi.h"
......
131 132
http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t *s)
132 133
{
133 134
  streaming_message_t *sm;
134
  int run = 1;
135 135
  mk_mux_t *mkm = NULL;
136
  uint32_t event_id = 0;
136
  struct mk_ts_pat_pmt pat_pmt_buf;
137
  int ts_packets_cnt = 1000;
138
  int run = 1;
137 139
  int timeouts = 0;
140
  uint32_t event_id = 0;
138 141

  
139 142
  if (s->ths_flags & SUBSCRIPTION_RAW_MPEGTS)
140 143
    http_output_content(hc, "video/mp2t");
......
177 180
    timeouts = 0; //Reset timeout counter
178 181

  
179 182
    switch(sm->sm_type) {
183

  
180 184
    case SMT_PACKET: {
181 185
      if(!mkm)
182 186
        break;
......
196 200
    }
197 201

  
198 202
    case SMT_START:
199

  
200 203
      tvhlog(LOG_DEBUG, "webui",  "Start streaming %s", hc->hc_url_orig);
201

  
202 204
      if (s->ths_flags & SUBSCRIPTION_RAW_MPEGTS) {
203

  
204 205
        struct streaming_start *ss = sm->sm_data;
205
        uint8_t pat_ts[188];
206
        uint8_t pmt_ts[188];  
207
        int pcrpid = ss->ss_pcr_pid;
208
        int pmtpid = 0x0fff;
209

  
210
        //Send PAT
211
        memset(pat_ts, 0xff, 188);
212
        psi_build_pat(NULL, pat_ts+5, 183, pmtpid);
213
        pat_ts[0] = 0x47;
214
        pat_ts[1] = 0x40;
215
        pat_ts[2] = 0x00;
216
        pat_ts[3] = 0x10;
217
        pat_ts[4] = 0x00;
218
        run = (write(hc->hc_fd, pat_ts, 188) == 188);
219

  
206
        run = mk_ts_build_pat_pmt(&pat_pmt_buf, ss, s->ths_service->s_pmt_pid, s->ths_service->s_pcr_pid);
220 207
        if(!run)
221 208
          break;
222 209

  
223
        //Send PMT
224
        memset(pmt_ts, 0xff, 188);
225
        psi_build_pmt(ss, pmt_ts+5, 183, pcrpid);
226
        pmt_ts[0] = 0x47;
227
        pmt_ts[1] = 0x40 | (pmtpid >> 8);
228
        pmt_ts[2] = pmtpid;
229
        pmt_ts[3] = 0x10;
230
        pmt_ts[4] = 0x00;
231
        run = (write(hc->hc_fd, pmt_ts, 188) == 188);
232

  
233 210
      } else {
234

  
235 211
        if(mkm)
236 212
          break;
237 213

  
......
241 217
          http_output_content(hc, "video/x-matroska");
242 218

  
243 219
        mkm = mk_mux_stream_create(hc->hc_fd, sm->sm_data, s->ths_channel);
244

  
245 220
      }
246 221
      break;
247 222

  
......
261 236
      if (s->ths_flags & SUBSCRIPTION_RAW_MPEGTS) {
262 237
        streaming_tsbuf_t *tsbuf = sm->sm_data;
263 238
        uint32_t size = tsbuf->ts_cnt * 188;
239

  
240
        ts_packets_cnt += tsbuf->ts_cnt;
241
        if (ts_packets_cnt >= 1000) {
242
          ts_packets_cnt = 0;
243
          run = write(hc->hc_fd, pat_pmt_buf.pat_ts, 188) == 188;
244
          run = write(hc->hc_fd, pat_pmt_buf.pmt_ts, 188) == 188;
245
        }
246

  
247
        if(!run)
248
          break;
249

  
264 250
        run = (write(hc->hc_fd, tsbuf->ts_data, size) == size);
265 251
      }
266 252
      break;
267
- 
(7-7/8)