/** * Updates program clock reference time. * * @param arg */ void pcr_update_thread( void * arg ) { sSX_DESC *desc; UINT64 pcr_time; UINT64 pcr_received_time; UINT64 curr_time; while(1) { desc = sx_pipe_get(SX_VRDMA_PCR); if(desc == NULL) { goto cleanup; } sSLICE_HDR *hdr = (sSLICE_HDR *) desc->data; // Update PCR time. pcr_time = hdr->timestamp; // Free descriptor. sx_desc_put(desc); // Cache received time. pcr_received_time = sink_time_get(); cleanup: // Get current time. curr_time = sink_time_get(); pthread_mutex_lock(&f_cblk.lock); f_cblk.curr_time = pcr_time + (curr_time - pcr_received_time) - SX_SYSTEM_AUDIO_SOURCE_DELAY_MS - SX_SYSTEM_DELAY_MS; pthread_mutex_unlock(&f_cblk.lock); usleep(2*1000); } }
/** * Slice packing thread. * * @param arg */ void slice_packing_thread( void * arg ) { sSX_DESC *desc; desc = NULL; while(1) { UINT32 len = sx_pipe_len_get(SX_VRDMA_SLICE_READY); if(len >= 10) { // More than enough. Try again next iteration. goto next_iter; } UINT32 slices_to_dump = 10 - len; do { desc = sx_pipe_get(SX_VRDMA_SLICE); if(desc == NULL) { goto next_iter; } // Dump slice. video_scheduler_slice_dump(desc); slices_to_dump--; } while (slices_to_dump > 0); next_iter: usleep(2*1000); } }
// -------------------------------------------------------- // decoder_thread // Decoder thread // // Description: // This function defines the decoder thread. // void video_scheduler_thread( void * arg ) { sSX_DESC *desc; UINT64 slice_present_time; desc = NULL; while(1) { while(1) { // ------------------- // Get slice. // ------------------- // Get slice. if(desc == NULL) { desc = sx_pipe_get(SX_VRDMA_SLICE_READY); if(desc == NULL) { goto next_iter; } sSLICE_HDR *hdr = (sSLICE_HDR *) desc->data; // Get PTS. slice_present_time = ((sSLICE_HDR *) desc->data)->timestamp; } UINT64 estimated_source_time = estimated_source_time_get(); UINT8 present = (estimated_source_time > slice_present_time) ? 1 : 0; if(!present) { goto next_iter; } // ------------------- // Present slice. // ------------------- sSX_DESC *curr = desc->next; sSX_DESC *next; do { sx_video_sink_buf_set((sDECODER_HW_BUFFER *) curr->data); next = curr->next; free(curr); curr = next; } while (curr != NULL); free(desc->data); free(desc); // Set descriptor pointer to NULL. desc = NULL; } next_iter: usleep(1*1000); } }
// -------------------------------------------------------- // decoder_thread // Decoder thread // // Description: // This function defines the decoder thread. // void audio_scheduler_thread( void * arg ) { sSX_DESC *desc; while(1) { if(f_cblk.state == STATE_INACTIVE) { UINT32 len = sx_pipe_len_get(SX_VRDMA_LPCM_SLICE); if(len > (SX_SYSTEM_DELAY_MS / 10)) { f_cblk.state = STATE_ACTIVE; printf("(audio_scheduler): Transition to active. [len = %u]\n", len); goto next_iter; } } else { UINT32 data_left_ms = sx_pipe_len_get(SX_VRDMA_LPCM_SLICE) * 10; UINT32 queued_ms = sx_audio_sink_ms_left_get(); if((data_left_ms + queued_ms) == 0) { f_cblk.state = STATE_INACTIVE; printf("(audio_scheduler): Transition to inactive.\n"); goto next_iter; } if(queued_ms < 200) { UINT32 slices_to_queue = (200 - queued_ms + 10) / 10; do { // Get slice. desc = sx_pipe_get(SX_VRDMA_LPCM_SLICE); if(desc == NULL) { goto next_iter; } // Dump slice. audio_scheduler_slice_dump(desc); slices_to_queue--; } while(slices_to_queue > 0); } } next_iter: usleep(5*1000); } }