diff --git a/ext-codec/MP3.cpp b/ext-codec/MP3.cpp new file mode 100644 index 00000000..7fdf5321 --- /dev/null +++ b/ext-codec/MP3.cpp @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#include "MP3.h" +#include "MP3Rtp.h" +#include "Extension/Factory.h" +#include "Extension/CommonRtp.h" +#include "Extension/CommonRtmp.h" + +using namespace std; +using namespace toolkit; + +namespace mediakit { + +Sdp::Ptr MP3Track::getSdp(uint8_t payload_type) const { + return std::make_shared(payload_type, *this); +} + +Track::Ptr MP3Track::clone() const { + return std::make_shared(*this); +} + +namespace { + +CodecId getCodec() { + return CodecMP3; +} + +Track::Ptr getTrackByCodecId(int sample_rate, int channels, int sample_bit) { + return std::make_shared(sample_rate, channels); +} + +Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) { + return std::make_shared(track->_samplerate, track->_channel); +} + +RtpCodec::Ptr getRtpEncoderByCodecId(uint8_t pt) { + return std::make_shared(); +} + +RtpCodec::Ptr getRtpDecoderByCodecId() { + return std::make_shared(); +} + +RtmpCodec::Ptr getRtmpEncoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +RtmpCodec::Ptr getRtmpDecoderByTrack(const Track::Ptr &track) { + return std::make_shared(track); +} + +Frame::Ptr getFrameFromPtr(const char *data, size_t bytes, uint64_t dts, uint64_t pts) { + return std::make_shared(CodecMP3, (char *)data, bytes, dts, pts); +} + +} // namespace + +CodecPlugin mp3_plugin = { getCodec, + getTrackByCodecId, + getTrackBySdp, + getRtpEncoderByCodecId, + getRtpDecoderByCodecId, + getRtmpEncoderByTrack, + getRtmpDecoderByTrack, + getFrameFromPtr }; + +}//namespace mediakit + + diff --git a/ext-codec/MP3.h b/ext-codec/MP3.h new file mode 100644 index 00000000..8b8608c0 --- /dev/null +++ b/ext-codec/MP3.h @@ -0,0 +1,33 @@ +/* + * 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_MP3_H +#define ZLMEDIAKIT_MP3_H + +#include "Extension/Frame.h" +#include "Extension/Track.h" + +namespace mediakit { + +/** + * MP3音频通道 + */ +class MP3Track : public AudioTrackImp{ +public: + using Ptr = std::shared_ptr; + MP3Track(int sample_rate, int channels) : AudioTrackImp(CodecMP3,sample_rate,channels,16){} + +private: + Sdp::Ptr getSdp(uint8_t payload_type) const override; + Track::Ptr clone() const override; +}; + +}//namespace mediakit +#endif //ZLMEDIAKIT_MP3_H \ No newline at end of file diff --git a/ext-codec/MP3Rtp.cpp b/ext-codec/MP3Rtp.cpp new file mode 100644 index 00000000..ee382c1a --- /dev/null +++ b/ext-codec/MP3Rtp.cpp @@ -0,0 +1,83 @@ +#include "MP3Rtp.h" +#define MPEG12_HEADER_LEN 4 + +namespace mediakit { + +//MPEG Audio-specific header +/* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| MBZ | Frag_offset | ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + + +MP3RtpEncoder::MP3RtpEncoder(int sample_rate, int channels, int sample_bit) { + _sample_rate = sample_rate; + _channels = channels; + _sample_bit = sample_bit; +} + +void MP3RtpEncoder::outputRtp(const char *data, size_t len, size_t offset, bool mark, uint64_t stamp) { + auto rtp = getRtpInfo().makeRtp(TrackAudio, nullptr, len + 4, mark, stamp); + auto payload = rtp->data() + RtpPacket::kRtpTcpHeaderSize + RtpPacket::kRtpHeaderSize; + payload[0] = 0; + payload[1] = 0; + payload[2] = offset >> 8; + payload[3] = offset ; + memcpy(payload + 4, data, len); + RtpCodec::inputRtp(std::move(rtp), false); +} + +bool MP3RtpEncoder::inputFrame(const Frame::Ptr &frame) { + auto ptr = frame->data() + frame->prefixSize(); + auto size = frame->size() - frame->prefixSize(); + auto remain_size = size; + auto max_size = getRtpInfo().getMaxSize() - MPEG12_HEADER_LEN; + int offset = 0; + while (remain_size > 0) { + if (remain_size <= max_size) { + outputRtp(ptr, remain_size, offset, true, frame->dts()); + break; + } + outputRtp(ptr, max_size, offset, false, frame->dts()); + ptr += max_size; + remain_size -= max_size; + offset += max_size; + } + return true; +} + +///////////////////////////////////////////////////////////////////////////////////// + +MP3RtpDecoder::MP3RtpDecoder() { + obtainFrame(); +} + +void MP3RtpDecoder::obtainFrame() { + _frame = FrameImp::create(); + _frame->_codec_id = CodecMP3; +} + +bool MP3RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { + auto payload_size = rtp->getPayloadSize(); + if (payload_size <= MPEG12_HEADER_LEN) { + return false; + } + auto stamp = rtp->getStampMS(); + auto ptr = rtp->getPayload(); + + _frame->_buffer.append((char *)ptr + MPEG12_HEADER_LEN, payload_size - MPEG12_HEADER_LEN); + flushData(); + + _last_dts = stamp; + return false; +} + +void MP3RtpDecoder::flushData() { + RtpCodec::inputFrame(_frame); + obtainFrame(); +} + +} // namespace mediakit \ No newline at end of file diff --git a/ext-codec/MP3Rtp.h b/ext-codec/MP3Rtp.h new file mode 100644 index 00000000..d5aba4b6 --- /dev/null +++ b/ext-codec/MP3Rtp.h @@ -0,0 +1,57 @@ +/* + * 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_MP3RTP_H +#define ZLMEDIAKIT_MP3RTP_H + +#include "Rtsp/RtpCodec.h" +#include "Extension/Frame.h" +#include "Extension/CommonRtp.h" + +namespace mediakit { + +class MP3RtpEncoder : public RtpCodec { +public: + using Ptr = std::shared_ptr; + + MP3RtpEncoder(int sample_rate = 44100, int channels = 2, int sample_bit = 16); + + void outputRtp(const char *data, size_t len, size_t offset, bool mark, uint64_t stamp); + + bool inputFrame(const Frame::Ptr &frame) override; + +private: + int _channels; + int _sample_rate; + int _sample_bit; +}; + + +class MP3RtpDecoder : public RtpCodec { +public: + using Ptr = std::shared_ptr; + + MP3RtpDecoder(); + + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override; + +private: + void obtainFrame(); + + void flushData(); + + +private: + uint64_t _last_dts = 0; + FrameImp::Ptr _frame; +}; + +}//namespace mediakit +#endif //ZLMEDIAKIT_MP3RTP_H diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index b332db6c..d09d18a1 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -29,6 +29,7 @@ REGISTER_CODEC(opus_plugin); REGISTER_CODEC(g711a_plugin) REGISTER_CODEC(g711u_plugin); REGISTER_CODEC(l16_plugin); +REGISTER_CODEC(mp3_plugin); void Factory::registerPlugin(const CodecPlugin &plugin) { InfoL << "Load codec: " << getCodecName(plugin.getCodec());