整理代码

This commit is contained in:
蒲爽 2026-09-28 21:33:04 +08:00
commit c7b4e178ec
364 changed files with 59691 additions and 0 deletions

View file

@ -0,0 +1,237 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPEGMuxer.h"
#include "../core/VideoEncoder.h"
#include "../core/AudioEncoder.h"
#include "../core/SampleFormat.h"
#include "../core/System.h"
namespace Video
{
namespace MediaServer
{
/*
*******************************************************************************
* TYPEDEFS
*******************************************************************************
*/
struct CodecIDItem
{
Core::CodecID id;
int type;
};
/*
*******************************************************************************
* LOCAL VARIABLES
*******************************************************************************
*/
static const std::array<CodecIDItem, 8> codecMap = {{
{Core::CodecID::H264, PSI_STREAM_H264},
{Core::CodecID::H265, PSI_STREAM_H265},
{Core::CodecID::MJPEG, PSI_STREAM_JPEG_2000},
{Core::CodecID::MP3, PSI_STREAM_MP3},
{Core::CodecID::AAC, PSI_STREAM_AAC},
{Core::CodecID::OPUS, PSI_STREAM_AUDIO_OPUS},
{Core::CodecID::G711A, PSI_STREAM_AUDIO_G711A},
{Core::CodecID::G711U, PSI_STREAM_AUDIO_G711U},
}};
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
MPEGMuxer::Stream::Stream(const std::string& name, int id, Core::PacketQueue::Ptr pQueue)
: _name(name), _id(id), _pQueue(pQueue)
{
}
MPEGMuxer::Stream::~Stream()
{
}
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
static int isMulticastAddr(const char* ip)
{
int r;
struct addrinfo* ai;
r = getaddrinfo(ip, 0, NULL, &ai);
if (0 != r)
return 0;
if (AF_INET == ai->ai_addr->sa_family)
{
const struct sockaddr_in* in = (const struct sockaddr_in*)ai->ai_addr;
assert(sizeof(struct sockaddr_in) == ai->ai_addrlen);
r = (ntohl(in->sin_addr.s_addr) & 0xf0000000) == 0xe0000000 ? 1 : 0;
}
else if (AF_INET6 == ai->ai_addr->sa_family)
{
const struct sockaddr_in6* in6 = (const struct sockaddr_in6*)ai->ai_addr;
assert(sizeof(struct sockaddr_in6) == ai->ai_addrlen);
r = in6->sin6_addr.s6_addr[0] == 0xff ? 1 : 0;
}
else
{
assert(0);
r = 0;
}
freeaddrinfo(ai);
return r;
}
Video::MediaServer::MPEGMuxer::MPEGMuxer(const std::string& url)
: Core::Muxer(Poco::format("MediaServer::MPEGMuxer(%s)", url), url)
{
}
MPEGMuxer::~MPEGMuxer()
{
}
void MPEGMuxer::connect()
{
Poco::URI uri(url());
std::string scheme = uri.getScheme();
std::string host = uri.getHost();
short port = uri.getPort();
_socket = socket_udp_bind_ipv4(nullptr, 50609);
if (socket_invalid == _socket)
throw Poco::InvalidAccessException(Poco::format("%s: Create socket FAIL", name()));
if (isMulticastAddr(host.c_str()))
socket_udp_multicast(_socket, host.c_str(), nullptr, 16);
memset(&_destAddr, 0, sizeof(_destAddr));
socket_addr_from_ipv4(&_destAddr, host.c_str(), port);
static mpeg_muxer_func_t func = {[](void* param, size_t bytes) -> void*
{
MPEGMuxer* pMuxer = (MPEGMuxer*)param;
if (pMuxer->_writeIndex + bytes > sizeof(pMuxer->_buffer))
pMuxer->flush();
return &pMuxer->_buffer[pMuxer->_writeIndex];
},
[](void* param, void* packet) -> void {},
[](void* param, int stream, void* packet, size_t bytes) -> int
{
MPEGMuxer* pMuxer = (MPEGMuxer*)param;
pMuxer->_writeIndex += bytes;
return 0;
}};
_pMuxer = mpeg_muxer_create(0, &func, this);
if (!_pMuxer)
throw Poco::InvalidAccessException(Poco::format("%s: Create MPEG-Muxer FAIL!", name()));
// mpeg_muxer_add_program(_pMuxer, 1, "XXXX", 4); /* 多节目方式 */
previousComponents().foreach (
[&](Core::Component::Ptr pPrevious) -> void
{
auto pVideoEncoder = pPrevious.cast<Core::VideoEncoder>();
if (!pVideoEncoder.isNull())
{
int id = mpeg_muxer_add_stream(_pMuxer, getCodecID(pVideoEncoder->getCodecID()), nullptr, 0);
_streams.push_back(new Stream(Poco::format("%s/Stream(%s)", name(), pVideoEncoder->name()), id,
packetQueues().find(pPrevious)));
return;
}
auto pAudioEncoder = pPrevious.cast<Core::AudioEncoder>();
if (!pAudioEncoder.isNull())
{
int id = mpeg_muxer_add_stream(_pMuxer, getCodecID(pAudioEncoder->getCodecID()), nullptr, 0);
_streams.push_back(new Stream(Poco::format("%s/Stream(%s)", name(), pAudioEncoder->name()), id,
packetQueues().find(pPrevious)));
}
});
}
void MPEGMuxer::mux()
{
std::sort(_streams.begin(), _streams.end(), [](auto a, auto b) { return *a < *b; });
auto& pStream = *_streams.begin();
Core::Packet::Ptr pPacket = pStream->queue()->dequeue(4000);
if (pStream->serialCodeWatcher().isChanged(pPacket->serialCode()))
throw Poco::ApplicationException(Poco::format("%s: Stream changed, restart...", name()));
pStream->setTimeline(pPacket->pts());
int flags = 0;
if (pPacket->isVideo())
flags |= pPacket->isKeyFrame() ? MPEG_FLAG_IDR_FRAME : 0;
mpeg_muxer_input(_pMuxer, pStream->id(), flags, pPacket->pts() * 90000 / 1000000, pPacket->dts() * 90000 / 1000000,
pPacket->data(), pPacket->length());
#if (TRACE_VIDEO_FRAME_RATE)
if (pPacket->isVideo())
{
count++;
uint64_t now = Core::System::timestamp();
int64_t delta = now - timeline;
if (delta >= 1000000)
{
timeline = now;
std::cout << " ==> " << name() << " fps: " << (double)count / (delta / 1000000) << std::endl;
count = 0;
}
}
#endif
}
void MPEGMuxer::disconnect()
{
if (_writeIndex > 0 && _socket != socket_invalid)
flush();
if (_pMuxer)
{
mpeg_muxer_destroy(_pMuxer);
_pMuxer = nullptr;
}
if (_socket != socket_invalid)
{
socket_close(_socket);
_socket = socket_invalid;
}
_streams.clear();
}
void MPEGMuxer::flush()
{
socket_sendto_by_time(_socket, _buffer, _writeIndex, 0, (const struct sockaddr*)&_destAddr, sizeof(_destAddr),
1000);
_writeIndex = 0;
}
const int MPEGMuxer::getCodecID(Core::CodecID id)
{
for (const auto& m : codecMap)
{
if (id == m.id)
return m.type;
}
throw Poco::NotFoundException(
Poco::format("Video::MediaServer: Can't find %s in codec-map", Core::codecIDToString(id)));
}
}
}