mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
添加对g711A/U rtsp支持相关文件,api添加windows静态库编译选项,g711 RTMP支持尚未修改
This commit is contained in:
parent
fb77293648
commit
340629cdc6
@ -1,15 +1,24 @@
|
|||||||
include_directories(include source)
|
include_directories(include source)
|
||||||
|
|
||||||
file(GLOB api_src_list include/*.h source/*.cpp source/*.h source/*.c)
|
file(GLOB api_src_list include/*.h source/*.cpp source/*.h source/*.c)
|
||||||
|
|
||||||
|
set(ENABLE_API_STATIC false)
|
||||||
|
|
||||||
if (IOS)
|
if (IOS)
|
||||||
add_library(mk_api STATIC ${api_src_list})
|
add_library(mk_api STATIC ${api_src_list})
|
||||||
target_link_libraries(mk_api ${LINK_LIB_LIST})
|
target_link_libraries(mk_api ${LINK_LIB_LIST})
|
||||||
|
else ()
|
||||||
|
if(ENABLE_API_STATIC)
|
||||||
|
add_library(mk_api STATIC ${api_src_list})
|
||||||
|
if (WIN32)
|
||||||
|
add_definitions(-DMediaKitApi_STATIC)
|
||||||
|
endif ()
|
||||||
else ()
|
else ()
|
||||||
add_library(mk_api SHARED ${api_src_list})
|
add_library(mk_api SHARED ${api_src_list})
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_definitions(-DMediaKitApi_EXPORTS)
|
add_definitions(-DMediaKitApi_EXPORTS)
|
||||||
endif ()
|
endif ()
|
||||||
|
endif()
|
||||||
target_link_libraries(mk_api ${LINK_LIB_LIST})
|
target_link_libraries(mk_api ${LINK_LIB_LIST})
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
#ifndef MediaKitApi_STATIC
|
||||||
#if defined(MediaKitApi_EXPORTS)
|
#if defined(MediaKitApi_EXPORTS)
|
||||||
#define API_EXPORT __declspec(dllexport)
|
#define API_EXPORT __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
@ -26,6 +28,11 @@
|
|||||||
#define API_CALL
|
#define API_CALL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define API_EXPORT
|
||||||
|
#define API_CALL
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,6 +65,16 @@ API_EXPORT void API_CALL mk_media_init_h265(mk_media ctx, int width, int height,
|
|||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_media_init_aac(mk_media ctx, int channel, int sample_bit, int sample_rate, int profile);
|
API_EXPORT void API_CALL mk_media_init_aac(mk_media ctx, int channel, int sample_bit, int sample_rate, int profile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加g711音频轨道
|
||||||
|
* @param ctx 对象指针
|
||||||
|
* @param au 1.G711A 2.G711U
|
||||||
|
* @param channel 通道数
|
||||||
|
* @param sample_bit 采样位数,只支持16
|
||||||
|
* @param sample_rate 采样率
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_media_init_g711(mk_media ctx, int au, int sample_bit, int sample_rate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化h264/h265/aac完毕后调用此函数,
|
* 初始化h264/h265/aac完毕后调用此函数,
|
||||||
* 在单track(只有音频或视频)时,因为ZLMediaKit不知道后续是否还要添加track,所以会多等待3秒钟
|
* 在单track(只有音频或视频)时,因为ZLMediaKit不知道后续是否还要添加track,所以会多等待3秒钟
|
||||||
@ -113,6 +123,15 @@ API_EXPORT void API_CALL mk_media_input_aac(mk_media ctx, void *data, int len, u
|
|||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_media_input_aac1(mk_media ctx, void *data, int len, uint32_t dts, void *adts);
|
API_EXPORT void API_CALL mk_media_input_aac1(mk_media ctx, void *data, int len, uint32_t dts, void *adts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入单帧G711音频
|
||||||
|
* @param ctx 对象指针
|
||||||
|
* @param data 单帧G711数据
|
||||||
|
* @param len 单帧G711数据字节数
|
||||||
|
* @param dts 时间戳,毫秒
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_media_input_g711(mk_media ctx, void* data, int len, uint32_t dts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediaSource.close()回调事件
|
* MediaSource.close()回调事件
|
||||||
* 在选择关闭一个关联的MediaSource时,将会最终触发到该回调
|
* 在选择关闭一个关联的MediaSource时,将会最终触发到该回调
|
||||||
|
@ -140,6 +140,20 @@ API_EXPORT void API_CALL mk_media_init_aac(mk_media ctx, int channel, int sample
|
|||||||
(*obj)->getChannel()->initAudio(info);
|
(*obj)->getChannel()->initAudio(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_media_init_g711(mk_media ctx, int au, int sample_bit, int sample_rate)
|
||||||
|
{
|
||||||
|
assert(ctx);
|
||||||
|
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
||||||
|
AudioInfo info;
|
||||||
|
info.iSampleRate = sample_rate;
|
||||||
|
info.iChannel = 1;
|
||||||
|
info.iSampleBit = sample_bit;
|
||||||
|
info.iProfile = 0;
|
||||||
|
info.codecId = (CodecId)au;
|
||||||
|
(*obj)->getChannel()->initAudio(info);
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx){
|
API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
@ -170,6 +184,12 @@ API_EXPORT void API_CALL mk_media_input_aac1(mk_media ctx, void *data, int len,
|
|||||||
(*obj)->getChannel()->inputAAC((char *) data, len, dts, (char *) adts);
|
(*obj)->getChannel()->inputAAC((char *) data, len, dts, (char *) adts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_media_input_g711(mk_media ctx, void* data, int len, uint32_t dts)
|
||||||
|
{
|
||||||
|
assert(ctx && data && len > 0);
|
||||||
|
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
||||||
|
(*obj)->getChannel()->inputG711((char*)data, len, dts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "Util/base64.h"
|
#include "Util/base64.h"
|
||||||
#include "Util/TimeTicker.h"
|
#include "Util/TimeTicker.h"
|
||||||
#include "Extension/AAC.h"
|
#include "Extension/AAC.h"
|
||||||
|
#include "Extension/G711.h"
|
||||||
#include "Extension/H264.h"
|
#include "Extension/H264.h"
|
||||||
#include "Extension/H265.h"
|
#include "Extension/H265.h"
|
||||||
|
|
||||||
@ -148,6 +149,14 @@ void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t u
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DevChannel::inputG711(const char* pcData, int iDataLen, uint32_t uiStamp)
|
||||||
|
{
|
||||||
|
if (uiStamp == 0) {
|
||||||
|
uiStamp = (uint32_t)_aTicker[1].elapsedTime();
|
||||||
|
}
|
||||||
|
inputFrame(std::make_shared<G711FrameNoCacheAble>(_audio->codecId, (char*)pcData, iDataLen, uiStamp, 0));
|
||||||
|
}
|
||||||
|
|
||||||
void DevChannel::initVideo(const VideoInfo& info) {
|
void DevChannel::initVideo(const VideoInfo& info) {
|
||||||
_video = std::make_shared<VideoInfo>(info);
|
_video = std::make_shared<VideoInfo>(info);
|
||||||
addTrack(std::make_shared<H264Track>());
|
addTrack(std::make_shared<H264Track>());
|
||||||
@ -160,6 +169,8 @@ void DevChannel::initH265Video(const VideoInfo &info){
|
|||||||
|
|
||||||
void DevChannel::initAudio(const AudioInfo& info) {
|
void DevChannel::initAudio(const AudioInfo& info) {
|
||||||
_audio = std::make_shared<AudioInfo>(info);
|
_audio = std::make_shared<AudioInfo>(info);
|
||||||
|
if (info.codecId == CodecAAC)
|
||||||
|
{
|
||||||
addTrack(std::make_shared<AACTrack>());
|
addTrack(std::make_shared<AACTrack>());
|
||||||
|
|
||||||
AACFrame adtsHeader;
|
AACFrame adtsHeader;
|
||||||
@ -186,6 +197,11 @@ void DevChannel::initAudio(const AudioInfo& info) {
|
|||||||
adtsHeader.no_raw_data_blocks_in_frame = 0;
|
adtsHeader.no_raw_data_blocks_in_frame = 0;
|
||||||
writeAdtsHeader(adtsHeader, _adtsHeader);
|
writeAdtsHeader(adtsHeader, _adtsHeader);
|
||||||
}
|
}
|
||||||
|
else if (info.codecId == CodecG711A || info.codecId == CodecG711U)
|
||||||
|
{
|
||||||
|
addTrack(std::make_shared<G711Track>(info.codecId, info.iSampleBit, info.iSampleRate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
};
|
};
|
||||||
class AudioInfo {
|
class AudioInfo {
|
||||||
public:
|
public:
|
||||||
|
CodecId codecId;
|
||||||
int iChannel;
|
int iChannel;
|
||||||
int iSampleBit;
|
int iSampleBit;
|
||||||
int iSampleRate;
|
int iSampleRate;
|
||||||
@ -121,6 +122,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader);
|
void inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G711音频帧
|
||||||
|
* @param pcData 音频帧
|
||||||
|
* @param iDataLen 帧数据长度
|
||||||
|
* @param uiStamp 时间戳,单位毫秒
|
||||||
|
*/
|
||||||
|
void inputG711(const char* pcData, int iDataLen, uint32_t uiStamp);
|
||||||
#ifdef ENABLE_X264
|
#ifdef ENABLE_X264
|
||||||
/**
|
/**
|
||||||
* 输入yuv420p视频帧,内部会完成编码并调用inputH264方法
|
* 输入yuv420p视频帧,内部会完成编码并调用inputH264方法
|
||||||
|
@ -13,8 +13,10 @@
|
|||||||
#include "H264Rtmp.h"
|
#include "H264Rtmp.h"
|
||||||
#include "H265Rtmp.h"
|
#include "H265Rtmp.h"
|
||||||
#include "AACRtmp.h"
|
#include "AACRtmp.h"
|
||||||
|
#include "G711Rtmp.h"
|
||||||
#include "H264Rtp.h"
|
#include "H264Rtp.h"
|
||||||
#include "AACRtp.h"
|
#include "AACRtp.h"
|
||||||
|
#include "G711Rtp.h"
|
||||||
#include "H265Rtp.h"
|
#include "H265Rtp.h"
|
||||||
#include "Common/Parser.h"
|
#include "Common/Parser.h"
|
||||||
|
|
||||||
@ -45,6 +47,14 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
|||||||
return std::make_shared<AACTrack>(aac_cfg);
|
return std::make_shared<AACTrack>(aac_cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(track->_codec.data(), "PCMA") == 0) {
|
||||||
|
return std::make_shared<G711Track>(CodecG711A);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(track->_codec.data(), "PCMU") == 0) {
|
||||||
|
return std::make_shared<G711Track>(CodecG711U);
|
||||||
|
}
|
||||||
|
|
||||||
if (strcasecmp(track->_codec.data(), "h264") == 0) {
|
if (strcasecmp(track->_codec.data(), "h264") == 0) {
|
||||||
//a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA==
|
//a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA==
|
||||||
auto map = Parser::parseArgs(FindField(track->_fmtp.data()," ", nullptr),";","=");
|
auto map = Parser::parseArgs(FindField(track->_fmtp.data()," ", nullptr),";","=");
|
||||||
@ -90,6 +100,12 @@ Track::Ptr Factory::getTrackByCodecId(CodecId codecId) {
|
|||||||
case CodecAAC:{
|
case CodecAAC:{
|
||||||
return std::make_shared<AACTrack>();
|
return std::make_shared<AACTrack>();
|
||||||
}
|
}
|
||||||
|
case CodecG711A: {
|
||||||
|
return std::make_shared<G711Track>(CodecG711A);
|
||||||
|
}
|
||||||
|
case CodecG711U: {
|
||||||
|
return std::make_shared<G711Track>(CodecG711U);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
WarnL << "暂不支持该CodecId:" << codecId;
|
WarnL << "暂不支持该CodecId:" << codecId;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -125,6 +141,9 @@ RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
|
|||||||
return std::make_shared<H265RtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
|
return std::make_shared<H265RtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
|
||||||
case CodecAAC:
|
case CodecAAC:
|
||||||
return std::make_shared<AACRtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
|
return std::make_shared<AACRtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
|
||||||
|
case CodecG711A:
|
||||||
|
case CodecG711U:
|
||||||
|
return std::make_shared<G711RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
|
||||||
default:
|
default:
|
||||||
WarnL << "暂不支持该CodecId:" << codec_id;
|
WarnL << "暂不支持该CodecId:" << codec_id;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -139,6 +158,9 @@ RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) {
|
|||||||
return std::make_shared<H265RtpDecoder>();
|
return std::make_shared<H265RtpDecoder>();
|
||||||
case CodecAAC:
|
case CodecAAC:
|
||||||
return std::make_shared<AACRtpDecoder>(track->clone());
|
return std::make_shared<AACRtpDecoder>(track->clone());
|
||||||
|
case CodecG711A:
|
||||||
|
case CodecG711U:
|
||||||
|
return std::make_shared<G711RtpDecoder>(track->clone());
|
||||||
default:
|
default:
|
||||||
WarnL << "暂不支持该CodecId:" << track->getCodecName();
|
WarnL << "暂不支持该CodecId:" << track->getCodecName();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -198,6 +220,9 @@ RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) {
|
|||||||
return std::make_shared<AACRtmpEncoder>(track);
|
return std::make_shared<AACRtmpEncoder>(track);
|
||||||
case CodecH265:
|
case CodecH265:
|
||||||
return std::make_shared<H265RtmpEncoder>(track);
|
return std::make_shared<H265RtmpEncoder>(track);
|
||||||
|
case CodecG711A:
|
||||||
|
case CodecG711U:
|
||||||
|
return std::make_shared<G711RtmpEncoder>(track);
|
||||||
default:
|
default:
|
||||||
WarnL << "暂不支持该CodecId:" << track->getCodecName();
|
WarnL << "暂不支持该CodecId:" << track->getCodecName();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -209,6 +234,8 @@ AMFValue Factory::getAmfByCodecId(CodecId codecId) {
|
|||||||
case CodecAAC: return AMFValue("mp4a");
|
case CodecAAC: return AMFValue("mp4a");
|
||||||
case CodecH264: return AMFValue("avc1");
|
case CodecH264: return AMFValue("avc1");
|
||||||
case CodecH265: return AMFValue(FLV_CODEC_H265);
|
case CodecH265: return AMFValue(FLV_CODEC_H265);
|
||||||
|
case CodecG711A: return AMFValue(7);
|
||||||
|
case CodecG711U: return AMFValue(8);
|
||||||
default: return AMFValue(AMF_NULL);
|
default: return AMFValue(AMF_NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@ typedef enum {
|
|||||||
CodecH264 = 0,
|
CodecH264 = 0,
|
||||||
CodecH265,
|
CodecH265,
|
||||||
CodecAAC,
|
CodecAAC,
|
||||||
|
CodecG711A,
|
||||||
|
CodecG711U,
|
||||||
CodecMax = 0x7FFF
|
CodecMax = 0x7FFF
|
||||||
} CodecId;
|
} CodecId;
|
||||||
|
|
||||||
|
26
src/Extension/G711.cpp
Normal file
26
src/Extension/G711.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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 "G711.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
|
||||||
|
Sdp::Ptr G711Track::getSdp() {
|
||||||
|
if(!ready()){
|
||||||
|
WarnL << "AAC Track未准备好";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::make_shared<G711Sdp>(getCodecId(), getAudioSampleRate(), getCodecId() == CodecG711A ? 8 : 0, getAudioSampleBit());
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
248
src/Extension/G711.h
Normal file
248
src/Extension/G711.h
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* 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_G711_H
|
||||||
|
#define ZLMEDIAKIT_G711_H
|
||||||
|
|
||||||
|
#include "Frame.h"
|
||||||
|
#include "Track.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
class G711Frame;
|
||||||
|
|
||||||
|
unsigned const samplingFrequencyTableG711[16] = { 96000, 88200,
|
||||||
|
64000, 48000,
|
||||||
|
44100, 32000,
|
||||||
|
24000, 22050,
|
||||||
|
16000, 12000,
|
||||||
|
11025, 8000,
|
||||||
|
7350, 0, 0, 0 };
|
||||||
|
|
||||||
|
void makeAdtsHeader(const string &strAudioCfg,G711Frame &adts);
|
||||||
|
void writeAdtsHeader(const G711Frame &adts, uint8_t *pcAdts) ;
|
||||||
|
string makeG711AdtsConfig(const uint8_t *pcAdts);
|
||||||
|
void getAACInfo(const G711Frame &adts,int &iSampleRate,int &iChannel);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac帧,包含adts头
|
||||||
|
*/
|
||||||
|
class G711Frame : public Frame {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<G711Frame> Ptr;
|
||||||
|
|
||||||
|
char *data() const override{
|
||||||
|
return (char *)buffer;
|
||||||
|
}
|
||||||
|
uint32_t size() const override {
|
||||||
|
return frameLength;
|
||||||
|
}
|
||||||
|
uint32_t dts() const override {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
uint32_t prefixSize() const override{
|
||||||
|
return iPrefixSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return CodecAAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool configFrame() const override{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
unsigned int frameLength; // 一个帧的长度包括 raw data block
|
||||||
|
unsigned char buffer[2 * 1024 + 7];
|
||||||
|
uint32_t timeStamp;
|
||||||
|
uint32_t iPrefixSize = 0;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
class G711FrameNoCacheAble : public FrameNoCacheAble {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<G711FrameNoCacheAble> Ptr;
|
||||||
|
|
||||||
|
G711FrameNoCacheAble(CodecId codecId, char *ptr,uint32_t size,uint32_t dts,int prefixeSize = 7){
|
||||||
|
_codecId = codecId;
|
||||||
|
_ptr = ptr;
|
||||||
|
_size = size;
|
||||||
|
_dts = dts;
|
||||||
|
_prefixSize = prefixeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return _codecId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool configFrame() const override{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CodecId _codecId;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g711音频通道
|
||||||
|
*/
|
||||||
|
class G711Track : public AudioTrack{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<G711Track> Ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延后获取adts头信息
|
||||||
|
* 在随后的inputFrame中获取adts头信息
|
||||||
|
*/
|
||||||
|
G711Track(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G711A G711U
|
||||||
|
*/
|
||||||
|
G711Track(CodecId codecId, int sampleBit = 16, int sampleRate = 8000){
|
||||||
|
_codecid = codecId;
|
||||||
|
_sampleBit = sampleBit;
|
||||||
|
_sampleRate = sampleRate;
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回编码类型
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return _codecid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在获取aac_cfg前是无效的Track
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool ready() override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回音频采样率
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getAudioSampleRate() const override{
|
||||||
|
return _sampleRate;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 返回音频采样位数,一般为16或8
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getAudioSampleBit() const override{
|
||||||
|
return _sampleBit;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 返回音频通道数
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getAudioChannel() const override{
|
||||||
|
return _channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入数据帧,并获取aac_cfg
|
||||||
|
* @param frame 数据帧
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override{
|
||||||
|
AudioTrack::inputFrame(frame);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void onReady(){
|
||||||
|
/*
|
||||||
|
if(_cfg.size() < 2){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
G711Frame aacFrame;
|
||||||
|
makeAdtsHeader(_cfg,aacFrame);
|
||||||
|
getAACInfo(aacFrame,_sampleRate,_channel);*/
|
||||||
|
}
|
||||||
|
Track::Ptr clone() override {
|
||||||
|
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//生成sdp
|
||||||
|
Sdp::Ptr getSdp() override ;
|
||||||
|
private:
|
||||||
|
string _cfg;
|
||||||
|
CodecId _codecid = CodecG711A;
|
||||||
|
int _sampleRate = 8000;
|
||||||
|
int _sampleBit = 16;
|
||||||
|
int _channel = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac类型SDP
|
||||||
|
*/
|
||||||
|
class G711Sdp : public Sdp {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param aac_codecId G711A G711U
|
||||||
|
* @param sample_rate 音频采样率
|
||||||
|
* @param playload_type rtp playload type 默认0为G711U, 8为G711A
|
||||||
|
* @param bitrate 比特率
|
||||||
|
*/
|
||||||
|
G711Sdp(CodecId codecId,
|
||||||
|
int sample_rate,
|
||||||
|
int playload_type = 0,
|
||||||
|
int bitrate = 128) : Sdp(sample_rate,playload_type), _codecId(codecId){
|
||||||
|
_printer << "m=audio 0 RTP/AVP " << playload_type << "\r\n";
|
||||||
|
//_printer << "b=AS:" << bitrate << "\r\n";
|
||||||
|
_printer << "a=rtpmap:" << playload_type << (codecId == CodecG711A ? " PCMA/" : " PCMU/") << sample_rate << "\r\n";
|
||||||
|
_printer << "a=control:trackID=" << getTrackType() << "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
string getSdp() const override {
|
||||||
|
return _printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override {
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return _codecId;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
_StrPrinter _printer;
|
||||||
|
CodecId _codecId = CodecG711A;
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_AAC_H
|
68
src/Extension/G711Rtmp.cpp
Normal file
68
src/Extension/G711Rtmp.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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 "G711Rtmp.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
G711RtmpDecoder::G711RtmpDecoder() {
|
||||||
|
_adts = obtainFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
G711Frame::Ptr G711RtmpDecoder::obtainFrame() {
|
||||||
|
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
||||||
|
auto frame = ResourcePoolHelper<G711Frame>::obtainObj();
|
||||||
|
frame->frameLength = 0;
|
||||||
|
frame->iPrefixSize = 0;
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool G711RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool key_pos) {
|
||||||
|
onGetG711(pkt->strBuf.data() + 2, pkt->strBuf.size() - 2, pkt->timeStamp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void G711RtmpDecoder::onGetG711(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
|
||||||
|
if(iLen + 7 > sizeof(_adts->buffer)){
|
||||||
|
WarnL << "Illegal adts data, exceeding the length limit.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//拷贝aac负载
|
||||||
|
memcpy(_adts->buffer, pcData, iLen);
|
||||||
|
_adts->frameLength = iLen;
|
||||||
|
_adts->timeStamp = ui32TimeStamp;
|
||||||
|
|
||||||
|
//写入环形缓存
|
||||||
|
RtmpCodec::inputFrame(_adts);
|
||||||
|
_adts = obtainFrame();
|
||||||
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
G711RtmpEncoder::G711RtmpEncoder(const Track::Ptr &track) {
|
||||||
|
_track = dynamic_pointer_cast<G711Track>(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
void G711RtmpEncoder::inputFrame(const Frame::Ptr& frame) {
|
||||||
|
|
||||||
|
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
|
||||||
|
rtmpPkt->strBuf.clear();
|
||||||
|
rtmpPkt->strBuf.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||||
|
|
||||||
|
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
|
||||||
|
rtmpPkt->chunkId = CHUNK_AUDIO;
|
||||||
|
rtmpPkt->streamId = STREAM_MEDIA;
|
||||||
|
rtmpPkt->timeStamp = frame->dts();
|
||||||
|
rtmpPkt->typeId = MSG_AUDIO;
|
||||||
|
RtmpCodec::inputRtmp(rtmpPkt, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace mediakit
|
86
src/Extension/G711Rtmp.h
Normal file
86
src/Extension/G711Rtmp.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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_G711RTMPCODEC_H
|
||||||
|
#define ZLMEDIAKIT_G711RTMPCODEC_H
|
||||||
|
|
||||||
|
#include "Rtmp/RtmpCodec.h"
|
||||||
|
#include "Extension/Track.h"
|
||||||
|
#include "Extension/G711.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
/**
|
||||||
|
* G711 Rtmp转adts类
|
||||||
|
*/
|
||||||
|
class G711RtmpDecoder : public RtmpCodec , public ResourcePoolHelper<G711Frame> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<G711RtmpDecoder> Ptr;
|
||||||
|
|
||||||
|
G711RtmpDecoder();
|
||||||
|
~G711RtmpDecoder() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入Rtmp并解码
|
||||||
|
* @param Rtmp Rtmp数据包
|
||||||
|
* @param key_pos 此参数内部强制转换为false,请忽略之
|
||||||
|
*/
|
||||||
|
bool inputRtmp(const RtmpPacket::Ptr &Rtmp, bool key_pos = false) override;
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCodecId(CodecId codecId)
|
||||||
|
{
|
||||||
|
_codecid = codecId;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return _codecid;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onGetG711(const char* pcData, int iLen, uint32_t ui32TimeStamp);
|
||||||
|
G711Frame::Ptr obtainFrame();
|
||||||
|
protected:
|
||||||
|
G711Frame::Ptr _adts;
|
||||||
|
CodecId _codecid = CodecG711A;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac adts转Rtmp类
|
||||||
|
*/
|
||||||
|
class G711RtmpEncoder : public G711RtmpDecoder , public ResourcePoolHelper<RtmpPacket> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<G711RtmpEncoder> Ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数,track可以为空,此时则在inputFrame时输入adts头
|
||||||
|
* 如果track不为空且包含adts头相关信息,
|
||||||
|
* 那么inputFrame时可以不输入adts头
|
||||||
|
* @param track
|
||||||
|
*/
|
||||||
|
G711RtmpEncoder(const Track::Ptr &track);
|
||||||
|
~G711RtmpEncoder() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入aac 数据,可以不带adts头
|
||||||
|
* @param frame aac数据
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
private:
|
||||||
|
G711Track::Ptr _track;
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_G711RTMPCODEC_H
|
101
src/Extension/G711Rtp.cpp
Normal file
101
src/Extension/G711Rtp.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* 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 "G711Rtp.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
G711RtpEncoder::G711RtpEncoder(uint32_t ui32Ssrc,
|
||||||
|
uint32_t ui32MtuSize,
|
||||||
|
uint32_t ui32SampleRate,
|
||||||
|
uint8_t ui8PlayloadType,
|
||||||
|
uint8_t ui8Interleaved) :
|
||||||
|
RtpInfo(ui32Ssrc,
|
||||||
|
ui32MtuSize,
|
||||||
|
ui32SampleRate,
|
||||||
|
ui8PlayloadType,
|
||||||
|
ui8Interleaved){
|
||||||
|
}
|
||||||
|
|
||||||
|
void G711RtpEncoder::inputFrame(const Frame::Ptr &frame) {
|
||||||
|
GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS);
|
||||||
|
auto uiStamp = frame->dts();
|
||||||
|
auto pcData = frame->data() + frame->prefixSize();
|
||||||
|
auto iLen = frame->size() - frame->prefixSize();
|
||||||
|
|
||||||
|
uiStamp %= cycleMS;
|
||||||
|
char *ptr = (char *) pcData;
|
||||||
|
int iSize = iLen;
|
||||||
|
while (iSize > 0) {
|
||||||
|
if (iSize <= _ui32MtuSize - 20) {
|
||||||
|
makeG711Rtp(ptr, iSize, true, uiStamp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
makeG711Rtp(ptr, _ui32MtuSize - 20, false, uiStamp);
|
||||||
|
ptr += (_ui32MtuSize - 20);
|
||||||
|
iSize -= (_ui32MtuSize - 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void G711RtpEncoder::makeG711Rtp(const void *data, unsigned int len, bool mark, uint32_t uiStamp) {
|
||||||
|
RtpCodec::inputRtp(makeRtp(getTrackType(),data,len,mark,uiStamp), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
G711RtpDecoder::G711RtpDecoder(const Track::Ptr &track){
|
||||||
|
auto aacTrack = dynamic_pointer_cast<G711Track>(track);
|
||||||
|
_codecid = aacTrack->getCodecId();
|
||||||
|
if(!aacTrack || !aacTrack->ready()){
|
||||||
|
WarnL << "该g711 track无效!";
|
||||||
|
}else{
|
||||||
|
//_aac_cfg = aacTrack->getAacCfg();
|
||||||
|
}
|
||||||
|
_adts = obtainFrame();
|
||||||
|
}
|
||||||
|
G711RtpDecoder::G711RtpDecoder() {
|
||||||
|
_adts = obtainFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
G711Frame::Ptr G711RtpDecoder::obtainFrame() {
|
||||||
|
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
|
||||||
|
auto frame = ResourcePoolHelper<G711Frame>::obtainObj();
|
||||||
|
frame->frameLength = 0;
|
||||||
|
frame->iPrefixSize = 0;
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool G711RtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
|
||||||
|
// 获取rtp数据长度
|
||||||
|
int length = rtppack->size() - rtppack->offset;
|
||||||
|
|
||||||
|
// 获取rtp数据
|
||||||
|
const uint8_t *rtp_packet_buf = (uint8_t *)rtppack->data() + rtppack->offset;
|
||||||
|
|
||||||
|
_adts->frameLength = length;
|
||||||
|
memcpy(_adts->buffer, rtp_packet_buf, length);
|
||||||
|
if (rtppack->mark == true) {
|
||||||
|
_adts->timeStamp = rtppack->timeStamp;
|
||||||
|
onGetG711(_adts);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void G711RtpDecoder::onGetG711(const G711Frame::Ptr &frame) {
|
||||||
|
//写入环形缓存
|
||||||
|
RtpCodec::inputFrame(frame);
|
||||||
|
_adts = obtainFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
|
84
src/Extension/G711Rtp.h
Normal file
84
src/Extension/G711Rtp.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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_G711RTPCODEC_H
|
||||||
|
#define ZLMEDIAKIT_G711RTPCODEC_H
|
||||||
|
|
||||||
|
#include "Rtsp/RtpCodec.h"
|
||||||
|
#include "Extension/G711.h"
|
||||||
|
namespace mediakit{
|
||||||
|
/**
|
||||||
|
* G711 rtp转adts类
|
||||||
|
*/
|
||||||
|
class G711RtpDecoder : public RtpCodec , public ResourcePoolHelper<G711Frame> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<G711RtpDecoder> Ptr;
|
||||||
|
|
||||||
|
G711RtpDecoder(const Track::Ptr &track);
|
||||||
|
~G711RtpDecoder() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入rtp并解码
|
||||||
|
* @param rtp rtp数据包
|
||||||
|
* @param key_pos 此参数内部强制转换为false,请忽略之
|
||||||
|
*/
|
||||||
|
bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override;
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return _codecid;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
G711RtpDecoder();
|
||||||
|
private:
|
||||||
|
void onGetG711(const G711Frame::Ptr &frame);
|
||||||
|
G711Frame::Ptr obtainFrame();
|
||||||
|
private:
|
||||||
|
G711Frame::Ptr _adts;
|
||||||
|
CodecId _codecid = CodecG711A;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g711 转rtp类
|
||||||
|
*/
|
||||||
|
class G711RtpEncoder : public G711RtpDecoder , public RtpInfo {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<G711RtpEncoder> Ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ui32Ssrc ssrc
|
||||||
|
* @param ui32MtuSize mtu 大小
|
||||||
|
* @param ui32SampleRate 采样率
|
||||||
|
* @param ui8PlayloadType pt类型
|
||||||
|
* @param ui8Interleaved rtsp interleaved 值
|
||||||
|
*/
|
||||||
|
G711RtpEncoder(uint32_t ui32Ssrc,
|
||||||
|
uint32_t ui32MtuSize,
|
||||||
|
uint32_t ui32SampleRate,
|
||||||
|
uint8_t ui8PlayloadType = 0,
|
||||||
|
uint8_t ui8Interleaved = TrackAudio * 2);
|
||||||
|
~G711RtpEncoder() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param frame g711数据
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override;
|
||||||
|
private:
|
||||||
|
void makeG711Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
|
||||||
|
private:
|
||||||
|
unsigned char _aucSectionBuf[1600];
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_G711RTPCODEC_H
|
@ -779,7 +779,7 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
|||||||
rtp_info.pop_back();
|
rtp_info.pop_back();
|
||||||
|
|
||||||
sendRtspResponse("200 OK",
|
sendRtspResponse("200 OK",
|
||||||
{"Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << /*pMediaSrc->getTimeStamp(TrackInvalid) / 1000.0*/iStartTime/1000,
|
{"Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << (useBuf? iStartTime / 1000:pMediaSrc->getTimeStamp(TrackInvalid) / 1000.0),
|
||||||
"RTP-Info",rtp_info
|
"RTP-Info",rtp_info
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user