muxer_mpeg.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,496 行 · 第 1/5 页
C
2,496 行
}static void write_mpeg_rate(int type, unsigned char *b, unsigned int rate) { rate = ((rate*8)+399) / 400; if(type == MUX_MPEG1) { b[0] = ((rate >> 15) & 0x7f) | 0x80; b[1] = (rate >> 7) & 0xff; b[2] = ((rate << 1) & 0xff) | 1; } else { b[0] = (rate >> 14); b[1] = (rate >> 6) & 0xff; b[2] = ((rate & 0x3f) << 2) | 0x03; }}static void write_mpeg_std(unsigned char *b, unsigned int size, unsigned int type, uint8_t mod) { //type = 0:mpeg audio/128, 1:video and pes private streams (including ac3/dts/lpcm)/1024 if(type == 0) //audio size = (size + 127) / 128; else //video or other size = ((size + 1023) / 1024); if(! size) size++; b[0] = ((size >> 8) & 0x3f) | (type==1 ? 0x60 : 0x40) | mod; b[1] = size & 0xff;}static void write_mpeg2_scr(unsigned char *b, uint64_t ts) { uint16_t t1, t2, t3, scr_ext; scr_ext = ts % 300ULL; ts /= 300ULL; ts &= 0x1FFFFFFFFULL; //33 bits 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 | ((scr_ext >> 7) & 0x03) | 0x4; b[5] = ((scr_ext << 1) & 0xFF) | 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 //stolen from libavformat if(priv->is_xvcd || priv->is_dvd) buff[len++] = 0xe1; //system_audio_lock, system_video_lock, marker, 1 video stream bound else buff[len++] = 0x21; //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]) = be2me_32(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] = 0x1e; //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; } } *((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, stream_t *stream){ 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; } stream_write_buffer(stream, buff, offset); 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_DBG3, "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; 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 = max(h->min_pes_hlen, len); return len;} static int write_mpeg_pack(muxer_t *muxer, muxer_stream_t *s, stream_t *stream, int isoend){ size_t tot, offset; muxer_priv_t *priv; unsigned char *buff; int stuffing_len; priv = (muxer_priv_t *) muxer->priv; buff = priv->buff; if(isoend) { offset = priv->packet_size - 4; write_pes_padding(buff, offset); buff[offset + 0] = buff[offset + 1] = 0; buff[offset + 2] = 1; buff[offset + 3] = 0xb9; stream_write_buffer(stream, buff, priv->packet_size); return 1; } else //FAKE DVD NAV PACK { 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; } stream_write_buffer(stream, buff, offset); priv->headers_size += offset; tot = offset; muxer->movi_end += tot; return tot; }}static void update_demux_bufsize(muxer_headers_t *spriv, uint64_t dts, int framelen, int type){ int dim = (spriv->track_len+16)*sizeof(buffer_track_t); if(spriv->track_pos+1 >= spriv->track_len) { buffer_track_t *tmp = realloc(spriv->buffer_track, dim); if(!tmp) { mp_msg(MSGT_MUXER, MSGL_ERR, "\r\nERROR, couldn't realloc %d bytes for tracking buffer\r\n", dim); return; } spriv->buffer_track = tmp; memset(&(spriv->buffer_track[spriv->track_pos+1]), 0, 16*sizeof(buffer_track_t)); spriv->track_len += 16; } spriv->buffer_track[spriv->track_pos].size = framelen; spriv->buffer_track[spriv->track_pos].dts = dts; //must be dts spriv->track_pos++;}static void fix_a52_headers(muxer_stream_t *s){ muxer_headers_t *spriv = s->priv; int x = spriv->payload_offset; spriv->pack[x+0] = 0x80; spriv->pack[x+1] = spriv->frames; if(spriv->frames) { spriv->pack[x+2] = ((spriv->last_frame_rest+1) >> 8) & 0xff; //256 * 0 ... spriv->pack[x+3] = (spriv->last_frame_rest+1) & 0xff; // + 1 byte(s) to skip } else spriv->pack[x+2] = spriv->pack[x+3] = 0;}static inline void remove_frames(muxer_headers_t *spriv, int n){ mpeg_frame_t tmp; int i; for(i = n; i < spriv->framebuf_used; i++) { tmp = spriv->framebuf[i - n]; spriv->framebuf[i - n] = spriv->framebuf[i]; spriv->framebuf[i] = tmp; } spriv->framebuf_used -= n;}static int calc_packet_len(muxer_stream_t *s, int psize, int finalize){ muxer_headers_t *spriv = s->priv; int n, len, frpos, m; n = len = 0; frpos = spriv->framebuf[0].pos; while(len < psize && n < spriv->framebuf_used) { if(!frpos && len>0 && s->type == MUXER_TYPE_VIDEO && spriv->framebuf[n].type==I_FRAME) return len; m = FFMIN(spriv->framebuf[n].size - frpos, psize - len); len += m; frpos += m; if(frpos == spriv->framebuf[n].size) { frpos = 0; n++; } } if(len < psize && !finalize) return 0; return len;}static int find_packet_timestamps(muxer_priv_t *priv, muxer_stream_t *s, unsigned int start, uint64_t *dts, uint64_t *pts){ muxer_headers_t *spriv = s->priv; int i, m, pes_hlen, ret, threshold; uint64_t spts, sdts, dpts; if(!spriv->framebuf_used) return 0; spts = spriv->pts; sdts = spriv->dts; spriv->dts = spriv->pts = 0; ret = 0; if(spriv->framebuf[0].pos == 0) // start of frame i = 0; else { pes_hlen = calc_pes_hlen(priv->mux, spriv, priv); if(pes_hlen < spriv->min_pes_hlen) pes_hlen = spriv->min_pes_hlen; m = spriv->framebuf[0].size - spriv->framebuf[0].pos; if(start + pes_hlen + m >= priv->packet_size) //spriv->pack_offset i = -1; //this pack won't have a pts: no space available else { if(spriv->framebuf_used < 2) goto fail; if(spriv->framebuf[1].pts == spriv->framebuf[1].dts) threshold = 5; else threshold = 10;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?