1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/video_coding/main/interface/video_coding.h" 12 #include "webrtc/modules/video_coding/main/source/generic_decoder.h" 13 #include "webrtc/modules/video_coding/main/source/internal_defines.h" 14 #include "webrtc/system_wrappers/interface/clock.h" 15 #include "webrtc/system_wrappers/interface/logging.h" 16 17 namespace webrtc { 18 19 VCMDecodedFrameCallback::VCMDecodedFrameCallback(VCMTiming& timing, 20 Clock* clock) 21 : 22 _critSect(CriticalSectionWrapper::CreateCriticalSection()), 23 _clock(clock), 24 _receiveCallback(NULL), 25 _timing(timing), 26 _timestampMap(kDecoderFrameMemoryLength), 27 _lastReceivedPictureID(0) 28 { 29 } 30 31 VCMDecodedFrameCallback::~VCMDecodedFrameCallback() 32 { 33 delete _critSect; 34 } 35 36 void VCMDecodedFrameCallback::SetUserReceiveCallback( 37 VCMReceiveCallback* receiveCallback) 38 { 39 CriticalSectionScoped cs(_critSect); 40 _receiveCallback = receiveCallback; 41 } 42 43 VCMReceiveCallback* VCMDecodedFrameCallback::UserReceiveCallback() 44 { 45 CriticalSectionScoped cs(_critSect); 46 return _receiveCallback; 47 } 48 49 int32_t VCMDecodedFrameCallback::Decoded(I420VideoFrame& decodedImage) 50 { 51 // TODO(holmer): We should improve this so that we can handle multiple 52 // callbacks from one call to Decode(). 53 VCMFrameInformation* frameInfo; 54 VCMReceiveCallback* callback; 55 { 56 CriticalSectionScoped cs(_critSect); 57 frameInfo = static_cast<VCMFrameInformation*>( 58 _timestampMap.Pop(decodedImage.timestamp())); 59 callback = _receiveCallback; 60 } 61 62 if (frameInfo == NULL) { 63 LOG(LS_WARNING) << "Too many frames backed up in the decoder, dropping " 64 "this one."; 65 return WEBRTC_VIDEO_CODEC_OK; 66 } 67 68 _timing.StopDecodeTimer( 69 decodedImage.timestamp(), 70 frameInfo->decodeStartTimeMs, 71 _clock->TimeInMilliseconds()); 72 73 if (callback != NULL) 74 { 75 decodedImage.set_render_time_ms(frameInfo->renderTimeMs); 76 callback->FrameToRender(decodedImage); 77 } 78 return WEBRTC_VIDEO_CODEC_OK; 79 } 80 81 int32_t 82 VCMDecodedFrameCallback::ReceivedDecodedReferenceFrame( 83 const uint64_t pictureId) 84 { 85 CriticalSectionScoped cs(_critSect); 86 if (_receiveCallback != NULL) 87 { 88 return _receiveCallback->ReceivedDecodedReferenceFrame(pictureId); 89 } 90 return -1; 91 } 92 93 int32_t 94 VCMDecodedFrameCallback::ReceivedDecodedFrame(const uint64_t pictureId) 95 { 96 _lastReceivedPictureID = pictureId; 97 return 0; 98 } 99 100 uint64_t VCMDecodedFrameCallback::LastReceivedPictureID() const 101 { 102 return _lastReceivedPictureID; 103 } 104 105 int32_t VCMDecodedFrameCallback::Map(uint32_t timestamp, VCMFrameInformation* frameInfo) 106 { 107 CriticalSectionScoped cs(_critSect); 108 return _timestampMap.Add(timestamp, frameInfo); 109 } 110 111 int32_t VCMDecodedFrameCallback::Pop(uint32_t timestamp) 112 { 113 CriticalSectionScoped cs(_critSect); 114 if (_timestampMap.Pop(timestamp) == NULL) 115 { 116 return VCM_GENERAL_ERROR; 117 } 118 return VCM_OK; 119 } 120 121 VCMGenericDecoder::VCMGenericDecoder(VideoDecoder& decoder, bool isExternal) 122 : 123 _callback(NULL), 124 _frameInfos(), 125 _nextFrameInfoIdx(0), 126 _decoder(decoder), 127 _codecType(kVideoCodecUnknown), 128 _isExternal(isExternal), 129 _keyFrameDecoded(false) 130 { 131 } 132 133 VCMGenericDecoder::~VCMGenericDecoder() 134 { 135 } 136 137 int32_t VCMGenericDecoder::InitDecode(const VideoCodec* settings, 138 int32_t numberOfCores) 139 { 140 _codecType = settings->codecType; 141 142 return _decoder.InitDecode(settings, numberOfCores); 143 } 144 145 int32_t VCMGenericDecoder::Decode(const VCMEncodedFrame& frame, 146 int64_t nowMs) 147 { 148 _frameInfos[_nextFrameInfoIdx].decodeStartTimeMs = nowMs; 149 _frameInfos[_nextFrameInfoIdx].renderTimeMs = frame.RenderTimeMs(); 150 _callback->Map(frame.TimeStamp(), &_frameInfos[_nextFrameInfoIdx]); 151 152 _nextFrameInfoIdx = (_nextFrameInfoIdx + 1) % kDecoderFrameMemoryLength; 153 int32_t ret = _decoder.Decode(frame.EncodedImage(), 154 frame.MissingFrame(), 155 frame.FragmentationHeader(), 156 frame.CodecSpecific(), 157 frame.RenderTimeMs()); 158 159 if (ret < WEBRTC_VIDEO_CODEC_OK) 160 { 161 LOG(LS_WARNING) << "Failed to decode frame with timestamp " 162 << frame.TimeStamp() << ", error code: " << ret; 163 _callback->Pop(frame.TimeStamp()); 164 return ret; 165 } 166 else if (ret == WEBRTC_VIDEO_CODEC_NO_OUTPUT || 167 ret == WEBRTC_VIDEO_CODEC_REQUEST_SLI) 168 { 169 // No output 170 _callback->Pop(frame.TimeStamp()); 171 } 172 return ret; 173 } 174 175 int32_t 176 VCMGenericDecoder::Release() 177 { 178 return _decoder.Release(); 179 } 180 181 int32_t VCMGenericDecoder::Reset() 182 { 183 return _decoder.Reset(); 184 } 185 186 int32_t VCMGenericDecoder::SetCodecConfigParameters(const uint8_t* buffer, int32_t size) 187 { 188 return _decoder.SetCodecConfigParameters(buffer, size); 189 } 190 191 int32_t VCMGenericDecoder::RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback) 192 { 193 _callback = callback; 194 return _decoder.RegisterDecodeCompleteCallback(callback); 195 } 196 197 bool VCMGenericDecoder::External() const 198 { 199 return _isExternal; 200 } 201 202 } // namespace 203