static void mpa_decode (demux_t *demux, void *data, block_t *block) { if (block->i_buffer < 4) { block_Release (block); return; } block->i_buffer -= 4; /* 32-bits RTP/MPA header */ block->p_buffer += 4; codec_decode (demux, data, block); }
void xiph_destroy (demux_t *demux, void *data) { rtp_xiph_t *self = (rtp_xiph_t *)data; // sunqueen modify if (!data) return; if (self->block) { self->block->i_flags |= BLOCK_FLAG_CORRUPTED; codec_decode (demux, self->id, self->block); } codec_destroy (demux, self->id); free (self); }
static void mpv_decode (demux_t *demux, void *data, block_t *block) { if (block->i_buffer < 4) { block_Release (block); return; } block->i_buffer -= 4; /* 32-bits RTP/MPV header */ block->p_buffer += 4; #if 0 if (block->p_buffer[-3] & 0x4) { /* MPEG2 Video extension header */ /* TODO: shouldn't we skip this too ? */ } #endif codec_decode (demux, data, block); }
static void decode_and_write(struct s_sndfile *sf_out, struct s_codec_state_store *decoder_states, media_data *md) { codec_state *decoder; coded_unit *cu; int i; assert(md->nrep > 0); for(i = 0; i < md->nrep; i++) { if (codec_is_native_coding(md->rep[i]->id)) { break; } } if (i == md->nrep) { /* no decoded audio available for frame */ cu = (coded_unit*)block_alloc(sizeof(coded_unit)); assert(cu != NULL); memset(cu, 0, sizeof(coded_unit)); decoder = codec_state_store_get(decoder_states, md->rep[0]->id); codec_decode(decoder, md->rep[0], cu); assert(md->rep[md->nrep] == NULL); md->rep[md->nrep] = cu; md->nrep++; } assert(codec_is_native_coding(md->rep[md->nrep - 1]->id)); assert(sf_out != NULL); snd_write_audio(&sf_out, (sample*)md->rep[md->nrep - 1]->data, md->rep[md->nrep - 1]->data_len / sizeof(sample)); }
void xiph_decode (demux_t *demux, void *data, block_t *block) { rtp_xiph_t *self = (rtp_xiph_t *)data; // sunqueen modify if (!data || block->i_buffer < 4) goto drop; /* 32-bits RTP header (§2.2) */ uint32_t ident = GetDWBE (block->p_buffer); block->i_buffer -= 4; block->p_buffer += 4; unsigned fragtype = (ident >> 6) & 3; unsigned datatype = (ident >> 4) & 3; unsigned pkts = (ident) & 15; ident >>= 8; /* RTP defragmentation */ if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY)) { /* Screwed! discontinuity within a fragmented packet */ msg_Warn (demux, self->vorbis ? "discontinuity in fragmented Vorbis packet" : "discontinuity in fragmented Theora packet"); block_Release (self->block); self->block = NULL; } if (fragtype <= 1) { if (self->block) /* Invalid first fragment */ { block_Release (self->block); self->block = NULL; } } else { if (!self->block) goto drop; /* Invalid non-first fragment */ } if (fragtype > 0) { /* Fragment */ if (pkts > 0 || block->i_buffer < 2) goto drop; size_t fraglen = GetWBE (block->p_buffer); if (block->i_buffer < (fraglen + 2)) goto drop; /* Invalid payload length */ block->i_buffer = fraglen; if (fragtype == 1)/* Keep first fragment */ { block->i_buffer += 2; self->block = block; } else { /* Append non-first fragment */ size_t len = self->block->i_buffer; self->block = block_Realloc (self->block, 0, len + fraglen); if (!self->block) { block_Release (block); return; } memcpy (self->block->p_buffer + len, block->p_buffer + 2, fraglen); block_Release (block); } if (fragtype < 3) return; /* Non-last fragment */ /* Last fragment reached, process it */ block = self->block; self->block = NULL; SetWBE (block->p_buffer, block->i_buffer - 2); pkts = 1; } /* RTP payload packets processing */ while (pkts > 0) { if (block->i_buffer < 2) goto drop; size_t len = GetWBE (block->p_buffer); block->i_buffer -= 2; block->p_buffer += 2; if (block->i_buffer < len) goto drop; switch (datatype) { case 0: /* Raw payload */ { if (self->ident != ident) { msg_Warn (demux, self->vorbis ? "ignoring raw Vorbis payload without configuration" : "ignoring raw Theora payload without configuration"); break; } block_t *raw = block_Alloc (len); memcpy (raw->p_buffer, block->p_buffer, len); raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */ codec_decode (demux, self->id, raw); break; } case 1: /* Packed configuration frame (§3.1.1) */ { if (self->ident == ident) break; /* Ignore config retransmission */ void *extv; ssize_t extc = xiph_header (&extv, block->p_buffer, len); if (extc < 0) break; es_format_t fmt; es_format_Init (&fmt, self->vorbis ? AUDIO_ES : VIDEO_ES, self->vorbis ? VLC_CODEC_VORBIS : VLC_CODEC_THEORA); fmt.p_extra = extv; fmt.i_extra = extc; codec_destroy (demux, self->id); msg_Dbg (demux, self->vorbis ? "Vorbis packed configuration received (%06"PRIx32")" : "Theora packed configuration received (%06"PRIx32")", ident); self->ident = ident; self->id = (es_out_id_t *)codec_init (demux, &fmt); // sunqueen modify break; } } block->i_buffer -= len; block->p_buffer += len; pkts--; } drop: block_Release (block); }
void local_player_task(uint_32 para) { _mqx_int return_code, res; my_audio_format_t format; FILE_PTR stream_ptr = NULL, stream_ptr1 = NULL; //device_ptr = NULL, uint_32 mclk_freq, fs_freq, bit_width = 0; I2S_STATISTICS_STRUCT stats; int32_t numberOfSamples =0, sampleProduced, bufOut; file_meta_data_t * metadata = NULL; audio_stream_type_t stream_type; char_ptr mem_ptr = NULL; boolean shell_cmd = FALSE; CCI_Ctx ctx; int32_t strLen, i; uint32_t file_extension=0; _task_id pcm_flush_id = MQX_NULL_TASK_ID; uint_32 cnt = 0; int32_t max_audio_buf_size = 0; lp_param_t * lpp_param = (lp_param_t *)para; TASK_TEMPLATE_STRUCT task_template; printf("local_player_task.. Enter 1\n"); if (msi_snd_init_with_periodbuffer(1024, 18) != 0) /* for SPI sd card play FLAC, 18K buffer is at least! */ { LOCALPLAY_LOG(" Error: Unable to open the device \"%s\".\n", AUDIO_DIVECE_NAME_STR); return; } /* create semaphore must before pcm_flush_task */ if(MQX_OK != _lwsem_create(&pcm_decoded_sem, 0)) { LOCALPLAY_LOG("\n Error - Unable to creat lwsem: pcm_decoded_sem\n"); } LOCALPLAY_LOG("Creating pcm flush task.........\n"); task_template.TASK_TEMPLATE_INDEX = 0; task_template.TASK_ADDRESS = pcm_flush_task; task_template.TASK_STACKSIZE = 2000; task_template.TASK_PRIORITY = 12; task_template.TASK_NAME = "pcm_flush"; task_template.TASK_ATTRIBUTES = 0; task_template.CREATION_PARAMETER = 0; task_template.DEFAULT_TIME_SLICE = 0; pcm_flush_id = _task_create_blocked(0, 0, (uint_32)&task_template); if (pcm_flush_id == MQX_NULL_TASK_ID) { printf("local_player_task create pcm_flush_task failed \n"); goto clean_up; } else{ gPcmFlushTaskFinish = 0; _task_ready(_task_get_td(pcm_flush_id)); _lwevent_set(&player_event, PLAYER_EVENT_MSK_SONG_RESUME); } metadata = (file_meta_data_t *) _mem_alloc_system_zero(sizeof(file_meta_data_t)); if (NULL == metadata) { LOCALPLAY_LOG("\n Failed to allocate memory for metadata.\n"); return; } decoding = TRUE; while (1) { #ifndef USB_ACCESSORY_PLAY _lwevent_wait_ticks( &player_event, PLAYER_EVENT_MSK_SONG_READY | PLAYER_EVENT_MSK_SD_FS_UNMOUNTED | PLAYER_EVENT_MSK_SHELL_COMMAND, FALSE, 0); #else _lwevent_wait_ticks( &player_event, PLAYER_EVENT_MSK_SONG_READY | PLAYER_EVENT_MSK_SD_FS_UNMOUNTED | PLAYER_EVENT_MSK_SHELL_COMMAND | PLAYER_EVENT_MSK_USB_ATTACHED, FALSE, 0); #endif shell_cmd = FALSE; #ifdef USB_ACCESSORY_PLAY if (player_event.VALUE & PLAYER_EVENT_MSK_USB_ATTACHED) { _lwevent_clear(&player_event, PLAYER_EVENT_MSK_USB_ATTACHED); //LOCALPLAY_LOG("__guoyifang__: sd_player_task PLAYER_EVENT_MSK_USB_ACC_ATTACHED \n"); break; } #endif if (player_event.VALUE & PLAYER_EVENT_MSK_SD_FS_UNMOUNTED) { _lwevent_clear(&player_event, PLAYER_EVENT_MSK_SD_FS_UNMOUNTED); //LOCALPLAY_LOG("__guoyifang__: sd_player_task PLAYER_EVENT_MSK_SD_FS_UNMOUNTED \n"); break; } if (player_event.VALUE & PLAYER_EVENT_MSK_SONG_READY) { _lwevent_clear(&player_event, PLAYER_EVENT_MSK_SONG_READY); } if (player_event.VALUE & PLAYER_EVENT_MSK_SHELL_COMMAND) { _lwevent_clear(&player_event, PLAYER_EVENT_MSK_SHELL_COMMAND); shell_cmd = TRUE; } LOCALPLAY_LOG(" --------------------------------------------------------------\n"); printf("play lock umount at %d\n",lpp_param->lp_type); _lwsem_wait(lpp_param->mfs_io_sem); /******************decoding is a critical value, assume decoding is TRUE every time.*******************/ printf("SET decoding.\n"); decoding = TRUE; // next/prev btn ISR may clear decoding to 0 /*******************************************/ /*config the audio subsystem according metadata*/ printf( " Open stream file %s\n", full_path); stream_ptr = fopen(full_path, "r"); if (stream_ptr == NULL) { printf(" Unable to open the file: %s\n", full_path); goto clean_up; } stream_ptr1 = fopen(full_path, "r"); if (stream_ptr1 == NULL) { printf(" Unable to open the file: %s\n", full_path); goto clean_up; } /* Determine the extension of the file */ i=0; strLen= strlen((const char *)full_path); if(strLen > 4){ /* find the '.' */ while(strLen--){ if(full_path[i]=='.') break; i++; } if(strLen){ char *p; /* Copy out the extension : 8.3 filename */ memcpy(&file_extension, full_path+i+1, 3); p = (char *) (&file_extension); for(i = 0; i < 4; i++, p++){ if((*p >= 'a') && (*p <= 'z')){ *p -= ('a' - 'A'); } } } ctx.user_data = (void*) stream_ptr; ctx.cci_dec_read = get_file_data;; ctx.cci_dec_seek = seek_file_data; ctx.cci_dec_tell = get_file_position; /* Check if metadata was found. */ return_code = cci_extract_meta_data(file_extension, metadata, &ctx); if (return_code != 0) { printf("\n Metadata not found\n"); goto clean_up; } print_metadata(metadata); //todo } else { printf("\n Metadata not found\n"); goto clean_up; } if ( metadata->stream_type == STREAM_TYPE_MP3 ) { /* Seek from the beginning of the file */ seek_file_data(0, metadata->start_pos, 0, stream_ptr); } else { /* Seek from the beginning of the file */ seek_file_data(0, 0, 0, stream_ptr); } stream_type = metadata->stream_type; #if 0 format.audio_format.ENDIAN = AUDIO_LITTLE_ENDIAN; format.audio_format.ALIGNMENT = AUDIO_ALIGNMENT_LEFT; if((streamType == kCodecStreamTypePcm) || // bitsPerSample Value is 8/16/24 /* * The demo not support kCodecStreamTypeImaAdpcm/kCodecStreamTypeMsAdpcm currently. */ (streamType == kCodecStreamTypeImaAdpcm) || // bitsPerSample Value is 4 (streamType == kCodecStreamTypeMsAdpcm)) // bitsPerSample Value is 4 { format.audio_format.BITS = metadata->i32BitsPerSample; }else{ format.audio_format.BITS = 16; } // Currently, the wave decoder output 16bits only for kCodecStreamTypePcm. format.audio_format.BITS = 16; format.audio_format.SIZE = (format.audio_format.BITS + 7)/8; format.audio_format.CHANNELS = metadata->i32NumChannels; format.fs_freq = metadata->u32SampleRate; fs_freq = format.fs_freq; mclk_freq = fs_freq * CLK_MULT; // Setup audio data format in device if (ioctl(device_ptr, IO_IOCTL_AUDIO_SET_IO_DATA_FORMAT, &format.audio_format) != I2S_OK) { LOCALPLAY_LOG(" Error: Input data format not supported.\n"); goto clean_up; } // Setup rest of parameters - master clock, valid data bits and sampling frequency if ((ioctl(device_ptr, IO_IOCTL_I2S_SET_MCLK_FREQ, &mclk_freq) != I2S_OK) || (ioctl(device_ptr, IO_IOCTL_I2S_SET_DATA_BITS, &format.audio_format.BITS) != I2S_OK) || (ioctl(device_ptr, IO_IOCTL_I2S_SET_FS_FREQ, &fs_freq) != I2S_OK)) { LOCALPLAY_LOG(" Error: Unable to setup \"%s\" device driver.\n", AUDIO_DIVECE_NAME_STR); goto clean_up; } // Setup audio codec return_code = SetupCodec(device_ptr); if (return_code != 0) { LOCALPLAY_LOG(" Audio codec configuration failed. Error 0x%X.\n", return_code); goto clean_up; } ioctl(device_ptr, IO_IOCTL_I2S_GET_FS_FREQ, &fs_freq); ioctl(device_ptr, IO_IOCTL_I2S_GET_DATA_BITS, &bit_width); LOCALPLAY_LOG(" Playback information\n"); LOCALPLAY_LOG(" Sampling frequency: %d Hz\n", fs_freq); LOCALPLAY_LOG(" Bit depth: %d bits\n", (uint_8)bit_width); LOCALPLAY_LOG(" Channels: "); if (format.audio_format.CHANNELS == 1) { LOCALPLAY_LOG("mono\n"); } else { LOCALPLAY_LOG("stereo\n"); } #else if((stream_type == STREAM_TYPE_PCM) || // bitsPerSample Value is 8/16/24 /* * The demo not support kCodecStreamTypeImaAdpcm/kCodecStreamTypeMsAdpcm currently. */ (stream_type == STREAM_TYPE_IMAADPCM) || // bitsPerSample Value is 4 (stream_type == STREAM_TYPE_MSADPCM)) // bitsPerSample Value is 4 { format.audio_format.BITS = metadata->bits_per_sample; }else{ format.audio_format.BITS = 16; } format.audio_format.CHANNELS = metadata->num_channels; // Currently, the wave decoder output 16bits only for kCodecStreamTypePcm. format.audio_format.BITS = 16; #if 0 if(audio_ioctl(setChNum, format.audio_format.CHANNELS)!= I2S_OK) { LOCALPLAY_LOG(" Error: audio_ioctl setChNum failed.\n"); goto clean_up; } if(audio_ioctl(setBitWidth, format.audio_format.BITS)!= I2S_OK) { LOCALPLAY_LOG(" Error: audio_ioctl setBitWidth failed.\n"); goto clean_up; } #endif format.fs_freq = metadata->sample_rate; #if 0 if(audio_ioctl(setSamplerate, format.fs_freq)!= I2S_OK) { LOCALPLAY_LOG(" Error: audio_ioctl setSamplerate failed.\n"); goto clean_up; } #endif msi_snd_set_format(format.fs_freq, format.audio_format.BITS, format.audio_format.CHANNELS); #endif mem_ptr = (char_ptr) _mem_alloc_system_zero(codec_get_mem_info(stream_type)); if (NULL == mem_ptr) { LOCALPLAY_LOG("Failed to allocate memory for the decoder.\n"); goto clean_up; } // MP4 decoder need two fd g_userData[0] = (int) stream_ptr; g_userData[1] = (int) stream_ptr1; if (metadata->audio_sub_type == MEDIA_SUBTYPE_ADTS) g_userData[2] = 1; else if (metadata->audio_sub_type == MEDIA_SUBTYPE_M4A) g_userData[2] = 2; else if ( metadata->stream_type == STREAM_TYPE_OPUS ) { g_userData[2] = metadata->sample_rate; g_userData[3] = metadata->num_channels; } else g_userData[2] = 0; g_callbackFunctionArray[0] = (int32_t *) &get_file_data; g_callbackFunctionArray[1] = (int32_t *) &seek_file_data; g_callbackFunctionArray[2] = (int32_t *) &get_file_position; while (1) { res = codec_init(stream_type, (long **)&mem_ptr,g_callbackFunctionArray, &g_userData[0]); if (res == CODEC_INIT_ERROR) { LOCALPLAY_LOG("\n Codec Init Failed with error code %d\n", res); decoding = FALSE; goto clean_up; } if (res == CODEC_MORE_DATA_REQUIRED) { LOCALPLAY_LOG("\n More Data Processing Required for Init \n"); } if (res == CODEC_SUCCESS) { LOCALPLAY_LOG("\n Codec Init Done Successfully \n\n"); break; } else { printf("codec init other err\n"); decoding = FALSE; goto clean_up; } } if (res == CODEC_SUCCESS) { LOCALPLAY_LOG(" Playing %s...\n\n", full_path); // ioctl(device_ptr, IO_IOCTL_I2S_CLEAR_STATISTICS, NULL); /* Reset variables before every song's playbacking */ //printf("SET decoding.\n"); //decoding = TRUE; // next/prev btn ISR may clear decoding to 0 cnt = 0; max_audio_buf_size = 0; g_audio_buf_ptr = NULL; //_lwevent_clear(&player_event, PLAYER_EVENT_MSK_AUDIO_BUF_FILLED); /* Clear pcm_decoded_sem for play next song */ _lwsem_poll(&pcm_decoded_sem); _lwsem_poll(&pcm_decoded_sem); if(MQX_OK != _lwsem_create(&pcm_flush_sem, AUDIO_BUF_CNT)) { LOCALPLAY_LOG("\n Error - Unable to create lwsem: pcm_flush_sem\n"); } /* * umute */ msi_snd_umute(); //sai_dma_output_init(); while (decoding) { /* * For FLAC decoder, it produced more than 18K bytes per frame, and takes about 30ms. * While take 44.1K/16bit/2ch/4Kbytes DMA buffer as example, the margin time is 4K/4/2/44100~=10ms. * We need bigger DMA buffer, or decode in a ping-pong way. */ res = codec_decode(stream_type, (long **)&mem_ptr, &sampleProduced, &bufOut); if (res == CODEC_END_OF_DECODE) { printf("\n End of Decode \n"); break; } else if (res == CODEC_DECODE_ERROR) { printf("\n Codec Decode Failed \n"); break; } else if(res != CODEC_SUCCESS){ printf("codec_decode else err %d\n",res); break; } cnt += sampleProduced; while (decoding) { numberOfSamples = codec_get_pcm_samples(stream_type, (long **)&mem_ptr, &sampleProduced, &bufOut); if (numberOfSamples == 0) break; #if 1 if (max_audio_buf_size < sampleProduced) { //More bigger buffer needed max_audio_buf_size = sampleProduced; if (NULL != g_audio_buf_ptr) { LOCALPLAY_LOG(" Bigger buffer needed.\n"); _mem_free(g_audio_buf_ptr); } g_audio_buf_ptr = (uchar_ptr) _mem_alloc_system_zero(max_audio_buf_size); if (NULL == g_audio_buf_ptr) { LOCALPLAY_LOG(" Failed to allocate g_audio_buf_ptr. max_audio_buf_size %d \n", max_audio_buf_size); decoding = 0; break; } #if 1 //sai_dma_buffer_adjust(sampleProduced); #endif } #endif if (MQX_OK != _lwsem_wait(&pcm_flush_sem)) { LOCALPLAY_LOG("\n Error: Wait for pcm_flush_sem failed.\n"); // _task_set_error(res); } _mem_copy((void *)bufOut, g_audio_buf_ptr, sampleProduced); //g_audio_buf_ptr = bufOut; g_buf_bytes_to_flush = sampleProduced; if (_lwsem_post(&pcm_decoded_sem) != MQX_OK) { LOCALPLAY_LOG("\n pcm_flush : Error - Unable to set pcm_decoded_sem."); } if (numberOfSamples == sampleProduced) sampleProduced = 0; }//end while decoding }//end while decoding }//end if res==kCodeSuccess #if 0 fflush(device_ptr); #else msi_snd_mute(); if (MQX_OK != _lwsem_wait(&pcm_flush_sem)) LOCALPLAY_LOG("\n Error: Wait for latest pcm_flush_sem failed.\n"); msi_snd_flush(); #endif #if 1 //sai_dma_output_stop(); #endif #if 0 /* Print transfer statistics */ if (ioctl(device_ptr, IO_IOCTL_I2S_GET_STATISTICS, &stats) != I2S_OK) { LOCALPLAY_LOG(" Error: Cannot read I2S statistics.\n"); } else { LOCALPLAY_LOG("\n Playback stats\n"); LOCALPLAY_LOG(" Total interrupts: %d\n", stats.INTERRUPTS); LOCALPLAY_LOG(" Bytes requested for transmit: %d\n", stats.PACKETS_REQUESTED * format.audio_format.SIZE); LOCALPLAY_LOG(" Bytes transmitted: %d\n", stats.TX_PACKETS * format.audio_format.SIZE); LOCALPLAY_LOG(" Underruns of hardware FIFO: %d\n", stats.FIFO_ERROR); LOCALPLAY_LOG(" Software buffer empty: %d\n", stats.BUFFER_ERROR); } #endif LOCALPLAY_LOG("\n DONE\n"); clean_up: printf("done to clean up,decoding %d \n",decoding); /* Clean up for next song */ if (NULL != mem_ptr) { _mem_free(mem_ptr); mem_ptr = NULL; } if (NULL != g_audio_buf_ptr) { _mem_free(g_audio_buf_ptr); g_audio_buf_ptr = NULL; } if (NULL != stream_ptr) { res = fclose(stream_ptr); if ((res != MQX_OK)&&(res != MFS_DISK_IS_WRITE_PROTECTED)) { /*LOCALPLAY_LOG*/printf(" Error: Unable to close file 0x%x.\n", res); } stream_ptr = NULL; } if (NULL != stream_ptr1) { res = fclose(stream_ptr1); if ((res != MQX_OK)&&(res != MFS_DISK_IS_WRITE_PROTECTED)) { /*LOCALPLAY_LOG*/printf(" Error: Unable to close file 0x%x.\n", res); } stream_ptr1 = NULL; } if(MQX_OK != _lwsem_destroy(&pcm_flush_sem)) { LOCALPLAY_LOG("\n Error - Unable to destroy lwsem: pcm_flush_sem\n"); } if (decoding == TRUE) { // playback finished in normal way, ie, next/prev not pressed if (!shell_cmd) { // and was not triggered by Shell // just like next btn being pressed _lwevent_set(&player_event, PLAYER_EVENT_MSK_NEXT_BTN_PRESSED); } } /* if exit this task ,must route this point ! */ printf("play unlock umount at %d\n",lpp_param->lp_type); _lwsem_post(lpp_param->mfs_io_sem); }//end while(1) #if 0 // clean up further if (NULL != device_ptr) { if (fclose(device_ptr) != MQX_OK) { LOCALPLAY_LOG(" Error: Unable to close \"%s\" device driver.\n", full_path); } } #else msi_snd_deinit(); #endif if (NULL != metadata) _mem_free(metadata); if (MQX_NULL_TASK_ID != pcm_flush_id) { gPcmFlushTaskFinish = 1; _lwsem_post(&pcm_decoded_sem); while(gPcmFlushTaskFinish == 1){ _sched_yield(); } //_task_destroy(pcm_flush_id); pcm_flush_id = MQX_NULL_TASK_ID; ///*LOCALPLAY_LOG*/printf(" pcm flush task destoryed \n"); } if(MQX_OK != _lwsem_destroy(&pcm_decoded_sem)) { LOCALPLAY_LOG("\n Error - Unable to destroy lwsem: pcm_decoded_sem\n"); } //printf("__guoyifang__: sd_player_task %d set PLAYER_TASK_KILLED.\n",lpp_param->lp_type); _lwevent_set(&player_event, PLAYER_EVENT_MSK_PLAYER_TASK_KILLED); printf("sd_player_task exit.\n"); //_task_block(); //wait for being destroyed }