From d27a8117e1900065972e66048d1daff83926d032 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 12 May 2020 11:48:15 +0800 Subject: [PATCH] =?UTF-8?q?mp4=E5=BD=95=E5=88=B6=E6=94=AF=E6=8C=81opus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/Opus.cpp | 23 +++++++++ src/Extension/Opus.h | 107 ++++++++++++++++++++++++++++++++++++++++ src/Record/MP4Muxer.cpp | 63 +++++++++++++---------- 3 files changed, 166 insertions(+), 27 deletions(-) create mode 100644 src/Extension/Opus.cpp create mode 100644 src/Extension/Opus.h diff --git a/src/Extension/Opus.cpp b/src/Extension/Opus.cpp new file mode 100644 index 00000000..e4e15a57 --- /dev/null +++ b/src/Extension/Opus.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Use of this source code is governed by MIT 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 "Opus.h" + +namespace mediakit{ + +Sdp::Ptr OpusTrack::getSdp() { + if(!ready()){ + WarnL << getCodecName() << " Track未准备好"; + return nullptr; + } + return std::make_shared(getAudioSampleRate(), getAudioChannel()); +} + +}//namespace mediakit \ No newline at end of file diff --git a/src/Extension/Opus.h b/src/Extension/Opus.h new file mode 100644 index 00000000..b763a2da --- /dev/null +++ b/src/Extension/Opus.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved. + * + * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit). + * + * Use of this source code is governed by MIT 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_OPUS_H +#define ZLMEDIAKIT_OPUS_H + +#include "Frame.h" +#include "Track.h" + +namespace mediakit{ + +/** + * Opus帧 + */ +class OpusFrame : public FrameImp { +public: + typedef std::shared_ptr Ptr; + + OpusFrame(){ + _codecid = CodecOpus; + } +}; + +/** + * 不可缓存的Opus帧 + */ +class OpusFrameNoCacheAble : public FrameFromPtr { +public: + typedef std::shared_ptr Ptr; + + OpusFrameNoCacheAble(char *ptr,uint32_t size,uint32_t dts, uint32_t pts = 0,int prefix_size = 0){ + _ptr = ptr; + _size = size; + _dts = dts; + _prefix_size = prefix_size; + } + + CodecId getCodecId() const override{ + return CodecOpus; + } + + bool keyFrame() const override { + return false; + } + + bool configFrame() const override{ + return false; + } +}; + +/** + * Opus帧音频通道 + */ +class OpusTrack : public AudioTrackImp{ +public: + typedef std::shared_ptr Ptr; + OpusTrack(int sample_rate, int channels, int sample_bit) : AudioTrackImp(CodecOpus,sample_rate,channels,sample_bit){} + +private: + //克隆该Track + Track::Ptr clone() override { + return std::make_shared::type >(*this); + } + //生成sdp + Sdp::Ptr getSdp() override ; +}; + +/** + * Opus类型SDP + */ +class OpusSdp : public Sdp { +public: + /** + * 构造opus sdp + * @param sample_rate 音频采样率 + * @param playload_type rtp playload + * @param bitrate 比特率 + */ + OpusSdp(int sample_rate, + int channels, + int playload_type = 98, + int bitrate = 128) : Sdp(sample_rate,playload_type){ + _printer << "m=audio 0 RTP/AVP " << playload_type << "\r\n"; + _printer << "a=rtpmap:" << playload_type << " opus/" << sample_rate << "/" << channels << "\r\n"; + _printer << "a=control:trackID=" << (int)TrackAudio << "\r\n"; + } + + string getSdp() const override { + return _printer; + } + + CodecId getCodecId() const override { + return CodecOpus; + } +private: + _StrPrinter _printer; +}; + +}//namespace mediakit +#endif //ZLMEDIAKIT_OPUS_H diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index 64cfbc4e..8f3bb60d 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -122,27 +122,48 @@ void MP4Muxer::inputFrame(const Frame::Ptr &frame) { } } +static uint8_t getObject(CodecId codecId){ + switch (codecId){ + case CodecG711A : return MOV_OBJECT_G711a; + case CodecG711U : return MOV_OBJECT_G711u; + case CodecOpus : return MOV_OBJECT_OPUS; + case CodecAAC : return MOV_OBJECT_AAC; + case CodecH264 : return MOV_OBJECT_H264; + case CodecH265 : return MOV_OBJECT_HEVC; + default : return 0; + } +} + void MP4Muxer::addTrack(const Track::Ptr &track) { + auto mp4_object = getObject(track->getCodecId()); + if (!mp4_object) { + WarnL << "MP4录制不支持该编码格式:" << track->getCodecName(); + return; + } + + if (!track->ready()) { + WarnL << "Track[" << track->getCodecName() << "]未就绪"; + return; + } + switch (track->getCodecId()) { case CodecG711A: - case CodecG711U: { - auto audio_track = dynamic_pointer_cast(track); + case CodecG711U: + case CodecOpus: { + auto audio_track = dynamic_pointer_cast(track); if (!audio_track) { - WarnL << "不是G711 Track"; - return; - } - if (!audio_track->ready()) { - WarnL << "G711 Track未就绪"; + WarnL << "不是音频Track:" << track->getCodecName(); return; } + auto track_id = mov_writer_add_audio(_mov_writter.get(), - track->getCodecId() == CodecG711A ? MOV_OBJECT_G711a : MOV_OBJECT_G711u, + mp4_object, audio_track->getAudioChannel(), audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), audio_track->getAudioSampleRate(), nullptr, 0); if (track_id < 0) { - WarnL << "添加G711 Track失败:" << track_id; + WarnL << "添加Track[" << track->getCodecName() << "]失败:" << track_id; return; } _codec_to_trackid[track->getCodecId()].track_id = track_id; @@ -155,12 +176,9 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { WarnL << "不是AAC Track"; return; } - if(!audio_track->ready()){ - WarnL << "AAC Track未就绪"; - return; - } + auto track_id = mov_writer_add_audio(_mov_writter.get(), - MOV_OBJECT_AAC, + mp4_object, audio_track->getAudioChannel(), audio_track->getAudioSampleBit() * audio_track->getAudioChannel(), audio_track->getAudioSampleRate(), @@ -178,10 +196,6 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { WarnL << "不是H264 Track"; return; } - if(!h264_track->ready()){ - WarnL << "H264 Track未就绪"; - return; - } struct mpeg4_avc_t avc = {0}; string sps_pps = string("\x00\x00\x00\x01", 4) + h264_track->getSps() + @@ -196,7 +210,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { } auto track_id = mov_writer_add_video(_mov_writter.get(), - MOV_OBJECT_H264, + mp4_object, h264_track->getVideoWidth(), h264_track->getVideoHeight(), extra_data, @@ -216,10 +230,6 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { WarnL << "不是H265 Track"; return; } - if(!h265_track->ready()){ - WarnL << "H265 Track未就绪"; - return; - } struct mpeg4_hevc_t hevc = {0}; string vps_sps_pps = string("\x00\x00\x00\x01", 4) + h265_track->getVps() + @@ -235,7 +245,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { } auto track_id = mov_writer_add_video(_mov_writter.get(), - MOV_OBJECT_HEVC, + mp4_object, h265_track->getVideoWidth(), h265_track->getVideoHeight(), extra_data, @@ -248,9 +258,8 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { _have_video = true; } break; - default: - WarnL << "MP4录制不支持该编码格式:" << track->getCodecName(); - break; + + default: WarnL << "MP4录制不支持该编码格式:" << track->getCodecName(); break; } }