📄 remux.c
字号:
else { off++; aring_read( rem, b, 1); } } if (!found) return -1; rem->aframe = rem->aframen-1; if (aring_peek(rem, buf, 3, 0) < 1) return -1; headr = buf+2; ai->layer = (buf[1] & 0x06) >> 1; fprintf(stderr,"Audiostream: Layer: %d", 4-ai->layer); ai->bit_rate = bitrates[(3-ai->layer)][(headr[0] >> 4 )]*1000; if (ai->bit_rate == 0) fprintf (stderr," Bit rate: free"); else if (ai->bit_rate == 0xf) fprintf (stderr," BRate: reserved"); else fprintf (stderr," BRate: %d kb/s", ai->bit_rate/1000); ai->frequency = (headr[0] & 0x0c ) >> 2; if (ai->frequency == 3) fprintf (stderr, " Freq: reserved\n"); else fprintf (stderr," Freq: %2.1f kHz\n", freq[ai->frequency]/10.); return 0;}void init_remux(Remux *rem, int fin, int fout, int mult){ rem->video_info.framerate = 0; rem->audio_info.layer = -1; rem->fin = fin; rem->fout = fout; ring_init(&rem->vid_buffy, 40*BUFFYSIZE*mult); ring_init(&rem->aud_buffy, BUFFYSIZE*mult); init_ptsl(rem->vpts_list); init_ptsl(rem->apts_list); init_framel(rem->vframe_list); init_framel(rem->aframe_list); rem->vptsn = 0; rem->aptsn = 0; rem->vframen = 0; rem->aframen = 0; rem->vframe = 0; rem->aframe = 0; rem->vcframe = 0; rem->acframe = 0; rem->vpts = 0; rem->vdts = 0; rem->apts_off = 0; rem->vpts_off = 0; rem->apts_delay= 0; rem->vpts_delay= 0; rem->dts_delay = 0; rem->apts = 0; rem->vpes = 0; rem->apes = 0; rem->vpts_old = 0; rem->apts_old = 0; rem->SCR = 0; rem->vwrite = 0; rem->awrite = 0; rem->vread = 0; rem->aread = 0; rem->group = 0; rem->groupframe= 0; rem->pack_size = 0; rem->muxr = 0; rem->time_off = 0;}uint32_t bytes2pts(int bytes, int rate){ if (bytes < 0xFFFFFFFFUL/720000UL) return (uint32_t)(bytes*720000UL/rate); else return (uint32_t)(bytes/rate*720000UL);}long pts2bytes( uint32_t pts, int rate){ if (pts < 0xEFFFFFFFUL/rate) return (pts*rate/720000); else return (pts* (rate/720000));}int write_audio_pes( Remux *rem, uint8_t *buf, int *alength){ int add; int pos = 0; int p = 0; uint32_t pts = 0; int stuff = 0; int length = *alength; if (!length) return 0; p = PS_HEADER_L1+PES_H_MIN; if (rem->apts_old != rem->apts){ pts = (uint32_t)((u64)rem->apts + rem->apts_delay - rem->apts_off); p += 5; } if ( length+p >= rem->pack_size){ length = rem->pack_size; } else { if (rem->pack_size-length-p <= PES_MIN){ stuff = rem->pack_size - length; length = rem->pack_size; } else length = length+p; } pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0); pos += write_pes_header( 0xC0, length-pos, pts, buf+pos, stuff); add = aring_read( rem, buf+pos, length-pos); *alength = add; if (add < 0) return -1; pos += add; rem->apts_old = rem->apts; rem->apts = rem->apts_list[0].PTS; if (pos+PES_MIN < rem->pack_size){ pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0, buf+pos, 0); pos = rem->pack_size; } if (pos != rem->pack_size) { fprintf(stderr,"apos: %d\n",pos); exit(1); } return pos;}int write_video_pes( Remux *rem, uint8_t *buf, int *vlength){ int add; int pos = 0; int p = 0; uint32_t pts = 0; uint32_t dts = 0; int stuff = 0; int length = *vlength; long diff = 0; if (! length) return 0; p = PS_HEADER_L1+PES_H_MIN; if (rem->vpts_old != rem->vpts){ pts = (uint32_t)((u64)rem->vpts + rem->vpts_delay - rem->vpts_off); p += 5; } if ( length+p >= rem->pack_size){ length = rem->pack_size; } else { if (rem->pack_size - length - p <= PES_MIN){ stuff = rem->pack_size - length; length = rem->pack_size; } else length = length+p; } pos = write_ps_header(buf,rem->SCR,rem->muxr, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0); pos += write_pes_header( 0xE0, length-pos, pts, buf+pos, stuff); add = vring_read( rem, buf+pos, length-pos); *vlength = add; if (add < 0) return -1; pos += add; rem->vpts_old = rem->vpts; dts = rem->vdts; rem->vpts = rem->vpts_list[0].PTS; rem->vdts = rem->vpts_list[0].dts; if ( diff > 0) rem->SCR += diff; if (pos+PES_MIN < rem->pack_size){ // fprintf(stderr,"vstuffing: %d \n",rem->pack_size-pos); pos += write_pes_header( PADDING_STREAM, rem->pack_size-pos, 0, buf+pos, 0); pos = rem->pack_size; } return pos;}void print_info( Remux *rem , int ret){ int newtime = 0; static int time = 0; int i = 0; while(! newtime && i < rem->vframen) { if( (newtime = rem->vframe_list[i].time)) break; i++; } if (newtime) time = newtime; fprintf(stderr,"SCR:"); printpts(rem->SCR); fprintf(stderr," VDTS:"); printpts((uint32_t)((u64)rem->vdts - rem->vpts_off + rem->vpts_delay)); fprintf(stderr," APTS:"); printpts((uint32_t)((u64)rem->apts - rem->apts_off + rem->apts_delay)); fprintf(stderr," TIME:%2d:", time/3600); fprintf(stderr,"%02d:", (time%3600)/60); fprintf(stderr,"%02d", (time%3600)%60); if (ret) fprintf(stderr,"\n"); else fprintf(stderr,"\r");}void remux(int fin, int fout, int pack_size, int mult){ Remux rem; long ptsdiff; uint8_t buf[MAX_PACK_L]; long pos = 0; int r = 0; int i, r1, r2; long packets = 0; uint8_t mpeg_end[4] = { 0x00, 0x00, 0x01, 0xB9 }; uint32_t SCR_inc = 0; int data_size; long vbuf, abuf; long vbuf_max, abuf_max; PTS_List abufl[MAX_PTS]; PTS_List vbufl[MAX_PTS]; int abufn = 0; int vbufn = 0; u64 pts_d = 0; int ok_audio; int ok_video; uint32_t apos = 0; uint32_t vpos = 0; int vpack_size = 0; int apack_size = 0; init_ptsl(abufl); init_ptsl(vbufl); init_remux(&rem, fin, fout, mult); rem.pack_size = pack_size; data_size = pack_size - MAX_H_SIZE; fprintf(stderr,"pack_size: %d header_size: %d data size: %d\n", pack_size, MAX_H_SIZE, data_size); refill_buffy(&rem); fprintf(stderr,"Package size: %d\n",pack_size); if ( get_video_info(&rem) < 0 ){ fprintf(stderr,"ERROR: Can't find valid video stream\n"); exit(1); } i = 0; while(! rem.time_off && i < rem.vframen) { if( (rem.time_off = rem.vframe_list[i].time)) break; i++; } if ( get_audio_info(&rem) < 0 ){ fprintf(stderr,"ERROR: Can't find valid audio stream\n"); exit(1); } rem.vpts = rem.vpts_list[0].PTS; rem.vdts = rem.vpts; rem.vpts_off = rem.vpts; fprintf(stderr,"Video start PTS = %fs \n",rem.vpts_off/90000.); rem.apts = rem.apts_list[0].PTS; rem.apts_off = rem.apts; ptsdiff = rem.vpts - rem.apts; if (ptsdiff > 0) rem.vpts_off -= ptsdiff; else rem.apts_off -= -ptsdiff; fprintf(stderr,"Audio start PTS = %fs\n",rem.apts_off/90000.); fprintf(stderr,"Difference Video - Audio = %fs\n",ptsdiff/90000.); fprintf(stderr,"Time offset = %ds\n",rem.time_off); rem.muxr = (rem.video_info.bit_rate + rem.audio_info.bit_rate)/400; fprintf(stderr,"MUXRATE: %.2f Mb/sec\n",rem.muxr/2500.); SCR_inc = 1800 * pack_size / rem.muxr; r = 0; while ( rem.vptsn < 2 && !r) r = refill_buffy(&rem); r = 0; while ( rem.aptsn < 2 && !r) r = refill_buffy(&rem); //rem.vpts_delay = (uint32_t)(2*90000ULL* (u64)pack_size/rem.muxr); rem.vpts_delay = rem.dts_delay; rem.apts_delay = rem.vpts_delay; vbuf_max = 29440; abuf_max = 4096; vbuf = 0; abuf = 0; pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 0xC0, 0, 32, 0xE0, 1, 230); pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, buf+pos,0); pos = rem.pack_size; write( fout, buf, pos); apos = rem.aread; vpos = rem.vread; print_info( &rem, 1 ); while( ring_rest(&rem.aud_buffy) && ring_rest(&rem.vid_buffy) ){ uint32_t next_apts; uint32_t next_vdts; int asize, vsize; r1 = 0; r2 = 0; while ( rem.aframen < 2 && !r1) r1 = refill_buffy(&rem); while ( rem.vframen < 2 && !r2) r2 = refill_buffy(&rem); if (r1 && r2) break; if ( !r1 && apos <= rem.aread) apos = rem.aframe_list[1].pos; if ( !r2 && vpos <= rem.vread) vpos = rem.vframe_list[1].pos; apack_size = apos - rem.aread; vpack_size = vpos - rem.vread; next_vdts = (uint32_t)((u64)rem.vdts + rem.vpts_delay - rem.vpts_off) ; ok_video = ( rem.SCR < next_vdts); next_apts = (uint32_t)((u64)rem.apts + rem.apts_delay - rem.apts_off) ; ok_audio = ( rem.SCR < next_apts); asize = (apack_size > data_size ? data_size: apack_size); vsize = (vpack_size > data_size ? data_size: vpack_size); fprintf(stderr,"vframen: %d aframen: %d v_ok: %d a_ok: %d v_buf: %d a_buf: %d vpacks: %d apacks: %d\n",rem.vframen,rem.aframen, ok_video, ok_audio, (int)vbuf,(int)abuf,vsize, asize); if( vbuf+vsize < vbuf_max && vsize && ok_audio ){ fprintf(stderr,"1 "); pos = write_video_pes( &rem, buf, &vpack_size); write( fout, buf, pos); vbuf += vpack_size; vbufn = add_pts( vbufl, rem.vdts, vpack_size, 0, vbufn, 0); packets++; } else if ( abuf+asize < abuf_max && asize && ok_video ){ fprintf(stderr,"2 "); pos = write_audio_pes( &rem, buf, &apack_size); write( fout, buf, pos); abuf += apack_size; abufn = add_pts( abufl, rem.apts, apack_size, 0, abufn, 0); packets++; } else if ( abuf+asize < abuf_max && asize && !ok_audio){ fprintf(stderr,"3 "); pos = write_audio_pes( &rem, buf, &apack_size); write( fout, buf, pos); abuf += apack_size; abufn = add_pts( abufl, rem.apts, apack_size, 0, abufn, 0); packets++; } else if (vbuf+vsize < vbuf_max && vsize && !ok_video){ fprintf(stderr,"4 "); pos = write_video_pes( &rem, buf, &vpack_size); write( fout, buf, pos); vbuf += vpack_size; vbufn = add_pts( vbufl, rem.vdts, vpack_size, 0, vbufn, 0); packets++; } else { fprintf(stderr,"5 "); pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0); pos += write_pes_header( PADDING_STREAM, pack_size-pos, 0, buf+pos, 0); write( fout, buf, pos); } //fprintf(stderr,"vbufn: %d abufn: %d ", vbufn,abufn); //fprintf(stderr,"vbuf: %5d abuf: %4d\n", vbuf,abuf); if (rem.SCR > rem.vdts+rem.vpts_off -rem.vpts_delay) rem.SCR = rem.vdts-rem.vpts_off; rem.SCR = (uint32_t)((u64) rem.SCR + SCR_inc); if ( rem.apts_off + rem.SCR < rem.apts_delay ) pts_d = 0; else pts_d = (u64) rem.SCR + rem.apts_off - rem.apts_delay; abuf -= del_ptss( abufl, (uint32_t) pts_d, &abufn); if ( rem.vpts_off + rem.SCR < rem.vpts_delay ) pts_d = 0; else pts_d = (u64) rem.SCR + rem.vpts_off - rem.vpts_delay; vbuf -= del_ptss( vbufl, (uint32_t) pts_d, &vbufn); print_info( &rem, 1); //fprintf(stderr,"vbufn: %d abufn: %d ", vbufn,abufn); //fprintf(stderr,"vbuf: %5d abuf: %4d\n\n", vbuf,abuf); } pos = write_ps_header(buf,rem.SCR,rem.muxr, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0); pos += write_pes_header( PADDING_STREAM, pack_size-pos-4, 0, buf+pos, 0); pos = rem.pack_size-4; write( fout, buf, pos); write( fout, mpeg_end, 4); fprintf(stderr,"\ndone\n");}typedef struct pes_buffer_s{ ringbuffy pes_buffy; uint8_t type; PTS_List pts_list[MAX_PTS]; FRAME_List frame_list[MAX_FRAME]; int pes_size; uint64_t written; uint64_t read;} PESBuffer;void init_PESBuffer(PESBuffer *pbuf, int pes_size, int buf_size, uint8_t type){ init_framel( pbuf->frame_list); init_ptsl( pbuf->pts_list); ring_init( &pbuf->pes_buffy, buf_size); pbuf->pes_size = pes_size; pbuf->type = type; pbuf->written = 0; pbuf->read = 0;} #define MAX_PBUF 4typedefstruct remux_s{ PESBuffer pbuf_list[MAX_PBUF]; int num_pbuf;} REMUX;void init_REMUX(REMUX *rem){ rem->num_pbuf = 0;}#define REPACK 2048 #define ABUF_SIZE REPACK*1024#define VBUF_SIZE REPACK*10240void remux_main(uint8_t *buf, int count, p2p *p){ int i, b; int bufsize = 0; PESBuffer *pbuf; REMUX *rem = (REMUX *) p->data; uint8_t type = buf[3]; int *npbuf = &(rem->num_pbuf); switch ( type ){ case PRIVATE_STREAM1: bufsize = ABUF_SIZE; case VIDEO_STREAM_S ... VIDEO_STREAM_E: if (!bufsize) bufsize = VBUF_SIZE; case AUDIO_STREAM_S ... AUDIO_STREAM_E: if (!bufsize) bufsize = ABUF_SIZE; b = -1; for ( i = 0; i < *npbuf; i++){ if ( type == rem->pbuf_list[i].type ){ b = i; break; } } if (b < 0){ if ( *npbuf < MAX_PBUF ){ init_PESBuffer(&rem->pbuf_list[*npbuf], p->repack+6, bufsize, type); b = *npbuf; (*npbuf)++; } else { fprintf(stderr,"Not enough PES buffers\n"); exit(1); } } break; default: return; } pbuf = &(rem->pbuf_list[b]); if (ring_write(&(pbuf->pes_buffy),(char *)buf,count) != count){ fprintf(stderr,"buffer overflow type 0x%2x\n",type); exit(1); } else { pbuf->written += count; if ((p->flag2 & PTS_DTS_FLAGS)){ uint32_t PTS = ntohl(trans_pts_dts(p->pts)); add_pts(pbuf->pts_list, PTS, pbuf->written, pbuf->written, 0, 0); } p->flag2 = 0; }}void output_mux(p2p *p) { int i, filling; PESBuffer *pbuf; ringbuffy *pes_buffy; REMUX *rem = (REMUX *) p->data; int repack = p->repack; int npbuf = rem->num_pbuf; for ( i = 0; i < npbuf; i++){ pbuf = &(rem->pbuf_list[i]); pes_buffy = &pbuf->pes_buffy; filling = pes_buffy->size - ring_rest(pes_buffy); if (filling/(2 *repack)){ pbuf->read += ring_read_file(pes_buffy, p->fd1, (filling/repack)*repack); } }}#define SIZE 32768void remux2(int fdin, int fdout){ p2p p; int count = 1; uint8_t buf[SIZE]; uint64_t length = 0; uint64_t l = 0; int verb = 0; REMUX rem; init_p2p(&p, remux_main, REPACK); p.fd1 = fdout; p.data = (void *) &rem; if (fdin != STDIN_FILENO) verb = 1; if (verb) { length = lseek(fdin, 0, SEEK_END); lseek(fdin,0,SEEK_SET); } while (count > 0){ count = read(fdin,buf,SIZE); l += count; if (verb) fprintf(stderr,"Writing %2.2f %%\r", 100.*l/length); get_pes(buf,count,&p,pes_repack); output_mux(&p); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -