📄 muxer_mpeg.c
字号:
{ uint16_t t1, t2, t3; ts >>= 10; ts &= 0x1FFFFFFFFULL; //33 bits, no extension; input must be * 92160000 t1 = (ts >> 30) & 0x7;; t2 = (ts >> 15) & 0x7fff; t3 = ts & 0x7fff; b[0] = (t1 << 3 ) | 0x44 | ((t2 >> 13) & 0x3); b[1] = (t2 >> 5); b[2] = (t2 & 0x1f) << 3 | 0x4 | ((t3 >> 13) & 0x3); b[3] = (t3 >> 5); b[4] = (t3 & 0x1f) << 3 | 0x4; b[5] = 1;}static int write_mpeg_pack_header(muxer_t *muxer, char *buff){ int len; muxer_priv_t *priv; priv = (muxer_priv_t *) muxer->priv; *(uint32_t *)buff = be2me_32(PACK_HEADER_START_CODE); if(priv->mux==MUX_MPEG1) { write_mpeg_ts(&buff[4], priv->scr, 0x20); // 0010 and SCR write_mpeg_rate(priv->mux, &buff[9], muxer->sysrate); len = 12; } else { write_mpeg2_scr(&buff[4], priv->scr); // 0010 and SCR write_mpeg_rate(priv->mux, &buff[10], muxer->sysrate); buff[13] = 0xf8; //5 bits reserved + 3 set to 0 to indicate 0 stuffing bytes len = 14; } return len;}static int write_mpeg_system_header(muxer_t *muxer, char *buff){ int len; uint8_t i; muxer_priv_t *priv; priv = (muxer_priv_t *) muxer->priv; len = 0; *(uint32_t *)(&buff[len]) = be2me_32(SYSTEM_HEADER_START_CODE); len += 4; *(uint16_t *)(&buff[len]) = 0; //fake length, we'll fix it later len += 2; write_mpeg_rate(MUX_MPEG1, &buff[len], muxer->sysrate); len += 3; buff[len++] = 0x4 | (priv->is_xvcd ? 1 : 0); //1 audio stream bound, no fixed, CSPS only for xvcd buff[len++] = 0xe1; //system_audio_lock, system_video_lock, marker, 1 video stream bound buff[len++] = ((priv->mux == MUX_MPEG1) ? 0xff : 0x7f); //in mpeg2 there's the packet rate restriction for(i = 0; i < priv->sys_info.cnt; i++) { buff[len++] = priv->sys_info.streams[i].id; write_mpeg_std(&buff[len], priv->sys_info.streams[i].bufsize, priv->sys_info.streams[i].type, (priv->sys_info.streams[i].type == 1 ? 0xe0: 0xc0)); len += 2; } *(uint16_t *)(&buff[4]) = be2me_16(len - 6); // length field fixed return len;}static int write_mpeg_psm(muxer_t *muxer, char *buff){ int len; uint8_t i; uint16_t dlen; muxer_priv_t *priv; priv = (muxer_priv_t *) muxer->priv; len = 0; *(uint32_t *)(&buff[len]) = be2me_32(PSM_START_CODE); len += 4; *(uint16_t *)(&buff[len]) = 0; //fake length, we'll fix it later len += 2; buff[len++] = 0xe0; //1 current, 2 bits reserved, 5 version 0 buff[len++] = 0xff; //7 reserved, 1 marker buff[len] = buff[len+1] = 0; //length of the program descriptors (unused) len += 2; *(uint16_t *)(&buff[len]) = 0; //length of the es descriptors len += 2; dlen = 0; for(i = 0; i < priv->psm_info.cnt; i++) { if( (priv->psm_info.streams[i].id == 0xbd) || (priv->psm_info.streams[i].id >= 0xe0 && priv->psm_info.streams[i].id <= 0xef) || (priv->psm_info.streams[i].id >= 0xc0 && priv->psm_info.streams[i].id <= 0xcf) ) { buff[len++] = priv->psm_info.streams[i].type; buff[len++] = priv->psm_info.streams[i].id; buff[len++] = 0; //len of descriptor upper ... buff[len++] = 6; //... lower //registration descriptor buff[len++] = 0x5; //tag buff[len++] = 4; //length: 4 bytes memcpy(&(buff[len]), (char*) &(priv->psm_info.streams[i].format), 4); len += 4; dlen += 10; } } *(uint16_t *)(&buff[10]) = be2me_16(dlen); //length of the es descriptors *(uint16_t *)(&buff[4]) = be2me_16(len - 6 + 4); // length field fixed, including size of CRC32 *(uint32_t *)(&buff[len]) = CalcCRC32(buff, len); len += 4; //for crc return len;}static int write_mpeg_pes_header(muxer_headers_t *h, uint8_t *pes_id, uint8_t *buff, uint16_t plen, int stuffing_len, int mux_type){ int len; len = 0; memcpy(&buff[len], pes_id, 4); len += 4; buff[len] = buff[len+1] = 0; //fake len len += 2; if(mux_type == MUX_MPEG1) { if(stuffing_len > 0) { memset(&buff[len], 0xff, stuffing_len); len += stuffing_len; } if(h->buffer_size > 0) { write_mpeg_std(&buff[len], h->buffer_size, h->type, 0x40); // 01 is pes1 format len += 2; } } else //MPEG2 { buff[len] = (h->pes_is_aligned ? 0x84 : 0x80); //0x10... len++; buff[len] = ((h->buffer_size > 0) ? 1 : 0) | (h->pts ? (h->dts ? 0xC0 : 0x80) : 0); //pes extension + pts/dts flags len++; buff[len] = (h->pts ? (h->dts ? 10 : 5) : 0) + ((h->buffer_size > 0) ? 3 : 0) + stuffing_len;//pts + std + stuffing len++; } if(h->pts) { write_mpeg_ts(&buff[len], h->pts, (h->dts ? 0x30 : 0x20)); // 001x and both PTS/DTS len += 5; if(h->dts) { write_mpeg_ts(&buff[len], h->dts, 0x10); // 0001 before DTS len += 5; } } else { if(mux_type == MUX_MPEG1) { buff[len] = 0x0f; len += 1; } } if(mux_type == MUX_MPEG2) { if(h->buffer_size > 0) { buff[len] = 0x10; //std flag len++; write_mpeg_std(&buff[len], h->buffer_size, h->type, 0x40); len += 2; } if(stuffing_len > 0) { memset(&buff[len], 0xff, stuffing_len); len += stuffing_len; } } if(h->has_pes_priv_headers > 0) { memcpy(&buff[len], h->pes_priv_headers, h->has_pes_priv_headers); len += h->has_pes_priv_headers; } *((uint16_t*) &buff[4]) = be2me_16(len + plen - 6); //fix pes packet size return len;}static void write_pes_padding(uint8_t *buff, uint16_t len){ //6 header bytes + len-6 0xff chars buff[0] = buff[1] = 0; buff[2] = 1; buff[3] = 0xbe; *((uint16_t*) &buff[4]) = be2me_16(len - 6); memset(&buff[6], 0xff, len - 6);}static void write_psm_block(muxer_t *muxer, FILE *f){ uint16_t offset, stuffing_len; muxer_priv_t *priv = (muxer_priv_t *) muxer->priv; uint8_t *buff = priv->buff; offset = write_mpeg_pack_header(muxer, buff); offset += write_mpeg_psm(muxer, &buff[offset]); stuffing_len = priv->packet_size - offset; if(stuffing_len > 0) { //insert a PES padding packet write_pes_padding(&buff[offset], stuffing_len); offset += stuffing_len; } fwrite(buff, offset, 1, f); priv->headers_size += offset;}static int write_nav_pack(uint8_t *buff){ // concatenation of pes_private2 + 03d4 x 0 and pes_private2 + 03fa x 0 int len; mp_msg(MSGT_MUXER, MSGL_V, "NAV\n"); len = 0; *(uint32_t *)(&buff[len]) = be2me_32(PES_PRIVATE2); len += 4; buff[len++] = 0x3; buff[len++] = 0xd4; memset(&buff[len], 0, 0x03d4); len += 0x03d4; *(uint32_t *)(&buff[len]) = be2me_32(PES_PRIVATE2); len += 4; buff[len++] = 0x3; buff[len++] = 0xfa; memset(&buff[len], 0, 0x03fa); len += 0x03fa; return len;}static uint32_t calc_pes_hlen(int format, muxer_headers_t *h, muxer_priv_t *priv){ uint32_t len; if(format == MUX_MPEG1) len = 6; else len = 9; //era 12 if(h->pts) { len += 5; if(h->dts) len += 5; } else if(format == MUX_MPEG1) len += 1; if(h->buffer_size > 0) { if(format == MUX_MPEG2) len += 3; else len += 2; } len += h->has_pes_priv_headers; return len;}static uint32_t calc_pack_hlen(muxer_priv_t *priv, muxer_headers_t *h){ uint32_t len; if(priv->mux == MUX_MPEG1) len = 12; else len = 14; /*if((priv->is_genmpeg1 || priv->is_genmpeg2) && priv->update_system_header) len += (6 + (3*priv->sys_info.cnt));*/ if(h->min_pes_hlen > 0) len += h->min_pes_hlen; else len += calc_pes_hlen(priv->mux, h, priv); return len;}static int write_mpeg_pack(muxer_t *muxer, muxer_stream_t *s, FILE *f, char *bl, uint32_t len, int isoend){ size_t tot, offset, pes_hlen, pack_hlen; muxer_priv_t *priv; uint8_t *buff; int stuffing_len = 0, stflen; muxer_headers_t *spriv; priv = (muxer_priv_t *) muxer->priv; buff = priv->buff; if(isoend) { buff[0] = buff[1] = 0; buff[2] = 1; buff[3] = 0xb9; fwrite(buff, 4, 1, f); return 1; } if((len == 0) || (bl == NULL)) //PACK headers only { offset = write_mpeg_pack_header(muxer, buff); offset += write_mpeg_system_header(muxer, &buff[offset]); //priv->update_system_header = 0; if(priv->is_dvd) offset += write_nav_pack(&buff[offset]); stuffing_len = priv->packet_size - offset; if(stuffing_len > 0) { //insert a PES padding packet write_pes_padding(&buff[offset], stuffing_len); offset += stuffing_len; } fwrite(buff, offset, 1, f); priv->headers_size += offset; tot = offset; muxer->movi_end += tot; return tot; } else { spriv = (muxer_headers_t *) s->priv; mp_msg(MSGT_MUXER, MSGL_V, "\nwrite_mpeg_pack(MUX=%d, len=%u, rate=%u, id=%X, pts: %llu, dts: %llu, scr: %llu, PACK_size:%u\n", priv->mux, len, muxer->sysrate, s->ckid, spriv->pts, spriv->dts, priv->scr, priv->packet_size); //stflen is the count of stuffing bytes in the pes header itself, //stuffing_len is the size of the stuffing pes stream (must be at least 7 bytes long) stflen = stuffing_len = 0; offset = 0; offset = pack_hlen = write_mpeg_pack_header(muxer, &buff[offset]); if(priv->update_system_header && (priv->is_genmpeg1 || priv->is_genmpeg2)) { pack_hlen += write_mpeg_system_header(muxer, &buff[offset]); priv->update_system_header = 0; } offset = pack_hlen; pes_hlen = calc_pes_hlen(priv->mux, spriv, priv); if(spriv->min_pes_hlen > 0) { if(spriv->min_pes_hlen > pes_hlen) stflen = spriv->min_pes_hlen - pes_hlen; } if((len >= priv->packet_size - pack_hlen - max(pes_hlen, spriv->min_pes_hlen))) stuffing_len = 0; else stuffing_len = priv->packet_size - pack_hlen - max(pes_hlen, spriv->min_pes_hlen) - len; if(stuffing_len > 0) { if(stuffing_len < 7) { if(stflen + stuffing_len > 16) { int x = 7 - stuffing_len; stflen -= x; stuffing_len += x; } else { stflen += stuffing_len; stuffing_len = 0; } } } if(priv->skip_padding) //variable packet size, just for fun and to reduce file size { stuffing_len = 0; len = min(len, priv->packet_size - pack_hlen - pes_hlen - stflen); } else len = priv->packet_size - pack_hlen - pes_hlen - stflen - stuffing_len; mp_msg(MSGT_MUXER, MSGL_V, "LEN=%d, pack: %d, pes: %d, stf: %d, stf2: %d\n", len, pack_hlen, pes_hlen, stflen, stuffing_len); pes_hlen = write_mpeg_pes_header(spriv, (uint8_t *) &s->ckid, &buff[offset], len, stflen, priv->mux); offset += pes_hlen; fwrite(buff, offset, 1, f); mp_msg(MSGT_MUXER, MSGL_V, "pack_len = %u, pes_hlen = %u, stuffing_len: %d+%d, SCRIVO: %d bytes di payload\n", pack_hlen, pes_hlen, stuffing_len, stflen, len); fwrite(bl, len, 1, f); offset += len; if(stuffing_len > 0) { //insert a PES padding packet mp_msg(MSGT_MUXER, MSGL_V, "STUFFING: %d\n", stuffing_len); write_pes_padding(buff, stuffing_len); fwrite(buff, stuffing_len, 1, f); } else stuffing_len = 0; offset += stuffing_len; mp_msg(MSGT_MUXER, MSGL_V, "\nwritten len=%d, spriv: pack(%d), pes(%d), stuffing(%d) tot(%d), offset: %d\n", len, pack_hlen, pes_hlen, stuffing_len, pack_hlen + pes_hlen + stuffing_len, offset); priv->headers_size += pack_hlen + pes_hlen + stuffing_len + stflen; priv->data_size += len; muxer->movi_end += offset; return len; }}static void patch_seq(muxer_priv_t *priv, unsigned char *buf){ if(priv->vwidth > 0) { buf[4] = (priv->vwidth >> 4) & 0xff; buf[5] &= 0x0f; buf[5] |= (priv->vwidth & 0x0f) << 4; } if(priv->vheight > 0) { buf[5] &= 0xf0; buf[5] |= (priv->vheight >> 8) & 0x0f; buf[6] = priv->vheight & 0xff; } if(priv->vaspect > 0) buf[7] = (buf[7] & 0x0f) | (priv->vaspect << 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -