|
MythTV
0.26-pre
|
00001 /* 00002 * replex.c 00003 * 00004 * 00005 * Copyright (C) 2003 Marcus Metzler <mocm@metzlerbros.de> 00006 * Metzler Brothers Systementwicklung GbR 00007 * Changes to use MythTV logging 00008 * Copyright (C) 2011 Gavin Hurlbut <ghurlbut@mythtv.org> 00009 * 00010 * This program is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU General Public License 00012 * as published by the Free Software Foundation; either version 2 00013 * of the License, or (at your option) any later version. 00014 * 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * General Public License for more details. 00020 * 00021 * 00022 * You should have received a copy of the GNU General Public License 00023 * along with this program; if not, write to the Free Software 00024 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00025 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00026 * 00027 */ 00028 //#define IN_DEBUG 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 /* find the MP2 encoder */ 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 /* put sample parameters */ 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 /* open it */ 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 /* the codec gives us the frame size, in samples */ 00117 frame_size = c->frame_size; 00118 samples = malloc(frame_size * 2 * c->channels); 00119 00120 /* create samples for a single blank frame */ 00121 for (j=0;j<frame_size;j++) { 00122 samples[2*j] = 0; 00123 samples[2*j+1] = 0; 00124 } 00125 00126 /* encode the samples */ 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 // try to fix audio sync - only works for mpeg audio for now 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 // FIXME can only remove one frame at a time for now 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 // limit inserts to a maximum of 5 frames 00299 if (framesdiff > 5) 00300 framesdiff = 5; 00301 00302 // alloc memmory for audio frame 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 // try to encode a blank frame 00311 if (encode_mp2_audio(aframe, framebuf, sizeof(uint8_t) * aframe->framesize) != 0) { 00312 // encode failed so just use a copy of the current frame 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 // add each extra frame required direct to the output file 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 //#define ANA 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) { // adaptation 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 // rx->aframe_count[0] = ac->ai[0].initial_frames; 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 }
1.7.6.1