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

📄 play_video.c

📁 Sample code for use on smp 863x processor.
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;			case Profile_MPEG2_SD:	case Profile_MPEG2_DVD:	case Profile_MPEG2_HD:	case Profile_MPEG2_SD_Packed:	case Profile_MPEG2_HD_Packed:	case Profile_MPEG2_DVD_Packed:	case Profile_MPEG2_SD_DeInt:	case Profile_MPEG2_DVD_DeInt:	case Profile_MPEG2_HD_DeInt:	case Profile_MPEG2_SD_Packed_DeInt:	case Profile_MPEG2_DVD_Packed_DeInt:	case Profile_MPEG2_HD_Packed_DeInt:		RMDBGLOG((ENABLE, "MPEG 2 video\n"));		break;			case Profile_DIVX3_SD:	case Profile_DIVX3_HD:	case Profile_DIVX3_SD_Packed: 	case Profile_DIVX3_HD_Packed:		RMDBGLOG((ENABLE, "DIVX3 video\n"));		break;			case Profile_WMV_SD:	case Profile_WMV_816P:	case Profile_WMV_HD:		RMDBGLOG((ENABLE, "WMV9 video\n"));		break;			case Profile_MPEG4_SD:	case Profile_MPEG4_HD:	case Profile_MPEG4_SD_Packed:	case Profile_MPEG4_HD_Packed:	case Profile_MPEG4_SD_DeInt:	case Profile_MPEG4_HD_DeInt:	case Profile_MPEG4_SD_Packed_DeInt:	case Profile_MPEG4_HD_Packed_DeInt:	case Profile_MPEG4_SD_Padding:	case Profile_MPEG4_HD_Padding:	case Profile_MPEG4_SD_DeInt_Padding:	case Profile_MPEG4_HD_DeInt_Padding:		RMDBGLOG((ENABLE, "MPEG4 video. Set video timescale\n"));		if (!context.video_opt->vtimescale.enable) {			context.video_opt->vtimescale.enable = TRUE;			context.video_opt->vtimescale.time_resolution = 90000;		}		break;	case Profile_VC1_SD:	case Profile_VC1_HD:		RMDBGLOG((ENABLE, "VC1 video\n"));		break;			case Profile_H264_SD:	case Profile_H264_HD:	case Profile_H264_SD_DeInt:	case Profile_H264_HD_DeInt:		RMDBGLOG((ENABLE, "H264 video\n"));		break;	}	// apply the fixed vop rate if required	err = apply_video_decoder_options(&dcc_info, context.video_opt);	if (RMFAILED(err)) {		RMDBGLOG((ENABLE, "Error applying video_decoder_options %d\n", err));		goto cleanup;	}#ifndef WITH_MONO	set_default_out_window(&(dcc_info.disp_info->out_window));	set_default_out_window(&(dcc_info.disp_info->osd_window[0]));	set_default_out_window(&(dcc_info.disp_info->osd_window[1]));	dcc_info.disp_info->active_window = &(dcc_info.disp_info->out_window);	dcc_info.disp_info->video_enable = TRUE;	err = apply_display_options(&dcc_info, context.disp_opt);	if (RMFAILED(err)) {		RMDBGLOG((ENABLE, "Cannot set display options %d\n", err));		goto cleanup;	}	display_key_usage(KEYFLAGS);#endif /*WITH_MONO*/	/* dmapool must be created after the module open in case we do no copy transfers */ 	err = RUAOpenPool(dcc_info.pRUA, dcc_info.video_decoder, context.play_opt->dmapool_count, context.play_opt->dmapool_log2size, RUA_POOL_DIRECTION_SEND, &pDMA);	if (RMFAILED(err)) {		RMuint32 poolSize = context.play_opt->dmapool_count << context.play_opt->dmapool_log2size;		fprintf(stderr, "Error cannot open dmapool %d\n\n"			"requested %lu bytes of dmapool (%lu buffers of %lu bytes), make sure you\n"			"loaded llad with the right parameters. For example:\n"			"max_dmapool_memory_size >= %lu max_dmabuffer_log2_size >= %lu\n\n",			err,			poolSize,			context.play_opt->dmapool_count,			(RMuint32)(1 << context.play_opt->dmapool_log2size),			poolSize,			context.play_opt->dmapool_log2size);		goto cleanup;	}	context.pDMA = pDMA;	file = open_stream(context.play_opt->filename, RM_FILE_OPEN_READ, 0);	if (file == NULL) {		RMDBGLOG((ENABLE, "Cannot open file %s\n", context.play_opt->filename));		goto cleanup;	}	context.f_bitstream = file;	RMSizeOfOpenFile(file, &context.fileSize);#if !(STORE_SEQ_HEADER_LOCALLY)		RMDBGLOG((ENABLE, "file: %s, size %llu, duration %llu s \n", context.play_opt->filename, context.fileSize, context.play_opt->duration / 1000));	if (context.play_opt->duration)		fprintf(stderr, "duration %llu secs\n", context.play_opt->duration / 1000);	dcc_info.RM_PSM_commands = RM_PSM_ENABLE_PLAY;	dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_STOP;	dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_PAUSE;	dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_SPEED;	dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_FASTER;	dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_SLOWER;	dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_NEXTPIC;	dcc_info.trick_supported = TRUE;	if ((context.play_opt->duration > 1000) && (context.fileSize > 0)) {		RMDBGLOG((ENABLE, "seek, ffwd and iframe modes enabled\n"));				dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_SEEK;				dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_IFWD;		dcc_info.seek_supported = TRUE;		dcc_info.iframe_supported = TRUE;	}#endif //STORE_SEQ_HEADER_LOCALLY#if FORCE_IFRAME_FWD_COMMAND	RMDBGLOG((ENABLE, "\n\n\nIFrame forward command forced to enabled. Use ']' key to enter IFrameFwd state\n\n"));	dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_IFWD;#endif	/* initialize the external close caption source */	if (NULL == context.play_opt->bcc_filename) {		context.bcc_enabled = FALSE;	}	else {		RMnonAscii *naname;		context.bcc_enabled = TRUE;		naname = RMnonAsciiFromAscii(context.play_opt->bcc_filename);		err = bcc_init(&context.pbcc, naname, dcc_info.pRUA, context.dcc_info);		if (RMFAILED(err)) {			RMDBGLOG((ENABLE, "Error %s: failed to init BCC subsystem.\n", RMstatusToString(err)));			context.bcc_enabled = FALSE;		}		RMFreeNonAscii(naname);	 }	context.PSMcontext = &PSMContext;	PSMContext.validPSMContexts = 1;	PSMContext.currentActivePSMContext = 1;	PSMContext.keyflags = KEYFLAGS;	/* Send WMV9 parameters */	if (context.video_opt->vcodec == EMhwlibVideoCodec_WMV) {		struct VideoDecoder_WMV9VSProp_type wmv9_prop;		RMuint32 Image_Width, Image_Height;		RMDBGLOG((ENABLE, "Setting WMV9 parameters...size is %lu x %lu\n", context.video_opt->vcodec_max_width, context.video_opt->vcodec_max_height));		Image_Width = context.video_opt->vcodec_max_width;		Image_Height = context.video_opt->vcodec_max_height;		wmv9_prop.Sequence = context.video_opt->wmv9_seq;		wmv9_prop.Image_Width = Image_Width;		wmv9_prop.Image_Height = Image_Height;		wmv9_prop.MB_Width = (Image_Width + 15) / 16;		wmv9_prop.MB_Height = (Image_Height + 15) / 16;		err = RUASetProperty(dcc_info.pRUA, dcc_info.video_decoder, RMVideoDecoderPropertyID_WMV9VSProp, &wmv9_prop, sizeof(wmv9_prop), 0);	}#if ENABLE_MONITOR	context.monitor = TRUE;#endif#ifndef WITH_MONO	RMTermInit(TRUE);    // don't allow ctrl-C and the like ...	RMSignalInit(NULL, NULL);  // ... but catch other termination signals to call RMTermExit()#endif	do {		enum RM_PSM_State FSMstate;		RMuint8 *buf;				if (context.play_opt->start_pause) {			RMDBGLOG((ENABLE, "start in pause mode!\n"));			/* required, because if we do 'next' the decoder *must* be running */			err = Play(&context, RM_DEVICES_VIDEO, /*DCCVideoPlayIFrame*/DCCVideoPlayFwd);			if (RMFAILED(err)) {				fprintf(stderr, "Cannot start decoders %d\n", err);				goto cleanup;			}						err = Pause(&context, RM_DEVICES_VIDEO);			if (RMFAILED(err)) {				fprintf(stderr, "Cannot pause decoders %d\n", err);				goto cleanup;			}			RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Paused);		}		else 			RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Playing);		context.play_opt->start_pause = FALSE;	mainloop:		RMDBGLOG((ENABLE, "mainloop\n"));		if (RMSeekFile(file, 0, RM_FILE_SEEK_START) == RM_ERRORSEEKFILE) {			RMDBGLOG((ENABLE,"seeking file to beginning\n"));			goto cleanup;		}		context.byte_counter = 0;		context.FirstPTS = 0;			mainloop_no_seek:		RMDBGLOG((ENABLE, "mainloop_no_seek\n"));		/* do not set this property when start for the first time */		if (context.initVideo == TRUE) {#if STORE_SEQ_HEADER_LOCALLY			resendheader = TRUE;#else			RMbool keep_sequence = TRUE;			err = RUASetProperty(dcc_info.pRUA, dcc_info.video_decoder, RMVideoDecoderPropertyID_StorePreviousVideoHeader, &keep_sequence, sizeof(keep_sequence), 0);			if (RMFAILED(err)) {				RMDBGLOG((ENABLE, "Error setting video decoder to keep sequence header on Stop %d\n", err));				return err;			}			RMDBGLOG((ENABLE, "init video decoder\n"));			context.initVideo = FALSE;#endif //STORE_SEQ_HEADER_LOCALLY		}		context.FirstSystemTimeStamp = TRUE;		context.highSpeedIFrameMode = FALSE;		context.trickMode = FALSE;		context.iframeMode = FALSE;		context.ResyncTimer = FALSE;		FSMstate = RM_PSM_GetState(context.PSMcontext, &(context.dcc_info));		if ((FSMstate != RM_PSM_Paused) && (FSMstate != RM_PSM_Stopped)) {				RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Playing);		}		else {			PROCESS_KEY(FALSE, TRUE);		}		RMDBGLOG((ENABLE, "DCCSTCSetSpeed %lx %lx\n", context.play_opt->speed_N, context.play_opt->speed_M));		DCCSTCSetSpeed(dcc_info.pStcSource, context.play_opt->speed_N, context.play_opt->speed_M);		/* do prebufferization only when in playing state */		FSMstate = RM_PSM_GetState(context.PSMcontext, &(context.dcc_info));		if (FSMstate == RM_PSM_Playing) {			/* required, because if we start straight into pause mode, we cant send buffers (weird)	*/			err = Play(&context, RM_DEVICES_VIDEO, DCCVideoPlayFwd);			if (RMFAILED(err)) {				fprintf(stderr, "Cannot start decoders %d\n", err);				goto cleanup;			}						/* ...for prebuffering */			err = Pause(&context, RM_DEVICES_VIDEO | RM_DEVICES_STC);			if (RMFAILED(err)) {				fprintf(stderr, "Cannot pause decoders %d\n", err);				goto cleanup;			}						RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Prebuffering);			context.prebuf_level = 0;		}#ifdef WITH_MONO		RMDCCInfo(&dcc_info); // pass DCC context to application#endif		/* wake up disks if necessary */		switch (context.play_opt->disk_ctrl_state) {		case DISK_CONTROL_STATE_DISABLE:		case DISK_CONTROL_STATE_RUNNING:			break;		case DISK_CONTROL_STATE_SLEEPING:			if(context.play_opt->disk_ctrl_callback && context.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN) == RM_OK)				context.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING;			break;		}		while (1) { // additional 'while' used for taking care of commands issued during EOSWait			while (1) {				RMuint32 count;				RMstatus status;				struct emhwlib_info Info;			#ifdef	SEND_IBC				if (!ibc_sent && (context.byte_counter >= HARDCODE_BYTECOUNT)) {					SendInbandCommand(&context);					ibc_sent = TRUE;				}#endif				/* first, try to fill up the CC fifo */				if (context.bcc_enabled)				{					bcc_feed(context.pbcc, dcc_info.pRUA, 0);				}							update_hdmi(&dcc_info, context.disp_opt, NULL);								PROCESS_KEY(FALSE, TRUE);							get_buffer:				switch (context.play_opt->disk_ctrl_state) {				case DISK_CONTROL_STATE_DISABLE:				case DISK_CONTROL_STATE_SLEEPING:					break;				case DISK_CONTROL_STATE_RUNNING:					if (context.dmabuffer_index > 0) {						context.dmabuffer_index--;						buf = context.dmabuffer_array[context.dmabuffer_index];												RMDBGLOG((ENABLE, "fill buffer phase: got buffer %p (index %lu, level %lu, count %lu)\n", 							  buf,							  context.dmabuffer_index,							  context.play_opt->disk_ctrl_low_level,							  context.play_opt->dmapool_count));												goto fill_buffer;					}					break;				}								while (RUAGetBuffer(pDMA, &buf,  COMMON_TIMEOUT_US) != RM_OK) {					/* this has a double purpose: 					   1) in mpeg4 elementary streams, the video decoder is able to recover the PTS from the					   stream. When doing Stop/Play, after the Play the video decoder will find the correct PTS, 					   since we cant set the STC to that value because it's unknown to us, there would be a delay					   until STC (set to zero) meets the PTS the decoder got.					   The solution is to prebufferize (thus the decoder will get the PTS and we can obtain it					   thru a property, and then set the STC accordingly)					   2) prebuffering, because we dont start playing until fifo's are full (unintended purpose) */					check_prebuf_state(&context, 0);					switch (context.play_opt->disk_ctrl_state) {					case DISK_CONTROL_STATE_DISABLE:					case DISK_CONTROL_STATE_SLEEPING:						break;					case DISK_CONTROL_STATE_RUNNING:						if(context.play_opt->disk_ctrl_callback && context.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK)							context.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING;						break;					}					PROCESS_KEY(FALSE, TRUE);				}								check_prebuf_state(&context, (RMuint32) (1 << context.play_opt->dmapool_log2size));					switch (context.play_opt->disk_ctrl_state) {				case DISK_CONTROL_STATE_DISABLE:				case DISK_CONTROL_STATE_RUNNING:					break;				case DISK_CONTROL_STATE_SLEEPING:					context.dmabuffer_array[context.dmabuffer_index] = buf;					context.dmabuffer_index ++;					if (context.dmabuffer_index + context.play_opt->disk_ctrl_low_level >= context.play_opt->dmapool_count) {						if(context.play_opt->disk_ctrl_callback && context.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN) == RM_OK)							context.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING;					}					RMDBGLOG((ENABLE, "recycle buffer phase: got buffer %p (index %lu, level %lu, count %lu)\n", 						  buf,						  context.dmabuffer_index,						  context.play_opt->disk_ctrl_low_level,						  context.play_opt->dmapool_count));					goto get_buffer;				}							fill_buffer:				if ((!trickSizeToSend) && (dcc_info.seek_supported)) {					trickSizeToSend = (RMuint32) (context.fileSize / (context.play_opt->duration / 500)); //there are roughly 2 iframes per second					trickBuffersToSend = trickSizeToSend >> context.play_opt->dmapool_log2size;					RMDBGLOG((ENABLE, "size %llu, duration %lu s, iframeSize %lu, buffers %lu (of %lu bytes)\n", 						  context.fileSize, 						  (RMuint32)(context.play_opt->duration / 1000), 						  trickSizeToSend,						  trickBuffersToSend,						  (1 << context.play_opt->dmapool_log2size)));									}				#if STORE_SEQ_HEADER_LOCALLY

⌨️ 快捷键说明

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