play_asf.c

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

C
1,567
字号
				/* software decode wmapro while polling disk ready status, otherwise				   we might run out of buffer in case buffer size is too small or				   when spinning up the disk takes too long.				   probably not necessary in this case, since we are coming from a seek				   and buffers are flushed anyway */				while (poll_count--) {					if (SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN_NOWAIT) == RM_OK) {						SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING;						break;					}					asf_try_decode_wmapro(&SendContext, FALSE);					PROCESS_KEY(TRUE, TRUE);					usleep(TIMEOUT_100MS);				}				if (SendContext.play_opt->disk_ctrl_state != DISK_CONTROL_STATE_RUNNING)					RMDBGLOG((ENABLE, "warning, couldn't wakeup disk in time\n"));			}			break;		}		while (1) { // additional 'while' used for taking care of commands issued during EOSWait			while(1) {				RMuint32 count;								/* first, try to fill up the CC fifo */				if (SendContext.bcc_enabled) {					bcc_feed(SendContext.pbcc, SendContext.pRUA, SendContext.Preroll);				}								//asf_try_decode_wmapro(&SendContext, FALSE);				//PROCESS_KEY(TRUE);				PROCESS_KEY(FALSE, TRUE);				update_hdmi(SendContext.dcc_info, SendContext.disp_opt, &(SendContext.audio_opt[0]));				/* wake up disks if necessary */				switch (SendContext.play_opt->disk_ctrl_state) {				case DISK_CONTROL_STATE_DISABLE:				case DISK_CONTROL_STATE_RUNNING:					break;				case DISK_CONTROL_STATE_SLEEPING:					if (SendContext.play_opt->disk_ctrl_callback) {						RMuint32 poll_count = DISK_CONTROL_MAX_WAKEUP_COUNT;												/* software decode wmapro while polling disk ready status, otherwise						   we might run out of buffer in case buffer size is too small or						   when spinning up the disk takes too long.						   						   probably not necessary in this case, since we are coming from a seek						   and buffers are flushed anyway */						while (poll_count--) {							if (SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN_NOWAIT) == RM_OK) {								SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING;								break;							}														asf_try_decode_wmapro(&SendContext, FALSE);							PROCESS_KEY(TRUE, TRUE);														usleep(TIMEOUT_100MS);						}												if (SendContext.play_opt->disk_ctrl_state != DISK_CONTROL_STATE_RUNNING)							RMDBGLOG((ENABLE, "warning, couldn't wakeup disk in time\n"));					}					break;				}#ifdef CHECK_BUFFER_4_FREAD				{				int cWait = 0;#endif								get_buffer:				switch (SendContext.play_opt->disk_ctrl_state) {				case DISK_CONTROL_STATE_DISABLE:				case DISK_CONTROL_STATE_SLEEPING:					break;				case DISK_CONTROL_STATE_RUNNING:					if (SendContext.dmabuffer_index > 0) {						SendContext.dmabuffer_index--;						buffer = SendContext.dmabuffer_array[SendContext.dmabuffer_index];						RMDBGLOG((ENABLE, "fill buffer phase: got buffer %p (index %lu, level %lu, count %lu)\n", 							  buffer,							  SendContext.dmabuffer_index,							  SendContext.play_opt->disk_ctrl_low_level,							  SendContext.play_opt->dmapool_count));						goto fill_buffer;					}					break;				}				RMDBGLOG((DISABLE, "try to RUAGetBuffer. AvailableBufferCount= %ld\n",					RUAGetAvailableBufferCount(SendContext.pDMA)));				while(RUAGetBuffer(SendContext.pDMA, &buffer, GETBUFFER_TIMEOUT_US) != RM_OK) {					/*RMbool gotKey;*/										asf_check_prebuf_state(&SendContext, 0);#ifdef CHECK_BUFFER_4_FREAD					cWait ++;#endif					switch (SendContext.play_opt->disk_ctrl_state) {					case DISK_CONTROL_STATE_DISABLE:					case DISK_CONTROL_STATE_SLEEPING:						break;					case DISK_CONTROL_STATE_RUNNING:						if(SendContext.play_opt->disk_ctrl_callback && SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK)							SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING;						break;					}					asf_try_decode_wmapro(&SendContext, FALSE);					PROCESS_KEY(FALSE, TRUE);					update_hdmi(SendContext.dcc_info, SendContext.disp_opt, &(SendContext.audio_opt[0]));				}#ifdef CHECK_BUFFER_4_FREAD				if(cWait>0)printf("FRead wait: %d\n", cWait);				}#endif			#if (EM86XX_MODE == EM86XX_MODEID_STANDALONE) && (EM86XX_CHIP != EM86XX_CHIPID_TANGO2)				buffer = (RMuint8 *)((RMuint32)buffer & 0x7fffffff);#endif								asf_check_prebuf_state(&SendContext, (1 << SendContext.play_opt->dmapool_log2size));				switch (SendContext.play_opt->disk_ctrl_state) {				case DISK_CONTROL_STATE_DISABLE:				case DISK_CONTROL_STATE_RUNNING:					break;				case DISK_CONTROL_STATE_SLEEPING:					SendContext.dmabuffer_array[SendContext.dmabuffer_index] = buffer;					SendContext.dmabuffer_index ++;					if (SendContext.dmabuffer_index + SendContext.play_opt->disk_ctrl_low_level >= SendContext.play_opt->dmapool_count) {						if (SendContext.play_opt->disk_ctrl_callback) {							RMuint32 poll_count = DISK_CONTROL_MAX_WAKEUP_COUNT;														/* software decode wmapro while polling disk ready status, otherwise							   we might run out of buffer in case buffer size is too small or							   when spinning up the disk takes too long */							while (poll_count--) {								if (SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN_NOWAIT) == RM_OK) {									SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING;									break;								}								asf_try_decode_wmapro(&SendContext, FALSE);								PROCESS_KEY(TRUE, TRUE);								usleep(TIMEOUT_100MS);							}							if (SendContext.play_opt->disk_ctrl_state != DISK_CONTROL_STATE_RUNNING)								RMDBGLOG((ENABLE, "warning, couldn't wakeup disk in time\n"));						}					}					RMDBGLOG((ENABLE, "recycle buffer phase: got buffer %p (index %lu, level %lu, count %lu)\n", 						  buffer,						  SendContext.dmabuffer_index,						  SendContext.play_opt->disk_ctrl_low_level,						  SendContext.play_opt->dmapool_count));					goto get_buffer;				}							fill_buffer:				err = readBitstream(&SendContext, buffer, &count);				if (err == RM_OK) {					rc = RMASFVDemuxDEMUX(SendContext.vASFDemux,buffer, count);				}				else if (err == RM_EOS) {					RMDBGLOG((ENABLE, "wait for eos\n"));					if (buffer != NULL) 						RUAReleaseBuffer(SendContext.pDMA, buffer);					break;				}				else if (err == RM_SKIP_DATA) {					RMint64 currentTime;					RMuint64 stc; 					//get the time in 1000th units because presentation time from ASF is always in 1/1000					//!!! the above assumption might be wrong see #5529, however it doesnt change this routine 					DCCSTCGetTime(SendContext.dcc_info->pStcSource, &stc, 1000);					currentTime = (RMuint64)stc; 					if ((currentTime > (RMint64)SendContext.lastSTC + 1000) ||					    (currentTime < (RMint64)SendContext.lastSTC - 1000)) {						SendContext.lastSTC = stc;						RMDBGLOG((ENABLE, "time = %llu/%llu (%ld/100)\n", currentTime, SendContext.Duration, (currentTime * 100) / SendContext.Duration));					}					if (currentTime > (RMint64)SendContext.Duration) {						RMDBGLOG((ENABLE, "currentTime > duration!\n"));						goto signal_eos;						break;					}					else if (currentTime <= 0) {						RMDBGLOG((ENABLE, "currentTime <= 0\n"));						goto signal_eos;						break;					}					usleep(100000); // to prevent high CPU usage				}				else if (err == RM_DRM_DECRYPTION_FAILED) {					RMDBGLOG((ENABLE, "decrytion error, abort\n"));					if (buffer != NULL) 						RUAReleaseBuffer(SendContext.pDMA, buffer);					goto exit_with_error;				}				else if (err == RM_ERRORENDOFFILE) {					RMDBGLOG((ENABLE, "EOF %s (%ld), wait for eos\n", RMstatusToString(err), err));					if (buffer != NULL) 						RUAReleaseBuffer(SendContext.pDMA, buffer);					break;				}				else {					RMDBGLOG((ENABLE, "error %s (%ld), exit\n", RMstatusToString(err), err));					if (buffer != NULL) 						RUAReleaseBuffer(SendContext.pDMA, buffer);					goto exit_with_error;				}							if (buffer != NULL) {					RMDBGLOG((RELEASE_BUFFER_ENABLE, "Releasing buffer %p\n", buffer));					RUAReleaseBuffer(SendContext.pDMA, buffer);					buffer = NULL;				}#if 0				/* TODO: This code should use multiple audio. Get profiling value */								{					RMreal profile;					err = RUAGetProperty(SendContext.pRUA,							     SendContext.dcc_info->audio_decoder,							     RMGenericPropertyID_Profile,							     &profile,							     sizeof(profile));					if (err == RM_OK) {						printf("Audio DSP Usage = %02.2f%%\n", profile);					}				}#endif				/* check if the user pressed a key when we were processing a callback */				RMDBGLOG((DISABLE, "process_key after demuxing, actions 0x%lx toDo 0x%lx\n",					  SendContext.actions.cmd,					  SendContext.actions.toDoActions));				PROCESS_KEY(TRUE, FALSE);				update_hdmi(SendContext.dcc_info, SendContext.disp_opt, &(SendContext.audio_opt[0]));				{					asf_try_decode_wmapro(&SendContext, FALSE);					PROCESS_KEY(TRUE, TRUE);				}			}			asf_check_prebuf_state(&SendContext, 0);			switch (SendContext.play_opt->disk_ctrl_state) {			case DISK_CONTROL_STATE_DISABLE:			case DISK_CONTROL_STATE_SLEEPING:				break;			case DISK_CONTROL_STATE_RUNNING:				if(SendContext.play_opt->disk_ctrl_callback && SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK)					SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING;				break;			}			// in case we're still in pause state, wait for a key			PROCESS_KEY(FALSE, TRUE);		check_wmapro_fifo_emptiness_on_eos:			if (!RMfifo_is_empty(SendContext.wmapro_fifo)) {				RMDBGLOG((ENABLE, "WMAPRO FIFO is not empty before EOS\n"));				asf_try_decode_wmapro(&SendContext, TRUE);				PROCESS_KEY(TRUE, TRUE);				goto check_wmapro_fifo_emptiness_on_eos;			}			fprintf(stderr, "File ready %ld times, waiting for EOS\n", NTimes+1);			err = asf_WaitForEOS(&SendContext, &SendContext.actions);			{				RMuint64 stc;				DCCSTCGetTime(dcc_info.pStcSource, &stc, SendContext.video_vop_tir);				RMDBGLOG((ENABLE, "Timer duration %llu ms, Header Duration %llu ms\n", stc, SendContext.Duration));			}						if (err == RM_KEY_WHILE_WAITING_EOS) {				err = RM_OK;				PROCESS_KEY(FALSE, FALSE);				continue;			}			else {				if ((SendContext.isIFrameMode) && (SendContext.IFrameDirection < 0) && 0)					goto wmapro_decoder_delete;				else {				signal_eos:#ifdef WITH_MONO					/* callback to signal EOS to curacao/mono */					RMEOSCallback(); 					/* process any command that might be issued after an EOS signalling */					PROCESS_KEY(FALSE, TRUE);					/* after processing the key, if we are still here, proceed with EOS */#endif					break;	// EOS					}			}		}		if (SendContext.play_opt->loop_count > 0)			SendContext.play_opt->loop_count --;wmapro_decoder_delete:		if (SendContext.vDecoder != (void *)NULL) {						RMDBGLOG((ENABLE, "closing wmaprodecoder\n"));			RMWMAProVDecoderClose(SendContext.vDecoder);			RMDeleteWMAProVDecoder(SendContext.vDecoder);			SendContext.vDecoder = (void *)NULL;			asf_flush_wmaproFIFO(&SendContext);		}		NTimes++;		/* if there is another loop, stop devices */		if ((SendContext.play_opt->loop_count > 0) || (SendContext.play_opt->waitexit != TRUE) || (SendContext.play_opt->infinite_loop))			asf_Stop(&SendContext, RM_DEVICES_STC | RM_DEVICES_AUDIO | RM_DEVICES_VIDEO);	} while ((SendContext.play_opt->infinite_loop) || (SendContext.play_opt->loop_count > 0));	 cleanup:	error = 0; //normal exit exit_with_error:	if( SendContext.play_opt->waitexit ) {		RMascii key;		fprintf(stderr, "press q key again if you really want to stop & quit\n");		while ( !(RMGetKeyNoWait(&key) && ((key == 'q') || (key =='Q'))) );		asf_Stop(&SendContext, RM_DEVICES_STC);		asf_Stop(&SendContext, RM_DEVICES_STC | RM_DEVICES_AUDIO | RM_DEVICES_VIDEO);	}	if (err != RM_OK) {		fprintf(stderr, "quitting due to error %s (%d)...\n", RMstatusToString(err), err);		error = err; //exit with error	}	RMDBGLOG((ENABLE, "closing...\n"));	if(asf_close(&SendContext,		     wmapro_fifo_buffer_original,		     dtcpCookieHandle) != RM_OK) {		fprintf(stderr, "ERROR WHILE CLOSING\n");	}	if (error)				RMDBGLOG((ENABLE, "exiting with error %s (%d)\n", RMstatusToString(error), error));	return error;}

⌨️ 快捷键说明

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