ZLMediaKit/ext-codec/MP2V.h
2026-03-11 22:17:48 +08:00

98 lines
3.0 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
*
* Use of this source code is governed by MIT-like license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLMEDIAKIT_MP2V_H
#define ZLMEDIAKIT_MP2V_H
#include "Extension/Frame.h"
#include "Extension/Track.h"
namespace mediakit {
/**
* MPEG-2 Video 帧辅助类模板
* MPEG-2 Video frame helper class template
*/
template <typename Parent>
class MP2VFrameHelper : public Parent {
public:
using Ptr = std::shared_ptr<MP2VFrameHelper>;
template <typename... ARGS>
MP2VFrameHelper(ARGS &&...args)
: Parent(std::forward<ARGS>(args)...) {
this->_codec_id = CodecMP2V;
}
/**
* MPEG-2 视频起始码: 00 00 01 00 (picture_start_code)
* I帧判断picture_coding_type == 1 (I-Picture)
* picture_coding_type 位于 picture header 的第 11-12 bit (从 temporal_reference 之后)
*
* MPEG-2 video start code: 00 00 01 00 (picture_start_code)
* I-frame detection: picture_coding_type == 1 (I-Picture)
*/
bool keyFrame() const override {
auto data = (const uint8_t *)this->data() + this->prefixSize();
auto size = this->size() - this->prefixSize();
return isMP2VKeyFrame(data, size);
}
bool configFrame() const override { return false; }
static bool isMP2VKeyFrame(const uint8_t *data, size_t size) {
// 查找 picture start code (00 00 01 00),然后检查 picture_coding_type
// Look for picture start code (00 00 01 00), then check picture_coding_type
for (size_t i = 0; i + 5 < size; ++i) {
if (data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01 && data[i + 3] == 0x00) {
// picture header: temporal_reference(10bits) + picture_coding_type(3bits)
// picture_coding_type: 001 = I, 010 = P, 011 = B
uint8_t picture_coding_type = (data[i + 5] >> 3) & 0x07;
return picture_coding_type == 1;
}
}
return false;
}
};
/// MPEG-2 Video 帧类
using MP2VFrame = MP2VFrameHelper<FrameImp>;
using MP2VFrameNoCacheAble = MP2VFrameHelper<FrameFromPtr>;
/**
* MPEG-2 Video Track
*/
class MP2VTrack : public VideoTrackImp {
public:
using Ptr = std::shared_ptr<MP2VTrack>;
MP2VTrack() : VideoTrackImp(CodecMP2V) {}
Track::Ptr clone() const override { return std::make_shared<MP2VTrack>(*this); }
bool inputFrame(const Frame::Ptr &frame) override;
private:
Sdp::Ptr getSdp(uint8_t payload_type) const override;
/**
* 从 sequence header 中解析宽高和帧率
* Parse width, height and fps from sequence header
*/
void parseSequenceHeader(const uint8_t *data, size_t size);
private:
bool _seq_header_parsed = false;
};
} // namespace mediakit
#endif // ZLMEDIAKIT_MP2V_H