// Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "aac_server_media_subsession.hh" #include "MPEG4GenericRTPSink.hh" #include "utils.h" namespace easymedia { static unsigned const samplingFrequencyTable[16] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0}; AACServerMediaSubsession* AACServerMediaSubsession::createNew(UsageEnvironment& env, Live555MediaInput& wisInput, unsigned samplingFrequency, unsigned numChannels, unsigned char profile) { return new AACServerMediaSubsession(env, wisInput, samplingFrequency, numChannels, profile); } AACServerMediaSubsession::AACServerMediaSubsession(UsageEnvironment& env, Live555MediaInput& mediaInput, unsigned samplingFrequency, unsigned numChannels, unsigned char profile) : OnDemandServerMediaSubsession(env, True /*reuse the first source*/), fMediaInput(mediaInput), fSamplingFrequency(samplingFrequency), fNumChannels(numChannels) { unsigned char audioSpecificConfig[2]; unsigned char const audioObjectType = profile + 1; unsigned char samplingFrequencyIndex = 0; for (unsigned char i = 0; i < 16; i++) { if (samplingFrequencyTable[i] == fSamplingFrequency) { samplingFrequencyIndex = i; break; } } audioSpecificConfig[0] = (audioObjectType << 3) | (samplingFrequencyIndex >> 1); // audioSpecificConfig[1] = (samplingFrequencyIndex<<7) | // (channelConfiguration<<3); audioSpecificConfig[1] = (samplingFrequencyIndex << 7) | (fNumChannels << 3); sprintf(fConfigStr, "%02X%02x", audioSpecificConfig[0], audioSpecificConfig[1]); } AACServerMediaSubsession::~AACServerMediaSubsession() { LOG_FILE_FUNC_LINE(); } FramedSource* AACServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) { LOG_FILE_FUNC_LINE(); estBitrate = 96; // kbps, estimate return fMediaInput.audioSource(); } RTPSink* AACServerMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource) { if (!inputSource) { LOG("inputSource is not ready, can not create new rtp sink\n"); return NULL; } // ADTSAudioFileSource* adtsSource = (ADTSAudioFileSource*)inputSource; setAudioRTPSinkBufferSize(); RTPSink* rtpsink = MPEG4GenericRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic, fSamplingFrequency, "audio", "AAC-hbr", fConfigStr, fNumChannels); setVideoRTPSinkBufferSize(); return rtpsink; } // std::mutex AACServerMediaSubsession::kMutex; void AACServerMediaSubsession::startStream(unsigned clientSessionId, void* streamToken, TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData, unsigned short& rtpSeqNum, unsigned& rtpTimestamp, ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler, void* serverRequestAlternativeByteHandlerClientData) { OnDemandServerMediaSubsession::startStream(clientSessionId, streamToken, rtcpRRHandler, rtcpRRHandlerClientData, rtpSeqNum, rtpTimestamp, serverRequestAlternativeByteHandler, serverRequestAlternativeByteHandlerClientData); // kMutex.lock(); if (kSessionIdList.empty()) { fMediaInput.Start(envir()); } if (fMediaInput.GetStartAudioStreamCallback() != NULL) { fMediaInput.GetStartAudioStreamCallback()(); } LOG("%s:%s:%p - clientSessionId: 0x%08x\n", __FILE__, __func__, this, clientSessionId); kSessionIdList.push_back(clientSessionId); // kMutex.unlock(); } void AACServerMediaSubsession::deleteStream(unsigned clientSessionId, void*& streamToken) { // kMutex.lock(); LOG("%s - clientSessionId: 0x%08x\n", __func__, clientSessionId); kSessionIdList.remove(clientSessionId); if (kSessionIdList.empty()) { fMediaInput.Stop(envir()); } // kMutex.unlock(); OnDemandServerMediaSubsession::deleteStream(clientSessionId, streamToken); } } // namespace easymedia