📄 remux.c
字号:
#include "remux.h"unsigned int bitrates[3][16] ={{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0}, {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};uint32_t freq[4] = {441, 480, 320, 0};static uint32_t samples[4] = { 384, 1152, 0, 0};char *frames[3] = {"I-Frame","P-Frame","B-Frame"};void copy_ptslm(PTS_List *a, PTS_List *b){ a->pos = b->pos; a->PTS = b->PTS; a->dts = b->dts; a->spos = b->spos;}void clear_ptslm(PTS_List *a){ a->pos = 0; a->PTS = 0; a->dts = 0; a->spos = 0; }void init_ptsl(PTS_List *ptsl){ int i; for (i=0;i< MAX_PTS;i++){ clear_ptslm(&ptsl[i]); }}int del_pts(PTS_List *ptsl, int pos, int nr){ int i; int del = 0; for( i = 0; i < nr-1; i++){ if(pos > ptsl[i].pos && pos >= ptsl[i+1].pos) del++; } if(del) for( i = 0; i < nr-del; i++){ copy_ptslm(&ptsl[i], &ptsl[i+del]); } return nr-del;}int del_ptss(PTS_List *ptsl, int pts, int *nb){ int i; int del = 0; int sum = 0; int nr = *nb; for( i = 0; i < nr; i++){ if(pts > ptsl[i].PTS){ del++; sum += ptsl[i].pos; } } if(del) for( i = 0; i < nr-del; i++){ copy_ptslm(&ptsl[i], &ptsl[i+del]); } *nb = nr-del; return sum;}int add_pts(PTS_List *ptsl, uint32_t pts, int pos, int spos, int nr, uint32_t dts){ int i; for ( i=0;i < nr; i++) if (spos && ptsl[i].pos == pos) return nr; if (nr == MAX_PTS) { nr = del_pts(ptsl, ptsl[1].pos+1, nr); } else nr++; i = nr-1; ptsl[i].pos = pos; ptsl[i].spos = spos; ptsl[i].PTS = pts; ptsl[i].dts = dts; return nr;}void add_vpts(Remux *rem, uint8_t *pts){ uint32_t PTS = ntohl(trans_pts_dts(pts)); rem->vptsn = add_pts(rem->vpts_list, PTS, rem->vwrite, rem->awrite, rem->vptsn, PTS);}void add_apts(Remux *rem, uint8_t *pts){ uint32_t PTS = ntohl(trans_pts_dts(pts)); rem->aptsn = add_pts(rem->apts_list, PTS, rem->awrite, rem->vwrite, rem->aptsn, PTS);}void del_vpts(Remux *rem){ rem->vptsn = del_pts(rem->vpts_list, rem->vread, rem->vptsn);}void del_apts(Remux *rem){ rem->aptsn = del_pts(rem->apts_list, rem->aread, rem->aptsn);}void copy_framelm(FRAME_List *a, FRAME_List *b){ a->type = b->type; a->pos = b->pos; a->FRAME = b->FRAME; a->time = b->time; a->pts = b->pts; a->dts = b->dts;}void clear_framelm(FRAME_List *a){ a->type = 0; a->pos = 0; a->FRAME = 0; a->time = 0; a->pts = 0; a->dts = 0; }void init_framel(FRAME_List *framel){ int i; for (i=0;i< MAX_FRAME;i++){ clear_framelm(&framel[i]); }}int del_frame(FRAME_List *framel, int pos, int nr){ int i; int del = 0; for( i = 0; i < nr-1; i++){ if(pos > framel[i].pos && pos >= framel[i+1].pos) del++; } if(del) for( i = 0; i < nr-del; i++){ copy_framelm(&framel[i], &framel[i+del]); } return nr-del;}int add_frame(FRAME_List *framel, uint32_t frame, int pos, int type, int nr, uint32_t time, uint32_t pts, uint32_t dts){ int i; if (nr == MAX_FRAME) { nr = del_frame(framel, framel[1].pos+1, nr); } else nr++; i = nr-1; framel[i].type = type; framel[i].pos = pos; framel[i].FRAME = frame; framel[i].time = time; framel[i].pts = pts; framel[i].dts = dts; return nr;}void add_vframe(Remux *rem, uint32_t frame, long int pos, int type, int time, uint32_t pts, uint32_t dts){ rem->vframen = add_frame(rem->vframe_list, frame, pos, type, rem->vframen, time, pts, dts);}void add_aframe(Remux *rem, uint32_t frame, long int pos, uint32_t pts){ rem->aframen = add_frame(rem->aframe_list, frame, pos, 0, rem->aframen, 0, pts, pts);}void del_vframe(Remux *rem){ rem->vframen = del_frame(rem->vframe_list, rem->vread, rem->vframen);}void del_aframe(Remux *rem){ rem->aframen = del_frame(rem->aframe_list, rem->aread, rem->aframen);}void printpts(uint32_t pts){ fprintf(stderr,"%2d:%02d:%02d.%03d", (int)(pts/90000.)/3600, ((int)(pts/90000.)%3600)/60, ((int)(pts/90000.)%3600)%60, (((int)(pts/90.)%3600000)%60000)%1000 );}void find_vframes( Remux *rem, uint8_t *buf, int l){ int c = 0; int type; uint32_t time = 0; int hour; int min; int sec; u64 pts=0; u64 dts=0; uint32_t tempref = 0; while ( c < l - 6){ if (buf[c] == 0x00 && buf[c+1] == 0x00 && buf[c+2] == 0x01 && buf[c+3] == 0xB8) { c += 4; hour = (int)((buf[c]>>2)& 0x1F); min = (int)(((buf[c]<<4)& 0x30)| ((buf[c+1]>>4)& 0x0F)); sec = (int)(((buf[c+1]<<3)& 0x38)| ((buf[c+2]>>5)& 0x07)); time = 3600*hour + 60*min + sec; if ( rem->time_off){ time = (uint32_t)((u64)time - rem->time_off); hour = time/3600; min = (time%3600)/60; sec = (time%3600)%60; /* buf[c] |= (hour & 0x1F) << 2; buf[c] |= (min & 0x30) >> 4; buf[c+1] |= (min & 0x0F) << 4; buf[c+1] |= (sec & 0x38) >> 3; buf[c+2] |= (sec & 0x07) >> 5;*/ } rem->group++; rem->groupframe = 0; } if ( buf[c] == 0x00 && buf[c+1] == 0x00 && buf[c+2] == 0x01 && buf[c+3] == 0x00) { c += 4; tempref = (buf[c+1]>>6) & 0x03; tempref |= buf[c] << 2; type = ((buf[c+1]&0x38) >>3); if ( rem->video_info.framerate){ pts = ((u64)rem->vframe + tempref + 1 - rem->groupframe ) * 90000ULL /rem->video_info.framerate + rem->vpts_off; dts = (u64)rem->vframe * 90000ULL/ rem->video_info.framerate + rem->vpts_off; /* fprintf(stderr,"MYPTS:");printpts((uint32_t)pts-rem->vpts_off); fprintf(stderr," REALPTS:"); printpts(rem->vpts_list[rem->vptsn-1].PTS-rem->vpts_off); fprintf(stderr," DIFF:"); printpts(pts-(u64)rem->vpts_list[rem->vptsn-1].PTS); fprintf(stderr," DIST: %4d",-rem->vpts_list[rem->vptsn-1].pos+(rem->vwrite+c-4)); //fprintf(stderr," ERR: %3f",(double)(-rem->vpts_list[rem->vptsn-1].PTS+pts)/(rem->vframe+1)); fprintf(stderr,"\r"); */ rem->vptsn = add_pts(rem->vpts_list,(uint32_t)pts ,rem->vwrite+c-4, rem->awrite, rem->vptsn, (uint32_t)dts); } rem->vframe++; rem->groupframe++; add_vframe( rem, rem->vframe, rem->vwrite+c, type, time, pts, dts); } else c++; }}void find_aframes( Remux *rem, uint8_t *buf, int l){ int c = 0; u64 pts = 0; int sam; uint32_t fr; while ( c < l - 2){ if ( buf[c] == 0xFF && (buf[c+1] & 0xF8) == 0xF8) { c += 2; if ( rem->audio_info.layer >= 0){ sam = samples[3-rem->audio_info.layer]; fr = freq[rem->audio_info.frequency] ; pts = ( (u64)rem->aframe * sam * 900ULL)/fr + rem->apts_off; /* fprintf(stderr,"MYPTS:");printpts((uint32_t)pts-rem->apts_off); fprintf(stderr," REALPTS:"); printpts(rem->apts_list[rem->aptsn-1].PTS-rem->apts_off); fprintf(stderr," DIFF:"); printpts((uint32_t)((u64)rem->apts_list[rem->aptsn-1].PTS-pts)); fprintf(stderr," DIST: %4d",-rem->apts_list[rem->aptsn-1].pos+(rem->awrite+c-2)); fprintf(stderr,"\r"); */ rem->aptsn = add_pts(rem->apts_list,(uint32_t)pts ,rem->awrite+c-2, rem->vwrite, rem->aptsn, (uint32_t)pts); } rem->aframe++; add_aframe( rem, rem->aframe, rem->awrite+c, pts); } else c++; }}int refill_buffy(Remux *rem){ pes_packet pes; int count = 0; int acount, vcount; ringbuffy *vbuf = &rem->vid_buffy; ringbuffy *abuf = &rem->aud_buffy; int fin = rem->fin; acount = abuf->size-ring_rest(abuf); vcount = vbuf->size-ring_rest(vbuf); while ( acount > MAX_PLENGTH && vcount > MAX_PLENGTH && count < 10){ int neof; count++; init_pes(&pes); if ((neof = read_pes(fin,&pes)) <= 0) return -1; switch(pes.stream_id){ case AUDIO_STREAM_S ... AUDIO_STREAM_E: rem->apes++; if( rem->audio_info.layer < 0 && (pes.flags2 & PTS_DTS) ) add_apts(rem, pes.pts); find_aframes( rem, pes.pes_pckt_data, pes.length); ring_write(abuf,(char *)pes.pes_pckt_data,pes.length); rem->awrite += pes.length; break; case VIDEO_STREAM_S ... VIDEO_STREAM_E: rem->vpes++; if( !rem->video_info.framerate && (pes.flags2 & PTS_DTS) ) add_vpts(rem, pes.pts); find_vframes( rem, pes.pes_pckt_data, pes.length); ring_write(vbuf,(char *)pes.pes_pckt_data,pes.length); rem->vwrite += pes.length; break; } acount = abuf->size-ring_rest(abuf); vcount = vbuf->size-ring_rest(vbuf); kill_pes(&pes); } if (count < 10) return 0; return 1;}int vring_read( Remux *rem, uint8_t *buf, int l){ int c = 0; int r = 0; if (ring_rest(&rem->vid_buffy) <= l) r = refill_buffy(rem); if (r) return -1; c = ring_read(&rem->vid_buffy, (char *) buf, l); rem->vread += c; del_vpts(rem); del_vframe(rem); return c;}int aring_read( Remux *rem, uint8_t *buf, int l){ int c = 0; int r = 0; if (ring_rest(&rem->aud_buffy) <= l) r = refill_buffy(rem); if (r) return -1; c = ring_read(&rem->aud_buffy, (char *)buf, l); rem->aread += c; del_apts(rem); del_aframe(rem); return c;}int vring_peek( Remux *rem, uint8_t *buf, int l, long off){ int c = 0; if (ring_rest(&rem->vid_buffy) <= l) refill_buffy(rem); c = ring_peek(&rem->vid_buffy, (char *) buf, l, off); return c;}int aring_peek( Remux *rem, uint8_t *buf, int l, long off){ int c = 0; if (ring_rest(&rem->aud_buffy) <= l) refill_buffy(rem); c = ring_peek(&rem->aud_buffy, (char *)buf, l, off); return c;}int get_video_info(Remux *rem){ uint8_t buf[12]; uint8_t *headr; int found = 0; int sw; long off = 0; int form = -1; ringbuffy *vid_buffy = &rem->vid_buffy; VideoInfo *vi = &rem->video_info; while (found < 4 && ring_rest(vid_buffy)){ uint8_t b[3]; vring_peek( rem, b, 4, 0); if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 && b[3] == 0xb3) found = 4; else { off++; vring_read( rem, b, 1); } } rem->vframe = rem->vframen-1; if (! found) return -1; buf[0] = 0x00; buf[1] = 0x00; buf[2] = 0x01; buf[3] = 0xb3; headr = buf+4; if(vring_peek(rem, buf, 12, 0) < 12) return -1; vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]); sw = (int)((headr[3]&0xF0) >> 4) ; switch( sw ){ case 1: fprintf(stderr,"Videostream: ASPECT: 1:1"); vi->aspect_ratio = 100; break; case 2: fprintf(stderr,"Videostream: ASPECT: 4:3"); vi->aspect_ratio = 133; break; case 3: fprintf(stderr,"Videostream: ASPECT: 16:9"); vi->aspect_ratio = 177; break; case 4: fprintf(stderr,"Videostream: ASPECT: 2.21:1"); vi->aspect_ratio = 221; break; case 5 ... 15: fprintf(stderr,"Videostream: ASPECT: reserved"); vi->aspect_ratio = 0; break; default: vi->aspect_ratio = 0; return -1; } fprintf(stderr," Size = %dx%d",vi->horizontal_size,vi->vertical_size); sw = (int)(headr[3]&0x0F); switch ( sw ) { case 1: fprintf(stderr," FRate: 23.976 fps"); vi->framerate = 24000/1001.; form = -1; break; case 2: fprintf(stderr," FRate: 24 fps"); vi->framerate = 24; form = -1; break; case 3: fprintf(stderr," FRate: 25 fps"); vi->framerate = 25; form = VIDEO_MODE_PAL; break; case 4: fprintf(stderr," FRate: 29.97 fps"); vi->framerate = 30000/1001.; form = VIDEO_MODE_NTSC; break; case 5: fprintf(stderr," FRate: 30 fps"); vi->framerate = 30; form = VIDEO_MODE_NTSC; break; case 6: fprintf(stderr," FRate: 50 fps"); vi->framerate = 50; form = VIDEO_MODE_PAL; break; case 7: fprintf(stderr," FRate: 60 fps"); vi->framerate = 60; form = VIDEO_MODE_NTSC; break; } rem->dts_delay = (int)(7.0/vi->framerate/2.0*90000); vi->bit_rate = 400*(((headr[4] << 10) & 0x0003FC00UL) | ((headr[5] << 2) & 0x000003FCUL) | (((headr[6] & 0xC0) >> 6) & 0x00000003UL)); fprintf(stderr," BRate: %.2f Mbit/s",(vi->bit_rate)/1000000.); fprintf(stderr,"\n"); vi->video_format = form; /* marker_bit (&video_bs, 1); vi->vbv_buffer_size = getbits (&video_bs, 10); vi->CSPF = get1bit (&video_bs); */ return form;}int get_audio_info( Remux *rem){ uint8_t *headr; uint8_t buf[3]; long off = 0; int found = 0; ringbuffy *aud_buffy = &rem->aud_buffy; AudioInfo *ai = &rem->audio_info; while(!ring_rest(aud_buffy) && !refill_buffy(rem)); while (found < 2 && ring_rest(aud_buffy)){ uint8_t b[2]; refill_buffy(rem); aring_peek( rem, b, 2, 0); if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) found = 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -