mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-07 04:08:13 +08:00
新增若干音视频编码类型的默认实现
部分支持VP8/VP9/AV1/JPEG/MP3/H266/ADPCM/SVAC/G722/G723/G729
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user