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

📄 muxer_mpeg.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 5 页
字号:
		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);	}}#define max(a, b) ((a) >= (b) ? (a) : (b))#define min(a, b) ((a) <= (b) ? (a) : (b))static uint32_t get_audio_frame_size(muxer_headers_t *spriv, uint8_t *buf, int format, int samples_ps){	uint32_t sz, tmp, spf;	#ifdef USE_LIBA52#include "../liba52/a52.h"	if(format == 0x2000)	{		int t1, t2, t3;		sz = (uint32_t) a52_syncinfo(buf, &t1, &t2, &t3);		if(sz)			return sz;	}#endif	if(format == 0x2000)		spf = 1536;	else if((format == 0x55) && (samples_ps < 32000))		spf = 576;	else		spf = 1152;	tmp = spriv->bitrate * spf;	sz = tmp / samples_ps;	if(sz % 2)		sz++;			return sz;}static int reorder_frame(muxer_headers_t *spriv, uint8_t *ptr, size_t len, uint8_t pt, uint32_t temp_ref, uint64_t idur){	uint16_t idx = 0, move=0;		/*	HOW TO REORDER FRAMES IN DECODING ORDER:		current frame is n		IF pt(n)==I or P and			n>0 && temp_ref(n) > temp_ref(n-1) && pt(n-1 .. n-m)==B				then insert frame n before frame n-m 				and shift forward the others	*/	idx = spriv->framebuf_used;	if(spriv->reorder)	{		//stores the frame in decoding order		if((idx > 0) && ((pt == I_FRAME) || (pt == P_FRAME)))		{			if((spriv->framebuf[idx - 1].type == B_FRAME) && (spriv->framebuf[idx - 1].temp_ref == temp_ref-1))			{				while((spriv->framebuf[idx - 1].type == B_FRAME) && (spriv->framebuf[idx - 1].temp_ref < temp_ref) && (idx > 0))					idx--;				move = spriv->framebuf_used - idx;	//from idx there are 'move' frames to move forward			}		}	}		//now idx is the position where we should store the frame 	if(idx+move >= spriv->framebuf_cnt)	{	//realloc		//fprintf(stderr, "\nREALLOC1: %d\n", (int) spriv->framebuf_cnt+1);		spriv->framebuf = (mpeg_frame_t*) realloc(spriv->framebuf, (spriv->framebuf_cnt+1)*sizeof(mpeg_frame_t));		if(spriv->framebuf == NULL)		{			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(idx), abort\n");			return 0;		}				spriv->framebuf[spriv->framebuf_cnt].size = 0;		spriv->framebuf[spriv->framebuf_cnt].alloc_size = 0;				spriv->framebuf[spriv->framebuf_cnt].buffer = (uint8_t*) malloc(len);		if(spriv->framebuf[spriv->framebuf_cnt].buffer == NULL)		{			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n");			return 0;		}		spriv->framebuf[spriv->framebuf_cnt].alloc_size = len;				spriv->framebuf_cnt++;	}			while(move > 0)	{		mpeg_frame_t f;				f = spriv->framebuf[move + idx];		spriv->framebuf[move + idx] = spriv->framebuf[move + idx - 1];		spriv->framebuf[move + idx - 1] = f;		move--;	}		if(spriv->framebuf[idx].alloc_size < len)	{		spriv->framebuf[idx].buffer = realloc(spriv->framebuf[idx].buffer, len);		if(spriv->framebuf[idx].buffer == NULL)		{			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n");			return 0;		}		spriv->framebuf[idx].alloc_size = len;	}		mp_msg(MSGT_MUXER, MSGL_DBG2, "\nIDX: %u, type: %c, temp_ref: %u, ptr: %p, len: %u, alloc: %u, buffer: %p\n", 		(uint32_t) idx, FTYPE(pt), temp_ref, ptr, (uint32_t) len, (uint32_t) spriv->framebuf[idx].alloc_size, spriv->framebuf[idx].buffer);			memcpy(spriv->framebuf[idx].buffer, ptr, len);	spriv->framebuf[idx].size = len;	spriv->framebuf[idx].temp_ref = temp_ref;	spriv->framebuf[idx].type = pt;	spriv->framebuf[idx].idur = idur;	spriv->framebuf_used++;		return 1;}static uint32_t dump_audio(muxer_t *muxer, muxer_stream_t *as, uint32_t abytes, int force){	uint32_t len = 0, sz;	uint64_t num_frames = 0, next_pts;	uint16_t rest;	int64_t tmp;	double delta_pts;	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;	muxer_headers_t *apriv = (muxer_headers_t*) as->priv;		if((abytes < apriv->frame_size) && (! force))	//pl_size	//if((abytes < apriv->max_pl_size) && (! force))	//pl_size	{		apriv->is_late = 1;		mp_msg(MSGT_MUXER, MSGL_V, "NOT SAVING: %u bytes\n", abytes);		return 0;	}		abytes = min(abytes, as->b_buffer_len);			//available bytes	if(! abytes)		return 0;	if(as->ckid == be2me_32(0x1bd))		apriv->has_pes_priv_headers = 4;	else		apriv->has_pes_priv_headers = 0;	rest = (apriv->size % apriv->frame_size);	if(rest)		rest = apriv->frame_size - rest;		sz = priv->packet_size - calc_pack_hlen(priv, apriv);	//how many payload bytes we are about to write	num_frames = (sz + apriv->frame_size - 1 - rest) / apriv->frame_size;		mp_msg(MSGT_MUXER, MSGL_V, "\nAUDIO: tot=%llu, sz=%u bytes, FRAMES: %llu * %u, REST: %u, DELTA_PTS: %u\n", 		apriv->size, sz, num_frames, (uint32_t) apriv->frame_size, (uint32_t) rest, (uint32_t) ((num_frames * apriv->delta_pts) >> 10));		next_pts = ((uint64_t) (num_frames * apriv->delta_pts)) + apriv->pts;	if(((priv->scr + (63000*1024)) < next_pts) && (priv->scr < apriv->pts) && (! force))	{		apriv->is_late = 1;		return 0;	}	if(as->ckid == be2me_32(0x1bd))	{		apriv->pes_priv_headers[0] = 0x80;		apriv->pes_priv_headers[1] = num_frames;		apriv->pes_priv_headers[2] = ((rest+1) >> 8) & 0xff;	//256 * 0 ...		apriv->pes_priv_headers[3] = (rest+1) & 0xff;		// + 1 byte(s) to skip	}		if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0)		apriv->buffer_size = 4*1024;	if(apriv->pts < priv->scr)		mp_msg(MSGT_MUXER, MSGL_ERR, "\nERROR: SCR: %llu, APTS: %llu, DELTA=-%.3lf secs\n", 			priv->scr, apriv->pts, (double) ((priv->scr - apriv->pts)/92160000.0));		len = write_mpeg_pack(muxer, as, muxer->file, &(as->b_buffer[as->b_buffer_ptr]), abytes, 0);	if((priv->is_xsvcd || priv->is_xvcd) && apriv->size == 0)		apriv->buffer_size = 0;		apriv->size += len;	apriv->pts = next_pts;		mp_msg(MSGT_MUXER, MSGL_DBG2, "NUM_FRAMES: %llu\n", num_frames);		tmp = apriv->pts - priv->scr;	if((abs(tmp) > (63000*1024)) || (apriv->pts <= priv->scr))	{		double d;		d = (double) apriv->frame_size / (double) apriv->bitrate;		d *= (tmp - (63000*1024));		apriv->compensate = (uint32_t) d;				if(abs(tmp) > 92160000)	//usually up to 1 second it still acceptable			mp_msg(MSGT_MUXER, MSGL_ERR, "\nWARNING: SCR: %llu, APTS: %llu, DELTA=%.3lf secs, BYTES=%d\n", priv->scr, apriv->pts, 				(((double) tmp)/92160000.0), apriv->compensate);	}	mp_msg(MSGT_MUXER, MSGL_V, "\nWRITTEN AUDIO: %u bytes, TIMER: %.3lf, FRAMES: %llu * %u, DELTA_PTS: %.3lf\n", 		len, (double) (apriv->pts/92160000), num_frames, (uint32_t) apriv->frame_size, delta_pts);		as->b_buffer_ptr += len;	as->b_buffer_len -= len;		if(as->b_buffer_len > 0)		memmove(as->b_buffer, &(as->b_buffer[as->b_buffer_ptr]), as->b_buffer_len);	as->b_buffer_ptr = 0;		return len;}static void drop_delayed_audio(muxer_t *muxer, muxer_stream_t *as, int64_t size){	//muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;	muxer_headers_t *apriv = (muxer_headers_t *) as->priv;	int64_t size1, div, rest;	//initial value	double rest_pts;		div = size / apriv->frame_size;	rest = size % apriv->frame_size;	if(rest >= apriv->frame_size / 2)		size1 = (div+1) * apriv->frame_size;	else		size1 = (div) * apriv->frame_size;	fprintf(stderr, "SIZE1: %llu, LEN: %llu\n", size1, (uint64_t)as->b_buffer_len);	size1 = min(size1, as->b_buffer_len);	memmove(as->b_buffer, &(as->b_buffer[size]), as->b_buffer_len - size1);	as->b_buffer_len -= size1;		rest = size1 - size;	rest_pts = (double) rest / (double) apriv->bitrate;	apriv->pts += (int64_t) (92160000.0 * rest_pts);	mp_msg(MSGT_MUXER, MSGL_V, "DROPPED: %lld bytes, REST= %lld, REST_PTS: %.3lf, AUDIO_PTS%.3lf\n", size1, rest, rest_pts, (double) (apriv->pts/92160000.0));}static void save_delayed_audio(muxer_t *muxer, muxer_stream_t *as, uint64_t dur){	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;	muxer_headers_t *apriv = (muxer_headers_t *) as->priv;	uint64_t init_pts, last_pts;	//initial value		init_pts = apriv->pts;	mp_msg(MSGT_MUXER, MSGL_V, "DUR: %llu, DIFF: %llu\n", dur, apriv->pts - init_pts);	while(dur > apriv->pts - init_pts)	{		priv->scr = (92160000 * apriv->size) / apriv->bitrate;		last_pts = apriv->pts;		dump_audio(muxer, as, as->b_buffer_len, 0);		mp_msg(MSGT_MUXER, MSGL_V, "DUR: %llu, DIFF: %llu, SCR: %llu\n", dur, apriv->pts - init_pts, priv->scr);	}		//priv->init_delay_pts = last_pts;	priv->init_delay_pts = (90 * 1024 * abs(conf_init_adelay)) + apriv->init_pts - (90 * 1024 * abs(conf_init_vpts));	if(priv->init_delay_pts <= priv->scr)		priv->init_delay_pts = last_pts;	mp_msg(MSGT_MUXER, MSGL_INFO, "INIT_VPTS: %llu (%.3lf)\n", priv->init_delay_pts, (double) (priv->init_delay_pts/92160000.0));}static inline void update_scr(muxer_priv_t *priv, uint32_t len, uint32_t totlen, double mult){	uint64_t delta_scr;	double perc;		perc = (double) len / (double) totlen;		delta_scr = (uint64_t) (mult * perc);	priv->scr += delta_scr;		mp_msg(MSGT_MUXER, MSGL_V, "UPDATE SCR TO %llu (%.3lf): mult is %.3lf,  perc: %.3lf, %u/%u, delta: %llu\n", 		priv->scr, (double) (priv->scr/92160000.0), mult, perc, len, totlen, delta_scr);}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_V, "\n");		while(n < vpriv->framebuf_used)		{			mp_msg(MSGT_MUXER, MSGL_V, "n=%d, type=%c, temp_ref=%u\n", n, FTYPE(vpriv->framebuf[n].type), vpriv->framebuf[n].temp_ref);			if(n+1 < vpriv->framebuf_used)				mp_msg(MSGT_MUXER, MSGL_V, "n+1=%d, type=%c, temp_ref=%u\n", n+1, FTYPE(vpriv->framebuf[n+1].type), vpriv->framebuf[n+1].temp_ref);							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 uint64_t fix_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int n){	int i, j, fixed = 0;	uint64_t last_dts, last_idur, ret;	uint32_t mintr, maxtr;	ret = 0;	if((vpriv->size == 0) && (fixed == 0))	//first pts adjustment, only at the beginning of the stream to manage BBI structures	{		int delay = 0;		for(i = 0; i < n; i++)		{			if(vpriv->framebuf[i].type == I_FRAME)			{				for(j = i + 1; j < n; j++)				{					if(vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref)					{						ret += vpriv->framebuf[j].idur;						delay++;						fixed = 1;					}				}				if(fixed)					break;			}		}				if(! fixed)			ret = 0;		else			vpriv->last_pts += ret;				mp_msg(MSGT_MUXER, MSGL_INFO, "INITIAL DELAY of %d frames\n", delay);	}		//KLUDGE BEGINS: Gop header (0x000001b8 in the video stream that signals a temp_ref wraparound) is _not_ mandatory, 	//so if we don't detect the right wraparound we will have a totally wrong timestamps assignment; let's go on	mintr = vpriv->framebuf[0].temp_ref;	maxtr = vpriv->framebuf[0].temp_ref;	for(i = 0; i < n; i++)	{		mintr = min(vpriv->framebuf[i].temp_ref, mintr);		maxtr = max(vpriv->framebuf[i].temp_ref, maxtr);	}	if(maxtr - mintr > 600)	//there must be a temp_ref wraparound	{		mp_msg(MSGT_MUXER, MSGL_INFO, "\nDETECTED possible temp_ref wraparound in the videostreams: n=%d, mintr=%u, maxtr=%u\n", n, mintr, maxtr);		for(i = 0; i < n; i++)		{			if(vpriv->framebuf[i].temp_ref < 1000)				vpriv->framebuf[i].temp_ref += 1024;		}		}	//KLUDGE ENDS			for(i = 0; i < n; i++)	{		vpriv->framebuf[i].pts = vpriv->last_pts;				for(j = 0; j < n; j++)		{			if((vpriv->framebuf[i].temp_ref >= vpriv->framebuf[j].temp_ref) && (i != j))			{				vpriv->framebuf[i].pts += vpriv->framebuf[j].idur;			}		}	}	if(vpriv->size == 0)		last_dts = vpriv->init_dts = vpriv->framebuf[0].pts - (ret + vpriv->framebuf[0].idur);	else		last_dts = vpriv->last_dts;		last_idur = 0;		mp_msg(MSGT_MUXER, MSGL_V, "\n");	for(i = 0; i < n; i++)	{		vpriv->framebuf[i].dts = last_dts + last_idur;		last_idur = vpriv->framebuf[i].idur;		last_dts = vpriv->framebuf[i].dts;		mp_msg(MSGT_MUXER, MSGL_V, "I=%d, type: %c, TR: %u, pts=%.3lf, dts=%.3lf, size=%u\n", 			i, FTYPE(vpriv->framebuf[i].type), vpriv->framebuf[i].temp_ref, (double) (vpriv->framebuf[i].pts/92160000.0), 			(double) (vpriv->framebuf[i].dts/92160000.0), vpriv->framebuf[i].size);	}		if((vpriv->size == 0) && (priv->init_delay_pts > 0))	{		uint64_t diff;				for(i = 0; i < vpriv->framebuf_used; i++)		{			vpriv->framebuf[i].pts += priv->init_delay_pts;			vpriv->framebuf[i].dts += priv->init_delay_pts;		}				diff = vpriv->framebuf[0].pts - vpriv->framebuf[0].dts;		if(vpriv->init_pts >= diff)			vpriv->init_dts = vpriv->init_pts - diff;		else			vpriv->init_dts = diff;				vpriv->last_dts +=  priv->init_delay_pts;				vpriv->init_pts = 0;		vpriv->last_pts +=  priv->init_delay_pts;				priv->init_delay_pts = 0;		mp_msg(MSGT_MUXER, MSGL_INFO, "INIT delayed video timestamps: PTS=%.3lf, DTS=%.3lf, DUR=%.3lf\n", 			(double) (vpriv->last_pts/92160000.0), (double) (vpriv->last_dts/92160000.0), (double) (vpriv->framebuf[0].idur/92160000.0));	}		return ret;}static void check_pts(muxer_priv_t *priv, muxer_headers_t *vpriv, int i){	uint64_t dpts;		dpts = max(vpriv->last_saved_pts, vpriv->pts) - min(vpriv->last_saved_pts, vpriv->pts);	dpts += vpriv->framebuf[i].idur;	if((!priv->ts_allframes) && (

⌨️ 快捷键说明

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