⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 muxer_mpeg.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 5 页
字号:
		(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 + -