MythTV  0.26-pre
replex.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends