muxer_mpeg.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,496 行 · 第 1/5 页

C
2,496
字号
			//headers+frame 0 < space available including timestamps				if(start + pes_hlen + m  < priv->packet_size - threshold)				i = 1;			else				i = -1;		}	}	if(i > -1)	{		dpts = FFMAX(spriv->last_saved_pts, spriv->framebuf[i].pts) - 			FFMIN(spriv->last_saved_pts, spriv->framebuf[i].pts) +			spriv->framebuf[0].idur;		if(s->type != MUXER_TYPE_VIDEO)			ret = 1;		else if((spriv->framebuf[i].type == I_FRAME || priv->ts_allframes || dpts >= 36000*300))	//0.4 seconds			ret = 1;		if(ret)		{			*pts = spriv->framebuf[i].pts;			*dts = spriv->framebuf[i].dts;			if(*dts == *pts)				*dts = 0;		}	}fail:	spriv->pts = spts;	spriv->dts = sdts;	return ret;}static int get_packet_stats(muxer_priv_t *priv, muxer_stream_t *s, pack_stats_t *p, int finalize){	muxer_headers_t *spriv = s->priv;	int len, len2, pack_hlen, pes_hlen, hlen, target, stflen, stuffing_len;	uint64_t pts, dts;	spriv->pts = spriv->dts = 0;	p->dts = p->pts = p->frame_pts = p->frame_dts = 0;	p->len = 0;	if(priv->rawpes)		pack_hlen = 0;	else if(priv->mux == MUX_MPEG1)		pack_hlen = 12;	else		pack_hlen = 14;	if(find_packet_timestamps(priv, s, pack_hlen, &dts, &pts))	{		p->pts = p->frame_pts = pts;		p->dts = p->frame_dts = dts;		spriv->pts = pts;		spriv->dts = dts;	}	pes_hlen = calc_pes_hlen(priv->mux, spriv, priv);	p->stflen = stflen = (spriv->min_pes_hlen > pes_hlen ? spriv->min_pes_hlen - pes_hlen : 0);	target = len = priv->packet_size - pack_hlen - pes_hlen - stflen;	//max space available	if(s->type == MUXER_TYPE_AUDIO && s->wf->wFormatTag == AUDIO_A52)		hlen = 4;	else		hlen = 0;	len -= hlen;	target -= hlen;		len2 = calc_packet_len(s, target, finalize);	if(!len2 || (len2 < target && s->type == MUXER_TYPE_AUDIO && !finalize))	{		//p->len = 0;		//p->dts = p->pts = 0;		spriv->pts = spriv->dts = 0;		//fprintf(stderr, "\r\nLEN2: %d, target: %d, type: %d\r\n", len2, target, s->type);		return 0;	}	len = len2;	stuffing_len = 0;	if(len < target)	{		if(s->type == MUXER_TYPE_VIDEO)		{			if(spriv->pts)				target += 5;			if(spriv->dts)				target += 5;			spriv->pts = spriv->dts = 0;			p->pts = p->dts = 0;		}		stuffing_len = target - len;		if(stuffing_len > 0 && 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;			}		}	}		len += hlen;		p->len = len;	p->stflen = stflen;	return p->len;}static int fill_packet(muxer_t *muxer, muxer_stream_t *s, int finalize){	//try to fill a packet as much as possible	//spriv->pack_offset is the start position inited to 0	//data is taken from spriv->framebuf	//if audio and a52 insert the headers	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;	muxer_headers_t *spriv = (muxer_headers_t *) s->priv;	int len, m, n, dvd_pack = 0;	mpeg_frame_t *frm;	pack_stats_t p;	spriv->dts = spriv->pts = 0;	if(! spriv->framebuf_used)	{		spriv->pack_offset = 0;		return 0;	}	if(!spriv->pack_offset)	{		if(priv->rawpes)			spriv->pack_offset = 0;		else		spriv->pack_offset = write_mpeg_pack_header(muxer, spriv->pack);		if(priv->update_system_header && (priv->is_genmpeg1 || priv->is_genmpeg2))		{			spriv->pack_offset += write_mpeg_system_header(muxer, &spriv->pack[spriv->pack_offset]);			priv->update_system_header = 0;		}		spriv->pes_set = 0;		spriv->pes_offset = spriv->pack_offset;		spriv->payload_offset = 0;		spriv->frames = 0;		spriv->last_frame_rest = 0;	}	if(!spriv->pes_set)	{		int bufsize = 0;		//search the pts. yes if either it's video && (I-frame or priv->ts_allframes) && framebuf[i].pos == 0		//or  it's audio && framebuf[i].pos == 0		//NB pts and dts can only be relative to the first frame beginning in this pack		if((priv->is_xsvcd || priv->is_xvcd || priv->rawpes) && spriv->size == 0)		{			if(s->type == MUXER_TYPE_VIDEO)				bufsize = (conf_vbuf_size ? conf_vbuf_size : (priv->is_xvcd ? 46 : 232));			else				bufsize = (conf_abuf_size ? conf_abuf_size : 4);			spriv->buffer_size = bufsize*1024;		}		if(priv->is_dvd && s->type == MUXER_TYPE_VIDEO 			&& spriv->framebuf[0].type==I_FRAME && spriv->framebuf[0].pos==0)			dvd_pack = 1;		if(! get_packet_stats(priv, s, &p, finalize))		{			spriv->pack_offset = 0;			return 0;		}		spriv->dts = p.dts;		spriv->pts = p.pts;		if(spriv->pts)			spriv->last_saved_pts = p.pts;				spriv->pack_offset += write_mpeg_pes_header(spriv, (uint8_t *) &s->ckid, &(spriv->pack[spriv->pack_offset]), 			p.len, p.stflen, priv->mux);		if(s->type == MUXER_TYPE_AUDIO && s->wf->wFormatTag == AUDIO_A52)		{			spriv->payload_offset = spriv->pack_offset;			spriv->pack_offset += 4;	//for the 4 bytes of header			if(!spriv->framebuf[0].pos)				spriv->last_frame_rest = 0;			else				spriv->last_frame_rest = spriv->framebuf[0].size - spriv->framebuf[0].pos;		}		spriv->pes_set = 1;	}	if(spriv->dts || spriv->pts)	{		if((spriv->dts && priv->scr >= spriv->dts) || priv->scr >= spriv->pts)			mp_msg(MSGT_MUXER, MSGL_ERR, "\r\nERROR: scr %.3lf, dts %.3lf, pts %.3lf\r\n", (double) priv->scr/27000000.0, (double) spriv->dts/27000000.0, (double) spriv->pts/27000000.0);		else if(priv->scr + 63000*300 < spriv->dts)			mp_msg(MSGT_MUXER, MSGL_INFO, "\r\nWARNING>: scr %.3lf, dts %.3lf, pts %.3lf, diff %.3lf, piff %.3lf\r\n", (double) priv->scr/27000000.0, (double) spriv->dts/27000000.0, (double) spriv->pts/27000000.0, (double)(spriv->dts - priv->scr)/27000000.0, (double)(spriv->pts - priv->scr)/27000000.0);	}	n = 0;	len = 0;	frm = spriv->framebuf;	while(spriv->pack_offset < priv->packet_size && n < spriv->framebuf_used)	{		if(!frm->pos)		{			//since iframes must always be aligned at block boundaries exit when we find the 			//beginning of one in the middle of the flush			if(len > 0 && s->type == MUXER_TYPE_VIDEO && frm->type == I_FRAME)			{				break;			}			spriv->frames++;			update_demux_bufsize(spriv, frm->dts, frm->size, s->type);		}		m = FFMIN(frm->size - frm->pos, priv->packet_size - spriv->pack_offset);		memcpy(&(spriv->pack[spriv->pack_offset]), &(frm->buffer[frm->pos]), m);		len += m;		spriv->pack_offset += m;		frm->pos += m;				if(frm->pos == frm->size)	//end of frame		{			frm->pos = frm->size = 0;			frm->pts = frm->dts = 0;			n++;			frm++;		}	}	if((priv->is_xsvcd || priv->is_xvcd || priv->rawpes) && spriv->size == 0)		spriv->buffer_size = 0;	spriv->size += len;	if(dvd_pack && (spriv->pack_offset == priv->packet_size))		write_mpeg_pack(muxer, NULL, muxer->stream, 0);	//insert fake Nav Packet	if(n > 0)		remove_frames(spriv,  n);	spriv->track_bufsize += len;	if(spriv->track_bufsize > spriv->max_buffer_size)		mp_msg(MSGT_MUXER, MSGL_ERR, "\r\nBUFFER OVERFLOW: %d > %d, pts: %"PRIu64"\r\n", spriv->track_bufsize, spriv->max_buffer_size, spriv->pts);	if(s->type == MUXER_TYPE_AUDIO && s->wf->wFormatTag == AUDIO_A52)		fix_a52_headers(s);		if(spriv->pack_offset < priv->packet_size && !priv->rawpes)	//here finalize is set	{		int diff = priv->packet_size - spriv->pack_offset;		write_pes_padding(&(spriv->pack[spriv->pack_offset]), diff);		spriv->pack_offset += diff;	}		stream_write_buffer(muxer->stream, spriv->pack, spriv->pack_offset);	priv->headers_size += spriv->pack_offset - len;	priv->data_size += len;	muxer->movi_end += spriv->pack_offset;	spriv->pack_offset = 0;	spriv->pes_set = 0;	spriv->frames = 0;		return len;}static inline int find_best_stream(muxer_t *muxer){	int i, ndts;	uint64_t dts = -1;	muxer_priv_t *priv = muxer->priv;	muxer_headers_t *spriv;	pack_stats_t p;	unsigned int perc, sperc;	ndts = -1;	perc = -1;		//THIS RULE MUST ALWAYS apply: dts  <= SCR + 0.7 seconds	for(i = 0; i < muxer->avih.dwStreams; i++)	{		spriv = muxer->streams[i]->priv;		p.len = 0;		get_packet_stats(priv, muxer->streams[i], &p, 0);				if(spriv->track_bufsize + p.len > spriv->max_buffer_size)			continue;		if(p.frame_pts && p.frame_dts > priv->scr + 63000*300)			continue;		if(spriv->framebuf[0].dts <= dts)		{			dts = spriv->framebuf[0].dts;			ndts = i;		}		if(conf_interleaving2)		{			sperc = (spriv->track_bufsize * 1024) / spriv->max_buffer_size;			if(sperc < perc)			{				ndts = i;				perc = sperc;			}		}	}	return ndts;}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);		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);	}}static void update_scr(muxer_t *muxer){	muxer_priv_t *priv = muxer->priv;	muxer_stream_t *stream;	muxer_headers_t *spriv;	int i, j;	uint64_t mindts = (uint64_t) -1;	priv->scr += priv->delta_scr;	for(i = 0; i < muxer->avih.dwStreams; i++)	{		stream = muxer->streams[i];		spriv = stream->priv;		if(spriv->framebuf_used && spriv->framebuf[0].dts < mindts)			mindts = spriv->framebuf[0].dts;	}	mp_msg(MSGT_MUXER, MSGL_DBG2, "UPDATE SCR TO %"PRIu64" (%.3lf)\n", priv->scr, (double) (priv->scr/27000000.0));		for(i = 0; i < muxer->avih.dwStreams; i++)	{		stream = muxer->streams[i];		spriv = stream->priv;		j = 0;		while(j < spriv->track_pos && priv->scr >= spriv->buffer_track[j].dts)		{			spriv->track_bufsize -= spriv->buffer_track[j].size;			j++;		}		if(spriv->track_bufsize < 0)		{			double d;			muxer->sysrate = (muxer->sysrate * 11) / 10;	//raise by 10%			d = (double) priv->packet_size / (double)muxer->sysrate;			priv->delta_scr = (uint64_t) (d * 27000000.0f);			mp_msg(MSGT_MUXER, MSGL_INFO, "\r\nBUFFER UNDEFLOW at stream %d, raising muxrate to %d kb/s, delta_scr: %"PRIu64"\r\n", i, muxer->sysrate/125, priv->delta_scr);			spriv->track_bufsize = 0;		}		if(j > 0)		{			memmove(spriv->buffer_track, &(spriv->buffer_track[j]), (spriv->track_len - j) * sizeof(buffer_track_t));			spriv->track_pos -= j;			for(j = spriv->track_pos; j < spriv->track_len; j++)				spriv->buffer_track[j].size = 0;		}		if(spriv->framebuf_used && spriv->framebuf[0].dts < mindts)			mindts = spriv->framebuf[0].dts;	}}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_DBG2, "\n");		while(n < vpriv->framebuf_used)		{			mp_msg(MSGT_MUXER, MSGL_DBG2, "CALC_FRAMES, n=%d, type=%c, pts=%.3lf\n", n, FTYPE(vpriv->framebuf[n].type), (double)vpriv->framebuf[n].pts/27000000.0f);			if(n+1 < vpriv->framebuf_used)				mp_msg(MSGT_MUXER, MSGL_DBG2, "n+1=%d, type=%c, pts=%.3lf\n", n+1, FTYPE(vpriv->framebuf[n+1].type), (double)vpriv->framebuf[n+1].pts/27000000.0f);							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 int flush_buffers(muxer_t *muxer, int finalize){	int i, n, found;	int skip_cnt;	uint64_t 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;	double duration;	uint64_t iduration, iaduration;		/* 		analyzes all streams and decides what to flush		trying to respect an interleaving distribution		equal to the v_bitrate/a_bitrate proportion	*/	n = 0;	vs = as = NULL;	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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?