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);
}
Exemple #2
0
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);