📄 muxer_mpeg.c
字号:
if(priv->vframerate > 0) buf[7] = (buf[7] & 0xf0) | priv->vframerate; if(priv->vbitrate > 0) { buf[8] = (priv->vbitrate >> 10); buf[9] = (priv->vbitrate >> 2); buf[10] = (buf[10] & 0x3f) | (unsigned char) ((priv->vbitrate & 0x4) << 2); }}static void patch_panscan(muxer_priv_t *priv, unsigned char *buf){ //patches sequence display extension (display_horizontal_size and display_vertical_size) //1: int offset = 1; if(buf[0] & 0x01) offset += 3; if(priv->panscan_width > 0) { buf[offset] = (priv->panscan_width >> 6); buf[offset+1] = ((priv->panscan_width & 0x3F) << 2) | (buf[offset + 1] & 0x03); } offset++; if(priv->panscan_height > 0) { buf[offset] = (priv->panscan_height >> 13) << 7; buf[offset+1] = (priv->panscan_height >> 5) & 0xFF; buf[offset+2] = ((priv->panscan_height & 0x1F) << 3) | (buf[offset+2] & 0x07); }}#define max(a, b) ((a) >= (b) ? (a) : (b))#define min(a, b) ((a) <= (b) ? (a) : (b))static uint32_t get_audio_frame_size(muxer_headers_t *spriv, uint8_t *buf, int format, int samples_ps){ uint32_t sz, tmp, spf; #ifdef USE_LIBA52#include "../liba52/a52.h" if(format == 0x2000) { int t1, t2, t3; sz = (uint32_t) a52_syncinfo(buf, &t1, &t2, &t3); if(sz) return sz; }#endif if(format == 0x2000) spf = 1536; else if((format == 0x55) && (samples_ps < 32000)) spf = 576; else spf = 1152; tmp = spriv->bitrate * spf; sz = tmp / samples_ps; if(sz % 2) sz++; return sz;}static int reorder_frame(muxer_headers_t *spriv, uint8_t *ptr, size_t len, uint8_t pt, uint32_t temp_ref, uint64_t idur){ uint16_t idx = 0, move=0; /* HOW TO REORDER FRAMES IN DECODING ORDER: current frame is n IF pt(n)==I or P and n>0 && temp_ref(n) > temp_ref(n-1) && pt(n-1 .. n-m)==B then insert frame n before frame n-m and shift forward the others */ idx = spriv->framebuf_used; if(spriv->reorder) { //stores the frame in decoding order if((idx > 0) && ((pt == I_FRAME) || (pt == P_FRAME))) { if((spriv->framebuf[idx - 1].type == B_FRAME) && (spriv->framebuf[idx - 1].temp_ref == temp_ref-1)) { while((spriv->framebuf[idx - 1].type == B_FRAME) && (spriv->framebuf[idx - 1].temp_ref < temp_ref) && (idx > 0)) idx--; move = spriv->framebuf_used - idx; //from idx there are 'move' frames to move forward } } } //now idx is the position where we should store the frame if(idx+move >= spriv->framebuf_cnt) { //realloc //fprintf(stderr, "\nREALLOC1: %d\n", (int) spriv->framebuf_cnt+1); spriv->framebuf = (mpeg_frame_t*) realloc(spriv->framebuf, (spriv->framebuf_cnt+1)*sizeof(mpeg_frame_t)); if(spriv->framebuf == NULL) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(idx), abort\n"); return 0; } spriv->framebuf[spriv->framebuf_cnt].size = 0; spriv->framebuf[spriv->framebuf_cnt].alloc_size = 0; spriv->framebuf[spriv->framebuf_cnt].buffer = (uint8_t*) malloc(len); if(spriv->framebuf[spriv->framebuf_cnt].buffer == NULL) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n"); return 0; } spriv->framebuf[spriv->framebuf_cnt].alloc_size = len; spriv->framebuf_cnt++; } while(move > 0) { mpeg_frame_t f; f = spriv->framebuf[move + idx]; spriv->framebuf[move + idx] = spriv->framebuf[move + idx - 1]; spriv->framebuf[move + idx - 1] = f; move--; } if(spriv->framebuf[idx].alloc_size < len) { spriv->framebuf[idx].buffer = realloc(spriv->framebuf[idx].buffer, len); if(spriv->framebuf[idx].buffer == NULL) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n"); return 0; } spriv->framebuf[idx].alloc_size = len; } mp_msg(MSGT_MUXER, MSGL_DBG2, "\nIDX: %u, type: %c, temp_ref: %u, ptr: %p, len: %u, alloc: %u, buffer: %p\n", (uint32_t) idx, FTYPE(pt), temp_ref, ptr, (uint32_t) len, (uint32_t) spriv->framebuf[idx].alloc_size, spriv->framebuf[idx].buffer); memcpy(spriv->framebuf[idx].buffer, ptr, len); spriv->framebuf[idx].size = len; spriv->framebuf[idx].temp_ref = temp_ref; spriv->framebuf[idx].type = pt; spriv->framebuf[idx].idur = idur; spriv->framebuf_used++; return 1;}static uint32_t dump_audio(muxer_t *muxer, muxer_stream_t *as, uint32_t abytes, int force){ uint32_t len = 0, sz; uint64_t num_frames = 0, next_pts; uint16_t rest; int64_t tmp; double delta_pts; muxer_priv_t *priv = (muxer_priv_t *) muxer->priv; muxer_headers_t *apriv = (muxer_headers_t*) as->priv; if((abytes < apriv->frame_size) && (! force)) //pl_size //if((abytes < apriv->max_pl_size) && (! force)) //pl_size { apriv->is_late = 1; mp_msg(MSGT_MUXER, MSGL_V, "NOT SAVING: %u bytes\n", abytes); return 0; } abytes = min(abytes, as->b_buffer_len); //available bytes if(! abytes) return 0; if(as->ckid == be2me_32(0x1bd)) apriv->has_pes_priv_headers = 4; else apriv->has_pes_priv_headers = 0; rest = (apriv->size % apriv->frame_size); if(rest) rest = apriv->frame_size - rest; sz = priv->packet_size - calc_pack_hlen(priv, apriv); //how many payload bytes we are about to write num_frames = (sz + apriv->frame_size - 1 - rest) / apriv->frame_size; mp_msg(MSGT_MUXER, MSGL_V, "\nAUDIO: tot=%llu, sz=%u bytes, FRAMES: %llu * %u, REST: %u, DELTA_PTS: %u\n", apriv->size, sz, num_frames, (uint32_t) apriv->frame_size, (uint32_t) rest, (uint32_t) ((num_frames * apriv->delta_pts) >> 10)); next_pts = ((uint64_t) (num_frames * apriv->delta_pts)) + apriv->pts; if(((priv->scr + (63000*1024)) < next_pts) && (priv->scr < apriv->pts) && (! force)) { apriv->is_late = 1; return 0; } if(as->ckid == be2me_32(0x1bd)) { apriv->pes_priv_headers[0] = 0x80; apriv->pes_priv_headers[1] = num_frames; apriv->pes_priv_headers[2] = ((rest+1) >> 8) & 0xff; //256 * 0 ... apriv->pes_priv_headers[3] = (rest+1) & 0xff; // + 1 byte(s) to skip } if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0) apriv->buffer_size = 4*1024; if(apriv->pts < priv->scr) mp_msg(MSGT_MUXER, MSGL_ERR, "\nERROR: SCR: %llu, APTS: %llu, DELTA=-%.3lf secs\n", priv->scr, apriv->pts, (double) ((priv->scr - apriv->pts)/92160000.0)); len = write_mpeg_pack(muxer, as, muxer->file, &(as->b_buffer[as->b_buffer_ptr]), abytes, 0); if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0) apriv->buffer_size = 0; apriv->size += len; apriv->pts = next_pts; mp_msg(MSGT_MUXER, MSGL_DBG2, "NUM_FRAMES: %llu\n", num_frames); tmp = apriv->pts - priv->scr; if((abs(tmp) > (63000*1024)) || (apriv->pts <= priv->scr)) { double d; d = (double) apriv->frame_size / (double) apriv->bitrate; d *= (tmp - (63000*1024)); apriv->compensate = (uint32_t) d; if(abs(tmp) > 92160000) //usually up to 1 second it still acceptable mp_msg(MSGT_MUXER, MSGL_ERR, "\nWARNING: SCR: %llu, APTS: %llu, DELTA=%.3lf secs, BYTES=%d\n", priv->scr, apriv->pts, (((double) tmp)/92160000.0), apriv->compensate); } mp_msg(MSGT_MUXER, MSGL_V, "\nWRITTEN AUDIO: %u bytes, TIMER: %.3lf, FRAMES: %llu * %u, DELTA_PTS: %.3lf\n", len, (double) (apriv->pts/92160000), num_frames, (uint32_t) apriv->frame_size, delta_pts); as->b_buffer_ptr += len; as->b_buffer_len -= len; if(as->b_buffer_len > 0) memmove(as->b_buffer, &(as->b_buffer[as->b_buffer_ptr]), as->b_buffer_len); as->b_buffer_ptr = 0; return len;}static void drop_delayed_audio(muxer_t *muxer, muxer_stream_t *as, int64_t size){ //muxer_priv_t *priv = (muxer_priv_t *) muxer->priv; muxer_headers_t *apriv = (muxer_headers_t *) as->priv; int64_t size1, div, rest; //initial value double rest_pts; div = size / apriv->frame_size; rest = size % apriv->frame_size; if(rest >= apriv->frame_size / 2) size1 = (div+1) * apriv->frame_size; else size1 = (div) * apriv->frame_size; fprintf(stderr, "SIZE1: %llu, LEN: %llu\n", size1, (uint64_t)as->b_buffer_len); size1 = min(size1, as->b_buffer_len); memmove(as->b_buffer, &(as->b_buffer[size]), as->b_buffer_len - size1); as->b_buffer_len -= size1; rest = size1 - size; rest_pts = (double) rest / (double) apriv->bitrate; apriv->pts += (int64_t) (92160000.0 * rest_pts); mp_msg(MSGT_MUXER, MSGL_V, "DROPPED: %lld bytes, REST= %lld, REST_PTS: %.3lf, AUDIO_PTS%.3lf\n", size1, rest, rest_pts, (double) (apriv->pts/92160000.0));}static void save_delayed_audio(muxer_t *muxer, muxer_stream_t *as, uint64_t dur){ muxer_priv_t *priv = (muxer_priv_t *) muxer->priv; muxer_headers_t *apriv = (muxer_headers_t *) as->priv; uint64_t init_pts, last_pts; //initial value init_pts = apriv->pts; mp_msg(MSGT_MUXER, MSGL_V, "DUR: %llu, DIFF: %llu\n", dur, apriv->pts - init_pts); while(dur > apriv->pts - init_pts) { priv->scr = (92160000 * apriv->size) / apriv->bitrate; last_pts = apriv->pts; dump_audio(muxer, as, as->b_buffer_len, 0); mp_msg(MSGT_MUXER, MSGL_V, "DUR: %llu, DIFF: %llu, SCR: %llu\n", dur, apriv->pts - init_pts, priv->scr); } //priv->init_delay_pts = last_pts; priv->init_delay_pts = (90 * 1024 * abs(conf_init_adelay)) + apriv->init_pts - (90 * 1024 * abs(conf_init_vpts)); if(priv->init_delay_pts <= priv->scr) priv->init_delay_pts = last_pts; mp_msg(MSGT_MUXER, MSGL_INFO, "INIT_VPTS: %llu (%.3lf)\n", priv->init_delay_pts, (double) (priv->init_delay_pts/92160000.0));}static inline void update_scr(muxer_priv_t *priv, uint32_t len, uint32_t totlen, double mult){ uint64_t delta_scr; double perc; perc = (double) len / (double) totlen; delta_scr = (uint64_t) (mult * perc); priv->scr += delta_scr; mp_msg(MSGT_MUXER, MSGL_V, "UPDATE SCR TO %llu (%.3lf): mult is %.3lf, perc: %.3lf, %u/%u, delta: %llu\n", priv->scr, (double) (priv->scr/92160000.0), mult, perc, len, totlen, delta_scr);}static int calc_frames_to_flush(muxer_headers_t *vpriv){ int n, found = 0; if(vpriv->framebuf_used > 0) { n = 0; //let's count how many frames we'll store in the next pack sequence mp_msg(MSGT_MUXER, MSGL_V, "\n"); while(n < vpriv->framebuf_used) { mp_msg(MSGT_MUXER, MSGL_V, "n=%d, type=%c, temp_ref=%u\n", n, FTYPE(vpriv->framebuf[n].type), vpriv->framebuf[n].temp_ref); if(n+1 < vpriv->framebuf_used) mp_msg(MSGT_MUXER, MSGL_V, "n+1=%d, type=%c, temp_ref=%u\n", n+1, FTYPE(vpriv->framebuf[n+1].type), vpriv->framebuf[n+1].temp_ref); if(vpriv->framebuf[n].type == I_FRAME) { if(n > 0) { found = 1; break; } } n++; } } if(found && (n < vpriv->framebuf_used+1)) return n; else return 0;}static uint64_t fix_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int n){ int i, j, fixed = 0; uint64_t last_dts, last_idur, ret; uint32_t mintr, maxtr; ret = 0; if((vpriv->size == 0) && (fixed == 0)) //first pts adjustment, only at the beginning of the stream to manage BBI structures { int delay = 0; for(i = 0; i < n; i++) { if(vpriv->framebuf[i].type == I_FRAME) { for(j = i + 1; j < n; j++) { if(vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref) { ret += vpriv->framebuf[j].idur; delay++; fixed = 1; } } if(fixed) break; } } if(! fixed) ret = 0; else vpriv->last_pts += ret; mp_msg(MSGT_MUXER, MSGL_INFO, "INITIAL DELAY of %d frames\n", delay); } //KLUDGE BEGINS: Gop header (0x000001b8 in the video stream that signals a temp_ref wraparound) is _not_ mandatory, //so if we don't detect the right wraparound we will have a totally wrong timestamps assignment; let's go on mintr = vpriv->framebuf[0].temp_ref; maxtr = vpriv->framebuf[0].temp_ref; for(i = 0; i < n; i++) { mintr = min(vpriv->framebuf[i].temp_ref, mintr); maxtr = max(vpriv->framebuf[i].temp_ref, maxtr); } if(maxtr - mintr > 600) //there must be a temp_ref wraparound { mp_msg(MSGT_MUXER, MSGL_INFO, "\nDETECTED possible temp_ref wraparound in the videostreams: n=%d, mintr=%u, maxtr=%u\n", n, mintr, maxtr); for(i = 0; i < n; i++) { if(vpriv->framebuf[i].temp_ref < 1000) vpriv->framebuf[i].temp_ref += 1024; } } //KLUDGE ENDS for(i = 0; i < n; i++) { vpriv->framebuf[i].pts = vpriv->last_pts; for(j = 0; j < n; j++) { if((vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref) && (i != j)) { vpriv->framebuf[i].pts += vpriv->framebuf[j].idur; } } } if(vpriv->size == 0) last_dts = vpriv->init_dts = vpriv->framebuf[0].pts - (ret + vpriv->framebuf[0].idur); else last_dts = vpriv->last_dts; last_idur = 0; mp_msg(MSGT_MUXER, MSGL_V, "\n"); for(i = 0; i < n; i++) { vpriv->framebuf[i].dts = last_dts + last_idur; last_idur = vpriv->framebuf[i].idur; last_dts = vpriv->framebuf[i].dts; mp_msg(MSGT_MUXER, MSGL_V, "I=%d, type: %c, TR: %u, pts=%.3lf, dts=%.3lf, size=%u\n", i, FTYPE(vpriv->framebuf[i].type), vpriv->framebuf[i].temp_ref, (double) (vpriv->framebuf[i].pts/92160000.0), (double) (vpriv->framebuf[i].dts/92160000.0), vpriv->framebuf[i].size); } if((vpriv->size == 0) && (priv->init_delay_pts > 0)) { uint64_t diff; for(i = 0; i < vpriv->framebuf_used; i++) { vpriv->framebuf[i].pts += priv->init_delay_pts; vpriv->framebuf[i].dts += priv->init_delay_pts; } diff = vpriv->framebuf[0].pts - vpriv->framebuf[0].dts; if(vpriv->init_pts >= diff) vpriv->init_dts = vpriv->init_pts - diff; else vpriv->init_dts = diff; vpriv->last_dts += priv->init_delay_pts; vpriv->init_pts = 0; vpriv->last_pts += priv->init_delay_pts; priv->init_delay_pts = 0; mp_msg(MSGT_MUXER, MSGL_INFO, "INIT delayed video timestamps: PTS=%.3lf, DTS=%.3lf, DUR=%.3lf\n", (double) (vpriv->last_pts/92160000.0), (double) (vpriv->last_dts/92160000.0), (double) (vpriv->framebuf[0].idur/92160000.0)); } return ret;}static void check_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int i){ uint64_t dpts; dpts = max(vpriv->last_saved_pts, vpriv->pts) - min(vpriv->last_saved_pts, vpriv->pts); dpts += vpriv->framebuf[i].idur; if((!priv->ts_allframes) && (
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -