00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdlib.h>
00032 #include <getopt.h>
00033 #include <stdarg.h>
00034 #include <stdio.h>
00035 #include <stdint.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 #include <string.h>
00040 #include <unistd.h>
00041
00042 #include "replex.h"
00043 #include "pes.h"
00044
00045 #ifndef O_LARGEFILE
00046 #define O_LARGEFILE 0
00047 #endif
00048
00049 #include "libavcodec/avcodec.h"
00050 #include "libavformat/avformat.h"
00051
00052 #ifdef USING_MINGW
00053 # define S_IRGRP 0
00054 # define S_IWGRP 0
00055 # define S_IROTH 0
00056 # define S_IWOTH 0
00057 #endif
00058
00059 #ifndef O_LARGEFILE
00060 #define O_LARGEFILE 0
00061 #endif
00062
00063 #include "mythlogging.h"
00064
00065 static int replex_all_set(struct replex *rx);
00066
00067 static int replex_check_id(struct replex *rx, uint16_t id)
00068 {
00069 int i;
00070
00071 if (id==rx->vpid)
00072 return 0;
00073
00074 for (i=0; i<rx->apidn; i++)
00075 if (id==rx->apid[i])
00076 return i+1;
00077
00078 for (i=0; i<rx->ac3n; i++)
00079 if (id==rx->ac3_id[i])
00080 return i+0x80;
00081
00082 return -1;
00083 }
00084
00085 static int encode_mp2_audio(audio_frame_t *aframe, uint8_t *buffer, int bufsize)
00086 {
00087 AVCodec *codec;
00088 AVCodecContext *c= NULL;
00089 int frame_size, j, out_size;
00090 short *samples;
00091
00092 LOG(VB_GENERAL, LOG_INFO, "encoding an MP2 audio frame");
00093
00094
00095 codec = avcodec_find_encoder(CODEC_ID_MP2);
00096 if (!codec) {
00097 LOG(VB_GENERAL, LOG_ERR, "codec not found");
00098 return 1;
00099 }
00100
00101 c = avcodec_alloc_context();
00102
00103
00104 c->bit_rate = aframe->bit_rate;
00105 c->sample_rate = aframe->frequency;
00106 c->channels = 2;
00107 c->sample_fmt = AV_SAMPLE_FMT_S16;
00108
00109
00110 if (avcodec_open(c, codec) < 0) {
00111 LOG(VB_GENERAL, LOG_ERR, "could not open codec");
00112 av_free(c);
00113 return 1;
00114 }
00115
00116
00117 frame_size = c->frame_size;
00118 samples = malloc(frame_size * 2 * c->channels);
00119
00120
00121 for (j=0;j<frame_size;j++) {
00122 samples[2*j] = 0;
00123 samples[2*j+1] = 0;
00124 }
00125
00126
00127 out_size = avcodec_encode_audio(c, buffer, bufsize, samples);
00128
00129 if (out_size != bufsize) {
00130 LOG(VB_GENERAL, LOG_ERR,
00131 "frame size (%d) does not equal required size (%d)?",
00132 out_size, bufsize);
00133 free(samples);
00134 avcodec_close(c);
00135 av_free(c);
00136 return 1;
00137 }
00138
00139 free(samples);
00140 avcodec_close(c);
00141 av_free(c);
00142
00143 return 0;
00144 }
00145
00146 static void analyze_audio( pes_in_t *p, struct replex *rx, int len, int num, int type)
00147 {
00148 int c=0;
00149 int pos=0;
00150 audio_frame_t *aframe = NULL;
00151 index_unit *iu = NULL;
00152 ringbuffer *rbuf = NULL, *index_buf = NULL;
00153 uint64_t *acount=NULL;
00154 uint64_t *fpts=NULL;
00155 uint64_t *lpts=NULL;
00156 int bsize = 0;
00157 int first = 1;
00158 uint8_t buf[7];
00159 int off=0;
00160 int *apes_abort=NULL;
00161 int re=0;
00162
00163 switch ( type ){
00164 case AC3:
00165 #ifdef IN_DEBUG
00166 LOG(VB_GENERAL, LOG_DEBUG, "AC3");
00167 #endif
00168 aframe = &rx->ac3frame[num];
00169 iu = &rx->current_ac3index[num];
00170 rbuf = &rx->ac3rbuffer[num];
00171 index_buf = &rx->index_ac3rbuffer[num];
00172 acount = &rx->ac3frame_count[num];
00173 fpts = &rx->first_ac3pts[num];
00174 lpts = &rx->last_ac3pts[num];
00175 bsize = rx->ac3buf;
00176 apes_abort = &rx->ac3pes_abort[num];
00177 break;
00178
00179 case MPEG_AUDIO:
00180 #ifdef IN_DEBUG
00181 LOG(VB_GENERAL, LOG_DEBUG, "MPEG AUDIO");
00182 #endif
00183 aframe = &rx->aframe[num];
00184 iu = &rx->current_aindex[num];
00185 rbuf = &rx->arbuffer[num];
00186 index_buf = &rx->index_arbuffer[num];
00187 acount = &rx->aframe_count[num];
00188 fpts = &rx->first_apts[num];
00189 lpts = &rx->last_apts[num];
00190 bsize = rx->audiobuf;
00191 apes_abort = &rx->apes_abort[num];
00192 break;
00193 }
00194
00195 *apes_abort = 0;
00196 off = ring_rdiff(rbuf, p->ini_pos);
00197 while (c < len){
00198 if ( (pos = find_audio_sync(rbuf, buf, c+off, type, len-c) )
00199 >= 0 ){
00200 if (!aframe->set){
00201 switch( type ){
00202 case AC3:
00203 re = get_ac3_info(rbuf, aframe,
00204 pos+c+off,
00205 len-c-pos);
00206 break;
00207 case MPEG_AUDIO:
00208 re = get_audio_info(rbuf, aframe,
00209 pos+c+off,
00210 len-c-pos);
00211 break;
00212 }
00213 if ( re == -2){
00214 *apes_abort = len -c;
00215 return;
00216 }
00217 if (re < 0) return;
00218
00219
00220 if (!rx->ignore_pts){
00221 if ((p->flag2 & PTS_ONLY)){
00222 *fpts = trans_pts_dts(p->pts);
00223 LOG(VB_GENERAL, LOG_INFO,
00224 "starting audio PTS: ");
00225 printpts(*fpts);
00226 } else aframe->set = 0;
00227 }
00228
00229 if (aframe->set && first)
00230 ring_skip(rbuf,pos+c);
00231
00232 } else {
00233 int diff = ring_posdiff(rbuf, iu->start,
00234 p->ini_pos + pos+c);
00235
00236 if ( (re = check_audio_header(rbuf, aframe,
00237 pos+c+off,len-c-pos,
00238 type)) < 0){
00239
00240 if ( re == -2){
00241 *apes_abort = len -c;
00242 return;
00243 }
00244
00245 if ((int) aframe->framesize > diff){
00246 if ( re == -3){
00247 c += pos+1;
00248 continue;
00249 }
00250
00251 c += pos+2;
00252 #ifdef IN_DEBUG
00253 LOG(VB_GENERAL, LOG_DEBUG,"
00254 WRONG HEADER1 %d", diff);
00255 #endif
00256 continue;
00257 }
00258 }
00259 if ((int) aframe->framesize > diff){
00260 c += pos+2;
00261 #if 0
00262 LOG(VB_GENERAL, LOG_ERR,
00263 "WRONG HEADER2 %d", diff);
00264 #endif
00265 continue;
00266 }
00267 }
00268
00269
00270 if (aframe->set && rx->fix_sync && first && type == MPEG_AUDIO){
00271 int frame_time = aframe->frametime;
00272 int64_t diff;
00273 diff = ptsdiff(trans_pts_dts(p->pts), add_pts_audio(0, aframe,*acount + 1) + *fpts);
00274 if (abs ((int)diff) >= frame_time){
00275 LOG(VB_GENERAL, LOG_INFO,
00276 "fixing audio PTS inconsistency - diff: ");
00277 printpts(abs(diff));
00278
00279 if (diff < 0){
00280 diff = abs(diff);
00281 int framesdiff = diff / frame_time;
00282 LOG(VB_GENERAL, LOG_INFO,
00283 " - need to remove %d frame(s)",
00284 framesdiff);
00285
00286
00287 if (framesdiff > 1)
00288 framesdiff = 1;
00289 iu->pts = add_pts_audio(0, aframe, -framesdiff);
00290 c += aframe->framesize;
00291 continue;
00292 } else {
00293 int framesdiff = diff / frame_time;
00294 LOG(VB_GENERAL, LOG_INFO,
00295 " - need to add %d frame(s)",
00296 framesdiff);
00297
00298
00299 if (framesdiff > 5)
00300 framesdiff = 5;
00301
00302
00303 uint8_t *framebuf;
00304 if ( !(framebuf = (uint8_t *) malloc(sizeof(uint8_t) * aframe->framesize))) {
00305 LOG(VB_GENERAL, LOG_ERR,
00306 "Not enough memory for audio frame");
00307 exit(1);
00308 }
00309
00310
00311 if (encode_mp2_audio(aframe, framebuf, sizeof(uint8_t) * aframe->framesize) != 0) {
00312
00313 int res;
00314 res = ring_peek(rbuf, framebuf, aframe->framesize, 0);
00315 if (res != (int) aframe->framesize) {
00316 LOG(VB_GENERAL, LOG_ERR,
00317 "ring buffer failed to peek frame res: %d",
00318 res);
00319 exit(1);
00320 }
00321 }
00322
00323
00324 int x;
00325 for (x = 0; x < framesdiff; x++){
00326 if (type == AC3){
00327 if (rx->dmx_out[num+1+rx->apidn])
00328 write(rx->dmx_out[num+1+rx->apidn], framebuf, aframe->framesize);
00329 }else{
00330 if (rx->dmx_out[num+1])
00331 write(rx->dmx_out[num+1], framebuf, aframe->framesize);
00332 }
00333 *acount += 1;
00334 }
00335
00336 free(framebuf);
00337 }
00338 }
00339 }
00340
00341 if (aframe->set){
00342 if(iu->active){
00343 iu->length = ring_posdiff(rbuf,
00344 iu->start,
00345 p->ini_pos +
00346 pos+c);
00347
00348 if (iu->length < aframe->framesize ||
00349 iu->length > aframe->framesize+1){
00350 LOG(VB_GENERAL, LOG_ERR,
00351 "Wrong audio frame size: %d",
00352 iu->length);
00353 iu->err= FRAME_ERR;
00354 }
00355 if (ring_write(index_buf,
00356 (uint8_t *)iu,
00357 sizeof(index_unit)) < 0){
00358 LOG(VB_GENERAL, LOG_ERR,
00359 "audio ring buffer overrun error");
00360 exit(1);
00361 }
00362 *acount += 1;
00363 }
00364
00365 init_index(iu);
00366 iu->active = 1;
00367 iu->pts = add_pts_audio(0, aframe,*acount);
00368 iu->framesize = aframe->framesize;
00369
00370 if (!rx->ignore_pts &&
00371 first && (p->flag2 & PTS_ONLY)){
00372 int64_t diff;
00373
00374 diff = ptsdiff(trans_pts_dts(p->pts),
00375 iu->pts + *fpts);
00376 if( !rx->keep_pts && abs ((int)diff) > 40*CLOCK_MS){
00377 LOG(VB_GENERAL, LOG_ERR,
00378 "audio PTS inconsistent:");
00379 printpts(trans_pts_dts(p->pts)-*fpts);
00380 printpts(iu->pts);
00381 LOG(VB_GENERAL, LOG_ERR,
00382 "diff: ");
00383 printpts(abs(diff));
00384 }
00385 if (rx->keep_pts){
00386 fix_audio_count(acount, aframe,
00387 uptsdiff(trans_pts_dts(
00388 p->pts),
00389 *fpts),
00390 iu->pts);
00391 iu->pts = uptsdiff(trans_pts_dts(p->pts),
00392 *fpts);
00393 if (*lpts && ptsdiff(iu->pts,*lpts)<0)
00394 LOG(VB_GENERAL, LOG_WARNING,
00395 "Warning negative audio PTS increase!\n");
00396 *lpts = iu->pts;
00397 }
00398 first = 0;
00399 }
00400 if (rx->analyze >1){
00401 if ((p->flag2 & PTS_ONLY)){
00402 iu->pts = trans_pts_dts(p->pts);
00403 } else {
00404 iu->pts = 0;
00405 }
00406 }
00407 iu->start = (p->ini_pos+pos+c)%bsize;
00408 }
00409 c += pos;
00410 if (c + (int) aframe->framesize > len){
00411 #if 0
00412 LOG(VB_GENERAL, LOG_INFO, "SHORT %d", len -c);
00413 #endif
00414 c = len;
00415 } else {
00416 c += aframe->framesize;
00417 }
00418 } else {
00419 *apes_abort = len-c;
00420 c=len;
00421 }
00422 }
00423 }
00424
00425 static void analyze_video( pes_in_t *p, struct replex *rx, int len)
00426 {
00427 uint8_t buf[8];
00428 int c=0;
00429 int pos=0;
00430 uint8_t head;
00431 int seq_end = 0;
00432 uint8_t frame = 0;
00433 uint64_t newpts = 0;
00434 uint64_t newdts = 0;
00435 index_unit *iu;
00436 int off=0;
00437 ringbuffer *rbuf;
00438 ringbuffer *index_buf;
00439 sequence_t *s;
00440 int i;
00441
00442 uint16_t tempref = 0;
00443 int seq_h = 0;
00444 int gop = 0;
00445 int frame_off = 0;
00446 int gop_off = 0;
00447 int seq_p = 0;
00448 int flush=0;
00449
00450 rbuf = &rx->vrbuffer;
00451 index_buf = &rx->index_vrbuffer;
00452 iu = &rx->current_vindex;
00453 s = &rx->seq_head;
00454
00455 rx->vpes_abort = 0;
00456 off = ring_rdiff(rbuf, p->ini_pos);
00457 #ifdef IN_DEBUG
00458 LOG(VB_GENERAL, LOG_DEBUG, " ini pos %d", (p->ini_pos)%rx->videobuf);
00459 #endif
00460
00461
00462 #if 0
00463 LOG(VB_GENERAL, LOG_INFO, "len %d %d",len,off);
00464 #endif
00465 while (c < len){
00466 if ((pos = ring_find_any_header( rbuf, &head, c+off, len-c))
00467 >=0 ){
00468 switch(head){
00469 case SEQUENCE_HDR_CODE:
00470 #ifdef IN_DEBUG
00471 LOG(VB_GENERAL, LOG_DEBUG, " seq headr %d",
00472 (p->ini_pos+c+pos)%rx->videobuf);
00473 #endif
00474
00475 seq_h = 1;
00476 seq_p = c+pos;
00477
00478
00479 if (!s->set){
00480 int re=0;
00481 re = get_video_info(rbuf, &rx->seq_head,
00482 pos+c+off, len -c -pos);
00483
00484 #ifdef IN_DEBUG
00485 LOG(VB_GENERAL, LOG_DEBUG,
00486 " seq headr result %d", re);
00487 #endif
00488 if (re == -2){
00489 rx->vpes_abort = len -(c+pos-1);
00490 return;
00491 }
00492 if (s->set){
00493 ring_skip(rbuf, pos+c);
00494 off -= pos+c;
00495 }
00496 if (!rx->ignore_pts &&
00497 !(p->flag2 & PTS_ONLY)) s->set = 0;
00498 }
00499 if (s->set){
00500 flush = 1;
00501 }
00502 break;
00503
00504 case EXTENSION_START_CODE:{
00505 int ext_id = 0;
00506
00507 #ifdef IN_DEBUG
00508 LOG(VB_GENERAL, LOG_DEBUG, " seq ext headr %d",
00509 (p->ini_pos+c+pos)+rx->videobuf);
00510 #endif
00511 ext_id = get_video_ext_info(rbuf,
00512 &rx->seq_head,
00513 pos+c+off,
00514 len -c -pos);
00515 if (ext_id == -2){
00516 rx->vpes_abort = len - (pos-1+c);
00517 return;
00518 }
00519
00520
00521 if(ext_id == PICTURE_CODING_EXTENSION
00522 && s->ext_set && iu->active){
00523 if (!rx->ignore_pts &&
00524 !rx->vframe_count &&
00525 !rx->first_vpts){
00526 rx->first_vpts = trans_pts_dts(
00527 p->pts);
00528
00529 for (i = 0; i< s->current_tmpref;
00530 i++) ptsdec(&rx->first_vpts,
00531 SEC_PER);
00532 LOG(VB_GENERAL, LOG_INFO,
00533 "starting with video PTS:");
00534 printpts(rx->first_vpts);
00535 }
00536
00537 newpts = 0;
00538 #ifdef IN_DEBUG
00539
00540 LOG(VB_GENERAL, LOG_DEBUG,
00541 "fcount %d gcount %d tempref %d %d",
00542 (int)rx->vframe_count, (int)rx->vgroup_count,
00543 (int)s->current_tmpref,
00544 (int)(s->current_tmpref - rx->vgroup_count
00545 + rx->vframe_count));
00546 #endif
00547 newdts = next_ptsdts_video(
00548 &newpts,s, rx->vframe_count,
00549 rx->vgroup_count);
00550
00551 if (!rx->ignore_pts &&
00552 (p->flag2 & PTS_ONLY)){
00553 int64_t diff;
00554
00555 diff = ptsdiff(iu->pts,
00556 rx->first_vpts
00557 + newpts);
00558
00559 if (!rx->keep_pts &&
00560 abs((int)(diff)) > 3*SEC_PER/2){
00561 LOG(VB_GENERAL, LOG_INFO,
00562 "video PTS inconsistent:");
00563 printpts(trans_pts_dts(p->pts));
00564 printpts(iu->pts);
00565 printpts(newpts+rx->first_vpts);
00566 printpts(newpts);
00567 LOG(VB_GENERAL, LOG_INFO,
00568 " diff: ");
00569 printpts(abs((int)diff));
00570 }
00571 }
00572
00573 if (!rx->ignore_pts &&
00574 (p->flag2 & PTS_DTS) == PTS_DTS){
00575 uint64_t diff;
00576 diff = ptsdiff(iu->dts,
00577 newdts +
00578 rx->first_vpts);
00579 if (!rx->keep_pts &&
00580 abs((int)diff) > 3*SEC_PER/2){
00581 LOG(VB_GENERAL, LOG_INFO,
00582 "video DTS inconsistent: ");
00583 printpts(trans_pts_dts(p->dts));
00584 printpts(iu->dts);
00585 printpts(newdts+rx->first_vpts);
00586 printpts(newdts);
00587 LOG(VB_GENERAL, LOG_INFO,
00588 "diff: ");
00589 printpts(abs((int)diff));
00590 }
00591 }
00592 if (!rx->keep_pts){
00593 iu->pts = newpts;
00594 iu->dts = newdts;
00595 } else {
00596 if (p->flag2 & PTS_DTS){
00597 ptsdec(&iu->pts,
00598 rx->first_vpts);
00599
00600 if ((p->flag2 & PTS_DTS) == PTS_DTS){
00601 ptsdec(&iu->dts,
00602 rx->first_vpts);
00603 } else iu->dts = newdts;
00604
00605 fix_video_count(s,&rx->vframe_count,
00606 iu->pts,newpts,
00607 iu->dts,newdts);
00608
00609 } else {
00610 iu->pts = newpts;
00611 iu->dts = newdts;
00612 }
00613 }
00614 if (rx->last_vpts &&
00615 ptsdiff(iu->dts, rx->last_vpts) <0)
00616 LOG(VB_GENERAL, LOG_WARNING,
00617 "Warning negative video PTS increase!");
00618 rx->last_vpts = iu->dts;
00619 }
00620
00621 if (rx->analyze){
00622 if ((p->flag2 & PTS_DTS) == PTS_DTS){
00623 iu->pts = trans_pts_dts(p->pts);
00624 iu->dts = trans_pts_dts(p->dts);
00625 } else if (p->flag2 & PTS_ONLY){
00626 iu->pts = trans_pts_dts(p->pts);
00627 iu->dts = 0;
00628 } else {
00629 iu->pts = 0;
00630 iu->dts = 0;
00631 }
00632 }
00633
00634
00635 break;
00636 }
00637
00638 case SEQUENCE_END_CODE:
00639 #ifdef IN_DEBUG
00640 LOG(VB_GENERAL, LOG_DEBUG, " seq end %d",
00641 (p->ini_pos+c+pos)%rx->videobuf);
00642 #endif
00643 if (s->set)
00644 seq_end = 1;
00645
00646 break;
00647
00648 case GROUP_START_CODE:{
00649 int hour, min, sec;
00650
00651 #ifdef ANA
00652 LOG(VB_GENERAL, LOG_DEBUG, " %d",
00653 (int)rx->vgroup_count);
00654 #endif
00655
00656 if (s->set){
00657 if (!seq_h) flush = 1;
00658 }
00659 gop = 1;
00660 gop_off = c+pos - seq_p;
00661
00662 if (ring_peek(rbuf, (uint8_t *) buf, 7,
00663 off+c+pos) < 0){
00664 rx->vpes_abort = len -(c+pos-1);
00665 return;
00666 }
00667 hour = (int)((buf[4]>>2)& 0x1F);
00668 min = (int)(((buf[4]<<4)& 0x30)|
00669 ((buf[5]>>4)& 0x0F));
00670 sec = (int)(((buf[5]<<3)& 0x38)|
00671 ((buf[6]>>5)& 0x07));
00672 #ifdef IN_DEBUG
00673 LOG(VB_GENERAL, LOG_DEBUG,
00674 " gop %02d:%02d.%02d %d",
00675 hour,min,sec,
00676 (p->ini_pos+c+pos)%rx->videobuf);
00677 #endif
00678 rx->vgroup_count = 0;
00679
00680 break;
00681 }
00682
00683 case PICTURE_START_CODE:{
00684 if (len-(c+pos) < 14){
00685 rx->vpes_abort = len - (pos-1+c);
00686 return;
00687 }
00688
00689 if (ring_peek(rbuf, (uint8_t *) buf, 6,
00690 off+c+pos) < 0) return;
00691
00692
00693 frame = ((buf[5]&0x38) >>3);
00694
00695 if (frame == I_FRAME){
00696 if( !rx->first_iframe){
00697 if (s->set){
00698 rx->first_iframe = 1;
00699 } else {
00700 s->set=0;
00701 flush = 0;
00702 break;
00703 }
00704 }
00705 }
00706
00707 frame_off = c+pos - seq_p;
00708 if (s->set){
00709 if (!seq_h && !gop) flush = 1;
00710 }
00711 tempref = (buf[5]>>6) & 0x03;
00712 tempref |= buf[4] << 2;
00713
00714 switch (frame){
00715 case I_FRAME:
00716 #ifdef ANA
00717 LOG(VB_GENERAL, LOG_DEBUG, "I");
00718 #endif
00719 #ifdef IN_DEBUG
00720 LOG(VB_GENERAL, LOG_DEBUG,
00721 " I-frame %d",
00722 (p->ini_pos+c+pos)%rx->videobuf);
00723 #endif
00724 break;
00725 case B_FRAME:
00726 #ifdef ANA
00727 LOG(VB_GENERAL, LOG_DEBUG, "B");
00728 #endif
00729 #ifdef IN_DEBUG
00730 LOG(VB_GENERAL, LOG_DEBUG,
00731 " B-frame %d",
00732 (p->ini_pos+c+pos)%rx->videobuf);
00733 #endif
00734 break;
00735 case P_FRAME:
00736 #ifdef ANA
00737 LOG(VB_GENERAL, LOG_DEBUG, "P");
00738 #endif
00739 #ifdef IN_DEBUG
00740 LOG(VB_GENERAL, LOG_DEBUG,
00741 " P-frame %d",
00742 (p->ini_pos+c+pos)%rx->videobuf);
00743 #endif
00744 break;
00745 }
00746 s->current_frame = frame;
00747 s->current_tmpref = tempref;
00748
00749 break;
00750 }
00751 default:
00752 #ifdef IN_DEBUG
00753 #if 0
00754 LOG(VB_GENERAL, LOG_ERR,
00755 "other header 0x%02x (%d+%d)", head, c, pos);
00756 #endif
00757 #endif
00758 break;
00759 }
00760
00761 if (flush && s->set && rx->first_iframe){
00762 if(iu->active){
00763 rx->vframe_count++;
00764 rx->vgroup_count++;
00765
00766 iu->length = ring_posdiff(rbuf,
00767 iu->start,
00768 p->ini_pos+
00769 pos+c-frame_off);
00770
00771 if ( ring_write(index_buf, (uint8_t *)
00772 &rx->current_vindex,
00773 sizeof(index_unit))<0){
00774 LOG(VB_GENERAL, LOG_ERR,
00775 "video ring buffer overrun error");
00776 exit(1);
00777
00778 }
00779 }
00780 init_index(&rx->current_vindex);
00781 flush = 0;
00782 iu->active = 1;
00783 if (!rx->ignore_pts){
00784 if ((p->flag2 & PTS_DTS) == PTS_DTS){
00785 iu->pts = trans_pts_dts(p->pts);
00786 iu->dts = trans_pts_dts(p->dts);
00787 } else if (p->flag2 & PTS_ONLY){
00788 iu->pts = trans_pts_dts(p->pts);
00789 }
00790 }
00791 iu->start = (p->ini_pos+pos+c-frame_off)
00792 %rx->videobuf;
00793 #ifdef IN_DEBUG
00794 LOG(VB_GENERAL, LOG_DEBUG, "START %d",
00795 iu->start);
00796 #endif
00797 }
00798
00799 if (s->set){
00800 if (frame)
00801 iu->frame = (frame&0xFF);
00802 if (seq_h)
00803 iu->seq_header = 1;
00804 if (seq_end)
00805 iu->seq_end = 1;
00806 if (gop)
00807 iu->gop = 1;
00808 if (gop_off)
00809 iu->gop_off = gop_off;
00810 if (frame_off)
00811 iu->frame_off = frame_off;
00812 }
00813 c+=pos+4;
00814 } else {
00815 if (pos == -2){
00816 rx->vpes_abort = 4;
00817
00818 }
00819 c = len;
00820 }
00821 }
00822 }
00823
00824 static void es_out(pes_in_t *p)
00825 {
00826
00827 struct replex *rx;
00828 char t[80];
00829 int len;
00830
00831 len = p->plength-3-p->hlength;
00832
00833 rx = (struct replex *) p->priv;
00834
00835 switch(p->type)
00836 {
00837 case 0xE0: {
00838 sprintf(t, "Video ");
00839 if (rx->vpes_abort){
00840 p->ini_pos = (p->ini_pos - rx->vpes_abort)%rx->vrbuffer.size;
00841 len += rx->vpes_abort;
00842 }
00843 analyze_video(p, rx, len);
00844 if (!rx->seq_head.set){
00845 ring_skip(&rx->vrbuffer, len);
00846 }
00847 break;
00848 }
00849
00850 case 1 ... 32:{
00851 int l;
00852 l = p->type - 1;
00853 sprintf(t, "Audio%d ", l);
00854 if (rx->apes_abort[l]){
00855 p->ini_pos = (p->ini_pos - rx->apes_abort[l])
00856 %rx->arbuffer[l].size;
00857 len += rx->apes_abort[l];
00858 }
00859 analyze_audio(p, rx, len, l, MPEG_AUDIO);
00860 if (!rx->aframe[l].set)
00861 ring_skip(&rx->arbuffer[l], len);
00862
00863 break;
00864 }
00865
00866 case 0x80 ... 0x87:{
00867 int l;
00868 l = p->type - 0x80;
00869 sprintf(t, "AC3 %d ", p->type);
00870 if (rx->ac3pes_abort[l]){
00871 p->ini_pos = (p->ini_pos - rx->ac3pes_abort[l])
00872 %rx->ac3rbuffer[l].size;
00873 len += rx->ac3pes_abort[l];
00874 }
00875 analyze_audio(p, rx, len, l, AC3);
00876 if (!rx->ac3frame[l].set)
00877 ring_skip(&rx->ac3rbuffer[l], len);
00878 break;
00879 }
00880
00881 default:
00882 LOG(VB_GENERAL, LOG_ERR, "UNKNOWN AUDIO type %d", p->type);
00883 return;
00884
00885
00886 }
00887
00888 #ifdef IN_DEBUG
00889 LOG(VB_GENERAL, LOG_DEBUG, "%s PES", t);
00890 #endif
00891 }
00892
00893 static void pes_es_out(pes_in_t *p)
00894 {
00895
00896 struct replex *rx;
00897 char t[80];
00898 int len, i;
00899 int l=0;
00900
00901 len = p->plength-3-p->hlength;
00902 rx = (struct replex *) p->priv;
00903
00904 switch(p->cid){
00905 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
00906 if (rx->vpid != p->cid) break;
00907 p->type = 0xE0;
00908 p->ini_pos = ring_wpos(&rx->vrbuffer);
00909
00910 if (ring_write(&rx->vrbuffer, p->buf+9+p->hlength, len)<0){
00911 LOG(VB_GENERAL, LOG_ERR,
00912 "video ring buffer overrun error");
00913 exit(1);
00914 }
00915 if (rx->vpes_abort){
00916 p->ini_pos = (p->ini_pos - rx->vpes_abort)%rx->vrbuffer.size;
00917 len += rx->vpes_abort;
00918 }
00919 sprintf(t, "Video ");
00920 analyze_video(p, rx, len);
00921 if (!rx->seq_head.set){
00922 ring_skip(&rx->vrbuffer, len);
00923 }
00924 break;
00925
00926 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
00927 p->type = p->cid - 0xc0 + 1;
00928 l = -1;
00929 for (i=0; i<rx->apidn; i++)
00930 if (p->cid == rx->apid[i])
00931 l = i;
00932 if (l < 0) break;
00933 p->ini_pos = ring_wpos(&rx->arbuffer[l]);
00934 if (ring_write(&rx->arbuffer[l], p->buf+9+p->hlength, len)<0){
00935 LOG(VB_GENERAL, LOG_ERR,
00936 "video ring buffer overrun error");
00937 exit(1);
00938 }
00939 if (rx->apes_abort[l]){
00940 p->ini_pos = (p->ini_pos - rx->apes_abort[l])
00941 %rx->arbuffer[l].size;
00942 len += rx->apes_abort[l];
00943 }
00944
00945 sprintf(t, "Audio%d ", l);
00946 analyze_audio(p, rx, len, l, MPEG_AUDIO);
00947 if (!rx->aframe[l].set)
00948 ring_skip(&rx->arbuffer[l], len);
00949
00950 break;
00951
00952 case PRIVATE_STREAM1:{
00953 int hl=4;
00954 if (rx->vdr){
00955 hl=0;
00956 p->type=0x80;
00957 l = 0;
00958 } else {
00959 uint16_t fframe;
00960
00961 fframe=0;
00962 fframe = p->buf[9+p->hlength+3];
00963 fframe |= (p->buf[9+p->hlength+2]<<8);
00964
00965 if (fframe > p->plength) break;
00966
00967 p->type = p->buf[9+p->hlength];
00968 l = -1;
00969 for (i=0; i<rx->ac3n; i++)
00970 if (p->type == rx->ac3_id[i])
00971 l = i;
00972 if (l < 0) break;
00973 }
00974 len -= hl;
00975 p->ini_pos = ring_wpos(&rx->ac3rbuffer[l]);
00976
00977 if (ring_write(&rx->ac3rbuffer[l], p->buf+9+hl+p->hlength, len)<0){
00978 LOG(VB_GENERAL, LOG_ERR,
00979 "video ring buffer overrun error");
00980 exit(1);
00981 }
00982 if (rx->ac3pes_abort[l]){
00983 p->ini_pos = (p->ini_pos - rx->ac3pes_abort[l])
00984 %rx->ac3rbuffer[l].size;
00985 len += rx->ac3pes_abort[l];
00986 }
00987
00988 sprintf(t, "AC3 %d ", p->type);
00989 analyze_audio(p, rx, len, l, AC3);
00990 sprintf(t,"%d",rx->ac3frame[l].set);
00991 if (!rx->ac3frame[l].set)
00992 ring_skip(&rx->ac3rbuffer[l], len);
00993 }
00994 break;
00995
00996 default:
00997 return;
00998 }
00999
01000 #ifdef IN_DEBUG
01001 LOG(VB_GENERAL, LOG_DEBUG, "%s PES %d", t, len);
01002 #endif
01003 }
01004
01005 static void avi_es_out(pes_in_t *p)
01006 {
01007
01008 struct replex *rx;
01009 char t[80];
01010 int len;
01011
01012 len = p->plength;
01013
01014 rx = (struct replex *) p->priv;
01015
01016
01017 switch(p->type)
01018 {
01019 case 0xE0: {
01020 sprintf(t, "Video ");
01021 if (!len){
01022 rx->vframe_count++;
01023 break;
01024 }
01025 analyze_video(p, rx, len);
01026 if (!rx->seq_head.set){
01027 ring_skip(&rx->vrbuffer, len);
01028 }
01029 break;
01030 }
01031
01032 case 1 ... 32:{
01033 int l;
01034 l = p->type - 1;
01035 sprintf(t, "Audio%d ", l);
01036 if (!len){
01037 rx->aframe_count[l]++;
01038 break;
01039 }
01040 analyze_audio(p, rx, len, l, MPEG_AUDIO);
01041 if (!rx->aframe[l].set)
01042 ring_skip(&rx->arbuffer[l], len);
01043
01044 break;
01045 }
01046
01047 case 0x80 ... 0x87:{
01048 int l;
01049
01050 l = p->type - 0x80;
01051 sprintf(t, "AC3 %d ", p->type);
01052 if (!len){
01053 rx->ac3frame_count[l]++;
01054 break;
01055 }
01056 analyze_audio(p, rx, len, l, AC3);
01057 if (!rx->ac3frame[l].set)
01058 ring_skip(&rx->ac3rbuffer[l], len);
01059 break;
01060 }
01061
01062 default:
01063 return;
01064
01065
01066 }
01067 #ifdef IN_DEBUG
01068 LOG(VB_GENERAL, LOG_DEBUG, "%s PES", t);
01069 #endif
01070
01071 }
01072
01073
01074 static int replex_tsp(struct replex *rx, uint8_t *tsp)
01075 {
01076 uint16_t pid;
01077 int type;
01078 int off=0;
01079 pes_in_t *p=NULL;
01080
01081 pid = get_pid(tsp+1);
01082
01083 if ((type=replex_check_id(rx, pid))<0)
01084 return 0;
01085
01086 switch(type){
01087 case 0:
01088 p = &rx->pvideo;
01089 break;
01090
01091 case 1 ... 32:
01092 p = &rx->paudio[type-1];
01093 break;
01094
01095 case 0x80 ... 0x87:
01096 p = &rx->pac3[type-0x80];
01097 break;
01098 default:
01099 return 0;
01100
01101 }
01102
01103
01104 if ( tsp[1] & PAY_START) {
01105 if (p->plength == MMAX_PLENGTH-6){
01106 p->plength = p->found-6;
01107 es_out(p);
01108 init_pes_in(p, p->type, NULL, 0);
01109 }
01110 }
01111
01112 if ( tsp[3] & ADAPT_FIELD) {
01113 off = tsp[4] + 1;
01114 if (off+4 >= TS_SIZE) return 0;
01115 }
01116
01117 get_pes(p, tsp+4+off, TS_SIZE-4-off, es_out);
01118
01119 return 0;
01120 }
01121
01122
01123 static ssize_t save_read(struct replex *rx, void *buf, size_t count)
01124 {
01125 ssize_t neof = 1;
01126 size_t re = 0;
01127 int fd = rx->fd_in;
01128
01129 if (rx->itype== REPLEX_AVI){
01130 int l = rx->inflength - rx->finread;
01131 if ( l <= 0) return 0;
01132 if ( (int) count > l) count = l;
01133 }
01134 while(neof >= 0 && re < count){
01135 neof = read(fd, ((char*)buf)+re, count - re);
01136 if (neof > 0) re += neof;
01137 else break;
01138 }
01139 rx->finread += re;
01140 #ifndef OUT_DEBUG
01141 if (rx->inflength){
01142 uint8_t per=0;
01143
01144 per = (uint8_t)(rx->finread*100/rx->inflength);
01145 if (per % 10 == 0 && rx->lastper < per){
01146 LOG(VB_GENERAL, LOG_DEBUG, "read %3d%%", (int)per);
01147 rx->lastper = per;
01148 }
01149 } else
01150 LOG(VB_GENERAL, LOG_DEBUG, "read %.2f MB",
01151 rx->finread/1024.0/1024.0);
01152 #endif
01153 if (neof < 0 && re == 0) return neof;
01154 else return re;
01155 }
01156
01157 static int guess_fill( struct replex *rx)
01158 {
01159 int vavail, aavail, ac3avail, i, fill;
01160
01161 vavail = 0;
01162 ac3avail =0;
01163 aavail = 0;
01164 fill =0;
01165
01166 #define LIMIT 3
01167 if ((vavail = ring_avail(&rx->index_vrbuffer)/sizeof(index_unit))
01168 < LIMIT)
01169 fill = ring_free(&rx->vrbuffer);
01170
01171 for (i=0; i<rx->apidn;i++){
01172 if ((aavail = ring_avail(&rx->index_arbuffer[i])
01173 /sizeof(index_unit)) < LIMIT)
01174 if (fill < (int) ring_free(&rx->arbuffer[i]))
01175 fill = ring_free(&rx->arbuffer[i]);
01176 }
01177
01178 for (i=0; i<rx->ac3n;i++){
01179 if ((ac3avail = ring_avail(&rx->index_ac3rbuffer[i])
01180 /sizeof(index_unit)) < LIMIT)
01181 if (fill < (int) ring_free(&rx->ac3rbuffer[i]))
01182 fill = ring_free(&rx->ac3rbuffer[i]);
01183 }
01184
01185 #if 0
01186 LOG(VB_GENERAL, LOG_INFO, "free %d %d %d %d", fill, vavail, aavail,
01187 ac3avail);
01188 #endif
01189
01190 if (!fill){
01191 if(vavail && (aavail || ac3avail)) return 0;
01192 else return -1;
01193 }
01194
01195 return fill/2;
01196 }
01197
01198
01199
01200 #define IN_SIZE (1000*TS_SIZE)
01201 static void find_pids_file(struct replex *rx)
01202 {
01203 uint8_t buf[IN_SIZE];
01204 int afound=0;
01205 int vfound=0;
01206 int count=0;
01207 int re=0;
01208 uint16_t vpid=0, apid=0, ac3pid=0;
01209
01210 LOG(VB_GENERAL, LOG_INFO, "Trying to find PIDs");
01211 while (!afound && !vfound && count < (int) rx->inflength){
01212 if (rx->vpid) vfound = 1;
01213 if (rx->apidn) afound = 1;
01214 if ((re = save_read(rx,buf,IN_SIZE))<0)
01215 LOG(VB_GENERAL, LOG_ERR, "reading: %s",
01216 strerror(errno));
01217 else
01218 count += re;
01219 if ( (re = find_pids(&vpid, &apid, &ac3pid, buf, re))){
01220 if (!rx->vpid && vpid){
01221 rx->vpid = vpid;
01222 LOG(VB_GENERAL, LOG_INFO,"vpid 0x%04x",
01223 (int)rx->vpid);
01224 vfound++;
01225 }
01226 if (!rx->apidn && apid){
01227 rx->apid[0] = apid;
01228 LOG(VB_GENERAL, LOG_INFO, "apid 0x%04x",
01229 (int)rx->apid[0]);
01230 rx->apidn++;
01231 afound++;
01232 }
01233 if (!rx->ac3n && ac3pid){
01234 rx->ac3_id[0] = ac3pid;
01235 LOG(VB_GENERAL, LOG_INFO, "ac3pid 0x%04x",
01236 (int)rx->ac3_id[0]);
01237 rx->ac3n++;
01238 afound++;
01239 }
01240
01241 }
01242
01243 }
01244
01245 lseek(rx->fd_in,0,SEEK_SET);
01246 if (!afound || !vfound){
01247 LOG(VB_GENERAL, LOG_ERR, "Couldn't find all pids");
01248 exit(1);
01249 }
01250
01251 }
01252
01253 #define MAXVPID 16
01254 #define MAXAPID 32
01255 #define MAXAC3PID 16
01256 static void find_all_pids_file(struct replex *rx)
01257 {
01258 uint8_t buf[IN_SIZE];
01259 int count=0;
01260 int j;
01261 int re=0;
01262 uint16_t vpid[MAXVPID], apid[MAXAPID], ac3pid[MAXAC3PID];
01263 int vn=0, an=0,ac3n=0;
01264 uint16_t vp,ap,cp;
01265 int vpos, apos, cpos;
01266
01267 memset (vpid , 0 , MAXVPID*sizeof(uint16_t));
01268 memset (apid , 0 , MAXAPID*sizeof(uint16_t));
01269 memset (ac3pid , 0 , MAXAC3PID*sizeof(uint16_t));
01270
01271 LOG(VB_GENERAL, LOG_INFO, "Trying to find PIDs");
01272 while (count < (int) rx->inflength-IN_SIZE){
01273 if ((re = save_read(rx,buf,IN_SIZE))<0)
01274 LOG(VB_GENERAL, LOG_ERR, "reading: %s",
01275 strerror(errno));
01276 else
01277 count += re;
01278 if ( (re = find_pids_pos(&vp, &ap, &cp, buf, re,
01279 &vpos, &apos, &cpos))){
01280 if (vp){
01281 int old=0;
01282 for (j=0; j < vn; j++){
01283 #if 0
01284 LOG(VB_GENERAL, LOG_INFO,
01285 "%d. %d", j+1, vpid[j]);
01286 #endif
01287 if (vpid[j] == vp){
01288 old = 1;
01289 break;
01290 }
01291 }
01292 if (!old){
01293 vpid[vn]=vp;
01294
01295 LOG(VB_GENERAL, LOG_INFO,
01296 "vpid %d: 0x%04x (%d) PES ID: 0x%02x",
01297 vn+1,
01298 (int)vpid[vn], (int)vpid[vn],
01299 buf[vpos]);
01300 if (vn+1 < MAXVPID) vn++;
01301 }
01302 }
01303
01304 if (ap){
01305 int old=0;
01306 for (j=0; j < an; j++)
01307 if (apid[j] == ap){
01308 old = 1;
01309 break;
01310 }
01311 if (!old){
01312 apid[an]=ap;
01313 LOG(VB_GENERAL, LOG_INFO,
01314 "apid %d: 0x%04x (%d) PES ID: 0x%02x",
01315 an +1,
01316 (int)apid[an],(int)apid[an],
01317 buf[apos]);
01318 if (an+1 < MAXAPID) an++;
01319 }
01320 }
01321
01322 if (cp){
01323 int old=0;
01324 for (j=0; j < ac3n; j++)
01325 if (ac3pid[j] == cp){
01326 old = 1;
01327 break;
01328 }
01329 if (!old){
01330 ac3pid[ac3n]=cp;
01331 LOG(VB_GENERAL, LOG_INFO,
01332 "ac3pid %d: 0x%04x (%d)",
01333 ac3n+1,
01334 (int)ac3pid[ac3n],
01335 (int)ac3pid[ac3n]);
01336 if (ac3n+1< MAXAC3PID) ac3n++;
01337 }
01338 }
01339 }
01340
01341 }
01342
01343 lseek(rx->fd_in,0,SEEK_SET);
01344 }
01345
01346 static void find_pids_stdin(struct replex *rx, uint8_t *buf, int len)
01347 {
01348 int afound=0;
01349 int vfound=0;
01350 uint16_t vpid=0, apid=0, ac3pid=0;
01351
01352 if (rx->vpid) vfound = 1;
01353 if (rx->apidn) afound = 1;
01354 LOG(VB_GENERAL, LOG_INFO, "Trying to find PIDs");
01355 if ( find_pids(&vpid, &apid, &ac3pid, buf, len) ){
01356 if (!rx->vpid && vpid){
01357 rx->vpid = vpid;
01358 vfound++;
01359 }
01360 if (!rx->apidn && apid){
01361 rx->apid[0] = apid;
01362 rx->apidn++;
01363 afound++;
01364 ring_init(&rx->arbuffer[0], rx->audiobuf);
01365 init_pes_in(&rx->paudio[0], 1, &rx->arbuffer[0], 0);
01366 rx->paudio[0].priv = (void *) rx;
01367 ring_init(&rx->index_arbuffer[0], INDEX_BUF);
01368 memset(&rx->aframe[0], 0, sizeof(audio_frame_t));
01369 init_index(&rx->current_aindex[0]);
01370 rx->aframe_count[0] = 0;
01371 rx->first_apts[0] = 0;
01372 }
01373
01374 if (!rx->ac3n && ac3pid){
01375 rx->ac3_id[0] = ac3pid;
01376 rx->ac3n++;
01377 afound++;
01378 ring_init(&rx->ac3rbuffer[0], AC3_BUF);
01379 init_pes_in(&rx->pac3[0], 0x80, &rx->ac3rbuffer[0],0);
01380 rx->pac3[0].priv = (void *) rx;
01381 ring_init(&rx->index_ac3rbuffer[0], INDEX_BUF);
01382 memset(&rx->ac3frame[0], 0, sizeof(audio_frame_t));
01383 init_index(&rx->current_ac3index[0]);
01384 rx->ac3frame_count[0] = 0;
01385 rx->first_ac3pts[0] = 0;
01386 }
01387
01388 }
01389
01390 if (afound && vfound){
01391 LOG(VB_GENERAL, LOG_INFO, "found");
01392 if (rx->vpid)
01393 LOG(VB_GENERAL, LOG_INFO, "vpid %d (0x%04x)",
01394 rx->vpid, rx->vpid);
01395 if (rx->apidn)
01396 LOG(VB_GENERAL, LOG_INFO, "apid %d (0x%04x)",
01397 rx->apid[0], rx->apid[0]);
01398 if (rx->ac3n)
01399 LOG(VB_GENERAL, LOG_INFO, "ac3pid %d (0x%04x)",
01400 rx->ac3_id[0], rx->ac3_id[0]);
01401 } else {
01402 LOG(VB_GENERAL, LOG_ERR, "Couldn't find pids");
01403 exit(1);
01404 }
01405
01406 }
01407
01408
01409 static void pes_id_out(pes_in_t *p)
01410 {
01411
01412 struct replex *rx;
01413 int len;
01414
01415 len = p->plength-3-p->hlength;
01416 rx = (struct replex *) p->priv;
01417
01418 rx->scan_found=0;
01419 switch(p->cid){
01420 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
01421 rx->scan_found=p->cid;
01422 break;
01423
01424 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
01425 rx->scan_found=p->cid;
01426 break;
01427
01428 case PRIVATE_STREAM1:
01429 if (rx->vdr){
01430 rx->scan_found = 0x80;
01431 break;
01432 } else {
01433
01434 uint8_t id = p->buf[9+p->hlength];
01435 switch(id){
01436 case 0x80 ... 0x8f:
01437 {
01438 int c=0;
01439 uint16_t fframe;
01440
01441 fframe=0;
01442 fframe = p->buf[9+p->hlength+3];
01443 fframe |= (p->buf[9+p->hlength+2]<<8);
01444
01445 if (fframe < p->plength){
01446 if ((c=find_audio_s(p->buf,
01447 9+p->hlength+4+fframe,
01448 AC3, p->plength+6)) >= 0){
01449 rx->scan_found = id;
01450 #if 0
01451 LOG(VB_GENERAL, LOG_INFO,
01452 "0x%04x 0x%04x \n",
01453 c-9-p->hlength-4, fframe);
01454 if (id>0x80)show_buf(p->buf+9+p->hlength,8);
01455 if (id>0x80)show_buf(p->buf+c,8);
01456 #endif
01457 }
01458 }
01459 break;
01460 }
01461 }
01462 break;
01463 }
01464 default:
01465 p->cid = 0;
01466 p->type = 0;
01467 rx->scan_found=0;
01468 memset(p->buf,0,MAX_PLENGTH*sizeof(uint8_t));
01469 return;
01470 }
01471 }
01472
01473 static void find_pes_ids(struct replex *rx)
01474 {
01475 uint8_t buf[IN_SIZE];
01476 int count=0;
01477 int j;
01478 int re=0;
01479 uint16_t vpid[MAXVPID], apid[MAXAPID], ac3pid[MAXAC3PID];
01480 int vn=0, an=0,ac3n=0;
01481
01482 memset (vpid , 0 , MAXVPID*sizeof(uint16_t));
01483 memset (apid , 0 , MAXAPID*sizeof(uint16_t));
01484 memset (ac3pid , 0 , MAXAC3PID*sizeof(uint16_t));
01485
01486 LOG(VB_GENERAL, LOG_INFO, "Trying to find PES IDs");
01487 rx->scan_found=0;
01488 rx->pvideo.priv = rx ;
01489 while (count < (int) rx->inflength-IN_SIZE){
01490 if ((re = save_read(rx,buf,IN_SIZE))<0)
01491 LOG(VB_GENERAL, LOG_ERR, "reading: %s",
01492 strerror(errno));
01493 else
01494 count += re;
01495
01496 get_pes(&rx->pvideo, buf, re, pes_id_out);
01497
01498 if ( rx->scan_found ){
01499
01500 switch (rx->scan_found){
01501
01502 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
01503 {
01504 int old=0;
01505 for (j=0; j < vn; j++){
01506 #if 0
01507 LOG(VB_GENERAL, LOG_INFO,
01508 "%d. %d", j+1, vpid[j]);
01509 #endif
01510 if (vpid[j] == rx->scan_found){
01511 old = 1;
01512 break;
01513 }
01514 }
01515 if (!old){
01516 vpid[vn]=rx->scan_found;
01517
01518 LOG(VB_GENERAL, LOG_INFO,
01519 "MPEG VIDEO %d: 0x%02x (%d)",
01520 vn+1,
01521 (int)vpid[vn], (int)vpid[vn]);
01522 if (vn+1 < MAXVPID) vn++;
01523 }
01524 }
01525 break;
01526
01527
01528 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
01529 {
01530 int old=0;
01531 for (j=0; j < an; j++)
01532 if (apid[j] == rx->scan_found){
01533 old = 1;
01534 break;
01535 }
01536 if (!old){
01537 apid[an]=rx->scan_found;
01538 LOG(VB_GENERAL, LOG_INFO,
01539 "MPEG AUDIO %d: 0x%02x (%d)",
01540 an +1,
01541 (int)apid[an],(int)apid[an]);
01542 if (an+1 < MAXAPID) an++;
01543 }
01544 }
01545 break;
01546
01547 case 0x80 ... 0x8f:
01548 {
01549 int old=0;
01550 for (j=0; j < ac3n; j++)
01551 if (ac3pid[j] == rx->scan_found){
01552 old = 1;
01553 break;
01554 }
01555 if (!old){
01556 ac3pid[ac3n]=rx->scan_found;
01557 if (rx->vdr){
01558 LOG(VB_GENERAL, LOG_INFO,
01559 "possible AC3 AUDIO with private stream 1 pid (0xbd)");
01560 }else{
01561 LOG(VB_GENERAL, LOG_INFO,
01562 "AC3 AUDIO %d: 0x%02x (%d)",
01563 ac3n+1,
01564 (int)ac3pid[ac3n],
01565 (int)ac3pid[ac3n]);
01566 }
01567 if (ac3n+1< MAXAC3PID) ac3n++;
01568 }
01569 rx->scan_found = 0;
01570 }
01571 break;
01572 }
01573 rx->scan_found = 0;
01574 }
01575 }
01576 }
01577
01578
01579
01580 static void replex_finish(struct replex *rx)
01581 {
01582 if (!replex_all_set(rx)){
01583 LOG(VB_GENERAL, LOG_ERR, "Can't find all required streams");
01584 if (rx->itype == REPLEX_PS){
01585 LOG(VB_GENERAL, LOG_ERR,
01586 "Please check if audio and video have standard IDs (0xc0 or 0xe0)");
01587 }
01588 exit(1);
01589 }
01590
01591 if (!rx->demux)
01592 finish_mpg((multiplex_t *)rx->priv);
01593 exit(0);
01594 }
01595
01596 static int replex_fill_buffers(struct replex *rx, uint8_t *mbuf)
01597 {
01598 uint8_t buf[IN_SIZE];
01599 int i,j;
01600 int count=0;
01601 int fill;
01602 int re;
01603 int rsize;
01604 int tries = 0;
01605
01606 if (rx->finish) return 0;
01607 fill = guess_fill(rx);
01608 #if 0
01609 LOG(VB_GENERAL, LOG_INFO, "trying to fill buffers with %d", fill);
01610 #endif
01611 if (fill < 0) return -1;
01612
01613 memset(buf, 0, IN_SIZE);
01614
01615 switch(rx->itype){
01616 case REPLEX_TS:
01617 if (fill < IN_SIZE){
01618 rsize = fill - (fill%188);
01619 } else rsize = IN_SIZE;
01620
01621 #if 0
01622 LOG(VB_GENERAL, LOG_INFO, "filling with %d", rsize);
01623 #endif
01624
01625 if (!rsize) return 0;
01626
01627 memset(buf, 0, IN_SIZE);
01628
01629 if ( mbuf ){
01630 for ( i = 0; i < 188 ; i++){
01631 if ( mbuf[i] == 0x47 ) break;
01632 }
01633
01634 if ( i == 188){
01635 LOG(VB_GENERAL, LOG_ERR, "Not a TS");
01636 return -1;
01637 } else {
01638 memcpy(buf,mbuf+i,2*TS_SIZE-i);
01639 if ((count = save_read(rx,mbuf,i))<0)
01640 LOG(VB_GENERAL, LOG_ERR, "reading: %s",
01641 strerror(errno));
01642 memcpy(buf+2*TS_SIZE-i,mbuf,i);
01643 i = 188;
01644 }
01645 } else i=0;
01646
01647
01648 #define MAX_TRIES 5
01649 while (count < rsize && tries < MAX_TRIES){
01650 if ((re = save_read(rx,buf+i,rsize-i)+i)<0)
01651 LOG(VB_GENERAL, LOG_ERR, "reading: %s",
01652 strerror(errno));
01653 else
01654 count += re;
01655 tries++;
01656
01657 if (!rx->vpid || !(rx->apidn || rx->ac3n)){
01658 find_pids_stdin(rx, buf, re);
01659 }
01660
01661 for( j = 0; j < re; j+= TS_SIZE){
01662
01663 if ( re - j < TS_SIZE) break;
01664
01665 if ( replex_tsp( rx, buf+j) < 0){
01666 LOG(VB_GENERAL, LOG_ERR,
01667 "Error reading TS");
01668 exit(1);
01669 }
01670 }
01671 i=0;
01672 }
01673
01674 if (tries == MAX_TRIES)
01675 replex_finish(rx);
01676 return 0;
01677 break;
01678
01679 case REPLEX_PS:
01680 rsize = fill;
01681 if (fill > IN_SIZE) rsize = IN_SIZE;
01682 if (mbuf)
01683 get_pes(&rx->pvideo, mbuf, 2*TS_SIZE, pes_es_out);
01684
01685 while (count < rsize && tries < MAX_TRIES){
01686 if ((re = save_read(rx, buf, rsize))<0)
01687 LOG(VB_GENERAL, LOG_ERR, "reading PS: %s",
01688 strerror(errno));
01689 else
01690 count += re;
01691
01692 get_pes(&rx->pvideo, buf, re, pes_es_out);
01693
01694 tries++;
01695
01696 }
01697
01698 if (tries == MAX_TRIES)
01699 replex_finish(rx);
01700 return 0;
01701 break;
01702
01703
01704 case REPLEX_AVI:
01705 rsize = fill;
01706 if (fill > IN_SIZE) rsize = IN_SIZE;
01707
01708 if (!(rx->ac.avih_flags & AVI_HASINDEX)){
01709
01710 if (mbuf){
01711 get_avi(&rx->pvideo, mbuf, rx->avi_rest, avi_es_out);
01712 }
01713
01714 while (count < rsize && tries < MAX_TRIES){
01715 if ((re = save_read(rx, buf, rsize))<0)
01716 LOG(VB_GENERAL, LOG_ERR, "reading AVI: %s",
01717 strerror(errno));
01718 else
01719 count += re;
01720
01721 get_avi(&rx->pvideo, buf, re, avi_es_out);
01722
01723 tries++;
01724 }
01725 } else {
01726 if (get_avi_from_index(&rx->pvideo, rx->fd_in,
01727 &rx->ac, avi_es_out, rsize) < 0)
01728 tries = MAX_TRIES;
01729 }
01730
01731 if (tries == MAX_TRIES)
01732 replex_finish(rx);
01733 return 0;
01734 break;
01735 }
01736
01737 return -1;
01738 }
01739
01740 static int fill_buffers(void *r, int finish)
01741 {
01742 struct replex *rx = (struct replex *)r;
01743
01744 rx->finish = finish;
01745
01746 return replex_fill_buffers(rx, NULL);
01747 }
01748
01749
01750 void init_index(index_unit *iu)
01751 {
01752 memset(iu,0, sizeof(index_unit));
01753 iu->frame_start = 1;
01754 }
01755
01756 static int replex_all_set(struct replex *rx)
01757 {
01758 int i;
01759 int set=0;
01760
01761 for (i=0; i < rx->ac3n ;i++){
01762 set += rx->ac3frame[i].set;
01763 }
01764 for (i=0; i<rx->apidn;i++){
01765 set += rx->aframe[i].set;
01766 }
01767 set += rx->seq_head.set;
01768
01769 if (set == (rx->ac3n+ rx->apidn + 1)) return 1;
01770 return 0;
01771 }
01772
01773
01774 static int check_stream_type(struct replex *rx, uint8_t * buf, int len)
01775 {
01776 int c=0;
01777 avi_context ac;
01778 uint8_t head;
01779
01780 if (rx->itype != REPLEX_TS) return rx->itype;
01781
01782 if (len< 2*TS_SIZE){
01783 LOG(VB_GENERAL, LOG_ERR, "cannot determine streamtype");
01784 exit(1);
01785 }
01786
01787 LOG(VB_GENERAL, LOG_INFO, "Checking for TS: ");
01788 while (c < len && buf[c]!=0x47) c++;
01789 if (c<len && len-c>=TS_SIZE){
01790 if (buf[c+TS_SIZE] == 0x47){
01791 LOG(VB_GENERAL, LOG_INFO, "confirmed");
01792 return REPLEX_TS;
01793 } else LOG(VB_GENERAL, LOG_INFO, "failed");
01794 } else LOG(VB_GENERAL, LOG_INFO, "failed");
01795
01796 LOG(VB_GENERAL, LOG_INFO, "Checking for AVI: ");
01797 if (check_riff(&ac, buf, len)>=0){
01798 LOG(VB_GENERAL, LOG_INFO, "confirmed");
01799 rx->itype = REPLEX_AVI;
01800 rx->vpid = 0xE0;
01801 rx->apidn = 1;
01802 rx->apid[0] = 0xC0;
01803 rx->ignore_pts =1;
01804 return REPLEX_AVI;
01805 } else LOG(VB_GENERAL, LOG_INFO, "failed");
01806
01807 LOG(VB_GENERAL, LOG_INFO, "Checking for PS: ");
01808 if (find_any_header(&head, buf, len) >= 0){
01809 LOG(VB_GENERAL, LOG_INFO, "confirmed(maybe)");
01810 } else {
01811 LOG(VB_GENERAL, LOG_INFO,"failed, trying it anyway");
01812 }
01813 rx->itype=REPLEX_PS;
01814 if (!rx->vpid) rx->vpid = 0xE0;
01815 if (!(rx->apidn || rx->ac3n)){
01816 rx->apidn = 1;
01817 rx->apid[0] = 0xC0;
01818 }
01819 return REPLEX_PS;
01820 }
01821
01822
01823 static void init_replex(struct replex *rx)
01824 {
01825 int i;
01826 uint8_t mbuf[2*TS_SIZE];
01827
01828 rx->analyze=0;
01829
01830 if (save_read(rx, mbuf, 2*TS_SIZE)<0)
01831 LOG(VB_GENERAL, LOG_ERR, "reading: %s",
01832 strerror(errno));
01833
01834 check_stream_type(rx, mbuf, 2*TS_SIZE);
01835 if (rx->itype == REPLEX_TS){
01836 if (!rx->vpid || !(rx->apidn || rx->ac3n)){
01837 if (rx->inflength){
01838 find_pids_file(rx);
01839 }
01840 }
01841 }
01842
01843
01844 if (rx->otype==REPLEX_HDTV){
01845 rx->videobuf = 4*VIDEO_BUF;
01846 } else {
01847 rx->videobuf = VIDEO_BUF;
01848 }
01849 rx->audiobuf = AUDIO_BUF;
01850 rx->ac3buf = AC3_BUF;
01851
01852 if (rx->itype == REPLEX_AVI){
01853 rx->videobuf = 4*VIDEO_BUF;
01854 rx->audiobuf = 2*rx->videobuf;
01855 }
01856
01857 rx->vpes_abort = 0;
01858 rx->first_iframe = 0;
01859 ring_init(&rx->vrbuffer, rx->videobuf);
01860 if (rx->itype == REPLEX_TS || rx->itype == REPLEX_AVI)
01861 init_pes_in(&rx->pvideo, 0xE0, &rx->vrbuffer, 0);
01862 else {
01863 init_pes_in(&rx->pvideo, 0, NULL, 1);
01864 }
01865 rx->pvideo.priv = (void *) rx;
01866 ring_init(&rx->index_vrbuffer, INDEX_BUF);
01867 memset(&rx->seq_head, 0, sizeof(sequence_t));
01868 init_index(&rx->current_vindex);
01869 rx->vgroup_count = 0;
01870 rx->vframe_count = 0;
01871 rx->first_vpts = 0;
01872 rx->video_state = S_SEARCH;
01873 rx->last_vpts = 0;
01874
01875 for (i=0; i<rx->apidn;i++){
01876
01877 rx->apes_abort[i] = 0;
01878 rx->audio_state[i] = S_SEARCH;
01879 ring_init(&rx->arbuffer[i], rx->audiobuf);
01880
01881 if (rx->itype == REPLEX_TS){
01882 init_pes_in(&rx->paudio[i], i+1,
01883 &rx->arbuffer[i], 0);
01884 rx->paudio[i].priv = (void *) rx;
01885 }
01886 ring_init(&rx->index_arbuffer[i], INDEX_BUF);
01887 memset(&rx->aframe[i], 0, sizeof(audio_frame_t));
01888 init_index(&rx->current_aindex[i]);
01889 rx->aframe_count[i] = 0;
01890 rx->first_apts[i] = 0;
01891 rx->last_apts[i] = 0;
01892 }
01893
01894 for (i=0; i<rx->ac3n;i++){
01895 rx->ac3pes_abort[i] = 0;
01896 rx->ac3_state[i] = S_SEARCH;
01897 ring_init(&rx->ac3rbuffer[i], AC3_BUF);
01898 if (rx->itype == REPLEX_TS){
01899 init_pes_in(&rx->pac3[i], 0x80+i,
01900 &rx->ac3rbuffer[i],0);
01901 rx->pac3[i].priv = (void *) rx;
01902 }
01903 ring_init(&rx->index_ac3rbuffer[i], INDEX_BUF);
01904 memset(&rx->ac3frame[i], 0, sizeof(audio_frame_t));
01905 init_index(&rx->current_ac3index[i]);
01906 rx->ac3frame_count[i] = 0;
01907 rx->first_ac3pts[i] = 0;
01908 rx->last_ac3pts[i] = 0;
01909 }
01910
01911 if (rx->itype == REPLEX_TS){
01912 if (replex_fill_buffers(rx, mbuf)< 0) {
01913 LOG(VB_GENERAL, LOG_ERR, "error filling buffer");
01914 exit(1);
01915 }
01916 } else if ( rx->itype == REPLEX_AVI){
01917 #define AVI_S 1024
01918 avi_context *ac;
01919 uint8_t buf[AVI_S];
01920 int re=0;
01921 ssize_t read_count = 0;
01922
01923 lseek(rx->fd_in, 0, SEEK_SET);
01924 ac = &rx->ac;
01925 memset(ac, 0, sizeof(avi_context));
01926 if ((read_count = save_read(rx, buf, 12)) != 12) {
01927 LOG(VB_GENERAL, LOG_ERR,
01928 "Error reading in 12 bytes from replex. Read %d bytes",
01929 (int)read_count);
01930 exit(1);
01931 }
01932
01933 if (check_riff(ac, buf, 12) < 0){
01934 LOG(VB_GENERAL, LOG_ERR, "Wrong RIFF header");
01935 exit(1);
01936 } else {
01937 LOG(VB_GENERAL, LOG_INFO, "Found RIFF header");
01938 }
01939
01940 memset(ac, 0, sizeof(avi_context));
01941 re = read_avi_header(ac, rx->fd_in);
01942 if (avi_read_index(ac,rx->fd_in) < 0 || re < 0){
01943 LOG(VB_GENERAL, LOG_ERR, "Error reading index");
01944 exit(1);
01945 }
01946
01947 rx->vframe_count = ac->ai[0].initial_frames*ac->vi.fps/
01948 ac->ai[0].fps;
01949
01950 rx->inflength = lseek(rx->fd_in, 0, SEEK_CUR)+ac->movi_length;
01951
01952 LOG(VB_GENERAL, LOG_INFO, "AVI initial frames %d",
01953 (int)rx->vframe_count);
01954 if (!ac->done){
01955 LOG(VB_GENERAL, LOG_ERR, "Error reading AVI header");
01956 exit(1);
01957 }
01958
01959 if (replex_fill_buffers(rx, buf+re)< 0) {
01960 LOG(VB_GENERAL, LOG_ERR, "error filling buffer");
01961 exit(1);
01962 }
01963 } else {
01964 if (replex_fill_buffers(rx, mbuf)< 0) {
01965 LOG(VB_GENERAL, LOG_ERR, "error filling buffer");
01966 exit(1);
01967 }
01968 }
01969
01970 }
01971
01972
01973 static void fix_audio(struct replex *rx, multiplex_t *mx)
01974 {
01975 int i;
01976 index_unit aiu;
01977 int size;
01978
01979 size = sizeof(index_unit);
01980
01981 for ( i = 0; i < rx->apidn; i++){
01982 do {
01983 while (ring_avail(&rx->index_arbuffer[i]) <
01984 sizeof(index_unit)){
01985 if (replex_fill_buffers(rx, 0)< 0) {
01986 LOG(VB_GENERAL, LOG_ERR,
01987 "error in fix audio");
01988 exit(1);
01989 }
01990 }
01991 ring_peek(&rx->index_arbuffer[i], (uint8_t *)&aiu, size, 0);
01992 if ( ptscmp(aiu.pts + rx->first_apts[i], rx->first_vpts) < 0){
01993 ring_skip(&rx->index_arbuffer[i], size);
01994 ring_skip(&rx->arbuffer[i], aiu.length);
01995 } else break;
01996
01997 } while (1);
01998 mx->ext[i].pts_off = aiu.pts;
01999
02000 LOG(VB_GENERAL, LOG_INFO, "Audio%d offset: ", i);
02001 printpts(mx->ext[i].pts_off);
02002 printpts(rx->first_apts[i]+mx->ext[i].pts_off);
02003 }
02004
02005 for ( i = 0; i < rx->ac3n; i++){
02006 do {
02007 while (ring_avail(&rx->index_ac3rbuffer[i]) <
02008 sizeof(index_unit)){
02009 if (replex_fill_buffers(rx, 0)< 0) {
02010 LOG(VB_GENERAL, LOG_ERR,
02011 "error in fix audio");
02012 exit(1);
02013 }
02014 }
02015 ring_peek(&rx->index_ac3rbuffer[i], (uint8_t *)&aiu,
02016 size, 0);
02017 if ( ptscmp (aiu.pts+rx->first_ac3pts[i], rx->first_vpts) < 0){
02018 ring_skip(&rx->index_ac3rbuffer[i], size);
02019 ring_skip(&rx->ac3rbuffer[i], aiu.length);
02020 } else break;
02021 } while (1);
02022 mx->ext[i].pts_off = aiu.pts;
02023
02024 LOG(VB_GENERAL, LOG_INFO, "AC3%d offset: ", i);
02025 printpts(mx->ext[i].pts_off);
02026 printpts(rx->first_ac3pts[i]+mx->ext[i].pts_off);
02027
02028 }
02029 }
02030
02031
02032
02033 static int get_next_video_unit(struct replex *rx, index_unit *viu)
02034 {
02035 if (ring_avail(&rx->index_vrbuffer)){
02036 ring_read(&rx->index_vrbuffer, (uint8_t *)viu,
02037 sizeof(index_unit));
02038 return 1;
02039 }
02040 return 0;
02041 }
02042
02043 static int get_next_audio_unit(struct replex *rx, index_unit *aiu, int i)
02044 {
02045 if(ring_avail(&rx->index_arbuffer[i])){
02046 ring_read(&rx->index_arbuffer[i], (uint8_t *)aiu,
02047 sizeof(index_unit));
02048 return 1;
02049 }
02050 return 0;
02051 }
02052
02053 static int get_next_ac3_unit(struct replex *rx, index_unit *aiu, int i)
02054 {
02055 if (ring_avail(&rx->index_ac3rbuffer[i])) {
02056 ring_read(&rx->index_ac3rbuffer[i], (uint8_t *)aiu,
02057 sizeof(index_unit));
02058
02059 return 1;
02060 }
02061 return 0;
02062 }
02063
02064
02065 static void do_analyze(struct replex *rx)
02066 {
02067 index_unit dummy;
02068 index_unit dummy2;
02069 int i;
02070 uint64_t lastvpts;
02071 uint64_t lastvdts;
02072 uint64_t lastapts[N_AUDIO];
02073 uint64_t lastac3pts[N_AC3];
02074 int av;
02075
02076 av = rx->analyze-1;
02077
02078 lastvpts = 0;
02079 lastvdts = 0;
02080 memset(lastapts, 0, N_AUDIO*sizeof(uint64_t));
02081 memset(lastac3pts, 0, N_AC3*sizeof(uint64_t));
02082
02083 LOG(VB_GENERAL, LOG_INFO, "STARTING ANALYSIS");
02084
02085
02086 while(!rx->finish){
02087 if (replex_fill_buffers(rx, 0)< 0) {
02088 LOG(VB_GENERAL, LOG_ERR,
02089 "error in get next video unit");
02090 return;
02091 }
02092 for (i=0; i< rx->apidn; i++){
02093 while(get_next_audio_unit(rx, &dummy2, i)){
02094 ring_skip(&rx->arbuffer[i],
02095 dummy2.length);
02096 if (av>=1){
02097 LOG(VB_GENERAL, LOG_INFO,
02098 "MPG2 Audio%d unit: length %d "
02099 "PTS ", i, dummy2.length);
02100 printptss(dummy2.pts);
02101
02102 if (lastapts[i]){
02103 LOG(VB_GENERAL, LOG_INFO,
02104 " diff:");
02105 printptss(ptsdiff(dummy2.pts,lastapts[i]));
02106 }
02107 lastapts[i] = dummy2.pts;
02108 }
02109 }
02110 }
02111
02112 for (i=0; i< rx->ac3n; i++){
02113 while(get_next_ac3_unit(rx, &dummy2, i)){
02114 ring_skip(&rx->ac3rbuffer[i],
02115 dummy2.length);
02116 if (av>=1){
02117 LOG(VB_GENERAL, LOG_INFO,
02118 "AC3 Audio%d unit: length %d "
02119 "PTS ", i, dummy2.length);
02120 printptss(dummy2.pts);
02121 if (lastac3pts[i]){
02122 LOG(VB_GENERAL, LOG_INFO,
02123 " diff:");
02124 printptss(ptsdiff(dummy2.pts, lastac3pts[i]));
02125 }
02126 lastac3pts[i] = dummy2.pts;
02127 }
02128 }
02129 }
02130
02131 while (get_next_video_unit(rx, &dummy)){
02132 ring_skip(&rx->vrbuffer,
02133 dummy.length);
02134 if (av==0 || av==2){
02135 LOG(VB_GENERAL, LOG_INFO, "Video unit: ");
02136 if (dummy.seq_header){
02137 LOG(VB_GENERAL, LOG_INFO,
02138 "Sequence header ");
02139 }
02140 if (dummy.gop){
02141 LOG(VB_GENERAL, LOG_INFO,
02142 "GOP header ");
02143 }
02144 switch (dummy.frame){
02145 case I_FRAME:
02146 LOG(VB_GENERAL, LOG_INFO, "I-frame");
02147 break;
02148 case B_FRAME:
02149 LOG(VB_GENERAL, LOG_INFO, "B-frame");
02150 break;
02151 case P_FRAME:
02152 LOG(VB_GENERAL, LOG_INFO, "P-frame");
02153 break;
02154 }
02155 LOG(VB_GENERAL, LOG_INFO, " length %d PTS ",
02156 dummy.length);
02157 printptss(dummy.pts);
02158 if (lastvpts){
02159 LOG(VB_GENERAL, LOG_INFO," diff:");
02160 printptss(ptsdiff(dummy.pts, lastvpts));
02161 }
02162 lastvpts = dummy.pts;
02163
02164 LOG(VB_GENERAL, LOG_INFO, " DTS ");
02165 printptss(dummy.dts);
02166 if (lastvdts){
02167 LOG(VB_GENERAL, LOG_INFO, " diff:");
02168 printptss(ptsdiff(dummy.dts,lastvdts));
02169 }
02170 lastvdts = dummy.dts;
02171 }
02172 }
02173 }
02174
02175
02176 }
02177
02178 static void do_scan(struct replex *rx)
02179 {
02180 uint8_t mbuf[2*TS_SIZE];
02181
02182 rx->analyze=0;
02183
02184 if (save_read(rx, mbuf, 2*TS_SIZE)<0)
02185 LOG(VB_GENERAL, LOG_ERR, "reading: %s",
02186 strerror(errno));
02187
02188 LOG(VB_GENERAL, LOG_INFO, "STARTING SCAN");
02189
02190 check_stream_type(rx, mbuf, 2*TS_SIZE);
02191
02192 switch(rx->itype){
02193 case REPLEX_TS:
02194 find_all_pids_file(rx);
02195 break;
02196
02197 case REPLEX_PS:
02198 init_pes_in(&rx->pvideo, 0, NULL, 1);
02199 find_pes_ids(rx);
02200 break;
02201
02202 case REPLEX_AVI:
02203 break;
02204 }
02205
02206 }
02207
02208 static void do_demux(struct replex *rx)
02209 {
02210 index_unit dummy;
02211 index_unit dummy2;
02212 int i;
02213 LOG(VB_GENERAL, LOG_INFO, "STARTING DEMUX");
02214
02215 while(!rx->finish){
02216 if (replex_fill_buffers(rx, 0)< 0) {
02217 LOG(VB_GENERAL, LOG_ERR,
02218 "error in get next video unit");
02219 return;
02220 }
02221 for (i=0; i< rx->apidn; i++){
02222 while(get_next_audio_unit(rx, &dummy2, i)){
02223 ring_read_file(&rx->arbuffer[i],
02224 rx->dmx_out[i+1],
02225 dummy2.length);
02226 }
02227 }
02228
02229 for (i=0; i< rx->ac3n; i++){
02230 while(get_next_ac3_unit(rx, &dummy2, i)){
02231 ring_read_file(&rx->ac3rbuffer[i],
02232 rx->dmx_out[i+1+rx->apidn],
02233 dummy2.length);
02234 }
02235 }
02236
02237 while (get_next_video_unit(rx, &dummy)){
02238 ring_read_file(&rx->vrbuffer, rx->dmx_out[0],
02239 dummy.length);
02240 }
02241 }
02242 }
02243
02244
02245 static void do_replex(struct replex *rx)
02246 {
02247 int video_ok = 0;
02248 int ext_ok[N_AUDIO];
02249 int start=1;
02250 multiplex_t mx;
02251
02252
02253 LOG(VB_GENERAL, LOG_INFO, "STARTING REPLEX");
02254 memset(&mx, 0, sizeof(mx));
02255 memset(ext_ok, 0, N_AUDIO*sizeof(int));
02256
02257 while (!replex_all_set(rx)){
02258 if (replex_fill_buffers(rx, 0)< 0) {
02259 LOG(VB_GENERAL, LOG_INFO, "error filling buffer");
02260 exit(1);
02261 }
02262 }
02263
02264 int i;
02265 for (i = 0; i < rx->apidn; i++){
02266 rx->exttype[i] = 2;
02267 rx->extframe[i] = rx->aframe[i];
02268 rx->extrbuffer[i] = rx->arbuffer[i];
02269 rx->index_extrbuffer[i] = rx->index_arbuffer[i];
02270 rx->exttypcnt[i+1] = i;
02271 }
02272
02273 int ac3Count = 1;
02274 for (i = rx->apidn; i < rx->apidn + rx->ac3n; i++){
02275 rx->exttype[i] = 1;
02276 rx->extframe[i] = rx->ac3frame[i];
02277 rx->extrbuffer[i] = rx->ac3rbuffer[i];
02278 rx->index_extrbuffer[i] = rx->index_ac3rbuffer[i];
02279 rx->exttypcnt[i] = ac3Count++;
02280 }
02281
02282 mx.priv = (void *) rx;
02283 rx->priv = (void *) &mx;
02284 init_multiplex(&mx, &rx->seq_head, rx->extframe,
02285 rx->exttype, rx->exttypcnt, rx->video_delay,
02286 rx->audio_delay, rx->fd_out, fill_buffers,
02287 &rx->vrbuffer, &rx->index_vrbuffer,
02288 rx->extrbuffer, rx->index_extrbuffer,
02289 rx->otype);
02290
02291 if (!rx->ignore_pts){
02292 fix_audio(rx, &mx);
02293 }
02294 setup_multiplex(&mx);
02295
02296 while(1){
02297 check_times( &mx, &video_ok, ext_ok, &start);
02298
02299 write_out_packs( &mx, video_ok, ext_ok);
02300 }
02301 }
02302
02303
02304 static void usage(char *progname)
02305 {
02306 printf ("usage: %s [options] <input files>\n\n",progname);
02307 printf ("options:\n");
02308 printf (" --help, -h: print help message\n");
02309 printf (" --type, -t: set output type (MPEG2, DVD, HDTV)\n");
02310 printf (" --of, -o: set output file\n");
02311 printf (" --input_stream, -i: set input stream type (TS(default), PS, AVI)\n");
02312 printf (" --audio_pid, -a: audio PID for TS stream (also used for PS id)\n");
02313 printf (" --ac3_id, -c: ID of AC3 audio for demux (also used for PS id)\n");
02314 printf (" --video_pid, -v: video PID for TS stream (also used for PS id)\n");
02315 printf (" --video_delay, -d: video delay in ms\n");
02316 printf (" --audio_delay, -e: audio delay in ms\n");
02317 printf (" --ignore_PTS, -f: ignore all PTS information of original\n");
02318 printf (" --keep_PTS, -k: keep and don't correct PTS information of original\n");
02319 printf (" --fix_sync, -n: try to fix audio sync while demuxing\n");
02320 printf (" --demux, -z: demux only (-o is basename)\n");
02321 printf (" --analyze, -y: analyze (0=video,1=audio, 2=both)\n");
02322 printf (" --scan, -s: scan for streams\n");
02323 printf (" --vdr, -x: handle AC3 for vdr input file\n");
02324 exit(1);
02325 }
02326
02327 int main(int argc, char **argv)
02328 {
02329 int c;
02330 int analyze=0;
02331 int scan =0;
02332 char *filename = NULL;
02333 const char *type = "SVCD";
02334 const char *inpt = "TS";
02335
02336 struct replex rx;
02337
02338 memset(&rx, 0, sizeof(struct replex));
02339
02340 while (1) {
02341 int option_index = 0;
02342 static struct option long_options[] = {
02343 {"type", required_argument, NULL, 't'},
02344 {"input_stream", required_argument, NULL, 'i'},
02345 {"video_pid", required_argument, NULL, 'v'},
02346 {"audio_pid", required_argument, NULL, 'a'},
02347 {"audio_delay", required_argument, NULL, 'e'},
02348 {"video_delay", required_argument, NULL, 'd'},
02349 {"ac3_id", required_argument, NULL, 'c'},
02350 {"of",required_argument, NULL, 'o'},
02351 {"ignore_PTS",required_argument, NULL, 'f'},
02352 {"keep_PTS",required_argument, NULL, 'k'},
02353 {"fix_sync",no_argument, NULL, 'n'},
02354 {"demux",no_argument, NULL, 'z'},
02355 {"analyze",required_argument, NULL, 'y'},
02356 {"scan",required_argument, NULL, 's'},
02357 {"vdr",required_argument, NULL, 'x'},
02358 {"help", no_argument , NULL, 'h'},
02359 {0, 0, 0, 0}
02360 };
02361 c = getopt_long (argc, argv,
02362 "t:o:a:v:i:hp:q:d:c:n:fkd:e:zy:sx",
02363 long_options, &option_index);
02364 if (c == -1)
02365 break;
02366
02367 switch (c) {
02368 case 't':
02369 type = optarg;
02370 break;
02371 case 'i':
02372 inpt = optarg;
02373 break;
02374 case 'd':
02375 rx.video_delay = strtol(optarg,(char **)NULL, 0)
02376 *CLOCK_MS;
02377 break;
02378 case 'e':
02379 rx.audio_delay = strtol(optarg,(char **)NULL, 0)
02380 *CLOCK_MS;
02381 break;
02382 case 'a':
02383 if (rx.apidn==N_AUDIO){
02384 LOG(VB_GENERAL, LOG_ERR, "Too many audio PIDs");
02385 exit(1);
02386 }
02387 rx.apid[rx.apidn] = strtol(optarg,(char **)NULL, 0);
02388 rx.apidn++;
02389 break;
02390 case 'v':
02391 rx.vpid = strtol(optarg,(char **)NULL, 0);
02392 break;
02393 case 'c':
02394 if (rx.ac3n==N_AC3){
02395 LOG(VB_GENERAL, LOG_ERR, "Too many audio PIDs");
02396 exit(1);
02397 }
02398 rx.ac3_id[rx.ac3n] = strtol(optarg,(char **)NULL, 0);
02399 rx.ac3n++;
02400 break;
02401 case 'o':
02402 filename = optarg;
02403 break;
02404 case 'f':
02405 rx.ignore_pts =1;
02406 break;
02407 case 'k':
02408 rx.keep_pts =1;
02409 break;
02410 case 'z':
02411 rx.demux =1;
02412 break;
02413 case 'n':
02414 rx.fix_sync =1;
02415 break;
02416 case 'y':
02417 analyze = strtol(optarg,(char **)NULL, 0);
02418 if (analyze>2) usage(argv[0]);
02419 analyze++;
02420 break;
02421 case 's':
02422 scan = 1;
02423 break;
02424 case 'x':
02425 rx.vdr=1;
02426 break;
02427 case 'h':
02428 case '?':
02429 default:
02430 usage(argv[0]);
02431 }
02432 }
02433
02434 if (rx.fix_sync)
02435 av_register_all();
02436
02437 if (optind == argc-1) {
02438 if ((rx.fd_in = open(argv[optind] ,O_RDONLY| O_LARGEFILE)) < 0) {
02439 perror("Error opening input file ");
02440 exit(1);
02441 }
02442 LOG(VB_GENERAL, LOG_INFO, "Reading from %s", argv[optind]);
02443 rx.inflength = lseek(rx.fd_in, 0, SEEK_END);
02444 LOG(VB_GENERAL, LOG_INFO, "Input file length: %.2f MB",
02445 rx.inflength/1024.0/1024.0);
02446 lseek(rx.fd_in,0,SEEK_SET);
02447 rx.lastper = 0;
02448 rx.finread = 0;
02449 } else {
02450 LOG(VB_GENERAL, LOG_INFO, "using stdin as input");
02451 rx.fd_in = STDIN_FILENO;
02452 rx.inflength = 0;
02453 }
02454
02455 if (!rx.demux){
02456 if (filename){
02457 if ((rx.fd_out = open(filename,O_WRONLY|O_CREAT
02458 |O_TRUNC|O_LARGEFILE,
02459 S_IRUSR|S_IWUSR|S_IRGRP|
02460 S_IWGRP|
02461 S_IROTH|S_IWOTH)) < 0){
02462 perror("Error opening output file");
02463 exit(1);
02464 }
02465 LOG(VB_GENERAL, LOG_INFO, "Output File is: %s",
02466 filename);
02467 } else {
02468 rx.fd_out = STDOUT_FILENO;
02469 LOG(VB_GENERAL, LOG_INFO, "using stdout as output");
02470 }
02471 }
02472 if (scan){
02473 if (rx.fd_in == STDIN_FILENO){
02474 LOG(VB_GENERAL, LOG_ERR, "Can`t scan from pipe");
02475 exit(1);
02476 }
02477 do_scan(&rx);
02478 exit(0);
02479 }
02480
02481 if (!strncmp(type,"MPEG2",6))
02482 rx.otype=REPLEX_MPEG2;
02483 else if (!strncmp(type,"DVD",4))
02484 rx.otype=REPLEX_DVD;
02485 else if (!strncmp(type,"HDTV",4))
02486 rx.otype=REPLEX_HDTV;
02487 else if (!rx.demux)
02488 usage(argv[0]);
02489
02490 if (!strncmp(inpt,"TS",3)){
02491 rx.itype=REPLEX_TS;
02492 } else if (!strncmp(inpt,"PS",3)){
02493 rx.itype=REPLEX_PS;
02494 if (!rx.vpid) rx.vpid = 0xE0;
02495 if (!(rx.apidn || rx.ac3n)){
02496 rx.apidn = 1;
02497 rx.apid[0] = 0xC0;
02498 }
02499 } else if (!strncmp(inpt,"AVI",4)){
02500 rx.itype=REPLEX_AVI;
02501 rx.vpid = 0xE0;
02502 rx.apidn = 1;
02503 rx.apid[0] = 0xC0;
02504 rx.ignore_pts =1;
02505 } else {
02506 usage(argv[0]);
02507 }
02508
02509 init_replex(&rx);
02510 rx.analyze= analyze;
02511
02512 if (rx.demux) {
02513 int i;
02514 char fname[256];
02515 if (!filename){
02516 filename = malloc(4);
02517 strcpy(filename,"out");
02518 }
02519 if (strlen(filename) > 250){
02520 LOG(VB_GENERAL, LOG_ERR, "Basename too long");
02521 exit(0);
02522 }
02523
02524 snprintf(fname,256,"%s.mv2",filename);
02525 if ((rx.dmx_out[0] = open(fname,O_WRONLY|
02526 O_CREAT|O_TRUNC|
02527 O_LARGEFILE,
02528 S_IRUSR|S_IWUSR|
02529 S_IRGRP|S_IWGRP|
02530 S_IROTH|S_IWOTH))
02531 < 0){
02532 perror("Error opening output file");
02533 exit(1);
02534 }
02535 LOG(VB_GENERAL, LOG_INFO, "Video output File is: %s",
02536 fname);
02537
02538 for (i=0; i < rx.apidn; i++){
02539 snprintf(fname,256,"%s%d.mp2",filename
02540 ,i);
02541 if ((rx.dmx_out[i+1] =
02542 open(fname,O_WRONLY|
02543 O_CREAT|O_TRUNC|
02544 O_LARGEFILE,
02545 S_IRUSR|S_IWUSR|
02546 S_IRGRP|S_IWGRP|
02547 S_IROTH|S_IWOTH))
02548 < 0){
02549 perror("Error opening output file");
02550 exit(1);
02551 }
02552 LOG(VB_GENERAL, LOG_INFO, "Audio%d output File is: %s",
02553 i, fname);
02554 }
02555
02556
02557 for (i=0; i < rx.ac3n; i++){
02558 snprintf(fname,256,"%s%d.ac3",filename
02559 ,i);
02560 if ((rx.dmx_out[i+1+rx.apidn] =
02561 open(fname,O_WRONLY|
02562 O_CREAT|O_TRUNC|
02563 O_LARGEFILE,
02564 S_IRUSR|S_IWUSR|
02565 S_IRGRP|S_IWGRP|
02566 S_IROTH|S_IWOTH))
02567 < 0){
02568 perror("Error opening output file");
02569 exit(1);
02570 }
02571 LOG(VB_GENERAL, LOG_INFO, "AC3%d output File is: %s",
02572 i, fname);
02573 }
02574 do_demux(&rx);
02575 } else if (analyze){
02576 rx.demux=1;
02577 do_analyze(&rx);
02578 } else {
02579 do_replex(&rx);
02580 }
02581
02582 return 0;
02583 }
02584
02585 void LogPrintLine( uint64_t mask, LogLevel_t level, const char *file, int line,
02586 const char *function, int fromQString,
02587 const char *format, ... )
02588 {
02589 va_list arguments;
02590
02591 va_start(arguments, format);
02592 vfprintf(stderr, format, arguments);
02593 va_end(arguments);
02594 fprintf(stderr, "\n");
02595 }