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 video_scheduler_slice_dump( sdesc *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; sdesc *curr_desc; sdesc *head_desc; // Consistency check assert(slice_head); // Get descriptor sdesc *hw_desc = desc_get(); // Set this as another chain sdesc *hw_desc_head = hw_desc; // Get a hw buffer sDECODER_HW_BUFFER * hw_buf = 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 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) { UINT8 stuffing = 0; if(afc & 0x02) { stuffing = 1 + ts->payload.payload[0]; } start_offset = stuffing; if(PUSI_GET(ts->hdr)) { start_offset += 14; } payload_size = sizeof(sMPEG2_TS_PAYLOAD) - start_offset; 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 = desc_get(); // Point to the new descriptor hw_desc = hw_desc->next; // Get a new buffer hw_buf = 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) desc_put(slice_head->next); // Set slice slice_head->next = hw_desc_head; pipe_put(VRDMA_SLICE_READY, slice_head); }
/** * Find the slice start. * * @param desc * @param pes_payload_size * @param pts_ms * @return */ static UINT8 slice_start_find( sSX_DESC *desc, UINT32 *pes_payload_size, UINT64 *pts_ms ) { UINT8 *curr_ptr; UINT32 bytes_left; sMPEG2_TS *ts; UINT32 pid; UINT32 afc; // 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); do { sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr; afc = AFC_GET(ts->hdr); pid = PID_GET(ts->hdr); if(PUSI_GET(ts->hdr) && (pid == 0x1011)) { curr_ptr = &ts->payload.payload[0]; curr_ptr += sizeof(sPES); sPES_EXT *pes_ext = (sPES_EXT *) curr_ptr; UINT16 len = ntohs(pes_ext->length); if(len > 0) { *pes_payload_size = len - 8; } else { *pes_payload_size = 0; } curr_ptr += sizeof(sPES_EXT); // Consistency check. assert(*curr_ptr == 0x05); curr_ptr++; UINT32 i; UINT64 pts; pts = 0; for(i = 0; i < 5; i++) { pts = ((pts << 8) | curr_ptr[i]); } UINT64 pts_hz; UINT64 mask; pts_hz = 0; mask = 0x0007; pts_hz |= (pts & (mask << 33)) >> 3; mask = 0x7fff; pts_hz |= (pts & (mask << 17)) >> 2; mask = 0x7fff; pts_hz |= (pts & (mask << 1)) >> 1; // Convert to ms. *pts_ms = pts_hz / 90; return 1; } curr_ptr += sizeof(sMPEG2_TS); bytes_left -= sizeof(sMPEG2_TS); } while (bytes_left > 0);
/** * Interpret mpeg 2 transport stream data. * * @param desc * @param pes_payload_size * @param cc_start * @param cc_end */ static void m2ts_data_interpret( sSX_DESC *desc, UINT32 *pes_payload_size, UINT8 *cc_start, UINT8 *cc_end ) { UINT8 *curr_ptr; UINT32 bytes_left; UINT32 afc; UINT32 pid; UINT32 pes_byte_count; UINT32 payload_size; UINT8 cc; // 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); sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr; UINT8 first_chunk = 1; 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) { cc = CC_GET(ts->hdr); if(first_chunk) { *cc_start = cc; first_chunk = 0; } if(PUSI_GET(ts->hdr)) { assert(afc == 0x01); // printf("### 0x%x 0x%x 0x%x 0x%x\n", // ts->payload.payload[14], // ts->payload.payload[15], // ts->payload.payload[16], // ts->payload.payload[17]); payload_size = (sizeof(sMPEG2_TS_PAYLOAD) - 14); } else { if(afc == 0x01) { payload_size = sizeof(sMPEG2_TS_PAYLOAD); } else if(afc == 0x03) { payload_size = sizeof(sMPEG2_TS_PAYLOAD) - 1 - ts->payload.payload[0]; } else { assert(0); } } pes_byte_count += payload_size; } bytes_left -= sizeof(sMPEG2_TS); curr_ptr += sizeof(sMPEG2_TS); } while (bytes_left > 0); *cc_end = cc; *pes_payload_size = pes_byte_count; }
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); }
/** * Find the slice start. * * @param desc * @param pes_payload_size * @param pts_ms * @return */ static UINT8 slice_start_find( sSX_DESC *desc, UINT32 *pes_payload_size, UINT64 *pts_ms ) { UINT8 *curr_ptr; UINT32 bytes_left; sMPEG2_TS *ts; UINT32 pid; UINT32 afc; // 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); do { sMPEG2_TS *ts = (sMPEG2_TS *) curr_ptr; afc = AFC_GET(ts->hdr); pid = PID_GET(ts->hdr); if(PUSI_GET(ts->hdr) && (pid == 0x1011)) { curr_ptr = &ts->payload.payload[0]; UINT8 adaptation_field_len = 0; if(afc & 0x02) { // adaption field is present. // // determine how many bytes to skip. adaptation_field_len = 1 + *curr_ptr; } // Skip 'adaptation field length' field. curr_ptr += adaptation_field_len; // Skip adaptation field length. curr_ptr += sizeof(sPES); sPES_EXT *pes_ext = (sPES_EXT *) curr_ptr; UINT16 len = ntohs(pes_ext->length); if(len > 0) { *pes_payload_size = len - 8; } else { *pes_payload_size = 0; } curr_ptr += sizeof(sPES_EXT); if(*curr_ptr != 0x05) { printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", ((UINT8 *) ts)[0], ((UINT8 *) ts)[1], ((UINT8 *) ts)[2], ((UINT8 *) ts)[3], ((UINT8 *) ts)[4], ((UINT8 *) ts)[5], ((UINT8 *) ts)[6], ((UINT8 *) ts)[7]); printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", ((UINT8 *) ts)[8], ((UINT8 *) ts)[9], ((UINT8 *) ts)[10], ((UINT8 *) ts)[11], ((UINT8 *) ts)[12], ((UINT8 *) ts)[13], ((UINT8 *) ts)[14], ((UINT8 *) ts)[15]); printf("*curr_ptr = 0x%x, delta = %u\n", *curr_ptr, (UINT8 *)curr_ptr - (UINT8 *) ts); // Consistency check. assert(0); } curr_ptr++; UINT32 i; UINT64 pts; pts = 0; for(i = 0; i < 5; i++) { pts = ((pts << 8) | curr_ptr[i]); } UINT64 pts_hz; UINT64 mask; pts_hz = 0; mask = 0x0007; pts_hz |= (pts & (mask << 33)) >> 3; mask = 0x7fff; pts_hz |= (pts & (mask << 17)) >> 2; mask = 0x7fff; pts_hz |= (pts & (mask << 1)) >> 1; // Convert to ms. *pts_ms = pts_hz / 90; return 1; } curr_ptr += sizeof(sMPEG2_TS); bytes_left -= sizeof(sMPEG2_TS); } while (bytes_left > 0);