/** * Drops a given slice. */ static void slice_drop( void ) { sSX_DESC *curr; sSX_DESC *next; // Drop slice. sx_desc_put(f_cblk.slice_chain.head); // Reset head and tail. f_cblk.slice_chain.head = NULL; f_cblk.slice_chain.tail = NULL; printf("slice_dropped() invoked\n"); }
/** * 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); } }
static void video_scheduler_slice_dump( sSX_DESC *slice_head ) { UINT8 *curr_ptr; UINT32 bytes_left; UINT32 afc; UINT32 pes_byte_count; UINT32 payload_size; UINT32 start_offset; UINT32 copy_index; UINT32 pid; sSX_DESC *curr_desc; sSX_DESC *head_desc; // Consistency check. assert(slice_head); // Get descriptor. sSX_DESC *hw_desc = sx_desc_get(); // Set this as another chain. sSX_DESC *hw_desc_head = hw_desc; // Get a hw buffer. sDECODER_HW_BUFFER * hw_buf = sx_video_sink_buf_get(); assert(hw_buf != NULL); // Set payload. hw_desc->data = (UINT8 *) hw_buf; // Get first descriptor. // // First descriptor holds the timestamp and will be skipped. curr_desc = slice_head; copy_index = 0; do { // Get next. curr_desc = curr_desc->next; // Get current. curr_ptr = curr_desc->data; // Get data left. bytes_left = curr_desc->data_len; assert(bytes_left > sizeof(sRTP_HDR)); // Get RTP header. // sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr; // Get TS header. curr_ptr += sizeof(sRTP_HDR); // Get TS bytes left. bytes_left -= sizeof(sRTP_HDR); assert((bytes_left % sizeof(sMPEG2_TS)) == 0); pes_byte_count = 0; do { sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr; afc = AFC_GET(ts->hdr); pid = PID_GET(ts->hdr); if(pid == 0x1011) { if(PUSI_GET(ts->hdr)) { assert(afc == 0x01); start_offset = 14; payload_size = (sizeof(sMPEG2_TS_PAYLOAD) - 14); } else { if(afc == 0x01) { start_offset = 0; payload_size = sizeof(sMPEG2_TS_PAYLOAD); } else if(afc == 0x03) { start_offset = 1 + ts->payload.payload[0]; payload_size = sizeof(sMPEG2_TS_PAYLOAD) - 1 - ts->payload.payload[0]; } else { assert(0); } } if((copy_index + payload_size) > 81920) { // If the hw buffer is full, just submit the current buffer. hw_buf->buffer_len = copy_index; // Get a new descriptor. hw_desc->next = sx_desc_get(); // Point to the new descriptor. hw_desc = hw_desc->next; // Get a new buffer. hw_buf = sx_video_sink_buf_get(); assert(hw_buf != NULL); // Set new payload. hw_desc->data = (UINT8 *) hw_buf; // Reset index. copy_index = 0; } memcpy(&hw_buf->buffer[copy_index], &ts->payload.payload[start_offset], payload_size); copy_index += payload_size; } curr_ptr += sizeof(sMPEG2_TS); bytes_left -= sizeof(sMPEG2_TS); } while (bytes_left > 0); } while (curr_desc->next != NULL); // Set length. hw_buf->buffer_len = copy_index; // Free the existing slice, minus the head (timestamp). sx_desc_put(slice_head->next); // Set slice. slice_head->next = hw_desc_head; sx_pipe_put(SX_VRDMA_SLICE_READY, slice_head); }
static void audio_scheduler_slice_dump( sSX_DESC *slice_head ) { UINT8 *curr_ptr; UINT32 bytes_left; UINT32 afc; UINT32 pid; UINT32 pes_byte_count; UINT32 payload_size; UINT32 start_offset; UINT32 copy_index; UINT32 samples_left; UINT32 ms_left; sSX_DESC *desc; static UINT8 playback_speed = 1; ms_left = audio_total_remaining_ms(); if(ms_left > (100 + SX_SYSTEM_DELAY_MS)) { if(playback_speed != 2) { sx_audio_sink_playback_speed_inc(); playback_speed = 2; } } else if(ms_left < (50 + SX_SYSTEM_DELAY_MS)) { if(playback_speed != 0) { sx_audio_sink_playback_speed_dec(); playback_speed = 0; } } else { if(playback_speed != 1) { sx_audio_sink_playback_speed_reset(); playback_speed = 1; } } UINT8 *buf = sx_audio_sink_buffer_get(); copy_index = 0; desc = slice_head; do { // Get current. curr_ptr = desc->data; // Get data left. bytes_left = desc->data_len; assert(bytes_left > sizeof(sRTP_HDR)); // Get RTP header. // sRTP_HDR *rtp_hdr = (sRTP_HDR *) curr_ptr; // Get TS header. curr_ptr += sizeof(sRTP_HDR); // Get TS bytes left. bytes_left -= sizeof(sRTP_HDR); assert((bytes_left % sizeof(sMPEG2_TS)) == 0); pes_byte_count = 0; do { sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr; afc = AFC_GET(ts->hdr); pid = PID_GET(ts->hdr); if(pid == 0x1100) { UINT8 stuffing = 0; if(afc & 0x02) { stuffing = 1 + ts->payload.payload[0]; } start_offset = stuffing; if(PUSI_GET(ts->hdr)) { start_offset += 20; } payload_size = sizeof(sMPEG2_TS_PAYLOAD) - start_offset; #if 0 if(PUSI_GET(ts->hdr)) { assert(afc == 0x01); start_offset = 20; payload_size = (sizeof(sMPEG2_TS_PAYLOAD) - start_offset); } else { if(afc == 0x01) { start_offset = 0; payload_size = sizeof(sMPEG2_TS_PAYLOAD); } else if(afc == 0x03) { start_offset = 1 + ts->payload.payload[0]; payload_size = sizeof(sMPEG2_TS_PAYLOAD) - start_offset; } else { assert(0); } } #endif // printf("copy 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", // ts->payload.payload[start_offset], // ts->payload.payload[start_offset + 1], // ts->payload.payload[start_offset + 2], // ts->payload.payload[start_offset + 3], // ts->payload.payload[start_offset + 4], // ts->payload.payload[start_offset + 5], // ts->payload.payload[start_offset + 6], // ts->payload.payload[start_offset + 7]); memcpy(&buf[copy_index], &ts->payload.payload[start_offset], payload_size); copy_index += payload_size; } curr_ptr += sizeof(sMPEG2_TS); bytes_left -= sizeof(sMPEG2_TS); } while (bytes_left > 0); desc = desc->next; } while (desc != NULL); sx_desc_put(slice_head); assert(copy_index == 1920); // printf("### 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", // buf[0], // buf[1], // buf[2], // buf[3], // buf[4], // buf[5], // buf[6], // buf[7]); audio_endianness_convert((UINT16 *) buf, 960); // Push to decoder hardware. sx_audio_sink_buffer_set(buf, 1920); }