muxer_mpeg.c

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

C
2,496
字号
		if(spriv->framebuf[idx].buffer == NULL)		{			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n");			return -1;		}		spriv->framebuf[idx].alloc_size = spriv->framebuf[idx].size + len;	}		memcpy(&(spriv->framebuf[idx].buffer[spriv->framebuf[idx].size]), ptr, len);	spriv->framebuf[idx].size += len;	spriv->framebuf[idx].pos = 0;	spriv->framebuf[idx].type = pt;	spriv->framebuf[idx].idur = idur;	spriv->framebuf[idx].dts = dts;	spriv->framebuf[idx].pts = pts;	spriv->framebuf_used++;	mp_msg(MSGT_MUXER, MSGL_DBG2, "\r\nAdded frame, size: %u, idur: %"PRIu64", dts: %"PRIu64", pts: %"PRIu64", used: %u\r\n", len, idur, dts, pts, spriv->framebuf_used);	return idx;}static int analyze_mpa(muxer_stream_t *s){	int i = 0, len, max, chans, srate, spf, layer;	int score[4] = {0, 0, 0, 0};		while(i < s->b_buffer_len + 3)	{		if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0))		{			len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL);			if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))			{				score[layer]++;				i += len;			}		}		i++;	}	max = 0;	layer = 2;	for(i = 1; i <= 3; i++)	{		if(score[i] >= max)		{			max = score[i];			layer = i;		}	}	return layer;	//actual layer with the highest score}extern int aac_parse_frame(uint8_t *buf, int *srate, int *num);static int parse_audio(muxer_stream_t *s, int finalize, unsigned int *nf, double *timer, double delay, int drop){	int i, j, len, chans, srate, spf, layer, dummy, tot, num, frm_idx;	int finished;	unsigned int frames;	uint64_t idur;	double dur;	muxer_headers_t *spriv = (muxer_headers_t *) s->priv;	i = tot = frames = 0;	finished = 0;	while(1)	{		len = 0;		switch(s->wf->wFormatTag)		{		case AUDIO_MP2:		case AUDIO_MP3:			{				if(i + 3 >= s->b_buffer_len)				{					finished = 1;					break;				}							if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0))				{					len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL);					if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len) 						&& layer == spriv->mpa_layer)					{						dur = (double) spf / (double) srate;						idur = (27000000ULL * spf) / srate;					}					else						len = 0;				}			}		break;		case AUDIO_A52:			{				if(i + 6 >= s->b_buffer_len)				{					finished = 1;					break;				}					if(s->b_buffer[i] == 0x0B && s->b_buffer[i+1] == 0x77)				{					srate = 0;				#ifdef USE_LIBA52					len = a52_syncinfo(&(s->b_buffer[i]), &dummy, &srate, &dummy);				#else					len = mp_a52_framesize(&(s->b_buffer[i]), &srate);				#endif					if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))					{						dur = (double) 1536 / (double) srate;						idur = (27000000ULL * 1536) / srate;					}					else						len = 0;				}			}		break;		case AUDIO_AAC1:		case AUDIO_AAC2:			{				if(i + 7 >= s->b_buffer_len)				{					finished = 1;					break;				}					if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xF6) == 0xF0))				{					len = aac_parse_frame(&(s->b_buffer[i]), &srate, &num);					if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len))					{						dur = (double) 1024 / (double) srate;						idur = (27000000ULL * 1024 * num) / srate;					}					else						len = 0;				}			}		}		if(finished)			break;		if(!len)		{			i++;			continue;		}				spriv->timer += dur;		if(spriv->drop_delayed_frames && delay < 0 && spriv->timer <= -delay)		{			i += len;			tot = i;			continue;		}		frames++;		fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot);		frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, spriv->last_pts, spriv->last_pts);		if(frm_idx < 0)		{			mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't add audio frame buffer(frame), abort\n");			goto audio_exit;		}		for(j = frm_idx; j < spriv->framebuf_cnt; j++)			spriv->framebuf[j].pts = spriv->last_pts;		spriv->last_pts += idur;		i += len;		tot = i;	}audio_exit:	if(tot)	{		memmove(s->b_buffer, &(s->b_buffer[tot]), s->b_buffer_len - tot);		s->b_buffer_len -= tot;		s->b_buffer_ptr += tot;		if(s->b_buffer_len > 0)			memmove(s->b_buffer, &(s->b_buffer[s->b_buffer_ptr]), s->b_buffer_len);		s->b_buffer_ptr = 0;	}	if(finalize)	{		frm_idx = add_frame(spriv, 0, s->b_buffer, s->b_buffer_len, 0, spriv->last_pts, spriv->last_pts);		if(frm_idx >= 0)		{			for(j = frm_idx; j < spriv->framebuf_cnt; j++)				spriv->framebuf[j].pts = spriv->last_pts;		}	}	*nf = frames;	*timer = spriv->timer;	return tot;}static void fix_parameters(muxer_stream_t *stream){	muxer_headers_t *spriv = stream->priv;	muxer_t *muxer = stream->muxer;	muxer_priv_t *priv = muxer->priv;	if(stream->type == MUXER_TYPE_AUDIO)	{		spriv->is_ready = 1;		if(conf_abuf_size)			spriv->max_buffer_size = conf_abuf_size*1024;		else		spriv->max_buffer_size = 4*1024;		if(stream->wf->wFormatTag == AUDIO_A52)		{			stream->ckid = be2me_32 (0x1bd);			if(priv->is_genmpeg1 || priv->is_genmpeg2)				fix_audio_sys_header(priv, spriv->id, 0xbd, FFMAX(conf_abuf_size, 58)*1024);	//only one audio at the moment			spriv->id = 0xbd;			if(!conf_abuf_size)			spriv->max_buffer_size = 16*1024;		}		else if(stream->wf->wFormatTag == AUDIO_AAC1 || stream->wf->wFormatTag == AUDIO_AAC2)		{			priv->use_psm = 1;		}		else if(stream->wf->wFormatTag == AUDIO_MP2 || stream->wf->wFormatTag == AUDIO_MP3)			spriv->is_ready = 0;	}	else	//video	{		if(conf_vbuf_size)			spriv->max_buffer_size = conf_vbuf_size*1024;		else		{		if(priv->is_dvd)			spriv->max_buffer_size = 232*1024;		else if(priv->is_xsvcd)			spriv->max_buffer_size = 230*1024;		else if(priv->is_xvcd)			spriv->max_buffer_size = 46*1024;		else			spriv->max_buffer_size = 232*1024;	//no profile => unconstrained :) FIXME!!!		}				if(is_mpeg4(stream->bih->biCompression))			spriv->is_ready = 0;		else			spriv->is_ready = 1;	}}static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags, double dts_arg, double pts_arg){  size_t sz = 0;  uint64_t tmp;  muxer_t *muxer = s->muxer;  muxer_priv_t *priv = (muxer_priv_t *)muxer->priv;  muxer_headers_t *spriv = (muxer_headers_t*) s->priv;  float fps;  uint32_t stream_format, nf;  if(s->buffer == NULL)  	return;  if(len == -1)	return;  if (s->type == MUXER_TYPE_VIDEO) { // try to recognize frame type...	fps = (float) s->h.dwRate/ (float) s->h.dwScale;  	spriv->type = 1;	stream_format = s->bih->biCompression;        if(! spriv->vframes)	{		spriv->last_dts = spriv->last_pts - (uint64_t)(27000000.0f/fps);		mp_msg(MSGT_MUXER, MSGL_INFO,"INITV: %.3lf, %.3lf, fps: %.3f\r\n", (double) spriv->last_pts/27000000.0f, (double) spriv->last_dts/27000000.0f, fps);	}    if(is_mpeg1(stream_format) || is_mpeg2(stream_format))    {      spriv->is_mpeg12 = 1;      spriv->is_ready = 1;      if(len)        sz = parse_mpeg12_video(s, priv, spriv, fps, len);      else {        tmp = (uint64_t) (27000000.0f / fps);        spriv->last_pts += tmp;        spriv->last_dts += tmp;      }    }    else if(is_mpeg4(stream_format))     {      spriv->is_mpeg12 = 0;      spriv->telecine = 0;      if(spriv->size == 0)        priv->use_psm = 1;      if(len)        sz = parse_mpeg4_video(s, priv, spriv, fps, len);      else {        tmp = (uint64_t) (27000000.0f / fps);        spriv->last_pts += tmp;        spriv->last_dts += tmp;      }    }    mp_msg(MSGT_MUXER, MSGL_DBG2,"mpegfile_write_chunk, Video codec=%x, len=%u, mpeg12 returned %u\n", stream_format, (uint32_t) len, (uint32_t) sz);  } else { // MUXER_TYPE_AUDIO  	double fake_timer;  	spriv->type = 0;	stream_format = s->wf->wFormatTag;	if(s->b_buffer_size - s->b_buffer_len < len)	{		if(s->b_buffer_len > SIZE_MAX - len)		{			mp_msg(MSGT_MUXER, MSGL_FATAL, "\nFATAL! couldn't realloc, integer overflow\n");			return;		}		s->b_buffer = realloc(s->b_buffer, len  + s->b_buffer_len);		if(s->b_buffer == NULL)		{			mp_msg(MSGT_MUXER, MSGL_FATAL, "\nFATAL! couldn't realloc %d bytes\n", len  + s->b_buffer_len);			return;		}				s->b_buffer_size = len  + s->b_buffer_len;		mp_msg(MSGT_MUXER, MSGL_DBG2, "REALLOC(%d) bytes to AUDIO backbuffer\n", s->b_buffer_size);	}	memcpy(&(s->b_buffer[s->b_buffer_ptr + s->b_buffer_len]), s->buffer, len);	s->b_buffer_len += len;		if(!spriv->is_ready)	{		if(s->b_buffer_len >= 32*1024)		{			spriv->mpa_layer = analyze_mpa(s);			spriv->is_ready = 1;		}	}	else	{	parse_audio(s, 0, &nf, &fake_timer, priv->init_adelay, priv->drop);	spriv->vframes += nf;	if(! spriv->vframes)		mp_msg(MSGT_MUXER, MSGL_INFO, "AINIT: %.3lf\r\n", (double) spriv->last_pts/27000000.0f);		}  }  if(spriv->psm_fixed == 0) {  	add_to_psm(priv, spriv->id, stream_format);	spriv->psm_fixed = 1;	priv->psm_streams_cnt++;	if((priv->psm_streams_cnt == muxer->num_videos + muxer->num_audios) && priv->use_psm)		write_psm_block(muxer, muxer->stream);  }  flush_buffers(muxer, 0);}static void mpegfile_write_index(muxer_t *muxer){	int i, nf;	double fake_timer;	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;	mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_WritingTrailer);	for(i = 0; i < muxer->avih.dwStreams; i++)	{		if(muxer->streams[i]->type == MUXER_TYPE_AUDIO)			parse_audio(muxer->streams[i], 1, &nf, &fake_timer, priv->init_adelay, priv->drop);	}	while(flush_buffers(muxer, 0) > 0);	flush_buffers(muxer, 1);	if(priv->is_genmpeg1 || priv->is_genmpeg2)	{		priv->scr = 0;		write_mpeg_pack(muxer, NULL, muxer->stream, 1);	//insert fake Nav Packet	}			mp_msg(MSGT_MUXER, MSGL_INFO, "\nOverhead: %.3lf%% (%"PRIu64" / %"PRIu64")\n", 100.0 * (double)priv->headers_size / (double)priv->data_size, priv->headers_size, priv->data_size);}static void mpegfile_write_header(muxer_t *muxer){	muxer_priv_t *priv = (muxer_priv_t*) muxer->priv;		mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_WritingHeader);		priv->headers_cnt++;		//write the first system header only for generic mpeg1/2 muxes, and only when we have collected all necessary infos	if(priv->is_genmpeg1 || priv->is_genmpeg2 || ((priv->is_xvcd || priv->is_xsvcd) && (priv->headers_cnt == 1)))	{		write_mpeg_pack(muxer, NULL, muxer->stream, 0);		priv->update_system_header = 0;	}		return;}static void setup_sys_params(muxer_priv_t *priv){	if(priv->is_dvd)	{		int v = (conf_vbuf_size ? conf_vbuf_size : 232);		int a1 = (conf_abuf_size ? conf_abuf_size : 4);		int a2 = (conf_abuf_size>58 ? conf_abuf_size : 58);		priv->sys_info.cnt = 4;				priv->sys_info.streams[0].id = 0xb9;		priv->sys_info.streams[0].type = 1;		priv->sys_info.streams[0].bufsize = v*1024;					priv->sys_info.streams[1].id = 0xb8;		priv->sys_info.streams[1].type = 0;		priv->sys_info.streams[1].bufsize = a1*1024;				priv->sys_info.streams[2].id = 0xbd;		priv->sys_info.streams[2].type = 1;		priv->sys_info.streams[2].bufsize = a2*1024;				priv->sys_info.streams[3].id = 0xbf;		priv->sys_info.streams[3].type = 1;		priv->sys_info.streams[3].bufsize = 2*1024;	}	else if(priv->is_xvcd || priv->is_xsvcd)	{		int v = (conf_vbuf_size ? conf_vbuf_size : (priv->is_xvcd ? 46: 230));		int a1 = (conf_abuf_size ? conf_abuf_size : 4);		priv->sys_info.cnt = 2;				priv->sys_info.streams[0].id = 0xe0;		priv->sys_info.streams[0].type = 1;		priv->sys_info.streams[0].bufsize = v*1024;					priv->sys_info.streams[1].id = 0xc0;		priv->sys_info.streams[1].type = 0;		priv->sys_info.streams[1].bufsize = a1*1024;	}	else		priv->sys_info.cnt = 0;}/* excerpt from DGPulldown Copyright (C) 2005-2006, Donald Graft */static void generate_flags(int source, int target){	unsigned int i, trfp;	uint64_t dfl,tfl;	unsigned char ormask[4] = {0x0, 0x2, 0x80, 0x82};		dfl = (target - source) << 1;	tfl = source >> 1;		trfp = 0;	for(i = 0; i < MAX_PATTERN_LENGTH; i++)	{		tfl += dfl;		if(tfl >= source)		{			tfl -= source;			bff_mask[i] = ormask[trfp + 1];			trfp ^= 2;		}		else			bff_mask[i] = ormask[trfp];	}}int muxer_init_muxer_mpeg(muxer_t *muxer){  muxer_priv_t *priv;  priv = (muxer_priv_t *) calloc(1, sizeof(muxer_priv_t));  if(priv == NULL)  	return 0;  priv->update_system_header = 1;  //calloc() already zero-ed all flags, so we assign only the ones we need  if(conf_mux != NULL) {    if(! strcasecmp(conf_mux, "mpeg1"))    {    	priv->mux = MUX_MPEG1;	priv->packet_size = 2048;	priv->is_genmpeg1 = 1;	priv->muxrate = 1800 * 125;	//Constrained parameters    }

⌨️ 快捷键说明

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