MythTV  master
replex.cpp
Go to the documentation of this file.
1 /*
2  * replex.c
3  *
4  *
5  * Copyright (C) 2003 Marcus Metzler <mocm@metzlerbros.de>
6  * Metzler Brothers Systementwicklung GbR
7  * Changes to use MythTV logging
8  * Copyright (C) 2011 Gavin Hurlbut <ghurlbut@mythtv.org>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * General Public License for more details.
20  *
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
26  *
27  */
28 //#define IN_DEBUG
29 
30 
31 #include <stdlib.h>
32 #include <getopt.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <string.h>
40 #include <unistd.h>
41 
42 #include "replex.h"
43 #include "pes.h"
44 
45 #ifndef O_LARGEFILE
46 #define O_LARGEFILE 0
47 #endif
48 
49 extern "C" {
50 #include "libavcodec/avcodec.h"
51 #include "libavformat/avformat.h"
52 }
53 
54 #ifdef _WIN32
55 # define S_IRGRP 0
56 # define S_IWGRP 0
57 # define S_IROTH 0
58 # define S_IWOTH 0
59 #endif
60 
61 #ifndef O_LARGEFILE
62 #define O_LARGEFILE 0
63 #endif
64 
66 
67 static int replex_all_set(struct replex *rx);
68 
69 static int replex_check_id(struct replex *rx, uint16_t id)
70 {
71  int i;
72 
73  if (id==rx->vpid)
74  return 0;
75 
76  for (i=0; i<rx->apidn; i++)
77  if (id==rx->apid[i])
78  return i+1;
79 
80  for (i=0; i<rx->ac3n; i++)
81  if (id==rx->ac3_id[i])
82  return i+0x80;
83 
84  return -1;
85 }
86 
87 static int avcodec_encode_audio(AVCodecContext *avctx,
88  uint8_t *buf, int buf_size,
89  const short *samples)
90 {
91  AVPacket *pkt;
92  AVFrame *frame;
93  int ret, samples_size;
94 
95  pkt = av_packet_alloc();
96  if (pkt == nullptr)
97  {
98  LOG(VB_GENERAL, LOG_ERR, "packet allocation failed");
99  return AVERROR(ENOMEM);
100  }
101 
102  pkt->data = buf;
103  pkt->size = buf_size;
104 
105  if (samples) {
106  frame = av_frame_alloc();
107  if (!frame)
108  {
109  av_packet_free(&pkt);
110  return AVERROR(ENOMEM);
111  }
112 
113  if (avctx->frame_size) {
114  frame->nb_samples = avctx->frame_size;
115  } else {
116  /* if frame_size is not set, the number of samples must be
117  * calculated from the buffer size */
118  int64_t nb_samples;
119  if (!av_get_bits_per_sample(avctx->codec_id)) {
120  av_log(avctx, AV_LOG_ERROR, "avcodec_encode_audio() does not "
121  "support this codec\n");
122  av_frame_free(&frame);
123  av_packet_free(&pkt);
124  return AVERROR(EINVAL);
125  }
126  nb_samples = (int64_t)buf_size * 8 /
127  (av_get_bits_per_sample(avctx->codec_id) *
128  avctx->ch_layout.nb_channels);
129  if (nb_samples >= INT_MAX) {
130  av_frame_free(&frame);
131  av_packet_free(&pkt);
132  return AVERROR(EINVAL);
133  }
134  frame->nb_samples = nb_samples;
135  }
136 
137  /* it is assumed that the samples buffer is large enough based on the
138  * relevant parameters */
139  samples_size = av_samples_get_buffer_size(nullptr, avctx->ch_layout.nb_channels,
140  frame->nb_samples,
141  avctx->sample_fmt, 1);
142  if ((ret = avcodec_fill_audio_frame(frame, avctx->ch_layout.nb_channels,
143  avctx->sample_fmt,
144  (const uint8_t *)samples,
145  samples_size, 1)) < 0) {
146  av_frame_free(&frame);
147  av_packet_free(&pkt);
148  return ret;
149  }
150 
151  frame->pts = AV_NOPTS_VALUE;
152  } else {
153  frame = nullptr;
154  }
155 
156  // SUGGESTION
157  // Now that avcodec_encode_audio2 is deprecated and replaced
158  // by 2 calls, this could be optimized
159  // into separate routines or separate threads.
160  ret = avcodec_receive_packet(avctx, pkt);
161  if (ret != 0)
162  pkt->size=0;
163  if (ret == AVERROR(EAGAIN))
164  ret = 0;
165  if (ret == 0)
166  ret = avcodec_send_frame(avctx, frame);
167 
168  if (ret < 0)
169  {
170  char error[AV_ERROR_MAX_STRING_SIZE+25];
171  strcpy(error,"audio encode error: ");
172  strcat(error, av_make_error_string(error, sizeof(error), ret));
173  LOG(VB_GENERAL, LOG_ERR, error);
174  }
175 
176  /* free any side data since we cannot return it */
177  av_packet_free_side_data(pkt);
178 
179  if (frame && frame->extended_data != frame->data)
180  av_freep(&frame->extended_data);
181 
182  av_frame_free(&frame);
183  int size = pkt->size;
184  av_packet_free(&pkt);
185  return ret ? ret : size;
186 }
187 
188 static int encode_mp2_audio(audio_frame_t *aframe, uint8_t *buffer, int bufsize)
189 {
190  const AVCodec *codec;
191  AVCodecContext *c= nullptr;
192  int frame_size, j, out_size;
193  short *samples;
194 
195  LOG(VB_GENERAL, LOG_INFO, "encoding an MP2 audio frame");
196 
197  /* find the MP2 encoder */
198  codec = avcodec_find_encoder(AV_CODEC_ID_MP2);
199  if (!codec) {
200  LOG(VB_GENERAL, LOG_ERR, "codec not found");
201  return 1;
202  }
203 
204  c = avcodec_alloc_context3(codec);
205 
206  /* put sample parameters */
207  c->bit_rate = aframe->bit_rate;
208  c->sample_rate = aframe->frequency;
209  c->ch_layout.nb_channels = 2;
210  c->sample_fmt = AV_SAMPLE_FMT_S16;
211 
212  /* open it */
213  if (avcodec_open2(c, codec, nullptr) < 0) {
214  LOG(VB_GENERAL, LOG_ERR, "could not open codec");
215  av_free(c);
216  return 1;
217  }
218 
219  /* the codec gives us the frame size, in samples */
220  frame_size = c->frame_size;
221  samples = static_cast<short*>(malloc(frame_size * 2 * c->ch_layout.nb_channels));
222 
223  /* create samples for a single blank frame */
224  for (j=0;j<frame_size;j++) {
225  samples[2*j] = 0;
226  samples[2*j+1] = 0;
227  }
228 
229  /* encode the samples */
230  out_size = avcodec_encode_audio(c, buffer, bufsize, samples);
231 
232  if (out_size != bufsize) {
233  LOG(VB_GENERAL, LOG_ERR,
234  QString("frame size (%1) does not equal required size (%2)?")
235  .arg(out_size).arg(bufsize));
236  free(samples);
237  avcodec_free_context(&c);
238  return 1;
239  }
240 
241  free(samples);
242  avcodec_free_context(&c);
243 
244  return 0;
245 }
246 
247 static void analyze_audio( pes_in_t *p, struct replex *rx, int len, int num, int type)
248 {
249  int c=0;
250  int pos=0;
251  audio_frame_t *aframe = nullptr;
252  index_unit *iu = nullptr;
253  ringbuffer *rbuf = nullptr, *index_buf = nullptr;
254  uint64_t *acount=nullptr;
255  uint64_t *fpts=nullptr;
256  uint64_t *lpts=nullptr;
257  int bsize = 0;
258  int first = 1;
259  audio_sync_buf buf;
260  int off=0;
261  int *apes_abort=nullptr;
262  int re=0;
263 
264  switch ( type ){
265  case AC3:
266 #ifdef IN_DEBUG
267  LOG(VB_GENERAL, LOG_DEBUG, "AC3");
268 #endif
269  aframe = &rx->ac3frame[num];
270  iu = &rx->current_ac3index[num];
271  rbuf = &rx->ac3rbuffer[num];
272  index_buf = &rx->index_ac3rbuffer[num];
273  acount = &rx->ac3frame_count[num];
274  fpts = &rx->first_ac3pts[num];
275  lpts = &rx->last_ac3pts[num];
276  bsize = rx->ac3buf;
277  apes_abort = &rx->ac3pes_abort[num];
278  break;
279 
280  case MPEG_AUDIO:
281 #ifdef IN_DEBUG
282  LOG(VB_GENERAL, LOG_DEBUG, "MPEG AUDIO");
283 #endif
284  aframe = &rx->aframe[num];
285  iu = &rx->current_aindex[num];
286  rbuf = &rx->arbuffer[num];
287  index_buf = &rx->index_arbuffer[num];
288  acount = &rx->aframe_count[num];
289  fpts = &rx->first_apts[num];
290  lpts = &rx->last_apts[num];
291  bsize = rx->audiobuf;
292  apes_abort = &rx->apes_abort[num];
293  break;
294  }
295 
296  *apes_abort = 0;
297  off = ring_rdiff(rbuf, p->ini_pos);
298  while (c < len){
299  if ( (pos = find_audio_sync(rbuf, buf, c+off, type, len-c) )
300  >= 0 ){
301  if (!aframe->set){
302  switch( type ){
303  case AC3:
304  re = get_ac3_info(rbuf, aframe,
305  pos+c+off,
306  len-c-pos);
307  break;
308  case MPEG_AUDIO:
309  re = get_audio_info(rbuf, aframe,
310  pos+c+off,
311  len-c-pos);
312  break;
313  }
314  if ( re == -2){
315  *apes_abort = len -c;
316  return;
317  }
318  if (re < 0) return;
319 
320 
321  if (!rx->ignore_pts){
322  if ((p->flag2 & PTS_ONLY)){
323  *fpts = trans_pts_dts(p->pts);
324  LOG(VB_GENERAL, LOG_INFO,
325  "starting audio PTS: ");
326  printpts(*fpts);
327  } else aframe->set = 0;
328  }
329 
330  if (aframe->set && first)
331  ring_skip(rbuf,pos+c);
332 
333  } else {
334  int diff = ring_posdiff(rbuf, iu->start,
335  p->ini_pos + pos+c);
336 
337  if ( (re = check_audio_header(rbuf, aframe,
338  pos+c+off,len-c-pos,
339  type)) < 0){
340 
341  if ( re == -2){
342  *apes_abort = len -c;
343  return;
344  }
345 
346  if ((int) aframe->framesize > diff){
347  if ( re == -3){
348  c += pos+1;
349  continue;
350  }
351 
352  c += pos+2;
353 #ifdef IN_DEBUG
354  LOG(VB_GENERAL, LOG_DEBUG,
355  QString("WRONG HEADER1 %1").arg(diff));
356 #endif
357  continue;
358  }
359  }
360  if ((int) aframe->framesize > diff){
361  c += pos+2;
362 #if 0
363  LOG(VB_GENERAL, LOG_ERR,
364  QString("WRONG HEADER2 %1").arg(diff));
365 #endif
366  continue;
367  }
368  }
369 
370  // try to fix audio sync - only works for mpeg audio for now
371  if (aframe->set && rx->fix_sync && first && type == MPEG_AUDIO){
372  int frame_time = aframe->frametime;
373  int64_t diff;
374  diff = ptsdiff(trans_pts_dts(p->pts), add_pts_audio(0, aframe,*acount + 1) + *fpts);
375  if (abs ((int)diff) >= frame_time){
376  LOG(VB_GENERAL, LOG_INFO,
377  "fixing audio PTS inconsistency - diff: ");
378  printpts(abs(diff));
379 
380  if (diff < 0){
381  diff = abs(diff);
382  int framesdiff = diff / frame_time;
383  LOG(VB_GENERAL, LOG_INFO,
384  QString(" - need to remove %1 frame(s)")
385  .arg(framesdiff));
386 
387  // FIXME can only remove one frame at a time for now
388  if (framesdiff > 1)
389  framesdiff = 1;
390  iu->pts = add_pts_audio(0, aframe, -framesdiff);
391  c += aframe->framesize;
392  continue;
393  } else {
394  int framesdiff = diff / frame_time;
395  LOG(VB_GENERAL, LOG_INFO,
396  QString(" - need to add %1 frame(s)")
397  .arg(framesdiff));
398 
399  // limit inserts to a maximum of 5 frames
400  if (framesdiff > 5)
401  framesdiff = 5;
402 
403  // alloc memmory for audio frame
404  uint8_t *framebuf;
405  if ( !(framebuf = (uint8_t *) malloc(sizeof(uint8_t) * aframe->framesize))) {
406  LOG(VB_GENERAL, LOG_ERR,
407  "Not enough memory for audio frame");
408  exit(1);
409  }
410 
411  // try to encode a blank frame
412  if (encode_mp2_audio(aframe, framebuf, sizeof(uint8_t) * aframe->framesize) != 0) {
413  // encode failed so just use a copy of the current frame
414  int res;
415  res = ring_peek(rbuf, framebuf, aframe->framesize, 0);
416  if (res != (int) aframe->framesize) {
417  LOG(VB_GENERAL, LOG_ERR,
418  QString("ring buffer failed to peek frame res: %1")
419  .arg(res));
420  exit(1);
421  }
422  }
423 
424  // add each extra frame required direct to the output file
425  int x;
426  for (x = 0; x < framesdiff; x++){
427  if (rx->dmx_out[num+1]){
428  write(rx->dmx_out[num+1], framebuf, aframe->framesize);
429  }
430  *acount += 1;
431  }
432 
433  free(framebuf);
434  }
435  }
436  }
437 
438  if (aframe->set){
439  if(iu->active){
440  iu->length = ring_posdiff(rbuf,
441  iu->start,
442  p->ini_pos +
443  pos+c);
444 
445  if (iu->length < aframe->framesize ||
446  iu->length > aframe->framesize+1){
447  LOG(VB_GENERAL, LOG_ERR,
448  QString("Wrong audio frame size: %1")
449  .arg(iu->length));
450  iu->err= FRAME_ERR;
451  }
452  if (ring_write(index_buf,
453  (uint8_t *)iu,
454  sizeof(index_unit)) < 0){
455  LOG(VB_GENERAL, LOG_ERR,
456  "audio ring buffer overrun error");
457  exit(1);
458  }
459  *acount += 1;
460  }
461 
462  init_index(iu);
463  iu->active = 1;
464  iu->pts = add_pts_audio(0, aframe,*acount);
465  iu->framesize = aframe->framesize;
466 
467  if (!rx->ignore_pts &&
468  first && (p->flag2 & PTS_ONLY)){
469  int64_t diff;
470 
471  diff = ptsdiff(trans_pts_dts(p->pts),
472  iu->pts + *fpts);
473  if( !rx->keep_pts && (llabs(diff) > 40*CLOCK_MS)){
474  LOG(VB_GENERAL, LOG_ERR,
475  "audio PTS inconsistent:");
476  printpts(trans_pts_dts(p->pts)-*fpts);
477  printpts(iu->pts);
478  LOG(VB_GENERAL, LOG_ERR,
479  "diff: ");
480  printpts(abs(diff));
481  }
482  if (rx->keep_pts){
483  fix_audio_count(acount, aframe,
485  p->pts),
486  *fpts),
487  iu->pts);
488  iu->pts = uptsdiff(trans_pts_dts(p->pts),
489  *fpts);
490  if (*lpts && ptsdiff(iu->pts,*lpts)<0)
491  LOG(VB_GENERAL, LOG_WARNING,
492  "Warning negative audio PTS increase!\n");
493  *lpts = iu->pts;
494  }
495  first = 0;
496  }
497  if (rx->analyze >1){
498  if ((p->flag2 & PTS_ONLY)){
499  iu->pts = trans_pts_dts(p->pts);
500  } else {
501  iu->pts = 0;
502  }
503  }
504  iu->start = (p->ini_pos+pos+c)%bsize;
505  }
506  c += pos;
507  if (c + (int) aframe->framesize > len){
508 #if 0
509  LOG(VB_GENERAL, LOG_INFO,
510  QString("SHORT %1").arg(len-c));
511 #endif
512  c = len;
513  } else {
514  c += aframe->framesize;
515  }
516  } else {
517  *apes_abort = len-c;
518  c=len;
519  }
520  }
521 }
522 
523 static void analyze_video( pes_in_t *p, struct replex *rx, int len)
524 {
525  std::vector<uint8_t> buf(8);
526  int c=0;
527  int pos=0;
528  uint8_t head;
529  int seq_end = 0;
530  uint8_t frame = 0;
531  uint64_t newpts = 0;
532  uint64_t newdts = 0;
533  index_unit *iu;
534  int off=0;
535  ringbuffer *rbuf;
536  ringbuffer *index_buf;
537  sequence_t *s;
538  int i;
539 
540  uint16_t tempref = 0;
541  int seq_h = 0;
542  int gop = 0;
543  int frame_off = 0;
544  int gop_off = 0;
545  int seq_p = 0;
546  int flush=0;
547 
548  rbuf = &rx->vrbuffer;
549  index_buf = &rx->index_vrbuffer;
550  iu = &rx->current_vindex;
551  s = &rx->seq_head;
552 
553  rx->vpes_abort = 0;
554  off = ring_rdiff(rbuf, p->ini_pos);
555 #ifdef IN_DEBUG
556  LOG(VB_GENERAL, LOG_DEBUG, QString(" ini pos %1")
557  .arg((p->ini_pos)%rx->videobuf));
558 #endif
559 
560 
561 #if 0
562  LOG(VB_GENERAL, LOG_INFO, QString("len %1 %2").arg(len).arg(off));
563 #endif
564  while (c < len){
565  if ((pos = ring_find_any_header( rbuf, &head, c+off, len-c))
566  >=0 ){
567  switch(head){
568  case SEQUENCE_HDR_CODE:
569 #ifdef IN_DEBUG
570  LOG(VB_GENERAL, LOG_DEBUG, QString(" seq headr %1")
571  .arg((p->ini_pos+c+pos)%rx->videobuf));
572 #endif
573 
574  seq_h = 1;
575  seq_p = c+pos;
576 
577 
578  if (!s->set){
579  int re=0;
580  re = get_video_info(rbuf, &rx->seq_head,
581  pos+c+off, len -c -pos);
582 
583 #ifdef IN_DEBUG
584  LOG(VB_GENERAL, LOG_DEBUG,
585  QString(" seq headr result %1")
586  .arg(re));
587 #endif
588  if (re == -2){
589  rx->vpes_abort = len -(c+pos-1);
590  return;
591  }
592  if (s->set){
593  ring_skip(rbuf, pos+c);
594  off -= pos+c;
595  }
596  if (!rx->ignore_pts &&
597  !(p->flag2 & PTS_ONLY)) s->set = 0;
598  }
599  if (s->set){
600  flush = 1;
601  }
602  break;
603 
604  case EXTENSION_START_CODE:{
605  int ext_id = 0;
606 
607 #ifdef IN_DEBUG
608  LOG(VB_GENERAL, LOG_DEBUG,
609  QString(" seq ext headr %1")
610  .arg((p->ini_pos+c+pos)+rx->videobuf));
611 #endif
612  ext_id = get_video_ext_info(rbuf,
613  &rx->seq_head,
614  pos+c+off,
615  len -c -pos);
616  if (ext_id == -2){
617  rx->vpes_abort = len - (pos-1+c);
618  return;
619  }
620 
621 
622  if(ext_id == PICTURE_CODING_EXTENSION
623  && s->ext_set && iu->active){
624  if (!rx->ignore_pts &&
625  !rx->vframe_count &&
626  !rx->first_vpts){
628  p->pts);
629 
630  for (i = 0; i< s->current_tmpref;
631  i++) ptsdec(&rx->first_vpts,
632  SEC_PER);
633  LOG(VB_GENERAL, LOG_INFO,
634  "starting with video PTS:");
635  printpts(rx->first_vpts);
636  }
637 
638  newpts = 0;
639 #ifdef IN_DEBUG
640 
641  LOG(VB_GENERAL, LOG_DEBUG,
642  QString("fcount %1 gcount %2 tempref %3 %4")
643  .arg(rx->vframe_count).arg(rx->vgroup_count)
644  .arg(s->current_tmpref)
645  .arg(s->current_tmpref - rx->vgroup_count
646  + rx->vframe_count));
647 #endif
648  newdts = next_ptsdts_video(
649  &newpts,s, rx->vframe_count,
650  rx->vgroup_count);
651 
652  if (!rx->ignore_pts &&
653  (p->flag2 & PTS_ONLY)){
654  int64_t diff;
655 
656  diff = ptsdiff(iu->pts,
657  rx->first_vpts
658  + newpts);
659 
660  if (!rx->keep_pts &&
661  (llabs(diff) > 3*SEC_PER/2)){
662  LOG(VB_GENERAL, LOG_INFO,
663  "video PTS inconsistent:");
664  printpts(trans_pts_dts(p->pts));
665  printpts(iu->pts);
666  printpts(newpts+rx->first_vpts);
667  printpts(newpts);
668  LOG(VB_GENERAL, LOG_INFO,
669  " diff: ");
670  printpts(abs((int)diff));
671  }
672  }
673 
674  if (!rx->ignore_pts &&
675  (p->flag2 & PTS_DTS) == PTS_DTS){
676  int64_t diff;
677  diff = ptsdiff(iu->dts,
678  newdts +
679  rx->first_vpts);
680  if (!rx->keep_pts &&
681  (llabs(diff) > 3*SEC_PER/2)){
682  LOG(VB_GENERAL, LOG_INFO,
683  "video DTS inconsistent: ");
684  printpts(trans_pts_dts(p->dts));
685  printpts(iu->dts);
686  printpts(newdts+rx->first_vpts);
687  printpts(newdts);
688  LOG(VB_GENERAL, LOG_INFO,
689  "diff: ");
690  printpts(abs((int)diff));
691  }
692  }
693  if (!rx->keep_pts){
694  iu->pts = newpts;
695  iu->dts = newdts;
696  } else {
697  if (p->flag2 & PTS_DTS){
698  ptsdec(&iu->pts,
699  rx->first_vpts);
700 
701  if ((p->flag2 & PTS_DTS) == PTS_DTS){
702  ptsdec(&iu->dts,
703  rx->first_vpts);
704  } else iu->dts = newdts;
705 
707  iu->pts,newpts,
708  iu->dts,newdts);
709 
710  } else {
711  iu->pts = newpts;
712  iu->dts = newdts;
713  }
714  }
715  if (rx->last_vpts &&
716  ptsdiff(iu->dts, rx->last_vpts) <0)
717  LOG(VB_GENERAL, LOG_WARNING,
718  "Warning negative video PTS increase!");
719  rx->last_vpts = iu->dts;
720  }
721 
722  if (rx->analyze){
723  if ((p->flag2 & PTS_DTS) == PTS_DTS){
724  iu->pts = trans_pts_dts(p->pts);
725  iu->dts = trans_pts_dts(p->dts);
726  } else if (p->flag2 & PTS_ONLY){
727  iu->pts = trans_pts_dts(p->pts);
728  iu->dts = 0;
729  } else {
730  iu->pts = 0;
731  iu->dts = 0;
732  }
733  }
734 
735 
736  break;
737  }
738 
739  case SEQUENCE_END_CODE:
740 #ifdef IN_DEBUG
741  LOG(VB_GENERAL, LOG_DEBUG, QString(" seq end %1")
742  .arg((p->ini_pos+c+pos)%rx->videobuf));
743 #endif
744  if (s->set)
745  seq_end = 1;
746 
747  break;
748 
749  case GROUP_START_CODE:{
750 //#define ANA
751 #ifdef ANA
752  LOG(VB_GENERAL, LOG_DEBUG, QString(" %1")
753  .arg(rx->vgroup_count));
754 #endif
755 
756  if (s->set){
757  if (!seq_h) flush = 1;
758  }
759  gop = 1;
760  gop_off = c+pos - seq_p;
761 
762  if (ring_peek(rbuf, buf, 7, off+c+pos) < 0) {
763  rx->vpes_abort = len -(c+pos-1);
764  return;
765  }
766 #ifdef IN_DEBUG
767  int hour = (int)((buf[4]>>2)& 0x1F);
768  int min = (int)(((buf[4]<<4)& 0x30)|
769  ((buf[5]>>4)& 0x0F));
770  int sec = (int)(((buf[5]<<3)& 0x38)|
771  ((buf[6]>>5)& 0x07));
772  LOG(VB_GENERAL, LOG_DEBUG,
773  QString(" gop %1:%2.%3 %4")
774  .arg(hour,2,10,QChar('0'))
775  .arg(min, 2,10,QChar('0'))
776  .arg(sec, 2,10,QChar('0'))
777  .arg((p->ini_pos+c+pos)%rx->videobuf));
778 #endif
779  rx->vgroup_count = 0;
780 
781  break;
782  }
783 
784  case PICTURE_START_CODE:{
785  if (len-(c+pos) < 14){
786  rx->vpes_abort = len - (pos-1+c);
787  return;
788  }
789 
790  if (ring_peek(rbuf, buf, 6,
791  off+c+pos) < 0) return;
792 
793 
794  frame = ((buf[5]&0x38) >>3);
795 
796  if (frame == I_FRAME){
797  if( !rx->first_iframe){
798  if (s->set){
799  rx->first_iframe = 1;
800  } else {
801  s->set=0;
802  flush = 0;
803  break;
804  }
805  }
806  }
807 
808  frame_off = c+pos - seq_p;
809  if (s->set){
810  if (!seq_h && !gop) flush = 1;
811  }
812  tempref = (buf[5]>>6) & 0x03;
813  tempref |= buf[4] << 2;
814 
815  switch (frame){
816  case I_FRAME:
817 #ifdef ANA
818  LOG(VB_GENERAL, LOG_DEBUG, "I");
819 #endif
820 #ifdef IN_DEBUG
821  LOG(VB_GENERAL, LOG_DEBUG,
822  QString(" I-frame %1")
823  .arg((p->ini_pos+c+pos)%rx->videobuf));
824 #endif
825  break;
826  case B_FRAME:
827 #ifdef ANA
828  LOG(VB_GENERAL, LOG_DEBUG, "B");
829 #endif
830 #ifdef IN_DEBUG
831  LOG(VB_GENERAL, LOG_DEBUG,
832  QString(" B-frame %1")
833  .arg((p->ini_pos+c+pos)%rx->videobuf));
834 #endif
835  break;
836  case P_FRAME:
837 #ifdef ANA
838  LOG(VB_GENERAL, LOG_DEBUG, "P");
839 #endif
840 #ifdef IN_DEBUG
841  LOG(VB_GENERAL, LOG_DEBUG,
842  QString(" P-frame %1")
843  .arg((p->ini_pos+c+pos)%rx->videobuf));
844 #endif
845  break;
846  }
847  s->current_frame = frame;
848  s->current_tmpref = tempref;
849 
850  break;
851  }
852  default:
853 #ifdef IN_DEBUG
854 #if 0
855  LOG(VB_GENERAL, LOG_ERR,
856  QString("other header 0x%1 (%2+%3)")
857  .arg(head, 2,16,QChar('0')).arg(c).arg(pos));
858 #endif
859 #endif
860  break;
861  }
862 
863  if (flush && s->set && rx->first_iframe){
864  if(iu->active){
865  rx->vframe_count++;
866  rx->vgroup_count++;
867 
868  iu->length = ring_posdiff(rbuf,
869  iu->start,
870  p->ini_pos+
871  pos+c-frame_off);
872 
873  if ( ring_write(index_buf, (uint8_t *)
874  &rx->current_vindex,
875  sizeof(index_unit))<0){
876  LOG(VB_GENERAL, LOG_ERR,
877  "video ring buffer overrun error");
878  exit(1);
879 
880  }
881  }
883  flush = 0;
884  iu->active = 1;
885  if (!rx->ignore_pts){
886  if ((p->flag2 & PTS_DTS) == PTS_DTS){
887  iu->pts = trans_pts_dts(p->pts);
888  iu->dts = trans_pts_dts(p->dts);
889  } else if (p->flag2 & PTS_ONLY){
890  iu->pts = trans_pts_dts(p->pts);
891  }
892  }
893  iu->start = (p->ini_pos+pos+c-frame_off)
894  %rx->videobuf;
895 #ifdef IN_DEBUG
896  LOG(VB_GENERAL, LOG_DEBUG,
897  QString("START %1").arg(iu->start));
898 #endif
899  }
900 
901  if (s->set){
902  if (frame)
903  iu->frame = (frame&0xFF);
904  if (seq_h)
905  iu->seq_header = 1;
906  if (seq_end)
907  iu->seq_end = 1;
908  if (gop)
909  iu->gop = 1;
910  if (gop_off)
911  iu->gop_off = gop_off;
912  if (frame_off)
913  iu->frame_off = frame_off;
914  }
915  c+=pos+4;
916  } else {
917  if (pos == -2){
918  rx->vpes_abort = 4;
919 
920  }
921  c = len;
922  }
923  }
924 }
925 
926 static void es_out(pes_in_t *p)
927 {
928 
929  struct replex *rx;
930  char t[80];
931  int len;
932 
933  len = p->plength-3-p->hlength;
934 
935  rx = (struct replex *) p->priv;
936 
937  switch(p->type)
938  {
939  case 0xE0: {
940  sprintf(t, "Video ");
941  if (rx->vpes_abort){
942  p->ini_pos = (p->ini_pos - rx->vpes_abort)%rx->vrbuffer.size;
943  len += rx->vpes_abort;
944  }
945  analyze_video(p, rx, len);
946  if (!rx->seq_head.set){
947  ring_skip(&rx->vrbuffer, len);
948  }
949  break;
950  }
951 
952  case 1 ... 32:{
953  int l;
954  l = p->type - 1;
955  sprintf(t, "Audio%d ", l);
956  if (rx->apes_abort[l]){
957  p->ini_pos = (p->ini_pos - rx->apes_abort[l])
958  %rx->arbuffer[l].size;
959  len += rx->apes_abort[l];
960  }
961  analyze_audio(p, rx, len, l, MPEG_AUDIO);
962  if (!rx->aframe[l].set)
963  ring_skip(&rx->arbuffer[l], len);
964 
965  break;
966  }
967 
968  case 0x80 ... 0x87:{
969  int l;
970  l = p->type - 0x80;
971  sprintf(t, "AC3 %d ", p->type);
972  if (rx->ac3pes_abort[l]){
973  p->ini_pos = (p->ini_pos - rx->ac3pes_abort[l])
974  %rx->ac3rbuffer[l].size;
975  len += rx->ac3pes_abort[l];
976  }
977  analyze_audio(p, rx, len, l, AC3);
978  if (!rx->ac3frame[l].set)
979  ring_skip(&rx->ac3rbuffer[l], len);
980  break;
981  }
982 
983  default:
984  LOG(VB_GENERAL, LOG_ERR,
985  QString("UNKNOWN AUDIO type %1").arg(p->type));
986  return;
987 
988 
989  }
990 
991 #ifdef IN_DEBUG
992  LOG(VB_GENERAL, LOG_DEBUG, QString("%1 PES").arg(t));
993 #endif
994 }
995 
996 static void pes_es_out(pes_in_t *p)
997 {
998 
999  struct replex *rx;
1000  char t[80];
1001  int len, i;
1002  int l=0;
1003 
1004  len = p->plength-3-p->hlength;
1005  rx = (struct replex *) p->priv;
1006 
1007  switch(p->cid){
1008  case VIDEO_STREAM_S ... VIDEO_STREAM_E:
1009  if (rx->vpid != p->cid) break;
1010  p->type = 0xE0;
1011  p->ini_pos = ring_wpos(&rx->vrbuffer);
1012 
1013  if (ring_write(&rx->vrbuffer, p->buf+9+p->hlength, len)<0){
1014  LOG(VB_GENERAL, LOG_ERR,
1015  "video ring buffer overrun error");
1016  exit(1);
1017  }
1018  if (rx->vpes_abort){
1019  p->ini_pos = (p->ini_pos - rx->vpes_abort)%rx->vrbuffer.size;
1020  len += rx->vpes_abort;
1021  }
1022  sprintf(t, "Video ");
1023  analyze_video(p, rx, len);
1024  if (!rx->seq_head.set){
1025  ring_skip(&rx->vrbuffer, len);
1026  }
1027  break;
1028 
1029  case AUDIO_STREAM_S ... AUDIO_STREAM_E:
1030  p->type = p->cid - 0xc0 + 1;
1031  l = -1;
1032  for (i=0; i<rx->apidn; i++)
1033  if (p->cid == rx->apid[i])
1034  l = i;
1035  if (l < 0) break;
1036  p->ini_pos = ring_wpos(&rx->arbuffer[l]);
1037  if (ring_write(&rx->arbuffer[l], p->buf+9+p->hlength, len)<0){
1038  LOG(VB_GENERAL, LOG_ERR,
1039  "video ring buffer overrun error");
1040  exit(1);
1041  }
1042  if (rx->apes_abort[l]){
1043  p->ini_pos = (p->ini_pos - rx->apes_abort[l])
1044  %rx->arbuffer[l].size;
1045  len += rx->apes_abort[l];
1046  }
1047 
1048  sprintf(t, "Audio%d ", l);
1049  analyze_audio(p, rx, len, l, MPEG_AUDIO);
1050  if (!rx->aframe[l].set)
1051  ring_skip(&rx->arbuffer[l], len);
1052 
1053  break;
1054 
1055  case PRIVATE_STREAM1:{
1056  int hl=4;
1057  if (rx->vdr){
1058  hl=0;
1059  p->type=0x80;
1060  l = 0;
1061  } else {
1062  uint16_t fframe;
1063 
1064  fframe=0;
1065  fframe = p->buf[9+p->hlength+3];
1066  fframe |= (p->buf[9+p->hlength+2]<<8);
1067 
1068  if (fframe > p->plength) break;
1069 
1070  p->type = p->buf[9+p->hlength];
1071  l = -1;
1072  for (i=0; i<rx->ac3n; i++)
1073  if (p->type == rx->ac3_id[i])
1074  l = i;
1075  if (l < 0) break;
1076  }
1077  len -= hl;
1078  p->ini_pos = ring_wpos(&rx->ac3rbuffer[l]);
1079 
1080  if (ring_write(&rx->ac3rbuffer[l], p->buf+9+hl+p->hlength, len)<0){
1081  LOG(VB_GENERAL, LOG_ERR,
1082  "video ring buffer overrun error");
1083  exit(1);
1084  }
1085  if (rx->ac3pes_abort[l]){
1086  p->ini_pos = (p->ini_pos - rx->ac3pes_abort[l])
1087  %rx->ac3rbuffer[l].size;
1088  len += rx->ac3pes_abort[l];
1089  }
1090 
1091  sprintf(t, "AC3 %d ", p->type);
1092  analyze_audio(p, rx, len, l, AC3);
1093  sprintf(t,"%d",rx->ac3frame[l].set);
1094  if (!rx->ac3frame[l].set)
1095  ring_skip(&rx->ac3rbuffer[l], len);
1096  }
1097  break;
1098 
1099  default:
1100  return;
1101  }
1102 
1103 #ifdef IN_DEBUG
1104  LOG(VB_GENERAL, LOG_DEBUG, QString("%1 PES %2").arg(t).arg(len));
1105 #endif
1106 }
1107 
1108 static void avi_es_out(pes_in_t *p)
1109 {
1110 
1111  struct replex *rx;
1112  char t[80];
1113  int len;
1114 
1115  len = p->plength;
1116 
1117  rx = (struct replex *) p->priv;
1118 
1119 
1120  switch(p->type)
1121  {
1122  case 0xE0: {
1123  sprintf(t, "Video ");
1124  if (!len){
1125  rx->vframe_count++;
1126  break;
1127  }
1128  analyze_video(p, rx, len);
1129  if (!rx->seq_head.set){
1130  ring_skip(&rx->vrbuffer, len);
1131  }
1132  break;
1133  }
1134 
1135  case 1 ... 32:{
1136  int l;
1137  l = p->type - 1;
1138  sprintf(t, "Audio%d ", l);
1139  if (!len){
1140  rx->aframe_count[l]++;
1141  break;
1142  }
1143  analyze_audio(p, rx, len, l, MPEG_AUDIO);
1144  if (!rx->aframe[l].set)
1145  ring_skip(&rx->arbuffer[l], len);
1146 
1147  break;
1148  }
1149 
1150  case 0x80 ... 0x87:{
1151  int l;
1152 
1153  l = p->type - 0x80;
1154  sprintf(t, "AC3 %d ", p->type);
1155  if (!len){
1156  rx->ac3frame_count[l]++;
1157  break;
1158  }
1159  analyze_audio(p, rx, len, l, AC3);
1160  if (!rx->ac3frame[l].set)
1161  ring_skip(&rx->ac3rbuffer[l], len);
1162  break;
1163  }
1164 
1165  default:
1166  return;
1167 
1168 
1169  }
1170 #ifdef IN_DEBUG
1171  LOG(VB_GENERAL, LOG_DEBUG, QString("%1 PES").arg(t));
1172 #endif
1173 
1174 }
1175 
1176 
1177 static int replex_tsp(struct replex *rx, uint8_t *tsp)
1178 {
1179  uint16_t pid;
1180  int type;
1181  int off=0;
1182  pes_in_t *p=nullptr;
1183 
1184  pid = get_pid(tsp+1);
1185 
1186  if ((type=replex_check_id(rx, pid))<0)
1187  return 0;
1188 
1189  switch(type){
1190  case 0:
1191  p = &rx->pvideo;
1192  break;
1193 
1194  case 1 ... 32:
1195  p = &rx->paudio[type-1];
1196  break;
1197 
1198  case 0x80 ... 0x87:
1199  p = &rx->pac3[type-0x80];
1200  break;
1201  default:
1202  return 0;
1203 
1204  }
1205 
1206 
1207  if ( tsp[1] & PAY_START) {
1208  if (p->plength == MMAX_PLENGTH-6){
1209  p->plength = p->found-6;
1210  es_out(p);
1211  init_pes_in(p, p->type, nullptr, 0);
1212  }
1213  }
1214 
1215  if ( tsp[3] & ADAPT_FIELD) { // adaptation field?
1216  off = tsp[4] + 1;
1217  if (off+4 >= TS_SIZE) return 0;
1218  }
1219 
1220  get_pes(p, tsp+4+off, TS_SIZE-4-off, es_out);
1221 
1222  return 0;
1223 }
1224 
1225 
1226 static ssize_t save_read(struct replex *rx, void *buf, size_t count)
1227 {
1228  ssize_t neof = 1;
1229  size_t re = 0;
1230  int fd = rx->fd_in;
1231 
1232  if (rx->itype== REPLEX_AVI){
1233  int l = rx->inflength - rx->finread;
1234  if ( l <= 0) return 0;
1235  if ( (int) count > l) count = l;
1236  }
1237  while(neof >= 0 && re < count){
1238  neof = read(fd, ((char*)buf)+re, count - re);
1239  if (neof > 0) re += neof;
1240  else break;
1241  }
1242  rx->finread += re;
1243 #ifndef OUT_DEBUG
1244  if (rx->inflength){
1245  uint8_t per=0;
1246 
1247  per = (uint8_t)(rx->finread*100/rx->inflength);
1248  if (per % 10 == 0 && rx->lastper < per){
1249  LOG(VB_GENERAL, LOG_DEBUG, QString("read %1%%")
1250  .arg(per,3));
1251  rx->lastper = per;
1252  }
1253  } else
1254  LOG(VB_GENERAL, LOG_DEBUG, QString("read %1 MB")
1255  .arg(rx->finread/1024.0/1024.0, 0,'f',2,QChar('0')));
1256 #endif
1257  if (neof < 0 && re == 0) return neof;
1258  else return re;
1259 }
1260 
1261 static int guess_fill( struct replex *rx)
1262 {
1263  int vavail, aavail, ac3avail, i, fill;
1264 
1265  vavail = 0;
1266  ac3avail =0;
1267  aavail = 0;
1268  fill =0;
1269 
1270 #define LIMIT 3
1271  if ((vavail = ring_avail(&rx->index_vrbuffer)/sizeof(index_unit))
1272  < LIMIT)
1273  fill = ring_free(&rx->vrbuffer);
1274 
1275  for (i=0; i<rx->apidn;i++){
1276  if ((aavail = ring_avail(&rx->index_arbuffer[i])
1277  /sizeof(index_unit)) < LIMIT)
1278  if (fill < (int) ring_free(&rx->arbuffer[i]))
1279  fill = ring_free(&rx->arbuffer[i]);
1280  }
1281 
1282  for (i=0; i<rx->ac3n;i++){
1283  if ((ac3avail = ring_avail(&rx->index_ac3rbuffer[i])
1284  /sizeof(index_unit)) < LIMIT)
1285  if (fill < (int) ring_free(&rx->ac3rbuffer[i]))
1286  fill = ring_free(&rx->ac3rbuffer[i]);
1287  }
1288 
1289 #if 0
1290  LOG(VB_GENERAL, LOG_INFO,
1291  QString("free %1 %2 %3 %4")
1292  .arg(fill).arg(vavail).arg(aavail).arg(ac3avail));
1293 #endif
1294 
1295  if (!fill){
1296  if(vavail && (aavail || ac3avail)) return 0;
1297  else return -1;
1298  }
1299 
1300  return fill/2;
1301 }
1302 
1303 
1304 
1305 #define IN_SIZE (1000*TS_SIZE)
1306 static void find_pids_file(struct replex *rx)
1307 {
1308  uint8_t buf[IN_SIZE];
1309  int afound=0;
1310  int vfound=0;
1311  int count=0;
1312  int re=0;
1313  uint16_t vpid=0, apid=0, ac3pid=0;
1314 
1315  LOG(VB_GENERAL, LOG_INFO, "Trying to find PIDs");
1316  while (!afound && !vfound && count < (int) rx->inflength){
1317  if (rx->vpid) vfound = 1;
1318  if (rx->apidn) afound = 1;
1319  if ((re = save_read(rx,buf,IN_SIZE))<0)
1320  LOG(VB_GENERAL, LOG_ERR,
1321  QString("reading: %1").arg(strerror(errno)));
1322  else
1323  count += re;
1324  if ( (re = find_pids(&vpid, &apid, &ac3pid, buf, re))){
1325  if (!rx->vpid && vpid){
1326  rx->vpid = vpid;
1327  LOG(VB_GENERAL, LOG_INFO,QString("vpid 0x%1")
1328  .arg(rx->vpid, 4,16,QChar('0')));
1329  vfound++;
1330  }
1331  if (!rx->apidn && apid){
1332  rx->apid[0] = apid;
1333  LOG(VB_GENERAL, LOG_INFO, QString("apid 0x%1")
1334  .arg(rx->apid[0], 4,16,QChar('0')));
1335  rx->apidn++;
1336  afound++;
1337  }
1338  if (!rx->ac3n && ac3pid){
1339  rx->ac3_id[0] = ac3pid;
1340  LOG(VB_GENERAL, LOG_INFO, QString("ac3pid 0x%1")
1341  .arg(rx->ac3_id[0], 4,16,QChar('0')));
1342  rx->ac3n++;
1343  afound++;
1344  }
1345 
1346  }
1347 
1348  }
1349 
1350  lseek(rx->fd_in,0,SEEK_SET);
1351  if (!afound || !vfound){
1352  LOG(VB_GENERAL, LOG_ERR, "Couldn't find all pids");
1353  exit(1);
1354  }
1355 
1356 }
1357 
1358 #define MAXVPID 16
1359 #define MAXAPID 32
1360 #define MAXAC3PID 16
1361 static void find_all_pids_file(struct replex *rx)
1362 {
1363  uint8_t buf[IN_SIZE];
1364  int count=0;
1365  int j;
1366  int re=0;
1367  uint16_t vpid[MAXVPID], apid[MAXAPID], ac3pid[MAXAC3PID];
1368  int vn=0, an=0,ac3n=0;
1369  uint16_t vp,ap,cp;
1370  int vpos, apos, cpos;
1371 
1372  memset (vpid , 0 , MAXVPID*sizeof(uint16_t));
1373  memset (apid , 0 , MAXAPID*sizeof(uint16_t));
1374  memset (ac3pid , 0 , MAXAC3PID*sizeof(uint16_t));
1375 
1376  LOG(VB_GENERAL, LOG_INFO, "Trying to find PIDs");
1377  while (count < (int) rx->inflength-IN_SIZE){
1378  if ((re = save_read(rx,buf,IN_SIZE))<0)
1379  LOG(VB_GENERAL, LOG_ERR, QString("reading: %1")
1380  .arg(strerror(errno)));
1381  else
1382  count += re;
1383  if ( (re = find_pids_pos(&vp, &ap, &cp, buf, re,
1384  &vpos, &apos, &cpos))){
1385  if (vp){
1386  int old=0;
1387  for (j=0; j < vn; j++){
1388 #if 0
1389  LOG(VB_GENERAL, LOG_INFO,
1390  QString("%1. %2").arg(j+1).arg(vpid[j]));
1391 #endif
1392  if (vpid[j] == vp){
1393  old = 1;
1394  break;
1395  }
1396  }
1397  if (!old){
1398  vpid[vn]=vp;
1399 
1400  LOG(VB_GENERAL, LOG_INFO,
1401  QString("vpid %1: 0x%2 (%3) PES ID: 0x%4")
1402  .arg(vn+1)
1403  .arg(vpid[vn], 4,16,QChar('0'))
1404  .arg(vpid[vn])
1405  .arg(buf[vpos], 2,16,QChar('0')));
1406  if (vn+1 < MAXVPID) vn++;
1407  }
1408  }
1409 
1410  if (ap){
1411  int old=0;
1412  for (j=0; j < an; j++)
1413  if (apid[j] == ap){
1414  old = 1;
1415  break;
1416  }
1417  if (!old){
1418  apid[an]=ap;
1419  LOG(VB_GENERAL, LOG_INFO,
1420  QString("apid %1: 0x%2 (%3) PES ID: 0x%4")
1421  .arg(an +1)
1422  .arg(apid[an], 4,16,QChar('0'))
1423  .arg(apid[an])
1424  .arg(buf[apos], 2,16,QChar('0')));
1425  if (an+1 < MAXAPID) an++;
1426  }
1427  }
1428 
1429  if (cp){
1430  int old=0;
1431  for (j=0; j < ac3n; j++)
1432  if (ac3pid[j] == cp){
1433  old = 1;
1434  break;
1435  }
1436  if (!old){
1437  ac3pid[ac3n]=cp;
1438  LOG(VB_GENERAL, LOG_INFO,
1439  QString("ac3pid %1: 0x%2 (%3)")
1440  .arg(ac3n+1)
1441  .arg(ac3pid[ac3n], 4,16,QChar('0'))
1442  .arg(ac3pid[ac3n]));
1443  if (ac3n+1< MAXAC3PID) ac3n++;
1444  }
1445  }
1446  }
1447 
1448  }
1449 
1450  lseek(rx->fd_in,0,SEEK_SET);
1451 }
1452 
1453 static void find_pids_stdin(struct replex *rx, uint8_t *buf, int len)
1454 {
1455  int afound=0;
1456  int vfound=0;
1457  uint16_t vpid=0, apid=0, ac3pid=0;
1458 
1459  if (rx->vpid) vfound = 1;
1460  if (rx->apidn) afound = 1;
1461  LOG(VB_GENERAL, LOG_INFO, "Trying to find PIDs");
1462  if ( find_pids(&vpid, &apid, &ac3pid, buf, len) ){
1463  if (!rx->vpid && vpid){
1464  rx->vpid = vpid;
1465  vfound++;
1466  }
1467  if (!rx->apidn && apid){
1468  rx->apid[0] = apid;
1469  rx->apidn++;
1470  afound++;
1471  ring_init(&rx->arbuffer[0], rx->audiobuf);
1472  init_pes_in(&rx->paudio[0], 1, &rx->arbuffer[0], 0);
1473  rx->paudio[0].priv = (void *) rx;
1474  ring_init(&rx->index_arbuffer[0], INDEX_BUF);
1475  memset(&rx->aframe[0], 0, sizeof(audio_frame_t));
1476  init_index(&rx->current_aindex[0]);
1477  rx->aframe_count[0] = 0;
1478  rx->first_apts[0] = 0;
1479  }
1480 
1481  if (!rx->ac3n && ac3pid){
1482  rx->ac3_id[0] = ac3pid;
1483  rx->ac3n++;
1484  afound++;
1485  ring_init(&rx->ac3rbuffer[0], AC3_BUF);
1486  init_pes_in(&rx->pac3[0], 0x80, &rx->ac3rbuffer[0],0);
1487  rx->pac3[0].priv = (void *) rx;
1489  memset(&rx->ac3frame[0], 0, sizeof(audio_frame_t));
1490  init_index(&rx->current_ac3index[0]);
1491  rx->ac3frame_count[0] = 0;
1492  rx->first_ac3pts[0] = 0;
1493  }
1494 
1495  }
1496 
1497  if (afound && vfound){
1498  LOG(VB_GENERAL, LOG_INFO, "found");
1499  if (rx->vpid)
1500  LOG(VB_GENERAL, LOG_INFO, QString("vpid %1 (0x%2)")
1501  .arg(rx->vpid).arg(rx->vpid, 4,16,QChar('0')));
1502  if (rx->apidn)
1503  LOG(VB_GENERAL, LOG_INFO, QString("apid %1 (0x%2)")
1504  .arg(rx->apid[0]).arg(rx->apid[0], 4,16,QChar('0')));
1505  if (rx->ac3n)
1506  LOG(VB_GENERAL, LOG_INFO, QString("ac3pid %1 (0x%2)")
1507  .arg(rx->ac3_id[0]).arg(rx->ac3_id[0], 4,16,QChar('0')));
1508  } else {
1509  LOG(VB_GENERAL, LOG_ERR, "Couldn't find pids");
1510  exit(1);
1511  }
1512 
1513 }
1514 
1515 
1516 static void pes_id_out(pes_in_t *p)
1517 {
1518 
1519 // int len = p->plength-3-p->hlength;
1520  struct replex *rx = (struct replex *) p->priv;
1521 
1522  rx->scan_found=0;
1523  switch(p->cid){
1524  case VIDEO_STREAM_S ... VIDEO_STREAM_E:
1525  rx->scan_found=p->cid;
1526  break;
1527 
1528  case AUDIO_STREAM_S ... AUDIO_STREAM_E:
1529  rx->scan_found=p->cid;
1530  break;
1531 
1532  case PRIVATE_STREAM1:
1533  if (rx->vdr){
1534  rx->scan_found = 0x80;
1535  break;
1536  } else {
1537 
1538  uint8_t id = p->buf[9+p->hlength];
1539  switch(id){
1540  case 0x80 ... 0x8f:
1541  {
1542  int c=0;
1543  uint16_t fframe;
1544 
1545  fframe=0;
1546  fframe = p->buf[9+p->hlength+3];
1547  fframe |= (p->buf[9+p->hlength+2]<<8);
1548 
1549  if (fframe < p->plength){
1550  if ((c=find_audio_s(p->buf,
1551  9+p->hlength+4+fframe,
1552  AC3, p->plength+6)) >= 0){
1553  rx->scan_found = id;
1554 #if 0
1555  LOG(VB_GENERAL, LOG_INFO,
1556  QString("0x%1 0x%2 \n")
1557  .arg(c-9-p->hlength-4, 4,16,QChar('0'))
1558  .arg(fframe, 4,16,QChar('0')));
1559  if (id>0x80)show_buf(p->buf+9+p->hlength,8);
1560  if (id>0x80)show_buf(p->buf+c,8);
1561 #endif
1562  }
1563  }
1564  break;
1565  }
1566  }
1567  break;
1568  }
1569  default:
1570  p->cid = 0;
1571  p->type = 0;
1572  rx->scan_found=0;
1573  memset(p->buf,0,MAX_PLENGTH*sizeof(uint8_t));
1574  return;
1575  }
1576 }
1577 
1578 static void find_pes_ids(struct replex *rx)
1579 {
1580  uint8_t buf[IN_SIZE];
1581  int count=0;
1582  int j;
1583  int re=0;
1584  uint16_t vpid[MAXVPID], apid[MAXAPID], ac3pid[MAXAC3PID];
1585  int vn=0, an=0,ac3n=0;
1586 
1587  memset (vpid , 0 , MAXVPID*sizeof(uint16_t));
1588  memset (apid , 0 , MAXAPID*sizeof(uint16_t));
1589  memset (ac3pid , 0 , MAXAC3PID*sizeof(uint16_t));
1590 
1591  LOG(VB_GENERAL, LOG_INFO, "Trying to find PES IDs");
1592  rx->scan_found=0;
1593  rx->pvideo.priv = rx ;
1594  while (count < (int) rx->inflength-IN_SIZE){
1595  if ((re = save_read(rx,buf,IN_SIZE))<0)
1596  LOG(VB_GENERAL, LOG_ERR, QString("reading: %1")
1597  .arg(strerror(errno)));
1598  else
1599  count += re;
1600 
1601  get_pes(&rx->pvideo, buf, re, pes_id_out);
1602 
1603  if ( rx->scan_found ){
1604 
1605  switch (rx->scan_found){
1606 
1607  case VIDEO_STREAM_S ... VIDEO_STREAM_E:
1608  {
1609  int old=0;
1610  for (j=0; j < vn; j++){
1611 #if 0
1612  LOG(VB_GENERAL, LOG_INFO,
1613  QString("%1. %2").arg(j+1).arg(vpid[j]));
1614 #endif
1615  if (vpid[j] == rx->scan_found){
1616  old = 1;
1617  break;
1618  }
1619  }
1620  if (!old){
1621  vpid[vn]=rx->scan_found;
1622 
1623  LOG(VB_GENERAL, LOG_INFO,
1624  QString("MPEG VIDEO %1: 0x%2 (%3)")
1625  .arg(vn+1)
1626  .arg(vpid[vn], 2,16,QChar('0'))
1627  .arg(vpid[vn]));
1628  if (vn+1 < MAXVPID) vn++;
1629  }
1630  }
1631  break;
1632 
1633 
1634  case AUDIO_STREAM_S ... AUDIO_STREAM_E:
1635  {
1636  int old=0;
1637  for (j=0; j < an; j++)
1638  if (apid[j] == rx->scan_found){
1639  old = 1;
1640  break;
1641  }
1642  if (!old){
1643  apid[an]=rx->scan_found;
1644  LOG(VB_GENERAL, LOG_INFO,
1645  QString("MPEG AUDIO %1: 0x%2 (%3)")
1646  .arg(an +1)
1647  .arg(apid[an], 2,16,QChar('0'))
1648  .arg(apid[an]));
1649  if (an+1 < MAXAPID) an++;
1650  }
1651  }
1652  break;
1653 
1654  case 0x80 ... 0x8f:
1655  {
1656  int old=0;
1657  for (j=0; j < ac3n; j++)
1658  if (ac3pid[j] == rx->scan_found){
1659  old = 1;
1660  break;
1661  }
1662  if (!old){
1663  ac3pid[ac3n]=rx->scan_found;
1664  if (rx->vdr){
1665  LOG(VB_GENERAL, LOG_INFO,
1666  "possible AC3 AUDIO with private stream 1 pid (0xbd)");
1667  }else{
1668  LOG(VB_GENERAL, LOG_INFO,
1669  QString("AC3 AUDIO %1: 0x%2 (%3)")
1670  .arg(ac3n+1)
1671  .arg(ac3pid[ac3n], 2,16,QChar('0'))
1672  .arg(ac3pid[ac3n]));
1673  }
1674  if (ac3n+1< MAXAC3PID) ac3n++;
1675  }
1676  rx->scan_found = 0;
1677  }
1678  break;
1679  }
1680  rx->scan_found = 0;
1681  }
1682  }
1683 }
1684 
1685 
1686 
1687 static void replex_finish(struct replex *rx)
1688 {
1689  if (!replex_all_set(rx)){
1690  LOG(VB_GENERAL, LOG_ERR, "Can't find all required streams");
1691  if (rx->itype == REPLEX_PS){
1692  LOG(VB_GENERAL, LOG_ERR,
1693  "Please check if audio and video have standard IDs (0xc0 or 0xe0)");
1694  }
1695  exit(1);
1696  }
1697 
1698  if (!rx->demux)
1699  finish_mpg((multiplex_t *)rx->priv);
1700  exit(0);
1701 }
1702 
1703 static int replex_fill_buffers(struct replex *rx, uint8_t *mbuf)
1704 {
1705  uint8_t buf[IN_SIZE];
1706  int i,j;
1707  int count=0;
1708  int fill;
1709  int re;
1710  int rsize;
1711  int tries = 0;
1712 
1713  if (rx->finish) return 0;
1714  fill = guess_fill(rx);
1715 #if 0
1716  LOG(VB_GENERAL, LOG_INFO,
1717  QString("trying to fill buffers with %1").arg(fill));
1718 #endif
1719  if (fill < 0) return -1;
1720 
1721  memset(buf, 0, IN_SIZE);
1722 
1723  switch(rx->itype){
1724  case REPLEX_TS:
1725  if (fill < IN_SIZE){
1726  rsize = fill - (fill%188);
1727  } else rsize = IN_SIZE;
1728 
1729 #if 0
1730  LOG(VB_GENERAL, LOG_INFO, QString("filling with %1").arg(rsize));
1731 #endif
1732 
1733  if (!rsize) return 0;
1734 
1735  memset(buf, 0, IN_SIZE);
1736 
1737  if ( mbuf ){
1738  for ( i = 0; i < 188 ; i++){
1739  if ( mbuf[i] == 0x47 ) break;
1740  }
1741 
1742  if ( i == 188){
1743  LOG(VB_GENERAL, LOG_ERR, "Not a TS");
1744  return -1;
1745  } else {
1746  memcpy(buf,mbuf+i,2*TS_SIZE-i);
1747  if ((count = save_read(rx,mbuf,i))<0)
1748  LOG(VB_GENERAL, LOG_ERR, QString("reading: %1")
1749  .arg(strerror(errno)));
1750  memcpy(buf+2*TS_SIZE-i,mbuf,i);
1751  i = 188;
1752  }
1753  } else i=0;
1754 
1755 
1756 #define MAX_TRIES 5
1757  while (count < rsize && tries < MAX_TRIES){
1758  if ((re = save_read(rx,buf+i,rsize-i)+i)<0)
1759  LOG(VB_GENERAL, LOG_ERR, QString("reading: %1")
1760  .arg(strerror(errno)));
1761  else
1762  count += re;
1763  tries++;
1764 
1765  if (!rx->vpid || !(rx->apidn || rx->ac3n)){
1766  find_pids_stdin(rx, buf, re);
1767  }
1768 
1769  for( j = 0; j < re; j+= TS_SIZE){
1770 
1771  if ( re - j < TS_SIZE) break;
1772 
1773  if ( replex_tsp( rx, buf+j) < 0){
1774  LOG(VB_GENERAL, LOG_ERR,
1775  "Error reading TS");
1776  exit(1);
1777  }
1778  }
1779  i=0;
1780  }
1781 
1782  if (tries == MAX_TRIES)
1783  replex_finish(rx);
1784  return 0;
1785  break;
1786 
1787  case REPLEX_PS:
1788  rsize = fill;
1789  if (fill > IN_SIZE) rsize = IN_SIZE;
1790  if (mbuf)
1791  get_pes(&rx->pvideo, mbuf, 2*TS_SIZE, pes_es_out);
1792 
1793  while (count < rsize && tries < MAX_TRIES){
1794  if ((re = save_read(rx, buf, rsize))<0)
1795  LOG(VB_GENERAL, LOG_ERR, QString("reading PS: %1")
1796  .arg(strerror(errno)));
1797  else
1798  count += re;
1799 
1800  get_pes(&rx->pvideo, buf, re, pes_es_out);
1801 
1802  tries++;
1803 
1804  }
1805 
1806  if (tries == MAX_TRIES)
1807  replex_finish(rx);
1808  return 0;
1809  break;
1810 
1811 
1812  case REPLEX_AVI:
1813  rsize = fill;
1814  if (fill > IN_SIZE) rsize = IN_SIZE;
1815 
1816  if (!(rx->ac.avih_flags & AVI_HASINDEX)){
1817 
1818  if (mbuf){
1819  get_avi(&rx->pvideo, mbuf, rx->avi_rest, avi_es_out);
1820  }
1821 
1822  while (count < rsize && tries < MAX_TRIES){
1823  if ((re = save_read(rx, buf, rsize))<0)
1824  LOG(VB_GENERAL, LOG_ERR,
1825  QString("reading AVI: %1")
1826  .arg(strerror(errno)));
1827  else
1828  count += re;
1829 
1830  get_avi(&rx->pvideo, buf, re, avi_es_out);
1831 
1832  tries++;
1833  }
1834  } else {
1835  if (get_avi_from_index(&rx->pvideo, rx->fd_in,
1836  &rx->ac, avi_es_out, rsize) < 0)
1837  tries = MAX_TRIES;
1838  }
1839 
1840  if (tries == MAX_TRIES)
1841  replex_finish(rx);
1842  return 0;
1843  break;
1844  }
1845 
1846  return -1;
1847 }
1848 
1849 static int fill_buffers(void *r, int finish)
1850 {
1851  struct replex *rx = (struct replex *)r;
1852 
1853  rx->finish = finish;
1854 
1855  return replex_fill_buffers(rx, nullptr);
1856 }
1857 
1858 
1860 {
1861  memset(iu,0, sizeof(index_unit));
1862  iu->frame_start = 1;
1863 }
1864 
1865 static int replex_all_set(struct replex *rx)
1866 {
1867  int i;
1868  int set=0;
1869 
1870  for (i=0; i < rx->ac3n ;i++){
1871  set += rx->ac3frame[i].set;
1872  }
1873  for (i=0; i<rx->apidn;i++){
1874  set += rx->aframe[i].set;
1875  }
1876  set += rx->seq_head.set;
1877 
1878  if (set == (rx->ac3n+ rx->apidn + 1)) return 1;
1879  return 0;
1880 }
1881 
1882 
1883 static int check_stream_type(struct replex *rx, uint8_t * buf, int len)
1884 {
1885  int c=0;
1886  avi_context ac;
1887  uint8_t head;
1888 
1889  if (rx->itype != REPLEX_TS) return rx->itype;
1890 
1891  if (len< 2*TS_SIZE){
1892  LOG(VB_GENERAL, LOG_ERR, "cannot determine streamtype");
1893  exit(1);
1894  }
1895 
1896  LOG(VB_GENERAL, LOG_INFO, "Checking for TS: ");
1897  while (c < len && buf[c]!=0x47) c++;
1898  if (c<len && len-c>=TS_SIZE){
1899  if (buf[c+TS_SIZE] == 0x47){
1900  LOG(VB_GENERAL, LOG_INFO, "confirmed");
1901  return REPLEX_TS;
1902  } else LOG(VB_GENERAL, LOG_INFO, "failed");
1903  } else LOG(VB_GENERAL, LOG_INFO, "failed");
1904 
1905  LOG(VB_GENERAL, LOG_INFO, "Checking for AVI: ");
1906  if (check_riff(&ac, buf, len)>=0){
1907  LOG(VB_GENERAL, LOG_INFO, "confirmed");
1908  rx->itype = REPLEX_AVI;
1909  rx->vpid = 0xE0;
1910  rx->apidn = 1;
1911  rx->apid[0] = 0xC0;
1912  rx->ignore_pts =1;
1913  return REPLEX_AVI;
1914  } else LOG(VB_GENERAL, LOG_INFO, "failed");
1915 
1916  LOG(VB_GENERAL, LOG_INFO, "Checking for PS: ");
1917  if (find_any_header(&head, buf, len) >= 0){
1918  LOG(VB_GENERAL, LOG_INFO, "confirmed(maybe)");
1919  } else {
1920  LOG(VB_GENERAL, LOG_INFO,"failed, trying it anyway");
1921  }
1922  rx->itype=REPLEX_PS;
1923  if (!rx->vpid) rx->vpid = 0xE0;
1924  if (!(rx->apidn || rx->ac3n)){
1925  rx->apidn = 1;
1926  rx->apid[0] = 0xC0;
1927  }
1928  return REPLEX_PS;
1929 }
1930 
1931 
1932 static void init_replex(struct replex *rx)
1933 {
1934  int i;
1935  uint8_t mbuf[2*TS_SIZE];
1936 
1937  rx->analyze=0;
1938 
1939  if (save_read(rx, mbuf, 2*TS_SIZE)<0)
1940  LOG(VB_GENERAL, LOG_ERR,
1941  QString("reading: %1").arg(strerror(errno)));
1942 
1943  check_stream_type(rx, mbuf, 2*TS_SIZE);
1944  if (rx->itype == REPLEX_TS){
1945  if (!rx->vpid || !(rx->apidn || rx->ac3n)){
1946  if (rx->inflength){
1947  find_pids_file(rx);
1948  }
1949  }
1950  }
1951 
1952 
1953  if (rx->otype==REPLEX_HDTV){
1954  rx->videobuf = 4*VIDEO_BUF;
1955  } else {
1956  rx->videobuf = VIDEO_BUF;
1957  }
1958  rx->audiobuf = AUDIO_BUF;
1959  rx->ac3buf = AC3_BUF;
1960 
1961  if (rx->itype == REPLEX_AVI){
1962  rx->videobuf = 4*VIDEO_BUF;
1963  rx->audiobuf = 2*rx->videobuf;
1964  }
1965 
1966  rx->vpes_abort = 0;
1967  rx->first_iframe = 0;
1968  ring_init(&rx->vrbuffer, rx->videobuf);
1969  if (rx->itype == REPLEX_TS || rx->itype == REPLEX_AVI)
1970  init_pes_in(&rx->pvideo, 0xE0, &rx->vrbuffer, 0);
1971  else {
1972  init_pes_in(&rx->pvideo, 0, nullptr, 1);
1973  }
1974  rx->pvideo.priv = (void *) rx;
1976  memset(&rx->seq_head, 0, sizeof(sequence_t));
1977  init_index(&rx->current_vindex);
1978  rx->vgroup_count = 0;
1979  rx->vframe_count = 0;
1980  rx->first_vpts = 0;
1981  rx->video_state = S_SEARCH;
1982  rx->last_vpts = 0;
1983 
1984  for (i=0; i<rx->apidn;i++){
1985 
1986  rx->apes_abort[i] = 0;
1987  rx->audio_state[i] = S_SEARCH;
1988  ring_init(&rx->arbuffer[i], rx->audiobuf);
1989 
1990  if (rx->itype == REPLEX_TS){
1991  init_pes_in(&rx->paudio[i], i+1,
1992  &rx->arbuffer[i], 0);
1993  rx->paudio[i].priv = (void *) rx;
1994  }
1995  ring_init(&rx->index_arbuffer[i], INDEX_BUF);
1996  memset(&rx->aframe[i], 0, sizeof(audio_frame_t));
1997  init_index(&rx->current_aindex[i]);
1998  rx->aframe_count[i] = 0;
1999  rx->first_apts[i] = 0;
2000  rx->last_apts[i] = 0;
2001  }
2002 
2003  for (i=0; i<rx->ac3n;i++){
2004  rx->ac3pes_abort[i] = 0;
2005  rx->ac3_state[i] = S_SEARCH;
2006  ring_init(&rx->ac3rbuffer[i], AC3_BUF);
2007  if (rx->itype == REPLEX_TS){
2008  init_pes_in(&rx->pac3[i], 0x80+i,
2009  &rx->ac3rbuffer[i],0);
2010  rx->pac3[i].priv = (void *) rx;
2011  }
2013  memset(&rx->ac3frame[i], 0, sizeof(audio_frame_t));
2014  init_index(&rx->current_ac3index[i]);
2015  rx->ac3frame_count[i] = 0;
2016  rx->first_ac3pts[i] = 0;
2017  rx->last_ac3pts[i] = 0;
2018  }
2019 
2020  if (rx->itype == REPLEX_TS){
2021  if (replex_fill_buffers(rx, mbuf)< 0) {
2022  LOG(VB_GENERAL, LOG_ERR, "error filling buffer");
2023  exit(1);
2024  }
2025  } else if ( rx->itype == REPLEX_AVI){
2026 #define AVI_S 1024
2027  avi_context *ac;
2028  uint8_t buf[AVI_S];
2029  int re=0;
2030  ssize_t read_count = 0;
2031 
2032  lseek(rx->fd_in, 0, SEEK_SET);
2033  ac = &rx->ac;
2034  memset(ac, 0, sizeof(avi_context));
2035  if ((read_count = save_read(rx, buf, 12)) != 12) {
2036  LOG(VB_GENERAL, LOG_ERR,
2037  QString("Error reading in 12 bytes from replex. Read %1 bytes")
2038  .arg(read_count));
2039  exit(1);
2040  }
2041 
2042  if (check_riff(ac, buf, 12) < 0){
2043  LOG(VB_GENERAL, LOG_ERR, "Wrong RIFF header");
2044  exit(1);
2045  } else {
2046  LOG(VB_GENERAL, LOG_INFO, "Found RIFF header");
2047  }
2048 
2049  memset(ac, 0, sizeof(avi_context));
2050  re = read_avi_header(ac, rx->fd_in);
2051  if (avi_read_index(ac,rx->fd_in) < 0 || re < 0){
2052  LOG(VB_GENERAL, LOG_ERR, "Error reading index");
2053  exit(1);
2054  }
2055 // rx->aframe_count[0] = ac->ai[0].initial_frames;
2056  rx->vframe_count = ac->ai[0].initial_frames*ac->vi.fps/
2057  ac->ai[0].fps;
2058 
2059  rx->inflength = lseek(rx->fd_in, 0, SEEK_CUR)+ac->movi_length;
2060 
2061  LOG(VB_GENERAL, LOG_INFO, QString("AVI initial frames %1")
2062  .arg(rx->vframe_count));
2063  if (!ac->done){
2064  LOG(VB_GENERAL, LOG_ERR, "Error reading AVI header");
2065  exit(1);
2066  }
2067 
2068  if (replex_fill_buffers(rx, buf+re)< 0) {
2069  LOG(VB_GENERAL, LOG_ERR, "error filling buffer");
2070  exit(1);
2071  }
2072  } else {
2073  if (replex_fill_buffers(rx, mbuf)< 0) {
2074  LOG(VB_GENERAL, LOG_ERR, "error filling buffer");
2075  exit(1);
2076  }
2077  }
2078 
2079 }
2080 
2081 
2082 static void fix_audio(struct replex *rx, multiplex_t *mx)
2083 {
2084  int i;
2085  index_unit aiu;
2086  int size;
2087 
2088  size = sizeof(index_unit);
2089 
2090  for ( i = 0; i < rx->apidn; i++){
2091  do {
2092  while (ring_avail(&rx->index_arbuffer[i]) <
2093  sizeof(index_unit)){
2094  if (replex_fill_buffers(rx, nullptr)< 0) {
2095  LOG(VB_GENERAL, LOG_ERR,
2096  "error in fix audio");
2097  exit(1);
2098  }
2099  }
2100  ring_peek(&rx->index_arbuffer[i], (uint8_t *)&aiu, size, 0);
2101  if ( ptscmp(aiu.pts + rx->first_apts[i], rx->first_vpts) < 0){
2102  ring_skip(&rx->index_arbuffer[i], size);
2103  ring_skip(&rx->arbuffer[i], aiu.length);
2104  } else break;
2105 
2106  } while (1);
2107  mx->ext[i].pts_off = aiu.pts;
2108 
2109  LOG(VB_GENERAL, LOG_INFO, QString("Audio%1 offset: ").arg(i));
2110  printpts(mx->ext[i].pts_off);
2111  printpts(rx->first_apts[i]+mx->ext[i].pts_off);
2112  }
2113 
2114  for ( i = 0; i < rx->ac3n; i++){
2115  do {
2116  while (ring_avail(&rx->index_ac3rbuffer[i]) <
2117  sizeof(index_unit)){
2118  if (replex_fill_buffers(rx, nullptr)< 0) {
2119  LOG(VB_GENERAL, LOG_ERR,
2120  "error in fix audio");
2121  exit(1);
2122  }
2123  }
2124  ring_peek(&rx->index_ac3rbuffer[i], (uint8_t *)&aiu,
2125  size, 0);
2126  if ( ptscmp (aiu.pts+rx->first_ac3pts[i], rx->first_vpts) < 0){
2127  ring_skip(&rx->index_ac3rbuffer[i], size);
2128  ring_skip(&rx->ac3rbuffer[i], aiu.length);
2129  } else break;
2130  } while (1);
2131  mx->ext[i].pts_off = aiu.pts;
2132 
2133  LOG(VB_GENERAL, LOG_INFO, QString("AC3%1 offset: ").arg(i));
2134  printpts(mx->ext[i].pts_off);
2135  printpts(rx->first_ac3pts[i]+mx->ext[i].pts_off);
2136 
2137  }
2138 }
2139 
2140 
2141 
2142 static int get_next_video_unit(struct replex *rx, index_unit *viu)
2143 {
2144  if (ring_avail(&rx->index_vrbuffer)){
2145  ring_read(&rx->index_vrbuffer, (uint8_t *)viu,
2146  sizeof(index_unit));
2147  return 1;
2148  }
2149  return 0;
2150 }
2151 
2152 static int get_next_audio_unit(struct replex *rx, index_unit *aiu, int i)
2153 {
2154  if(ring_avail(&rx->index_arbuffer[i])){
2155  ring_read(&rx->index_arbuffer[i], (uint8_t *)aiu,
2156  sizeof(index_unit));
2157  return 1;
2158  }
2159  return 0;
2160 }
2161 
2162 static int get_next_ac3_unit(struct replex *rx, index_unit *aiu, int i)
2163 {
2164  if (ring_avail(&rx->index_ac3rbuffer[i])) {
2165  ring_read(&rx->index_ac3rbuffer[i], (uint8_t *)aiu,
2166  sizeof(index_unit));
2167 
2168  return 1;
2169  }
2170  return 0;
2171 }
2172 
2173 
2174 static void do_analyze(struct replex *rx)
2175 {
2176  index_unit dummy;
2177  index_unit dummy2;
2178  int i;
2179  uint64_t lastvpts;
2180  uint64_t lastvdts;
2181  uint64_t lastapts[N_AUDIO];
2182  uint64_t lastac3pts[N_AC3];
2183  int av;
2184 
2185  av = rx->analyze-1;
2186 
2187  lastvpts = 0;
2188  lastvdts = 0;
2189  memset(lastapts, 0, N_AUDIO*sizeof(uint64_t));
2190  memset(lastac3pts, 0, N_AC3*sizeof(uint64_t));
2191 
2192  LOG(VB_GENERAL, LOG_INFO, "STARTING ANALYSIS");
2193 
2194 
2195  while(!rx->finish){
2196  if (replex_fill_buffers(rx, nullptr)< 0) {
2197  LOG(VB_GENERAL, LOG_ERR,
2198  "error in get next video unit");
2199  return;
2200  }
2201  for (i=0; i< rx->apidn; i++){
2202  while(get_next_audio_unit(rx, &dummy2, i)){
2203  ring_skip(&rx->arbuffer[i],
2204  dummy2.length);
2205  if (av>=1){
2206  LOG(VB_GENERAL, LOG_INFO,
2207  QString("MPG2 Audio%1 unit: length %2 PTS ")
2208  .arg(i).arg(dummy2.length));
2209  printptss(dummy2.pts);
2210 
2211  if (lastapts[i]){
2212  LOG(VB_GENERAL, LOG_INFO,
2213  " diff:");
2214  printptss(ptsdiff(dummy2.pts,lastapts[i]));
2215  }
2216  lastapts[i] = dummy2.pts;
2217  }
2218  }
2219  }
2220 
2221  for (i=0; i< rx->ac3n; i++){
2222  while(get_next_ac3_unit(rx, &dummy2, i)){
2223  ring_skip(&rx->ac3rbuffer[i],
2224  dummy2.length);
2225  if (av>=1){
2226  LOG(VB_GENERAL, LOG_INFO,
2227  QString("AC3 Audio%1 unit: length %2 PTS ")
2228  .arg(i).arg(dummy2.length));
2229  printptss(dummy2.pts);
2230  if (lastac3pts[i]){
2231  LOG(VB_GENERAL, LOG_INFO,
2232  " diff:");
2233  printptss(ptsdiff(dummy2.pts, lastac3pts[i]));
2234  }
2235  lastac3pts[i] = dummy2.pts;
2236  }
2237  }
2238  }
2239 
2240  while (get_next_video_unit(rx, &dummy)){
2241  ring_skip(&rx->vrbuffer,
2242  dummy.length);
2243  if (av==0 || av==2){
2244  LOG(VB_GENERAL, LOG_INFO, "Video unit: ");
2245  if (dummy.seq_header){
2246  LOG(VB_GENERAL, LOG_INFO,
2247  "Sequence header ");
2248  }
2249  if (dummy.gop){
2250  LOG(VB_GENERAL, LOG_INFO,
2251  "GOP header ");
2252  }
2253  switch (dummy.frame){
2254  case I_FRAME:
2255  LOG(VB_GENERAL, LOG_INFO, "I-frame");
2256  break;
2257  case B_FRAME:
2258  LOG(VB_GENERAL, LOG_INFO, "B-frame");
2259  break;
2260  case P_FRAME:
2261  LOG(VB_GENERAL, LOG_INFO, "P-frame");
2262  break;
2263  }
2264  LOG(VB_GENERAL, LOG_INFO, QString(" length %1 PTS ")
2265  .arg(dummy.length));
2266  printptss(dummy.pts);
2267  if (lastvpts){
2268  LOG(VB_GENERAL, LOG_INFO," diff:");
2269  printptss(ptsdiff(dummy.pts, lastvpts));
2270  }
2271  lastvpts = dummy.pts;
2272 
2273  LOG(VB_GENERAL, LOG_INFO, " DTS ");
2274  printptss(dummy.dts);
2275  if (lastvdts){
2276  LOG(VB_GENERAL, LOG_INFO, " diff:");
2277  printptss(ptsdiff(dummy.dts,lastvdts));
2278  }
2279  lastvdts = dummy.dts;
2280  }
2281  }
2282  }
2283 
2284 
2285 }
2286 
2287 static void do_scan(struct replex *rx)
2288 {
2289  uint8_t mbuf[2*TS_SIZE];
2290 
2291  rx->analyze=0;
2292 
2293  if (save_read(rx, mbuf, 2*TS_SIZE)<0)
2294  LOG(VB_GENERAL, LOG_ERR, QString("reading: %1")
2295  .arg(strerror(errno)));
2296 
2297  LOG(VB_GENERAL, LOG_INFO, "STARTING SCAN");
2298 
2299  check_stream_type(rx, mbuf, 2*TS_SIZE);
2300 
2301  switch(rx->itype){
2302  case REPLEX_TS:
2303  find_all_pids_file(rx);
2304  break;
2305 
2306  case REPLEX_PS:
2307  init_pes_in(&rx->pvideo, 0, nullptr, 1);
2308  find_pes_ids(rx);
2309  break;
2310 
2311  case REPLEX_AVI:
2312  break;
2313  }
2314 
2315 }
2316 
2317 static void do_demux(struct replex *rx)
2318 {
2319  index_unit dummy;
2320  index_unit dummy2;
2321  int i;
2322  LOG(VB_GENERAL, LOG_INFO, "STARTING DEMUX");
2323 
2324  while(!rx->finish){
2325  if (replex_fill_buffers(rx, nullptr)< 0) {
2326  LOG(VB_GENERAL, LOG_ERR,
2327  "error in get next video unit");
2328  return;
2329  }
2330  for (i=0; i< rx->apidn; i++){
2331  while(get_next_audio_unit(rx, &dummy2, i)){
2332  ring_read_file(&rx->arbuffer[i],
2333  rx->dmx_out[i+1],
2334  dummy2.length);
2335  }
2336  }
2337 
2338  for (i=0; i< rx->ac3n; i++){
2339  while(get_next_ac3_unit(rx, &dummy2, i)){
2340  ring_read_file(&rx->ac3rbuffer[i],
2341  rx->dmx_out[i+1+rx->apidn],
2342  dummy2.length);
2343  }
2344  }
2345 
2346  while (get_next_video_unit(rx, &dummy)){
2347  ring_read_file(&rx->vrbuffer, rx->dmx_out[0],
2348  dummy.length);
2349  }
2350  }
2351 }
2352 
2353 
2354 static void do_replex(struct replex *rx)
2355 {
2356  int video_ok = 0;
2357  aok_arr ext_ok {};
2358  int start=1;
2359  multiplex_t mx;
2360 
2361 
2362  LOG(VB_GENERAL, LOG_INFO, "STARTING REPLEX");
2363  memset(&mx, 0, sizeof(mx));
2364 
2365  while (!replex_all_set(rx)){
2366  if (replex_fill_buffers(rx, nullptr)< 0) {
2367  LOG(VB_GENERAL, LOG_INFO, "error filling buffer");
2368  exit(1);
2369  }
2370  }
2371 
2372  int i;
2373  for (i = 0; i < rx->apidn; i++){
2374  rx->exttype[i] = 2;
2375  rx->extframe[i] = rx->aframe[i];
2376  rx->extrbuffer[i] = rx->arbuffer[i];
2377  rx->index_extrbuffer[i] = rx->index_arbuffer[i];
2378  rx->exttypcnt[i+1] = i;
2379  }
2380 
2381  int ac3Count = 1;
2382  for (i = rx->apidn; i < rx->apidn + rx->ac3n; i++){
2383  rx->exttype[i] = 1;
2384  rx->extframe[i] = rx->ac3frame[i];
2385  rx->extrbuffer[i] = rx->ac3rbuffer[i];
2386  rx->index_extrbuffer[i] = rx->index_ac3rbuffer[i];
2387  rx->exttypcnt[i] = ac3Count++;
2388  }
2389 
2390  mx.priv = (void *) rx;
2391  rx->priv = (void *) &mx;
2392  init_multiplex(&mx, &rx->seq_head, rx->extframe,
2393  rx->exttype, rx->exttypcnt, rx->video_delay,
2394  rx->audio_delay, rx->fd_out, fill_buffers,
2395  &rx->vrbuffer, &rx->index_vrbuffer,
2396  rx->extrbuffer, rx->index_extrbuffer,
2397  rx->otype);
2398 
2399  if (!rx->ignore_pts){
2400  fix_audio(rx, &mx);
2401  }
2402  setup_multiplex(&mx);
2403 
2404  while(1){
2405  check_times( &mx, &video_ok, ext_ok, &start);
2406 
2407  if (write_out_packs( &mx, video_ok, ext_ok)) {
2408  LOG(VB_GENERAL, LOG_ERR, "error while writing");
2409  exit(1);
2410  }
2411  }
2412 }
2413 
2414 
2415 static void usage(char *progname)
2416 {
2417  printf ("usage: %s [options] <input files>\n\n",progname);
2418  printf ("options:\n");
2419  printf (" --help, -h: print help message\n");
2420  printf (" --type, -t: set output type (MPEG2, DVD, HDTV)\n");
2421  printf (" --of, -o: set output file\n");
2422  printf (" --input_stream, -i: set input stream type (TS(default), PS, AVI)\n");
2423  printf (" --audio_pid, -a: audio PID for TS stream (also used for PS id)\n");
2424  printf (" --ac3_id, -c: ID of AC3 audio for demux (also used for PS id)\n");
2425  printf (" --video_pid, -v: video PID for TS stream (also used for PS id)\n");
2426  printf (" --video_delay, -d: video delay in ms\n");
2427  printf (" --audio_delay, -e: audio delay in ms\n");
2428  printf (" --ignore_PTS, -f: ignore all PTS information of original\n");
2429  printf (" --keep_PTS, -k: keep and don't correct PTS information of original\n");
2430  printf (" --fix_sync, -n: try to fix audio sync while demuxing\n");
2431  printf (" --demux, -z: demux only (-o is basename)\n");
2432  printf (" --analyze, -y: analyze (0=video,1=audio, 2=both)\n");
2433  printf (" --scan, -s: scan for streams\n");
2434  printf (" --vdr, -x: handle AC3 for vdr input file\n");
2435  exit(1);
2436 }
2437 
2438 int main(int argc, char **argv)
2439 {
2440  int c;
2441  int analyze=0;
2442  int scan =0;
2443  char *filename = nullptr;
2444  const char *type = "SVCD";
2445  const char *inpt = "TS";
2446 
2447  struct replex rx;
2448 
2449  memset(&rx, 0, sizeof(struct replex));
2450 
2451  while (1) {
2452  int option_index = 0;
2453  static struct option long_options[] = {
2454  {"type", required_argument, nullptr, 't'},
2455  {"input_stream", required_argument, nullptr, 'i'},
2456  {"video_pid", required_argument, nullptr, 'v'},
2457  {"audio_pid", required_argument, nullptr, 'a'},
2458  {"audio_delay", required_argument, nullptr, 'e'},
2459  {"video_delay", required_argument, nullptr, 'd'},
2460  {"ac3_id", required_argument, nullptr, 'c'},
2461  {"of",required_argument, nullptr, 'o'},
2462  {"ignore_PTS",required_argument, nullptr, 'f'},
2463  {"keep_PTS",required_argument, nullptr, 'k'},
2464  {"fix_sync",no_argument, nullptr, 'n'},
2465  {"demux",no_argument, nullptr, 'z'},
2466  {"analyze",required_argument, nullptr, 'y'},
2467  {"scan",required_argument, nullptr, 's'},
2468  {"vdr",required_argument, nullptr, 'x'},
2469  {"help", no_argument , nullptr, 'h'},
2470  {nullptr, 0, nullptr, 0}
2471  };
2472  c = getopt_long (argc, argv,
2473  "t:o:a:v:i:hp:q:d:c:n:fkd:e:zy:sx",
2474  long_options, &option_index);
2475  if (c == -1)
2476  break;
2477 
2478  switch (c) {
2479  case 't':
2480  type = optarg;
2481  break;
2482  case 'i':
2483  inpt = optarg;
2484  break;
2485  case 'd':
2486  rx.video_delay = strtol(optarg,(char **)nullptr, 0)
2487  *CLOCK_MS;
2488  break;
2489  case 'e':
2490  rx.audio_delay = strtol(optarg,(char **)nullptr, 0)
2491  *CLOCK_MS;
2492  break;
2493  case 'a':
2494  if (rx.apidn==N_AUDIO){
2495  LOG(VB_GENERAL, LOG_ERR, "Too many audio PIDs");
2496  exit(1);
2497  }
2498  rx.apid[rx.apidn] = strtol(optarg,(char **)nullptr, 0);
2499  rx.apidn++;
2500  break;
2501  case 'v':
2502  rx.vpid = strtol(optarg,(char **)nullptr, 0);
2503  break;
2504  case 'c':
2505  if (rx.ac3n==N_AC3){
2506  LOG(VB_GENERAL, LOG_ERR, "Too many audio PIDs");
2507  exit(1);
2508  }
2509  rx.ac3_id[rx.ac3n] = strtol(optarg,(char **)nullptr, 0);
2510  rx.ac3n++;
2511  break;
2512  case 'o':
2513  filename = optarg;
2514  break;
2515  case 'f':
2516  rx.ignore_pts =1;
2517  break;
2518  case 'k':
2519  rx.keep_pts =1;
2520  break;
2521  case 'z':
2522  rx.demux =1;
2523  break;
2524  case 'n':
2525  rx.fix_sync =1;
2526  break;
2527  case 'y':
2528  analyze = strtol(optarg,(char **)nullptr, 0);
2529  if (analyze>2) usage(argv[0]);
2530  analyze++;
2531  break;
2532  case 's':
2533  scan = 1;
2534  break;
2535  case 'x':
2536  rx.vdr=1;
2537  break;
2538  case 'h':
2539  case '?':
2540  default:
2541  usage(argv[0]);
2542  }
2543  }
2544 
2545  if (optind == argc-1) {
2546  if ((rx.fd_in = open(argv[optind] ,O_RDONLY| O_LARGEFILE)) < 0) {
2547  perror("Error opening input file ");
2548  exit(1);
2549  }
2550  LOG(VB_GENERAL, LOG_INFO,
2551  QString("Reading from %1").arg(argv[optind]));
2552  rx.inflength = lseek(rx.fd_in, 0, SEEK_END);
2553  LOG(VB_GENERAL, LOG_INFO,
2554  QString("Input file length: %1 MB")
2555  .arg(rx.inflength/1024.0/1024.0, 0,'f',2,QChar('0')));
2556  lseek(rx.fd_in,0,SEEK_SET);
2557  rx.lastper = 0;
2558  rx.finread = 0;
2559  } else {
2560  LOG(VB_GENERAL, LOG_INFO, "using stdin as input");
2561  rx.fd_in = STDIN_FILENO;
2562  rx.inflength = 0;
2563  }
2564 
2565  if (!rx.demux){
2566  if (filename){
2567  if ((rx.fd_out = open(filename,O_WRONLY|O_CREAT
2568  |O_TRUNC|O_LARGEFILE,
2569  S_IRUSR|S_IWUSR|S_IRGRP|
2570  S_IWGRP|
2571  S_IROTH|S_IWOTH)) < 0){
2572  perror("Error opening output file");
2573  exit(1);
2574  }
2575  LOG(VB_GENERAL, LOG_INFO,
2576  QString("Output File is: %1").arg(filename));
2577  } else {
2578  rx.fd_out = STDOUT_FILENO;
2579  LOG(VB_GENERAL, LOG_INFO, "using stdout as output");
2580  }
2581  }
2582  if (scan){
2583  if (rx.fd_in == STDIN_FILENO){
2584  LOG(VB_GENERAL, LOG_ERR, "Can`t scan from pipe");
2585  exit(1);
2586  }
2587  do_scan(&rx);
2588  exit(0);
2589  }
2590 
2591  if (!strncmp(type,"MPEG2",6))
2592  rx.otype=REPLEX_MPEG2;
2593  else if (!strncmp(type,"DVD",4))
2594  rx.otype=REPLEX_DVD;
2595  else if (!strncmp(type,"HDTV",4))
2596  rx.otype=REPLEX_HDTV;
2597  else if (!rx.demux)
2598  usage(argv[0]);
2599 
2600  if (!strncmp(inpt,"TS",3)){
2601  rx.itype=REPLEX_TS;
2602  } else if (!strncmp(inpt,"PS",3)){
2603  rx.itype=REPLEX_PS;
2604  if (!rx.vpid) rx.vpid = 0xE0;
2605  if (!(rx.apidn || rx.ac3n)){
2606  rx.apidn = 1;
2607  rx.apid[0] = 0xC0;
2608  }
2609  } else if (!strncmp(inpt,"AVI",4)){
2610  rx.itype=REPLEX_AVI;
2611  rx.vpid = 0xE0;
2612  rx.apidn = 1;
2613  rx.apid[0] = 0xC0;
2614  rx.ignore_pts =1;
2615  } else {
2616  usage(argv[0]);
2617  }
2618 
2619  init_replex(&rx);
2620  rx.analyze= analyze;
2621 
2622  if (rx.demux) {
2623  int i;
2624  char fname[256];
2625  if (!filename){
2626  filename = static_cast<char*>(malloc(4));
2627  strcpy(filename,"out");
2628  }
2629  if (strlen(filename) > 250){
2630  LOG(VB_GENERAL, LOG_ERR, "Basename too long");
2631  exit(0);
2632  }
2633 
2634  snprintf(fname,256,"%s.mv2",filename);
2635  if ((rx.dmx_out[0] = open(fname,O_WRONLY|
2636  O_CREAT|O_TRUNC|
2637  O_LARGEFILE,
2638  S_IRUSR|S_IWUSR|
2639  S_IRGRP|S_IWGRP|
2640  S_IROTH|S_IWOTH))
2641  < 0){
2642  perror("Error opening output file");
2643  exit(1);
2644  }
2645  LOG(VB_GENERAL, LOG_INFO,
2646  QString("Video output File is: %1").arg(fname));
2647 
2648  for (i=0; i < rx.apidn; i++){
2649  snprintf(fname,256,"%s%d.mp2",filename
2650  ,i);
2651  if ((rx.dmx_out[i+1] =
2652  open(fname,O_WRONLY|
2653  O_CREAT|O_TRUNC|
2654  O_LARGEFILE,
2655  S_IRUSR|S_IWUSR|
2656  S_IRGRP|S_IWGRP|
2657  S_IROTH|S_IWOTH))
2658  < 0){
2659  perror("Error opening output file");
2660  exit(1);
2661  }
2662  LOG(VB_GENERAL, LOG_INFO,
2663  QString("Audio%1 output File is: %2")
2664  .arg(i).arg(fname));
2665  }
2666 
2667 
2668  for (i=0; i < rx.ac3n; i++){
2669  snprintf(fname,256,"%s%d.ac3",filename
2670  ,i);
2671  if ((rx.dmx_out[i+1+rx.apidn] =
2672  open(fname,O_WRONLY|
2673  O_CREAT|O_TRUNC|
2674  O_LARGEFILE,
2675  S_IRUSR|S_IWUSR|
2676  S_IRGRP|S_IWGRP|
2677  S_IROTH|S_IWOTH))
2678  < 0){
2679  perror("Error opening output file");
2680  exit(1);
2681  }
2682  LOG(VB_GENERAL, LOG_INFO,
2683  QString("AC3%1 output File is: %2")
2684  .arg(i).arg(fname));
2685  }
2686  do_demux(&rx);
2687  } else if (analyze){
2688  rx.demux=1;
2689  do_analyze(&rx);
2690  } else {
2691  do_replex(&rx);
2692  }
2693 
2694  return 0;
2695 }
ring_free
static unsigned int ring_free(ringbuffer *rbuf)
Definition: ringbuffer.h:101
pes_in_t::priv
void * priv
Definition: pes.h:89
replex::inflength
uint64_t inflength
Definition: replex.h:49
LIMIT
#define LIMIT
find_pes_ids
static void find_pes_ids(struct replex *rx)
Definition: replex.cpp:1578
PRIVATE_STREAM1
#define PRIVATE_STREAM1
Definition: pes.h:23
ring_posdiff
static int ring_posdiff(ringbuffer *rbuf, int pos1, int pos2)
Definition: ringbuffer.h:87
replex_tsp
static int replex_tsp(struct replex *rx, uint8_t *tsp)
Definition: replex.cpp:1177
index_unit::frame_start
uint8_t frame_start
Definition: mpg_common.h:48
S_SEARCH
@ S_SEARCH
Definition: replex.h:38
replex::audio_state
int audio_state[N_AUDIO]
Definition: replex.h:106
write_out_packs
int write_out_packs(multiplex_t *mx, int video_ok, aok_arr &ext_ok)
Definition: multiplex.cpp:590
avi_audio_s::fps
uint32_t fps
Definition: avi.h:51
ring_init
int ring_init(ringbuffer *rbuf, int size)
Definition: ringbuffer.cpp:38
CLOCK_MS
#define CLOCK_MS
Definition: element.h:78
sequence_t::current_frame
uint8_t current_frame
Definition: element.h:105
ptsdec
static void ptsdec(uint64_t *pts1, uint64_t pts2)
Definition: pes.h:122
avi_context::ai
avi_audio_info ai[MAX_TRACK]
Definition: avi.h:99
pes.h
error
static void error(const char *str,...)
Definition: vbi.cpp:36
REPLEX_PS
#define REPLEX_PS
Definition: replex.h:42
find_audio_sync
int find_audio_sync(ringbuffer *rbuf, audio_sync_buf &buf, int off, int type, int le)
Definition: element.cpp:327
MAX_PLENGTH
#define MAX_PLENGTH
Definition: pes.h:49
replex::extframe
audio_frame_t extframe[N_AUDIO]
Definition: replex.h:77
replex::current_vindex
index_unit current_vindex
Definition: replex.h:113
MAXVPID
#define MAXVPID
Definition: replex.cpp:1358
B_FRAME
#define B_FRAME
Definition: element.h:56
fill_buffers
static int fill_buffers(void *r, int finish)
Definition: replex.cpp:1849
replex::vdr
int vdr
Definition: replex.h:61
replex::demux
int demux
Definition: replex.h:57
ring_peek
int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.cpp:122
next_ptsdts_video
uint64_t next_ptsdts_video(uint64_t *pts, sequence_t *s, uint64_t fcount, uint64_t gcount)
Definition: element.cpp:76
find_audio_s
int find_audio_s(const uint8_t *rbuf, int off, int type, int le)
Definition: element.cpp:377
replex::ignore_pts
int ignore_pts
Definition: replex.h:46
ringbuffer
Definition: ringbuffer.h:39
index_unit::gop_off
uint8_t gop_off
Definition: mpg_common.h:46
sequence_t
Definition: element.h:87
SEC_PER
#define SEC_PER
Definition: element.h:80
find_any_header
int find_any_header(uint8_t *head, const uint8_t *buf, int length)
Definition: mpg_common.cpp:107
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
get_video_info
int get_video_info(ringbuffer *rbuf, sequence_t *s, int off, int le)
Definition: element.cpp:195
get_pid
uint16_t get_pid(const uint8_t *pid)
Definition: ts.cpp:47
index_unit::seq_end
uint8_t seq_end
Definition: mpg_common.h:42
fix_audio
static void fix_audio(struct replex *rx, multiplex_t *mx)
Definition: replex.cpp:2082
replex::extrbuffer
ringbuffer extrbuffer[N_AUDIO]
Definition: replex.h:78
replex::audiobuf
int audiobuf
Definition: replex.h:70
fix_video_count
void fix_video_count(sequence_t *s, uint64_t *frame, uint64_t origpts, uint64_t pts, uint64_t origdts, uint64_t dts)
Definition: element.cpp:117
avi_context::movi_length
int64_t movi_length
Definition: avi.h:73
VIDEO_STREAM_S
#define VIDEO_STREAM_S
Definition: pes.h:28
init_index
void init_index(index_unit *iu)
Definition: replex.cpp:1859
get_next_video_unit
static int get_next_video_unit(struct replex *rx, index_unit *viu)
Definition: replex.cpp:2142
avi_es_out
static void avi_es_out(pes_in_t *p)
Definition: replex.cpp:1108
replex::ac
avi_context ac
Definition: replex.h:60
replex::exttype
int exttype[N_AUDIO]
Definition: replex.h:75
index_unit::dts
uint64_t dts
Definition: mpg_common.h:40
S_IWGRP
#define S_IWGRP
Definition: replex.cpp:56
pes_es_out
static void pes_es_out(pes_in_t *p)
Definition: replex.cpp:996
get_audio_info
int get_audio_info(ringbuffer *rbuf, audio_frame_t *af, int off, int le)
Definition: element.cpp:483
mythburn.write
def write(text, progress=True)
Definition: mythburn.py:308
audio_frame_t::bit_rate
uint32_t bit_rate
Definition: element.h:112
INDEX_BUF
#define INDEX_BUF
Definition: replex.h:69
get_ac3_info
int get_ac3_info(ringbuffer *rbuf, audio_frame_t *af, int off, int le)
Definition: element.cpp:534
replex::first_iframe
int first_iframe
Definition: replex.h:111
replex::aframe_count
uint64_t aframe_count[N_AUDIO]
Definition: replex.h:103
replex::fd_in
int fd_in
Definition: replex.h:54
PICTURE_START_CODE
#define PICTURE_START_CODE
Definition: element.h:35
replex::last_ac3pts
uint64_t last_ac3pts[N_AC3]
Definition: replex.h:93
replex::ac3_id
uint16_t ac3_id[N_AC3]
Definition: replex.h:83
MMAX_PLENGTH
#define MMAX_PLENGTH
Definition: pes.h:50
replex::vframe_count
uint64_t vframe_count
Definition: replex.h:117
read_avi_header
int read_avi_header(avi_context *ac, int fd)
Definition: avi.cpp:215
printpts
void printpts(int64_t pts)
Definition: pes.cpp:43
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
replex::video_state
int video_state
Definition: replex.h:121
AC3
@ AC3
Definition: element.h:84
find_pids_file
static void find_pids_file(struct replex *rx)
Definition: replex.cpp:1306
init_multiplex
void init_multiplex(multiplex_t *mx, sequence_t *seq_head, audio_frame_t *extframe, int *exttype, const int *exttypcnt, uint64_t video_delay, uint64_t audio_delay, int fd, int(*fill_buffers)(void *p, int f), ringbuffer *vrbuffer, ringbuffer *index_vrbuffer, ringbuffer *extrbuffer, ringbuffer *index_extrbuffer, int otype)
Definition: multiplex.cpp:696
fix_audio_count
void fix_audio_count(uint64_t *acount, audio_frame_t *aframe, uint64_t origpts, uint64_t pts)
Definition: element.cpp:65
ring_read_file
int ring_read_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.cpp:300
REPLEX_HDTV
#define REPLEX_HDTV
Definition: multiplex.h:45
replex::current_ac3index
index_unit current_ac3index[N_AC3]
Definition: replex.h:85
I_FRAME
#define I_FRAME
Definition: element.h:54
avi_read_index
int avi_read_index(avi_context *ac, int fd)
Definition: avi.cpp:142
replex::vpes_abort
int vpes_abort
Definition: replex.h:114
replex::index_vrbuffer
ringbuffer index_vrbuffer
Definition: replex.h:116
replex::keep_pts
int keep_pts
Definition: replex.h:47
hardwareprofile.scan.scan
def scan(profile, smoonURL, gate)
Definition: scan.py:55
VIDEO_BUF
#define VIDEO_BUF
Definition: replex.h:66
sequence_t::set
int set
Definition: element.h:88
index_unit::seq_header
uint8_t seq_header
Definition: mpg_common.h:41
replex::avi_rest
int avi_rest
Definition: replex.h:52
replex::lastper
int lastper
Definition: replex.h:51
check_audio_header
int check_audio_header(ringbuffer *rbuf, audio_frame_t *af, int off, int le, int type)
Definition: element.cpp:419
P_FRAME
#define P_FRAME
Definition: element.h:55
ptsdiff
int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:78
do_replex
static void do_replex(struct replex *rx)
Definition: replex.cpp:2354
AVI_HASINDEX
#define AVI_HASINDEX
Definition: avi.h:37
replex::current_aindex
index_unit current_aindex[N_AUDIO]
Definition: replex.h:99
replex::ac3_state
int ac3_state[N_AUDIO]
Definition: replex.h:92
lseek
#define lseek
Definition: mythiowrapper.cpp:239
pes_id_out
static void pes_id_out(pes_in_t *p)
Definition: replex.cpp:1516
guess_fill
static int guess_fill(struct replex *rx)
Definition: replex.cpp:1261
multiplex_t::ext
ext_arr ext
Definition: multiplex.h:79
index_unit::frame_off
uint8_t frame_off
Definition: mpg_common.h:47
replex::last_vpts
uint64_t last_vpts
Definition: replex.h:122
AVFrame
struct AVFrame AVFrame
Definition: BorderDetector.h:15
avi_video_s::fps
uint32_t fps
Definition: avi.h:63
SEQUENCE_END_CODE
#define SEQUENCE_END_CODE
Definition: element.h:45
index_unit::active
uint8_t active
Definition: mpg_common.h:36
analyze_audio
static void analyze_audio(pes_in_t *p, struct replex *rx, int len, int num, int type)
Definition: replex.cpp:247
mythlogging.h
replex::ac3frame
audio_frame_t ac3frame[N_AC3]
Definition: replex.h:90
replex::vrbuffer
ringbuffer vrbuffer
Definition: replex.h:115
replex::fix_sync
int fix_sync
Definition: replex.h:48
trans_pts_dts
uint64_t trans_pts_dts(const uint8_t *pts)
Definition: mpg_common.cpp:143
replex::scan_found
int scan_found
Definition: replex.h:125
do_analyze
static void do_analyze(struct replex *rx)
Definition: replex.cpp:2174
replex::finish
int finish
Definition: replex.h:56
replex::index_arbuffer
ringbuffer index_arbuffer[N_AUDIO]
Definition: replex.h:102
FRAME_ERR
#define FRAME_ERR
Definition: mpg_common.h:67
hardwareprofile.config.p
p
Definition: config.py:33
audio_sync_buf
std::array< uint8_t, 7 > audio_sync_buf
Definition: element.h:123
index_unit::start
uint32_t start
Definition: mpg_common.h:38
hardwareprofile.i18n.t
t
Definition: i18n.py:36
PTS_ONLY
#define PTS_ONLY
Definition: pes.h:46
MAXAC3PID
#define MAXAC3PID
Definition: replex.cpp:1360
avi_context::done
int done
Definition: avi.h:75
N_AUDIO
#define N_AUDIO
Definition: multiplex.h:35
replex::itype
int itype
Definition: replex.h:44
replex::first_vpts
uint64_t first_vpts
Definition: replex.h:120
PAY_START
static constexpr uint8_t PAY_START
Definition: ts.h:35
sequence_t::current_tmpref
uint8_t current_tmpref
Definition: element.h:106
AUDIO_BUF
#define AUDIO_BUF
Definition: replex.h:67
REPLEX_DVD
#define REPLEX_DVD
Definition: multiplex.h:44
replex::last_apts
uint64_t last_apts[N_AUDIO]
Definition: replex.h:107
replex::index_ac3rbuffer
ringbuffer index_ac3rbuffer[N_AC3]
Definition: replex.h:88
find_pids
int find_pids(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid, uint8_t *buf, int len)
Definition: ts.cpp:127
replex::vpid
uint16_t vpid
Definition: replex.h:110
replex::ac3buf
int ac3buf
Definition: replex.h:71
get_avi_from_index
int get_avi_from_index(pes_in_t *p, int fd, avi_context *ac, void(*func)(pes_in_t *p), uint32_t insize)
Definition: avi.cpp:426
avi_context::avih_flags
uint32_t avih_flags
Definition: avi.h:83
audio_frame_t::frequency
uint32_t frequency
Definition: element.h:113
get_next_audio_unit
static int get_next_audio_unit(struct replex *rx, index_unit *aiu, int i)
Definition: replex.cpp:2152
S_IWOTH
#define S_IWOTH
Definition: replex.cpp:58
replex_fill_buffers
static int replex_fill_buffers(struct replex *rx, uint8_t *mbuf)
Definition: replex.cpp:1703
find_pids_pos
int find_pids_pos(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid, uint8_t *buf, int len, int *vpos, int *apos, int *ac3pos)
Definition: ts.cpp:57
check_times
void check_times(multiplex_t *mx, int *video_ok, aok_arr &ext_ok, int *start)
Definition: multiplex.cpp:493
audio_frame_t::set
int set
Definition: element.h:110
replex_all_set
static int replex_all_set(struct replex *rx)
Definition: replex.cpp:1865
TS_SIZE
static constexpr qint64 TS_SIZE
Definition: hlsstreamhandler.cpp:19
audio_frame_t::frametime
uint32_t frametime
Definition: element.h:118
index_unit::frame
uint8_t frame
Definition: mpg_common.h:45
replex::otype
int otype
Definition: replex.h:45
replex::pac3
pes_in_t pac3[N_AC3]
Definition: replex.h:84
ringbuffer::size
uint32_t size
Definition: ringbuffer.h:42
ring_write
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:90
add_pts_audio
uint64_t add_pts_audio(uint64_t pts, audio_frame_t *aframe, uint64_t frames)
Definition: element.cpp:56
ADAPT_FIELD
static constexpr uint8_t ADAPT_FIELD
Definition: ts.h:42
AUDIO_STREAM_E
#define AUDIO_STREAM_E
Definition: pes.h:27
usage
static void usage(char *progname)
Definition: replex.cpp:2415
replex::priv
void * priv
Definition: replex.h:124
S_IRGRP
#define S_IRGRP
Definition: replex.cpp:55
replex::exttypcnt
int exttypcnt[N_AUDIO]
Definition: replex.h:76
do_scan
static void do_scan(struct replex *rx)
Definition: replex.cpp:2287
O_LARGEFILE
#define O_LARGEFILE
Definition: replex.cpp:46
sequence_t::ext_set
int ext_set
Definition: element.h:89
finish_mpg
int finish_mpg(multiplex_t *mx)
Definition: multiplex.cpp:609
get_next_ac3_unit
static int get_next_ac3_unit(struct replex *rx, index_unit *aiu, int i)
Definition: replex.cpp:2162
encode_mp2_audio
static int encode_mp2_audio(audio_frame_t *aframe, uint8_t *buffer, int bufsize)
Definition: replex.cpp:188
MAX_TRIES
#define MAX_TRIES
replex::finread
uint64_t finread
Definition: replex.h:50
replex_check_id
static int replex_check_id(struct replex *rx, uint16_t id)
Definition: replex.cpp:69
N_AC3
#define N_AC3
Definition: multiplex.h:36
replex::ac3rbuffer
ringbuffer ac3rbuffer[N_AC3]
Definition: replex.h:87
ring_wpos
static int ring_wpos(ringbuffer *rbuf)
Definition: ringbuffer.h:77
es_out
static void es_out(pes_in_t *p)
Definition: replex.cpp:926
index_unit::err
uint8_t err
Definition: mpg_common.h:49
IN_SIZE
#define IN_SIZE
Definition: replex.cpp:1305
index_unit::framesize
uint32_t framesize
Definition: mpg_common.h:50
get_pes
void get_pes(pes_in_t *p, uint8_t *buf, int count, void(*func)(pes_in_t *p))
Definition: pes.cpp:164
replex::ac3n
int ac3n
Definition: replex.h:82
replex::index_extrbuffer
ringbuffer index_extrbuffer[N_AUDIO]
Definition: replex.h:79
replex::video_delay
uint64_t video_delay
Definition: replex.h:63
replex::videobuf
int videobuf
Definition: replex.h:72
index_unit::gop
uint8_t gop
Definition: mpg_common.h:43
uptsdiff
uint64_t uptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:104
SEQUENCE_HDR_CODE
#define SEQUENCE_HDR_CODE
Definition: element.h:42
ring_read
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:200
AC3_BUF
#define AC3_BUF
Definition: replex.h:68
replex::arbuffer
ringbuffer arbuffer[N_AUDIO]
Definition: replex.h:101
REPLEX_MPEG2
#define REPLEX_MPEG2
Definition: multiplex.h:43
ring_find_any_header
int ring_find_any_header(ringbuffer *rbuf, uint8_t *head, int off, int le)
Definition: mpg_common.cpp:216
replex::apid
uint16_t apid[N_AUDIO]
Definition: replex.h:97
avi_context
Definition: avi.h:70
init_pes_in
void init_pes_in(pes_in_t *p, int t, ringbuffer *rb, int wi)
Definition: pes.cpp:146
check_stream_type
static int check_stream_type(struct replex *rx, uint8_t *buf, int len)
Definition: replex.cpp:1883
get_avi
void get_avi(pes_in_t *p, uint8_t *buf, int count, void(*func)(pes_in_t *p))
Definition: avi.cpp:525
replex::fd_out
int fd_out
Definition: replex.h:55
VIDEO_STREAM_E
#define VIDEO_STREAM_E
Definition: pes.h:29
avcodec_encode_audio
static int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples)
Definition: replex.cpp:87
find_pids_stdin
static void find_pids_stdin(struct replex *rx, uint8_t *buf, int len)
Definition: replex.cpp:1453
replex
Definition: replex.h:40
ring_avail
static unsigned int ring_avail(ringbuffer *rbuf)
Definition: ringbuffer.h:108
save_read
static ssize_t save_read(struct replex *rx, void *buf, size_t count)
Definition: replex.cpp:1226
replex::analyze
int analyze
Definition: replex.h:59
AUDIO_STREAM_S
#define AUDIO_STREAM_S
Definition: pes.h:26
MPEG_AUDIO
@ MPEG_AUDIO
Definition: element.h:84
replex::apes_abort
int apes_abort[N_AUDIO]
Definition: replex.h:100
ring_skip
int ring_skip(ringbuffer *rbuf, int count)
Definition: ringbuffer.cpp:233
PICTURE_CODING_EXTENSION
#define PICTURE_CODING_EXTENSION
Definition: element.h:50
replex::seq_head
sequence_t seq_head
Definition: replex.h:119
setup_multiplex
void setup_multiplex(multiplex_t *mx)
Definition: multiplex.cpp:856
replex::audio_delay
uint64_t audio_delay
Definition: replex.h:64
main
int main(int argc, char **argv)
Definition: replex.cpp:2438
check_riff
int check_riff(avi_context *ac, uint8_t *buf, int len)
Definition: avi.cpp:79
MAXAPID
#define MAXAPID
Definition: replex.cpp:1359
get_video_ext_info
int get_video_ext_info(ringbuffer *rbuf, sequence_t *s, int off, int le)
Definition: element.cpp:591
replex::apidn
int apidn
Definition: replex.h:96
do_demux
static void do_demux(struct replex *rx)
Definition: replex.cpp:2317
audio_frame_t::framesize
uint32_t framesize
Definition: element.h:117
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
ptscmp
int ptscmp(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:114
REPLEX_AVI
#define REPLEX_AVI
Definition: replex.h:43
audio_frame_t
Definition: element.h:109
replex::aframe
audio_frame_t aframe[N_AUDIO]
Definition: replex.h:104
replex::dmx_out
int dmx_out[N_AC3+N_AUDIO+1]
Definition: replex.h:58
printptss
void printptss(int64_t pts)
Definition: pes.cpp:60
replex::ac3pes_abort
int ac3pes_abort[N_AC3]
Definition: replex.h:86
avi_audio_s::initial_frames
uint32_t initial_frames
Definition: avi.h:53
multiplex_t
Definition: multiplex.h:41
pes_in_t
Definition: pes.h:70
analyze_video
static void analyze_video(pes_in_t *p, struct replex *rx, int len)
Definition: replex.cpp:523
PTS_DTS
#define PTS_DTS
Definition: pes.h:47
avi_context::vi
avi_video_info vi
Definition: avi.h:98
GROUP_START_CODE
#define GROUP_START_CODE
Definition: element.h:46
multiplex_t::priv
void * priv
Definition: multiplex.h:88
build_compdb.filename
filename
Definition: build_compdb.py:21
index_unit
Definition: mpg_common.h:35
REPLEX_TS
#define REPLEX_TS
Definition: replex.h:41
init_replex
static void init_replex(struct replex *rx)
Definition: replex.cpp:1932
samples
static const std::array< const uint64_t, 4 > samples
Definition: element.cpp:46
replex::first_apts
uint64_t first_apts[N_AUDIO]
Definition: replex.h:105
replex::vgroup_count
uint64_t vgroup_count
Definition: replex.h:118
show_buf
void show_buf(uint8_t *buf, int length)
Definition: mpg_common.cpp:37
replex::first_ac3pts
uint64_t first_ac3pts[N_AC3]
Definition: replex.h:91
replex.h
AVI_S
#define AVI_S
replex_finish
static void replex_finish(struct replex *rx)
Definition: replex.cpp:1687
index_unit::pts
uint64_t pts
Definition: mpg_common.h:39
aok_arr
std::array< bool, N_AUDIO > aok_arr
Definition: multiplex.h:39
replex::paudio
pes_in_t paudio[N_AUDIO]
Definition: replex.h:98
find_all_pids_file
static void find_all_pids_file(struct replex *rx)
Definition: replex.cpp:1361
S_IROTH
#define S_IROTH
Definition: replex.cpp:57
replex::pvideo
pes_in_t pvideo
Definition: replex.h:112
EXTENSION_START_CODE
#define EXTENSION_START_CODE
Definition: element.h:44
index_unit::length
uint32_t length
Definition: mpg_common.h:37
ring_rdiff
static int ring_rdiff(ringbuffer *rbuf, int pos)
Definition: ringbuffer.h:97
replex::ac3frame_count
uint64_t ac3frame_count[N_AC3]
Definition: replex.h:89