Esempio n. 1
0
/*!
 * \brief Parse PES packet.
 * \param *bitstr: The bitstream to use.
 * \param *header: A pointer to a PES header structure.
 * \param *packet: A pointer to a PES packet structure.
 * \return 1 if succeed, 0 otherwise.
 *
 * From 'ISO/IEC 13818-1' specification:
 * 2.4.3.6 PES packet.
 * Table 2-17 – PES packet.
 *
 * Parse both MPEG-1 (ISO/IEC 11172-1) and MPEG-2 (ISO/IEC 13818-1) PES packets.
 */
int parse_pes(Bitstream_t *bitstr, PesHeader_t *header, PesPacket_t *packet)
{
    TRACE_2(MPS, "> parse_pes()");
    int retcode = SUCCESS;

    TRACE_INFO(MPS, "parse_pes() 0x%X @ %lli",
               header->start_code, bitstream_get_absolute_byte_offset(bitstr));

    // "regular" PES packet?
    if ((header->stream_id != SID_PROGRAM_STREAM_MAP) &&
        (header->stream_id != SID_PADDING) &&
        (header->stream_id != SID_PRIVATE_STREAM_2) &&
        (header->stream_id != SID_ECM_STREAM) &&
        (header->stream_id != SID_EMM_STREAM) &&
        (header->stream_id != SID_PROGRAM_STREAM_DIRECTORY) &&
        (header->stream_id != SID_DSMCC_STREAM) &&
        (header->stream_id != SID_2221E))
    {
        unsigned checkversion = next_bits(bitstr, 2);

        // Parse MPEG-2 PES header
        if ((checkversion & 0x02) == 0x02)
        {
            packet->mpeg_version = 2;

            if (read_bits(bitstr, 2) != 2)
            {
                TRACE_ERROR(MPS, "wrong 'marker_bits'");
                return FAILURE;
            }

            packet->PES_scrambling_control = read_bits(bitstr, 2);
            packet->PES_priority = read_bit(bitstr);
            packet->data_alignment_indicator = read_bit(bitstr);
            packet->copyright = read_bit(bitstr);
            packet->original_or_copy = read_bit(bitstr);
            packet->PTS_DTS_flag = read_bits(bitstr, 2);
            packet->ESCR_flag = read_bit(bitstr);
            packet->ES_rate_flag = read_bit(bitstr);
            packet->DSM_trick_mode_flag = read_bit(bitstr);
            packet->additional_copy_info_flag = read_bit(bitstr);
            packet->PES_CRC_flag = read_bit(bitstr);
            packet->PES_extension_flag = read_bit(bitstr);
            packet->PES_header_data_length = read_bits(bitstr, 8);

            if (packet->PTS_DTS_flag == 2)
            {
                if (read_bits(bitstr, 4) != 2)
                {
                    TRACE_ERROR(MPS, "wrong 'marker_bit'");
                    return FAILURE;
                }
                packet->PTS = read_bits(bitstr, 3) << 30;
                MARKER_BIT
                packet->PTS += read_bits(bitstr, 15) << 15;
                MARKER_BIT
                packet->PTS += read_bits(bitstr, 15);
                MARKER_BIT
            }
            else if (packet->PTS_DTS_flag == 3)
Esempio n. 2
0
static int __split_next_bits(struct sw842_param *p, u64 *d, u8 n, u8 s)
{
	u64 tmp = 0;
	int ret;

	if (n <= s) {
		pr_debug("split_next_bits invalid n %u s %u\n", n, s);
		return -EINVAL;
	}

	ret = next_bits(p, &tmp, n - s);
	if (ret)
		return ret;
	ret = next_bits(p, d, s);
	if (ret)
		return ret;
	*d |= tmp << s;
	return 0;
}
Esempio n. 3
0
// Read bnum bits from bitstream bstr with the most significant
// bit read first. A 64 bit unsigned integer is returned.
uint64_t read_bits(struct bitstream *bstr, unsigned bnum)
{
    uint64_t res = next_bits(bstr, bnum);

    // Special case for reading zero bits. Also abort when not enough
    // bits are left. Return zero
    if(bnum == 0 || bstr->bitsleft < 0)
        return 0;

    // Advance the bitstream
    bstr->bpos = bstr->_i_bpos;
    bstr->pos = bstr->_i_pos;

    return res;
}
Esempio n. 4
0
/*!
 * \brief Parse a pack header structure.
 * \param *bitstr The bitstream to use.
 * \param *pack_header A pointer to a pack_header structure.
 * \param *system_header A pointer to a system_header structure.
 * \return retcode 1 if succeed, 0 otherwise.
 *
 * This parser is based on the 'ISO/IEC 13818-1' international standard, part 1:
 * 'Transmission multiplexing and synchronization'.
 */
static int parse_pack_header(Bitstream_t *bitstr, PackHeader_t *pack_header, SystemHeader_t *system_header)
{
    TRACE_INFO(MPS, BLD_GREEN "parse_pack_header()" CLR_RESET " @ %i\n", bitstream_get_absolute_byte_offset(bitstr) - 4);
    int retcode = SUCCESS;
    int i = 0;

    pack_header->pack_start_code = PES_PACK_HEADER;

    if (read_bits(bitstr, 2) != 1)
    {
        TRACE_ERROR(MPS, "wrong 'marker_bit'\n");
        return FAILURE;
    }

    pack_header->system_clock_reference_base = read_bits(bitstr, 3) << 30;
    MARKER_BIT
    pack_header->system_clock_reference_base += read_bits(bitstr, 15) << 15;
    MARKER_BIT
    pack_header->system_clock_reference_base += read_bits(bitstr, 15);
    MARKER_BIT
    pack_header->system_clock_reference_extension = read_bits(bitstr, 9);
    MARKER_BIT
    pack_header->program_mux_rate = read_bits(bitstr, 22);
    MARKER_BIT
    MARKER_BIT
    int reserved = read_bits(bitstr, 5);

    pack_header->pack_stuffing_length = read_bits(bitstr, 3);

    // Stuffing
    for (i = 0; i < pack_header->pack_stuffing_length; i++)
    {
        if (read_bits(bitstr, 8) != 0xFF)
        {
            TRACE_ERROR(MPS, "Wrong 'stuffing_byte'\n");
            return FAILURE;
        }
    }

    // System header
    if (next_bits(bitstr, 32) == PES_SYSTEM_HEADER)
    {
        TRACE_INFO(MPS, BLD_GREEN "parse_system_header()" CLR_RESET " @ %i\n", bitstream_get_absolute_byte_offset(bitstr) - 4);
        skip_bits(bitstr, 32);

        system_header->header_length = read_bits(bitstr, 16);
        MARKER_BIT
        system_header->rate_bound = read_bits(bitstr, 22);
        MARKER_BIT
        system_header->audio_bound = read_bits(bitstr, 6);
        system_header->fixed_flag = read_bits(bitstr, 1);
        system_header->CSPS_flag = read_bits(bitstr, 1);
        system_header->system_audio_lock_flag = read_bits(bitstr, 1);
        system_header->system_video_lock_flag = read_bits(bitstr, 1);
        MARKER_BIT
        system_header->video_bound = read_bits(bitstr, 5);
        system_header->packet_rate_restriction_flag = read_bits(bitstr, 1);

        int reserved_bits = read_bits(bitstr, 7);

        // stack it?
        while (next_bit(bitstr) == 1)
        {
            system_header->stream_id = read_bits(bitstr, 8);
            MARKER_BIT
            MARKER_BIT
            system_header->PSTD_buffer_bound_scale = read_bits(bitstr, 1);
            system_header->PSTD_buffer_size_bound = read_bits(bitstr, 13);
        }
    }
    else
    {
        TRACE_2(MPS, " > No system_header()\n");
    }

    return retcode;
}
Esempio n. 5
0
/*!
 * \brief Parse a mp4 file.
 * \param *video A pointer to a VideoFile_t structure.
 * \return retcode 1 if succeed, 0 otherwise.
 *
 * This parser is based on the 'ISO/IEC 13818-1' international standard, part 1:
 * 'Transmission multiplexing and synchronization'.
 */
int ps_fileParse(VideoFile_t *video)
{
    TRACE_INFO(MPS, BLD_GREEN "ps_fileParse()\n" CLR_RESET);
    int retcode = SUCCESS;
    int sid = 0;

    // Init bitstream to parse container infos
    Bitstream_t *bitstr = init_bitstream(video, NULL);

    if (bitstr != NULL)
    {
        // Init bitstream_map to store container infos
        retcode = init_bitstream_map(&video->tracks_audio[0], 999999);
        retcode = init_bitstream_map(&video->tracks_video[0], 999999);

        if (retcode == SUCCESS)
        {
            video->tracks_audio[0]->stream_type = stream_AUDIO;
            video->tracks_audio[0]->stream_level = stream_level_PES;
            video->tracks_audio[0]->stream_codec = CODEC_MPEG_L3;
            video->tracks_audio[0]->sample_alignment = false;

            video->tracks_video[0]->stream_type = stream_VIDEO;
            video->tracks_video[0]->stream_level = stream_level_PES;
            video->tracks_video[0]->stream_codec = CODEC_MPEG12;
            video->tracks_video[0]->sample_alignment = false;

            // Read bitstream
            while (retcode == SUCCESS &&
                   (bitstream_get_absolute_byte_offset(bitstr) + 4) < video->file_size &&
                   next_bits(bitstr, 32) != PES_PROGRAM_END)
            {
                PackHeader_t pack_header;
                SystemHeader_t system_header;

                if (read_bits(bitstr, 32) == PES_PACK_HEADER)
                {
                    // Parse pack & system header
                    retcode = parse_pack_header(bitstr, &pack_header, &system_header);

                    // Then loop on PES
                    while (retcode == SUCCESS &&
                           (bitstream_get_absolute_byte_offset(bitstr) + 4) < video->file_size &&
                           next_bits(bitstr, 32) != PES_PACK_HEADER &&
                           next_bits(bitstr, 32) != PES_PROGRAM_END)
                    {
                        // Init
                        PesPacket_t pes_packet;
                        ProgramStreamMap_t pes_streammap;
                        ProgramStreamDirectory_t pes_streamdirectory;

                        // Parse start code
                        pes_packet.packet_start_offset = bitstream_get_absolute_byte_offset(bitstr);
                        pes_packet.packet_start_code   = read_bits(bitstr, 24);
                        pes_packet.stream_id           = (uint8_t)read_bits(bitstr, 8);

                        if (pes_packet.packet_start_code == PES_PACKETSTARTCODE)
                        {
                            switch (pes_packet.stream_id)
                            {
                            case SID_PROGRAM_STREAM_MAP:
                                retcode = parse_program_stream_map(bitstr, &pes_streammap);
                                break;
                            case SID_PROGRAM_STREAM_DIRECTORY:
                                retcode = parse_program_stream_directory(bitstr, &pes_streamdirectory);
                                break;
                            case SID_PADDING:
                                retcode = parse_pes_padding(bitstr, &pes_packet);
                                break;
                            case SID_PRIVATE_STREAM_1:
                                TRACE_2(MPS, BLD_GREEN "Private Stream 1 PES" CLR_RESET " @ %i\n", pes_packet.packet_start_offset);
                                retcode = skip_pes(bitstr, &pes_packet);
                                break;
                            case SID_PRIVATE_STREAM_2:
                                TRACE_2(MPS, BLD_GREEN "Private Stream 2 PES" CLR_RESET " @ %i\n", pes_packet.packet_start_offset);
                                retcode = skip_pes(bitstr, &pes_packet);
                                break;
                            case SID_VIDEO:
                                TRACE_INFO(MPS, BLD_GREEN "parse_pes_video()" CLR_RESET " @ %i\n", pes_packet.packet_start_offset);
                                retcode = parse_pes(bitstr, &pes_packet);
                                //print_pes(&pes_packet);

                                // Set sample into the bitstream_map
                                video->tracks_video[0]->sample_count++;
                                sid = video->tracks_video[0]->sample_count;
                                if (sid < 999999)
                                {
                                    video->tracks_video[0]->sample_type[sid] = sample_VIDEO;
                                    video->tracks_video[0]->sample_size[sid] = pes_packet.PES_packet_length + 6;
                                    video->tracks_video[0]->sample_offset[sid] = pes_packet.packet_start_offset;
                                    video->tracks_video[0]->sample_pts[sid] = pes_packet.PTS;
                                    video->tracks_video[0]->sample_dts[sid] = pes_packet.DTS;
                                }
                                break;
                            case SID_AUDIO:
                                TRACE_INFO(MPS, BLD_GREEN "parse_pes_audio()" CLR_RESET " @ %i\n", pes_packet.packet_start_offset);
                                retcode = parse_pes(bitstr, &pes_packet);
                                //print_pes(&pes_packet);

                                // Set sample into the bitstream_map
                                video->tracks_audio[0]->sample_count++;
                                sid = video->tracks_audio[0]->sample_count;
                                if (sid < 999999)
                                {
                                    video->tracks_audio[0]->sample_type[sid] = sample_AUDIO;
                                    video->tracks_audio[0]->sample_size[sid] = pes_packet.PES_packet_length + 6;
                                    video->tracks_audio[0]->sample_offset[sid] = pes_packet.packet_start_offset;
                                    video->tracks_audio[0]->sample_pts[sid] = pes_packet.PTS;
                                    video->tracks_audio[0]->sample_dts[sid] = pes_packet.DTS;
                                }
                                break;
                            default:
                                TRACE_WARNING(MPS, "Unknown PES type (0x%06X%02X) @ %i\n", pes_packet.packet_start_code, pes_packet.stream_id, pes_packet.packet_start_offset);
                                retcode = skip_pes(bitstr, &pes_packet);
                                break;
                            }
                        }
                        else
                        {
                            TRACE_ERROR(MPS, "No valid packet_start_code at %i\n", pes_packet.packet_start_offset);
                            retcode = FAILURE;
                        }
                    }
                }
                else
                {
                    TRACE_ERROR(MPS, "No pack header\n");
                    retcode = FAILURE;
                }
            }
        }

        // Free bitstream
        free_bitstream(&bitstr);
    }

    return retcode;
}
Esempio n. 6
0
/*!
 * \brief Parse a pack header structure.
 * \param *bitstr The bitstream to use.
 * \param *pack_header A pointer to a pack_header structure.
 * \return 1 if succeed, 0 otherwise.
 *
 * From 'ISO/IEC 13818-1' specification:
 * 2.5.3.3 Pack layer of Program Stream.
 * Table 2-33 – Program Stream pack header
 */
static int parse_pack_header(Bitstream_t *bitstr, PesHeader_t *header, PackHeader_t *packet)
{
    TRACE_INFO(MPS, BLD_GREEN "parse_pack_header()" CLR_RESET " @ %lli",
               header->offset_start);

    int retcode = SUCCESS;

    // Pack Headers do not have lengh field, rewind 2 bytes
    rewind_bits(bitstr, 16);

    if (read_bits(bitstr, 2) != 1)
    {
        TRACE_ERROR(MPS, "wrong 'marker_bits'");
        return FAILURE;
    }

    packet->system_clock_reference_base = read_bits(bitstr, 3) << 30;
    MARKER_BIT
    packet->system_clock_reference_base += read_bits(bitstr, 15) << 15;
    MARKER_BIT
    packet->system_clock_reference_base += read_bits(bitstr, 15);
    MARKER_BIT
    packet->system_clock_reference_extension = read_bits(bitstr, 9);
    MARKER_BIT
    packet->program_mux_rate = read_bits(bitstr, 22);
    MARKER_BIT
    MARKER_BIT
    /*unsigned reserved =*/ read_bits(bitstr, 5);

    packet->pack_stuffing_length = read_bits(bitstr, 3);

    // Stuffing
    for (uint8_t i = 0; i < packet->pack_stuffing_length; i++)
    {
        if (read_bits(bitstr, 8) != 0xFF)
        {
            TRACE_ERROR(MPS, "Wrong 'stuffing_byte'");
            return FAILURE;
        }
    }

    // System header // TODO split into its own function?
    if (next_bits(bitstr, 32) == 0x000001BB)
    {
        TRACE_INFO(MPS, BLD_GREEN "parse_system_header()" CLR_RESET " @ %lli",
                   bitstream_get_absolute_byte_offset(bitstr) - 4);
        skip_bits(bitstr, 48); // start code + size

        SystemHeader_t system_header;

        MARKER_BIT
        system_header.rate_bound = read_bits(bitstr, 22);
        MARKER_BIT
        system_header.audio_bound = read_bits(bitstr, 6);
        system_header.fixed_flag = read_bits(bitstr, 1);
        system_header.CSPS_flag = read_bits(bitstr, 1);
        system_header.system_audio_lock_flag = read_bits(bitstr, 1);
        system_header.system_video_lock_flag = read_bits(bitstr, 1);
        MARKER_BIT
        system_header.video_bound = read_bits(bitstr, 5);
        system_header.packet_rate_restriction_flag = read_bits(bitstr, 1);

        /*unsigned reserved_bits =*/ read_bits(bitstr, 7);

        // stack it?
        while (next_bit(bitstr) == 1)
        {
            system_header.stream_id = read_bits(bitstr, 8);
            MARKER_BIT
            MARKER_BIT
            system_header.PSTD_buffer_bound_scale = read_bits(bitstr, 1);
            system_header.PSTD_buffer_size_bound = read_bits(bitstr, 13);
        }
    }
    else
    {
        TRACE_2(MPS, " > No system_header()");
    }

    // Pack header have no length field, so we just have to parse them correctly
    header->offset_end = bitstream_get_absolute_byte_offset(bitstr);
    header->payload_length = header->offset_end - header->offset_start - 4;

    return retcode;
}