📄 muxer_mpeg.c
字号:
(priv->is_dvd && (vpriv->framebuf[i].type != I_FRAME)) || ((priv->is_genmpeg1 || priv->is_genmpeg2) && (vpriv->framebuf[i].type != I_FRAME) && (dpts < 64512000))) //0.7 seconds ) vpriv->pts = vpriv->dts = 0; if(vpriv->dts && ((vpriv->dts < priv->scr) || (vpriv->pts <= vpriv->dts))) { mp_msg(MSGT_MUXER, MSGL_V, "\nWARNING, SCR: %.3lf, DTS: %.3lf, PTS: %.3lf\n", (double) priv->scr/92160000.0,(double) vpriv->dts/92160000.0, (double) vpriv->pts/92160000.0); vpriv->dts = 0; } if(vpriv->pts && (vpriv->pts <= priv->scr)) { mp_msg(MSGT_MUXER, MSGL_ERR, "ERROR: SCR: %.3lf, VPTS: %.3lf, DELTA=-%.3lf secs\n", (double) (priv->scr/92160000.0), (double)(vpriv->pts/92160000.0), (double) ((priv->scr - vpriv->pts)/92160000.0)); vpriv->pts = vpriv->dts = 0; } if(vpriv->pts) vpriv->last_saved_pts = vpriv->pts;}static uint32_t calc_audio_chunk_size(muxer_stream_t *as, double duration, int finalize){ muxer_headers_t *apriv; uint32_t x, div, rest, abytes; double adur; uint64_t iaduration; apriv = (muxer_headers_t*) as->priv; abytes = (uint32_t) (duration * apriv->bitrate); //size of audio data to write x = (abytes + apriv->max_pl_size - 1) / apriv->max_pl_size; x *= apriv->max_pl_size; adur = (double) x / (double) apriv->bitrate; iaduration = (uint64_t) ((double) 92160000 * adur); abytes -= apriv->compensate; div = abytes / apriv->max_pl_size; rest = abytes % apriv->max_pl_size; if(apriv->compensate > 0) abytes = apriv->max_pl_size * (div - 1); else if(apriv->compensate < 0) abytes = apriv->max_pl_size * (div + 1); else abytes = apriv->max_pl_size * (rest ? div + 1 : div); apriv->compensate = 0; if(finalize) abytes = as->b_buffer_len; return abytes;}static int flush_buffers(muxer_t *muxer, int finalize){ int i, n, pl_size, found; size_t saved; uint32_t abytes, vbytes, bytes = 0, frame_bytes = 0, audio_rest = 0, tot = 0, muxrate; uint32_t offset; uint64_t idur, init_delay = 0; muxer_stream_t *s, *vs, *as; muxer_headers_t *vpriv = NULL, *apriv = NULL; muxer_priv_t *priv = (muxer_priv_t *) muxer->priv; uint8_t *tmp; double mult, duration; uint64_t iduration; mpeg_frame_t temp_frame; /* analyzes all streams and decides what to flush trying to respect an interleaving distribution equal to the v_bitrate/a_bitrate proportion */init: n = 0; vs = as = NULL; abytes = vbytes = found = 0; for(i = 0; i < muxer->avih.dwStreams; i++) { s = muxer->streams[i]; if(s->type == MUXER_TYPE_VIDEO) { vs = muxer->streams[i]; vpriv = (muxer_headers_t*) vs->priv; n = found = calc_frames_to_flush(vpriv); } else if(s->type == MUXER_TYPE_AUDIO) as = s; } if((! found) && finalize) { if(vpriv != NULL) found = n = vpriv->framebuf_used; } if(found) { mp_msg(MSGT_MUXER, MSGL_V, "\nVIDEO, FLUSH %d frames (of %d), 0 to %d\n", n, vpriv->framebuf_used, n-1); tmp = priv->tmp; vbytes = 0; vpriv = (muxer_headers_t*) vs->priv; if(priv->residual_cnt) { mpeg_frame_t *f = &(vpriv->framebuf[0]); size_t sz = f->size + priv->residual_cnt; if(f->alloc_size < sz) { f->buffer = (uint8_t *) realloc(f->buffer, sz); f->alloc_size = sz; } memmove(&(f->buffer[priv->residual_cnt]), f->buffer, f->size); memcpy(f->buffer, priv->residual, priv->residual_cnt); f->size += priv->residual_cnt; priv->residual_cnt = 0; } duration = 0; iduration = 0; for(i = 0; i < n; i++) { vbytes += vpriv->framebuf[i].size; iduration += vpriv->framebuf[i].idur; } duration = (double) (iduration / 92160000.0); if(vpriv->is_mpeg12) init_delay = fix_pts(priv, vpriv, n); else init_delay = 0; if(as != NULL) { apriv = (muxer_headers_t*) as->priv; abytes = calc_audio_chunk_size(as, duration, finalize); if((abytes / apriv->max_pl_size) > n) audio_rest = (abytes - (apriv->max_pl_size * n)) / n; else audio_rest = 0; if(as->b_buffer_len < abytes) { mp_msg(MSGT_MUXER, MSGL_V, "Not enough audio data (%u < %u), exit\n", as->b_buffer_len, abytes); return 0; } } if((as != NULL) && (init_delay > 0)) { if(apriv->size == 0) apriv->pts += init_delay; } saved = 0; bytes = vbytes + abytes; muxrate = (uint32_t) ((double) bytes/duration); if(muxrate > muxer->sysrate && (priv->is_genmpeg1 || priv->is_genmpeg2)) { mp_msg(MSGT_MUXER, MSGL_V, "NEW MUXRATE: %u -> %u\n", muxrate, muxer->sysrate); muxer->sysrate = muxrate; } idur = 0; offset = 0; priv->scr = vpriv->framebuf[0].dts - vpriv->init_dts; if((priv->is_xvcd || priv->is_xsvcd) && (vpriv->size == 0)) vpriv->buffer_size = (priv->is_xvcd ? 46 : 230)*1024; i = 0; while(i < n) { int frame_begin = 1, update; uint32_t pl_size = 0, target_size; uint8_t *buf; mp_msg(MSGT_MUXER, MSGL_V, "FRAME: %d, type: %c, TEMP_REF: %u, SIZE: %u\n", i, FTYPE(vpriv->framebuf[i].type), vpriv->framebuf[i].temp_ref, vpriv->framebuf[i].size); vpriv->pts = vpriv->framebuf[i].pts; vpriv->dts = vpriv->framebuf[i].dts; check_pts(priv, vpriv, i); if(priv->is_dvd && (vpriv->framebuf[i].type == I_FRAME) && (offset == 0)) { write_mpeg_pack(muxer, NULL, muxer->file, NULL, 0, 0); //insert fake Nav Packet vpriv->pes_is_aligned = 1; } offset = 0; vbytes = vpriv->framebuf[i].size; while(vbytes > 0 && (i < n)) { target_size = priv->packet_size - calc_pack_hlen(priv, vpriv); if((vbytes >= target_size) || ((vbytes < target_size) && (i == n-1))) { buf = &(vpriv->framebuf[i].buffer[offset]); pl_size = vbytes; update = 1; } else { uint32_t tmp_offset = 0; if(offset == 0) { vpriv->pts = vpriv->framebuf[i].pts; vpriv->dts = vpriv->framebuf[i].dts; check_pts(priv, vpriv, i); } else if(i < n-1) { vpriv->pts = vpriv->framebuf[i+1].pts; vpriv->dts = vpriv->framebuf[i+1].dts; check_pts(priv, vpriv, i+1); } else vpriv->pts = vpriv->dts = 0; target_size = priv->packet_size - calc_pack_hlen(priv, vpriv); //it was only priv->packet_size update = 0; while((tmp_offset < target_size) && (i < n)) { pl_size = min(target_size - tmp_offset, vbytes); memcpy(&(tmp[tmp_offset]), &(vpriv->framebuf[i].buffer[offset]), pl_size); tmp_offset += pl_size; offset += pl_size; vbytes -= pl_size; if(vbytes == 0) //current frame is saved, pass to the next { i++; vbytes = vpriv->framebuf[i].size; offset = 0; frame_begin = 1; } } buf = tmp; pl_size = tmp_offset; } if((pl_size < priv->packet_size - calc_pack_hlen(priv, vpriv)) && !finalize && (i >= n - 1)) { memcpy(priv->residual, buf, pl_size); priv->residual_cnt = pl_size; pl_size = update = vbytes = 0; } if(pl_size) pl_size = write_mpeg_pack(muxer, vs, muxer->file, buf, pl_size, 0); vpriv->pes_is_aligned = 0; vpriv->pts = vpriv->dts = 0; vpriv->buffer_size = 0; vpriv->size += pl_size; if(update) { vbytes -= pl_size; offset += pl_size; } /* this is needed to calculate SCR */ frame_bytes = max(vpriv->framebuf[i].size, priv->packet_size) + priv->packet_size; if(abytes > 0) //frame_bytes += min(apriv->max_pl_size, priv->packet_size) + audio_rest; frame_bytes += min(apriv->max_pl_size, abytes) + audio_rest; if(priv->ts_allframes) { tot = frame_bytes; mult = (double) vpriv->framebuf[min(i, n-1)].idur; } else { tot = bytes; //mult = (double) (max(iduration, iaduration)); mult = (double) (iduration); } update_scr(priv, pl_size, tot, mult); if(abytes > 0 && frame_begin) //it's time to save audio { pl_size = dump_audio(muxer, as, abytes, finalize); if(pl_size > 0) { abytes -= pl_size; update_scr(priv, pl_size, tot, mult); } } frame_begin = 0; } i++; } if(vpriv->is_mpeg12) { for(i = 0; i < n; i++) { vpriv->last_dts = vpriv->framebuf[i].dts; if(vpriv->framebuf[i].pts >= vpriv->last_pts) { vpriv->last_pts = vpriv->framebuf[i].pts; idur = vpriv->framebuf[i].idur; } } vpriv->last_dts += vpriv->framebuf[n-1].idur; vpriv->last_pts += idur; } for(i = n; i < vpriv->framebuf_used; i++) { temp_frame = vpriv->framebuf[i - n]; vpriv->framebuf[i - n] = vpriv->framebuf[i]; vpriv->framebuf[i] = temp_frame; } vpriv->framebuf_used -= n; if((as != NULL) && priv->has_audio) { while(abytes > 0) { mult = iduration; pl_size = dump_audio(muxer, as, abytes, finalize); if(pl_size > 0) { update_scr(priv, pl_size, bytes, mult); abytes -= pl_size; } else break; } } //goto init; } muxer->file_end = priv->scr; return found;}static uint64_t parse_fps(int fps){ // 90000 * 1024 / fps switch(fps) { case 239760: return 3843844; case 240000: return 3840000; case 250000: return 3686400; case 299700: return 3075075; case 300000: return 3072000; case 500000: return 1843200; case 599400: return 1537538; case 600000: return 1536000; default: mp_msg(MSGT_MUXER, MSGL_ERR, "ERROR! unknown fps code: %d", fps); return 0; }}static int soft_telecine(muxer_headers_t *vpriv, uint8_t *fps_ptr, uint8_t *se_ptr, uint8_t *pce_ptr, int n){ uint8_t fps, tff, rff; if(fps_ptr != NULL) { fps = *fps_ptr & 0x0f; if((!fps) || (fps > FRAMERATE_24)) { mp_msg(MSGT_MUXER, MSGL_ERR, "\nERROR! FRAMERATE IS INVALID: %d, disabling telecining\n", (int) fps); vpriv->telecine = 0; return 0; } *fps_ptr = (*fps_ptr & 0xf0) | (fps + 3); vpriv->nom_delta_pts = parse_fps((fps + 3) == FRAMERATE_2997 ? 299700 : 300000); } //in pce_ptr starting from bit 0 bit 24 is tff, bit 30 is rff, if(pce_ptr[3] & 0x2) { mp_msg(MSGT_MUXER, MSGL_ERR, "\nERROR! RFF bit is already set, disabling telecining\n"); vpriv->telecine = 0; return 0; } vpriv->picture.progressive_sequence = 0; vpriv->picture.progressive_frame = 1; if(se_ptr) se_ptr[1] &= 0xf7; if(! pce_ptr) return 0; if(! vpriv->vframes) //initial value of tff vpriv->trf = (pce_ptr[3] >> 6) & 0x2; //sets curent tff/rff bits tff = (vpriv->trf & 0x2) ? 0x80 : 0; rff = (vpriv->trf & 0x1) ? 0x2 : 0; mp_msg(MSGT_MUXER, MSGL_V, "\nTFF: %d, RFF: %d\n", tff >> 7, rff >> 1); pce_ptr[3] = (pce_ptr[3] & 0xfd) | tff | rff; pce_ptr[4] |= 0x80; //sets progressive frame if(! vpriv->vframes) mp_msg(MSGT_MUXER, MSGL_INFO, "\nENABLED SOFT TELECINING, FPS=%s, INITIAL PATTERN IS TFF:%d, RFF:%d\n", framerates[fps+3], tff >> 7, rff >> 1); while(n < 0) n+=4; vpriv->trf = (vpriv->trf + n) % 4; return 1;}static size_t parse_mpeg12_video(muxer_stream_t *s, muxer_priv_t *priv, muxer_headers_t *spriv, float fps, size_t len){ size_t ptr = 0, sz = 0, tmp = 0; uint8_t *fps_ptr = NULL; //pointer to the fps byte in the sequence header uint8_t *se_ptr = NULL; //pointer to sequence extension uint8_t *pce_ptr = NULL; //pointer to picture coding extension int frames_diff, d1; //how any frames we advanced respect to the last one mp_msg(MSGT_MUXER, MSGL_V,"parse_mpeg12_video, len=%u\n", (uint32_t) len); if(s->buffer[0] != 0 || s->buffer[1] != 0 || s->buffer[2] != 1 || len<6) { mp_msg(MSGT_MUXER, MSGL_ERR,"Unknown video format, possibly non-MPEG1/2 stream, len=%d!\n", len); return 0; } if(s->buffer[3] == 0 || s->buffer[3] == 0xb3 || s->buffer[3] == 0xb8) { // Video (0) Sequence header (b3) or GOP (b8) uint32_t temp_ref; int pt; if(s->buffer[3] == 0xb3) //sequence { fps_ptr = &(s->buffer[7]); mp_header_process_sequence_header(&(spriv->picture), &(s->buffer[4])); spriv->delta_pts = spriv->nom_delta_pts = parse_fps(spriv->picture.fps); spriv->delta_clock = (double) 1/fps; mp_msg(MSGT_MUXER, MSGL_V, "\nFPS: %.3f, FRAMETIME: %.3lf\n", fps, (double)1/fps); if(priv->patch_seq) patch_seq(priv, s->buffer); tmp = 12; if(s->buffer[tmp-1] & 2) tmp += 64; if(s->buffer[tmp-1] & 1) tmp += 64; if(s->buffer[tmp] == 0 && s->buffer[tmp+1] == 0 && s->buffer[tmp+2] == 1 && s->buffer[tmp+3] == 0xb5) { se_ptr = &(s->buffer[tmp+4]); mp_header_process_extension(&(spriv->picture), &(s->buffer[tmp+4])); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -