Replaced the _audio parameter with a strategy.
The purpose is to make _rtpReceiver mostly agnostic to if it processes audio or video, and make its delegates responsible for that. This patch makes the actual interfaces and interactions between the classes a lot clearer which will probably help straighten out the rather convoluted business logic in here. There are a number of rough edges I hope to address in coming patches. In particular, I think there are a lot of audio-specific hacks, especially when it comes to telephone event handling. I think we will see a lot of benefit once that stuff moves out of rtp_receiver altogether. The new strategy I introduced doesn't quite pull its own weight yet, but I think I will be able to remove a lot of that interface later once the responsibilities of the classes becomes move cohesive (e.g. that audio specific stuff actually lives in the audio class, and so on). Also I think it should be possible to extract payload type management to a helper class later on. BUG= TEST=vie/voe_auto_test, trybots Review URL: https://webrtc-codereview.appspot.com/1001006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3306 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -8,17 +8,20 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "trace.h"
|
||||
#include "rtp_receiver.h"
|
||||
|
||||
#include "rtp_rtcp_defines.h"
|
||||
#include "rtp_rtcp_impl.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h> //memcpy
|
||||
#include <math.h> // floor
|
||||
#include <stdlib.h> // abs
|
||||
#include <string.h> //memcpy
|
||||
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "rtp_receiver_audio.h"
|
||||
#include "rtp_receiver_strategy.h"
|
||||
#include "rtp_receiver_video.h"
|
||||
#include "rtp_rtcp_defines.h"
|
||||
#include "rtp_rtcp_impl.h"
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -36,7 +39,6 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
|
||||
RtpAudioFeedback* incomingMessagesCallback) :
|
||||
Bitrate(clock),
|
||||
_id(id),
|
||||
_audio(audio),
|
||||
_rtpRtcp(*owner),
|
||||
_criticalSectionCbs(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_cbRtpFeedback(NULL),
|
||||
@ -48,8 +50,6 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
|
||||
_lastReceivedPayloadLength(0),
|
||||
_lastReceivedPayloadType(-1),
|
||||
_lastReceivedMediaPayloadType(-1),
|
||||
_lastReceivedAudioSpecific(),
|
||||
_lastReceivedVideoSpecific(),
|
||||
|
||||
_packetTimeOutMS(0),
|
||||
|
||||
@ -95,16 +95,21 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
|
||||
_nackMethod(kNackOff),
|
||||
_RTX(false),
|
||||
_ssrcRTX(0) {
|
||||
// TODO(phoglund): Remove hacks requiring direct access to the audio receiver
|
||||
// and only instantiate one of these directly into the _rtpMediaReceiver
|
||||
// field. Right now an audio receiver carries around a video handler and
|
||||
// vice versa, which doesn't make sense.
|
||||
_rtpReceiverAudio = new RTPReceiverAudio(id, this, incomingMessagesCallback);
|
||||
_rtpReceiverVideo = new RTPReceiverVideo(id, this, owner);
|
||||
|
||||
if (audio) {
|
||||
_rtpMediaReceiver = _rtpReceiverAudio;
|
||||
} else {
|
||||
_rtpMediaReceiver = _rtpReceiverVideo;
|
||||
}
|
||||
|
||||
memset(_currentRemoteCSRC, 0, sizeof(_currentRemoteCSRC));
|
||||
memset(_currentRemoteEnergy, 0, sizeof(_currentRemoteEnergy));
|
||||
memset(&_lastReceivedAudioSpecific, 0, sizeof(_lastReceivedAudioSpecific));
|
||||
|
||||
_lastReceivedAudioSpecific.channels = 1;
|
||||
_lastReceivedVideoSpecific.maxRate = 0;
|
||||
_lastReceivedVideoSpecific.videoCodecType = kRtpNoVideo;
|
||||
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
|
||||
}
|
||||
@ -131,13 +136,17 @@ RTPReceiver::~RTPReceiver() {
|
||||
RtpVideoCodecTypes
|
||||
RTPReceiver::VideoCodecType() const
|
||||
{
|
||||
return _lastReceivedVideoSpecific.videoCodecType;
|
||||
ModuleRTPUtility::PayloadUnion mediaSpecific;
|
||||
_rtpMediaReceiver->GetLastMediaSpecificPayload(&mediaSpecific);
|
||||
return mediaSpecific.Video.videoCodecType;
|
||||
}
|
||||
|
||||
WebRtc_UWord32
|
||||
RTPReceiver::MaxConfiguredBitrate() const
|
||||
{
|
||||
return _lastReceivedVideoSpecific.maxRate;
|
||||
ModuleRTPUtility::PayloadUnion mediaSpecific;
|
||||
_rtpMediaReceiver->GetLastMediaSpecificPayload(&mediaSpecific);
|
||||
return mediaSpecific.Video.maxRate;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -201,7 +210,7 @@ void RTPReceiver::PacketTimeout()
|
||||
}
|
||||
|
||||
void
|
||||
RTPReceiver::ProcessDeadOrAlive(const bool RTCPalive, const WebRtc_Word64 now)
|
||||
RTPReceiver::ProcessDeadOrAlive(const bool rtcpAlive, const WebRtc_Word64 now)
|
||||
{
|
||||
if(_cbRtpFeedback == NULL)
|
||||
{
|
||||
@ -217,25 +226,10 @@ RTPReceiver::ProcessDeadOrAlive(const bool RTCPalive, const WebRtc_Word64 now)
|
||||
|
||||
} else
|
||||
{
|
||||
if(RTCPalive)
|
||||
if(rtcpAlive)
|
||||
{
|
||||
if(_audio)
|
||||
{
|
||||
// alive depends on CNG
|
||||
// if last received size < 10 likely CNG
|
||||
if(_lastReceivedPayloadLength < 10) // our CNG is 9 bytes
|
||||
{
|
||||
// potential CNG
|
||||
// receiver need to check kRtpNoRtp against NetEq speechType kOutputPLCtoCNG
|
||||
alive = kRtpNoRtp;
|
||||
} else
|
||||
{
|
||||
// dead
|
||||
}
|
||||
} else
|
||||
{
|
||||
// dead for video
|
||||
}
|
||||
alive = _rtpMediaReceiver->ProcessDeadOrAlive(
|
||||
_lastReceivedPayloadLength);
|
||||
}else
|
||||
{
|
||||
// no RTP packet for 1 sec and no RTCP
|
||||
@ -331,19 +325,9 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
|
||||
// if same ignore sending an error
|
||||
if (payloadNameLength == nameLength &&
|
||||
StringCompare(payload->name, payloadName, payloadNameLength)) {
|
||||
if (_audio &&
|
||||
payload->audio &&
|
||||
payload->typeSpecific.Audio.frequency == frequency &&
|
||||
payload->typeSpecific.Audio.channels == channels &&
|
||||
(payload->typeSpecific.Audio.rate == rate ||
|
||||
payload->typeSpecific.Audio.rate == 0 || rate == 0)) {
|
||||
payload->typeSpecific.Audio.rate = rate;
|
||||
// Ensure that we update the rate if new or old is zero
|
||||
return 0;
|
||||
}
|
||||
if (!_audio && !payload->audio) {
|
||||
// update maxBitrate for video
|
||||
payload->typeSpecific.Video.maxRate = rate;
|
||||
if (_rtpMediaReceiver->PayloadIsCompatible(*payload, frequency,
|
||||
channels, rate)) {
|
||||
_rtpMediaReceiver->UpdatePayloadRate(payload, rate);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -352,38 +336,11 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
|
||||
__FUNCTION__, payloadType);
|
||||
return -1;
|
||||
}
|
||||
if (_audio) {
|
||||
// remove existing item, hence search for the name
|
||||
// only for audio, for video we allow a codecs to use multiple pltypes
|
||||
std::map<WebRtc_Word8, Payload*>::iterator audio_it =
|
||||
_payloadTypeMap.begin();
|
||||
while (audio_it != _payloadTypeMap.end()) {
|
||||
Payload* payload = audio_it->second;
|
||||
size_t nameLength = strlen(payload->name);
|
||||
|
||||
if (payloadNameLength == nameLength &&
|
||||
StringCompare(payload->name, payloadName, payloadNameLength)) {
|
||||
// we found the payload name in the list
|
||||
// if audio check frequency and rate
|
||||
if (payload->audio) {
|
||||
if (payload->typeSpecific.Audio.frequency == frequency &&
|
||||
(payload->typeSpecific.Audio.rate == rate ||
|
||||
payload->typeSpecific.Audio.rate == 0 || rate == 0) &&
|
||||
payload->typeSpecific.Audio.channels == channels) {
|
||||
// remove old setting
|
||||
delete payload;
|
||||
_payloadTypeMap.erase(audio_it);
|
||||
break;
|
||||
}
|
||||
} else if(StringCompare(payloadName,"red",3)) {
|
||||
delete payload;
|
||||
_payloadTypeMap.erase(audio_it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
audio_it++;
|
||||
}
|
||||
}
|
||||
_rtpMediaReceiver->PossiblyRemoveExistingPayloadType(
|
||||
&_payloadTypeMap, payloadName, payloadNameLength, frequency, channels,
|
||||
rate);
|
||||
|
||||
Payload* payload = NULL;
|
||||
|
||||
// save the RED payload type
|
||||
@ -395,13 +352,8 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
|
||||
payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
||||
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
|
||||
} else {
|
||||
if (_audio) {
|
||||
payload = _rtpReceiverAudio->RegisterReceiveAudioPayload(
|
||||
payloadName, payloadType, frequency, channels, rate);
|
||||
} else {
|
||||
payload = _rtpReceiverVideo->RegisterReceiveVideoPayload(
|
||||
payloadName, payloadType, rate);
|
||||
}
|
||||
payload = _rtpMediaReceiver->CreatePayloadType(
|
||||
payloadName, payloadType, frequency, channels, rate);
|
||||
}
|
||||
if (payload == NULL) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||
@ -512,7 +464,7 @@ WebRtc_Word32 RTPReceiver::ReceivePayload(
|
||||
if(payload->audio) {
|
||||
*frequency = payload->typeSpecific.Audio.frequency;
|
||||
} else {
|
||||
*frequency = 90000;
|
||||
*frequency = kDefaultVideoFrequency;
|
||||
}
|
||||
}
|
||||
if (channels) {
|
||||
@ -565,7 +517,7 @@ WebRtc_Word32 RTPReceiver::RemotePayload(
|
||||
if (payload->audio) {
|
||||
*frequency = payload->typeSpecific.Audio.frequency;
|
||||
} else {
|
||||
*frequency = 90000;
|
||||
*frequency = kDefaultVideoFrequency;
|
||||
}
|
||||
}
|
||||
if (channels) {
|
||||
@ -721,19 +673,12 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket(
|
||||
CheckSSRCChanged(rtp_header);
|
||||
|
||||
bool is_red = false;
|
||||
VideoPayload video_specific;
|
||||
video_specific.maxRate = 0;
|
||||
video_specific.videoCodecType = kRtpNoVideo;
|
||||
|
||||
AudioPayload audio_specific;
|
||||
audio_specific.channels = 0;
|
||||
audio_specific.frequency = 0;
|
||||
ModuleRTPUtility::PayloadUnion specificPayload;
|
||||
|
||||
if (CheckPayloadChanged(rtp_header,
|
||||
first_payload_byte,
|
||||
is_red,
|
||||
audio_specific,
|
||||
video_specific) == -1) {
|
||||
&specificPayload) == -1) {
|
||||
if (length - rtp_header->header.headerLength == 0)
|
||||
{
|
||||
// ok keepalive packet
|
||||
@ -749,22 +694,13 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket(
|
||||
}
|
||||
CheckCSRC(rtp_header);
|
||||
|
||||
const WebRtc_UWord8* payload_data =
|
||||
packet + rtp_header->header.headerLength;
|
||||
|
||||
WebRtc_UWord16 payload_data_length =
|
||||
static_cast<WebRtc_UWord16>(length - rtp_header->header.headerLength);
|
||||
ModuleRTPUtility::GetPayloadDataLength(rtp_header, packet_length);
|
||||
|
||||
WebRtc_Word32 retVal = _rtpMediaReceiver->ParseRtpPacket(
|
||||
rtp_header, specificPayload, is_red, packet,
|
||||
packet_length, _clock.GetTimeInMS());
|
||||
|
||||
WebRtc_Word32 retVal = 0;
|
||||
if(_audio) {
|
||||
retVal = _rtpReceiverAudio->ParseAudioCodecSpecific(
|
||||
rtp_header, payload_data, payload_data_length, audio_specific, is_red);
|
||||
} else {
|
||||
retVal = _rtpReceiverVideo->ParseVideoCodecSpecific(
|
||||
rtp_header, payload_data, payload_data_length,
|
||||
video_specific.videoCodecType, is_red, packet, packet_length,
|
||||
_clock.GetTimeInMS());
|
||||
}
|
||||
if(retVal < 0) {
|
||||
return retVal;
|
||||
}
|
||||
@ -816,11 +752,7 @@ RTPReceiver::UpdateStatistics(const WebRtcRTPHeader* rtpHeader,
|
||||
const WebRtc_UWord16 bytes,
|
||||
const bool oldPacket)
|
||||
{
|
||||
WebRtc_UWord32 freq = 90000;
|
||||
if(_audio)
|
||||
{
|
||||
freq = _rtpReceiverAudio->AudioFrequency();
|
||||
}
|
||||
WebRtc_UWord32 freq = _rtpMediaReceiver->GetFrequencyHz();
|
||||
|
||||
Bitrate::Update(bytes);
|
||||
|
||||
@ -918,10 +850,8 @@ bool RTPReceiver::RetransmitOfOldPacket(
|
||||
if (InOrderPacket(sequenceNumber)) {
|
||||
return false;
|
||||
}
|
||||
WebRtc_UWord32 frequencyKHz = 90; // Video frequency.
|
||||
if (_audio) {
|
||||
frequencyKHz = _rtpReceiverAudio->AudioFrequency() / 1000;
|
||||
}
|
||||
|
||||
WebRtc_UWord32 frequencyKHz = _rtpMediaReceiver->GetFrequencyHz() / 1000;
|
||||
WebRtc_Word64 timeDiffMS = _clock.GetTimeInMS() - _lastReceiveTime;
|
||||
// Diff in time stamp since last received in order.
|
||||
WebRtc_Word32 rtpTimeStampDiffMS = static_cast<WebRtc_Word32>(
|
||||
@ -1025,11 +955,8 @@ WebRtc_Word32
|
||||
RTPReceiver::EstimatedRemoteTimeStamp(WebRtc_UWord32& timestamp) const
|
||||
{
|
||||
CriticalSectionScoped lock(_criticalSectionRTPReceiver);
|
||||
WebRtc_UWord32 freq = 90000;
|
||||
if(_audio)
|
||||
{
|
||||
freq = _rtpReceiverAudio->AudioFrequency();
|
||||
}
|
||||
WebRtc_UWord32 freq = _rtpMediaReceiver->GetFrequencyHz();
|
||||
|
||||
if(_localTimeLastReceivedTimestamp == 0)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
|
||||
@ -1079,7 +1006,7 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) {
|
||||
bool newSSRC = false;
|
||||
bool reInitializeDecoder = false;
|
||||
char payloadName[RTP_PAYLOAD_NAME_SIZE];
|
||||
WebRtc_UWord32 frequency = 90000; // default video freq
|
||||
WebRtc_UWord32 frequency = kDefaultVideoFrequency; // default video freq
|
||||
WebRtc_UWord8 channels = 1;
|
||||
WebRtc_UWord32 rate = 0;
|
||||
|
||||
@ -1119,7 +1046,7 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) {
|
||||
channels = payload->typeSpecific.Audio.channels;
|
||||
rate = payload->typeSpecific.Audio.rate;
|
||||
} else {
|
||||
frequency = 90000;
|
||||
frequency = kDefaultVideoFrequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1149,12 +1076,17 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) {
|
||||
}
|
||||
|
||||
// no criticalsection when called
|
||||
// TODO(phoglund): Move as much as possible of this code path into the media
|
||||
// specific receivers. Basically this method goes through a lot of trouble to
|
||||
// compute something which is only used by the media specific parts later. If
|
||||
// this code path moves we can get rid of some of the rtp_receiver ->
|
||||
// media_specific interface (such as CheckPayloadChange, possibly get/set
|
||||
// last known payload).
|
||||
WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
|
||||
const WebRtcRTPHeader* rtpHeader,
|
||||
const WebRtc_Word8 firstPayloadByte,
|
||||
bool& isRED,
|
||||
AudioPayload& audioSpecificPayload,
|
||||
VideoPayload& videoSpecificPayload) {
|
||||
ModuleRTPUtility::PayloadUnion* specificPayload) {
|
||||
bool reInitializeDecoder = false;
|
||||
|
||||
char payloadName[RTP_PAYLOAD_NAME_SIZE];
|
||||
@ -1178,39 +1110,25 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
|
||||
|
||||
//when we receive RED we need to check the real payload type
|
||||
if (payloadType == _lastReceivedPayloadType) {
|
||||
if(_audio)
|
||||
{
|
||||
memcpy(&audioSpecificPayload, &_lastReceivedAudioSpecific,
|
||||
sizeof(_lastReceivedAudioSpecific));
|
||||
} else {
|
||||
memcpy(&videoSpecificPayload, &_lastReceivedVideoSpecific,
|
||||
sizeof(_lastReceivedVideoSpecific));
|
||||
}
|
||||
_rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (_audio) {
|
||||
if (_rtpReceiverAudio->TelephoneEventPayloadType(payloadType)) {
|
||||
// don't do callbacks for DTMF packets
|
||||
isRED = false;
|
||||
return 0;
|
||||
}
|
||||
// frequency is updated for CNG
|
||||
bool cngPayloadTypeHasChanged = false;
|
||||
bool isCngPayloadType = _rtpReceiverAudio->CNGPayloadType(
|
||||
payloadType, &audioSpecificPayload.frequency,
|
||||
&cngPayloadTypeHasChanged);
|
||||
bool shouldResetStatistics = false;
|
||||
bool shouldDiscardChanges = false;
|
||||
|
||||
if (cngPayloadTypeHasChanged) {
|
||||
ResetStatistics();
|
||||
}
|
||||
_rtpMediaReceiver->CheckPayloadChanged(
|
||||
payloadType, specificPayload, &shouldResetStatistics,
|
||||
&shouldDiscardChanges);
|
||||
|
||||
if (isCngPayloadType) {
|
||||
// don't do callbacks for DTMF packets
|
||||
isRED = false;
|
||||
return 0;
|
||||
}
|
||||
if (shouldResetStatistics) {
|
||||
ResetStatistics();
|
||||
}
|
||||
if (shouldDiscardChanges) {
|
||||
isRED = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
|
||||
_payloadTypeMap.find(payloadType);
|
||||
|
||||
@ -1222,22 +1140,16 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
|
||||
assert(payload);
|
||||
payloadName[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
||||
strncpy(payloadName, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
|
||||
|
||||
_lastReceivedPayloadType = payloadType;
|
||||
|
||||
reInitializeDecoder = true;
|
||||
|
||||
if(payload->audio) {
|
||||
memcpy(&_lastReceivedAudioSpecific, &(payload->typeSpecific.Audio),
|
||||
sizeof(_lastReceivedAudioSpecific));
|
||||
memcpy(&audioSpecificPayload, &(payload->typeSpecific.Audio),
|
||||
sizeof(_lastReceivedAudioSpecific));
|
||||
} else {
|
||||
memcpy(&_lastReceivedVideoSpecific, &(payload->typeSpecific.Video),
|
||||
sizeof(_lastReceivedVideoSpecific));
|
||||
memcpy(&videoSpecificPayload, &(payload->typeSpecific.Video),
|
||||
sizeof(_lastReceivedVideoSpecific));
|
||||
_rtpMediaReceiver->SetLastMediaSpecificPayload(payload->typeSpecific);
|
||||
_rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload);
|
||||
|
||||
if (_lastReceivedVideoSpecific.videoCodecType == kRtpFecVideo)
|
||||
if(!payload->audio) {
|
||||
if (VideoCodecType() == kRtpFecVideo)
|
||||
{
|
||||
// Only reset the decoder on media packets.
|
||||
reInitializeDecoder = false;
|
||||
@ -1254,39 +1166,16 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
|
||||
ResetStatistics();
|
||||
}
|
||||
} else {
|
||||
if(_audio)
|
||||
{
|
||||
memcpy(&audioSpecificPayload, &_lastReceivedAudioSpecific,
|
||||
sizeof(_lastReceivedAudioSpecific));
|
||||
} else
|
||||
{
|
||||
memcpy(&videoSpecificPayload, &_lastReceivedVideoSpecific,
|
||||
sizeof(_lastReceivedVideoSpecific));
|
||||
}
|
||||
_rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload);
|
||||
isRED = false;
|
||||
}
|
||||
} // end critsect
|
||||
if (reInitializeDecoder) {
|
||||
CriticalSectionScoped lock(_criticalSectionCbs);
|
||||
if (_cbRtpFeedback) {
|
||||
// create new decoder instance
|
||||
if(_audio) {
|
||||
if (-1 == _cbRtpFeedback->OnInitializeDecoder(_id, payloadType,
|
||||
payloadName, audioSpecificPayload.frequency,
|
||||
audioSpecificPayload.channels, audioSpecificPayload.rate)) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||
"Failed to create audio decoder for payload type:%d",
|
||||
payloadType);
|
||||
return -1; // Wrong payload type
|
||||
}
|
||||
} else {
|
||||
if (-1 == _cbRtpFeedback->OnInitializeDecoder(_id, payloadType,
|
||||
payloadName, 90000, 1, 0)) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||
"Failed to create video decoder for payload type:%d",
|
||||
payloadType);
|
||||
return -1; // Wrong payload type
|
||||
}
|
||||
if (-1 == _rtpMediaReceiver->InvokeOnInitializeDecoder(
|
||||
_cbRtpFeedback, _id, payloadType, payloadName, *specificPayload)) {
|
||||
return -1; // Wrong payload type.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user