mpeg-ps 视频流解析--PsProgramStreamMap

63 阅读2分钟

写在前面

  • 依据mpeg-ps视频流格式,按文档逻辑对每个字段进行解析。
  • 这里给出 PsProgramStreamMap 的解析流程
  • 完整代码已上传git: github.com/lzz71993497…

PsProgramStreamMap.h

//
// Created by lzz on 2025/5/31.
//

#ifndef PS_PARSER_PSPROGRAMSTREAMMAP_H
#define PS_PARSER_PSPROGRAMSTREAMMAP_H


#include <iostream>
#include <memory>
#include <unordered_map>

#define PSM_PREFIX_LEN 4
#define PSM_LEN 2
#define PSM_PARAM_LEN 2
#define PSI_LEN 2
#define ESM_LEN 2
#define CRC_32 4

class PsProgramStreamMap : public std::enable_shared_from_this<PsProgramStreamMap>{
public:
    explicit PsProgramStreamMap(bool is_logging);
    ~PsProgramStreamMap();
    size_t input(const uint8_t* data,size_t len);
    static size_t minLength();

private:
    size_t parseProgramStreamMapLength(const uint8_t* start);
    size_t parseParam(const uint8_t* start);
    size_t parseProgramStreamInfoLength(const uint8_t* start);
    size_t parseElementaryStreamMapLength(const uint8_t* start);
    size_t parseCRC32(const uint8_t* start);
    void log();
    bool is_logging_;
    size_t program_stream_map_length_ = 0;
    size_t program_stream_info_length_ = 0;
    size_t elementary_stream_map_length_ = 0;
    std::unordered_map<std::string,std::string> paramMap;
};


#endif//PS_PARSER_PSPROGRAMSTREAMMAP_H

PsProgramStreamMap.cpp

//
// Created by lzz on 2025/5/31.
//

#include "PsProgramStreamMap.h"
#include "LoggerStream.h"
#include "LogUtils.h"

PsProgramStreamMap::PsProgramStreamMap(bool is_logging) {
    this->is_logging_ = is_logging;
    paramMap.clear();
}

PsProgramStreamMap::~PsProgramStreamMap() {
    LogInfo << "delete psProgramStreamMap";
}
size_t PsProgramStreamMap::input(const uint8_t *data, size_t len) {
    if(len < minLength()){
        return 0;
    }
    const uint8_t* ptr = data + PSM_PREFIX_LEN;
    ptr += parseProgramStreamMapLength(ptr);
    ptr += parseParam(ptr);
    ptr += parseProgramStreamInfoLength(ptr);
    ptr += parseElementaryStreamMapLength(ptr);
    ptr += parseCRC32(ptr);
    log();
    return ptr - data;
}

size_t PsProgramStreamMap::minLength() {
    return PSM_PREFIX_LEN + PSM_LEN + PSM_PARAM_LEN + PSI_LEN + ESM_LEN + CRC_32;
}

size_t PsProgramStreamMap::parseProgramStreamMapLength(const uint8_t* start) {
    auto program_stream_map_length = (uint16_t)((start[0] << 8) | (start[1]));
    this->program_stream_map_length_ = static_cast<size_t>(program_stream_map_length);
    LogUtils::addParam(paramMap,"program_stream_map_length",program_stream_map_length);
    return PSM_LEN;
}

size_t PsProgramStreamMap::parseParam(const uint8_t* start){
    auto current_next_indicator = (start[0] >> 7) & 0x01;
    auto reserved_1 = (start[0] >> 5) & 0x03;
    auto program_stream_map_version = start[0] & 0x1F;
    auto reserved_2 = (start[1] >> 1) & 0x7F;
    auto marker_bit = start[1] & 0x01;

    LogUtils::addParam(paramMap,"current_next_indicator",current_next_indicator);
    LogUtils::addParam(paramMap, "reserved_1", reserved_1);
    LogUtils::addParam(paramMap, "program_stream_map_version", program_stream_map_version);
    LogUtils::addParam(paramMap, "reserved_2", reserved_2);
    LogUtils::addParam(paramMap, "marker_bit", marker_bit);
    return PSM_PARAM_LEN;
}


void PsProgramStreamMap::log() {
    if(is_logging_){
        LogUtils::printfParam(paramMap);
    }
}

// todo 后续解析descriptor的内容
size_t PsProgramStreamMap::parseProgramStreamInfoLength(const uint8_t *start) {
    auto program_stream_info_length = (uint16_t)((start[0] << 8) | (start[1]));
    this -> program_stream_info_length_ = static_cast<size_t>(program_stream_info_length);
    LogUtils::addParam(paramMap,"program_stream_info_length",program_stream_info_length);
    //跳过参数和字段长度
    return program_stream_info_length_ + PSI_LEN;
}

// todo 后续解析字段内容,以及内部descriptor的内容
size_t PsProgramStreamMap::parseElementaryStreamMapLength(const uint8_t *start) {
    auto elementary_stream_map_length = (uint16_t)((start[0] << 8) | (start[1]));
    this -> elementary_stream_map_length_ = static_cast<size_t>(elementary_stream_map_length);
    LogUtils::addParam(paramMap,"elementary_stream_map_length_",elementary_stream_map_length);
    //跳过参数和字段长度
    return elementary_stream_map_length_ + ESM_LEN;
}
size_t PsProgramStreamMap::parseCRC32(const uint8_t *start) {
    auto crc_32 = (start[0] << 24) | (start[1] << 16) |
                  (start[2] << 8) | (start[3]);
   LogUtils::addParam(paramMap,"crc_32",crc_32);
    return CRC_32;
}