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 + -
显示快捷键?