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
49extern "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
67static int replex_all_set(struct replex *rx);
68
69static 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
87static 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
188static 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
247static 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
523static 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){
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
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
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
926static 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
996static 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){
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
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
1108static 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
1177static 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
1226static 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
1261static 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)
1306static 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
1361static 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;
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
1453static 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;
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));
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
1516static 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){
1525 rx->scan_found=p->cid;
1526 break;
1527
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
1578static 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;
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
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
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
1687static 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
1703static 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
1849static 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
1865static 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
1883static int check_stream_type(struct replex *rx, uint8_t * buf, int len)
1884{
1885 int c=0;
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
1932static 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));
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 }
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));
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;
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
2082static 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
2142static 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
2152static 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
2162static 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
2174static 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
2287static 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:
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
2317static 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
2354static 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,
2395 &rx->vrbuffer, &rx->index_vrbuffer,
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
2415static 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
2438int 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))
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|
2638 S_IRUSR|S_IWUSR|
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|
2655 S_IRUSR|S_IWUSR|
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|
2675 S_IRUSR|S_IWUSR|
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}
AVFrame AVFrame
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
int read_avi_header(avi_context *ac, int fd)
Definition: avi.cpp:215
int check_riff(avi_context *ac, uint8_t *buf, int len)
Definition: avi.cpp:79
void get_avi(pes_in_t *p, uint8_t *buf, int count, void(*func)(pes_in_t *p))
Definition: avi.cpp:525
int avi_read_index(avi_context *ac, int fd)
Definition: avi.cpp:142
#define AVI_HASINDEX
Definition: avi.h:37
int get_audio_info(ringbuffer *rbuf, audio_frame_t *af, int off, int le)
Definition: element.cpp:488
uint64_t add_pts_audio(uint64_t pts, audio_frame_t *aframe, uint64_t frames)
Definition: element.cpp:56
int find_audio_sync(ringbuffer *rbuf, audio_sync_buf &buf, int off, int type, int le)
Definition: element.cpp:329
void fix_audio_count(uint64_t *acount, audio_frame_t *aframe, uint64_t origpts, uint64_t pts)
Definition: element.cpp:65
int get_ac3_info(ringbuffer *rbuf, audio_frame_t *af, int off, int le)
Definition: element.cpp:539
int find_audio_s(const uint8_t *rbuf, int off, int type, int le)
Definition: element.cpp:381
uint64_t next_ptsdts_video(uint64_t *pts, sequence_t *s, uint64_t fcount, uint64_t gcount)
Definition: element.cpp:76
int get_video_ext_info(ringbuffer *rbuf, sequence_t *s, int off, int le)
Definition: element.cpp:596
int get_video_info(ringbuffer *rbuf, sequence_t *s, int off, int le)
Definition: element.cpp:197
int check_audio_header(ringbuffer *rbuf, audio_frame_t *af, int off, int le, int type)
Definition: element.cpp:425
static const std::array< const uint64_t, 4 > samples
Definition: element.cpp:46
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
#define PICTURE_START_CODE
Definition: element.h:35
#define SEQUENCE_END_CODE
Definition: element.h:45
#define P_FRAME
Definition: element.h:55
#define PICTURE_CODING_EXTENSION
Definition: element.h:50
#define I_FRAME
Definition: element.h:54
#define B_FRAME
Definition: element.h:56
#define CLOCK_MS
Definition: element.h:78
#define GROUP_START_CODE
Definition: element.h:46
@ AC3
Definition: element.h:84
@ MPEG_AUDIO
Definition: element.h:84
#define EXTENSION_START_CODE
Definition: element.h:44
#define SEC_PER
Definition: element.h:80
std::array< uint8_t, 7 > audio_sync_buf
Definition: element.h:123
#define SEQUENCE_HDR_CODE
Definition: element.h:42
static constexpr qint64 TS_SIZE
unsigned short uint16_t
Definition: iso6937tables.h:3
void show_buf(uint8_t *buf, int length)
Definition: mpg_common.cpp:37
int ring_find_any_header(ringbuffer *rbuf, uint8_t *head, int off, int le)
Definition: mpg_common.cpp:216
int find_any_header(uint8_t *head, const uint8_t *buf, int length)
Definition: mpg_common.cpp:107
uint64_t trans_pts_dts(const uint8_t *pts)
Definition: mpg_common.cpp:143
#define FRAME_ERR
Definition: mpg_common.h:67
int write_out_packs(multiplex_t *mx, int video_ok, aok_arr &ext_ok)
Definition: multiplex.cpp:600
void check_times(multiplex_t *mx, int *video_ok, aok_arr &ext_ok, int *start)
Definition: multiplex.cpp:500
void setup_multiplex(multiplex_t *mx)
Definition: multiplex.cpp:865
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:705
int finish_mpg(multiplex_t *mx)
Definition: multiplex.cpp:619
#define REPLEX_MPEG2
Definition: multiplex.h:43
#define N_AUDIO
Definition: multiplex.h:35
#define REPLEX_HDTV
Definition: multiplex.h:45
#define N_AC3
Definition: multiplex.h:36
#define REPLEX_DVD
Definition: multiplex.h:44
std::array< bool, N_AUDIO > aok_arr
Definition: multiplex.h:39
#define lseek
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
def read(device=None, features=[])
Definition: disc.py:35
def scan(profile, smoonURL, gate)
Definition: scan.py:54
def error(message)
Definition: smolt.py:409
def write(text, progress=True)
Definition: mythburn.py:307
void get_pes(pes_in_t *p, uint8_t *buf, int count, void(*func)(pes_in_t *p))
Definition: pes.cpp:167
void printptss(int64_t pts)
Definition: pes.cpp:60
void printpts(int64_t pts)
Definition: pes.cpp:43
int ptscmp(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:114
int64_t ptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:78
uint64_t uptsdiff(uint64_t pts1, uint64_t pts2)
Definition: pes.cpp:104
void init_pes_in(pes_in_t *p, int t, ringbuffer *rb, int wi)
Definition: pes.cpp:147
static void ptsdec(uint64_t *pts1, uint64_t pts2)
Definition: pes.h:122
#define AUDIO_STREAM_S
Definition: pes.h:26
#define PTS_ONLY
Definition: pes.h:46
#define VIDEO_STREAM_E
Definition: pes.h:29
#define MMAX_PLENGTH
Definition: pes.h:50
#define PRIVATE_STREAM1
Definition: pes.h:23
#define AUDIO_STREAM_E
Definition: pes.h:27
#define PTS_DTS
Definition: pes.h:47
#define MAX_PLENGTH
Definition: pes.h:49
#define VIDEO_STREAM_S
Definition: pes.h:28
#define MAXVPID
Definition: replex.cpp:1358
static void find_pes_ids(struct replex *rx)
Definition: replex.cpp:1578
#define S_IROTH
Definition: replex.cpp:57
#define MAXAC3PID
Definition: replex.cpp:1360
#define O_LARGEFILE
Definition: replex.cpp:46
static int check_stream_type(struct replex *rx, uint8_t *buf, int len)
Definition: replex.cpp:1883
static void find_pids_file(struct replex *rx)
Definition: replex.cpp:1306
static void do_replex(struct replex *rx)
Definition: replex.cpp:2354
static void avi_es_out(pes_in_t *p)
Definition: replex.cpp:1108
int main(int argc, char **argv)
Definition: replex.cpp:2438
static int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples)
Definition: replex.cpp:87
static void replex_finish(struct replex *rx)
Definition: replex.cpp:1687
static int replex_fill_buffers(struct replex *rx, uint8_t *mbuf)
Definition: replex.cpp:1703
#define S_IRGRP
Definition: replex.cpp:55
static void do_scan(struct replex *rx)
Definition: replex.cpp:2287
#define S_IWOTH
Definition: replex.cpp:58
#define LIMIT
static void find_pids_stdin(struct replex *rx, uint8_t *buf, int len)
Definition: replex.cpp:1453
static int encode_mp2_audio(audio_frame_t *aframe, uint8_t *buffer, int bufsize)
Definition: replex.cpp:188
static void analyze_audio(pes_in_t *p, struct replex *rx, int len, int num, int type)
Definition: replex.cpp:247
static void usage(char *progname)
Definition: replex.cpp:2415
static int get_next_video_unit(struct replex *rx, index_unit *viu)
Definition: replex.cpp:2142
static int fill_buffers(void *r, int finish)
Definition: replex.cpp:1849
static void init_replex(struct replex *rx)
Definition: replex.cpp:1932
static int replex_all_set(struct replex *rx)
Definition: replex.cpp:1865
static void analyze_video(pes_in_t *p, struct replex *rx, int len)
Definition: replex.cpp:523
#define AVI_S
static int guess_fill(struct replex *rx)
Definition: replex.cpp:1261
static void pes_es_out(pes_in_t *p)
Definition: replex.cpp:996
void init_index(index_unit *iu)
Definition: replex.cpp:1859
static void es_out(pes_in_t *p)
Definition: replex.cpp:926
#define MAXAPID
Definition: replex.cpp:1359
static void fix_audio(struct replex *rx, multiplex_t *mx)
Definition: replex.cpp:2082
static int get_next_audio_unit(struct replex *rx, index_unit *aiu, int i)
Definition: replex.cpp:2152
static int get_next_ac3_unit(struct replex *rx, index_unit *aiu, int i)
Definition: replex.cpp:2162
static void do_demux(struct replex *rx)
Definition: replex.cpp:2317
static ssize_t save_read(struct replex *rx, void *buf, size_t count)
Definition: replex.cpp:1226
static void find_all_pids_file(struct replex *rx)
Definition: replex.cpp:1361
static void do_analyze(struct replex *rx)
Definition: replex.cpp:2174
static void pes_id_out(pes_in_t *p)
Definition: replex.cpp:1516
#define S_IWGRP
Definition: replex.cpp:56
static int replex_check_id(struct replex *rx, uint16_t id)
Definition: replex.cpp:69
static int replex_tsp(struct replex *rx, uint8_t *tsp)
Definition: replex.cpp:1177
#define IN_SIZE
Definition: replex.cpp:1305
#define MAX_TRIES
#define REPLEX_TS
Definition: replex.h:41
#define AUDIO_BUF
Definition: replex.h:67
@ S_SEARCH
Definition: replex.h:38
#define REPLEX_PS
Definition: replex.h:42
#define AC3_BUF
Definition: replex.h:68
#define VIDEO_BUF
Definition: replex.h:66
#define REPLEX_AVI
Definition: replex.h:43
#define INDEX_BUF
Definition: replex.h:69
int ring_read(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:202
int ring_write(ringbuffer *rbuf, uint8_t *data, int count)
Definition: ringbuffer.cpp:92
int ring_read_file(ringbuffer *rbuf, int fd, int count)
Definition: ringbuffer.cpp:302
int ring_peek(ringbuffer *rbuf, uint8_t *data, unsigned int count, uint32_t off)
Definition: ringbuffer.cpp:124
int ring_skip(ringbuffer *rbuf, int count)
Definition: ringbuffer.cpp:235
int ring_init(ringbuffer *rbuf, int size)
Definition: ringbuffer.cpp:38
static unsigned int ring_avail(ringbuffer *rbuf)
Definition: ringbuffer.h:108
static int ring_wpos(ringbuffer *rbuf)
Definition: ringbuffer.h:77
static unsigned int ring_free(ringbuffer *rbuf)
Definition: ringbuffer.h:101
static int ring_rdiff(ringbuffer *rbuf, int pos)
Definition: ringbuffer.h:97
static int ring_posdiff(ringbuffer *rbuf, int pos1, int pos2)
Definition: ringbuffer.h:87
uint32_t bit_rate
Definition: element.h:112
uint32_t framesize
Definition: element.h:117
uint32_t frequency
Definition: element.h:113
uint32_t frametime
Definition: element.h:118
uint32_t fps
Definition: avi.h:51
uint32_t initial_frames
Definition: avi.h:53
int done
Definition: avi.h:75
avi_audio_info ai[MAX_TRACK]
Definition: avi.h:99
int64_t movi_length
Definition: avi.h:73
uint32_t avih_flags
Definition: avi.h:83
avi_video_info vi
Definition: avi.h:98
uint32_t fps
Definition: avi.h:63
uint32_t framesize
Definition: mpg_common.h:50
uint32_t start
Definition: mpg_common.h:38
uint8_t seq_header
Definition: mpg_common.h:41
uint64_t pts
Definition: mpg_common.h:39
uint8_t gop
Definition: mpg_common.h:43
uint8_t frame
Definition: mpg_common.h:45
uint8_t gop_off
Definition: mpg_common.h:46
uint8_t err
Definition: mpg_common.h:49
uint64_t dts
Definition: mpg_common.h:40
uint8_t seq_end
Definition: mpg_common.h:42
uint8_t active
Definition: mpg_common.h:36
uint8_t frame_off
Definition: mpg_common.h:47
uint32_t length
Definition: mpg_common.h:37
uint8_t frame_start
Definition: mpg_common.h:48
void * priv
Definition: multiplex.h:88
ext_arr ext
Definition: multiplex.h:79
Definition: pes.h:70
void * priv
Definition: pes.h:89
Definition: replex.h:40
uint64_t audio_delay
Definition: replex.h:64
index_unit current_aindex[N_AUDIO]
Definition: replex.h:99
int fix_sync
Definition: replex.h:48
int apes_abort[N_AUDIO]
Definition: replex.h:100
uint64_t aframe_count[N_AUDIO]
Definition: replex.h:103
uint16_t apid[N_AUDIO]
Definition: replex.h:97
uint64_t first_ac3pts[N_AC3]
Definition: replex.h:91
int itype
Definition: replex.h:44
int audiobuf
Definition: replex.h:70
int lastper
Definition: replex.h:51
ringbuffer index_arbuffer[N_AUDIO]
Definition: replex.h:102
int keep_pts
Definition: replex.h:47
uint64_t finread
Definition: replex.h:50
int scan_found
Definition: replex.h:125
ringbuffer extrbuffer[N_AUDIO]
Definition: replex.h:78
int fd_in
Definition: replex.h:54
uint64_t first_vpts
Definition: replex.h:120
int finish
Definition: replex.h:56
ringbuffer index_ac3rbuffer[N_AC3]
Definition: replex.h:88
int analyze
Definition: replex.h:59
uint64_t last_vpts
Definition: replex.h:122
int dmx_out[N_AC3+N_AUDIO+1]
Definition: replex.h:58
uint64_t video_delay
Definition: replex.h:63
int demux
Definition: replex.h:57
audio_frame_t extframe[N_AUDIO]
Definition: replex.h:77
audio_frame_t aframe[N_AUDIO]
Definition: replex.h:104
index_unit current_vindex
Definition: replex.h:113
int ac3buf
Definition: replex.h:71
void * priv
Definition: replex.h:124
avi_context ac
Definition: replex.h:60
pes_in_t pvideo
Definition: replex.h:112
int videobuf
Definition: replex.h:72
audio_frame_t ac3frame[N_AC3]
Definition: replex.h:90
ringbuffer arbuffer[N_AUDIO]
Definition: replex.h:101
int exttype[N_AUDIO]
Definition: replex.h:75
uint16_t vpid
Definition: replex.h:110
int fd_out
Definition: replex.h:55
ringbuffer vrbuffer
Definition: replex.h:115
pes_in_t pac3[N_AC3]
Definition: replex.h:84
int ignore_pts
Definition: replex.h:46
int ac3_state[N_AUDIO]
Definition: replex.h:92
int video_state
Definition: replex.h:121
int ac3pes_abort[N_AC3]
Definition: replex.h:86
int vdr
Definition: replex.h:61
index_unit current_ac3index[N_AC3]
Definition: replex.h:85
ringbuffer index_extrbuffer[N_AUDIO]
Definition: replex.h:79
uint64_t inflength
Definition: replex.h:49
int otype
Definition: replex.h:45
uint64_t vframe_count
Definition: replex.h:117
int apidn
Definition: replex.h:96
int audio_state[N_AUDIO]
Definition: replex.h:106
uint64_t vgroup_count
Definition: replex.h:118
uint64_t ac3frame_count[N_AC3]
Definition: replex.h:89
int first_iframe
Definition: replex.h:111
int vpes_abort
Definition: replex.h:114
int ac3n
Definition: replex.h:82
uint64_t first_apts[N_AUDIO]
Definition: replex.h:105
int exttypcnt[N_AUDIO]
Definition: replex.h:76
uint64_t last_apts[N_AUDIO]
Definition: replex.h:107
sequence_t seq_head
Definition: replex.h:119
uint16_t ac3_id[N_AC3]
Definition: replex.h:83
ringbuffer index_vrbuffer
Definition: replex.h:116
ringbuffer ac3rbuffer[N_AC3]
Definition: replex.h:87
uint64_t last_ac3pts[N_AC3]
Definition: replex.h:93
pes_in_t paudio[N_AUDIO]
Definition: replex.h:98
int avi_rest
Definition: replex.h:52
uint32_t size
Definition: ringbuffer.h:42
uint8_t current_tmpref
Definition: element.h:106
int set
Definition: element.h:88
int ext_set
Definition: element.h:89
uint8_t current_frame
Definition: element.h:105
uint16_t get_pid(const uint8_t *pid)
Definition: ts.cpp:48
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:58
int find_pids(uint16_t *vpid, uint16_t *apid, uint16_t *ac3pid, uint8_t *buf, int len)
Definition: ts.cpp:128
static constexpr uint8_t ADAPT_FIELD
Definition: ts.h:42
static constexpr uint8_t PAY_START
Definition: ts.h:35