mpeg-ps 视频流解析--psPackHeader

63 阅读3分钟

写在前面

  • 依据mpeg-ps视频流格式,按文档逻辑对每个字段进行解析。
  • 这里给出 psPackHeader的解析流程

psPackHeader 源码

psPackHeader.h

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

#ifndef PS_PARSER_PSPACKHEADER_H
#define PS_PARSER_PSPACKHEADER_H

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

#define SCR_LEN 6
#define PROGRAM_MUX_RATE_LEN 3
#define PACK_STUFF_LEN 1
#define PREFIX_LEN 4

class PsPackHeader : public std::enable_shared_from_this<PsPackHeader>{
public:
    explicit PsPackHeader(bool is_logging);
    ~PsPackHeader();
    size_t input(const uint8_t* data, size_t len);
    static size_t minLength();
private:
    size_t parseSCR(const uint8_t* scr_start);
    size_t parseStuffLen(const uint8_t* stuff);
    size_t parseProgramMuxRate(const uint8_t* start);
    // todo 解析填充数据段,后续完成
    size_t parseStuffingParam(const uint8_t* start);
    void log();
    std::unordered_map<std::string,std::string> paramMap;
    bool is_logging_ = false;
    size_t stuffing_length_ = 0;
};

#endif//PS_PARSER_PSPACKHEADER_H

psPackHeader.cpp


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

#include "PsPackHeader.h"
#include "LoggerStream.h"
#include "LogUtils.h"


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

PsPackHeader::~PsPackHeader() {
    LogInfo << "delete psPackHeader";
}

size_t PsPackHeader::input(const uint8_t *data, size_t len) {
    if(len < minLength()){
        return 0;
    }
    // 跳过头直接开始处理数据
    const uint8_t* ptr = data + PREFIX_LEN;
    // 解析
    ptr += parseSCR(ptr);
    ptr += parseProgramMuxRate(ptr);
    ptr += parseStuffLen(ptr);
    // 跳过所有的填充参数
    ptr += stuffing_length_;
    log();
    return ptr - data;

}

size_t PsPackHeader::minLength() {
    return PREFIX_LEN + SCR_LEN + PROGRAM_MUX_RATE_LEN + PACK_STUFF_LEN;
}

size_t PsPackHeader::parseSCR(const uint8_t* scr_start){
    uint64_t src_base = (uint64_t)(((scr_start[0] >> 3) & 0x07) << 30 ) |     // scr bas[32..30]
                        (uint64_t)((scr_start[0] & 0x03 ) << 28 ) |           //    获取后两位
                        (uint64_t)(( scr_start[1] ) << 20) |
                        (uint64_t)(((scr_start[2] >> 3) & 0x1F ) << 15 ) |    // 取前5位    scr_base[29-15]
                        (uint64_t)((scr_start[2] & 0x03 ) << 13 ) |
                        (uint64_t)(( scr_start[3] ) << 5) |
                        (uint64_t)((scr_start[4] >> 3) & 0x1F);
    auto begin = (uint8_t)((scr_start[0] >> 6) & 0x03);                    // 两位固定值 01
    auto mark_bit_1 = (uint8_t)((scr_start[0] >> 2) & 0x01);               //mark_bit(应为1)
    auto mark_bit_2 = (uint8_t)((scr_start[2] >> 2) & 0x01);               // 取1位 mark_bit (应为1)
    auto mark_bit_3 = (uint8_t)((scr_start[4] >> 2) & 0x01);               // mark_bit
    uint16_t scr_extension = (uint16_t)((scr_start[4] & 0x03) << 7) |         // 后面2个取的是scr_extension
                             (uint16_t)((scr_start[5] >> 1)& 0x7F );          // 取7位
    auto mark_bit_extension = (uint8_t)(scr_start[5] & 0x01);              // 最后一位的标志位 mark_bit
    // 数据写入map
    LogUtils::addParam(paramMap,"src_base",src_base);
    LogUtils::addParam(paramMap,"begin",begin);
    LogUtils::addParam(paramMap,"mark_bit_1",mark_bit_1);
    LogUtils::addParam(paramMap,"mark_bit_2",mark_bit_2);
    LogUtils::addParam(paramMap,"mark_bit_3",mark_bit_3);
    LogUtils::addParam(paramMap,"scr_extension",scr_extension);
    LogUtils::addParam(paramMap,"mark_bit_extension",mark_bit_extension);
    return SCR_LEN;
}

size_t PsPackHeader::parseProgramMuxRate(const uint8_t* start){
    uint32_t program_mux_rate = (uint32_t)(start[0] << 14) |
                                (uint32_t)(start[1] << 6) |
                                (uint32_t)((start[2] >> 2) & 0x3F);
    uint8_t mark = start[2] & 0x03;
    LogUtils::addParam(paramMap,"program_mux_rate",program_mux_rate);
    LogUtils::addParam(paramMap,"mark",mark);
    return PROGRAM_MUX_RATE_LEN;
}

size_t PsPackHeader::parseStuffLen(const uint8_t *start) {
    auto reserved = (uint8_t)(start[0] >> 3 & 0x1F);
    auto pack_stuffing_length = start[0] & 0x07;
    stuffing_length_ = static_cast<size_t>(pack_stuffing_length);
    LogUtils::addParam(paramMap,"reserved",reserved);
    LogUtils::addParam(paramMap,"pack_stuffing_length",pack_stuffing_length);
    return PACK_STUFF_LEN;
}

size_t PsPackHeader::parseStuffingParam(const uint8_t *start) {
    // todo
    return 0;
}

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