新增若干音视频编码类型的默认实现

部分支持VP8/VP9/AV1/JPEG/MP3/H266/ADPCM/SVAC/G722/G723/G729
This commit is contained in:
xia-chu
2024-11-29 23:38:27 +08:00
parent 87b42ab492
commit 892108d6ba
19 changed files with 202 additions and 266 deletions

View File

@@ -12,9 +12,10 @@
#include <cinttypes>
#include <random>
#include "Rtsp.h"
#include "Network/Socket.h"
#include "Common/Parser.h"
#include "Common/config.h"
#include "Network/Socket.h"
#include "Extension/Track.h"
#include "Extension/Factory.h"
using namespace std;
@@ -24,50 +25,84 @@ namespace mediakit {
int RtpPayload::getClockRate(int pt) {
switch (pt) {
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \
#define XX(name, type, value, clock_rate, channel, codec_id) \
case value: return clock_rate;
RTP_PT_MAP(SWITCH_CASE)
#undef SWITCH_CASE
RTP_PT_MAP(XX)
#undef XX
default: return 90000;
}
}
int RtpPayload::getClockRateByCodec(CodecId codec) {
#define XX(name, type, value, clock_rate, channel, codec_id) { codec_id, clock_rate },
static map<CodecId, int> s_map = { RTP_PT_MAP(XX) };
#undef XX
auto it = s_map.find(codec);
if (it == s_map.end()) {
WarnL << "Unsupported codec: " << getCodecName(codec);
return 90000;
}
return it->second;
}
int RtpPayload::getPayloadType(const Track &track) {
#define XX(name, type, value, clock_rate, channel, codec_id) { codec_id, info { clock_rate, channel, value } },
struct info {
int clock_rate;
int channels;
int pt;
};
static map<CodecId, info> s_map = { RTP_PT_MAP(XX) };
#undef XX
auto it = s_map.find(track.getCodecId());
if (it == s_map.end()) {
return -1;
}
if (track.getTrackType() == TrackAudio) {
if (static_cast<const AudioTrack &>(track).getAudioSampleRate() != it->second.clock_rate
|| static_cast<const AudioTrack &>(track).getAudioChannel() != it->second.channels) {
return -1;
}
}
return it->second.pt;
}
TrackType RtpPayload::getTrackType(int pt) {
switch (pt) {
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \
#define XX(name, type, value, clock_rate, channel, codec_id) \
case value: return type;
RTP_PT_MAP(SWITCH_CASE)
#undef SWITCH_CASE
RTP_PT_MAP(XX)
#undef XX
default: return TrackInvalid;
}
}
int RtpPayload::getAudioChannel(int pt) {
switch (pt) {
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \
#define XX(name, type, value, clock_rate, channel, codec_id) \
case value: return channel;
RTP_PT_MAP(SWITCH_CASE)
#undef SWITCH_CASE
RTP_PT_MAP(XX)
#undef XX
default: return 1;
}
}
const char *RtpPayload::getName(int pt) {
switch (pt) {
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \
#define XX(name, type, value, clock_rate, channel, codec_id) \
case value: return #name;
RTP_PT_MAP(SWITCH_CASE)
#undef SWITCH_CASE
RTP_PT_MAP(XX)
#undef XX
default: return "unknown payload type";
}
}
CodecId RtpPayload::getCodecId(int pt) {
switch (pt) {
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \
#define XX(name, type, value, clock_rate, channel, codec_id) \
case value: return codec_id;
RTP_PT_MAP(SWITCH_CASE)
#undef SWITCH_CASE
RTP_PT_MAP(XX)
#undef XX
default: return CodecInvalid;
}
}
@@ -91,13 +126,7 @@ static void getAttrSdp(const multimap<string, string> &attr, _StrPrinter &printe
}
string SdpTrack::getName() const {
switch (_pt) {
#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \
case value: return #name;
RTP_PT_MAP(SWITCH_CASE)
#undef SWITCH_CASE
default: return _codec;
}
return RtpPayload::getName(_pt);
}
string SdpTrack::getControlUrl(const string &base_url) const {
@@ -715,6 +744,23 @@ TitleSdp::TitleSdp(float dur_sec, const std::map<std::string, std::string> &head
_printer << "a=control:*\r\n";
}
DefaultSdp::DefaultSdp(int payload_type, const Track &track)
: Sdp(track.getTrackType() == TrackVideo ? 9000 : static_cast<const AudioTrack &>(track).getAudioSampleRate(), payload_type) {
_printer << "m=" << track.getTrackTypeStr() << " 0 RTP/AVP " << payload_type << "\r\n";
auto bitrate = track.getBitRate() >> 10;
if (bitrate) {
_printer << "b=AS:" << bitrate << "\r\n";
}
if (payload_type < 96) {
return;
}
_printer << "a=rtpmap:" << payload_type << " " << track.getCodecName() << "/" << getSampleRate();
if (track.getTrackType() == TrackAudio) {
_printer << "/" << static_cast<const AudioTrack &>(track).getAudioChannel();
}
_printer << "\r\n";
}
} // namespace mediakit
namespace toolkit {

View File

@@ -11,16 +11,18 @@
#ifndef RTSP_RTSP_H_
#define RTSP_RTSP_H_
#include "Common/macros.h"
#include "Extension/Frame.h"
#include "Network/Socket.h"
#include <memory>
#include <string.h>
#include <string>
#include <memory>
#include <unordered_map>
#include "Network/Socket.h"
#include "Common/macros.h"
#include "Extension/Frame.h"
namespace mediakit {
class Track;
namespace Rtsp {
typedef enum {
RTP_Invalid = -1,
@@ -32,27 +34,27 @@ typedef enum {
#define RTP_PT_MAP(XX) \
XX(PCMU, TrackAudio, 0, 8000, 1, CodecG711U) \
XX(GSM, TrackAudio, 3, 8000, 1, CodecInvalid) \
XX(G723, TrackAudio, 4, 8000, 1, CodecInvalid) \
XX(G723, TrackAudio, 4, 8000, 1, CodecG723) \
XX(DVI4_8000, TrackAudio, 5, 8000, 1, CodecInvalid) \
XX(DVI4_16000, TrackAudio, 6, 16000, 1, CodecInvalid) \
XX(LPC, TrackAudio, 7, 8000, 1, CodecInvalid) \
XX(PCMA, TrackAudio, 8, 8000, 1, CodecG711A) \
XX(G722, TrackAudio, 9, 8000, 1, CodecInvalid) \
XX(G722, TrackAudio, 9, 16000, 1, CodecG722) \
XX(L16_Stereo, TrackAudio, 10, 44100, 2, CodecInvalid) \
XX(L16_Mono, TrackAudio, 11, 44100, 1, CodecInvalid) \
XX(QCELP, TrackAudio, 12, 8000, 1, CodecInvalid) \
XX(CN, TrackAudio, 13, 8000, 1, CodecInvalid) \
XX(MPA, TrackAudio, 14, 90000, 1, CodecInvalid) \
XX(G728, TrackAudio, 15, 8000, 1, CodecInvalid) \
XX(MP3, TrackAudio, 14, 44100, 2, CodecMP3) \
XX(G728, TrackAudio, 15, 8000, 1, CodecG728) \
XX(DVI4_11025, TrackAudio, 16, 11025, 1, CodecInvalid) \
XX(DVI4_22050, TrackAudio, 17, 22050, 1, CodecInvalid) \
XX(G729, TrackAudio, 18, 8000, 1, CodecInvalid) \
XX(G729, TrackAudio, 18, 8000, 1, CodecG729) \
XX(CelB, TrackVideo, 25, 90000, 1, CodecInvalid) \
XX(JPEG, TrackVideo, 26, 90000, 1, CodecJPEG) \
XX(nv, TrackVideo, 28, 90000, 1, CodecInvalid) \
XX(H261, TrackVideo, 31, 90000, 1, CodecInvalid) \
XX(MPV, TrackVideo, 32, 90000, 1, CodecInvalid) \
XX(MP2T, TrackVideo, 33, 90000, 1, CodecInvalid) \
XX(MP2T, TrackVideo, 33, 90000, 1, CodecTS) \
XX(H263, TrackVideo, 34, 90000, 1, CodecInvalid)
typedef enum {
@@ -213,10 +215,12 @@ private:
class RtpPayload {
public:
static int getClockRate(int pt);
static int getClockRateByCodec(CodecId codec);
static TrackType getTrackType(int pt);
static int getAudioChannel(int pt);
static const char *getName(int pt);
static CodecId getCodecId(int pt);
static int getPayloadType(const Track &track);
private:
RtpPayload() = delete;
@@ -243,8 +247,8 @@ public:
public:
int _pt = 0xff;
int _channel;
int _samplerate;
int _channel = 0;
int _samplerate = 0;
TrackType _type;
std::string _codec;
std::string _fmtp;
@@ -340,6 +344,15 @@ private:
uint32_t _sample_rate;
};
class DefaultSdp : public Sdp {
public:
DefaultSdp(int payload_type, const Track &track);
std::string getSdp() const override { return _printer; }
private:
toolkit::_StrPrinter _printer;
};
/**
* sdp中除音视频外的其他描述部分
* Other description part in sdp except audio and video

View File

@@ -65,14 +65,19 @@ bool RtspMuxer::addTrack(const Track::Ptr &track) {
WarnL << "Already add a track kind of: " << track->getTrackTypeStr() << ", ignore track: " << track->getCodecName();
return false;
}
if (!track->ready()) {
WarnL << track->getCodecName() << " unready!";
return false;
}
auto &ref = _tracks[track->getIndex()];
auto &encoder = ref.encoder;
CHECK(!encoder);
auto pt = RtpPayload::getPayloadType(*track);
// payload type 96以后则为动态pt [AUTO-TRANSLATED:812ac0a2]
// Payload type 96 and above is dynamic PT
Sdp::Ptr sdp = track->getSdp(96 + _index);
Sdp::Ptr sdp = track->getSdp(pt == -1 ? 96 + _index : pt);
if (!sdp) {
WarnL << "Unsupported codec: " << track->getCodecName();
return false;