play_asf.c

来自「1. 8623L平台」· C语言 代码 · 共 1,567 行 · 第 1/4 页

C
1,567
字号
	RMDBGLOG((ENABLE, "Should seek to %ld s\n", seekTo));	// must be in milliseconds	seekTo *= 1000;#ifndef EM86XX_DEBUG_AUDIO	asf_Stop(pSendContext, RM_DEVICES_STC | RM_DEVICES_AUDIO | RM_DEVICES_VIDEO);#endif	position = RMASFVDemuxSeek(pSendContext->vASFDemux, &seekTo);	if (position == 0) {		RMDBGLOG((ENABLE, "seek failed, restarting\n"));		RMSeekFile(pSendContext->f_bitstream, pSendContext->asf_Header_Object_Size+50, RM_FILE_SEEK_START);		/* presets the demux to start parsing first packet */		RMASFVDemuxResetState(pSendContext->vASFDemux);		seekTo = 0;	}	else		RMSeekFile(pSendContext->f_bitstream, position, RM_FILE_SEEK_START);	RMGetCurrentPositionOfFile (pSendContext->f_bitstream, &position);	RMDBGLOG((ENABLE, "Seeked to %ld s, pos %llu\n", seekTo/1000, position));	       	pSendContext->FirstSystemTimeStamp = TRUE;	if ((pSendContext->isWMAPRO) && (pSendContext->audio_parameters[pSendContext->audio_stream_index].enabled)) {		if (pSendContext->vDecoder != NULL) {			RMDBGLOG((ENABLE, "close wmapro decoder\n"));			RMWMAProVDecoderClose(pSendContext->vDecoder);						RMDBGLOG((ENABLE, "open wmapro decoder\n"));			RMWMAProVDecoderOpen(pSendContext->vDecoder);		}		else			RMDBGLOG((ENABLE, "no wmapro decoder created!\n"));	}		pSendContext->IFrameFSMState = RMasfIFrameFSM_Disabled;	pSendContext->SeekAudio = TRUE;	pSendContext->SeekVideo = TRUE;	pSendContext->audioSamplesDropped = FALSE;#ifndef EM86XX_DEBUG_AUDIO	/* the stc will be put into "play" mode with the first pts */	asf_Play(pSendContext, RM_DEVICES_AUDIO | RM_DEVICES_VIDEO, DCCVideoPlayFwd);#endif#if 0	{		RMstatus err;		/* restart recording data after the seek */		RMDBGLOG((ENABLE, "restarting save data\n"));		err = close_save_files(pSendContext->play_opt);		if (RMFAILED(err)) {			fprintf(stderr, "Cannot close files used to save data %d\n", err);			return RM_ERROR;		}		err = open_save_files(pSendContext->play_opt);		if (RMFAILED(err)) {			fprintf(stderr, "cannot open files to save data %d\n", err);			return RM_ERROR;		}	}#endif	return RM_OK;}static RMstatus asf_InitIFrameTrickMode(struct asf_context* pSendContext){	RMstatus err = RM_OK;	RMint64 position = 0;	RMuint32 size, packet;	RMint32 N;	RMuint32 M;	enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info));		DCCSTCGetSpeed(pSendContext->dcc_info->pStcSource, &N, &M);	RMDBGLOG((ENABLE, "Init IFrame trickmode, speed is %ld/%lu\n", N, M));	if (PlaybackStatus == RM_PSM_IForward) 		pSendContext->IFrameDirection = 1;	else if (PlaybackStatus == RM_PSM_IRewind) 		pSendContext->IFrameDirection = -1;	else {		RMDBGLOG((ENABLE, "cant determine iframe trickmode playback direction, defaulting to forward!"));		pSendContext->IFrameDirection = 1;	}	{		RMuint64 currentPTS;		RUAGetProperty(pSendContext->pRUA, pSendContext->dcc_info->SurfaceID, RMGenericPropertyID_CurrentDisplayPTS, &(pSendContext->CurrentDisplayPTS), sizeof(RMuint64));		if (pSendContext->video_vop_tir == 90000)			pSendContext->CurrentDisplayPTS *= 2;				RMDBGLOG((ENABLE, "updated display pts %llu s\n", pSendContext->CurrentDisplayPTS));		currentPTS = round_int_div(pSendContext->CurrentDisplayPTS, (RMuint32) pSendContext->video_vop_tir);		RMDBGLOG((ENABLE, "has to find position of time %llu s\n", currentPTS));		asf_seek(pSendContext, currentPTS);		RMGetCurrentPositionOfFile(pSendContext->f_bitstream, &position);		RMDBGLOG((ENABLE, "setting start position to %llu\n", position));		pSendContext->CurrentDisplayPTS = 0;	}	RMDBGLOG((ENABLE, "playing trickmode...direction %s\n", (pSendContext->IFrameDirection >= 0) ? "forward":"backward"));	err = RMASFVDemuxSetTrickModeDirection(pSendContext->vASFDemux, pSendContext->IFrameDirection);	if (err != RM_OK)		return RM_ERROR;	err = RMASFVDemuxInitTrickMode(pSendContext->vASFDemux, (RMuint64 *)&position);	if (err != RM_OK)		return RM_ERROR;		/* skip the IFrame we just seeked to */	err = RMASFVDemuxGetNextIFrame(pSendContext->vASFDemux, (RMuint64 *)&position, &size, &packet);	if (err != RM_OK)		return RM_ERROR;		RMSeekFile(pSendContext->f_bitstream, position, RM_FILE_SEEK_START);	RMDBGLOG((ENABLE, "skipping one iframe at pos %llu, size %lu, packet %lu\n", position, size, packet));	RMDBGLOG((ENABLE, "flush video...\n"));	asf_Stop(pSendContext, RM_DEVICES_VIDEO);	pSendContext->IFrameSize = 0;	pSendContext->IFrameFSMState = RMasfIFrameFSM_Init;	pSendContext->SeekAudio = FALSE;	pSendContext->SeekVideo = FALSE;	asf_Play(pSendContext, RM_DEVICES_VIDEO | RM_DEVICES_STC, DCCVideoPlayIFrame);#if 0	{		RMstatus err;		/* restart recording data after the seek */		RMDBGLOG((ENABLE, "restarting save data\n"));		err = close_save_files(pSendContext->play_opt);		if (RMFAILED(err)) {			fprintf(stderr, "Cannot close files used to save data %d\n", err);			return RM_ERROR;		}		err = open_save_files(pSendContext->play_opt);		if (RMFAILED(err)) {			fprintf(stderr, "cannot open files to save data %d\n", err);			return RM_ERROR;		}	}#endif		return RM_OK;}static RMstatus asf_ResumeFromIFrameTrickMode(struct asf_context * pSendContext){	RMstatus err = RM_OK;	RMuint64 time;	RMuint64 roundUpTime;	err = RUAGetProperty(pSendContext->pRUA, pSendContext->dcc_info->SurfaceID, RMGenericPropertyID_CurrentDisplayPTS, &time, sizeof(time));	if (pSendContext->video_vop_tir == 90000)		time *= 2;	RMDBGLOG((ENABLE, "resume from trickmode at %llu in %ld units\n", time, pSendContext->video_vop_tir));	pSendContext->CurrentDisplayPTS = (time * 1000) / pSendContext->video_vop_tir;	roundUpTime = time / pSendContext->video_vop_tir;	if ((time - (roundUpTime * pSendContext->video_vop_tir)) > 0)		roundUpTime++;	RMDBGLOG((ENABLE, "seeking to %llu ms => adj time is %llu\n", time, roundUpTime));	asf_seek(pSendContext, roundUpTime);	DCCSTCSetSpeed(pSendContext->dcc_info->pStcSource, pSendContext->play_opt->speed_N, pSendContext->play_opt->speed_M);	//asf_Stop(pSendContext, RM_DEVICES_STC);	asf_Pause(pSendContext, RM_DEVICES_STC | RM_DEVICES_VIDEO | RM_DEVICES_AUDIO);	RM_PSM_SetState(pSendContext->PSMcontext, &(pSendContext->dcc_info), RM_PSM_Prebuffering);	return RM_OK;}static RMstatus asf_FastAudioRecovery(struct asf_context * pSendContext){	RMstatus err = RM_OK;	RMuint64 time;	RMuint64 roundUpTime;	if ((!pSendContext->audioSamplesDropped) && (pSendContext->sendAudioTrickmode)) {		RMDBGLOG((ENABLE, "FastAudioRecovery: -sat was also enabled and there were no audio samples dropped during trickmodes, ignore\n"));		return RM_OK;	}	else if (pSendContext->sendAudioTrickmode)		RMDBGLOG((ENABLE, "FastAudioRecovery: -sat was also enabled but we dropped audio samples\n"));	err = RUAGetProperty(pSendContext->pRUA, pSendContext->dcc_info->SurfaceID, RMGenericPropertyID_CurrentDisplayPTS, &time, sizeof(time));	if (pSendContext->video_vop_tir == 90000)		time *= 2;	RMDBGLOG((ENABLE, "FastAudioRecovery: resume from trickmode at %llu in %ld units\n", time, pSendContext->video_vop_tir));	roundUpTime = time / pSendContext->video_vop_tir;	if ((time - (roundUpTime * pSendContext->video_vop_tir)) > 0)		roundUpTime++;	RMDBGLOG((ENABLE, "seeking to %llu ms => adj time is %llu\n", time, roundUpTime));	asf_seek(pSendContext, roundUpTime);	DCCSTCSetSpeed(pSendContext->dcc_info->pStcSource, pSendContext->play_opt->speed_N, pSendContext->play_opt->speed_M);	//asf_Stop(pSendContext, RM_DEVICES_STC);	asf_Pause(pSendContext, RM_DEVICES_STC | RM_DEVICES_VIDEO | RM_DEVICES_AUDIO);	RM_PSM_SetState(pSendContext->PSMcontext, &(pSendContext->dcc_info), RM_PSM_Prebuffering);	return RM_OK;}static RMstatus restartAudioDecoder(struct asf_context * pSendContext){	RMuint64 stc;	if (!pSendContext->audio_parameters[pSendContext->audio_stream_index].enabled)		return RM_ERROR;	RMDBGLOG((ENABLE, "restart audio decoder\n"));#ifndef	EM86XX_DEBUG_AUDIO	asf_Stop(pSendContext, RM_DEVICES_AUDIO);#endif	if (pSendContext->isWMAPRO) {		if (pSendContext->vDecoder != NULL) {			RMDBGLOG((ENABLE, "close wmapro decoder\n"));			RMWMAProVDecoderClose(pSendContext->vDecoder);						RMDBGLOG((ENABLE, "open wmapro decoder\n"));			RMWMAProVDecoderOpen(pSendContext->vDecoder);		}		else			RMDBGLOG((ENABLE, "no wmapro decoder created!\n"));	}	pSendContext->audio_decoder_initialized = FALSE;	 	//get the time in 1000th units because presentation time from ASF is always in 1/1000 	DCCSTCGetTime(pSendContext->dcc_info->pStcSource, &stc, 1000);	RMDBGLOG((ENABLE, ">> stc is %llu\n", stc));	if ((!pSendContext->VideoStreamFound) && (pSendContext->AudioStreamFound)) {		RMuint64 time;		pSendContext->accurateAudioSeekTo = stc;		time = stc / 1000;		time -= 2;		RMDBGLOG((ENABLE, "seeking to %llu s\n", time));		if ((RMint64)time >= 0)			asf_seek(pSendContext, time);		else			asf_seek(pSendContext, 0);				DCCSTCSetSpeed(pSendContext->dcc_info->pStcSource, pSendContext->play_opt->speed_N, pSendContext->play_opt->speed_M);		RM_PSM_SetState(pSendContext->PSMcontext, &(pSendContext->dcc_info), RM_PSM_Playing);		RMDBGLOG((ENABLE, "accurate audio seek to %llu\n", stc));		asf_Stop(pSendContext, RM_DEVICES_STC);	}#ifndef	EM86XX_DEBUG_AUDIO	asf_Play(pSendContext, RM_DEVICES_AUDIO, 0);#endif	return RM_OK;}static RMstatus readBitstream(struct asf_context *pSendContext, RMuint8 *buffer, RMuint32 *bytesRead){	RMstatus status;	RMuint64 position;	RMuint32 size, packet;	RMuint32 count;	RMuint32 buffersize;	RMuint32 alignedPacket;	enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info));	buffersize = (1 << pSendContext->play_opt->dmapool_log2size);	if (pSendContext->drmError) {		RMDBGLOG((ENABLE, "there was a decryption error, abort playback\n"));		return RM_DRM_DECRYPTION_FAILED;	}	/* The Microsoft Janus DRM requires ASF data packets to be contiguous for decryption.	 * If the file is Janus encrypted, an integer multiple of ASF data packets will be	 * read into the RUA buffer (i.e. the read size is truncated).  If the file is not	 * Janus encrypted, the entire RUA buffer will be filled. */	if (pSendContext && pSendContext->asf_packetSize && pSendContext->isContentEncrypted) {		/* In case we play the file completely sequentially, the		 * asf_packetSize is not known at the first read, since we		 * haven't parsed the stream yet, so use default size if		 * asf_packetSize == 0 */		alignedPacket = (buffersize/pSendContext->asf_packetSize)*pSendContext->asf_packetSize;		buffersize = alignedPacket;					if (((RMuint32) (1 << pSendContext->play_opt->dmapool_log2size)) < pSendContext->asf_packetSize) {				RMDBGLOG((ENABLE, "** Read Buffers too small\n"));				return RM_ERROR;		}	}	if ((PlaybackStatus != RM_PSM_Playing) && (PlaybackStatus != RM_PSM_Prebuffering)) {		if (pSendContext->isIFrameMode) {			if (pSendContext->IFrameSize == 0) {				RMuint32 sizeToRead;				status = RMASFVDemuxGetNextIFrame(pSendContext->vASFDemux, &position, &size, &packet);				RMDBGLOG((TRICKDBG, "got iframe at pos(%llu), size(%lu), packet(%lu)\n", position, size, packet));				if (status != RM_OK) {					RMDBGLOG((ENABLE, "error getting next iframe\n"));					return status;				}								RMSeekFile(pSendContext->f_bitstream, position, RM_FILE_SEEK_START);				pSendContext->IFrameFSMState = RMasfIFrameFSM_Init;				pSendContext->IFrameSize = size;				sizeToRead = RMmin(buffersize, size);				RMDBGLOG((READ_DBG, "read %lu bytes\n", sizeToRead));				status = RMReadFile(pSendContext->f_bitstream, buffer, sizeToRead, &count);								pSendContext->IFrameSize -= (RMint32)count;				if (pSendContext->IFrameSize <= 0)					pSendContext->IFrameSize = 0;				RMDBGLOG((TRICKDBG, "filled buffer with %lu bytes, should read %lu, left %lu\n", count, sizeToRead, pSendContext->IFrameSize));			}			else {				RMuint32 sizeToRead = RMmin(buffersize, (RMuint32)pSendContext->IFrameSize);				RMDBGLOG((READ_DBG, "read %lu bytes\n", sizeToRead));								status = RMReadFile(pSendContext->f_bitstream, buffer, sizeToRead, &count);				pSendContext->IFrameSize -= (RMint32)count;				if (pSendContext->IFrameSize <= 0)					pSendContext->IFrameSize = 0;				RMDBGLOG((TRICKDBG, "filled buffer with %lu bytes, should read %lu, left %lu\n", count, sizeToRead, pSendContext->IFrameSize));			}						}		else if ((!pSendContext->VideoStreamFound) && (pSendContext->AudioStreamFound))			return RM_SKIP_DATA;		else {			RMDBGLOG((READ_DBG, "read %lu bytes\n", buffersize));			status = RMReadFile(pSendContext->f_bitstream, buffer, buffersize, &count);			if (status == RM_OK && pSendContext && pSendContext->asf_packetSize && pSendContext->isContentEncrypted && buffersize != count) {				RMDBGLOG((ENABLE, "ERROR: buffersize=%lu, count=%lu, status=%d\n", buffersize, count, (int)status));				count = (count/pSendContext->asf_packetSize)*pSendContext->asf_packetSize;				RMDBGLOG((ENABLE,"SOLVE: count=%lu, asf_packet_size=%lu\n", count, pSendContext->asf_packetSize));				status = RM_ERRORENDOFFILE;

⌨️ 快捷键说明

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