📄 decoder_task.c
字号:
/************************************************** * * decoder.c * * CVS ID: $Id: decoder_task.c,v 1.67 2007/03/19 17:58:06 belardi Exp $ * Author: Raffaele Belardi [RB] - STM * Date: $Date: 2007/03/19 17:58:06 $ * Revision: $Revision: 1.67 $ * * Description: * * Main entry point for Accordo+ Decoder task. * * The functions here are mainly concerned with interactions with * the other OS threads. The structure of the function should be * sufficiently generic to be able to use MP3 or WMA (or other types) * of bitstream decoders. * *************************************************** * * COPYRIGHT (C) ST Microelectronics 2005 * All Rights Reserved * **************************************************** * * STM CVS Log: * * $Log: decoder_task.c,v $ * Revision 1.67 2007/03/19 17:58:06 belardi * Integration of Optomech AAC decoder P150307 * * Revision 1.66 2007/01/30 13:29:39 marcucci * 16/32 bit run-time selection * * Revision 1.65 2006/11/01 10:35:57 chlapik * - decoder_immediate_eof which is set from CTR, when modified in DEC task, disable/enable scheduling used * - when waiting for AB empty, if stop cmd arrived (state DECODER_WAIT_AB_EMPTY), don't call ResumeDecoder(), instead of it do immediate stop * * Revision 1.64 2006/10/31 14:14:19 chlapik * support for Layer I & II: * - Layer type, sample rate and channel number are determined by BitrateParser before playback * - mp3 decoder checks if these parameters found in valid header matches, if not scan bitstream per bytes * * Revision 1.63 2006/09/27 19:48:48 belardi * Removed (global) unused variables * * Revision 1.62 2006/09/26 13:16:33 belardi * Removed compilation warnings * * Revision 1.61 2006/09/18 09:55:21 belardi * Corrected CVS keyword usage * * Revision 1.60 2006/09/18 09:23:02 belardi * Added Log CVS keyword into file header * * ***************************************************/#include <string.h> // for memcpy#include "configuration.h"//#include "os20.h"#include "gendef.h"#include "hwreg.h"#include "osal.h"#include "allocation.h" //[LL]#include "decoder_task.h"#include "controller.h"#include "audiobuffer.h"#if (HAVE_WMA!=0)#include "wmawrap.h" //M.Ch. //[LL]#endif#include "mp3wrap.h"#if (0 != HAVE_AAC)#include "aacwrap.h"#endif#include "audiowrap.h"//#include "framebuffer.h"#include "mp3dec.h" // ARM library include file/********* GLOBALS ********/t_decoder_status_event decoder_status_event;//int g_decoderFastSeekJumpBytes; // [RB] unusedt_PlayMode decoderPlayMode;t_fileType NextFileType = ft_unknown;t_fileType CurrentFileType = ft_unknown;t_fileType PreviousFileType = ft_unknown;uint16 CurrentSampling_fr = kDecoderSampleRate_Undefined;uint8 CurrentCh_num = 0;uint32 CurrentBistreamType = 0;uint8 decoder_immediate_eof;uint32 decoder_task_state;char WaitingMode = 0; //[LL]uint32 pcm_size;extern uint8 g_FB_readFrom;extern eDecoderSampleRate CurrentSampleRateConverterFrequency;extern void ReconfigureDMA_CH0(t_fileType FileType); /* defined in audiobuffer.c */ //[LL]/***** OS related stuff *******/#if (DEBUG_INCLUDE_COUNTERS==1)static uint32 countFBUnderflows;uint32 countABUnderflows;uint32 countMP3GoodFrames;uint32 countMP3BadFrames;#endif/***** Decoder related stuff *****/tDecoderTime_event decoder_time_event[EVENT_MAX_STAGES]; // send time events from DEC to CTR/* Internal function prototypes */uint32 InitializeDecoder(t_fileType file_type);void ResumeDecoder(int flag);void KillDecoder(DecoderKillType killType);void SelectDecodersPCMSampleSize(void){ pcm_size = OUTPUT_FORMAT_32BIT;}/********* FUNCTIONS ********/void InitDecoderTask(void){ // Initialize Audio Buffer (output buffer) AudioBufferInit(); decoder_status_event.state = DECODER_STATE_RESET; decoder_immediate_eof = 0; decoder_task_state = DECODER_PLAYBACK; #if (DEBUG_INCLUDE_COUNTERS==1) countFBUnderflows = 0; // [RB] debug countABUnderflows = 0; // [RB] debug countMP3GoodFrames = 0; // [RB] debug countMP3BadFrames = 0; // [RB] debug#endif }/***********************************************************************//* Function: get_decoder_time_event_data *//* *//*! \brief return pointer to decoder time information * \param * \return pointer to time information structure * \remark *//***********************************************************************/void * get_decoder_time_event_data(t_event_stage i){ return (void *) &decoder_time_event[i];}/********************************************* * * InitializeDecoder() * * Decide which decoder to initialize and call * the appropriate initialization function. * * Set up an array of pointers to funtions pointing * to the right decoder functions * * ******************************************/uint32 InitializeDecoder(t_fileType file_type){ t_bool IsSameFileType = FALSE; if (CurrentFileType == file_type) { IsSameFileType = TRUE; } /* initialize the decoder */ switch (file_type) {#if (HAVE_WMA!=0) case ft_WMA: //debugStartProfiling(); WMAInit(IsSameFileType); break;#endif case ft_MP3_LayerI: CurrentBistreamType = 0x4D504731; MP3Init(); break; case ft_MP3_LayerII: CurrentBistreamType = 0x4D504732; MP3Init(); break; case ft_MP3_LayerIII: CurrentBistreamType = 0x4D504733; //debugStartProfiling(); MP3Init(); break;#if (0 != HAVE_AAC) case ft_AAC: AACInit(); break;#endif case ft_Audio: //debugStartProfiling(); if (IsSameFileType) return 0; AudioInit(); break; default: // error break; } NextFileType = file_type;// CurrentSampleRateConverterFrequency = kDecoderSampleRate_Undefined; return 1;}/********************************************* * * ResumeDecoder() * * ******************************************/void ResumeDecoder(int flag){ decoderReturnType ret = decoderUninitilaized; switch (CurrentFileType) {#if (HAVE_WMA!=0) case ft_WMA: ret = WMADecode(flag); break;#endif case ft_Audio: ret = AudioDecode(flag); break; case ft_MP3_LayerI: case ft_MP3_LayerII: case ft_MP3_LayerIII: ret = MP3Decode(flag); break;#if (0 != HAVE_AAC) case ft_AAC: ret = AACDecode(flag); break;#endif // HAVE_AAC } switch (ret) { case decoderWaitingFBdata: #if (DEBUG_INCLUDE_COUNTERS==1) countFBUnderflows++; // [RB] debug#endif decoder_status_event.state = DECODER_STATE_WAIT_FB; // send status event to the Controller event_req_set_decoder(READY); event_sleep_set_decoder(READY); //controller_update_status(CONTROLLER_NEW_DECODER_DATA_REQUEST_EVENT); //controller_update_status(CONTROLLER_NEW_DECODER_SLEEP_EVENT); break; case decoderWaitingABempty: decoder_status_event.state = DECODER_STATE_WAIT_AB; event_sleep_set_decoder(READY); //controller_update_status(CONTROLLER_NEW_DECODER_SLEEP_EVENT); break; case decoderEOF: // natural EOF decoder_status_event.state = DECODER_STATE_RESET_TRANSITION; KillDecoder(closeOnly); decoder_status_event.state = DECODER_STATE_RESET; event_stop_set_decoder(READY); //controller_update_status(CONTROLLER_NEW_DECODER_STOP_EVENT); break; case decoderEOF_immediate: //if decoder cought stop request (decoder_immediate_EOF), cancel following //stop request, not to perform decoder kill twice event_disable_scheduling(); event_in_shedule(DECODER_CMD_EVENT); event_in_clear(DECODER_CMD_EVENT); event_enable_scheduling(); // requested immediate EOF (next / stop / fseek) decoder_status_event.state = DECODER_STATE_RESET_TRANSITION; //KillDecoder(closeOnlyAndClearAllFB); KillDecoder(closeOnly); //decoder_inevent = 0; decoder_status_event.state = DECODER_STATE_RESET; event_stop_set_decoder(READY); //controller_update_status(CONTROLLER_NEW_DECODER_STOP_EVENT); break; case decoderFatalError: // signal upwards#if (0 != HAVE_AAC) decoder_status_event.state = DECODER_STATE_RESET_TRANSITION; KillDecoder(closeOnly); decoder_status_event.state = DECODER_STATE_RESET; event_stop_set_decoder(READY);#endif /* HAVE_AAC */ break; }}/********************************************* * * KillDecoder() * * ******************************************/void KillDecoder(DecoderKillType killType){ switch (CurrentFileType) { // case MP3 LayerIII // May use some more intelligent strategy to cleanup, i.e. // call with closeOnly here and maybe closeAndDestroy later only if // the next requested file to decode is not compatible with this decoder. //WMAKill(closeAndDestroy);#if (HAVE_WMA!=0) case ft_WMA: WMAKill(killType); break;#endif case ft_MP3_LayerI: case ft_MP3_LayerII: case ft_MP3_LayerIII: MP3Kill(killType); break;#if (0 != HAVE_AAC) case ft_AAC: AACKill(killType); break;#endif // HAVE_AAC case ft_Audio: AudioKill(killType); break; } event_disable_scheduling(); decoder_immediate_eof = 0; event_enable_scheduling();}/******************************************************************************//******************************************************************************//******************************************************************************/t_decoder_cmd_event decoder_cmd_event_data[EVENT_MAX_STAGES];void *get_decoder_cmd_event_data(t_event_stage i){ // controler -> decoder return (void *)&decoder_cmd_event_data[i];}/********************************************* * * decoder_cmd() * * ******************************************/ RETVAL decoder_task_cmd(t_decoder_cmd_event* cmd_event){ t_decoder_cmd_event* pout_event; switch(cmd_event->command) { case DECODER_CMD_FB_READY: case DECODER_CMD_START: break; case DECODER_CMD_STOP: decoder_immediate_eof = 1; // stop receiving AB_empty events break; } pout_event = (t_decoder_cmd_event *)pevent_get_out(DECODER_CMD_EVENT); *pout_event = *cmd_event; event_set_out(DECODER_CMD_EVENT); //priority dependent (semaphore signal immediatelly) //event_cmd_set(DECODER_CMD_EVENT); //independent from priorities event_out_shedule(DECODER_CMD_EVENT); return BUSY; }void decoder_process_events(void){ uint32 reconfigure; while (1) { switch (decoder_task_state) { case DECODER_WAIT_AB_EMPTY: if (g_ABempty == AudioBufferElements) { while (CIF_CONF.field.wr_fifo_cnt); // wait for fifo to be empty CIF_CONF.field.wr_fifo_rst = 1; // start CIF reconfiguration: if (NextFileType == ft_Audio) { CIF_CONF.field.wr_burst_len = 2; while (CIF_CONF.field.src) CIF_CONF.field.src = 0; } else { CIF_CONF.field.wr_burst_len = 1; while (!CIF_CONF.field.src) CIF_CONF.field.src = 1; } //since file type has changed, reconfigure DMA ReconfigureDMA_CH0(NextFileType); CurrentFileType = NextFileType; decoder_status_event.state = DECODER_STATE_PLAY; decoder_task_state = DECODER_PLAYBACK; ResumeDecoder(DECODER_CMD_FB_READY); } else if(DECODER_CMD.command == DECODER_CMD_STOP) { //waiting for audio buffer empty, but it is still not, stop cmd arrived decoder_task_state = DECODER_PLAYBACK; decoder_status_event.state = DECODER_STATE_RESET_TRANSITION; KillDecoder(closeOnly); decoder_status_event.state = DECODER_STATE_RESET; event_stop_set_decoder(READY); } return; case DECODER_PLAYBACK: // PROCESS COMMAND EVENTS if (IS_DECODER_CMD_EVENT) { if (DECODER_CMD.command == DECODER_CMD_START) { if (decoder_status_event.state == DECODER_STATE_RESET) { event_start_set_decoder(READY); reconfigure = InitializeDecoder(DECODER_CMD.command_params.start_params.fileType); CurrentSampling_fr = DECODER_CMD.command_params.start_params.sampling_fr; CurrentCh_num = DECODER_CMD.command_params.start_params.ch_num; if (reconfigure) { decoder_task_state = DECODER_WAIT_AB_EMPTY; break; } else { decoder_status_event.state = DECODER_STATE_PLAY; ResumeDecoder(DECODER_CMD_FB_READY); return; } } } else if (DECODER_CMD.command == DECODER_CMD_FB_READY) { if (decoder_status_event.state == DECODER_STATE_WAIT_FB) { decoder_status_event.state = DECODER_STATE_PLAY; ResumeDecoder(DECODER_CMD_FB_READY); return; } } else if (DECODER_CMD.command == DECODER_CMD_STOP) { if (decoder_status_event.state == DECODER_STATE_RESET) { event_disable_scheduling(); decoder_immediate_eof = 0; event_enable_scheduling(); event_stop_set_decoder(READY); return; } decoder_status_event.state = DECODER_STATE_RESET_TRANSITION; KillDecoder(closeOnly); decoder_status_event.state = DECODER_STATE_RESET; event_stop_set_decoder(READY); return; } } if (IS_DMA0_XFER_EVENT) { // PROCESS STATUS EVENTS from DMA (AudioBuffer) if(decoder_status_event.state == DECODER_STATE_WAIT_AB) { decoder_status_event.state = DECODER_STATE_PLAY; ResumeDecoder(DECODER_CMD_AB_EMPTY); } } return; default: return; } // switch } // while(1)}void DecoderTask(void *unused){ while(1) { OSAL_wait_thread(OSAL_THREAD_DecoderTask); event_disable_scheduling(); event_in_shedule(DECODER_CMD_EVENT); event_in_shedule(DMA0_IRQ_XFER_EVENT); event_in_shedule(DMA0_IRQ_TIME_EVENT); event_enable_scheduling(); // decoder_fsm: decoder_process_events(); event_disable_scheduling(); event_in_clear(DECODER_CMD_EVENT); event_in_clear(DMA0_IRQ_XFER_EVENT); event_in_clear(DMA0_IRQ_TIME_EVENT); //event_out_shedule(DECODER_TIME_EVENT); event_out_shedule(DECODER_REQ_EVENT); event_out_shedule(DECODER_SLEEP_EVENT); event_out_shedule(DECODER_STOP_EVENT); event_out_shedule(DECODER_START_EVENT); event_enable_scheduling(); } // while(1) }// ****************************** //uint8 decoderStopRequest(void){ uint8 retval; event_disable_scheduling(); retval = decoder_immediate_eof; event_enable_scheduling(); return retval;}#if 0 // [RB] commented out to reduce ROM spacevoid setDecoderPlayMode(t_PlayMode PlayMode){ decoderPlayMode = PlayMode; // seek or scan}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -