00001 #include <unistd.h>
00002 #include <string.h>
00003 #include <stdlib.h>
00004
00005 #include "multiplex.h"
00006 #include "ts.h"
00007
00008 static int buffers_filled(multiplex_t *mx)
00009 {
00010 int vavail=0, aavail=0, i;
00011
00012 vavail = ring_avail(mx->index_vrbuffer)/sizeof(index_unit);
00013
00014 for (i=0; i<mx->extcnt;i++){
00015 aavail += ring_avail(&mx->index_extrbuffer[i])/
00016 sizeof(index_unit);
00017 }
00018
00019 if (aavail+vavail) return ((aavail+vavail));
00020 return 0;
00021 }
00022
00023 static int use_video(uint64_t vpts, extdata_t *ext, int *aok, int n)
00024 {
00025 int i;
00026 for(i=0; i < n; i++)
00027 if(aok[i] && ptscmp(vpts,ext[i].pts) > 0)
00028 return 0;
00029 return 1;
00030 }
00031 static int which_ext(extdata_t *ext, int *aok, int n)
00032 {
00033 int i;
00034 int started = 0;
00035 int pos = -1;
00036 uint64_t tmppts;
00037 for(i=0; i < n; i++)
00038 if(aok[i]){
00039 if(! started){
00040 started=1;
00041 tmppts=ext[i].pts;
00042 pos = i;
00043 } else if(ptscmp(tmppts, ext[i].pts) > 0) {
00044 tmppts = ext[i].pts;
00045 pos = i;
00046 }
00047 }
00048 return pos;
00049 }
00050
00051 static int peek_next_video_unit(multiplex_t *mx, index_unit *viu)
00052 {
00053 if (!ring_avail(mx->index_vrbuffer) && mx->finish) return 0;
00054
00055 while (ring_avail(mx->index_vrbuffer) < sizeof(index_unit))
00056 if (mx->fill_buffers(mx->priv, mx->finish)< 0) {
00057 fprintf(stderr,"error in peek next video unit\n");
00058 return 0;
00059 }
00060
00061 ring_peek(mx->index_vrbuffer, (uint8_t *)viu, sizeof(index_unit),0);
00062 #ifdef OUT_DEBUG
00063 fprintf(stderr,"video index start: %d stop: %d (%d) rpos: %d\n",
00064 viu->start, (viu->start+viu->length),
00065 viu->length, ring_rpos(mx->vrbuffer));
00066 #endif
00067
00068 return 1;
00069 }
00070
00071 static int get_next_video_unit(multiplex_t *mx, index_unit *viu)
00072 {
00073 index_unit nviu;
00074 if (!ring_avail(mx->index_vrbuffer) && mx->finish) return 0;
00075
00076 while (ring_avail(mx->index_vrbuffer) < sizeof(index_unit))
00077 if (mx->fill_buffers(mx->priv, mx->finish)< 0) {
00078 fprintf(stderr,"error in get next video unit\n");
00079 return 0;
00080 }
00081
00082 ring_read(mx->index_vrbuffer, (uint8_t *)viu, sizeof(index_unit));
00083 #ifdef OUT_DEBUG
00084 fprintf(stderr,"video index start: %d stop: %d (%d) rpos: %d\n",
00085 viu->start, (viu->start+viu->length),
00086 viu->length, ring_rpos(mx->vrbuffer));
00087 #endif
00088 if(! peek_next_video_unit(mx, &nviu))
00089 return 1;
00090
00091 viu->ptsrate = (uptsdiff(nviu.dts, viu->dts) << 8) / viu->length;
00092 return 1;
00093 }
00094
00095 static int peek_next_ext_unit(multiplex_t *mx, index_unit *extiu, int i)
00096 {
00097 if (!ring_avail(&mx->index_extrbuffer[i]) && mx->finish) return 0;
00098
00099 while (ring_avail(&mx->index_extrbuffer[i]) < sizeof(index_unit))
00100 if (mx->fill_buffers(mx->priv, mx->finish)< 0) {
00101 fprintf(stderr,"error in peek next video unit\n");
00102 return 0;
00103 }
00104
00105 ring_peek(&mx->index_extrbuffer[i], (uint8_t *)extiu,
00106 sizeof(index_unit),0);
00107 #ifdef OUT_DEBUG
00108 fprintf(stderr,"ext index start: %d stop: %d (%d) rpos: %d\n",
00109 extiu->start, (extiu->start+extiu->length),
00110 extiu->length, ring_rpos(mx->extrbuffer));
00111 #endif
00112
00113 return 1;
00114 }
00115
00116 static int get_next_ext_unit(multiplex_t *mx, index_unit *extiu, int i)
00117 {
00118 index_unit niu, *piu = extiu;
00119 int j, length = 0;
00120 for(j = 0; j < mx->ext[i].frmperpkt; j++) {
00121 if (!ring_avail(&mx->index_extrbuffer[i]) && mx->finish)
00122 break;
00123
00124 while(ring_avail(&mx->index_extrbuffer[i]) < sizeof(index_unit))
00125 if (mx->fill_buffers(mx->priv, mx->finish)< 0) {
00126 fprintf(stderr,"error in get next ext unit\n");
00127 break;
00128 }
00129
00130 ring_read(&mx->index_extrbuffer[i], (uint8_t *)piu,
00131 sizeof(index_unit));
00132 length += piu->length;
00133 piu = &niu;
00134 }
00135 if (j == 0)
00136 return 0;
00137 extiu->length = length;
00138 extiu->framesize = length;
00139 if(! peek_next_ext_unit(mx, &niu, i))
00140 return 1;
00141
00142 extiu->ptsrate = (uptsdiff(niu.pts, extiu->pts) << 8) / extiu->length;
00143
00144 #ifdef OUT_DEBUG
00145 fprintf(stderr,"ext index start: %d stop: %d (%d) rpos: %d\n",
00146 extiu->start, (extiu->start+extiu->length),
00147 extiu->length, ring_rpos(&mx->extrbuffer[i]));
00148 #endif
00149 return 1;
00150 }
00151
00152 static uint8_t get_ptsdts(multiplex_t *mx, index_unit *viu)
00153 {
00154 uint8_t ptsdts = 0;
00155 switch (mx->frame_timestamps){
00156 case TIME_ALWAYS:
00157 if (viu->frame == I_FRAME || viu->frame == P_FRAME)
00158 ptsdts = PTS_DTS;
00159 else
00160 ptsdts = PTS_ONLY;
00161 break;
00162
00163 case TIME_IFRAME:
00164 if (viu->frame == I_FRAME)
00165 ptsdts = PTS_DTS;
00166 break;
00167 }
00168 return ptsdts;
00169 }
00170
00171 static void writeout_video(multiplex_t *mx)
00172 {
00173 uint8_t outbuf[3000];
00174 int written=0;
00175 uint8_t ptsdts=0;
00176 unsigned int length;
00177 int nlength=0;
00178 int frame_len=0;
00179 index_unit *viu = &mx->viu;
00180
00181 #ifdef OUT_DEBUG
00182 fprintf(stderr,"writing VIDEO pack\n");
00183 #endif
00184
00185 if(viu->frame_start) {
00186 ptsdts = get_ptsdts(mx, viu);
00187 frame_len = viu->length;
00188 }
00189
00190 if (viu->frame_start && viu->seq_header && viu->gop &&
00191 viu->frame == I_FRAME){
00192 if (!mx->startup && mx->is_ts){
00193 write_ts_patpmt(mx->ext, mx->extcnt, 1, outbuf);
00194 write(mx->fd_out, outbuf, mx->pack_size*2);
00195 ptsinc(&mx->SCR, mx->SCRinc*2);
00196 } else if (!mx->startup && mx->navpack){
00197 write_nav_pack(mx->pack_size, mx->extcnt,
00198 mx->SCR, mx->muxr, outbuf);
00199 write(mx->fd_out, outbuf, mx->pack_size);
00200 ptsinc(&mx->SCR, mx->SCRinc);
00201 } else mx->startup = 0;
00202 #ifdef OUT_DEBUG
00203 fprintf (stderr, " with sequence and gop header\n");
00204 #endif
00205 }
00206
00207 if (mx->finish != 2 && dummy_space(&mx->vdbuf) < mx->data_size){
00208 return;
00209 }
00210 length = viu->length;
00211 while (!mx->is_ts && length < mx->data_size){
00212 index_unit nviu;
00213 int old_start = viu->frame_start;
00214 int old_frame = viu->frame;
00215 uint64_t old_pts = viu->pts;
00216 uint64_t old_dts = viu->dts;
00217 dummy_add(&mx->vdbuf, uptsdiff(viu->dts+mx->video_delay,0)
00218 , viu->length);
00219 if ( peek_next_video_unit(mx, &nviu)){
00220 if (!(nviu.seq_header && nviu.gop &&
00221 nviu.frame == I_FRAME)){
00222 get_next_video_unit(mx, viu);
00223 frame_len = viu->length;
00224 length += viu->length;
00225 if(old_start) {
00226 viu->pts = old_pts;
00227 viu->dts = old_dts;
00228 viu->frame = old_frame;
00229 } else {
00230 ptsdts = get_ptsdts(mx, viu);
00231 }
00232 } else break;
00233 } else break;
00234 }
00235
00236 if (viu->frame_start){
00237 viu->frame_start=0;
00238 if (viu->gop){
00239 uint8_t gop[8];
00240 frame_len=length-frame_len;
00241 ring_peek(mx->vrbuffer, gop, 8, frame_len);
00242 pts2time( viu->pts + mx->video_delay, gop, 8);
00243 ring_poke(mx->vrbuffer, gop, 8, frame_len);
00244 viu->gop=0;
00245 }
00246 if (mx->VBR) {
00247 mx->extra_clock = ptsdiff(viu->dts + mx->video_delay,
00248 mx->SCR + 500*CLOCK_MS);
00249 #ifdef OUT_DEBUG1
00250 fprintf(stderr,"EXTRACLOCK2: %lli %lli %lli\n", viu->dts, mx->video_delay, mx->SCR);
00251 fprintf(stderr,"EXTRACLOCK2: %lli ", mx->extra_clock);
00252 printpts(mx->extra_clock);
00253 fprintf(stderr,"\n");
00254 #endif
00255
00256 if (mx->extra_clock < 0)
00257 mx->extra_clock = 0.0;
00258 }
00259 }
00260
00261
00262 nlength = length;
00263 if (mx->is_ts)
00264 written = write_video_ts( viu->pts+mx->video_delay,
00265 viu->dts+mx->video_delay,
00266 mx->SCR, outbuf, &nlength,
00267 ptsdts, mx->vrbuffer);
00268 else
00269 written = write_video_pes( mx->pack_size, mx->extcnt,
00270 viu->pts+mx->video_delay,
00271 viu->dts+mx->video_delay,
00272 mx->SCR, mx->muxr, outbuf, &nlength,
00273 ptsdts, mx->vrbuffer);
00274
00275 length -= nlength;
00276 dummy_add(&mx->vdbuf, uptsdiff( viu->dts+mx->video_delay,0)
00277 , viu->length-length);
00278 viu->length = length;
00279
00280
00281 viu->dts = uptsdiff(viu->dts + ((nlength*viu->ptsrate)>>8), 0);
00282
00283 write(mx->fd_out, outbuf, written);
00284
00285 #ifdef OUT_DEBUG
00286 fprintf(stderr,"VPTS");
00287 printpts(viu->pts);
00288 fprintf(stderr," DTS");
00289 printpts(viu->dts);
00290 printpts(mx->video_delay);
00291 fprintf(stderr,"\n");
00292 #endif
00293
00294 if (viu->length == 0){
00295 get_next_video_unit(mx, viu);
00296 }
00297
00298 }
00299
00300 static void writeout_ext(multiplex_t *mx, int n)
00301 {
00302 uint8_t outbuf[3000];
00303 int written=0;
00304 unsigned int length=0;
00305 int nlength=0;
00306 uint64_t pts, dpts=0;
00307 int newpts=0;
00308 int nframes=1;
00309 int ac3_off=0;
00310 int rest_data = 5;
00311
00312 int type = mx->ext[n].type;
00313 ringbuffer *airbuffer = &mx->index_extrbuffer[n];
00314 dummy_buffer *dbuf = &mx->ext[n].dbuf;
00315 uint64_t adelay = mx->ext[n].pts_off;
00316 uint64_t *apts = &mx->ext[n].pts;
00317 index_unit *aiu = &mx->ext[n].iu;
00318
00319 switch (type){
00320
00321 case MPEG_AUDIO:
00322 #ifdef OUT_DEBUG
00323 fprintf(stderr,"writing AUDIO%d pack\n",n);
00324 #endif
00325 break;
00326
00327 case AC3:
00328 #ifdef OUT_DEBUG
00329 fprintf(stderr,"writing AC3%d pack\n",n);
00330 #endif
00331 rest_data = 1;
00332 break;
00333
00334 default:
00335 return;
00336 }
00337
00338 if (mx->finish != 2 && dummy_space(dbuf) < mx->data_size + rest_data){
00339 return;
00340 }
00341
00342 pts = uptsdiff( aiu->pts + mx->audio_delay, adelay );
00343 *apts = pts;
00344 length = aiu->length;
00345 if (length < aiu->framesize){
00346 newpts = 1;
00347 ac3_off = length;
00348 }
00349 dummy_add(dbuf, pts, aiu->length);
00350
00351 #ifdef OUT_DEBUG
00352 fprintf(stderr,"start: %d stop: %d (%d) length %d ",
00353 aiu->start, (aiu->start+aiu->length),
00354 aiu->length, length);
00355 printpts(*apts);
00356 printpts(aiu->pts);
00357 printpts(mx->audio_delay);
00358 printpts(adelay);
00359 printpts(pts);
00360 fprintf(stderr,"\n");
00361 #endif
00362 while (!mx->is_ts && length < mx->data_size + rest_data){
00363 if (ring_read(airbuffer, (uint8_t *)aiu, sizeof(index_unit)) > 0){
00364 dpts = uptsdiff(aiu->pts +mx->audio_delay, adelay );
00365
00366 if (newpts){
00367 pts = dpts;
00368 newpts=0;
00369 }
00370
00371 length+= aiu->length;
00372 if (length < mx->data_size + rest_data)
00373 dummy_add(dbuf, dpts, aiu->length);
00374
00375 *apts = dpts;
00376 nframes++;
00377 #ifdef OUT_DEBUG
00378 fprintf(stderr,"start: %d stop: %d (%d) length %d ",
00379 aiu->start, (aiu->start+aiu->length),
00380 aiu->length, length);
00381 printpts(*apts);
00382 printpts(aiu->pts);
00383 printpts(mx->audio_delay);
00384 printpts(adelay);
00385 fprintf(stderr,"\n");
00386 #endif
00387 } else if (mx->finish){
00388 break;
00389 } else if (mx->fill_buffers(mx->priv, mx->finish)< 0) {
00390 fprintf(stderr,"error in writeout ext\n");
00391 exit(1);
00392 }
00393 }
00394
00395 nlength = length;
00396
00397 switch (type) {
00398 case MPEG_AUDIO:
00399 if(mx->is_ts)
00400 written = write_audio_ts( mx->ext[n].strmnum, pts,
00401 outbuf, &nlength, newpts ? 0 : PTS_ONLY,
00402 &mx->extrbuffer[n]);
00403 else
00404 written = write_audio_pes( mx->pack_size, mx->extcnt,
00405 mx->ext[n].strmnum, pts, mx->SCR,
00406 mx->muxr, outbuf, &nlength, PTS_ONLY,
00407 &mx->extrbuffer[n]);
00408 break;
00409 case AC3:
00410 if(mx->is_ts)
00411 written = write_ac3_ts(mx->ext[n].strmnum, pts,
00412 outbuf, &nlength, newpts ? 0 : PTS_ONLY,
00413 mx->ext[n].frmperpkt, &mx->extrbuffer[n]);
00414 else
00415 written = write_ac3_pes( mx->pack_size, mx->extcnt,
00416 mx->ext[n].strmnum, pts, mx->SCR,
00417 mx->muxr, outbuf, &nlength, PTS_ONLY,
00418 nframes, ac3_off,
00419 &mx->extrbuffer[n]);
00420 break;
00421 }
00422
00423 length -= nlength;
00424 write(mx->fd_out, outbuf, written);
00425
00426 dummy_add(dbuf, dpts, aiu->length-length);
00427 aiu->length = length;
00428 aiu->start = ring_rpos(&mx->extrbuffer[n]);
00429
00430 if (aiu->length == 0){
00431 get_next_ext_unit(mx, aiu, n);
00432 } else {
00433
00434 aiu->pts = uptsdiff(aiu->pts + ((nlength*aiu->ptsrate)>>8), 0);
00435 }
00436 *apts = uptsdiff(aiu->pts + mx->audio_delay, adelay);
00437 #ifdef OUT_DEBUG
00438 if ((int64_t)*apts < 0) fprintf(stderr,"SCHEISS ");
00439 fprintf(stderr,"APTS");
00440 printpts(*apts);
00441 printpts(aiu->pts);
00442 printpts(mx->audio_delay);
00443 printpts(adelay);
00444 fprintf(stderr,"\n");
00445 #endif
00446
00447 if (mx->fill_buffers(mx->priv, mx->finish)< 0) {
00448 fprintf(stderr,"error in writeout ext\n");
00449 exit(1);
00450 }
00451 }
00452
00453 static void writeout_padding (multiplex_t *mx)
00454 {
00455 uint8_t outbuf[3000];
00456
00457
00458 write_padding_pes( mx->pack_size, mx->extcnt, mx->SCR,
00459 mx->muxr, outbuf);
00460 write(mx->fd_out, outbuf, mx->pack_size);
00461 }
00462
00463 void check_times( multiplex_t *mx, int *video_ok, int *ext_ok, int *start)
00464 {
00465 int i;
00466 int set_ok = 0;
00467
00468 memset(ext_ok, 0, N_AUDIO*sizeof(int));
00469 *video_ok = 0;
00470
00471 if (mx->fill_buffers(mx->priv, mx->finish)< 0) {
00472 fprintf(stderr,"error in get next video unit\n");
00473 return;
00474 }
00475
00476
00477 mx->oldSCR = mx->SCR;
00478 if (!*start){
00479 ptsinc(&mx->SCR, mx->SCRinc);
00480 } else *start = 0;
00481
00482 if (mx->VBR) {
00483 #ifdef OUT_DEBUG1
00484 fprintf(stderr,"EXTRACLOCK: %lli ", mx->extra_clock);
00485 printpts(mx->extra_clock);
00486 fprintf(stderr,"\n");
00487 #endif
00488
00489 if (mx->extra_clock > 0.0) {
00490 int64_t d = mx->extra_clock/ mx->SCRinc - 1;
00491 if (d > 0)
00492 mx->extra_clock = d*mx->SCRinc;
00493 else
00494 mx->extra_clock = 0.0;
00495 }
00496
00497 if (mx->extra_clock > 0.0) {
00498 int64_t temp_scr = mx->extra_clock;
00499
00500 for (i=0; i<mx->extcnt; i++){
00501 if (ptscmp(mx->SCR + temp_scr + 100*CLOCK_MS,
00502 mx->ext[i].iu.pts) > 0) {
00503 while (ptscmp(mx->SCR + temp_scr
00504 + 100*CLOCK_MS,
00505 mx->ext[i].iu.pts) > 0)
00506 temp_scr -= mx->SCRinc;
00507 temp_scr += mx->SCRinc;
00508 }
00509 }
00510
00511 if (temp_scr > 0.0) {
00512 mx->SCR += temp_scr;
00513 mx->extra_clock -= temp_scr;
00514 } else
00515 mx->extra_clock = 0.0;
00516 }
00517 }
00518
00519
00520 dummy_delete(&mx->vdbuf, mx->SCR);
00521
00522 for (i=0;i <mx->extcnt; i++)
00523 dummy_delete(&mx->ext[i].dbuf, mx->SCR);
00524
00525 if (dummy_space(&mx->vdbuf) > mx->vsize && mx->viu.length > 0 &&
00526 (ptscmp(mx->viu.dts + mx->video_delay, 500*CLOCK_MS +mx->oldSCR)<0)
00527 && ring_avail(mx->index_vrbuffer)){
00528 *video_ok = 1;
00529 set_ok = 1;
00530 }
00531
00532 for (i = 0; i < mx->extcnt; i++){
00533 if (dummy_space(&mx->ext[i].dbuf) > mx->extsize &&
00534 mx->ext[i].iu.length > 0 &&
00535 ptscmp(mx->ext[i].pts, 500*CLOCK_MS + mx->oldSCR) < 0
00536 && ring_avail(&mx->index_extrbuffer[i])){
00537 ext_ok[i] = 1;
00538 set_ok = 1;
00539 }
00540 }
00541 #ifdef OUT_DEBUG
00542 if (set_ok) {
00543 fprintf(stderr, "SCR");
00544 printpts(mx->oldSCR);
00545 fprintf(stderr, "VDTS");
00546 printpts(mx->viu.dts);
00547 fprintf(stderr, " (%d)", *video_ok);
00548 fprintf(stderr, " EXT");
00549 for (i = 0; i < mx->extcnt; i++){
00550 fprintf(stderr, "%d:", mx->ext[i].type);
00551 printpts(mx->ext[i].pts);
00552 fprintf(stderr, " (%d)", ext_ok[i]);
00553 }
00554 fprintf(stderr, "\n");
00555 }
00556 #endif
00557 }
00558 void write_out_packs( multiplex_t *mx, int video_ok, int *ext_ok)
00559 {
00560 int i;
00561
00562 if (video_ok && use_video(mx->viu.dts + mx->video_delay,
00563 mx->ext, ext_ok, mx->extcnt)) {
00564 writeout_video(mx);
00565 } else {
00566 i = which_ext(mx->ext, ext_ok, mx->extcnt);
00567 int done=0;
00568 if(i>=0) {
00569 writeout_ext(mx, i);
00570 done = 1;
00571 }
00572 if (!done && !mx->VBR){
00573 writeout_padding(mx);
00574 }
00575 }
00576
00577 }
00578
00579 void finish_mpg(multiplex_t *mx)
00580 {
00581 int start=0;
00582 int video_ok = 0;
00583 int ext_ok[N_AUDIO];
00584 int n,nn,old,i;
00585 uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 };
00586
00587 memset(ext_ok, 0, N_AUDIO*sizeof(int));
00588 mx->finish = 1;
00589
00590 old = 0;nn=0;
00591 while ((n=buffers_filled(mx)) && nn<1000 ){
00592 if (n== old) nn++;
00593 else nn=0;
00594 old = n;
00595 check_times( mx, &video_ok, ext_ok, &start);
00596 write_out_packs( mx, video_ok, ext_ok);
00597 }
00598
00599 old = 0;nn=0;
00600 while ((n=ring_avail(mx->index_vrbuffer)/sizeof(index_unit))
00601 && nn<1000){
00602 if (n== old) nn++;
00603 else nn= 0;
00604 old = n;
00605 writeout_video(mx);
00606 }
00607
00608
00609 mx->finish = 2;
00610 old = 0;nn=0;
00611 for (i = 0; i < mx->extcnt; i++){
00612 while ((n=ring_avail(&mx->index_extrbuffer[i])/
00613 sizeof(index_unit)) && nn <100){
00614 if (n== old) nn++;
00615 else nn = 0;
00616 old = n;
00617 writeout_ext(mx, i);
00618 }
00619 }
00620
00621 if (mx->otype == REPLEX_MPEG2)
00622 write(mx->fd_out, mpeg_end,4);
00623
00624 dummy_destroy(&mx->vdbuf);
00625 for (i=0; i<mx->extcnt;i++)
00626 dummy_destroy(&mx->ext[i].dbuf);
00627 }
00628
00629 static int get_ts_video_overhead(int pktsize, sequence_t *seq)
00630 {
00631 uint32_t framesize;
00632 uint32_t numpkt;
00633 int pktdata = pktsize - TS_HEADER_MIN;
00634 framesize = seq->bit_rate * 50 / seq->frame_rate;
00635 numpkt = (framesize + PES_H_MIN + 10 + pktdata -1) / pktdata;
00636 return pktsize- ((pktsize * numpkt) - framesize + numpkt - 1) / numpkt;
00637 }
00638
00639 static int get_ts_ext_overhead(int pktsize, audio_frame_t *extframe,
00640 extdata_t *ext, int cnt)
00641 {
00642 int i, max = 0;
00643 int pktdata = pktsize - TS_HEADER_MIN;
00644 for (i = 0; i < cnt; i++) {
00645 int size, numpkt, overhead;
00646
00647
00648
00649 ext[i].frmperpkt = extframe[i].bit_rate / 53 /
00650 extframe[i].framesize;
00651 size = extframe[i].framesize * ext[i].frmperpkt;
00652 numpkt = (size + pktdata - 1) / pktdata;
00653 overhead = (pktsize * numpkt - size + numpkt - 1) / numpkt;
00654 if(overhead > max)
00655 max = overhead;
00656 }
00657 return pktsize - max;
00658 }
00659
00660 void init_multiplex( multiplex_t *mx, sequence_t *seq_head,
00661 audio_frame_t *extframe, int *exttype, int *exttypcnt,
00662 uint64_t video_delay, uint64_t audio_delay, int fd,
00663 int (*fill_buffers)(void *p, int f),
00664 ringbuffer *vrbuffer, ringbuffer *index_vrbuffer,
00665 ringbuffer *extrbuffer, ringbuffer *index_extrbuffer,
00666 int otype)
00667 {
00668 int i;
00669 uint32_t data_rate;
00670
00671 mx->fill_buffers = fill_buffers;
00672 mx->video_delay = video_delay;
00673 mx->audio_delay = audio_delay;
00674 mx->fd_out = fd;
00675 mx->otype = otype;
00676
00677 switch(mx->otype){
00678
00679 case REPLEX_DVD:
00680 mx->video_delay += 180*CLOCK_MS;
00681 mx->audio_delay += 180*CLOCK_MS;
00682 mx->pack_size = 2048;
00683 mx->audio_buffer_size = 4*1024;
00684 mx->video_buffer_size = 232*1024;
00685 mx->mux_rate = 1260000;
00686 mx->navpack = 1;
00687 mx->frame_timestamps = TIME_IFRAME;
00688 mx->VBR = 1;
00689 mx->reset_clocks = 0;
00690 mx->write_end_codes = 0;
00691 mx->set_broken_link = 0;
00692 mx->is_ts = 0;
00693 break;
00694
00695
00696 case REPLEX_MPEG2:
00697 mx->video_delay += 180*CLOCK_MS;
00698 mx->audio_delay += 180*CLOCK_MS;
00699 mx->pack_size = 2048;
00700 mx->audio_buffer_size = 4*1024;
00701 mx->video_buffer_size = 224*1024;
00702 mx->mux_rate = 0;
00703 mx->navpack = 0;
00704 mx->frame_timestamps = TIME_ALWAYS;
00705 mx->VBR = 1;
00706 mx->reset_clocks = 1;
00707 mx->write_end_codes = 1;
00708 mx->set_broken_link = 1;
00709 mx->is_ts = 0;
00710 break;
00711
00712 case REPLEX_HDTV:
00713 mx->video_delay += 180*CLOCK_MS;
00714 mx->audio_delay += 180*CLOCK_MS;
00715 mx->pack_size = 2048;
00716 mx->audio_buffer_size = 4*1024;
00717 mx->video_buffer_size = 4*224*1024;
00718 mx->mux_rate = 0;
00719 mx->navpack = 0;
00720 mx->frame_timestamps = TIME_ALWAYS;
00721 mx->VBR = 1;
00722 mx->reset_clocks = 1;
00723 mx->write_end_codes = 1;
00724 mx->set_broken_link = 1;
00725 mx->is_ts = 0;
00726 break;
00727
00728 case REPLEX_TS_SD:
00729 mx->video_delay += 180*CLOCK_MS;
00730 mx->audio_delay += 180*CLOCK_MS;
00731 mx->pack_size = 188;
00732 mx->audio_buffer_size = 4*1024;
00733 mx->video_buffer_size = 232*1024;
00734 mx->mux_rate = 1260000;
00735 mx->navpack = 0;
00736 mx->frame_timestamps = TIME_ALWAYS;
00737 mx->VBR = 1;
00738 mx->reset_clocks = 0;
00739 mx->write_end_codes = 0;
00740 mx->set_broken_link = 0;
00741 mx->is_ts = 1;
00742 break;
00743
00744 case REPLEX_TS_HD:
00745 mx->video_delay += 180*CLOCK_MS;
00746 mx->audio_delay += 180*CLOCK_MS;
00747 mx->pack_size = 188;
00748 mx->audio_buffer_size = 4*1024;
00749 mx->video_buffer_size = 4*224*1024;
00750 mx->mux_rate = 0;
00751 mx->navpack = 0;
00752 mx->frame_timestamps = TIME_ALWAYS;
00753 mx->VBR = 1;
00754 mx->reset_clocks = 0;
00755 mx->write_end_codes = 0;
00756 mx->set_broken_link = 0;
00757 mx->is_ts = 1;
00758 break;
00759 }
00760
00761 for (mx->extcnt = 0, data_rate = 0, i = 0;
00762 i < N_AUDIO && exttype[i]; i++){
00763 if (exttype[i] >= MAX_TYPES) {
00764 fprintf(stderr, "Found illegal stream type %d\n",
00765 exttype[i]);
00766 exit(1);
00767 }
00768 mx->ext[i].type = exttype[i];
00769 mx->ext[i].pts_off = 0;
00770 mx->ext[i].frmperpkt = 1;
00771 mx->ext[i].strmnum = exttypcnt[i];
00772 strncpy(mx->ext[i].language, extframe[i].language, 4);
00773 dummy_init(&mx->ext[i].dbuf, mx->audio_buffer_size);
00774 data_rate += extframe[i].bit_rate;
00775 mx->extcnt++;
00776 }
00777
00778 mx->vrbuffer = vrbuffer;
00779 mx->index_vrbuffer = index_vrbuffer;
00780 mx->extrbuffer = extrbuffer;
00781 mx->index_extrbuffer = index_extrbuffer;
00782
00783 dummy_init(&mx->vdbuf, mx->video_buffer_size);
00784
00785
00786
00787 if(mx->is_ts) {
00788
00789 mx->data_size = get_ts_video_overhead(mx->pack_size, seq_head);
00790 mx->extsize = get_ts_ext_overhead(mx->pack_size, extframe,
00791 mx->ext, mx->extcnt);
00792
00793 } else {
00794
00795 mx->data_size = mx->pack_size - PES_H_MIN - PS_HEADER_L1 - 10;
00796 mx->extsize = mx->data_size + 5;
00797 }
00798 mx->vsize = mx->data_size;
00799
00800 data_rate += seq_head->bit_rate *400;
00801
00802 mx->muxr = ((uint64_t)data_rate / 8 * mx->pack_size) / mx->data_size;
00803
00804
00805 if (mx->mux_rate) {
00806 if ( mx->mux_rate < mx->muxr)
00807 fprintf(stderr, "data rate may be to high for required mux rate\n");
00808 mx->muxr = mx->mux_rate;
00809 }
00810 fprintf(stderr, "Mux rate: %.2f Mbit/s\n", mx->muxr*8.0/1000000.);
00811
00812 mx->SCRinc = 27000000ULL/((uint64_t)mx->muxr /
00813 (uint64_t) mx->pack_size);
00814
00815 }
00816
00817 void setup_multiplex(multiplex_t *mx)
00818 {
00819 int i;
00820
00821 get_next_video_unit(mx, &mx->viu);
00822 for (i=0; i < mx->extcnt; i++)
00823 {
00824 get_next_ext_unit(mx, &mx->ext[i].iu, i);
00825 if (mx->ext[i].type == MPEG_AUDIO || mx->ext[i].type == AC3)
00826 mx->ext[i].pts = uptsdiff(
00827 mx->ext[i].iu.pts + mx->audio_delay,
00828 mx->ext[i].pts_off);
00829 else
00830 mx->ext[i].pts = uptsdiff(
00831 mx->ext[i].iu.pts, mx->ext[i].pts_off);
00832 }
00833
00834 mx->SCR = 0;
00835
00836
00837 if (mx->is_ts) {
00838 uint8_t outbuf[2048];
00839 write_ts_patpmt(mx->ext, mx->extcnt, 1, outbuf);
00840 write(mx->fd_out, outbuf, mx->pack_size*2);
00841 ptsinc(&mx->SCR, mx->SCRinc*2);
00842 mx->startup = 1;
00843 } else if (mx->navpack){
00844 uint8_t outbuf[2048];
00845 write_nav_pack(mx->pack_size, mx->extcnt,
00846 mx->SCR, mx->muxr, outbuf);
00847 write(mx->fd_out, outbuf, mx->pack_size);
00848 ptsinc(&mx->SCR, mx->SCRinc);
00849 mx->startup = 1;
00850 } else mx->startup = 0;
00851 }